Tu Nombre commited on
Commit
7c7779c
·
1 Parent(s): 683e056

Actualización: Cambio a modelo Llama 3.1 8B

Browse files
Files changed (1) hide show
  1. familiar.html +468 -0
familiar.html ADDED
@@ -0,0 +1,468 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Monitor Familiar</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Exo+2:wght@300;600;800&display=swap" rel="stylesheet">
8
+ <style>
9
+ :root {
10
+ --bg: #030a0e;
11
+ --panel: #0a1a22;
12
+ --border: #0e3a50;
13
+ --cyan: #00e5ff;
14
+ --green: #00ff88;
15
+ --red: #ff2244;
16
+ --yellow: #ffcc00;
17
+ --text: #c8e8f0;
18
+ --mono: 'Share Tech Mono', monospace;
19
+ --display: 'Exo 2', sans-serif;
20
+ }
21
+
22
+ * { margin: 0; padding: 0; box-sizing: border-box; }
23
+
24
+ body {
25
+ background: var(--bg);
26
+ color: var(--text);
27
+ font-family: var(--display);
28
+ min-height: 100vh;
29
+ }
30
+
31
+ body::before {
32
+ content: '';
33
+ position: fixed;
34
+ inset: 0;
35
+ background: radial-gradient(ellipse at 20% 50%, rgba(0,229,255,0.04) 0%, transparent 60%);
36
+ pointer-events: none;
37
+ z-index: 0;
38
+ }
39
+
40
+ .grid-bg {
41
+ position: fixed;
42
+ inset: 0;
43
+ background-image:
44
+ linear-gradient(rgba(0,229,255,0.04) 1px, transparent 1px),
45
+ linear-gradient(90deg, rgba(0,229,255,0.04) 1px, transparent 1px);
46
+ background-size: 40px 40px;
47
+ pointer-events: none;
48
+ z-index: 0;
49
+ }
50
+
51
+ .container {
52
+ position: relative;
53
+ z-index: 1;
54
+ max-width: 480px;
55
+ margin: 0 auto;
56
+ padding: 16px;
57
+ }
58
+
59
+ .header {
60
+ text-align: center;
61
+ padding: 20px 0 16px;
62
+ border-bottom: 1px solid var(--border);
63
+ margin-bottom: 16px;
64
+ }
65
+
66
+ .header h1 {
67
+ font-size: 1.4rem;
68
+ font-weight: 800;
69
+ letter-spacing: 0.15em;
70
+ color: var(--cyan);
71
+ text-shadow: 0 0 20px rgba(0,229,255,0.5);
72
+ text-transform: uppercase;
73
+ }
74
+
75
+ .header p {
76
+ font-family: var(--mono);
77
+ font-size: 0.65rem;
78
+ color: #4a7a8a;
79
+ margin-top: 4px;
80
+ letter-spacing: 0.1em;
81
+ }
82
+
83
+ /* Nombre paciente */
84
+ .nombre-paciente {
85
+ text-align: center;
86
+ font-size: 1.1rem;
87
+ font-weight: 600;
88
+ color: var(--cyan);
89
+ margin-bottom: 14px;
90
+ font-family: var(--mono);
91
+ letter-spacing: 0.1em;
92
+ }
93
+
94
+ /* Estado principal */
95
+ .estado-box {
96
+ border: 2px solid var(--border);
97
+ border-radius: 8px;
98
+ padding: 20px;
99
+ margin-bottom: 14px;
100
+ background: var(--panel);
101
+ text-align: center;
102
+ transition: all 0.3s;
103
+ }
104
+
105
+ .estado-box.normal { border-color: var(--green); box-shadow: 0 0 20px rgba(0,255,136,0.15); }
106
+ .estado-box.critico { border-color: var(--red); box-shadow: 0 0 40px rgba(255,34,68,0.4); animation: pulseRed 0.8s infinite; }
107
+ .estado-box.sin_datos { border-color: var(--border); }
108
+
109
+ @keyframes pulseRed {
110
+ 0%, 100% { box-shadow: 0 0 20px rgba(255,34,68,0.3); }
111
+ 50% { box-shadow: 0 0 60px rgba(255,34,68,0.7); }
112
+ }
113
+
114
+ .estado-label {
115
+ font-family: var(--mono);
116
+ font-size: 0.6rem;
117
+ letter-spacing: 0.2em;
118
+ color: #4a7a8a;
119
+ margin-bottom: 8px;
120
+ }
121
+
122
+ .estado-valor {
123
+ font-size: 2.2rem;
124
+ font-weight: 800;
125
+ letter-spacing: 0.1em;
126
+ text-transform: uppercase;
127
+ }
128
+
129
+ .estado-valor.normal { color: var(--green); text-shadow: 0 0 15px rgba(0,255,136,0.5); }
130
+ .estado-valor.critico { color: var(--red); text-shadow: 0 0 20px rgba(255,34,68,0.8); }
131
+ .estado-valor.sin_datos { color: #4a7a8a; }
132
+
133
+ .motivo-texto {
134
+ font-family: var(--mono);
135
+ font-size: 0.78rem;
136
+ color: var(--yellow);
137
+ margin-top: 10px;
138
+ min-height: 18px;
139
+ line-height: 1.4;
140
+ }
141
+
142
+ /* Constantes */
143
+ .constantes {
144
+ display: grid;
145
+ grid-template-columns: 1fr 1fr;
146
+ gap: 10px;
147
+ margin-bottom: 14px;
148
+ }
149
+
150
+ .constante-card {
151
+ background: var(--panel);
152
+ border: 1px solid var(--border);
153
+ border-radius: 8px;
154
+ padding: 14px;
155
+ text-align: center;
156
+ }
157
+
158
+ .constante-label {
159
+ font-family: var(--mono);
160
+ font-size: 0.55rem;
161
+ color: #4a7a8a;
162
+ letter-spacing: 0.15em;
163
+ text-transform: uppercase;
164
+ margin-bottom: 6px;
165
+ }
166
+
167
+ .constante-valor {
168
+ font-family: var(--mono);
169
+ font-size: 2rem;
170
+ font-weight: bold;
171
+ color: var(--cyan);
172
+ }
173
+
174
+ .constante-unidad {
175
+ font-size: 0.65rem;
176
+ color: #4a7a8a;
177
+ margin-left: 2px;
178
+ }
179
+
180
+ /* Sonido */
181
+ .sonido-card {
182
+ background: var(--panel);
183
+ border: 1px solid var(--border);
184
+ border-radius: 8px;
185
+ padding: 14px;
186
+ margin-bottom: 14px;
187
+ }
188
+
189
+ .sonido-label {
190
+ font-family: var(--mono);
191
+ font-size: 0.55rem;
192
+ color: #4a7a8a;
193
+ letter-spacing: 0.15em;
194
+ text-transform: uppercase;
195
+ margin-bottom: 8px;
196
+ }
197
+
198
+ .sonido-texto {
199
+ font-family: var(--mono);
200
+ font-size: 0.8rem;
201
+ color: var(--text);
202
+ }
203
+
204
+ /* Actualización */
205
+ .actualizacion {
206
+ text-align: center;
207
+ font-family: var(--mono);
208
+ font-size: 0.65rem;
209
+ color: #4a7a8a;
210
+ margin-bottom: 14px;
211
+ }
212
+
213
+ .punto-vivo {
214
+ display: inline-block;
215
+ width: 6px;
216
+ height: 6px;
217
+ background: var(--green);
218
+ border-radius: 50%;
219
+ margin-right: 6px;
220
+ animation: blink 1.5s infinite;
221
+ vertical-align: middle;
222
+ }
223
+
224
+ @keyframes blink {
225
+ 0%, 100% { opacity: 1; }
226
+ 50% { opacity: 0.2; }
227
+ }
228
+
229
+ /* Botón ir a vigilante */
230
+ .btn-vigilante {
231
+ display: block;
232
+ width: 100%;
233
+ padding: 14px;
234
+ background: transparent;
235
+ border: 1px solid var(--border);
236
+ border-radius: 8px;
237
+ color: #4a7a8a;
238
+ font-family: var(--display);
239
+ font-size: 0.8rem;
240
+ font-weight: 600;
241
+ letter-spacing: 0.1em;
242
+ text-transform: uppercase;
243
+ cursor: pointer;
244
+ text-align: center;
245
+ text-decoration: none;
246
+ margin-bottom: 14px;
247
+ transition: all 0.2s;
248
+ }
249
+
250
+ .btn-vigilante:hover { border-color: var(--cyan); color: var(--cyan); }
251
+
252
+ /* Alarma overlay */
253
+ .alarma-overlay {
254
+ display: none;
255
+ position: fixed;
256
+ inset: 0;
257
+ background: rgba(255,34,68,0.15);
258
+ z-index: 100;
259
+ backdrop-filter: blur(2px);
260
+ animation: flashRed 0.5s infinite;
261
+ align-items: center;
262
+ justify-content: center;
263
+ }
264
+
265
+ .alarma-overlay.activa { display: flex; }
266
+
267
+ @keyframes flashRed {
268
+ 0%, 100% { background: rgba(255,34,68,0.1); }
269
+ 50% { background: rgba(255,34,68,0.3); }
270
+ }
271
+
272
+ .alarma-card {
273
+ background: #1a0508;
274
+ border: 2px solid var(--red);
275
+ border-radius: 12px;
276
+ padding: 30px;
277
+ text-align: center;
278
+ max-width: 300px;
279
+ box-shadow: 0 0 60px rgba(255,34,68,0.5);
280
+ }
281
+
282
+ .alarma-icono { font-size: 3rem; margin-bottom: 10px; }
283
+ .alarma-titulo {
284
+ font-size: 1.5rem;
285
+ font-weight: 800;
286
+ color: var(--red);
287
+ letter-spacing: 0.15em;
288
+ text-transform: uppercase;
289
+ margin-bottom: 10px;
290
+ }
291
+
292
+ .alarma-motivo {
293
+ font-family: var(--mono);
294
+ font-size: 0.8rem;
295
+ color: var(--text);
296
+ margin-bottom: 20px;
297
+ line-height: 1.5;
298
+ }
299
+
300
+ .btn-silenciar {
301
+ background: var(--red);
302
+ color: white;
303
+ border: none;
304
+ border-radius: 6px;
305
+ padding: 12px 24px;
306
+ font-family: var(--display);
307
+ font-weight: 600;
308
+ font-size: 0.85rem;
309
+ cursor: pointer;
310
+ letter-spacing: 0.1em;
311
+ text-transform: uppercase;
312
+ }
313
+ </style>
314
+ </head>
315
+ <body>
316
+
317
+ <div class="grid-bg"></div>
318
+
319
+ <div class="alarma-overlay" id="alarmaOverlay">
320
+ <div class="alarma-card">
321
+ <div class="alarma-icono">🚨</div>
322
+ <div class="alarma-titulo">¡ALERTA CRÍTICA!</div>
323
+ <div class="alarma-motivo" id="alarmaMotivo"></div>
324
+ <button class="btn-silenciar" onclick="silenciarAlarma()">SILENCIAR</button>
325
+ </div>
326
+ </div>
327
+
328
+ <div class="container">
329
+
330
+ <div class="header">
331
+ <h1>👨‍👩‍👧 Monitor Familiar</h1>
332
+ <p>VISTA DEL CUIDADOR · ACTUALIZACIÓN EN TIEMPO REAL</p>
333
+ </div>
334
+
335
+ <div class="nombre-paciente" id="nombrePaciente">── Esperando datos ──</div>
336
+
337
+ <div class="estado-box sin_datos" id="estadoBox">
338
+ <div class="estado-label">// ESTADO DEL PACIENTE</div>
339
+ <div class="estado-valor sin_datos" id="estadoValor">SIN DATOS</div>
340
+ <div class="motivo-texto" id="motivoTexto"></div>
341
+ </div>
342
+
343
+ <div class="constantes">
344
+ <div class="constante-card">
345
+ <div class="constante-label">// Pulso</div>
346
+ <div class="constante-valor" id="pulsoValor">--<span class="constante-unidad">BPM</span></div>
347
+ </div>
348
+ <div class="constante-card">
349
+ <div class="constante-label">// Oxígeno</div>
350
+ <div class="constante-valor" id="oxigenoValor">--<span class="constante-unidad">%</span></div>
351
+ </div>
352
+ </div>
353
+
354
+ <div class="sonido-card">
355
+ <div class="sonido-label">// Sonido ambiente</div>
356
+ <div class="sonido-texto" id="sonidoTexto">Sin datos</div>
357
+ </div>
358
+
359
+ <div class="actualizacion">
360
+ <span class="punto-vivo"></span>
361
+ <span id="ultimaActualizacion">Conectando...</span>
362
+ </div>
363
+
364
+ <a href="/app" class="btn-vigilante">⚕ Ir a pantalla de vigilancia</a>
365
+
366
+ </div>
367
+
368
+ <script>
369
+ const BACKEND = "https://cristobal299-iaweb.hf.space/estado";
370
+ let alarmaActiva = false;
371
+ let ultimoEstado = "";
372
+
373
+ async function actualizarDatos() {
374
+ try {
375
+ const resp = await fetch(BACKEND);
376
+ const data = await resp.json();
377
+
378
+ // Nombre
379
+ document.getElementById('nombrePaciente').textContent =
380
+ '👤 ' + (data.nombre || 'Paciente');
381
+
382
+ // Pulso y oxígeno
383
+ document.getElementById('pulsoValor').innerHTML =
384
+ (data.pulso || '--') + '<span class="constante-unidad">BPM</span>';
385
+ document.getElementById('oxigenoValor').innerHTML =
386
+ (data.oxigeno || '--') + '<span class="constante-unidad">%</span>';
387
+
388
+ // Sonido
389
+ document.getElementById('sonidoTexto').textContent =
390
+ data.sonido || 'Sin datos';
391
+
392
+ // Última actualización
393
+ document.getElementById('ultimaActualizacion').textContent =
394
+ 'Última actualización: ' + (data.ultima_actualizacion || '--');
395
+
396
+ // Estado
397
+ const estado = (data.estado || 'SIN_DATOS').toUpperCase();
398
+ const box = document.getElementById('estadoBox');
399
+ const valor = document.getElementById('estadoValor');
400
+ const motivo = document.getElementById('motivoTexto');
401
+
402
+ if (estado === 'CRITICO') {
403
+ box.className = 'estado-box critico';
404
+ valor.className = 'estado-valor critico';
405
+ valor.textContent = '⚠ CRÍTICO';
406
+ motivo.textContent = data.motivo || '';
407
+
408
+ // Disparar alarma solo si es nueva
409
+ if (ultimoEstado !== 'CRITICO' && !alarmaActiva) {
410
+ dispararAlarma(data.motivo || 'Estado crítico detectado');
411
+ }
412
+ } else if (estado === 'NORMAL') {
413
+ box.className = 'estado-box normal';
414
+ valor.className = 'estado-valor normal';
415
+ valor.textContent = '✓ NORMAL';
416
+ motivo.textContent = '';
417
+ } else {
418
+ box.className = 'estado-box sin_datos';
419
+ valor.className = 'estado-valor sin_datos';
420
+ valor.textContent = 'SIN DATOS';
421
+ motivo.textContent = 'Inicia la vigilancia en la otra pantalla';
422
+ }
423
+
424
+ ultimoEstado = estado;
425
+
426
+ } catch (err) {
427
+ document.getElementById('ultimaActualizacion').textContent =
428
+ 'Error de conexión — reintentando...';
429
+ }
430
+ }
431
+
432
+ function dispararAlarma(motivo) {
433
+ alarmaActiva = true;
434
+ document.getElementById('alarmaMotivo').textContent = motivo;
435
+ document.getElementById('alarmaOverlay').classList.add('activa');
436
+
437
+ try {
438
+ const ctx = new AudioContext();
439
+ function beep(freq, start, dur) {
440
+ const osc = ctx.createOscillator();
441
+ const gain = ctx.createGain();
442
+ osc.connect(gain);
443
+ gain.connect(ctx.destination);
444
+ osc.frequency.value = freq;
445
+ osc.type = 'square';
446
+ gain.gain.setValueAtTime(0.3, ctx.currentTime + start);
447
+ gain.gain.exponentialRampToValueAtTime(0.01, ctx.currentTime + start + dur);
448
+ osc.start(ctx.currentTime + start);
449
+ osc.stop(ctx.currentTime + start + dur);
450
+ }
451
+ for (let i = 0; i < 8; i++) {
452
+ beep(880, i * 0.4, 0.3);
453
+ beep(660, i * 0.4 + 0.2, 0.15);
454
+ }
455
+ } catch(e) {}
456
+ }
457
+
458
+ function silenciarAlarma() {
459
+ alarmaActiva = false;
460
+ document.getElementById('alarmaOverlay').classList.remove('activa');
461
+ }
462
+
463
+ // Actualizar cada 5 segundos
464
+ actualizarDatos();
465
+ setInterval(actualizarDatos, 5000);
466
+ </script>
467
+ </body>
468
+ </html>