Some checks failed
Deploy MyApp on Same Server / build-and-deploy (push) Failing after 1s
158 lines
5.9 KiB
TypeScript
158 lines
5.9 KiB
TypeScript
import { useMemo, useState } from 'react'
|
||
import { SummaryCard } from './SummaryCard'
|
||
import { WeatherData } from '@/features/weather'
|
||
import { GreenhouseForecastAlerts, getForecastAlertsCount } from './GreenhouseForecastAlerts'
|
||
import { Dialog } from '@/components/common/Dialog'
|
||
import { WeatherAlertBanner } from '@/components/alerts'
|
||
import { Loader2 } from 'lucide-react'
|
||
|
||
type SummaryTabProps = {
|
||
temperature: number[]
|
||
humidity: number[]
|
||
soil: number[]
|
||
gas: number[]
|
||
lux: number[]
|
||
forecastWeather?: WeatherData | null
|
||
forecastWeatherLoading?: boolean
|
||
onCardClick?: (param: string) => void
|
||
}
|
||
|
||
export function SummaryTab({ temperature, humidity, soil, gas, lux, forecastWeather, forecastWeatherLoading = false, onCardClick }: SummaryTabProps) {
|
||
const [isAlertsDialogOpen, setIsAlertsDialogOpen] = useState(false)
|
||
|
||
const alertsCount = useMemo(() => {
|
||
return getForecastAlertsCount(forecastWeather ?? null)
|
||
}, [forecastWeather])
|
||
// Memoized summary statistics for each parameter
|
||
const temperatureSummary = useMemo(() => {
|
||
if (temperature.length === 0) return { current: 0, min: 0, max: 0 }
|
||
return {
|
||
current: temperature.at(-1) ?? 0,
|
||
min: Math.min(...temperature),
|
||
max: Math.max(...temperature),
|
||
}
|
||
}, [temperature])
|
||
|
||
const humiditySummary = useMemo(() => {
|
||
if (humidity.length === 0) return { current: 0, min: 0, max: 0 }
|
||
return {
|
||
current: humidity.at(-1) ?? 0,
|
||
min: Math.min(...humidity),
|
||
max: Math.max(...humidity),
|
||
}
|
||
}, [humidity])
|
||
|
||
const soilSummary = useMemo(() => {
|
||
if (soil.length === 0) return { current: 0, min: 0, max: 0 }
|
||
return {
|
||
current: soil.at(-1) ?? 0,
|
||
min: Math.min(...soil),
|
||
max: Math.max(...soil),
|
||
}
|
||
}, [soil])
|
||
|
||
const gasSummary = useMemo(() => {
|
||
if (gas.length === 0) return { current: 0, min: 0, max: 0 }
|
||
return {
|
||
current: gas.at(-1) ?? 0,
|
||
min: Math.min(...gas),
|
||
max: Math.max(...gas),
|
||
}
|
||
}, [gas])
|
||
|
||
const luxSummary = useMemo(() => {
|
||
if (lux.length === 0) return { current: 0, min: 0, max: 0 }
|
||
return {
|
||
current: lux.at(-1) ?? 0,
|
||
min: Math.min(...lux),
|
||
max: Math.max(...lux),
|
||
}
|
||
}, [lux])
|
||
|
||
return (
|
||
<>
|
||
{/* Greenhouse Forecast Alerts Section */}
|
||
{forecastWeatherLoading ? (
|
||
<div className="mb-6">
|
||
<div className="w-full p-4 bg-gradient-to-r from-amber-50 to-orange-50 border-2 border-amber-200 rounded-xl text-right flex items-center justify-between">
|
||
<div className="flex items-center gap-3">
|
||
<div className="w-10 h-10 bg-amber-500 rounded-lg flex items-center justify-center">
|
||
<Loader2 className="w-6 h-6 text-white animate-spin" />
|
||
</div>
|
||
<div>
|
||
<p className="font-semibold text-gray-800">
|
||
در حال بارگذاری هشدارهای آب و هوایی...
|
||
</p>
|
||
<p className="text-sm text-gray-600 mt-1">
|
||
لطفاً صبر کنید
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
) : alertsCount > 0 && forecastWeather ? (
|
||
<WeatherAlertBanner
|
||
alertsCount={alertsCount}
|
||
onClick={() => setIsAlertsDialogOpen(true)}
|
||
/>
|
||
) : null}
|
||
|
||
{/* Summary Cards Grid */}
|
||
<div className="grid gap-6 grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
|
||
<SummaryCard
|
||
param="temperature"
|
||
currentValue={temperatureSummary.current}
|
||
minValue={temperatureSummary.min}
|
||
maxValue={temperatureSummary.max}
|
||
data={temperature}
|
||
onClick={() => onCardClick?.('temperature')}
|
||
/>
|
||
<SummaryCard
|
||
param="humidity"
|
||
currentValue={humiditySummary.current}
|
||
minValue={humiditySummary.min}
|
||
maxValue={humiditySummary.max}
|
||
data={humidity}
|
||
onClick={() => onCardClick?.('humidity')}
|
||
/>
|
||
<SummaryCard
|
||
param="gas"
|
||
currentValue={gasSummary.current}
|
||
minValue={gasSummary.min}
|
||
maxValue={gasSummary.max}
|
||
data={gas}
|
||
onClick={() => onCardClick?.('gas')}
|
||
/>
|
||
<SummaryCard
|
||
param="soil"
|
||
currentValue={soilSummary.current}
|
||
minValue={soilSummary.min}
|
||
maxValue={soilSummary.max}
|
||
data={soil}
|
||
onClick={() => onCardClick?.('soil')}
|
||
/>
|
||
<SummaryCard
|
||
param="lux"
|
||
currentValue={luxSummary.current}
|
||
minValue={luxSummary.min}
|
||
maxValue={luxSummary.max}
|
||
data={lux}
|
||
onClick={() => onCardClick?.('lux')}
|
||
/>
|
||
</div>
|
||
|
||
{/* Alerts Dialog */}
|
||
{forecastWeather && (
|
||
<Dialog
|
||
isOpen={isAlertsDialogOpen}
|
||
onClose={() => setIsAlertsDialogOpen(false)}
|
||
title="هشدارهای پیشبینی آب و هوا"
|
||
>
|
||
<GreenhouseForecastAlerts weatherData={forecastWeather} />
|
||
</Dialog>
|
||
)}
|
||
</>
|
||
)
|
||
}
|
||
|