feat: [dashboard] 날씨 위젯에 강수확률 표시 추가

- 단기예보 POP (하루 최대값) + 중기예보 rnSt 병합
- 우산 아이콘 + 퍼센트 표시 (50% 이상 진한 파랑 강조)
- 강수확률 0%일 때는 표시하지 않음
This commit is contained in:
김보곤
2026-02-21 13:40:28 +09:00
parent 9a9922739d
commit c5f4c53a50
2 changed files with 23 additions and 8 deletions

View File

@@ -74,15 +74,17 @@ private function buildForecast(): array
$midTmn = $midTa["taMin{$i}"] ?? null;
$midTmx = $midTa["taMax{$i}"] ?? null;
$midWf = $midLand["wf{$i}Am"] ?? ($midLand["wf{$i}"] ?? '');
$midPop = max($midLand["rnSt{$i}Am"] ?? 0, $midLand["rnSt{$i}Pm"] ?? 0, $midLand["rnSt{$i}"] ?? 0);
if ($shortData) {
// 단기예보 우선, 기온 없으면 중기로 보충
// 단기예보 우선, 기온/강수확률 없으면 중기로 보충
$forecasts[] = [
'date' => $date,
'tmn' => $shortData['tmn'] ?? $midTmn,
'tmx' => $shortData['tmx'] ?? $midTmx,
'icon' => $shortData['icon'] ?? (! empty($midWf) ? $this->midWeatherToIcon($midWf) : null),
'weather_text' => $shortData['weather_text'] ?: $midWf,
'pop' => $shortData['pop'] ?? $midPop,
];
} else {
$forecasts[] = [
@@ -91,6 +93,7 @@ private function buildForecast(): array
'tmx' => $midTmx,
'icon' => ! empty($midWf) ? $this->midWeatherToIcon($midWf) : null,
'weather_text' => $midWf,
'pop' => $midPop,
];
}
}
@@ -157,7 +160,7 @@ private function fetchShortForecast(): array
$value = $item['fcstValue'];
if (! isset($grouped[$fcstDate])) {
$grouped[$fcstDate] = ['date' => $fcstDate, 'tmn' => null, 'tmx' => null, 'sky' => null, 'pty' => null];
$grouped[$fcstDate] = ['date' => $fcstDate, 'tmn' => null, 'tmx' => null, 'sky' => null, 'pty' => null, 'pop' => 0];
}
match ($category) {
@@ -165,6 +168,7 @@ private function fetchShortForecast(): array
'TMX' => $grouped[$fcstDate]['tmx'] = (int) $value,
'SKY' => $grouped[$fcstDate]['sky'] ??= (int) $value,
'PTY' => $grouped[$fcstDate]['pty'] ??= (int) $value,
'POP' => $grouped[$fcstDate]['pop'] = max($grouped[$fcstDate]['pop'], (int) $value),
default => null,
};
}
@@ -178,6 +182,7 @@ private function fetchShortForecast(): array
'tmx' => $data['tmx'],
'icon' => $icon,
'weather_text' => $this->iconToText($icon),
'pop' => $data['pop'],
];
}

View File

@@ -30,6 +30,7 @@
$weatherText = $fc['weather_text'] ?? '';
$tmn = $fc['tmn'];
$tmx = $fc['tmx'];
$pop = $fc['pop'] ?? 0;
$hasData = ($tmn !== null || $tmx !== null || $icon !== null);
// 바 위치 계산 (%)
@@ -57,7 +58,7 @@
@if($hasData)
{{-- 날씨 아이콘 --}}
<div class="flex justify-center mb-1.5">
<div class="flex justify-center mb-1">
@if($icon)
@include('dashboard.partials.weather-icon', ['icon' => $icon])
@else
@@ -65,10 +66,19 @@
@endif
</div>
{{-- 날씨 텍스트 --}}
<div class="text-[11px] mb-3 truncate {{ $isPrecip ? 'text-blue-600 font-semibold' : 'text-gray-400' }}">
{{ $weatherText ?: '-' }}
</div>
{{-- 강수확률 --}}
@if($pop > 0)
<div class="flex items-center justify-center gap-0.5 mb-1.5">
{{-- 우산 아이콘 --}}
<svg style="width: 12px; height: 12px;" viewBox="0 0 24 24" fill="none" stroke="{{ $pop >= 50 ? '#2563eb' : '#93c5fd' }}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 2v1M4.93 4.93l.7.7M2 12h1M12 22c-1.66 0-3-1.34-3-3v-2"/>
<path d="M12 3a9 9 0 0 1 9 9H3a9 9 0 0 1 9-9z"/>
</svg>
<span class="text-[11px] font-semibold {{ $pop >= 50 ? 'text-blue-600' : 'text-blue-400' }}">{{ $pop }}%</span>
</div>
@else
<div class="mb-1.5" style="height: 18px;"></div>
@endif
{{-- 기온 그래프 --}}
@if($tmx !== null && $tmn !== null)
@@ -100,7 +110,7 @@
</div>
@else
{{-- 데이터 없는 --}}
<div class="flex flex-col items-center justify-center" style="min-height: 110px;">
<div class="flex flex-col items-center justify-center" style="min-height: 120px;">
<svg class="w-6 h-6 text-gray-300 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 12H4M12 4v16"/>
</svg>