- 단기예보 POP (하루 최대값) + 중기예보 rnSt 병합 - 우산 아이콘 + 퍼센트 표시 (50% 이상 진한 파랑 강조) - 강수확률 0%일 때는 표시하지 않음
124 lines
6.3 KiB
PHP
124 lines
6.3 KiB
PHP
{{-- 주간 날씨 위젯 (HTMX 파티셜) --}}
|
|
@if(empty($forecasts))
|
|
<div class="flex items-center justify-center py-8 text-sm text-gray-400">
|
|
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z"/>
|
|
</svg>
|
|
날씨 정보를 불러올 수 없습니다
|
|
</div>
|
|
@else
|
|
@php
|
|
$today = now()->format('Ymd');
|
|
$dayNames = ['일', '월', '화', '수', '목', '금', '토'];
|
|
|
|
// 전체 기온 범위 계산 (바 그래프용)
|
|
$allTmn = collect($forecasts)->pluck('tmn')->filter(fn($v) => $v !== null);
|
|
$allTmx = collect($forecasts)->pluck('tmx')->filter(fn($v) => $v !== null);
|
|
$globalMin = $allTmn->isNotEmpty() ? $allTmn->min() : 0;
|
|
$globalMax = $allTmx->isNotEmpty() ? $allTmx->max() : 20;
|
|
$range = max($globalMax - $globalMin, 1);
|
|
@endphp
|
|
<div class="flex gap-2 overflow-x-auto pb-1" style="flex-wrap: nowrap;">
|
|
@foreach($forecasts as $fc)
|
|
@php
|
|
$dt = \Carbon\Carbon::createFromFormat('Ymd', $fc['date']);
|
|
$isToday = ($fc['date'] === $today);
|
|
$dayName = $dayNames[$dt->dayOfWeek];
|
|
$isSunday = $dt->dayOfWeek === 0;
|
|
$isSaturday = $dt->dayOfWeek === 6;
|
|
$icon = $fc['icon'] ?? null;
|
|
$weatherText = $fc['weather_text'] ?? '';
|
|
$tmn = $fc['tmn'];
|
|
$tmx = $fc['tmx'];
|
|
$pop = $fc['pop'] ?? 0;
|
|
$hasData = ($tmn !== null || $tmx !== null || $icon !== null);
|
|
|
|
// 바 위치 계산 (%)
|
|
$barLeft = $tmn !== null ? round(($tmn - $globalMin) / $range * 100) : 0;
|
|
$barRight = $tmx !== null ? round(($tmx - $globalMin) / $range * 100) : 100;
|
|
$barWidth = max($barRight - $barLeft, 8);
|
|
|
|
// 강수 여부
|
|
$isPrecip = in_array($icon, ['rain', 'snow', 'sleet']);
|
|
@endphp
|
|
<div class="text-center rounded-xl border transition-all
|
|
{{ $isToday ? 'bg-blue-50 border-blue-200 shadow-md ring-1 ring-blue-100' : ($hasData ? 'bg-white border-gray-200 hover:shadow-sm' : 'bg-gray-50 border-gray-100') }}"
|
|
style="flex: 1 1 0; min-width: 100px; padding: 14px 10px;">
|
|
|
|
{{-- 요일 --}}
|
|
<div class="text-xs font-bold mb-0.5 tracking-wide
|
|
{{ $isToday ? 'text-blue-600' : ($isSunday ? 'text-red-500' : ($isSaturday ? 'text-blue-500' : 'text-gray-700')) }}">
|
|
{{ $isToday ? '오늘' : $dayName }}
|
|
</div>
|
|
|
|
{{-- 날짜 --}}
|
|
<div class="text-[11px] {{ $isToday ? 'text-blue-400' : 'text-gray-400' }} mb-3">
|
|
{{ $dt->format('m.d') }}
|
|
</div>
|
|
|
|
@if($hasData)
|
|
{{-- 날씨 아이콘 --}}
|
|
<div class="flex justify-center mb-1">
|
|
@if($icon)
|
|
@include('dashboard.partials.weather-icon', ['icon' => $icon])
|
|
@else
|
|
<div style="width: 40px; height: 40px;"></div>
|
|
@endif
|
|
</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)
|
|
<div class="relative mx-auto mb-2" style="height: 6px; border-radius: 3px; background: #f3f4f6;">
|
|
<div style="
|
|
position: absolute;
|
|
left: {{ $barLeft }}%;
|
|
width: {{ $barWidth }}%;
|
|
height: 100%;
|
|
border-radius: 3px;
|
|
background: linear-gradient(90deg, #60a5fa, #f87171);
|
|
"></div>
|
|
</div>
|
|
@endif
|
|
|
|
{{-- 최고/최저 기온 --}}
|
|
<div class="flex items-center justify-center gap-1.5">
|
|
@if($tmx !== null)
|
|
<span class="text-sm font-bold text-red-500">{{ $tmx }}°</span>
|
|
@else
|
|
<span class="text-sm text-gray-300">-</span>
|
|
@endif
|
|
<span class="text-gray-300">/</span>
|
|
@if($tmn !== null)
|
|
<span class="text-sm font-medium text-blue-500">{{ $tmn }}°</span>
|
|
@else
|
|
<span class="text-sm text-gray-300">-</span>
|
|
@endif
|
|
</div>
|
|
@else
|
|
{{-- 데이터 없는 날 --}}
|
|
<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>
|
|
<span class="text-[11px] text-gray-300">준비 중</span>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@endif
|