90 lines
2.6 KiB
Vue
90 lines
2.6 KiB
Vue
<template lang="pug">
|
|
v-card.widget-card.pa-4.rounded-xl(color="#1e1e24" flat)
|
|
.d-flex.flex-wrap.justify-space-between.align-center.mb-4.gap-2
|
|
.text-subtitle-1.font-weight-bold.d-flex.align-center
|
|
v-icon(color="secondary" start) mdi-calendar-check
|
|
| {{ $t('stats.consistency') }}
|
|
|
|
.legend-container
|
|
span.text-caption.text-medium-emphasis.mr-1 {{ $t('stats.less') }}
|
|
.legend-box.level-0
|
|
.legend-box.level-1
|
|
.legend-box.level-2
|
|
.legend-box.level-3
|
|
.legend-box.level-4
|
|
span.text-caption.text-medium-emphasis.ml-1 {{ $t('stats.more') }}
|
|
|
|
.heatmap-container
|
|
.heatmap-year
|
|
.heatmap-week(v-for="(week, wIdx) in weeks" :key="wIdx")
|
|
.heatmap-day-wrapper(v-for="(day, dIdx) in week" :key="dIdx")
|
|
v-tooltip(location="top" open-delay="100")
|
|
template(v-slot:activator="{ props }")
|
|
.heatmap-cell(
|
|
v-bind="props"
|
|
:class="[\
|
|
isToday(day.date) ? 'today-cell' : '',\
|
|
getHeatmapClass(day.count)\
|
|
]"
|
|
)
|
|
.text-center
|
|
.font-weight-bold {{ formatDate(day.date) }}
|
|
div {{ $t('stats.reviewsCount', { count: day.count }) }}
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue';
|
|
|
|
import { useI18n } from 'vue-i18n';
|
|
const { locale } = useI18n();
|
|
|
|
const props = defineProps({
|
|
heatmapData: {
|
|
type: Object,
|
|
default: () => ({})
|
|
}
|
|
});
|
|
|
|
const weeks = computed(() => {
|
|
const data = props.heatmapData || {};
|
|
const w = [];
|
|
const today = new Date();
|
|
|
|
const startDate = new Date(today);
|
|
startDate.setDate(today.getDate() - (52 * 7));
|
|
const dayOfWeek = startDate.getDay();
|
|
startDate.setDate(startDate.getDate() - dayOfWeek);
|
|
|
|
let currentWeek = [];
|
|
for (let i = 0; i < 371; i++) {
|
|
const d = new Date(startDate);
|
|
d.setDate(startDate.getDate() + i);
|
|
const dateStr = d.toISOString().split('T')[0];
|
|
|
|
currentWeek.push({
|
|
date: dateStr,
|
|
count: data[dateStr] || 0
|
|
});
|
|
|
|
if (currentWeek.length === 7) {
|
|
w.push(currentWeek);
|
|
currentWeek = [];
|
|
}
|
|
}
|
|
return w;
|
|
});
|
|
|
|
const getHeatmapClass = (count) => {
|
|
if (count === 0) return 'level-0';
|
|
if (count <= 5) return 'level-1';
|
|
if (count <= 10) return 'level-2';
|
|
if (count <= 20) return 'level-3';
|
|
return 'level-4';
|
|
};
|
|
|
|
const formatDate = (dateStr) => new Date(dateStr).toLocaleDateString(locale.value, { month: 'short', day: 'numeric' });
|
|
const isToday = (dateStr) => dateStr === new Date().toISOString().split('T')[0];
|
|
</script>
|
|
|
|
<style lang="scss" src="@/styles/components/_widgets.scss" scoped></style>
|