Skip to content

Commit d84f7d5

Browse files
authored
Merge pull request #43 from TaskFlow-CLAP/CLAP-167
�CLAP-167 통계 페이지 UI 제작
2 parents 87e4f2e + d9d0ac2 commit d84f7d5

File tree

8 files changed

+245
-2
lines changed

8 files changed

+245
-2
lines changed

src/components/LineChart.vue

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<template>
2+
<Line
3+
:data="teamData"
4+
:options="options" />
5+
</template>
6+
7+
<script setup lang="ts">
8+
import { Line } from 'vue-chartjs'
9+
import {
10+
Chart as ChartJS,
11+
Title,
12+
Tooltip,
13+
Legend,
14+
LineElement,
15+
PointElement,
16+
CategoryScale,
17+
LinearScale,
18+
Colors
19+
} from 'chart.js'
20+
21+
ChartJS.register(
22+
Title,
23+
Tooltip,
24+
Legend,
25+
LineElement,
26+
PointElement,
27+
CategoryScale,
28+
LinearScale,
29+
Colors
30+
)
31+
32+
const { labels, series, dataLabel } = defineProps<{
33+
labels: string[]
34+
series: number[]
35+
dataLabel: string
36+
}>()
37+
38+
const teamData = {
39+
labels,
40+
datasets: [
41+
{
42+
label: dataLabel,
43+
data: series,
44+
fill: true,
45+
tension: 0.4
46+
}
47+
]
48+
}
49+
50+
const options = {
51+
responsive: true,
52+
maintainAspectRatio: false
53+
}
54+
</script>

src/components/PieChart.vue

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,20 @@
66

77
<script setup lang="ts">
88
import { Pie } from 'vue-chartjs'
9-
import { Chart as ChartJS, Title, Tooltip, Legend, ArcElement, Colors } from 'chart.js'
9+
import {
10+
Chart as ChartJS,
11+
Title,
12+
Tooltip,
13+
Legend,
14+
ArcElement,
15+
Colors,
16+
type ChartEvent,
17+
type ActiveElement
18+
} from 'chart.js'
1019
ChartJS.register(Title, Tooltip, Legend, ArcElement, Colors)
1120
1221
const { labels, series } = defineProps<{ labels: string[]; series: number[] }>()
22+
const emit = defineEmits(['onClick'])
1323
1424
const teamData = {
1525
labels,
@@ -22,6 +32,12 @@ const teamData = {
2232
2333
const options = {
2434
responsive: true,
25-
maintainAspectRatio: false
35+
maintainAspectRatio: false,
36+
onClick: (event: ChartEvent, elements: ActiveElement[]) => {
37+
if (elements && elements.length > 0) {
38+
const clickedIndex = elements[0].index
39+
emit('onClick', labels[clickedIndex])
40+
}
41+
}
2642
}
2743
</script>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<template>
2+
<div class="text-xs font-bold flex gap-4">
3+
<button
4+
@click="changePeriod('DAY')"
5+
:class="
6+
periodType === 'DAY'
7+
? 'button-small-primary underline'
8+
: 'button-small-default hover:underline'
9+
">
10+
일간
11+
</button>
12+
<button
13+
@click="changePeriod('WEEK')"
14+
:class="
15+
periodType === 'WEEK'
16+
? 'button-small-primary underline'
17+
: 'button-small-default hover:underline'
18+
">
19+
주간
20+
</button>
21+
<button
22+
@click="changePeriod('MONTH')"
23+
:class="
24+
periodType === 'MONTH'
25+
? 'button-small-primary underline'
26+
: 'button-small-default hover:underline'
27+
">
28+
월간
29+
</button>
30+
</div>
31+
</template>
32+
33+
<script setup lang="ts">
34+
import type { PeriodType } from '@/types/manager'
35+
36+
const { periodType } = defineProps<{ periodType: PeriodType }>()
37+
const emit = defineEmits(['update:period'])
38+
39+
const changePeriod = (periodType: PeriodType) => {
40+
emit('update:period', periodType)
41+
}
42+
</script>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<template>
2+
<div
3+
class="flex flex-col h-fit gap-3 px-4 py-4 border-l-8 border-primary1 bg-white rounded-lg shadow-custom">
4+
<div class="flex flex-col gap-2">
5+
<span class="font-bold text-black">{{ title }}</span>
6+
<PeriodButtons
7+
:period-type="periodType"
8+
@update:period="changePeriod" />
9+
</div>
10+
<div class="w-full h-[1px] bg-border-1" />
11+
<div class="h-60">
12+
<PieChart
13+
v-if="chartType === 'pie'"
14+
:labels="['a', 'b', 'c']"
15+
:series="[1, 2, 3]" />
16+
<LineChart
17+
v-if="chartType === 'line'"
18+
:labels="['a', 'b', 'c']"
19+
:series="[1, 2, 3]"
20+
:data-label="title.slice(4)" />
21+
</div>
22+
</div>
23+
</template>
24+
25+
<script setup lang="ts">
26+
import { ref } from 'vue'
27+
import PieChart from '../PieChart.vue'
28+
import LineChart from '../LineChart.vue'
29+
import PeriodButtons from './PeriodButtons.vue'
30+
import type { PeriodType, StatisticsCardProps } from '@/types/manager'
31+
32+
const { title, statisticsType, chartType } = defineProps<StatisticsCardProps>()
33+
34+
const periodType = ref<PeriodType>('DAY')
35+
const changePeriod = (newPeriodType: PeriodType) => {
36+
periodType.value = newPeriodType
37+
}
38+
</script>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<template>
2+
<div
3+
class="flex flex-col h-fit gap-3 px-4 py-4 border-l-8 border-primary1 bg-white rounded-lg shadow-custom">
4+
<div class="flex flex-col gap-2">
5+
<span class="font-bold text-black">카테고리별 작업 요청량</span>
6+
<PeriodButtons
7+
:period-type="periodType"
8+
@update:period="changePeriod" />
9+
</div>
10+
<div class="w-full h-[1px] bg-border-1" />
11+
<div class="h-60 flex overflow-hidden">
12+
<div class="w-1/2 px-1">
13+
<PieChart
14+
:labels="['a', 'b', 'c', 'd']"
15+
:series="[1, 2, 3, 4]"
16+
@on-click="changeMainCategory" />
17+
</div>
18+
<div class="w-1/2 px-1">
19+
<PieChart
20+
:key="mainCategory"
21+
:labels="
22+
mainCategory
23+
? [`${mainCategory}-1`, `${mainCategory}-2`, `${mainCategory}-3`, `${mainCategory}-4`]
24+
: ['카테고리를 선택해주세요']
25+
"
26+
:series="mainCategory ? [1, 2, 3, 4] : []" />
27+
</div>
28+
</div>
29+
</div>
30+
</template>
31+
32+
<script setup lang="ts">
33+
import { ref } from 'vue'
34+
import PieChart from '../PieChart.vue'
35+
import PeriodButtons from './PeriodButtons.vue'
36+
import type { PeriodType } from '@/types/manager'
37+
38+
const periodType = ref<PeriodType>('DAY')
39+
const changePeriod = (newPeriodType: PeriodType) => {
40+
periodType.value = newPeriodType
41+
}
42+
43+
const mainCategory = ref('')
44+
const changeMainCategory = (value: string) => (mainCategory.value = value)
45+
</script>

src/router/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ const router = createRouter({
8787
path: '/user-update',
8888
name: 'UserUpdate',
8989
component: () => import('../views/UserUpdateView.vue')
90+
},
91+
{
92+
path: '/statistics',
93+
name: 'Statistics',
94+
component: () => import('../views/StatisticsView.vue')
9095
}
9196
]
9297
})

