Files
FanKarr/src/components/ToastContainer.vue
T
MasutaYunikon 9780aee40d feat!: refonte complète du frontend et amélioration des logs serveur
BREAKING CHANGE: nouvelle architecture frontend avec layout sidebar, système de thèmes et routes restructurées

### Frontend
- nouveau layout global `AppLayout.vue` avec sidebar de navigation inspirée Radarr/Sonarr
- sidebar configurable via un objet `NavItem[]` avec support parents/enfants cliquables
- 3 thèmes CSS (Indigo Électrique, Crimson Night, Teal Froid) persistés via localStorage
- switcher de thème en bas de sidebar avec pastilles colorées
- logo FanKarr cliquable, bouton déconnexion discret dans le header sidebar
- badge animé sur "Activité" affichant le nombre de téléchargements en cours
- migration complète vers Tailwind v4 avec variables CSS `@theme`
- classes utilitaires globales : `btn-primary`, `btn-secondary`, `settings-card`, `settings-input`

### Vues
- `SeriesView` : barre colorée en bas des affiches (vert/bleu/orange), dropdown filtres, boutons taille S/M/L/XL persistés
- `SerieView` : bouton état unique par épisode (↓/⟳/✓/✗), badges simplifiés, toast via `useToast` global
- `ActivityView` : onglets pill, stats, toggle "masquer importés", polling silencieux
- `DashboardView` : stats catalogue/importées/en cours/erreurs, torrents actifs, derniers imports
- `SettingsView` découpée en 3 vues indépendantes : `DownloadClientView`, `MediaManagementView`, `CatalogueView`
- `LogsView` déplacée dans `src/views/settings/`
- `AuthView` : migré au système de thème

### Composants
- `SidebarNavItem` : support badge, chevron masqué si badge présent
- `SettingsToggle` : composant réutilisable `v-model`
- `FolderPicker` : migré au thème, `Teleport` intégré
- `ToastContainer` : déplacé en bas droite, groupement des toasts similaires avec badge count

### Router
- `AppLayout` comme layout racine pour toutes les routes protégées
- `/auth` reste hors layout
- redirections `/` → `/series`, `/downloads` → `/activity`
- `SettingsLayout` avec titre dynamique par route
- scroll géré sur `<main id="main-scroll">` dans `AppLayout`

### Stores & composables
- nouveau store `downloads` partagé pour le badge sidebar
- `usePosterSize` : taille des affiches persistée en localStorage
- `useToast` : groupement des toasts du même type, timer reset au lieu d'empilement

### Serveur
- logs structurés via `logger` dans `auth.ts`, `organize.ts`, `organize-worker.ts`, `torrent-clients/index.ts`, `qbittorrent.ts`, `index.ts`
- suppression des `console.log/error/warn` en faveur de `logger.info/warn/error/debug`
- messages worker routés vers `logger` via `organize.ts`
- logs `debug` pour les événements verbeux (healthcheck, skip, worker terminé)
2026-03-27 07:02:31 +01:00

56 lines
2.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
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.
<template>
<Teleport to="body">
<div class="fixed bottom-4 right-4 z-50 flex flex-col gap-2">
<TransitionGroup name="toast">
<div
v-for="t in toasts"
:key="t.id"
@click="remove(t.id)"
class="flex items-center gap-3 px-4 py-3 rounded-xl border text-sm cursor-pointer min-w-64 max-w-sm"
:class="{
'bg-card border-green-500/30 text-green-400' : t.type === 'success',
'bg-card border-red-500/30 text-red-400' : t.type === 'error',
'bg-card border-accent/30 text-accent' : t.type === 'info',
}"
>
<svg v-if="t.type === 'success'" width="14" height="14" viewBox="0 0 14 14" stroke="currentColor" stroke-width="2" fill="none" class="shrink-0">
<polyline points="2 7 5.5 10.5 12 3"/>
</svg>
<svg v-else-if="t.type === 'error'" width="14" height="14" viewBox="0 0 14 14" stroke="currentColor" stroke-width="2" fill="none" class="shrink-0">
<line x1="3" y1="3" x2="11" y2="11"/><line x1="11" y1="3" x2="3" y2="11"/>
</svg>
<svg v-else width="14" height="14" viewBox="0 0 14 14" stroke="currentColor" stroke-width="2" fill="none" class="shrink-0">
<circle cx="7" cy="7" r="5"/><line x1="7" y1="5" x2="7" y2="7.5"/><circle cx="7" cy="9.5" r="0.5" fill="currentColor"/>
</svg>
<span class="flex-1 text-xs leading-snug">{{ t.message }}</span>
<!-- Badge count si groupé -->
<span
v-if="t.count && t.count > 1"
class="shrink-0 text-[10px] font-medium px-1.5 py-0.5 rounded-full"
:class="{
'bg-green-500/20 text-green-400' : t.type === 'success',
'bg-red-500/20 text-red-400' : t.type === 'error',
'bg-accent/20 text-accent' : t.type === 'info',
}"
>
×{{ t.count }}
</span>
</div>
</TransitionGroup>
</div>
</Teleport>
</template>
<script setup lang="ts">
import { useToast } from '@/composables/useToast'
const { toasts, remove } = useToast()
</script>
<style scoped>
.toast-enter-active { transition: all 0.2s ease; }
.toast-leave-active { transition: all 0.15s ease; }
.toast-enter-from { opacity: 0; transform: translateY(8px) scale(0.97); }
.toast-leave-to { opacity: 0; transform: translateY(4px) scale(0.97); }
</style>