+
diff --git a/src/components/task-detail/TaskDetailHistoryChat.vue b/src/components/task-detail/TaskDetailHistoryChat.vue
index c94d6669..2026fb36 100644
--- a/src/components/task-detail/TaskDetailHistoryChat.vue
+++ b/src/components/task-detail/TaskDetailHistoryChat.vue
@@ -44,7 +44,7 @@
삭제
-
+
{{ formatTimeShort(history.time) }}
diff --git a/src/components/task-detail/TaskDetailHistoryInput.vue b/src/components/task-detail/TaskDetailHistoryInput.vue
index 2dcc29a8..4545b25c 100644
--- a/src/components/task-detail/TaskDetailHistoryInput.vue
+++ b/src/components/task-detail/TaskDetailHistoryInput.vue
@@ -1,40 +1,44 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+ ({{ inputLength }}/{{ 254 }})
+
-
({{ inputLength }}/{{ 254 }})
총 {{ teamSummary.totalTasks }}건
-
+
+ content="진행 중인 작업이 없습니다"
+ position="top" />
diff --git a/src/components/team-board/TeamBoardCard.vue b/src/components/team-board/TeamBoardCard.vue
index 29ef35d5..25385485 100644
--- a/src/components/team-board/TeamBoardCard.vue
+++ b/src/components/team-board/TeamBoardCard.vue
@@ -22,7 +22,7 @@
총 {{ info.totalTaskCount }}건
+ class="w-full h-[360px] rounded-lg bg-primary2 shadow-custom overflow-y-auto scrollbar-hide flex flex-col items-center p-6 gap-4">
import('../views/NotFoundView.vue')
}
- ]
+ ],
+ scrollBehavior() {
+ return { top: 0 }
+ }
})
router.beforeEach(async (to, from, next) => {
@@ -135,7 +139,7 @@ router.beforeEach(async (to, from, next) => {
const { setError } = useErrorStore()
await memberStore.updateMemberInfoWithToken()
- const { info } = memberStore
+ const { info, isPendingUser } = memberStore
const redirectMap = {
ROLE_USER: '/my-request',
@@ -143,27 +147,6 @@ router.beforeEach(async (to, from, next) => {
ROLE_ADMIN: '/member-management'
}
- if (
- (info.role && PERMITTED_URL.UNKNOWN.includes(to.path) && to.path !== '/pw-change') ||
- (info.role && to.path === '/')
- ) {
- return next(redirectMap[info.role])
- }
-
- if (!info.role) {
- if (PERMITTED_URL.UNKNOWN.includes(to.path)) {
- return next()
- }
- if (to.path === '/login') {
- return next()
- }
- if (to.path === '/') {
- return next('/login')
- }
- setError('로그인이 필요합니다')
- return next('/login')
- }
-
const permittedUrlMap = {
ROLE_USER: PERMITTED_URL.ROLE_USER,
ROLE_MANAGER: PERMITTED_URL.ROLE_MANAGER,
@@ -176,19 +159,39 @@ router.beforeEach(async (to, from, next) => {
})
}
- if (
- from.path === redirectMap[info.role] &&
- !isPathPermitted(to.path, permittedUrlMap[info.role])
- ) {
- return false
+ if (isPendingUser) {
+ if (to.path === '/login' || to.path === '/pw-change') {
+ return next()
+ }
+ setError('권한이 없는 페이지입니다')
+ return next('/login')
}
- if (!isPathPermitted(to.path, permittedUrlMap[info.role])) {
- if (to.path === redirectMap[info.role]) {
+ if (!info.role) {
+ if (to.path === '/login') {
+ Cookies.remove('accessToken')
+ Cookies.remove('refreshToken')
return next()
}
- setError('권한이 없는 페이지입니다')
- return next(redirectMap[info.role])
+ if (PERMITTED_URL.UNKNOWN.includes(to.path)) {
+ return next()
+ }
+ if (to.path === '/') {
+ return next('/login')
+ }
+ setError('로그인이 필요합니다')
+ return next('/login')
+ }
+
+ if (info.role) {
+ if (PERMITTED_URL.UNKNOWN.includes(to.path) || to.path === '/') {
+ return next(redirectMap[info.role])
+ }
+
+ if (!isPathPermitted(to.path, permittedUrlMap[info.role])) {
+ setError('권한이 없는 페이지입니다')
+ return next(redirectMap[info.role])
+ }
}
return next()
diff --git a/src/stores/member.ts b/src/stores/member.ts
index 88bb4c32..d42572a0 100644
--- a/src/stores/member.ts
+++ b/src/stores/member.ts
@@ -23,11 +23,18 @@ export const useMemberStore = defineStore('memberInfo', () => {
const info = ref(INITIAL_INFO)
const isLogined = ref(false)
+ const isPendingUser = ref(false)
async function updateMemberInfoWithToken() {
+ isPendingUser.value = false
const token = Cookies.get('accessToken')
const refreshToken = Cookies.get('refreshToken')
- if (!token || !refreshToken) return
+ if (!token) {
+ return
+ } else if (!refreshToken) {
+ isPendingUser.value = true
+ return
+ }
const { data }: { data: User } = await axiosInstance.get('/api/members/info')
info.value = data
@@ -49,6 +56,7 @@ export const useMemberStore = defineStore('memberInfo', () => {
return {
info,
isLogined,
+ isPendingUser,
updateMemberInfoWithToken,
logout,
$reset
diff --git a/src/utils/axios.ts b/src/utils/axios.ts
index 92c5a46e..650c092e 100644
--- a/src/utils/axios.ts
+++ b/src/utils/axios.ts
@@ -79,6 +79,8 @@ const setInterceptors = (instance: AxiosInstance) => {
} catch {
setError('토큰 갱신에 실패하였습니다', '다시 로그인 해주세요', redirectToLogin)
}
+ } else {
+ setError('유효하지 않은 토큰입니다', '다시 로그인 해주세요', redirectToLogin)
}
}
break
diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue
index b9334d4e..b72f8e3d 100644
--- a/src/views/LoginView.vue
+++ b/src/views/LoginView.vue
@@ -56,8 +56,6 @@ import { postLogin } from '@/api/auth'
import ModalView from '@/components/common/ModalView.vue'
import TitleContainer from '@/components/common/TitleContainer.vue'
import { useMemberStore } from '@/stores/member'
-import axios from 'axios'
-import Cookies from 'js-cookie'
import { ref } from 'vue'
import { useRouter } from 'vue-router'
@@ -81,7 +79,7 @@ const handleLogin = async () => {
const res = await postLogin(name, password.value)
const role = await memberStore.updateMemberInfoWithToken()
- if (!Cookies.get('refreshToken')) {
+ if (memberStore.isPendingUser) {
router.push('/pw-change')
} else if (res) {
switch (role) {
diff --git a/src/views/PwChangeView.vue b/src/views/PwChangeView.vue
index 6ed0addb..51d806aa 100644
--- a/src/views/PwChangeView.vue
+++ b/src/views/PwChangeView.vue
@@ -104,7 +104,7 @@
@@ -192,4 +192,13 @@ const closeModal = () => {
const closeError = () => {
isErrorVisible.value = !isErrorVisible.value
}
+
+const goBack = () => {
+ if (Cookies.get('refreshToken')) {
+ router.replace('/edit-information')
+ } else {
+ Cookies.remove('accessToken')
+ router.replace('/login')
+ }
+}
diff --git a/src/views/StatisticsView.vue b/src/views/StatisticsView.vue
index 5256df6a..6bc02050 100644
--- a/src/views/StatisticsView.vue
+++ b/src/views/StatisticsView.vue
@@ -1,23 +1,27 @@
-
-
+
+
+
+
-
diff --git a/src/views/TaskBoardView.vue b/src/views/TaskBoardView.vue
index 7ecf62aa..5e5a6a13 100644
--- a/src/views/TaskBoardView.vue
+++ b/src/views/TaskBoardView.vue
@@ -1,10 +1,32 @@
-
-
+
+
+
-
+
-
+
+
+
+ 진행 중 {{ data?.tasksInProgress.length }}
+
+
+
+
+ 검토 중 {{ data?.tasksInReviewing.length }}
+
+
+
+
+ 완료 {{ data?.tasksCompleted.length }}
+
+
+
+
+
+
+
+
@@ -12,4 +34,27 @@
import TitleBar from '@/components/common/TitleBar.vue'
import TaskBoard from '@/components/task-board/TaskBoard.vue'
import TaskBoardFilterBar from '@/components/task-board/TaskBoardFilterBar.vue'
+import { useParseParams } from '@/hooks/useParseParams'
+import { useMemberStore } from '@/stores/member'
+import { useTaskBoardParamsStore } from '@/stores/params'
+import type { TaskCardList } from '@/types/manager'
+import { axiosInstance } from '@/utils/axios'
+import { useQuery } from '@tanstack/vue-query'
+import { storeToRefs } from 'pinia'
+
+const { params } = useTaskBoardParamsStore()
+const fetchTaskBoard = async () => {
+ const { parseBoardParams } = useParseParams()
+ const parsedParams = parseBoardParams(params)
+ const response = await axiosInstance.get('/api/task-board', { params: parsedParams })
+ return response.data
+}
+const memberStore = useMemberStore()
+const { isLogined } = storeToRefs(memberStore)
+
+const { data } = useQuery
({
+ queryKey: ['taskBoard', params],
+ queryFn: fetchTaskBoard,
+ enabled: isLogined
+})
diff --git a/src/views/TeamBoardView.vue b/src/views/TeamBoardView.vue
index ae99b55c..01b63672 100644
--- a/src/views/TeamBoardView.vue
+++ b/src/views/TeamBoardView.vue
@@ -1,10 +1,14 @@
-