Akira-Kurusu commited on
Commit
1570eec
·
verified ·
1 Parent(s): f2959a6

Update web/diagnosis.html

Browse files
Files changed (1) hide show
  1. web/diagnosis.html +103 -21
web/diagnosis.html CHANGED
@@ -199,6 +199,69 @@
199
  opacity: 0;
200
  pointer-events: none;
201
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  </style>
203
  </head>
204
  <body class="vertical light">
@@ -1239,28 +1302,47 @@ if (false) { /* removed */ }
1239
  }
1240
 
1241
  function showAlert(type, message) {
1242
- const alertClass = {
1243
- 'success': 'alert-success',
1244
- 'error': 'alert-danger',
1245
- 'warning': 'alert-warning',
1246
- 'info': 'alert-info'
1247
- }[type] || 'alert-info';
1248
-
1249
- const alertHtml = `
1250
- <div class="alert ${alertClass} alert-dismissible fade show" role="alert">
1251
- ${(function(){var n=type==='error'?'x-circle':type==='success'?'check-circle':type==='warning'?'alert-triangle':'info';return typeof feather!=='undefined'?feather.icons[n].toSvg({'width':16,'height':16,'stroke-width':1.8,'style':'margin-right:6px;vertical-align:middle;'}):'';})()}
1252
- ${message}
1253
- <button type="button" class="close" data-dismiss="alert">
1254
- <span aria-hidden="true">&times;</span>
1255
- </button>
1256
- </div>
1257
- `;
1258
-
1259
- $('.container-fluid').prepend(alertHtml);
1260
 
1261
- setTimeout(() => {
1262
- $('.alert').first().alert('close');
1263
- }, 5000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1264
  }
1265
 
1266
  // === FUNCIONES GLOBALES ===
 
199
  opacity: 0;
200
  pointer-events: none;
201
  }
202
+
203
+ /* ── TOAST NOTIFICATIONS ─────────────────────────── */
204
+ #toast-container {
205
+ position: fixed;
206
+ bottom: 1.5rem;
207
+ right: 1.5rem;
208
+ z-index: 99999;
209
+ display: flex;
210
+ flex-direction: column;
211
+ gap: 0.6rem;
212
+ pointer-events: none;
213
+ }
214
+ .toast-notify {
215
+ display: flex;
216
+ align-items: flex-start;
217
+ gap: 12px;
218
+ min-width: 300px;
219
+ max-width: 380px;
220
+ padding: 14px 16px;
221
+ border-radius: 10px;
222
+ box-shadow: 0 8px 24px rgba(0,0,0,0.15);
223
+ background: #fff;
224
+ border-left: 5px solid #ccc;
225
+ pointer-events: all;
226
+ opacity: 0;
227
+ transform: translateX(60px);
228
+ transition: opacity 0.3s ease, transform 0.3s ease;
229
+ position: relative;
230
+ overflow: hidden;
231
+ }
232
+ .toast-notify.show { opacity: 1; transform: translateX(0); }
233
+ .toast-notify.hide { opacity: 0; transform: translateX(60px); }
234
+ .toast-notify.toast-success { border-left-color: #28a745; }
235
+ .toast-notify.toast-error { border-left-color: #dc3545; }
236
+ .toast-notify.toast-warning { border-left-color: #ffc107; }
237
+ .toast-notify.toast-info { border-left-color: #17a2b8; }
238
+ .toast-icon { flex-shrink: 0; margin-top: 1px; }
239
+ .toast-success .toast-icon svg { stroke: #28a745; }
240
+ .toast-error .toast-icon svg { stroke: #dc3545; }
241
+ .toast-warning .toast-icon svg { stroke: #ffc107; }
242
+ .toast-info .toast-icon svg { stroke: #17a2b8; }
243
+ .toast-body { flex: 1; }
244
+ .toast-title { font-weight: 600; font-size: 0.875rem; margin-bottom: 2px; }
245
+ .toast-success .toast-title { color: #155724; }
246
+ .toast-error .toast-title { color: #721c24; }
247
+ .toast-warning .toast-title { color: #856404; }
248
+ .toast-info .toast-title { color: #0c5460; }
249
+ .toast-msg { font-size: 0.825rem; color: #555; line-height: 1.4; }
250
+ .toast-close {
251
+ background: none; border: none; font-size: 1rem;
252
+ line-height: 1; color: #aaa; cursor: pointer; padding: 0; flex-shrink: 0;
253
+ }
254
+ .toast-close:hover { color: #333; }
255
+ .toast-progress {
256
+ position: absolute;
257
+ bottom: 0; left: 0;
258
+ height: 3px;
259
+ border-radius: 0 0 0 10px;
260
+ }
261
+ .toast-success .toast-progress { background: #28a745; }
262
+ .toast-error .toast-progress { background: #dc3545; }
263
+ .toast-warning .toast-progress { background: #ffc107; }
264
+ .toast-info .toast-progress { background: #17a2b8; }
265
  </style>
266
  </head>
267
  <body class="vertical light">
 
1302
  }
1303
 
1304
  function showAlert(type, message) {
1305
+ if (!document.getElementById('toast-container')) {
1306
+ const container = document.createElement('div');
1307
+ container.id = 'toast-container';
1308
+ document.body.appendChild(container);
1309
+ }
1310
+ const container = document.getElementById('toast-container');
 
 
 
 
 
 
 
 
 
 
 
 
1311
 
1312
+ const icons = {
1313
+ success: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>',
1314
+ error: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>',
1315
+ warning: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',
1316
+ info: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>'
1317
+ };
1318
+ const titles = { success: 'Éxito', error: 'Error', warning: 'Advertencia', info: 'Información' };
1319
+ const duration = type === 'error' ? 6000 : 4000;
1320
+
1321
+ const toast = document.createElement('div');
1322
+ toast.className = `toast-notify toast-${type}`;
1323
+ toast.innerHTML = `
1324
+ <div class="toast-icon">${icons[type] || icons.info}</div>
1325
+ <div class="toast-body">
1326
+ <div class="toast-title">${titles[type] || 'Aviso'}</div>
1327
+ <div class="toast-msg">${message}</div>
1328
+ </div>
1329
+ <button class="toast-close" onclick="this.closest('.toast-notify').remove()">&times;</button>
1330
+ <div class="toast-progress" style="width:100%;transition:width ${duration}ms linear;"></div>
1331
+ `;
1332
+ container.appendChild(toast);
1333
+
1334
+ requestAnimationFrame(() => requestAnimationFrame(() => {
1335
+ toast.classList.add('show');
1336
+ const bar = toast.querySelector('.toast-progress');
1337
+ if (bar) requestAnimationFrame(() => { bar.style.width = '0%'; });
1338
+ }));
1339
+
1340
+ const timer = setTimeout(() => {
1341
+ toast.classList.add('hide');
1342
+ toast.addEventListener('transitionend', () => toast.remove(), { once: true });
1343
+ }, duration);
1344
+
1345
+ toast.querySelector('.toast-close').addEventListener('click', () => clearTimeout(timer));
1346
  }
1347
 
1348
  // === FUNCIONES GLOBALES ===