Files
FanKarr/src/composables/useToast.ts
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

54 lines
1.5 KiB
TypeScript

import { ref } from 'vue'
interface Toast {
id : number
message : string
type : 'success' | 'error' | 'info'
count : number
timer : ReturnType<typeof setTimeout>
}
const toasts = ref<Toast[]>([])
let nextId = 0
const DURATION = 3500
const GROUP_WINDOW = 800 // ms — toasts du même type dans cette fenêtre sont groupés
function add(message: string, type: Toast['type'] = 'info') {
const now = Date.now()
// Cherche un toast récent du même type à grouper
const existing = toasts.value.find(t => t.type === type)
if (existing) {
// Grouper — incrémenter le count et mettre à jour le message
clearTimeout(existing.timer)
existing.count++
existing.message = buildGroupMessage(type, existing.count)
existing.timer = setTimeout(() => remove(existing.id), DURATION)
return
}
// Nouveau toast
const id = nextId++
const timer = setTimeout(() => remove(id), DURATION)
toasts.value.push({ id, message, type, count: 1, timer })
}
function buildGroupMessage(type: Toast['type'], count: number): string {
if (type === 'success') return `${count} opérations réussies`
if (type === 'error') return `${count} erreurs`
return `${count} notifications`
}
function remove(id: number) {
const i = toasts.value.findIndex(t => t.id === id)
if (i !== -1) {
clearTimeout(toasts.value[i].timer)
toasts.value.splice(i, 1)
}
}
export function useToast() {
return { toasts, add, remove }
}