Skip to content

Commit cf46ee2

Browse files
authored
Merge pull request #27 from TaskFlow-CLAP/CLAP-115
CLAP-115 사용자 요청 세부정보 UI제작
2 parents 8a919f3 + 62a9cf7 commit cf46ee2

File tree

19 files changed

+577
-15
lines changed

19 files changed

+577
-15
lines changed

public/images/mockProfile.jpg

24.7 KB
Loading

src/assets/styles.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,7 @@ body {
100100
.input-box {
101101
@apply block w-full px-4 py-4 border border-zinc-300 rounded focus:outline-none;
102102
}
103+
104+
.task-detail {
105+
@apply text-xs text-body font-bold mb-2;
106+
}

src/components/lists/ListPagination.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<script setup lang="ts">
4343
import { nextIcon, nextSetIcon, prevIcon, prevSetIcon } from '@/constants/iconPath'
4444
import { computed } from 'vue'
45-
import CommonIcons from '../common/CommonIcons.vue';
45+
import CommonIcons from '../common/CommonIcons.vue'
4646
4747
const { pageNumber, totalPage } = defineProps<{ pageNumber: number; totalPage: number }>()
4848
const emit = defineEmits(['update:pageNumber'])

src/components/request-task/RequestTask.vue

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,8 @@
3333
</template>
3434

3535
<script lang="ts" setup>
36-
import {
37-
EXPLANATION_PLACEHOLDER,
38-
REQUEST_TASK_CATEGORIES,
39-
TITLE_PLACEHOLDER
40-
} from '@/constants/user'
36+
import { EXPLANATION_PLACEHOLDER, TITLE_PLACEHOLDER } from '@/constants/user'
37+
import { REQUEST_TASK_CATEGORIES } from '@/datas/taskdetail'
4138
import { ref } from 'vue'
4239
import RequestTaskDropdown from './RequestTaskDropdown.vue'
4340
import RequestTaskFileInput from './RequestTaskFileInput.vue'
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<template>
2+
<div class="flex flex-col rounded-lg max-w-1200 bg-white">
3+
<div class="w-full flex justify-between items-center">
4+
<div class="flex gap-4 text-sm font-bold">
5+
<div
6+
v-if="!isManager"
7+
class="flex gap-1 items-center cursor-pointer">
8+
<CommonIcons :name="reRequestIcon" />
9+
<p class="text-body">재요청</p>
10+
</div>
11+
<div
12+
v-if="status.iconName && status.text"
13+
class="flex gap-1 items-center cursor-pointer">
14+
<CommonIcons :name="status.iconName" />
15+
<p class="text-primary1">{{ status.text }}</p>
16+
</div>
17+
<div
18+
v-if="isManager"
19+
class="flex gap-1 items-center cursor-pointer">
20+
<CommonIcons :name="cancelIcon" />
21+
<p class="text-red-1">요청취소</p>
22+
</div>
23+
</div>
24+
<CommonIcons
25+
:name="closeIcon"
26+
@click="closeTaskDetail"
27+
class="cursor-pointer" />
28+
</div>
29+
<div class="w-full flex gap-6">
30+
<div class="w-full flex flex-col gap-y-8 overflow-y-auto scrollbar-hide">
31+
<TaskDetailLeft :task-detail="DUMMY_TASK_DETAIL_LEFT" />
32+
<div class="w-full border-border-1 border"></div>
33+
<TaskDetailHistory
34+
:history="DUMMY_TASK_DETAIL_HISTORY"
35+
:is-approved="false"
36+
:is-manager="false" />
37+
</div>
38+
<div class="w-[1px] bg-border-1"></div>
39+
<TaskDetailRight :task-detail="DUMMY_TASK_DETAIL_RIGHT" />
40+
</div>
41+
</div>
42+
</template>
43+
44+
<script setup lang="ts">
45+
import {
46+
approveIcon,
47+
cancelIcon,
48+
closeIcon,
49+
modificationIcon,
50+
reRequestIcon
51+
} from '@/constants/iconPath'
52+
import * as taskDetailData from '@/datas/taskdetail'
53+
import type { TaskDetailProps } from '@/types/user'
54+
import CommonIcons from '../common/CommonIcons.vue'
55+
import TaskDetailHistory from './TaskDetailHistory.vue'
56+
import TaskDetailLeft from './TaskDetailLeft.vue'
57+
import TaskDetailRight from './TaskDetailRight.vue'
58+
59+
const { DUMMY_TASK_DETAIL_HISTORY, DUMMY_TASK_DETAIL_LEFT, DUMMY_TASK_DETAIL_RIGHT } =
60+
taskDetailData
61+
62+
const { isManager, isApproved, closeTaskDetail } = defineProps<TaskDetailProps>()
63+
64+
const getStatus = (isManager: boolean) => {
65+
if (!isManager && !isApproved) {
66+
return {
67+
iconName: modificationIcon,
68+
text: '요청 수정'
69+
}
70+
} else if (isManager && !isApproved) {
71+
return {
72+
iconName: approveIcon,
73+
text: '요청 승인'
74+
}
75+
} else {
76+
return {}
77+
}
78+
}
79+
80+
const status = getStatus(isManager)
81+
</script>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<template>
2+
<div class="w-full h-32 border border-border-1 rounded">
3+
<div
4+
class="flex w-full justify-between items-center h-6 text-[10px] text-body font-bold bg-border-2 border-b border-b-border-1 px-4">
5+
<p class="w-7">파일명</p>
6+
<div class="flex gap-6">
7+
<p class="w-[60px]">용량</p>
8+
<p class="w-36">최종 업로드 시각</p>
9+
<p class="w-10">다운로드</p>
10+
</div>
11+
</div>
12+
<div
13+
v-if="files && files.length > 0"
14+
class="flex flex-col h-[102px] overflow-hidden overflow-y-auto">
15+
<div
16+
v-for="file in files"
17+
:key="file.fileName"
18+
class="flex w-full justify-between items-center h-8 text-xs border-b border-b-border-2 text-black px-4 shrink-0">
19+
<p class="flex truncate mr-3">{{ file.fileName }}</p>
20+
<div class="flex gap-6">
21+
<p class="w-[60px]">{{ formatFileSize(Number(file.fileSize)) }}</p>
22+
<p class="w-36">{{ new Date().toLocaleString() }}</p>
23+
<div class="w-10 flex items-center justify-center cursor-pointer">
24+
<CommonIcons
25+
class="cursor-pointer"
26+
:name="downloadIcon"
27+
@click="downloadFile(file)" />
28+
</div>
29+
</div>
30+
</div>
31+
</div>
32+
</div>
33+
</template>
34+
35+
<script lang="ts" setup>
36+
import { downloadIcon } from '@/constants/iconPath'
37+
import type { AttachmentResponse } from '@/types/user'
38+
import { formatFileSize } from '@/utils/unit'
39+
import CommonIcons from '../common/CommonIcons.vue'
40+
41+
const { files } = defineProps<{ files: AttachmentResponse[] }>()
42+
const downloadFile = (file: AttachmentResponse) => {
43+
console.log('향후 파일 다운 로직 추가', file)
44+
}
45+
</script>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<template>
2+
<div>
3+
<p class="task-detail">히스토리</p>
4+
<TaskDetailHistoryInput :history="history" />
5+
<div class="flex flex-col w-full items-center gap-6 mt-8">
6+
<div
7+
class="flex flex-col items-center gap-6"
8+
v-for="item in history"
9+
:key="item.name">
10+
<div
11+
class="flex w-[150px] h-7 items-center justify-center bg-background-1 rounded-xl text-body text-xs font-bold">
12+
{{ formatDateWithDay(item.date) }}
13+
</div>
14+
<div class="flex gap-1 text-body text-sm">
15+
<p>{{ HistoryMessageBefore[item.TaskHistoryType] }}</p>
16+
<p
17+
v-if="item.TaskHistoryType === 'STATUS_SWITCHED'"
18+
class="text-primary1">
19+
{{ item.details.taskStatus }}
20+
</p>
21+
<p
22+
v-else-if="
23+
item.TaskHistoryType === 'PROCESSOR_CHANGED' ||
24+
item.TaskHistoryType === 'PROCESSOR_ASSIGNED'
25+
"
26+
class="text-primary1">
27+
{{ item.name }}
28+
</p>
29+
<p>{{ HistoryMessageAfter[item.TaskHistoryType] }}</p>
30+
</div>
31+
</div>
32+
</div>
33+
</div>
34+
</template>
35+
36+
<script setup lang="ts">
37+
import { HistoryMessageAfter, HistoryMessageBefore } from '@/constants/user'
38+
import type { TaskDetailHistoryProps } from '@/types/user'
39+
import { formatDateWithDay } from '@/utils/date'
40+
import TaskDetailHistoryInput from './TaskDetailHistoryInput.vue'
41+
42+
const { history } = defineProps<{ history: TaskDetailHistoryProps[] }>()
43+
</script>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<template>
2+
<div
3+
:class="[
4+
'w-full flex gap-3 px-6 py-4 border border-border-1 items-center',
5+
{ 'bg-background-2': !isPossible }
6+
]">
7+
<input
8+
class="w-full h-8 focus:outline-none"
9+
type="text"
10+
:placeholder="placeHolderText"
11+
:disabled="!isPossible" />
12+
<input
13+
class="hidden"
14+
type="file"
15+
id="file"
16+
multiple
17+
@change="handleFileUpload" />
18+
<label
19+
for="file"
20+
class="cursor-pointer">
21+
<CommonIcons :name="clipIcon" />
22+
</label>
23+
<CommonIcons
24+
:name="sendIcon"
25+
class="cursor-pointer"
26+
:style="{ fill: isPossible ? '#7879EB' : '#A1A1AA' }" />
27+
</div>
28+
</template>
29+
30+
<script setup lang="ts">
31+
import { clipIcon, sendIcon } from '@/constants/iconPath'
32+
import type { TaskDetailHistoryProps } from '@/types/user'
33+
import { ref } from 'vue'
34+
import CommonIcons from '../common/CommonIcons.vue'
35+
36+
const { history } = defineProps<{ history: TaskDetailHistoryProps[] }>()
37+
const isPossible = ref(history.length !== 0)
38+
const placeHolderText = ref(isPossible?.value ? '텍스트를 입력' : '요청 승인 후 작성할 수 있습니다')
39+
40+
const handleFileUpload = (event: Event) => {
41+
const target = event.target as HTMLInputElement
42+
if (target.files && target.files.length > 0) {
43+
console.log('향후 파일 전송로직 추가')
44+
}
45+
}
46+
</script>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<template>
2+
<div class="flex-grow flex flex-col gap-6 pt-6">
3+
<div>
4+
<p class="task-detail">1차 카테고리</p>
5+
<p>{{ taskDetail.mainCategoryName }}</p>
6+
</div>
7+
<div>
8+
<p class="task-detail">2차 카테고리</p>
9+
<p>{{ taskDetail.categoryName }}</p>
10+
</div>
11+
<div>
12+
<p class="task-detail">제목</p>
13+
<p>{{ taskDetail.title }}</p>
14+
</div>
15+
<div>
16+
<p class="task-detail">부가 설명</p>
17+
<p class="px-6 py-4 bg-primary2 rounded-lg font-normal">{{ taskDetail.description }}</p>
18+
</div>
19+
<div>
20+
<p class="task-detail">첨부 파일</p>
21+
<TaskDetailFiles :files="taskDetail.attachmentResponse" />
22+
</div>
23+
</div>
24+
</template>
25+
26+
<script setup lang="ts">
27+
import type { TaskDetailLeftProps } from '@/types/user'
28+
import TaskDetailFiles from './TaskDetailFiles.vue'
29+
const { taskDetail } = defineProps<{ taskDetail: TaskDetailLeftProps }>()
30+
</script>
31+
32+
<style scoped></style>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<template>
2+
<div class="w-60 flex flex-col gap-y-6 py-6 text-black">
3+
<div>
4+
<p class="task-detail">ID</p>
5+
<p>{{ taskDetail.taskId }}</p>
6+
</div>
7+
<div>
8+
<p class="task-detail">요청일</p>
9+
<p>{{ taskDetail.requestedAt }}</p>
10+
</div>
11+
<div>
12+
<p class="task-detail">종료일</p>
13+
<p>{{ taskDetail.finishedAt }}</p>
14+
</div>
15+
<div>
16+
<p class="task-detail">상태</p>
17+
<p>{{ taskDetail.taskStatus }}</p>
18+
</div>
19+
<div>
20+
<p class="task-detail">요청자</p>
21+
<div class="flex gap-2">
22+
<img
23+
:src="taskDetail.requesterImageUrl"
24+
width="24"
25+
height="24"
26+
class="rounded-full"
27+
alt="requesterImg" />
28+
<p>{{ taskDetail.requesterNickName }}</p>
29+
</div>
30+
</div>
31+
<div>
32+
<p class="task-detail">처리자</p>
33+
<div class="flex gap-2">
34+
<img
35+
:src="taskDetail.processorImageUrl"
36+
width="24"
37+
height="24"
38+
class="rounded-full"
39+
alt="requesterImg" />
40+
<p>{{ taskDetail.processorNickName }}</p>
41+
</div>
42+
</div>
43+
</div>
44+
</template>
45+
46+
<script setup lang="ts">
47+
import type { TaskDetailRightProps } from '@/types/user'
48+
import { defineProps } from 'vue'
49+
50+
const { taskDetail } = defineProps<{ taskDetail: TaskDetailRightProps }>()
51+
</script>
52+
53+
<script setup lang="ts"></script>

0 commit comments

Comments
 (0)