Files

706 lines
47 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>Smart City Martinique</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
:root {
--primary: #1565C0; --primary-dark: #0D47A1; --accent: #00ACC1;
--bg: #0D1B2A; --bg-card: #1E3350; --bg-input: #1B2838;
--text: #E8EAF6; --text-secondary: #9FA8DA; --text-muted: #5C6BC0;
--danger: #D32F2F; --success: #2E7D32; --warning: #F57C00;
--radius: 16px; --radius-sm: 8px; --radius-full: 9999px;
}
html, body { height: 100%; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg); color: var(--text); min-height: 100%;
display: flex; flex-direction: column;
}
/* ── Top Nav ── */
.top-nav {
background: var(--bg-card);
border-bottom: 1px solid rgba(255,255,255,0.05);
display: flex;
justify-content: space-around;
align-items: center;
padding: 6px 0;
flex-shrink: 0;
}
.nav-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 1px;
text-decoration: none;
color: var(--text-muted);
font-size: 10px;
padding: 6px 10px;
border-radius: var(--radius-sm);
transition: color 0.2s;
position: relative;
}
.nav-item.active { color: var(--accent); }
.nav-item-icon { font-size: 20px; }
.nav-badge {
position: absolute;
top: 2px;
right: 4px;
background: var(--danger);
color: white;
border-radius: 8px;
padding: 0 4px;
font-size: 9px;
font-weight: 700;
min-width: 14px;
text-align: center;
}
/* ── Header ── */
.header {
background: linear-gradient(135deg, var(--primary), var(--accent));
padding: 30px 20px 50px;
text-align: center;
flex-shrink: 0;
}
.logo { width: 70px; height: 70px; background: rgba(255,255,255,0.15); border-radius: 18px; margin: 0 auto 12px; display: flex; align-items: center; justify-content: center; font-size: 36px; }
.header h1 { font-size: 24px; font-weight: 700; color: white; margin-bottom: 2px; }
.header p { font-size: 13px; color: rgba(255,255,255,0.8); }
/* ── Form ── */
.form-container { flex: 1; padding: 20px; max-width: 420px; margin: 0 auto; width: 100%; }
.form-title { font-size: 22px; font-weight: 700; margin-bottom: 24px; }
.input-group { margin-bottom: 16px; }
.input-group label { display: block; font-size: 13px; font-weight: 600; color: var(--text-secondary); margin-bottom: 6px; }
.input-wrapper { display: flex; align-items: center; background: var(--bg-input); border-radius: var(--radius-sm); border: 1px solid transparent; transition: border 0.2s; }
.input-wrapper:focus-within { border-color: var(--accent); }
.input-wrapper .icon { padding: 0 12px; font-size: 16px; }
.input-wrapper input { flex: 1; background: none; border: none; outline: none; color: var(--text); font-size: 15px; padding: 14px 12px 14px 0; }
.input-wrapper input::placeholder { color: var(--text-muted); }
.toggle-pw { padding: 0 12px; cursor: pointer; font-size: 16px; }
/* ── Buttons ── */
.btn { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; padding: 14px; border: none; border-radius: var(--radius-sm); font-size: 15px; font-weight: 700; cursor: pointer; transition: opacity 0.2s, transform 0.1s; }
.btn:active { transform: scale(0.98); opacity: 0.9; }
.btn-primary { background: var(--primary); color: white; }
.btn-secondary { background: var(--bg-card); color: var(--text); border: 1px solid var(--primary-dark); }
.btn-google { background: #fff; color: #333; }
.btn-apple { background: #000; color: #fff; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn .btn-icon { font-size: 18px; }
/* ── Links ── */
.link { color: var(--accent); text-decoration: none; font-size: 14px; font-weight: 600; }
.link:hover { text-decoration: underline; }
.text-center { text-align: center; }
.mt-12 { margin-top: 12px; }
.mt-24 { margin-top: 24px; }
.mb-8 { margin-bottom: 8px; }
/* ── Divider ── */
.divider { display: flex; align-items: center; gap: 16px; margin: 24px 0; }
.divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: var(--bg-card); }
.divider span { font-size: 12px; color: var(--text-muted); }
/* ── Error/Success ── */
.alert { padding: 12px; border-radius: var(--radius-sm); font-size: 13px; margin-bottom: 16px; display: none; }
.alert.show { display: block; }
.alert-error { background: rgba(211,47,47,0.15); color: #EF5350; border: 1px solid rgba(211,47,47,0.3); }
.alert-success { background: rgba(46,125,50,0.15); color: #66BB6A; border: 1px solid rgba(46,125,50,0.3); }
/* ── Checkbox ── */
.checkbox { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-secondary); cursor: pointer; }
.checkbox input { width: 18px; height: 18px; accent-color: var(--accent); }
/* ── Loading ── */
.spinner { width: 20px; height: 20px; border: 2px solid rgba(255,255,255,0.3); border-top-color: white; border-radius: 50%; animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
/* ── Transitions ── */
.screen { display: none; min-height: 100vh; flex-direction: column; }
.screen.active { display: flex; }
/* ── Home Dashboard ── */
.dashboard-header {
background: linear-gradient(135deg, var(--primary), var(--accent));
padding: 20px 16px 50px;
flex-shrink: 0;
}
.dashboard-header-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.greeting { font-size: 13px; color: rgba(255,255,255,0.85); }
.user-name { font-size: 20px; font-weight: 700; color: white; }
.notification-btn { position: relative; background: none; border: none; font-size: 24px; cursor: pointer; }
.notification-badge { position: absolute; top: -4px; right: -4px; background: var(--danger); color: white; border-radius: 10px; padding: 1px 5px; font-size: 10px; font-weight: 700; }
.search-bar { display: flex; align-items: center; background: rgba(255,255,255,0.2); border-radius: var(--radius-full); padding: 10px 16px; gap: 8px; }
.search-bar input { flex: 1; background: none; border: none; outline: none; color: white; font-size: 14px; }
.search-bar input::placeholder { color: rgba(255,255,255,0.5); }
/* ── Metrics Row ── */
.metrics-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; padding: 0 16px; margin-top: -25px; }
.metric-card { background: var(--bg-card); border-radius: var(--radius); padding: 12px 8px; text-align: center; border: 1px solid rgba(255,255,255,0.05); }
.metric-value { font-size: 20px; font-weight: 700; }
.metric-unit { font-size: 10px; color: var(--text-muted); }
.metric-label { font-size: 9px; color: var(--text-muted); margin-top: 2px; }
/* ── Section ── */
.section { padding: 16px; }
.section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
.section-title { font-size: 16px; font-weight: 700; }
.see-all { font-size: 13px; color: var(--accent); text-decoration: none; }
/* ── Cards ── */
.card { background: var(--bg-card); border-radius: var(--radius); padding: 14px; margin-bottom: 10px; border: 1px solid rgba(255,255,255,0.05); }
.card-title { font-size: 14px; font-weight: 700; margin-bottom: 4px; }
.card-subtitle { font-size: 12px; color: var(--text-secondary); }
.card-row { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; }
/* ── Quick Actions ── */
.quick-actions { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.quick-action { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 12px 8px; background: var(--bg-card); border-radius: var(--radius); text-decoration: none; color: var(--text); }
.quick-action-icon { width: 48px; height: 48px; border-radius: 14px; display: flex; align-items: center; justify-content: center; font-size: 22px; }
.quick-action-label { font-size: 10px; color: var(--text-secondary); text-align: center; }
/* ── Scrollable content ── */
.scrollable { flex: 1; overflow-y: auto; }
/* ── Badge ── */
.badge { display: inline-block; padding: 2px 8px; border-radius: var(--radius-full); font-size: 10px; font-weight: 600; cursor: pointer; }
.badge-green { background: rgba(46,125,50,0.2); color: #66BB6A; }
.badge-orange { background: rgba(245,124,0,0.2); color: #FFA726; }
.badge-red { background: rgba(211,47,47,0.2); color: #EF5350; }
.badge-blue { background: rgba(21,101,192,0.2); color: #64B5F6; }
/* ── Chat ── */
.chat-message { padding: 10px 14px; border-radius: var(--radius); margin-bottom: 8px; font-size: 14px; line-height: 1.5; max-width: 80%; }
.chat-message-bot { background: var(--bg-card); align-self: flex-start; }
.chat-message-user { background: var(--primary); align-self: flex-end; margin-left: auto; }
.chat-input { display: flex; gap: 8px; padding: 12px 16px; background: var(--bg-card); border-top: 1px solid rgba(255,255,255,0.05); flex-shrink: 0; }
.chat-input input { flex: 1; background: var(--bg); border: none; border-radius: var(--radius-full); padding: 10px 16px; color: var(--text); font-size: 14px; outline: none; }
.chat-input button { background: var(--primary); border: none; border-radius: 50%; width: 40px; height: 40px; color: white; font-size: 18px; cursor: pointer; }
/* ── Map ── */
.map-placeholder { width: 100%; height: 200px; background: #E8F5E9; border-radius: var(--radius); display: flex; flex-direction: column; align-items: center; justify-content: center; color: #4CAF50; margin-bottom: 12px; }
</style>
</head>
<body>
<!-- ═══════════════════════════════════════════════════════════════
SCREEN: LOGIN
═══════════════════════════════════════════════════════════════ -->
<div id="screen-login" class="screen active">
<div class="header">
<div class="logo">🏙️</div>
<h1>Smart City Martinique</h1>
<p>Martinique</p>
</div>
<div class="form-container">
<div class="alert alert-error" id="login-error"></div>
<div class="form-title">Connexion</div>
<div class="input-group">
<label>Email</label>
<div class="input-wrapper">
<span class="icon">📧</span>
<input type="email" id="login-email" placeholder="votre@email.com" autocomplete="email">
</div>
</div>
<div class="input-group">
<label>Mot de passe</label>
<div class="input-wrapper">
<span class="icon">🔒</span>
<input type="password" id="login-password" placeholder="••••••••" autocomplete="current-password">
<button type="button" class="toggle-pw" onclick="togglePw('login-password')" style="background:none;border:none;cursor:pointer;font-size:16px;padding:0 12px">👁️</button>
</div>
</div>
<div class="text-center mt-12">
<a href="#" class="link" onclick="forgotPassword()">Mot de passe oublié ?</a>
</div>
<button class="btn btn-primary mt-24" id="btn-login" onclick="handleLogin()">
<span>Se connecter</span>
</button>
<div class="divider"><span>ou</span></div>
<div style="display:flex;gap:12px">
<button class="btn btn-google" style="flex:1" onclick="socialLogin('google')"><span class="btn-icon">🔵</span> Google</button>
<button class="btn btn-apple" style="flex:1" onclick="socialLogin('apple')"><span class="btn-icon">🍎</span> Apple</button>
</div>
<div class="text-center mt-24">
<span style="font-size:14px;color:var(--text-secondary)">Pas encore de compte ? </span>
<a href="#" class="link" onclick="showScreen('register')">S'inscrire</a>
</div>
</div>
</div>
<!-- ═══════════════════════════════════════════════════════════════
SCREEN: REGISTER
═══════════════════════════════════════════════════════════════ -->
<div id="screen-register" class="screen">
<div class="header" style="padding-bottom:30px">
<div style="text-align:left;margin-bottom:16px"><a href="#" class="link" style="color:rgba(255,255,255,0.8)" onclick="showScreen('login')">← Retour</a></div>
<h1>Créer un compte</h1>
<p>Rejoignez Smart City Martinique</p>
</div>
<div class="form-container">
<div class="alert alert-error" id="register-error"></div>
<div class="alert alert-success" id="register-success"></div>
<div style="display:flex;gap:12px">
<div class="input-group" style="flex:1">
<label>Prénom</label>
<div class="input-wrapper"><input type="text" id="reg-firstname" placeholder="Jean"></div>
</div>
<div class="input-group" style="flex:1">
<label>Nom</label>
<div class="input-wrapper"><input type="text" id="reg-lastname" placeholder="Dupont"></div>
</div>
</div>
<div class="input-group">
<label>Email</label>
<div class="input-wrapper">
<span class="icon">📧</span>
<input type="email" id="reg-email" placeholder="votre@email.com">
</div>
</div>
<div class="input-group">
<label>Mot de passe</label>
<div class="input-wrapper">
<span class="icon">🔒</span>
<input type="password" id="reg-password" placeholder="Min. 8 caractères">
<button type="button" class="toggle-pw" onclick="togglePw('reg-password')" style="background:none;border:none;cursor:pointer;font-size:16px;padding:0 12px">👁️</button>
</div>
</div>
<div class="input-group">
<label>Confirmer</label>
<div class="input-wrapper">
<span class="icon">🔒</span>
<input type="password" id="reg-confirm" placeholder="Retapez le mot de passe">
</div>
</div>
<div class="checkbox mb-8">
<input type="checkbox" id="reg-terms">
<span>J'accepte les <a href="#" class="link">conditions d'utilisation</a></span>
</div>
<button class="btn btn-primary" id="btn-register" onclick="handleRegister()">
<span>S'inscrire</span>
</button>
<div class="text-center mt-24">
<span style="font-size:14px;color:var(--text-secondary)">Déjà un compte ? </span>
<a href="#" class="link" onclick="showScreen('login')">Se connecter</a>
</div>
</div>
</div>
<!-- ═══════════════════════════════════════════════════════════════
SCREEN: HOME DASHBOARD
═══════════════════════════════════════════════════════════════ -->
<div id="screen-home" class="screen">
<div class="dashboard-header">
<div class="dashboard-header-top">
<div>
<div class="greeting">Bonjour 👋</div>
<div class="user-name" id="home-user-name">Utilisateur</div>
</div>
<button class="notification-btn" onclick="showScreen('notifications')">🔔<span class="notification-badge">3</span></button>
</div>
<div class="search-bar">
<span>🔍</span>
<input type="text" placeholder="Rechercher un service, un lieu...">
</div>
</div>
<div class="scrollable" style="padding-top:60px">
<div class="metrics-row">
<div class="metric-card"><div class="metric-value" style="color:var(--accent)">28°</div><div class="metric-unit">C</div><div class="metric-label">Temp.</div></div>
<div class="metric-card"><div class="metric-value" style="color:#64B5F6">72%</div><div class="metric-unit"></div><div class="metric-label">Humidité</div></div>
<div class="metric-card"><div class="metric-value" style="color:#FFA726">42</div><div class="metric-unit">AQI</div><div class="metric-label">Air</div></div>
<div class="metric-card"><div class="metric-value" style="color:#EF5350">55</div><div class="metric-unit">dB</div><div class="metric-label">Bruit</div></div>
</div>
<div class="section">
<div class="section-header"><div class="section-title">Actions rapides</div></div>
<div class="quick-actions">
<a href="#" class="quick-action" onclick="showScreen('signalements')"><div class="quick-action-icon" style="background:rgba(211,47,47,0.15)">🚨</div><div class="quick-action-label">Signaler</div></a>
<a href="#" class="quick-action" onclick="showScreen('map')"><div class="quick-action-icon" style="background:rgba(21,101,192,0.15)">🚌</div><div class="quick-action-label">Transport</div></a>
<a href="#" class="quick-action" onclick="showScreen('marketplace')"><div class="quick-action-icon" style="background:rgba(46,125,50,0.15)"></div><div class="quick-action-label">Énergie</div></a>
<a href="#" class="quick-action" onclick="showScreen('sante')"><div class="quick-action-icon" style="background:rgba(245,124,0,0.15)">🏥</div><div class="quick-action-label">Santé</div></a>
</div>
</div>
<div class="section">
<div class="section-header"><div class="section-title">Météo</div><a href="#" class="see-all" onclick="showScreen('meteo')">Voir tout →</a></div>
<div class="card" style="background:linear-gradient(135deg,#1565C0,#0288D1);color:white">
<div style="display:flex;justify-content:space-between;align-items:center">
<div>
<div style="font-size:36px;font-weight:700">28°C</div>
<div style="font-size:13px;opacity:0.8">Fort-de-France</div>
<div style="font-size:12px;opacity:0.7;margin-top:4px">Ensoleillé • Humidité 72%</div>
</div>
<div style="font-size:48px">☀️</div>
</div>
</div>
</div>
<div class="section">
<div class="section-header"><div class="section-title">Capteurs en direct</div><a href="#" class="see-all" onclick="showScreen('sensors')">Voir tout →</a></div>
<div id="sensors-list"></div>
</div>
<div class="section">
<div class="section-header"><div class="section-title">Alertes</div></div>
<div class="card">
<div style="display:flex;gap:10px;align-items:flex-start">
<span style="font-size:20px">⚠️</span>
<div>
<div class="card-title">Qualité air — Schoelcher</div>
<div class="card-subtitle">AQI élevé détecté. Évitez les efforts prolongés.</div>
</div>
</div>
</div>
</div>
</div>
<nav class="top-nav">
<a href="#" class="nav-item active" onclick="showScreen('home')"><span class="nav-item-icon">🏠</span>Accueil</a>
<a href="#" class="nav-item" onclick="showScreen('map')"><span class="nav-item-icon">🗺️</span>Carte</a>
<a href="#" class="nav-item" onclick="showScreen('marketplace')"><span class="nav-item-icon">🛒</span>Market</a>
<a href="#" class="nav-item" onclick="showScreen('chat')"><span class="nav-item-icon">🤖</span>IA Chat</a>
<a href="#" class="nav-item" onclick="showScreen('profile')"><span class="nav-item-icon">👤</span>Profil</a>
</nav>
</div>
<!-- ═══════════════════════════════════════════════════════════════
SCREEN: MAP
═══════════════════════════════════════════════════════════════ -->
<div id="screen-map" class="screen">
<div class="dashboard-header" style="padding-bottom:16px">
<div class="section-header"><div class="section-title">Carte Interactive</div><span style="font-size:13px;color:rgba(255,255,255,0.7)">Martinique</span></div>
</div>
<div class="scrollable" style="padding-top:60px">
<div class="map-placeholder">
<div style="font-size:48px;margin-bottom:8px">🗺️</div>
<div style="font-size:14px;font-weight:600">Carte OpenStreetMap</div>
<div style="font-size:12px;color:#81C784">14.6°N, 61.0°W</div>
</div>
<div class="section">
<div class="section-header"><div class="section-title">Couches</div></div>
<div style="display:flex;gap:8px;flex-wrap:wrap">
<span class="badge badge-blue" onclick="toggleLayer(this)">📡 Capteurs</span>
<span class="badge badge-green" onclick="toggleLayer(this)">🌬️ Qualité Air</span>
<span class="badge badge-orange" onclick="toggleLayer(this)">🔊 Bruit</span>
<span class="badge" onclick="toggleLayer(this)">🚗 Trafic</span>
<span class="badge badge-blue" onclick="toggleLayer(this)">🌤️ Météo</span>
<span class="badge badge-red" onclick="toggleLayer(this)">🎉 Événements</span>
</div>
</div>
<div class="section">
<div class="section-header"><div class="section-title">Capteurs à proximité</div></div>
<div id="nearby-sensors"></div>
</div>
</div>
<nav class="top-nav">
<a href="#" class="nav-item" onclick="showScreen('home')"><span class="nav-item-icon">🏠</span>Accueil</a>
<a href="#" class="nav-item active" onclick="showScreen('map')"><span class="nav-item-icon">🗺️</span>Carte</a>
<a href="#" class="nav-item" onclick="showScreen('marketplace')"><span class="nav-item-icon">🛒</span>Market</a>
<a href="#" class="nav-item" onclick="showScreen('chat')"><span class="nav-item-icon">🤖</span>IA Chat</a>
<a href="#" class="nav-item" onclick="showScreen('profile')"><span class="nav-item-icon">👤</span>Profil</a>
</nav>
</div>
<!-- ═══════════════════════════════════════════════════════════════
SCREEN: MARKETPLACE
═══════════════════════════════════════════════════════════════ -->
<div id="screen-marketplace" class="screen">
<div class="dashboard-header" style="padding-bottom:16px">
<div class="section-header"><div class="section-title">Marketplace</div><span style="font-size:13px;color:rgba(255,255,255,0.7)">Services & Produits</span></div>
<div class="search-bar" style="margin-top:12px"><span>🔍</span><input type="text" placeholder="Rechercher un service..."></div>
</div>
<div class="scrollable" style="padding-top:60px">
<div class="section">
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px">
<span class="badge badge-blue" onclick="filterCategory(this)">Tous</span>
<span class="badge" onclick="filterCategory(this)">🍎 Alimentation</span>
<span class="badge" onclick="filterCategory(this)">🚌 Transport</span>
<span class="badge" onclick="filterCategory(this)">⚡ Énergie</span>
<span class="badge" onclick="filterCategory(this)">🏥 Santé</span>
</div>
<div id="marketplace-list"></div>
</div>
</div>
<nav class="top-nav">
<a href="#" class="nav-item" onclick="showScreen('home')"><span class="nav-item-icon">🏠</span>Accueil</a>
<a href="#" class="nav-item" onclick="showScreen('map')"><span class="nav-item-icon">🗺️</span>Carte</a>
<a href="#" class="nav-item active" onclick="showScreen('marketplace')"><span class="nav-item-icon">🛒</span>Market</a>
<a href="#" class="nav-item" onclick="showScreen('chat')"><span class="nav-item-icon">🤖</span>IA Chat</a>
<a href="#" class="nav-item" onclick="showScreen('profile')"><span class="nav-item-icon">👤</span>Profil</a>
</nav>
</div>
<!-- ═══════════════════════════════════════════════════════════════
SCREEN: AI CHAT
═══════════════════════════════════════════════════════════════ -->
<div id="screen-chat" class="screen">
<div class="dashboard-header" style="padding-bottom:16px;flex-shrink:0">
<div style="display:flex;align-items:center;gap:12px">
<div style="width:44px;height:44px;border-radius:14px;background:rgba(255,255,255,0.15);display:flex;align-items:center;justify-content:center;font-size:24px">🤖</div>
<div><div style="font-size:16px;font-weight:700;color:white">Smart City IA</div><div style="font-size:12px;color:rgba(255,255,255,0.7)">En ligne</div></div>
</div>
</div>
<div class="scrollable" style="padding:16px;display:flex;flex-direction:column" id="chat-messages">
<div class="chat-message chat-message-bot">Bonjour ! Je suis Smart City IA 🤖<br><br>Je peux vous aider avec :<br>• 🌤️ Météo en temps réel<br>• 🚌 Transports<br>• ⚡ Énergie<br>• 🚨 Alertes<br><br>Comment puis-je vous aider ?</div>
</div>
<div style="padding:8px 16px;display:flex;gap:8px;flex-wrap:wrap;background:var(--bg-card);border-top:1px solid rgba(255,255,255,0.05)">
<span class="badge badge-blue" onclick="quickPrompt('Météo aujourd\\'hui')">🌤️ Météo</span>
<span class="badge badge-green" onclick="quickPrompt('Prochain bus')">🚌 Bus</span>
<span class="badge badge-orange" onclick="quickPrompt('Consommation énergie')">⚡ Énergie</span>
<span class="badge badge-red" onclick="quickPrompt('Alertes en cours')">🚨 Alertes</span>
</div>
<div class="chat-input">
<input type="text" id="chat-input" placeholder="Posez votre question..." onkeypress="if(event.key==='Enter')sendChat()">
<button onclick="sendChat()"></button>
</div>
</div>
<!-- ═══════════════════════════════════════════════════════════════
SCREEN: PROFILE
═══════════════════════════════════════════════════════════════ -->
<div id="screen-profile" class="screen">
<div class="scrollable" style="padding-top:60px">
<div class="dashboard-header" style="text-align:center;padding-bottom:24px">
<div style="width:70px;height:70px;border-radius:18px;background:rgba(255,255,255,0.15);margin:0 auto 10px;display:flex;align-items:center;justify-content:center;font-size:36px">👤</div>
<div style="font-size:18px;font-weight:700;color:white" id="profile-name">Utilisateur</div>
<div style="font-size:12px;color:rgba(255,255,255,0.7)" id="profile-email">-</div>
<div style="display:flex;gap:6px;justify-content:center;margin-top:10px">
<span class="badge badge-blue">🏙️ Citoyen</span>
<span class="badge badge-green">✅ Vérifié</span>
</div>
</div>
<div class="section">
<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:16px">
<div class="card" style="text-align:center"><div style="font-size:20px;font-weight:700;color:var(--primary)">12</div><div style="font-size:10px;color:var(--text-muted)">Signalements</div></div>
<div class="card" style="text-align:center"><div style="font-size:20px;font-weight:700;color:var(--primary)">45</div><div style="font-size:10px;color:var(--text-muted)">Points</div></div>
<div class="card" style="text-align:center"><div style="font-size:20px;font-weight:700;color:var(--primary)">5</div><div style="font-size:10px;color:var(--text-muted)">Abonnements</div></div>
</div>
<div id="profile-menu"></div>
</div>
</div>
<nav class="top-nav">
<a href="#" class="nav-item" onclick="showScreen('home')"><span class="nav-item-icon">🏠</span>Accueil</a>
<a href="#" class="nav-item" onclick="showScreen('map')"><span class="nav-item-icon">🗺️</span>Carte</a>
<a href="#" class="nav-item" onclick="showScreen('marketplace')"><span class="nav-item-icon">🛒</span>Market</a>
<a href="#" class="nav-item" onclick="showScreen('chat')"><span class="nav-item-icon">🤖</span>IA Chat</a>
<a href="#" class="nav-item active" onclick="showScreen('profile')"><span class="nav-item-icon">👤</span>Profil</a>
</nav>
</div>
<!-- ═══════════════════════════════════════════════════════════════
SCREEN: NOTIFICATIONS
═══════════════════════════════════════════════════════════════ -->
<div id="screen-notifications" class="screen">
<div class="dashboard-header" style="padding-bottom:24px">
<div style="display:flex;justify-content:space-between;align-items:center">
<div class="section-header"><div class="section-title">Notifications</div></div>
<button class="link" style="font-size:13px" onclick="markAllRead()">Tout lu</button>
</div>
</div>
<div class="scrollable" style="padding-top:60px">
<div class="section" id="notifications-list"></div>
</div>
<nav class="top-nav">
<a href="#" class="nav-item active" onclick="showScreen('home')"><span class="nav-item-icon">🏠</span>Accueil</a>
<a href="#" class="nav-item" onclick="showScreen('map')"><span class="nav-item-icon">🗺️</span>Carte</a>
<a href="#" class="nav-item" onclick="showScreen('marketplace')"><span class="nav-item-icon">🛒</span>Market</a>
<a href="#" class="nav-item" onclick="showScreen('chat')"><span class="nav-item-icon">🤖</span>IA Chat</a>
<a href="#" class="nav-item" onclick="showScreen('profile')"><span class="nav-item-icon">👤</span>Profil</a>
</nav>
</div>
<!-- ═══════════════════════════════════════════════════════════════
PLACEHOLDER SCREENS
═══════════════════════════════════════════════════════════════ -->
<div id="screen-signalements" class="screen"><div class="scrollable" style="padding:60px 20px;text-align:center"><div style="font-size:48px;margin-bottom:16px">🚨</div><h2>Signalements</h2><p style="color:var(--text-secondary);margin-top:8px">Écran en cours de développement</p><button class="btn btn-primary" style="margin-top:24px" onclick="showScreen('home')">← Retour</button></div><nav class="top-nav"><a href="#" class="nav-item active" onclick="showScreen('home')"><span class="nav-item-icon">🏠</span>Accueil</a><a href="#" class="nav-item" onclick="showScreen('map')"><span class="nav-item-icon">🗺️</span>Carte</a><a href="#" class="nav-item" onclick="showScreen('marketplace')"><span class="nav-item-icon">🛒</span>Market</a><a href="#" class="nav-item" onclick="showScreen('chat')"><span class="nav-item-icon">🤖</span>IA Chat</a><a href="#" class="nav-item" onclick="showScreen('profile')"><span class="nav-item-icon">👤</span>Profil</a></nav></div>
<div id="screen-sensors" class="screen"><div class="scrollable" style="padding:60px 20px;text-align:center"><div style="font-size:48px;margin-bottom:16px">📡</div><h2>Capteurs IoT</h2><p style="color:var(--text-secondary);margin-top:8px">Écran en cours de développement</p><button class="btn btn-primary" style="margin-top:24px" onclick="showScreen('home')">← Retour</button></div><nav class="top-nav"><a href="#" class="nav-item active" onclick="showScreen('home')"><span class="nav-item-icon">🏠</span>Accueil</a><a href="#" class="nav-item" onclick="showScreen('map')"><span class="nav-item-icon">🗺️</span>Carte</a><a href="#" class="nav-item" onclick="showScreen('marketplace')"><span class="nav-item-icon">🛒</span>Market</a><a href="#" class="nav-item" onclick="showScreen('chat')"><span class="nav-item-icon">🤖</span>IA Chat</a><a href="#" class="nav-item" onclick="showScreen('profile')"><span class="nav-item-icon">👤</span>Profil</a></nav></div>
<div id="screen-meteo" class="screen"><div class="scrollable" style="padding:60px 20px;text-align:center"><div style="font-size:48px;margin-bottom:16px">🌤️</div><h2>Météo</h2><p style="color:var(--text-secondary);margin-top:8px">Écran en cours de développement</p><button class="btn btn-primary" style="margin-top:24px" onclick="showScreen('home')">← Retour</button></div><nav class="top-nav"><a href="#" class="nav-item active" onclick="showScreen('home')"><span class="nav-item-icon">🏠</span>Accueil</a><a href="#" class="nav-item" onclick="showScreen('map')"><span class="nav-item-icon">🗺️</span>Carte</a><a href="#" class="nav-item" onclick="showScreen('marketplace')"><span class="nav-item-icon">🛒</span>Market</a><a href="#" class="nav-item" onclick="showScreen('chat')"><span class="nav-item-icon">🤖</span>IA Chat</a><a href="#" class="nav-item" onclick="showScreen('profile')"><span class="nav-item-icon">👤</span>Profil</a></nav></div>
<div id="screen-sante" class="screen"><div class="scrollable" style="padding:60px 20px;text-align:center"><div style="font-size:48px;margin-bottom:16px">🏥</div><h2>Santé</h2><p style="color:var(--text-secondary);margin-top:8px">Écran en cours de développement</p><button class="btn btn-primary" style="margin-top:24px" onclick="showScreen('home')">← Retour</button></div><nav class="top-nav"><a href="#" class="nav-item active" onclick="showScreen('home')"><span class="nav-item-icon">🏠</span>Accueil</a><a href="#" class="nav-item" onclick="showScreen('map')"><span class="nav-item-icon">🗺️</span>Carte</a><a href="#" class="nav-item" onclick="showScreen('marketplace')"><span class="nav-item-icon">🛒</span>Market</a><a href="#" class="nav-item" onclick="showScreen('chat')"><span class="nav-item-icon">🤖</span>IA Chat</a><a href="#" class="nav-item" onclick="showScreen('profile')"><span class="nav-item-icon">👤</span>Profil</a></nav></div>
<script>
// ── Auth Token ──
let authToken = localStorage.getItem('authToken') || null;
// ── Screen Navigation ──
function showScreen(id) {
document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
document.getElementById('screen-' + id).classList.add('active');
document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));
const scrollable = document.querySelector('#screen-' + id + ' .scrollable');
if (scrollable) scrollable.scrollTop = 0;
}
// ── Toggle Password ──
function togglePw(id) {
const el = document.getElementById(id);
el.type = el.type === 'password' ? 'text' : 'password';
}
// ── API ──
async function apiCall(method, path, body, auth) {
const headers = { 'Content-Type': 'application/json' };
if (auth && authToken) headers['Authorization'] = 'Bearer ' + authToken;
const opts = { method, headers };
if (body) opts.body = JSON.stringify(body);
const resp = await fetch('https://api-smartapp.digitribe.fr/api' + path, opts);
const data = await resp.json().catch(() => null);
return { ok: resp.ok, status: resp.status, data };
}
// ── Login ──
async function handleLogin() {
const btn = document.getElementById('btn-login');
const email = document.getElementById('login-email').value.trim();
const password = document.getElementById('login-password').value;
const err = document.getElementById('login-error');
if (!email || !password) { err.textContent = 'Remplissez tous les champs'; err.classList.add('show'); return; }
btn.disabled = true; btn.innerHTML = '<div class="spinner"></div>';
try {
const { ok, data } = await apiCall('POST', '/auth/login', { email, password }, false);
if (ok && data?.accessToken) {
authToken = data.accessToken;
localStorage.setItem('authToken', authToken);
localStorage.setItem('user', JSON.stringify(data.user));
loadDashboard(); showScreen('home');
} else { err.textContent = data?.message || 'Identifiants incorrects'; err.classList.add('show'); }
} catch(e) { err.textContent = 'Erreur de connexion'; err.classList.add('show'); }
btn.disabled = false; btn.innerHTML = '<span>Se connecter</span>';
}
// ── Register ──
async function handleRegister() {
const btn = document.getElementById('btn-register');
const fn = document.getElementById('reg-firstname').value.trim();
const ln = document.getElementById('reg-lastname').value.trim();
const em = document.getElementById('reg-email').value.trim();
const pw = document.getElementById('reg-password').value;
const cf = document.getElementById('reg-confirm').value;
const err = document.getElementById('register-error');
const ok = document.getElementById('register-success');
err.classList.remove('show'); ok.classList.remove('show');
if (!fn||!ln||!em||!pw) { err.textContent = 'Remplissez tous les champs'; err.classList.add('show'); return; }
if (pw.length < 8) { err.textContent = 'Min. 8 caractères'; err.classList.add('show'); return; }
if (pw !== cf) { err.textContent = 'Mots de passe différents'; err.classList.add('show'); return; }
btn.disabled = true; btn.innerHTML = '<div class="spinner"></div>';
try {
const { ok: success, data } = await apiCall('POST', '/auth/register', { email:em, password:pw, firstName:fn, lastName:ln }, false);
if (success) { ok.textContent = 'Compte créé ! Connexion...'; ok.classList.add('show'); setTimeout(()=>{ handleLogin(); }, 1000); }
else { err.textContent = data?.message || 'Erreur'; err.classList.add('show'); }
} catch(e) { err.textContent = 'Erreur de connexion'; err.classList.add('show'); }
btn.disabled = false; btn.innerHTML = '<span>S\'inscrire</span>';
}
function socialLogin(p) { alert(p + ' — bientôt disponible'); }
function forgotPassword() { const e = prompt('Email :'); if(e) alert('Lien envoyé à ' + e); }
// ── Dashboard ──
function loadDashboard() {
const u = JSON.parse(localStorage.getItem('user') || '{}');
document.getElementById('home-user-name').textContent = u.firstName || 'Utilisateur';
document.getElementById('profile-name').textContent = (u.firstName||'') + ' ' + (u.lastName||'');
document.getElementById('profile-email').textContent = u.email || '-';
renderSensors(); renderMarketplace(); renderNotifications(); renderProfileMenu();
}
function renderSensors() {
const s = [
{n:'Centre-Ville',l:'Fort-de-France',v:'28.3',u:'°C',i:'🌡️',c:'badge-green'},
{n:'Port',l:'Baie de FDF',v:'72',u:'%',i:'💧',c:'badge-green'},
{n:'Qualité Air',l:'Schoelcher',v:'85',u:'AQI',i:'🌬️',c:'badge-orange'},
{n:'Bruit',l:'Centre-ville',v:'68',u:'dB',i:'🔊',c:'badge-red'},
];
document.getElementById('sensors-list').innerHTML = s.map(x=>`
<div class="card"><div style="display:flex;justify-content:space-between;align-items:center">
<div style="display:flex;gap:10px;align-items:center">
<div style="width:40px;height:40px;border-radius:12px;background:rgba(21,101,192,0.1);display:flex;align-items:center;justify-content:center;font-size:18px">${x.i}</div>
<div><div class="card-title">${x.n}</div><div class="card-subtitle">📍 ${x.l}</div></div>
</div>
<div style="text-align:right"><div style="font-size:20px;font-weight:700">${x.v}<span style="font-size:11px;color:var(--text-muted)"> ${x.u}</span></div><span class="badge ${x.c}">${x.u}</span></div>
</div></div>
`).join('');
document.getElementById('nearby-sensors').innerHTML = document.getElementById('sensors-list').innerHTML;
}
function renderMarketplace() {
const p = [
{n:'Panier Bio Local',pr:'AMAP Martinique',p:'15€',u:'/semaine',i:'🥬',r:4.8},
{n:'Pass Transport',pr:'CFTA',p:'45€',u:'/mois',i:'🎫',r:4.2},
{n:'Kit Solaire',pr:'EDF DOM',p:'299€',u:'',i:'☀️',r:4.6},
{n:'Télémédecine',pr:'Santé+',p:'25€',u:'/consult',i:'🩺',r:4.5},
];
document.getElementById('marketplace-list').innerHTML = p.map(x=>`
<div class="card"><div style="display:flex;gap:12px;align-items:center">
<div style="width:52px;height:52px;border-radius:14px;background:rgba(21,101,192,0.1);display:flex;align-items:center;justify-content:center;font-size:24px;flex-shrink:0">${x.i}</div>
<div style="flex:1"><div class="card-title">${x.n}</div><div class="card-subtitle">${x.pr}</div>
<div class="card-row"><span style="font-size:16px;font-weight:700;color:var(--primary)">${x.p}</span><span style="font-size:12px;color:var(--text-muted)">${x.u}</span><span style="font-size:12px;color:var(--text-secondary)">⭐ ${x.r}</span></div></div>
<button class="btn btn-primary" style="width:auto;padding:8px 16px;font-size:13px" onclick="alert('Ajouté')">+</button>
</div></div>
`).join('');
}
function renderNotifications() {
const n = [
{i:'🚨',t:'Alerte Qualité Air',b:'AQI élevé à Schoelcher (85).',h:'Il y a 30 min'},
{i:'🎉',t:'Fête de la Musique',b:'21 juin au centre-ville.',h:'Il y a 2j'},
{i:'',t:'Nouveau service',b:'Suivi bus temps réel disponible !',h:'Il y a 5j'},
];
document.getElementById('notifications-list').innerHTML = n.map(x=>`
<div class="card"><div style="display:flex;gap:12px;align-items:flex-start">
<span style="font-size:24px">${x.i}</span>
<div style="flex:1"><div class="card-title">${x.t}</div><div class="card-subtitle">${x.b}</div>
<div style="font-size:11px;color:var(--text-muted);margin-top:4px">${x.h}</div></div>
</div></div>
`).join('');
}
function renderProfileMenu() {
const items = [
{i:'🔔',l:'Notifications',a:"showScreen('notifications')"},
{i:'🌍',l:'Langue',v:'Français',a:"alert('Bientôt')"},
{i:'🌙',l:'Mode sombre',v:'Off',a:"alert('Bientôt')"},
{i:'🔒',l:'Confidentialité',a:"alert('Bientôt')"},
{i:'❓',l:'Aide & Support',a:"alert('Bientôt')"},
{i:'',l:'À propos',v:'v0.1.0',a:"alert('Smart City Martinique v0.1.0')"},
{i:'🚪',l:'Déconnexion',a:'logout()',s:'color:var(--danger)'},
];
document.getElementById('profile-menu').innerHTML = items.map(x=>`
<div class="card" onclick="${x.a}" style="cursor:pointer;display:flex;justify-content:space-between;align-items:center">
<div style="display:flex;gap:12px;align-items:center"><span style="font-size:20px">${x.i}</span><span style="font-size:15px;${x.s||''}">${x.l}</span></div>
<div style="display:flex;align-items:center;gap:8px">${x.v?`<span style="font-size:13px;color:var(--text-muted)">${x.v}</span>`:''}<span style="font-size:18px;color:var(--text-muted)"></span></div>
</div>
`).join('');
}
function logout() { authToken=null; localStorage.removeItem('authToken'); localStorage.removeItem('user'); showScreen('login'); }
function toggleLayer(el) { el.style.opacity = el.style.opacity === '0.5' ? '1' : '0.5'; }
function filterCategory(el) { document.querySelectorAll('[onclick^="filterCategory"]').forEach(e=>{e.style.background='';e.style.color='';}); el.style.background='var(--primary)'; el.style.color='white'; }
function markAllRead() { alert('Tout marqué comme lu'); }
// ── Chat ──
const chatResp = {
'météo':'☀️ Fort-de-France : 28°C, ensoleillé. Humidité 72%, vent 12 km/h NE.',
'bus':'🚌 L1 (Centre→Schoelcher) dans 8 min. L3 dans 12 min.',
'énergie':'⚡ Conso semaine : 45 kWh (-12%). Estimation mensuelle : 180 kWh.',
'alerte':'🚨 1 alerte : AQI élevé à Schoelcher (85).',
};
function sendChat() {
const input = document.getElementById('chat-input');
const msg = input.value.trim(); if (!msg) return;
const c = document.getElementById('chat-messages');
c.innerHTML += `<div class="chat-message chat-message-user">${msg}</div>`;
input.value = '';
setTimeout(()=>{
const l = msg.toLowerCase();
let r = 'Je consulte les données... 🔍';
for (const [k,v] of Object.entries(chatResp)) { if(l.includes(k)) { r=v; break; } }
c.innerHTML += `<div class="chat-message chat-message-bot">${r}</div>`;
c.scrollTop = c.scrollHeight;
}, 800);
}
function quickPrompt(t) { document.getElementById('chat-input').value = t; sendChat(); }
// ── Auto-login ──
if (authToken) { loadDashboard(); showScreen('home'); }
</script>
</body>
</html>