charts with period selection

This commit is contained in:
nquidox 2025-09-25 19:12:31 +03:00
parent e3a5d306d6
commit 8442b8e6b1

View file

@ -1,14 +1,152 @@
<script setup>
defineProps({
import { ref, watch } from 'vue'
import {
Chart as ChartJS,
Title,
Tooltip,
Legend,
LineElement,
PointElement,
CategoryScale,
TimeScale,
LinearScale
} from 'chart.js'
import { Line } from 'vue-chartjs'
import 'chartjs-adapter-date-fns'
ChartJS.register(
Title, Tooltip, Legend, LineElement, PointElement,
CategoryScale, TimeScale, LinearScale
)
const props = defineProps({
chartsData: {
type: Object,
required: true,
required: true
}
})
const originColors = {
surugaya: '#FF4560',
mandarake: '#775DD0'
}
const chartData = ref({
datasets: []
})
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
animation: false,
plugins: {
legend: { display: true },
tooltip: {
mode: 'index',
intersect: false,
callbacks: {
title: (context) => {
const date = new Date(context[0].parsed.x)
return date.toLocaleString('ru-RU', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
})
}
}
}
},
scales: {
x: {
type: 'time',
time: {
tooltipFormat: 'dd.MM.yyyy HH:mm',
unit: 'day',
displayFormats: { day: 'dd MMM' }
},
title: { display: true, text: 'Date' }
},
y: {
title: { display: true, text: 'Price' },
ticks: { precision: 0 }
}
},
elements: {
line: { borderWidth: 2, tension: 0, spanGaps: true },
point: { radius: 4, hoverRadius: 6 }
},
interaction: {
mode: 'nearest',
axis: 'x',
intersect: false
}
}
function transformToChartJSSeries(payload) {
const datasets = []
for (const origin of payload.origins) {
if (!origin.Prices || origin.Prices.length === 0) continue
const data = origin.Prices
.filter(p => p.value != null)
.map(p => {
let y = p.value
if (typeof y === 'string') {
y = parseFloat(y)
}
const x = typeof p.created_at === 'number'
? p.created_at * 1000
: new Date(p.created_at).getTime()
return {
x,
y: typeof y === 'number' && !isNaN(y) ? y : null
}
})
.filter(p => p.y !== null)
.sort((a, b) => a.x - b.x)
if (data.length === 0) continue
const color = originColors[origin.origin] || '#000000'
datasets.push({
label: origin.origin,
data,
borderColor: color,
backgroundColor: color + '20', // прозрачность
fill: false,
pointRadius: 4,
pointHoverRadius: 6,
type: 'line'
})
}
return datasets
}
watch(
() => props.chartsData,
(newData) => {
if (newData?.origins) {
const datasets = transformToChartJSSeries(newData)
chartData.value = { datasets }
}
},
{ immediate: true }
)
</script>
<template>
<n-card :title="chartsData.name" class="charts-card" style="--n-padding-bottom: 5px">
<div style="height: 400px; position: relative">
<Line
:data="chartData"
:options="chartOptions"
style="height: 100%; width: 100%"
/>
</div>
<p class="micro-uuid text-center">{{ chartsData.merch_uuid }}</p>
</n-card>
</template>