Add plant simulator feature with Persian localization and UI enhancements

- Introduced a new Plant Simulator section in the dashboard with a dedicated menu item.
- Added Persian translations for plant growth metrics and chart titles.
- Enhanced the GrowthChart component to utilize localized labels for better user experience.
- Updated PlantSimulator component to display plant statistics and growth visualization.
- Improved UI layout with Material-UI components for a more polished appearance.
This commit is contained in:
2026-02-20 23:48:14 +03:30
parent f9bb6a3984
commit 0eb109725e
3 changed files with 305 additions and 242 deletions
+31
View File
@@ -37,6 +37,7 @@
"waterData": "دیتاهای آب", "waterData": "دیتاهای آب",
"soilData": "اطلاعات خاک", "soilData": "اطلاعات خاک",
"cropZoning": "زون‌بندی کشت", "cropZoning": "زون‌بندی کشت",
"plantSimulator": "شبیه‌ساز رشد گیاه",
"dataSection": "بخش داده‌ها", "dataSection": "بخش داده‌ها",
"crm": "مدیریت ارتباط با مشتری", "crm": "مدیریت ارتباط با مشتری",
"analytics": "تحلیل‌ها", "analytics": "تحلیل‌ها",
@@ -561,5 +562,35 @@
"forecastChart": "پیش‌بینی هوا", "forecastChart": "پیش‌بینی هوا",
"forecastSubheader": "دما و رطوبت در ۷ روز آینده" "forecastSubheader": "دما و رطوبت در ۷ روز آینده"
} }
},
"plantSimulator": {
"title": "شبیه‌ساز رشد گیاه",
"height": "ارتفاع",
"leaves": "برگ",
"branches": "شاخه",
"fruits": "میوه",
"yield": "محصول (g)",
"yieldRate": "سرعت (g/s)",
"maxGrowthReached": "گیاه به حداکثر رشد رسید!",
"controls": "کنترل‌ها",
"stop": "توقف",
"start": "شروع",
"reset": "ریست",
"growthSpeed": "سرعت رشد",
"light": "نور",
"water": "آب",
"effectiveRate": "نرخ رشد مؤثر",
"chartTitle": "نمودار رشد گیاه",
"chartHeight": "ارتفاع",
"chartLeaves": "برگ",
"chartHeightPx": "ارتفاع (px)",
"chartLeafCount": "تعداد برگ",
"chartYield": "محصول (g)",
"chartYieldRate": "سرعت محصول (g/s)",
"progressGrowth": "پیشرفت رشد",
"lightStatus": "وضعیت نور",
"waterStatus": "وضعیت آب",
"yieldStatus": "محصول دهی",
"description": "این شبیه‌ساز رشد گیاه را بر اساس سرعت پایه، میزان نور خورشید و آب دریافتی محاسبه می‌کند. هر برگ به صورت تدریجی روی ساقه ظاهر شده و با حرکت طبیعی در باد نمایش داده می‌شود. محصول‌دهی (g) پس از ۲۰٪ رشد شروع شده و با تعداد برگ، نور و آب شتاب می‌گیرد. سرعت محصول (g/s) نشان‌دهنده نرخ لحظه‌ای تولید است. نمودار تغییرات همه شاخص‌ها را در طول زمان ثبت می‌کند."
} }
} }
@@ -105,6 +105,9 @@ const VerticalMenu = ({ scrollMenu }: Props) => {
<MenuItem href="/dashboard/crop-zoning" icon={<i className="tabler-map-2" />}> <MenuItem href="/dashboard/crop-zoning" icon={<i className="tabler-map-2" />}>
{t('cropZoning')} {t('cropZoning')}
</MenuItem> </MenuItem>
<MenuItem href="/dashboard/plant-simulator" icon={<i className="tabler-flower" />}>
{t('plantSimulator')}
</MenuItem>
</MenuSection> </MenuSection>
</Menu> </Menu>
@@ -1,6 +1,7 @@
'use client' 'use client'
import { useEffect, useRef, useState, useCallback, memo } from 'react' import { useEffect, useRef, useState, useCallback, memo } from 'react'
import { useTranslations } from 'next-intl'
import { import {
Chart as ChartJS, Chart as ChartJS,
LineElement, LineElement,
@@ -13,6 +14,12 @@ import {
Filler Filler
} from 'chart.js' } from 'chart.js'
import { Line } from 'react-chartjs-2' import { Line } from 'react-chartjs-2'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import Box from '@mui/material/Box'
import Grid from '@mui/material/Grid2'
import Button from '@mui/material/Button'
ChartJS.register(LineElement, PointElement, LinearScale, CategoryScale, Title, Tooltip, Legend, Filler) ChartJS.register(LineElement, PointElement, LinearScale, CategoryScale, Title, Tooltip, Legend, Filler)
@@ -393,59 +400,6 @@ function PlantSVG({ plant, tick, running }: { plant: PlantState; tick: number; r
// ─── Growth Chart ───────────────────────────────────────────────────────────── // ─── Growth Chart ─────────────────────────────────────────────────────────────
const CHART_OPTIONS = {
responsive: true,
animation: { duration: 0 },
plugins: {
legend: { labels: { color: '#e2e8f0', font: { size: 11 } } },
title: {
display: true,
text: 'نمودار رشد گیاه',
color: '#e2e8f0',
font: { size: 14 }
}
},
scales: {
x: {
ticks: { color: '#94a3b8', maxTicksLimit: 8 },
grid: { color: 'rgba(148,163,184,0.1)' }
},
yHeight: {
type: 'linear' as const,
position: 'left' as const,
min: 0,
max: MAX_HEIGHT,
ticks: { color: '#4a7c59' },
grid: { color: 'rgba(148,163,184,0.1)' },
title: { display: true, text: 'ارتفاع', color: '#4a7c59' }
},
yLeaf: {
type: 'linear' as const,
position: 'right' as const,
min: 0,
max: MAX_LEAVES,
ticks: { color: '#f9c74f' },
grid: { display: false },
title: { display: true, text: 'برگ', color: '#f9c74f' }
},
yYield: {
type: 'linear' as const,
position: 'left' as const,
min: 0,
max: MAX_YIELD,
display: false,
grid: { display: false }
},
yYieldRate: {
type: 'linear' as const,
position: 'right' as const,
min: 0,
display: false,
grid: { display: false }
}
}
}
const GrowthChart = memo(function GrowthChart({ const GrowthChart = memo(function GrowthChart({
heightHistory, heightHistory,
leafHistory, leafHistory,
@@ -457,13 +411,63 @@ const GrowthChart = memo(function GrowthChart({
yieldHistory: number[] yieldHistory: number[]
yieldRateHistory: number[] yieldRateHistory: number[]
}) { }) {
const t = useTranslations('plantSimulator')
const chartOptions = {
responsive: true,
animation: { duration: 0 },
plugins: {
legend: { labels: { font: { size: 11 } } },
title: {
display: true,
text: t('chartTitle'),
font: { size: 14 }
}
},
scales: {
x: {
ticks: { maxTicksLimit: 8 }
},
yHeight: {
type: 'linear' as const,
position: 'left' as const,
min: 0,
max: MAX_HEIGHT,
title: { display: true, text: t('chartHeight') }
},
yLeaf: {
type: 'linear' as const,
position: 'right' as const,
min: 0,
max: MAX_LEAVES,
grid: { display: false },
title: { display: true, text: t('chartLeaves') }
},
yYield: {
type: 'linear' as const,
position: 'left' as const,
min: 0,
max: MAX_YIELD,
display: false,
grid: { display: false }
},
yYieldRate: {
type: 'linear' as const,
position: 'right' as const,
min: 0,
display: false,
grid: { display: false }
}
}
}
const labels = heightHistory.map((_, i) => `${i}s`) const labels = heightHistory.map((_, i) => `${i}s`)
const data = { const data = {
labels, labels,
datasets: [ datasets: [
{ {
label: 'ارتفاع (px)', label: t('chartHeightPx'),
data: heightHistory, data: heightHistory,
borderColor: '#4a7c59', borderColor: '#4a7c59',
backgroundColor: 'rgba(74,124,89,0.10)', backgroundColor: 'rgba(74,124,89,0.10)',
@@ -473,7 +477,7 @@ const GrowthChart = memo(function GrowthChart({
yAxisID: 'yHeight' yAxisID: 'yHeight'
}, },
{ {
label: 'تعداد برگ', label: t('chartLeafCount'),
data: leafHistory, data: leafHistory,
borderColor: '#f9c74f', borderColor: '#f9c74f',
backgroundColor: 'rgba(249,199,79,0.10)', backgroundColor: 'rgba(249,199,79,0.10)',
@@ -483,7 +487,7 @@ const GrowthChart = memo(function GrowthChart({
yAxisID: 'yLeaf' yAxisID: 'yLeaf'
}, },
{ {
label: 'محصول (g)', label: t('chartYield'),
data: yieldHistory, data: yieldHistory,
borderColor: '#f97316', borderColor: '#f97316',
backgroundColor: 'rgba(249,115,22,0.10)', backgroundColor: 'rgba(249,115,22,0.10)',
@@ -493,7 +497,7 @@ const GrowthChart = memo(function GrowthChart({
yAxisID: 'yYield' yAxisID: 'yYield'
}, },
{ {
label: 'سرعت محصول (g/s)', label: t('chartYieldRate'),
data: yieldRateHistory, data: yieldRateHistory,
borderColor: '#a78bfa', borderColor: '#a78bfa',
backgroundColor: 'rgba(167,139,250,0.10)', backgroundColor: 'rgba(167,139,250,0.10)',
@@ -506,7 +510,7 @@ const GrowthChart = memo(function GrowthChart({
] ]
} }
return <Line data={data} options={CHART_OPTIONS} /> return <Line data={data} options={chartOptions} />
}) })
// ─── Main Component ─────────────────────────────────────────────────────────── // ─── Main Component ───────────────────────────────────────────────────────────
@@ -698,207 +702,232 @@ export default function PlantSimulator() {
} }
}, [running]) }, [running])
const t = useTranslations('plantSimulator')
const isFinished = plant.height >= MAX_HEIGHT const isFinished = plant.height >= MAX_HEIGHT
const statItems: { value: string | number; label: string; color: 'success' | 'warning' | 'error' | 'secondary' }[] = [
{ value: Math.round(plant.height), label: t('height'), color: 'success' },
{ value: plant.leaves.length, label: t('leaves'), color: 'warning' },
{ value: plant.branches.length, label: t('branches'), color: 'success' },
{ value: plant.fruits.length, label: t('fruits'), color: 'error' },
{ value: plant.yield.toFixed(1), label: t('yield'), color: 'warning' },
{ value: plant.yieldRate.toFixed(2), label: t('yieldRate'), color: 'secondary' }
]
return ( return (
<div className='min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 text-slate-100 p-6'> <Box className='flex flex-col gap-6 is-full'>
<h1 className='text-3xl font-bold text-center mb-8 tracking-tight'> <Typography variant='h4' className='text-center font-bold'>
🌱 شبیهساز رشد گیاه 🌱 {t('title')}
</h1> </Typography>
<div className='max-w-6xl mx-auto grid grid-cols-1 lg:grid-cols-3 gap-6'>
<Grid container spacing={6} className='max-w-6xl mx-auto'>
{/* ── Left: Plant visualization ── */} {/* ── Left: Plant visualization ── */}
<div className='lg:col-span-1 flex flex-col items-center gap-4'> <Grid size={{ xs: 12, lg: 4 }} className='flex flex-col items-center gap-4'>
<div className='bg-slate-800 border border-slate-700 rounded-2xl p-6 w-full flex flex-col items-center shadow-xl'> <Card className='is-full flex flex-col items-center p-6'>
<PlantSVG plant={plant} tick={plant.tick} running={running} /> <CardContent className='flex flex-col items-center gap-4 is-full p-0'>
<PlantSVG plant={plant} tick={plant.tick} running={running} />
{/* Stats */} <Grid container spacing={2} className='is-full'>
<div className='mt-4 grid grid-cols-3 gap-2 w-full text-sm'> {statItems.map((item, idx) => (
<div className='bg-green-900/40 border border-green-700/40 rounded-xl p-2.5 text-center'> <Grid key={idx} size={{ xs: 4 }}>
<div className='text-green-400 font-semibold text-base'>{Math.round(plant.height)}</div> <Card variant='outlined' className='text-center p-2.5'>
<div className='text-slate-400 text-[10px]'>ارتفاع</div> <Typography variant='h6' color={item.color}>
</div> {item.value}
<div className='bg-yellow-900/40 border border-yellow-700/40 rounded-xl p-2.5 text-center'> </Typography>
<div className='text-yellow-400 font-semibold text-base'>{plant.leaves.length}</div> <Typography variant='caption' color='text.secondary'>
<div className='text-slate-400 text-[10px]'>برگ</div> {item.label}
</div> </Typography>
<div className='bg-emerald-900/40 border border-emerald-700/40 rounded-xl p-2.5 text-center'> </Card>
<div className='text-emerald-400 font-semibold text-base'>{plant.branches.length}</div> </Grid>
<div className='text-slate-400 text-[10px]'>شاخه</div> ))}
</div> </Grid>
<div className='bg-red-900/40 border border-red-700/40 rounded-xl p-2.5 text-center'>
<div className='text-red-400 font-semibold text-base'>{plant.fruits.length}</div>
<div className='text-slate-400 text-[10px]'>میوه</div>
</div>
<div className='bg-orange-900/40 border border-orange-700/40 rounded-xl p-2.5 text-center'>
<div className='text-orange-400 font-semibold text-base'>{plant.yield.toFixed(1)}</div>
<div className='text-slate-400 text-[10px]'>محصول (g)</div>
</div>
<div className='bg-violet-900/40 border border-violet-700/40 rounded-xl p-2.5 text-center'>
<div className='text-violet-400 font-semibold text-base'>{plant.yieldRate.toFixed(2)}</div>
<div className='text-slate-400 text-[10px]'>سرعت (g/s)</div>
</div>
</div>
{isFinished && ( {isFinished && (
<div className='mt-3 text-yellow-300 text-sm font-medium animate-pulse'> <Typography variant='body2' color='warning.main' className='font-medium animate-pulse'>
🌼 گیاه به حداکثر رشد رسید! 🌼 {t('maxGrowthReached')}
</div> </Typography>
)} )}
</div> </CardContent>
</Card>
{/* Controls */} {/* Controls */}
<div className='bg-slate-800 border border-slate-700 rounded-2xl p-5 w-full shadow-xl space-y-4'> <Card className='is-full p-5'>
<h2 className='font-semibold text-slate-300 text-base mb-1'>کنترلها</h2> <CardContent className='space-y-4 p-0'>
<Typography variant='subtitle1' component='h2' className='font-semibold'>
{t('controls')}
</Typography>
{/* Start / Stop / Reset */} <Box className='flex gap-2'>
<div className='flex gap-2'> <Button
<button variant='contained'
onClick={() => setRunning(r => !r)} color={running ? 'error' : 'success'}
disabled={isFinished} onClick={() => setRunning(r => !r)}
className={`flex-1 py-2 rounded-xl font-semibold transition-all text-sm disabled={isFinished}
${running fullWidth
? 'bg-red-600 hover:bg-red-500' >
: 'bg-green-600 hover:bg-green-500'} {running ? `${t('stop')}` : `${t('start')}`}
disabled:opacity-40 disabled:cursor-not-allowed`} </Button>
> <Button
{running ? '⏸ توقف' : '▶ شروع'} variant='outlined'
</button> color='secondary'
<button onClick={() => { setRunning(false); reset() }}
onClick={() => { setRunning(false); reset() }} >
className='px-4 py-2 rounded-xl bg-slate-600 hover:bg-slate-500 text-sm font-semibold transition-all' {t('reset')}
> </Button>
ریست </Box>
</button>
</div>
{/* Speed slider */} <Box>
<div> <Typography variant='body2' color='text.secondary' className='flex justify-between mbe-1'>
<label className='flex justify-between text-sm text-slate-400 mb-1'> <span>{t('growthSpeed')}</span>
<span>سرعت رشد</span> <span className='font-medium'>{speed.toFixed(1)}×</span>
<span className='text-white font-medium'>{speed.toFixed(1)}×</span> </Typography>
</label> <input
<input type='range'
type='range' min={0.5} max={5} step={0.5} min={0.5}
value={speed} max={5}
onChange={e => setSpeed(Number(e.target.value))} step={0.5}
className='w-full accent-green-500' value={speed}
/> onChange={e => setSpeed(Number(e.target.value))}
</div> className='w-full'
/>
</Box>
{/* Light */} <Box>
<div> <Typography variant='body2' color='text.secondary' className='flex justify-between mbe-1'>
<label className='flex justify-between text-sm text-slate-400 mb-1'> <span> {t('light')}</span>
<span> نور</span> <span className='font-medium'>{env.light}%</span>
<span className='text-yellow-400 font-medium'>{env.light}%</span> </Typography>
</label> <input
<input type='range'
type='range' min={0} max={100} step={5} min={0}
value={env.light} max={100}
onChange={e => setEnv(prev => ({ ...prev, light: Number(e.target.value) }))} step={5}
className='w-full accent-yellow-400' value={env.light}
/> onChange={e => setEnv(prev => ({ ...prev, light: Number(e.target.value) }))}
</div> className='w-full'
/>
</Box>
{/* Water */} <Box>
<div> <Typography variant='body2' color='text.secondary' className='flex justify-between mbe-1'>
<label className='flex justify-between text-sm text-slate-400 mb-1'> <span>💧 {t('water')}</span>
<span>💧 آب</span> <span className='font-medium'>{env.water}%</span>
<span className='text-blue-400 font-medium'>{env.water}%</span> </Typography>
</label> <input
<input type='range'
type='range' min={0} max={100} step={5} min={0}
value={env.water} max={100}
onChange={e => setEnv(prev => ({ ...prev, water: Number(e.target.value) }))} step={5}
className='w-full accent-blue-400' value={env.water}
/> onChange={e => setEnv(prev => ({ ...prev, water: Number(e.target.value) }))}
</div> className='w-full'
/>
</Box>
{/* Effective rate indicator */} <Card variant='outlined' className='p-3'>
<div className='bg-slate-700/50 rounded-xl p-3 text-xs text-slate-400'> <Typography variant='caption' color='text.secondary'>
نرخ رشد مؤثر:{' '} {t('effectiveRate')}{' '}
<span className='text-green-400 font-semibold'> <Typography component='span' variant='caption' color='success.main' fontWeight='bold'>
{growthRate(env, speed).toFixed(2)}× {growthRate(env, speed).toFixed(2)}×
</span> </Typography>
</div> </Typography>
</div> </Card>
</div> </CardContent>
</Card>
</Grid>
{/* ── Right: Chart ── */} {/* ── Right: Chart ── */}
<div className='lg:col-span-2 bg-slate-800 border border-slate-700 rounded-2xl p-6 shadow-xl'> <Grid size={{ xs: 12, lg: 8 }}>
<GrowthChart <Card className='p-6'>
heightHistory={heightHistory} <CardContent>
leafHistory={leafHistory} <GrowthChart
yieldHistory={yieldHistory} heightHistory={heightHistory}
yieldRateHistory={yieldRateHistory} leafHistory={leafHistory}
/> yieldHistory={yieldHistory}
yieldRateHistory={yieldRateHistory}
/>
{/* Info cards */} <Grid container spacing={4} className='mt-6'>
<div className='mt-6 grid grid-cols-2 lg:grid-cols-4 gap-4 text-sm'> <Grid size={{ xs: 12, sm: 6, lg: 3 }}>
<div className='bg-slate-700/60 rounded-xl p-4 border border-slate-600'> <Card variant='outlined' className='p-4'>
<div className='text-slate-400 mb-1'>پیشرفت رشد</div> <Typography variant='body2' color='text.secondary' className='mbe-1'>
<div className='w-full bg-slate-600 rounded-full h-2 mb-1'> {t('progressGrowth')}
<div </Typography>
className='bg-green-500 h-2 rounded-full transition-all' <Box className='w-full rounded-full overflow-hidden bg-action-hover mbe-1' sx={{ height: 8 }}>
style={{ width: `${(plant.height / MAX_HEIGHT) * 100}%` }} <Box
/> className='bg-success rounded-full h-full transition-all'
</div> sx={{ width: `${(plant.height / MAX_HEIGHT) * 100}%` }}
<div className='text-green-400 font-semibold'> />
{Math.round((plant.height / MAX_HEIGHT) * 100)}% </Box>
</div> <Typography variant='body2' color='success.main' fontWeight='bold'>
</div> {Math.round((plant.height / MAX_HEIGHT) * 100)}%
</Typography>
</Card>
</Grid>
<Grid size={{ xs: 12, sm: 6, lg: 3 }}>
<Card variant='outlined' className='p-4'>
<Typography variant='body2' color='text.secondary' className='mbe-1'>
{t('lightStatus')}
</Typography>
<Box className='w-full rounded-full overflow-hidden bg-action-hover mbe-1' sx={{ height: 8 }}>
<Box
className='bg-warning rounded-full h-full transition-all'
sx={{ width: `${env.light}%` }}
/>
</Box>
<Typography variant='body2' color='warning.main' fontWeight='bold'>
{env.light}%
</Typography>
</Card>
</Grid>
<Grid size={{ xs: 12, sm: 6, lg: 3 }}>
<Card variant='outlined' className='p-4'>
<Typography variant='body2' color='text.secondary' className='mbe-1'>
{t('waterStatus')}
</Typography>
<Box className='w-full rounded-full overflow-hidden bg-action-hover mbe-1' sx={{ height: 8 }}>
<Box
className='bg-info rounded-full h-full transition-all'
sx={{ width: `${env.water}%` }}
/>
</Box>
<Typography variant='body2' color='info.main' fontWeight='bold'>
{env.water}%
</Typography>
</Card>
</Grid>
<Grid size={{ xs: 12, sm: 6, lg: 3 }}>
<Card variant='outlined' className='p-4'>
<Typography variant='body2' color='text.secondary' className='mbe-1'>
{t('yieldStatus')}
</Typography>
<Box className='w-full rounded-full overflow-hidden bg-action-hover mbe-1' sx={{ height: 8 }}>
<Box
className='bg-warning rounded-full h-full transition-all'
sx={{ width: `${(plant.yield / MAX_YIELD) * 100}%` }}
/>
</Box>
<Box className='flex justify-between items-center'>
<Typography variant='body2' color='warning.main' fontWeight='bold'>
{plant.yield.toFixed(1)}g
</Typography>
<Typography variant='caption' color='secondary.main'>
{plant.yieldRate.toFixed(3)} g/s
</Typography>
</Box>
</Card>
</Grid>
</Grid>
<div className='bg-slate-700/60 rounded-xl p-4 border border-slate-600'> <Card variant='outlined' className='mt-6 p-4'>
<div className='text-slate-400 mb-1'>وضعیت نور</div> <Typography variant='body2' color='text.secondary' className='leading-6'>
<div className='w-full bg-slate-600 rounded-full h-2 mb-1'> {t('description')}
<div </Typography>
className='bg-yellow-400 h-2 rounded-full transition-all' </Card>
style={{ width: `${env.light}%` }} </CardContent>
/> </Card>
</div> </Grid>
<div className='text-yellow-400 font-semibold'>{env.light}%</div> </Grid>
</div> </Box>
<div className='bg-slate-700/60 rounded-xl p-4 border border-slate-600'>
<div className='text-slate-400 mb-1'>وضعیت آب</div>
<div className='w-full bg-slate-600 rounded-full h-2 mb-1'>
<div
className='bg-blue-400 h-2 rounded-full transition-all'
style={{ width: `${env.water}%` }}
/>
</div>
<div className='text-blue-400 font-semibold'>{env.water}%</div>
</div>
<div className='bg-slate-700/60 rounded-xl p-4 border border-slate-600'>
<div className='text-slate-400 mb-1'>محصول دهی</div>
<div className='w-full bg-slate-600 rounded-full h-2 mb-1'>
<div
className='bg-orange-400 h-2 rounded-full transition-all'
style={{ width: `${(plant.yield / MAX_YIELD) * 100}%` }}
/>
</div>
<div className='flex justify-between items-center'>
<span className='text-orange-400 font-semibold'>{plant.yield.toFixed(1)}g</span>
<span className='text-violet-400 text-xs'>{plant.yieldRate.toFixed(3)} g/s</span>
</div>
</div>
</div>
{/* Description */}
<div className='mt-6 bg-slate-700/30 border border-slate-600/50 rounded-xl p-4 text-xs text-slate-400 leading-6'>
<p>
این شبیه‌ساز رشد گیاه را بر اساس سرعت پایه، میزان نور خورشید و آب دریافتی
محاسبه می‌کند. هر برگ به صورت تدریجی روی ساقه ظاهر شده و با حرکت طبیعی
در باد نمایش داده می‌شود. <strong className='text-slate-300'>محصول‌دهی (g)</strong> پس از ۲۰٪ رشد شروع شده
و با تعداد برگ، نور و آب شتاب می‌گیرد. <strong className='text-slate-300'>سرعت محصول (g/s)</strong> نشان‌دهنده
نرخ لحظه‌ای تولید است. نمودار تغییرات همه شاخص‌ها را در طول زمان ثبت می‌کند.
</p>
</div>
</div>
</div>
</div>
) )
} }