Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
e6694f2
♻️ [refactor] : 파일 위치 변경
BaekJiyeon02 Feb 4, 2025
6c48636
✨ [feat] : logout 기능 추가
BaekJiyeon02 Feb 4, 2025
a841b48
✨ [feat] : logout API 추가
BaekJiyeon02 Feb 4, 2025
8e015b9
✨ [feat] : Access Token 통해 로그인 여부 받아오기
BaekJiyeon02 Feb 4, 2025
d40fc80
✨ [feat] : 알림목록 조회 API 추가
BaekJiyeon02 Feb 4, 2025
290bc14
✨ [feat] : 알림목록 무한 스크롤
BaekJiyeon02 Feb 4, 2025
c75da99
✨ [feat] : 무한 스크롤 v3-infinite-loading 라이브러리 추가
BaekJiyeon02 Feb 4, 2025
745c13f
♻️ [refactor] : 불필요한 코드 제거
BaekJiyeon02 Feb 4, 2025
27cfe39
✨ [feat] : 알림 읽음 상태 변경, 미확인 알림 개수
BaekJiyeon02 Feb 4, 2025
127d11f
✨ [feat] : 미확인 알림 개수 반영
BaekJiyeon02 Feb 4, 2025
0eea7f7
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-F…
BaekJiyeon02 Feb 4, 2025
8977e3c
♻️ [refactor] : 임시 프로필 사진 제거
BaekJiyeon02 Feb 4, 2025
9b04fba
✨ [feat] :로그인시 반응형으로 바뀌지 않는 TopBar 수정
BaekJiyeon02 Feb 4, 2025
17cdd54
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-F…
BaekJiyeon02 Feb 4, 2025
455aecf
💄 [design] : 알림 디자인 수정
BaekJiyeon02 Feb 5, 2025
a3534fc
💄 [design] : 탑바 및 로그인 디자인 수정
BaekJiyeon02 Feb 5, 2025
ae0f361
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-F…
BaekJiyeon02 Feb 5, 2025
489f95b
Merge branch 'develop' of https://github.com/TaskFlow-CLAP/TaskFlow-F…
BaekJiyeon02 Feb 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"js-cookie": "^3.0.5",
"pinia": "^2.3.0",
"tailwind-scrollbar-hide": "^2.0.0",
"v3-infinite-loading": "^1.3.2",
"vue": "^3.5.13",
"vue-chartjs": "^5.3.2",
"vue-router": "^4.5.0",
Expand Down
28 changes: 22 additions & 6 deletions src/api/auth.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,44 @@
import { axiosInstance } from '@/utils/axios'
import Cookies from 'js-cookie'
import type { loginDataTypes } from '@/types/auth'
import { useMemberStore } from '@/stores/member'

export const postLogin = async (loginData: loginDataTypes, sessionId: string) => {
const memberStore = useMemberStore()
const response = await axiosInstance.post('/api/auths/login', loginData, {
headers: { sessionId: sessionId }
})
Cookies.set('accessToken', response.data.accessToken, {
path: '/',
sameSite: 'strict'
})
Cookies.set('refreshToken', response.data.refreshToken, {
path: '/',
sameSite: 'strict'
})

await memberStore.updateMemberInfoWithToken()
return response.data
}

export const patchPassword = async (password: string) => {
const accessToken = Cookies.get('accessToken')
const response = await axiosInstance.patch('/api/members/password', password)

if (!accessToken) return
return response.data
}

