optimization
Some checks failed
Deploy MyApp on Same Server / build-and-deploy (push) Failing after 1s

This commit is contained in:
2025-12-19 23:17:30 +03:30
parent 31b58b7151
commit 618960bb5c
101 changed files with 4812 additions and 2319 deletions

View File

@@ -1,104 +1,106 @@
import { useState, useMemo, memo, useCallback } from 'react'
import { BarChart3 } from 'lucide-react'
import { LineChart, Panel } from '@/components/Charts'
import { TimeRangeSelector } from './TimeRangeSelector'
import { DataGap } from './utils'
import { DataGap, detectDataGaps, normalizeTelemetryData } from '@/features/daily-report/utils'
import { TelemetryDto } from '@/lib/api'
import { EmptyState } from '@/components/common'
import { useTelemetryCharts } from '@/features/daily-report/hooks/useTelemetryCharts'
type ChartsTabProps = {
chartStartMinute: number
chartEndMinute: number
onStartMinuteChange: (minute: number) => void
onEndMinuteChange: (minute: number) => void
labels: string[]
soil: (number | null)[]
humidity: (number | null)[]
temperature: (number | null)[]
lux: (number | null)[]
gas: (number | null)[]
tempMinMax: { min: number; max: number }
luxMinMax: { min: number; max: number }
totalRecords: number
sortedTelemetry: TelemetryDto[]
dataGaps?: DataGap[]
}
export function ChartsTab({
chartStartMinute,
chartEndMinute,
onStartMinuteChange,
onEndMinuteChange,
labels,
soil,
humidity,
temperature,
lux,
gas,
tempMinMax,
luxMinMax,
totalRecords,
dataGaps = []
export const ChartsTab = memo(function ChartsTab({
sortedTelemetry,
dataGaps = [],
}: ChartsTabProps) {
const [chartStartMinute, setChartStartMinute] = useState(0)
const [chartEndMinute, setChartEndMinute] = useState(1439)
const handleStartMinuteChange = useCallback((minute: number) => {
setChartStartMinute(minute)
}, [])
const handleEndMinuteChange = useCallback((minute: number) => {
setChartEndMinute(minute)
}, [])
// Normalize telemetry data
const normalizedTelemetry = useMemo(
() => normalizeTelemetryData(sortedTelemetry),
[sortedTelemetry]
)
// Filter by time range
const filteredTelemetry = useMemo(() => {
return normalizedTelemetry.filter(
t => t.minute >= chartStartMinute && t.minute <= chartEndMinute
)
}, [normalizedTelemetry, chartStartMinute, chartEndMinute])
// Detect data gaps in filtered data
const timestamps = useMemo(
() => filteredTelemetry.map(t => t.timestamp),
[filteredTelemetry]
)
const filteredDataGaps = useMemo(
() => detectDataGaps(timestamps, 30),
[timestamps]
)
// Build charts using custom hook
const { charts, chartLabels } = useTelemetryCharts({
filteredTelemetry,
filteredDataGaps,
})
return (
<div className="space-y-6">
{/* Time Range Selector */}
<TimeRangeSelector
startMinute={chartStartMinute}
endMinute={chartEndMinute}
onStartMinuteChange={onStartMinuteChange}
onEndMinuteChange={onEndMinuteChange}
totalRecords={totalRecords}
onStartMinuteChange={handleStartMinuteChange}
onEndMinuteChange={handleEndMinuteChange}
totalRecords={filteredTelemetry.length}
dataGaps={dataGaps}
/>
{/* Charts Grid */}
{totalRecords === 0 ? (
<div className="flex flex-col items-center justify-center py-16 text-gray-500">
<BarChart3 className="w-12 h-12 text-gray-300 mb-4" />
<p className="text-gray-600">دادهای برای این بازه زمانی موجود نیست</p>
</div>
{filteredTelemetry.length === 0 ? (
<EmptyState
icon={BarChart3}
title="داده‌ای موجود نیست"
message="داده‌ای برای این بازه زمانی موجود نیست"
/>
) : (
<div className="grid gap-6 md:grid-cols-2">
<Panel title="رطوبت خاک">
<LineChart
labels={labels}
series={[{ label: 'رطوبت خاک (%)', data: soil as (number | null)[], borderColor: '#16a34a', backgroundColor: '#dcfce7', fill: true }]}
yAxisMin={0}
yAxisMax={100}
/>
</Panel>
<Panel title="رطوبت">
<LineChart
labels={labels}
series={[{ label: 'رطوبت (%)', data: humidity as (number | null)[], borderColor: '#3b82f6', backgroundColor: '#dbeafe', fill: true }]}
yAxisMin={0}
yAxisMax={100}
/>
</Panel>
<Panel title="دما">
<LineChart
labels={labels}
series={[{ label: 'دما (°C)', data: temperature as (number | null)[], borderColor: '#ef4444', backgroundColor: '#fee2e2', fill: true }]}
yAxisMin={tempMinMax.min}
yAxisMax={tempMinMax.max}
/>
</Panel>
<Panel title="نور">
<LineChart
labels={labels}
series={[{ label: 'Lux', data: lux as (number | null)[], borderColor: '#a855f7', backgroundColor: '#f3e8ff', fill: true }]}
yAxisMin={luxMinMax.min}
yAxisMax={luxMinMax.max}
/>
</Panel>
<Panel title="گاز CO">
<LineChart
labels={labels}
series={[{ label: 'CO (ppm)', data: gas as (number | null)[], borderColor: '#f59e0b', backgroundColor: '#fef3c7', fill: true }]}
yAxisMin={0}
yAxisMax={100}
/>
</Panel>
{charts.map(chart => (
<Panel key={chart.key} title={chart.title}>
<LineChart
labels={chartLabels}
series={[
{
label: chart.seriesLabel,
data: chart.data,
borderColor: chart.color,
backgroundColor: chart.bgColor,
fill: true,
},
]}
yAxisMin={chart.yAxisMin}
yAxisMax={chart.yAxisMax}
/>
</Panel>
))}
</div>
)}
</div>
)
}
}, (prevProps, nextProps) => {
// Custom comparison for better performance
return prevProps.sortedTelemetry.length === nextProps.sortedTelemetry.length &&
(prevProps.dataGaps?.length ?? 0) === (nextProps.dataGaps?.length ?? 0) &&
prevProps.sortedTelemetry[0]?.id === nextProps.sortedTelemetry[0]?.id
})