feat: add weather widget to user portal below navbar

This commit is contained in:
2026-06-28 23:36:29 -05:00
parent 291df16f1f
commit 59698686d5
2 changed files with 47 additions and 1 deletions
+11
View File
@@ -42,6 +42,16 @@ export async function GET() {
[userId]
);
// Get weather
let weather = undefined;
try {
const weatherRes = await fetch('http://localhost:3000/api/weather');
if (weatherRes.ok) {
const weatherData = await weatherRes.json();
weather = weatherData.data;
}
} catch { /* ignore */ }
return NextResponse.json({
reservations,
coupons,
@@ -49,6 +59,7 @@ export async function GET() {
benefits: benefits.map((b: { text: string }) => b.text),
wifiPassword,
trips,
weather,
});
} catch (error) {
if ((error as Error).message === 'Unauthorized') {
+36 -1
View File
@@ -20,10 +20,16 @@ interface Message {
created_at: string;
}
interface Weather {
current: { celsius: number; fahrenheit: number; summary: string; windspeed: number; weathercode: number };
today: { maxC: number; minC: number; maxF: number; minF: number; summary: string; weathercode: number };
}
interface PortalData {
trips: Trip[];
wifiPassword: string;
messages: Message[];
weather?: Weather;
}
const gold = '#E8A849';
@@ -123,10 +129,39 @@ export default function UserPage() {
return (
<main style={{ padding: '2rem', maxWidth: '64rem', margin: '0 auto' }}>
<h1 style={{ fontSize: 'clamp(28px, 4vw, 42px)', fontWeight: 400, fontStyle: 'italic', color: navy, margin: '0 0 2rem' }}>
<h1 style={{ fontSize: 'clamp(28px, 4vw, 42px)', fontWeight: 400, fontStyle: 'italic', color: navy, margin: '0 0 1.5rem' }}>
Your Portal
</h1>
{/* Weather Widget - Always visible below navbar */}
{data.weather && (
<div style={{ background: 'linear-gradient(135deg, #010D1E 0%, #1a2a3a 100%)', borderRadius: '16px', padding: '1.25rem 1.5rem', marginBottom: '2rem', display: 'flex', alignItems: 'center', gap: '2rem', flexWrap: 'wrap', boxShadow: '0 4px 16px rgba(1,13,30,0.2)' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
<div style={{ fontSize: '48px' }}>
{data.weather.current.weathercode <= 1 ? '☀️' : data.weather.current.weathercode === 2 ? '⛅' : data.weather.current.weathercode === 3 ? '☁️' : data.weather.current.weathercode >= 51 && data.weather.current.weathercode <= 55 ? '🌧️' : data.weather.current.weathercode >= 61 ? '🌧️' : '☀️'}
</div>
<div>
<div style={{ fontSize: '28px', fontWeight: 600, color: '#fff' }}>{data.weather.current.celsius}°C</div>
<div style={{ fontSize: '13px', color: 'rgba(255,255,255,0.7)' }}>{data.weather.current.summary}</div>
</div>
</div>
<div style={{ display: 'flex', gap: '2rem', flex: 1, justifyContent: 'flex-end', flexWrap: 'wrap' }}>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: '11px', color: 'rgba(255,255,255,0.6)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>High</div>
<div style={{ fontSize: '20px', fontWeight: 500, color: '#E8A849' }}>{data.weather.today.maxC}°</div>
</div>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: '11px', color: 'rgba(255,255,255,0.6)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>Low</div>
<div style={{ fontSize: '20px', fontWeight: 500, color: '#88b4e8' }}>{data.weather.today.minC}°</div>
</div>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: '11px', color: 'rgba(255,255,255,0.6)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>Wind</div>
<div style={{ fontSize: '16px', color: '#fff' }}>{data.weather.current.windspeed} km/h</div>
</div>
</div>
</div>
)}
{/* Welcome Message - Show on reservation day */}
{activeTrip && (
<Section title="Welcome!" highlight>