706 lines
47 KiB
HTML
706 lines
47 KiB
HTML
<!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>
|