-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKitchenRevenue.client.vue
More file actions
129 lines (106 loc) · 3.54 KB
/
Copy pathKitchenRevenue.client.vue
File metadata and controls
129 lines (106 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<template>
<UCard ref="cardRef" :ui="{ root: 'overflow-visible', body: '!px-0 !pt-0 !pb-3' }">
<template #header>
<div>
<p class="text-xs text-muted uppercase mb-1.5">
Выручка за {{ data.length }} {{ pluralizationRu(data.length, ['день', 'дня', 'дней']) }}
</p>
<p class="text-3xl text-highlighted font-semibold">
{{ formatNumber(total) }}
</p>
</div>
</template>
<VisXYContainer
:data="data"
:padding="{ top: 40 }"
class="h-96"
:width="width"
>
<VisLine
:x="x"
:y="y"
color="var(--ui-secondary)"
/>
<VisArea
:x="x"
:y="y"
color="var(--ui-secondary)"
:opacity="0.1"
/>
<VisAxis
type="x"
:x="x"
:tick-format="xTicks"
/>
<VisCrosshair
color="var(--ui-secondary)"
:template="template"
/>
<VisTooltip />
</VisXYContainer>
</UCard>
</template>
<script setup lang="ts">
import type { Period, Range } from '#shared/types'
import { VisArea, VisAxis, VisCrosshair, VisLine, VisTooltip, VisXYContainer } from '@unovis/vue'
import { eachDayOfInterval, eachMonthOfInterval, eachWeekOfInterval, format } from 'date-fns'
import { ru } from 'date-fns/locale'
type DataRecord = {
date: Date
total: number
checks: number
}
const { period, range, values } = defineProps<{
period: Period
range: Range
values: { date: string, total: number, checks: number }[]
}>()
const cardRef = useTemplateRef<HTMLElement | null>('cardRef')
const { width } = useElementSize(cardRef)
const data = ref<DataRecord[]>([])
watch([() => period, () => range, () => values], () => {
const dates = ({
daily: eachDayOfInterval,
weekly: eachWeekOfInterval,
monthly: eachMonthOfInterval,
} as Record<Period, typeof eachDayOfInterval>)[period](range)
data.value = dates.map((date) => {
const value = values.find((d) => new Date(d.date).getFullYear() === date.getFullYear() && new Date(d.date).getMonth() === date.getMonth() && new Date(d.date).getDate() === date.getDate())
return {
date,
total: value?.total ? value.total : 0,
checks: value?.checks ? value.checks : 0,
}
})
}, { immediate: true })
const x = (_: DataRecord, i: number) => i
const y = (d: DataRecord) => d.total
const total = computed(() => data.value.reduce((acc: number, { total }) => acc + total, 0))
const formatNumber = new Intl.NumberFormat('ru', { style: 'currency', currency: 'RUB', maximumFractionDigits: 0 }).format
function formatDate(date: Date): string {
return ({
daily: format(date, 'd MMMM', { locale: ru }),
weekly: format(date, 'd MMMM', { locale: ru }),
monthly: format(date, 'MMMM yyy', { locale: ru }),
})[period]
}
function xTicks(i: number) {
if (i === 0 || i === data.value.length - 1 || !data.value[i]) {
return ''
}
return formatDate(data.value[i].date)
}
const template = (d: DataRecord) => `${formatDate(d.date)}: ${formatNumber(d.total)}, ${d.checks} ${pluralizationRu(d.checks, ['чек', 'чека', 'чеков'])}`
</script>
<style scoped>
.unovis-xy-container {
--vis-crosshair-line-stroke-color: var(--ui-secondary);
--vis-crosshair-circle-stroke-color: var(--ui-bg);
--vis-axis-grid-color: var(--ui-border);
--vis-axis-tick-color: var(--ui-border);
--vis-axis-tick-label-color: var(--ui-text-dimmed);
--vis-tooltip-background-color: var(--ui-bg);
--vis-tooltip-border-color: var(--ui-border);
--vis-tooltip-text-color: var(--ui-text-highlighted);
}
</style>