src/types/manager.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,17 @@ export interface RequestApproveFormData {
7474
dueDate: string
7575
dueTime: string
7676
}
77+
78+
export type PeriodType = 'DAY' | 'WEEK' | 'MONTH'
79+
80+
type StatisticsType =
81+
| 'REQUEST_BY_PERIOD'
82+
| 'PROCESS_BY_PERIOD'
83+
| 'REQUEST_BY_CATEGORY'
84+
| 'PROCESS_BY_MANAGER'
85+
86+
export interface StatisticsCardProps {
87+
title: string
88+
statisticsType: StatisticsType
89+
chartType: 'line' | 'pie'
90+
}

src/views/StatisticsView.vue

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<template>
2+
<div class="list-view">
3+
<TitleBar title="통계" />
4+
5+
<div class="grow bg-primary2 rounded-lg grid grid-cols-2 gap-12 px-12 py-6 overflow-y-scroll">
6+
<StatisticsCard
7+
title="기간별 작업 요청량"
8+
statistics-type="REQUEST_BY_PERIOD"
9+
chart-type="line">
10+
</StatisticsCard>
11+
<StatisticsCategoryCard />
12+
<StatisticsCard
13+
title="기간별 작업 처리량"
14+
statistics-type="PROCESS_BY_PERIOD"
15+
chart-type="line">
16+
</StatisticsCard>
17+
<StatisticsCard
18+
title="담당자별 작업 처리량"
19+
statistics-type="PROCESS_BY_MANAGER"
20+
chart-type="pie" />
21+
</div>
22+
</div>
23+
</template>
24+
25+
<script setup lang="ts">
26+
import StatisticsCard from '@/components/statistics/StatisticsCard.vue'
27+
import StatisticsCategoryCard from '@/components/statistics/StatisticsCategoryCard.vue'
28+
import TitleBar from '@/components/TitleBar.vue'
29+
</script>

0 commit comments

Comments
 (0)