Files
Eric FELIXINE e30ae8ed09 feat(smart-app): implement complete mobile app MVP
- App.tsx: full navigation (Auth stack + Main tabs with 5 screens)
- Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen
- HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors
- MapScreen: interactive map with layer toggles (6 layers)
- MarketplaceScreen: categories (6), products (5), search
- ChatScreen: AI chat with quick prompts (4), bot responses
- ProfileScreen: user info, stats, menu (9 items), logout
- AlertsScreen: alert list with severity, acknowledge
- SensorsScreen: sensor list with type filters (6 types), search
- ZonesScreen: zone cards with stats
- SettingsScreen: language picker (FR/EN/ES/DE), privacy, about
- Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n
- Hooks: useSensors, useAlerts, useNotifications, useLocation
- Components: Card, Button, LoadingSpinner, ErrorBoundary, Header
- Services: iotService, notificationService (with axios API client)
- Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN)
- Theme: colors.ts with full design system (Blue Ocean palette)
- Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
2026-06-01 18:00:35 -04:00

175 lines
9.7 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smart App City — 09 Météo (Blue v2)</title>
<link rel="stylesheet" href="shared-blue.css">
<style>
.weather-hero {
background: linear-gradient(160deg, #0D47A1 0%, #1565C0 40%, #0288D1 100%);
padding: 24px 20px 32px;
color: white;
text-align: center;
position: relative; overflow: hidden;
}
.weather-hero::before {
content: ''; position: absolute;
width: 200px; height: 200px; border-radius: 50%;
background: rgba(255,255,255,0.05);
top: -60px; right: -60px;
}
.weather-main-temp { font-size: 72px; font-weight: 200; line-height: 1; }
.weather-main-temp span { font-size: 32px; vertical-align: top; }
.weather-condition { font-size: 20px; margin: 8px 0 4px; }
.weather-location { font-size: 14px; opacity: 0.8; }
.weather-details-grid {
display: grid; grid-template-columns: repeat(3, 1fr);
gap: 12px; padding: 0 20px; margin-top: 20px;
}
.weather-detail-item {
background: rgba(255,255,255,0.12);
border-radius: 12px; padding: 12px;
text-align: center; backdrop-filter: blur(4px);
}
.weather-detail-value { font-size: 18px; font-weight: 700; }
.weather-detail-label { font-size: 10px; opacity: 0.7; margin-top: 2px; }
.forecast-section { padding: 16px; }
.forecast-title { font-size: var(--text-md); font-weight: 700; margin-bottom: 12px; }
.hourly-scroll {
display: flex; gap: 12px; overflow-x: auto;
padding-bottom: 12px; scrollbar-width: none;
}
.hourly-scroll::-webkit-scrollbar { display: none; }
.hourly-item {
flex-shrink: 0; width: 60px; text-align: center;
background: var(--neutral-50); border-radius: 12px; padding: 10px 6px;
}
.hourly-time { font-size: 11px; color: var(--neutral-500); margin-bottom: 4px; }
.hourly-icon { font-size: 24px; margin-bottom: 4px; }
.hourly-temp { font-size: 14px; font-weight: 600; }
.daily-forecast { padding: 0 16px 16px; }
.daily-item {
display: flex; align-items: center; justify-content: space-between;
padding: 12px 0; border-bottom: 1px solid var(--neutral-100);
}
.daily-day { font-size: 14px; font-weight: 500; width: 100px; }
.daily-icon { font-size: 24px; flex: 1; text-align: center; }
.daily-temps { font-size: 14px; }
.daily-temps-high { font-weight: 700; }
.daily-temps-low { color: var(--neutral-400); }
.weather-alert {
margin: 0 16px 12px;
background: rgba(245,124,0,0.08);
border: 1px solid rgba(245,124,0,0.2);
border-radius: 12px; padding: 12px 14px;
display: flex; gap: 10px; align-items: center;
}
.weather-alert-text { font-size: 13px; color: var(--alert-warning); font-weight: 500; }
.sensor-weather-grid {
display: grid; grid-template-columns: repeat(2, 1fr);
gap: 10px; padding: 0 16px 16px;
}
.sensor-w-card {
background: white; border-radius: 12px; padding: 14px;
box-shadow: 0 1px 3px rgba(0,0,0,0.06);
border: 1px solid var(--neutral-100);
}
.sensor-w-value { font-size: 24px; font-weight: 700; color: var(--primary-500); }
.sensor-w-label { font-size: 11px; color: var(--neutral-500); }
/* Fixed viewport for PDF/iframe embedding */
html, body { width: 390px !important; height: 844px !important; overflow: hidden !important; margin: 0 !important; padding: 0 !important; }
</style>
</head>
<body>
<div class="mobile-frame">
<div class="status-bar"><span>9:41</span></div>
<!-- Weather Hero -->
<div class="weather-hero">
<div class="weather-main-temp">28<span>°C</span></div>
<div class="weather-condition">⛅ Partiellement nuageux</div>
<div class="weather-location">📍 Fort-de-France, Martinique</div>
<div class="weather-details-grid">
<div class="weather-detail-item">
<div class="weather-detail-value">💧 65%</div>
<div class="weather-detail-label">Humidité</div>
</div>
<div class="weather-detail-item">
<div class="weather-detail-value">💨 12 km/h</div>
<div class="weather-detail-label">Vent</div>
</div>
<div class="weather-detail-item">
<div class="weather-detail-value">☀️ UV 8</div>
<div class="weather-detail-label">Index UV</div>
</div>
</div>
</div>
<div class="content-area" style="top:290px;background:var(--neutral-50);">
<!-- Alert -->
<div class="weather-alert">
<span style="font-size:20px;">🌧️</span>
<div class="weather-alert-text">Pluie prévue à 14h — 80% de probabilité</div>
</div>
<!-- Hourly -->
<div class="forecast-section">
<div class="forecast-title">Prévisions horaires</div>
<div class="hourly-scroll">
<div class="hourly-item"><div class="hourly-time">Maintenant</div><div class="hourly-icon"></div><div class="hourly-temp">28°</div></div>
<div class="hourly-item"><div class="hourly-time">10h</div><div class="hourly-icon">☀️</div><div class="hourly-temp">29°</div></div>
<div class="hourly-item"><div class="hourly-time">11h</div><div class="hourly-icon">☀️</div><div class="hourly-temp">30°</div></div>
<div class="hourly-item"><div class="hourly-time">12h</div><div class="hourly-icon"></div><div class="hourly-temp">31°</div></div>
<div class="hourly-item"><div class="hourly-time">13h</div><div class="hourly-icon">🌤️</div><div class="hourly-temp">30°</div></div>
<div class="hourly-item"><div class="hourly-time">14h</div><div class="hourly-icon">🌧️</div><div class="hourly-temp">27°</div></div>
<div class="hourly-item"><div class="hourly-time">15h</div><div class="hourly-icon">🌧️</div><div class="hourly-temp">26°</div></div>
<div class="hourly-item"><div class="hourly-time">16h</div><div class="hourly-icon"></div><div class="hourly-temp">26°</div></div>
<div class="hourly-item"><div class="hourly-time">17h</div><div class="hourly-icon">🌤️</div><div class="hourly-temp">25°</div></div>
<div class="hourly-item"><div class="hourly-time">18h</div><div class="hourly-icon">🌙</div><div class="hourly-temp">24°</div></div>
</div>
</div>
<!-- Daily -->
<div class="daily-forecast">
<div class="forecast-title">7 prochains jours</div>
<div class="daily-item"><div class="daily-day">Aujourd'hui</div><div class="daily-icon"></div><div class="daily-temps"><span class="daily-temps-high">31°</span> / 24°</div></div>
<div class="daily-item"><div class="daily-day">Jeudi</div><div class="daily-icon">🌧️</div><div class="daily-temps"><span class="daily-temps-high">28°</span> / 23°</div></div>
<div class="daily-item"><div class="daily-day">Vendredi</div><div class="daily-icon">🌧️</div><div class="daily-temps"><span class="daily-temps-high">27°</span> / 23°</div></div>
<div class="daily-item"><div class="daily-day">Samedi</div><div class="daily-icon"></div><div class="daily-temps"><span class="daily-temps-high">29°</span> / 24°</div></div>
<div class="daily-item"><div class="daily-day">Dimanche</div><div class="daily-icon">☀️</div><div class="daily-temps"><span class="daily-temps-high">30°</span> / 24°</div></div>
<div class="daily-item"><div class="daily-day">Lundi</div><div class="daily-icon">☀️</div><div class="daily-temps"><span class="daily-temps-high">31°</span> / 25°</div></div>
<div class="daily-item"><div class="daily-day">Mardi</div><div class="daily-icon"></div><div class="daily-temps"><span class="daily-temps-high">30°</span> / 24°</div></div>
</div>
<!-- IoT Sensors -->
<div class="forecast-section">
<div class="forecast-title">Capteurs météo en direct</div>
<div class="sensor-weather-grid">
<div class="sensor-w-card"><div class="sensor-w-value">28.2°</div><div class="sensor-w-label">Temp. ressentie</div></div>
<div class="sensor-w-card"><div class="sensor-w-value">1013</div><div class="sensor-w-label">Pression (hPa)</div></div>
<div class="sensor-w-card"><div class="sensor-w-value">2.1 mm</div><div class="sensor-w-label">Précipitations 24h</div></div>
<div class="sensor-w-card"><div class="sensor-w-value">8 km</div><div class="sensor-w-label">Visibilité</div></div>
</div>
</div>
<div style="height:16px;"></div>
</div>
<!-- Bottom Nav -->
<div class="bottom-nav">
<div class="bottom-nav-item active"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22" fill="none" stroke="currentColor" stroke-width="2"/></svg><span>Accueil</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg><span>Carte</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg><span>AI Chat</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><span>Marché</span></div>
<div class="bottom-nav-item"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg><span>Profil</span></div>
</div>
<div style="position:absolute;bottom:88px;left:0;right:0;text-align:center;font-size:10px;color:var(--neutral-400);">09 — Météo · Blue v2</div>
</div>
</body>
</html>