-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKitchenRevenue.client.vue
More file actions
130 lines (107 loc) · 3.43 KB
/
KitchenRevenue.client.vue
File metadata and controls
130 lines (107 loc) · 3.43 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
130
<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 dateStr = format(date, 'yyyy-MM-dd')
const value = values.find((d) => d.date.startsWith(dateStr))
return {
date,
total: value?.total ?? 0,
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>