feat: add favicon and manifest for PWA support, include logo and related icons
@@ -2,9 +2,29 @@
|
|||||||
<html lang="es">
|
<html lang="es">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Wallabicher Dashboard</title>
|
<title>Wallabicher Dashboard</title>
|
||||||
|
|
||||||
|
<!-- Favicon -->
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||||
|
|
||||||
|
<!-- Apple Touch Icon (iOS) -->
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||||
|
|
||||||
|
<!-- Android Chrome Icons -->
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="/android-chrome-192x192.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="512x512" href="/android-chrome-512x512.png" />
|
||||||
|
|
||||||
|
<!-- Manifest for PWA -->
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
|
||||||
|
<!-- Theme colors -->
|
||||||
|
<meta name="theme-color" content="#0284c7" />
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
||||||
|
<meta name="apple-mobile-web-app-title" content="Wallabicher" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
BIN
web/frontend/public/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
web/frontend/public/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
web/frontend/public/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
web/frontend/public/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
web/frontend/public/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
web/frontend/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
web/frontend/public/logo.jpg
Normal file
|
After Width: | Height: | Size: 39 KiB |
22
web/frontend/public/manifest.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "Wallabicher Dashboard",
|
||||||
|
"short_name": "Wallabicher",
|
||||||
|
"description": "Dashboard para monitorear artículos de Wallapop y Vinted",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#0284c7",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone",
|
||||||
|
"start_url": "/"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -85,40 +85,40 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Toast notifications container -->
|
<!-- Toast notifications container -->
|
||||||
<div class="fixed bottom-4 right-4 z-50 space-y-2">
|
<div class="fixed top-4 right-4 z-50 space-y-2">
|
||||||
<div
|
<div
|
||||||
v-for="toast in toasts"
|
v-for="toast in toasts"
|
||||||
:key="toast.id"
|
:key="toast.id"
|
||||||
class="bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-4 max-w-md min-w-[320px] animate-slide-in"
|
class="bg-white/90 dark:bg-gray-800/90 backdrop-blur-sm border border-gray-200/50 dark:border-gray-700/50 rounded-lg shadow-md p-2 max-w-xs min-w-[200px] animate-slide-in"
|
||||||
>
|
>
|
||||||
<div class="flex items-start gap-3">
|
<div class="flex items-start gap-2">
|
||||||
<div class="flex-shrink-0">
|
<div class="flex-shrink-0">
|
||||||
<img
|
<img
|
||||||
v-if="toast.image"
|
v-if="toast.images"
|
||||||
:src="toast.image"
|
:src="toast.images[0]"
|
||||||
:alt="toast.title"
|
:alt="toast.title"
|
||||||
class="w-16 h-16 object-cover rounded"
|
class="w-10 h-10 object-cover rounded"
|
||||||
@error="($event) => $event.target.style.display = 'none'"
|
@error="($event) => $event.target.style.display = 'none'"
|
||||||
/>
|
/>
|
||||||
<div v-else class="w-16 h-16 bg-gray-200 dark:bg-gray-700 rounded flex items-center justify-center">
|
<div v-else class="w-10 h-10 bg-gray-200 dark:bg-gray-700 rounded flex items-center justify-center">
|
||||||
<span class="text-gray-400 text-xs">📦</span>
|
<span class="text-gray-400 text-xs">📦</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex-1 min-w-0">
|
||||||
<div class="flex items-start justify-between gap-2">
|
<div class="flex items-start justify-between gap-1">
|
||||||
<div class="flex-1">
|
<div class="flex-1 min-w-0">
|
||||||
<div class="flex items-center gap-2 mb-1">
|
<div class="flex items-center gap-1 mb-0.5">
|
||||||
<span
|
<span
|
||||||
class="px-2 py-0.5 text-xs font-semibold rounded"
|
class="px-1.5 py-0.5 text-[10px] font-semibold rounded"
|
||||||
:class="toast.platform === 'wallapop' ? 'bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200' : 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200'"
|
:class="toast.platform === 'wallapop' ? 'bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200' : 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200'"
|
||||||
>
|
>
|
||||||
{{ toast.platform?.toUpperCase() }}
|
{{ toast.platform?.toUpperCase() }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<h4 class="font-semibold text-gray-900 dark:text-gray-100 text-sm mb-1 line-clamp-2">
|
<h4 class="font-medium text-gray-900 dark:text-gray-100 text-xs mb-0.5 line-clamp-1 leading-tight">
|
||||||
{{ toast.title || 'Nuevo artículo' }}
|
{{ toast.title || 'Nuevo artículo' }}
|
||||||
</h4>
|
</h4>
|
||||||
<p v-if="toast.price" class="text-lg font-bold text-primary-600 dark:text-primary-400 mb-2">
|
<p v-if="toast.price" class="text-sm font-bold text-primary-600 dark:text-primary-400 mb-1">
|
||||||
{{ toast.price }} {{ toast.currency || '€' }}
|
{{ toast.price }} {{ toast.currency || '€' }}
|
||||||
</p>
|
</p>
|
||||||
<a
|
<a
|
||||||
@@ -126,14 +126,15 @@
|
|||||||
:href="toast.url"
|
:href="toast.url"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
class="text-xs text-primary-600 dark:text-primary-400 hover:underline inline-flex items-center gap-1"
|
class="text-[10px] text-primary-600 dark:text-primary-400 hover:underline inline-flex items-center gap-0.5"
|
||||||
>
|
>
|
||||||
Ver artículo →
|
Ver →
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@click="removeToast(toast.id)"
|
@click="removeToast(toast.id)"
|
||||||
class="flex-shrink-0 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
|
class="flex-shrink-0 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-xs leading-none p-0.5"
|
||||||
|
title="Cerrar"
|
||||||
>
|
>
|
||||||
✕
|
✕
|
||||||
</button>
|
</button>
|
||||||
@@ -183,10 +184,10 @@ function addToast(article) {
|
|||||||
...article,
|
...article,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Auto-remover después de 8 segundos
|
// Auto-remover después de 5 segundos (más corto para toasts discretos)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
removeToast(id);
|
removeToast(id);
|
||||||
}, 8000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeToast(id) {
|
function removeToast(id) {
|
||||||
|
|||||||
@@ -54,6 +54,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.animate-slide-in {
|
.animate-slide-in {
|
||||||
animation: slide-in 0.3s ease-out;
|
animation: slide-in 0.25s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||