export const deleteLogout = async () => {
const memberStore = useMemberStore()
const refreshToken = Cookies.get('refreshToken')

const response = await axiosInstance.patch('/api/members/password', password, {
const response = await axiosInstance.delete('/api/auths/logout', {
headers: {
Authorization: `Bearer ${accessToken}`
Authorization: `Bearer ${import.meta.env.VITE_ACCESS_TOKEN}`,
refreshToken: refreshToken
}
})

return response.data
Cookies.remove('accessToken', { path: '/' })
Cookies.remove('refreshToken', { path: '/' })
await memberStore.updateMemberInfoWithToken()
return response
}
18 changes: 18 additions & 0 deletions src/api/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
import { axiosInstance } from '../utils/axios'

export const getNotification = async (pageNum: number, sizeNum: number) => {
const response = await axiosInstance.get(`/api/notifications?page=${pageNum}&size=${sizeNum}`)

return response.data
}

export const patchNotificationRead = async (notificationId: number) => {
const response = await axiosInstance.patch(`/api/notification/${notificationId}`)
console.log(notificationId)
return response.data
}

export const getNotifiCount = async () => {
const response = await axiosInstance.get(`/api/notifications/count`)
console.log(response.data)
return response.data
}

export const getMainCategory = async () => {
const response = await axiosInstance.get('/api/main-category')
return response.data
Expand Down
4 changes: 2 additions & 2 deletions src/components/EditInformation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
class="w-24 h-24 rounded-full object-cover border mt-3" />
<div
v-else
class="w-24 h-24 rounded-full bg-background-1 flex items-center justify-center"></div>
class="w-24 h-24 rounded-full bg-background-1 flex items-center justify-center mt-3"></div>
<!-- 파일 업로드 필요 -->
<p class="mt-3 text-xs text-primary1 font-bold cursor-pointer">변경</p>
</div>
Expand Down Expand Up @@ -91,7 +91,7 @@ const memberId = ref('Chole.yeon')
const memberEmail = ref('[email protected]')
const memberDepartment = ref('인프라팀')
const memberJob = ref('인프라 아키텍처')
const imageUrl = ref('../../public/images/mockProfile.jpg')
const imageUrl = ref('')
const isModalVisible = ref(false)

const memberForm = ref({
Expand Down
103 changes: 73 additions & 30 deletions src/components/top-bar/NotificationModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class="flex relative w-[1200px] h-[72px] bg-opacity-15"
@click.self="closeModal">
<div
class="absolute right-6 top-[72px] h-60 w-80 bg-white rounded-lg shadow-[0_3px_10px_rgb(0,0,0,0.2)]">
class="absolute right-6 top-[72px] h-60 w-80 bg-white rounded-lg shadow-[0_3px_10px_rgb(0,0,0,0.2)] overflow-hidden">
<div class="flex relative px-4 pt-3 pb-2 border-b border-border-2">
<p class="text-body font-bold text-xs">알림</p>
<div class="absolute right-4">
Expand All @@ -25,48 +25,91 @@
</div>
</div>
</div>
<div class="max-h-[186px] flex flex-col h-full overflow-y-auto">
<div class="overflow-y-scroll flex"></div>
<button :class="['flex flex-col border-b py-3 px-4', { 'bg-primary2': isCheck }]">
<p class="text-xs text-body font-bold">{{ title }}</p>
<div class="flex text-xs pt-2">
<span class="text-black">
<span class="text-primary1 font-bold">"{{ taskTitle }}"</span>
&nbsp;요청이&nbsp;
<span class="text-primary1 font-bold">{{ message }}</span>
&nbsp;상태로 변경 되었습니다
</span>
</div>
</button>
<button :class="['flex flex-col border-b py-3 px-4', { 'bg-primary2': !isCheck }]">
<p class="text-xs text-body font-bold">{{ title }}</p>
<div class="flex text-xs pt-2">
<span class="text-black">
<span class="text-primary1 font-bold">"{{ taskTitle }}"</span>
&nbsp;요청이&nbsp;
<span class="text-primary1 font-bold">{{ message }}</span>
&nbsp;상태로 변경 되었습니다
</span>
</div>
</button>
<div class="max-h-[185px] flex flex-col h-full overflow-y-auto">
<div class="overflow-y-scroll flex flex-col">
<button
v-for="notification in notifications"
:key="notification.notificationId"
@click="readNotifi(notification.notificationId)"
:class="[
'flex flex-col border-b py-3 px-4',
{ 'bg-primary2': !notification.isRead }
]">
<p class="text-xs text-body font-bold">
{{ notification.notificationType }}
</p>
<div class="flex text-xs pt-2">
<span class="text-black">
<span class="text-primary1 font-bold"> "{{ notification.taskTitle }}" </span>
&nbsp;요청이&nbsp;
<span class="text-primary1 font-bold">
{{ notification.message }}
</span>
&nbsp;상태로 변경되었습니다.
</span>
</div>
</button>
<InfiniteLoading
@infinite="loadMoreNotifications"
class="flex items-center justify-center"
><template v-slot:complete>
<span class="flex py-2 items-center justify-center text-xs text-primary1"
>더 이상 없음</span
>
</template></InfiniteLoading
>
</div>
</div>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { onMounted, ref } from 'vue'
import InfiniteLoading from 'v3-infinite-loading'
import 'v3-infinite-loading/lib/style.css'
import CommonIcons from '../common/CommonIcons.vue'
import { smallCheckIcon, closeIcon } from '@/constants/iconPath'
import { getNotification, patchNotificationRead } from '@/api/common'

const props = defineProps<{
isOpen: boolean
}>()

const title = ref('작업 상태 변경 알림')
const taskTitle = ref('VM 생성 요청')
const message = ref('진행 중')
const isCheck = ref(true)
const notifications = ref<any[]>([])
const page = ref(0)
const pageSize = 5
const hasNext = ref(true)

const loadMoreNotifications = async ($state: any) => {
try {
const response = await getNotification(page.value, pageSize)
console.log(response)

if (response.isFirst) {
notifications.value = response.content
} else {
notifications.value.push(...response.content)
}

hasNext.value = response.hasNext

if (hasNext.value) {
page.value++
$state.loaded()
} else {
$state.complete()
}
} catch (error) {
console.error('알림을 불러오는 중 오류 발생:', error)
$state.error()
}
}

const readNotifi = (id: number) => {
patchNotificationRead(id)
}

const emit = defineEmits<{
(e: 'close'): void
Expand Down
45 changes: 40 additions & 5 deletions src/components/top-bar/ProfileModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
v-if="isOpen"
class="fixed inset-0 flex z-50 justify-center"
@click.self="closeModal">
<ModalView
:isOpen="isModalVisible"
type="successType"
@close="closeLogoutModal">
<template #header> 로그아웃 되었습니다. </template>
</ModalView>
<div
class="flex relative w-[1200px] h-[72px] bg-opacity-15"
@click.self="closeModal">
Expand All @@ -11,10 +17,18 @@
<div
class="flex items-center justify-center relative px-6 py-8 border-b bg-primary2 border-border-2">
<div class="flex flex-col items-center justify-center">
<div class="w-24 h-24 bg-background-1 rounded-full mb-6"></div>
<img
v-if="imgUrl"
class="rounded-full mb-6 w-24 h-24"
:src="info.imageUrl"
alt="프로필 이미지" />
<div
v-else
class="w-24 h-24 bg-background-1 rounded-full mb-6" />
<div>
<div class="flex flex-col justify-center items-center w-[172px]">
<p class="text-xs text-body font-bold">{{ name }}</p>

<p class="text-black">{{ nickname }}</p>
</div>
</div>
Expand All @@ -40,16 +54,27 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { deleteLogout } from '@/api/auth'
import ModalView from '../ModalView.vue'
import { useMemberStore } from '@/stores/member'
import { storeToRefs } from 'pinia'
import { computed } from 'vue'

const isModalVisible = ref(false)

const memberStore = useMemberStore()
const { info } = storeToRefs(memberStore)

const imgUrl = computed(() => info.value.imageUrl)
const name = computed(() => info.value.memberName)
const nickname = computed(() => info.value.nickname)

const router = useRouter()

const props = defineProps<{
isOpen: boolean
}>()

const name = ref('벡지연')
const nickname = ref('Chloe.yeon')

const emit = defineEmits<{
(e: 'close'): void
}>()
Expand All @@ -61,7 +86,17 @@ const handleEdit = () => {
router.push('/edit-information')
emit('close')
}
const openLogoutModal = () => {
isModalVisible.value = true
}
const closeLogoutModal = () => {
isModalVisible.value = false
emit('close')
router.push('/login')
}

const handleLogout = () => {
// 로그아웃 API 추가 필요
deleteLogout()
openLogoutModal()
}
</script>
Loading