diff --git a/src/assets/styles.css b/src/assets/styles.css index ece208b..1abacf0 100644 --- a/src/assets/styles.css +++ b/src/assets/styles.css @@ -99,7 +99,7 @@ body { @apply flex justify-center items-center w-full h-8 px-2 border-b border-border-1 relative text-xs cursor-pointer; } .filter-dropdown-option-list { - @apply w-full max-h-[160px] overflow-y-scroll absolute left-0 top-[calc(100%+8px)] shadow-custom p-2 flex flex-col gap-2 rounded bg-white cursor-auto; + @apply w-full max-h-[160px] overflow-y-auto scrollbar-hide absolute left-0 top-[calc(100%+8px)] shadow-custom p-2 flex flex-col gap-2 rounded bg-white cursor-auto; } .filter-dropdown-option { @apply text-xs p-2 rounded text-center cursor-pointer; @@ -117,7 +117,7 @@ body { @apply flex w-full h-11 items-center rounded p-4 bg-white border border-border-1 cursor-pointer; } .request-task-dropdown-option-list { - @apply absolute w-full h-40 overflow-y-auto top-[52px] flex flex-col gap-2 p-2 bg-white rounded z-10 shadow-custom; + @apply absolute w-full h-40 overflow-y-auto scrollbar-hide top-[52px] flex flex-col gap-2 p-2 bg-white rounded z-10 shadow-custom; } .request-task-dropdown-option { @apply w-full flex items-center h-11 p-2 rounded hover:bg-background-2 cursor-pointer; @@ -140,7 +140,7 @@ body { @apply flex w-full h-10 items-center text-sm rounded pl-4 pr-3 bg-white border border-border-1 cursor-pointer; } .task-detail-dropdown-option-list { - @apply absolute w-full h-40 overflow-y-auto top-11 flex flex-col gap-2 p-2 bg-white rounded z-10 shadow border-t border-t-border-2; + @apply absolute w-full h-40 overflow-y-auto scrollbar-hide top-11 flex flex-col gap-2 p-2 bg-white rounded z-10 shadow border-t border-t-border-2; } .task-detail-dropdown-option { @apply w-full flex items-center h-10 p-2 rounded hover:bg-background-2 cursor-pointer; diff --git a/src/components/common/ModalView.vue b/src/components/common/ModalView.vue index d12bb65..64077d6 100644 --- a/src/components/common/ModalView.vue +++ b/src/components/common/ModalView.vue @@ -27,7 +27,7 @@
diff --git a/src/components/lists/ListContainer.vue b/src/components/lists/ListContainer.vue index 4a1927c..d084cad 100644 --- a/src/components/lists/ListContainer.vue +++ b/src/components/lists/ListContainer.vue @@ -3,7 +3,7 @@
-
+
diff --git a/src/components/member-management/MemberManagementListCard.vue b/src/components/member-management/MemberManagementListCard.vue index 9f9396c..ef5f874 100644 --- a/src/components/member-management/MemberManagementListCard.vue +++ b/src/components/member-management/MemberManagementListCard.vue @@ -58,6 +58,9 @@ import { useRouter } from 'vue-router' import ResultModal from '../common/ResultModal.vue' import ListCardTab from '../lists/ListCardTab.vue' import ModalView from '../common/ModalView.vue' +import { useMemberStore } from '@/stores/member' +import { storeToRefs } from 'pinia' +import { useErrorStore } from '@/stores/error' const roleContent = (role: Role) => { return role === 'ROLE_USER' ? '사용자' : role === 'ROLE_MANAGER' ? '담당자' : '관리자' @@ -84,7 +87,14 @@ const isModalVisible = ref({ }) const resultModalType = ref('') const message = ref('') +const memberStore = useMemberStore() +const { info: myInfo } = storeToRefs(memberStore) +const { setError } = useErrorStore() const toggleModal = (key: keyof typeof isModalVisible.value) => { + if (key === 'delete' && info.nickname === myInfo.value.nickname) { + setError('자신의 계정은\n삭제할 수 없습니다') + return + } isModalVisible.value = Object.fromEntries( Object.keys(isModalVisible.value).map(k => [k, k === key]) ) as typeof isModalVisible.value diff --git a/src/components/request-approve/DueDateInput.vue b/src/components/request-approve/DueDateInput.vue index e751396..7d21c47 100644 --- a/src/components/request-approve/DueDateInput.vue +++ b/src/components/request-approve/DueDateInput.vue @@ -2,7 +2,8 @@ @@ -12,7 +13,7 @@ import type { DueDateInputProps } from '@/types/common' import { computed, defineEmits, defineProps, onMounted } from 'vue' -const { modelValue, inputType } = defineProps() +const { modelValue, inputType, isInvalidate } = defineProps() const emit = defineEmits(['update:modelValue']) diff --git a/src/components/request-approve/LabelDropdown.vue b/src/components/request-approve/LabelDropdown.vue index 24a8376..bde72c1 100644 --- a/src/components/request-approve/LabelDropdown.vue +++ b/src/components/request-approve/LabelDropdown.vue @@ -16,7 +16,7 @@
+ class="absolute w-full h-40 overflow-y-auto scrollbar-hide top-[52px] flex flex-col gap-2 p-2 bg-white rounded z-10 shadow border-t border-t-border-2">
+ :is-invalidate="isInvalidate === 'manager' ? 'manager' : ''" />

마감기한

@@ -40,10 +40,12 @@
+ inputType="date" + :is-invalidate="isInvalidate === 'date' ? 'date' : ''" /> + inputType="time" + :is-invalidate="isInvalidate === 'date' ? 'date' : ''" />
{ } const handleSubmit = async () => { - if (!category1.value || !category2.value) { - isInvalidate.value = 'category' + if (!category1.value) { + isInvalidate.value = 'category1' + return + } + if (!category2.value) { + isInvalidate.value = 'category2' return } if (!approveData.value.processor?.memberId) { diff --git a/src/components/request-task/CategoryDropDown.vue b/src/components/request-task/CategoryDropDown.vue index 180049f..19d0807 100644 --- a/src/components/request-task/CategoryDropDown.vue +++ b/src/components/request-task/CategoryDropDown.vue @@ -17,8 +17,8 @@ ref="htmlRef" class="relative flex">

{{ modelValue?.name ?? labelName + '를 선택해주세요' }} @@ -29,7 +29,7 @@

+ class="absolute w-full max-h-40 overflow-y-auto scrollbar-hide top-[52px] flex flex-col gap-2 p-2 bg-white rounded z-10 shadow border-t border-t-border-2">
+ :is-invalidate="isInvalidate === 'input' ? 'input' : ''" />
+ class="absolute w-full h-40 overflow-y-auto scrollbar-hide top-[52px] flex flex-col gap-2 p-2 bg-white rounded z-10 shadow border-t border-t-border-2">
+ class="flex flex-col h-[102px] overflow-hidden overflow-y-auto scrollbar-hide">

2차 카테고리

-
+
diff --git a/src/components/task-management/LabelManagement.vue b/src/components/task-management/LabelManagement.vue index 687021a..c205c81 100644 --- a/src/components/task-management/LabelManagement.vue +++ b/src/components/task-management/LabelManagement.vue @@ -7,7 +7,7 @@

구분명

-
+
diff --git a/src/components/team-board/CurrentTaskRatio.vue b/src/components/team-board/CurrentTaskRatio.vue index 651ace4..63c6510 100644 --- a/src/components/team-board/CurrentTaskRatio.vue +++ b/src/components/team-board/CurrentTaskRatio.vue @@ -14,8 +14,7 @@
총 {{ teamSummary.totalTasks }}건
-
+
-
+
총 {{ info.totalTaskCount }}건
+ class="w-full h-[360px] rounded-lg bg-primary2 shadow-custom overflow-y-auto flex flex-col items-center p-6 gap-4">
-
+
diff --git a/src/components/top-bar/TopBar.vue b/src/components/top-bar/TopBar.vue index ead8413..1f61320 100644 --- a/src/components/top-bar/TopBar.vue +++ b/src/components/top-bar/TopBar.vue @@ -8,12 +8,15 @@ @click="onOpenSide"> - +
@@ -63,9 +66,11 @@ import ProfileModal from './ProfileModal.vue' import { getNotifiCount } from '@/api/common' import ImageContainer from '../common/ImageContainer.vue' import { useOutsideClick } from '@/hooks/useOutsideClick' +import { useRouter } from 'vue-router' const memberStore = useMemberStore() const { isLogined, info } = storeToRefs(memberStore) +const router = useRouter() onMounted(async () => { if (isLogined.value) { diff --git a/src/components/user-manage/DepartmentDropDown.vue b/src/components/user-manage/DepartmentDropDown.vue index ae65669..ecaf73d 100644 --- a/src/components/user-manage/DepartmentDropDown.vue +++ b/src/components/user-manage/DepartmentDropDown.vue @@ -18,7 +18,7 @@
+ class="absolute w-full h-40 overflow-y-auto scrollbar-hide top-[52px] flex flex-col gap-2 p-2 bg-white rounded z-10 shadow border-t border-t-border-2">
{ await memberStore.updateMemberInfoWithToken() const { info } = memberStore - const originUrl = to.path.split('/')[1] - const redirectMap = { ROLE_USER: '/my-request', ROLE_MANAGER: '/my-task', ROLE_ADMIN: '/member-management' } - if ((info.role && to.path === '/login') || (info.role && to.path === '/')) { + if ((info.role && PERMITTED_URL.UNKNOWN.includes(to.path)) || (info.role && to.path === '/')) { return next(redirectMap[info.role]) } if (!info.role) { - if (PERMITTED_URL.UNKNOWN.includes(originUrl)) { + 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') } @@ -166,11 +167,11 @@ router.beforeEach(async (to, from, next) => { ROLE_ADMIN: PERMITTED_URL.ROLE_ADMIN } - if (from.path === redirectMap[info.role] && !permittedUrlMap[info.role].includes(originUrl)) { + if (from.path === redirectMap[info.role] && !permittedUrlMap[info.role].includes(to.path)) { return false } - if (!permittedUrlMap[info.role].includes(originUrl)) { + if (!permittedUrlMap[info.role].includes(to.path)) { if (to.path === redirectMap[info.role]) { return next() } diff --git a/src/types/common.ts b/src/types/common.ts index c1d69ee..43586dd 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -61,6 +61,7 @@ export type Role = 'ROLE_USER' | 'ROLE_MANAGER' | 'ROLE_ADMIN' export interface DueDateInputProps { modelValue: string | null inputType: string + isInvalidate?: string } export interface FormButtonProps { diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue index 3bc9b53..d029cd9 100644 --- a/src/views/LoginView.vue +++ b/src/views/LoginView.vue @@ -22,7 +22,8 @@ v-model="id" placeholder="아이디를 입력해주세요" required - class="input-box" /> + class="input-box" + autocomplete="username" />
+ class="input-box" + autocomplete="current-password" />