feat: update settings page and theme context for user preferences
- Replaced `SettingsPageClient` with `SettingsIndexPageClient` to fetch and display user preferences on the settings page. - Integrated `userPreferencesService` to retrieve all preferences asynchronously, enhancing data handling. - Refactored theme management in `ThemeContext` to use `updateViewPreferences` for saving theme changes, improving error handling and user feedback. - Marked the task for creating dedicated config sub-pages as complete in TODO.md.
This commit is contained in:
3
TODO.md
3
TODO.md
@@ -142,13 +142,12 @@
|
|||||||
- [x] Graphiques avec Recharts (tendances, vélocité, distribution)
|
- [x] Graphiques avec Recharts (tendances, vélocité, distribution)
|
||||||
- [x] Composants de graphiques (CompletionTrend, Velocity, Priority, Weekly)
|
- [x] Composants de graphiques (CompletionTrend, Velocity, Priority, Weekly)
|
||||||
- [x] Insights automatiques et métriques visuelles
|
- [x] Insights automatiques et métriques visuelles
|
||||||
- [ ] Export des données en CSV/JSON
|
|
||||||
|
|
||||||
## Autre Todo
|
## Autre Todo
|
||||||
- [x] Avoir un bouton pour réduire/agrandir la font des taches dans les kanban (swimlane et classique)
|
- [x] Avoir un bouton pour réduire/agrandir la font des taches dans les kanban (swimlane et classique)
|
||||||
- [x] Refactorer les couleurs des priorités dans un seul endroit
|
- [x] Refactorer les couleurs des priorités dans un seul endroit
|
||||||
- [x] Settings synchro Jira : ajouter une liste de projet à ignorer, doit etre pris en compte par le service bien sur
|
- [x] Settings synchro Jira : ajouter une liste de projet à ignorer, doit etre pris en compte par le service bien sur
|
||||||
- [ ] faire des pages à part entière dpour les sous-pages de la page config + SSR
|
- [x] faire des pages à part entière pour les sous-pages de la page config + SSR
|
||||||
- [ ] Système de sauvegarde automatique base de données
|
- [ ] Système de sauvegarde automatique base de données
|
||||||
- [ ] Sauvegarde automatique toutes les 6 heures (configurable)
|
- [ ] Sauvegarde automatique toutes les 6 heures (configurable)
|
||||||
- [ ] Configuration dans les paramètres (intervalle de temps + bouton sauvegarde manuelle)
|
- [ ] Configuration dans les paramètres (intervalle de temps + bouton sauvegarde manuelle)
|
||||||
|
|||||||
224
components/settings/AdvancedSettingsPageClient.tsx
Normal file
224
components/settings/AdvancedSettingsPageClient.tsx
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { UserPreferences } from '@/lib/types';
|
||||||
|
import { Header } from '@/components/ui/Header';
|
||||||
|
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
|
||||||
|
import { UserPreferencesProvider } from '@/contexts/UserPreferencesContext';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
interface AdvancedSettingsPageClientProps {
|
||||||
|
initialPreferences: UserPreferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AdvancedSettingsPageClient({ initialPreferences }: AdvancedSettingsPageClientProps) {
|
||||||
|
return (
|
||||||
|
<UserPreferencesProvider initialPreferences={initialPreferences}>
|
||||||
|
<div className="min-h-screen bg-[var(--background)]">
|
||||||
|
<Header
|
||||||
|
title="TowerControl"
|
||||||
|
subtitle="Paramètres avancés"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="container mx-auto px-4 py-4">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
{/* Breadcrumb */}
|
||||||
|
<div className="mb-4 text-sm">
|
||||||
|
<Link href="/settings" className="text-[var(--muted-foreground)] hover:text-[var(--primary)]">
|
||||||
|
Paramètres
|
||||||
|
</Link>
|
||||||
|
<span className="mx-2 text-[var(--muted-foreground)]">/</span>
|
||||||
|
<span className="text-[var(--foreground)]">Avancé</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Page Header */}
|
||||||
|
<div className="mb-6">
|
||||||
|
<h1 className="text-2xl font-mono font-bold text-[var(--foreground)] mb-2">
|
||||||
|
🛠️ Paramètres avancés
|
||||||
|
</h1>
|
||||||
|
<p className="text-[var(--muted-foreground)]">
|
||||||
|
Configuration système, sauvegarde et outils de développement
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-6">
|
||||||
|
{/* Sauvegarde et données */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<h2 className="text-lg font-semibold">💾 Sauvegarde et données</h2>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Gestion des sauvegardes automatiques et manuelles
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<h3 className="font-medium mb-2">Sauvegarde automatique</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)] mb-2">
|
||||||
|
Sauvegarde toutes les 6 heures (configurable)
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-[var(--muted-foreground)]">
|
||||||
|
Prochaine sauvegarde: dans 3h 42min
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<h3 className="font-medium mb-2">Sauvegardes disponibles</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)] mb-2">
|
||||||
|
5 sauvegardes conservées
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-[var(--muted-foreground)]">
|
||||||
|
Dernière: il y a 2h 18min
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-2 pt-2">
|
||||||
|
<button className="px-3 py-1.5 bg-[var(--primary)] text-[var(--primary-foreground)] rounded text-sm font-medium">
|
||||||
|
Créer une sauvegarde
|
||||||
|
</button>
|
||||||
|
<button className="px-3 py-1.5 bg-[var(--card)] text-[var(--foreground)] border border-[var(--border)] rounded text-sm font-medium">
|
||||||
|
Gérer les sauvegardes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Base de données */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<h2 className="text-lg font-semibold">🗄️ Base de données</h2>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Informations et maintenance de la base de données
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<h3 className="font-medium mb-1">Tâches</h3>
|
||||||
|
<p className="text-2xl font-bold text-[var(--primary)]">247</p>
|
||||||
|
<p className="text-xs text-[var(--muted-foreground)]">entrées</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<h3 className="font-medium mb-1">Tags</h3>
|
||||||
|
<p className="text-2xl font-bold text-[var(--primary)]">18</p>
|
||||||
|
<p className="text-xs text-[var(--muted-foreground)]">entrées</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<h3 className="font-medium mb-1">Taille DB</h3>
|
||||||
|
<p className="text-2xl font-bold text-[var(--primary)]">2.4</p>
|
||||||
|
<p className="text-xs text-[var(--muted-foreground)]">MB</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Export / Import */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<h2 className="text-lg font-semibold">📤 Export / Import</h2>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Sauvegarde et restauration des données
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<h3 className="font-medium mb-2">Export des données</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)] mb-3">
|
||||||
|
Exporter toutes les données au format JSON
|
||||||
|
</p>
|
||||||
|
<button className="px-3 py-1.5 bg-[var(--primary)] text-[var(--primary-foreground)] rounded text-sm">
|
||||||
|
Télécharger export
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<h3 className="font-medium mb-2">Import des données</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)] mb-3">
|
||||||
|
Restaurer des données depuis un fichier JSON
|
||||||
|
</p>
|
||||||
|
<button className="px-3 py-1.5 bg-[var(--card)] text-[var(--foreground)] border border-[var(--border)] rounded text-sm">
|
||||||
|
Choisir fichier
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Logs et debug */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<h2 className="text-lg font-semibold">🐛 Debug et logs</h2>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Outils de diagnostic et de résolution de problèmes
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<h3 className="font-medium mb-2">Logs système</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)] mb-3">
|
||||||
|
Consultation des logs d'erreur et d'activité
|
||||||
|
</p>
|
||||||
|
<button className="px-3 py-1.5 bg-[var(--card)] text-[var(--foreground)] border border-[var(--border)] rounded text-sm">
|
||||||
|
Voir les logs
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<h3 className="font-medium mb-2">Mode debug</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)] mb-3">
|
||||||
|
Activer les informations de debug détaillées
|
||||||
|
</p>
|
||||||
|
<button className="px-3 py-1.5 bg-[var(--card)] text-[var(--foreground)] border border-[var(--border)] rounded text-sm">
|
||||||
|
Activer debug
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Zone dangereuse */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<h2 className="text-lg font-semibold text-[var(--destructive)]">⚠️ Zone dangereuse</h2>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Actions irréversibles - à utiliser avec précaution
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<div className="p-4 bg-[var(--destructive)]/5 border border-[var(--destructive)]/20 rounded">
|
||||||
|
<h3 className="font-medium mb-2 text-[var(--destructive)]">Réinitialisation complète</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)] mb-3">
|
||||||
|
Supprime toutes les données (tâches, tags, préférences)
|
||||||
|
</p>
|
||||||
|
<button className="px-3 py-1.5 bg-[var(--destructive)] text-[var(--destructive-foreground)] rounded text-sm">
|
||||||
|
Réinitialiser
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Note développement futur */}
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="p-4 bg-[var(--warning)]/10 border border-[var(--warning)]/20 rounded">
|
||||||
|
<p className="text-sm text-[var(--warning)] font-medium mb-2">
|
||||||
|
🚧 Fonctionnalités en développement
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-[var(--muted-foreground)]">
|
||||||
|
La plupart des fonctions avancées seront implémentées dans les prochaines versions.
|
||||||
|
Cette page sert de prévisualisation de l'interface à venir.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UserPreferencesProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
64
components/settings/GeneralSettingsPageClient.tsx
Normal file
64
components/settings/GeneralSettingsPageClient.tsx
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { UserPreferences } from '@/lib/types';
|
||||||
|
import { Header } from '@/components/ui/Header';
|
||||||
|
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
|
||||||
|
import { UserPreferencesProvider } from '@/contexts/UserPreferencesContext';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
interface GeneralSettingsPageClientProps {
|
||||||
|
initialPreferences: UserPreferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GeneralSettingsPageClient({ initialPreferences }: GeneralSettingsPageClientProps) {
|
||||||
|
return (
|
||||||
|
<UserPreferencesProvider initialPreferences={initialPreferences}>
|
||||||
|
<div className="min-h-screen bg-[var(--background)]">
|
||||||
|
<Header
|
||||||
|
title="TowerControl"
|
||||||
|
subtitle="Paramètres généraux"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="container mx-auto px-4 py-4">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
{/* Breadcrumb */}
|
||||||
|
<div className="mb-4 text-sm">
|
||||||
|
<Link href="/settings" className="text-[var(--muted-foreground)] hover:text-[var(--primary)]">
|
||||||
|
Paramètres
|
||||||
|
</Link>
|
||||||
|
<span className="mx-2 text-[var(--muted-foreground)]">/</span>
|
||||||
|
<span className="text-[var(--foreground)]">Général</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Page Header */}
|
||||||
|
<div className="mb-6">
|
||||||
|
<h1 className="text-2xl font-mono font-bold text-[var(--foreground)] mb-2">
|
||||||
|
⚙️ Paramètres généraux
|
||||||
|
</h1>
|
||||||
|
<p className="text-[var(--muted-foreground)]">
|
||||||
|
Configuration des préférences de l'interface et du comportement général
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-6">
|
||||||
|
{/* Note développement futur */}
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="p-4 bg-[var(--warning)]/10 border border-[var(--warning)]/20 rounded">
|
||||||
|
<p className="text-sm text-[var(--warning)] font-medium mb-2">
|
||||||
|
🚧 Interface de configuration en développement
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-[var(--muted-foreground)]">
|
||||||
|
Les contrôles interactifs pour modifier ces préférences seront disponibles dans une prochaine version.
|
||||||
|
Pour l'instant, les préférences sont modifiables via les boutons de l'interface principale.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UserPreferencesProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
152
components/settings/IntegrationsSettingsPageClient.tsx
Normal file
152
components/settings/IntegrationsSettingsPageClient.tsx
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { UserPreferences, JiraConfig } from '@/lib/types';
|
||||||
|
import { Header } from '@/components/ui/Header';
|
||||||
|
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
|
||||||
|
import { JiraConfigForm } from '@/components/settings/JiraConfigForm';
|
||||||
|
import { JiraSync } from '@/components/jira/JiraSync';
|
||||||
|
import { JiraLogs } from '@/components/jira/JiraLogs';
|
||||||
|
import { UserPreferencesProvider } from '@/contexts/UserPreferencesContext';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
interface IntegrationsSettingsPageClientProps {
|
||||||
|
initialPreferences: UserPreferences;
|
||||||
|
initialJiraConfig: JiraConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function IntegrationsSettingsPageClient({
|
||||||
|
initialPreferences,
|
||||||
|
initialJiraConfig
|
||||||
|
}: IntegrationsSettingsPageClientProps) {
|
||||||
|
return (
|
||||||
|
<UserPreferencesProvider initialPreferences={initialPreferences}>
|
||||||
|
<div className="min-h-screen bg-[var(--background)]">
|
||||||
|
<Header
|
||||||
|
title="TowerControl"
|
||||||
|
subtitle="Intégrations externes"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="container mx-auto px-4 py-4">
|
||||||
|
<div className="max-w-6xl mx-auto">
|
||||||
|
{/* Breadcrumb */}
|
||||||
|
<div className="mb-4 text-sm">
|
||||||
|
<Link href="/settings" className="text-[var(--muted-foreground)] hover:text-[var(--primary)]">
|
||||||
|
Paramètres
|
||||||
|
</Link>
|
||||||
|
<span className="mx-2 text-[var(--muted-foreground)]">/</span>
|
||||||
|
<span className="text-[var(--foreground)]">Intégrations</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Page Header */}
|
||||||
|
<div className="mb-6">
|
||||||
|
<h1 className="text-2xl font-mono font-bold text-[var(--foreground)] mb-2">
|
||||||
|
🔌 Intégrations externes
|
||||||
|
</h1>
|
||||||
|
<p className="text-[var(--muted-foreground)]">
|
||||||
|
Configuration des intégrations avec les outils externes
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Layout en 2 colonnes pour optimiser l'espace */}
|
||||||
|
<div className="grid grid-cols-1 xl:grid-cols-3 gap-6">
|
||||||
|
|
||||||
|
{/* Colonne principale: Configuration Jira */}
|
||||||
|
<div className="xl:col-span-2 space-y-6">
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<h2 className="text-xl font-semibold flex items-center gap-2">
|
||||||
|
<span className="text-blue-600">🏢</span>
|
||||||
|
Jira Cloud
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Synchronisation automatique des tickets Jira vers TowerControl
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<JiraConfigForm />
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Futures intégrations */}
|
||||||
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<h2 className="text-xl font-semibold">Autres intégrations</h2>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Intégrations prévues pour les prochaines versions
|
||||||
|
</p>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
<span className="text-lg">📧</span>
|
||||||
|
<h3 className="font-medium">Slack/Teams</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Notifications et commandes via chat
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
<span className="text-lg">🐙</span>
|
||||||
|
<h3 className="font-medium">GitHub/GitLab</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Synchronisation des issues et PR
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
<span className="text-lg">📊</span>
|
||||||
|
<h3 className="font-medium">Calendriers</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Google Calendar, Outlook, etc.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-4 bg-[var(--card)] rounded border border-dashed border-[var(--border)]">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
<span className="text-lg">⏱️</span>
|
||||||
|
<h3 className="font-medium">Time tracking</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Toggl, RescueTime, etc.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Colonne latérale: Actions et Logs Jira */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
{initialJiraConfig?.enabled && (
|
||||||
|
<>
|
||||||
|
<JiraSync />
|
||||||
|
<JiraLogs />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!initialJiraConfig?.enabled && (
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="text-center py-6">
|
||||||
|
<span className="text-4xl mb-4 block">🔧</span>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Configurez Jira pour accéder aux outils de synchronisation
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UserPreferencesProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
220
components/settings/SettingsIndexPageClient.tsx
Normal file
220
components/settings/SettingsIndexPageClient.tsx
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { UserPreferences } from '@/lib/types';
|
||||||
|
import { Header } from '@/components/ui/Header';
|
||||||
|
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
|
||||||
|
import { UserPreferencesProvider } from '@/contexts/UserPreferencesContext';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
interface SettingsIndexPageClientProps {
|
||||||
|
initialPreferences: UserPreferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SettingsIndexPageClient({ initialPreferences }: SettingsIndexPageClientProps) {
|
||||||
|
const settingsPages = [
|
||||||
|
{
|
||||||
|
href: '/settings/general',
|
||||||
|
icon: '⚙️',
|
||||||
|
title: 'Paramètres généraux',
|
||||||
|
description: 'Interface, thème, préférences d\'affichage',
|
||||||
|
status: 'En développement'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: '/settings/integrations',
|
||||||
|
icon: '🔌',
|
||||||
|
title: 'Intégrations',
|
||||||
|
description: 'Jira, GitHub, Slack et autres services externes',
|
||||||
|
status: 'Fonctionnel'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: '/settings/advanced',
|
||||||
|
icon: '🛠️',
|
||||||
|
title: 'Paramètres avancés',
|
||||||
|
description: 'Sauvegarde, logs, debug et maintenance',
|
||||||
|
status: 'Prochainement'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<UserPreferencesProvider initialPreferences={initialPreferences}>
|
||||||
|
<div className="min-h-screen bg-[var(--background)]">
|
||||||
|
<Header
|
||||||
|
title="TowerControl"
|
||||||
|
subtitle="Configuration & Paramètres"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="container mx-auto px-4 py-4">
|
||||||
|
<div className="max-w-4xl mx-auto">
|
||||||
|
{/* Page Header */}
|
||||||
|
<div className="mb-8">
|
||||||
|
<h1 className="text-3xl font-mono font-bold text-[var(--foreground)] mb-3">
|
||||||
|
Paramètres
|
||||||
|
</h1>
|
||||||
|
<p className="text-[var(--muted-foreground)] text-lg">
|
||||||
|
Configuration de TowerControl et de ses intégrations
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Quick Stats */}
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<span className="text-2xl">🎨</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">Thème actuel</p>
|
||||||
|
<p className="font-medium capitalize">{initialPreferences.viewPreferences.theme}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<span className="text-2xl">🔌</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">Jira</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{initialPreferences.jiraConfig.enabled ? 'Configuré' : 'Non configuré'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<span className="text-2xl">📏</span>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">Taille police</p>
|
||||||
|
<p className="font-medium capitalize">{initialPreferences.viewPreferences.fontSize}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Settings Sections */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h2 className="text-xl font-semibold text-[var(--foreground)] mb-4">
|
||||||
|
Sections de configuration
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-1 gap-4">
|
||||||
|
{settingsPages.map((page) => (
|
||||||
|
<Link key={page.href} href={page.href}>
|
||||||
|
<Card className="transition-all hover:shadow-md hover:border-[var(--primary)]/30 cursor-pointer">
|
||||||
|
<CardContent className="p-6">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div className="flex items-start gap-4">
|
||||||
|
<span className="text-3xl">{page.icon}</span>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h3 className="text-lg font-semibold text-[var(--foreground)] mb-1">
|
||||||
|
{page.title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-[var(--muted-foreground)] mb-2">
|
||||||
|
{page.description}
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className={`px-2 py-1 rounded text-xs font-medium ${
|
||||||
|
page.status === 'Fonctionnel'
|
||||||
|
? 'bg-[var(--success)]/20 text-[var(--success)]'
|
||||||
|
: page.status === 'En développement'
|
||||||
|
? 'bg-[var(--warning)]/20 text-[var(--warning)]'
|
||||||
|
: 'bg-[var(--muted)]/20 text-[var(--muted-foreground)]'
|
||||||
|
}`}>
|
||||||
|
{page.status}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<svg
|
||||||
|
className="w-5 h-5 text-[var(--muted-foreground)]"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Quick Actions */}
|
||||||
|
<div className="mt-8">
|
||||||
|
<h2 className="text-xl font-semibold text-[var(--foreground)] mb-4">
|
||||||
|
Actions rapides
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-medium mb-1">Sauvegarde manuelle</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Créer une sauvegarde des données
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button className="px-3 py-1.5 bg-[var(--primary)] text-[var(--primary-foreground)] rounded text-sm">
|
||||||
|
Sauvegarder
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardContent className="p-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-medium mb-1">Test Jira</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
|
Tester la connexion Jira
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
className="px-3 py-1.5 bg-[var(--card)] text-[var(--foreground)] border border-[var(--border)] rounded text-sm"
|
||||||
|
disabled={!initialPreferences.jiraConfig.enabled}
|
||||||
|
>
|
||||||
|
Tester
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* System Info */}
|
||||||
|
<Card className="mt-8">
|
||||||
|
<CardHeader>
|
||||||
|
<h2 className="text-lg font-semibold">ℹ️ Informations système</h2>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm">
|
||||||
|
<div>
|
||||||
|
<p className="text-[var(--muted-foreground)]">Version</p>
|
||||||
|
<p className="font-medium">TowerControl v1.0.0</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-[var(--muted-foreground)]">Dernière maj</p>
|
||||||
|
<p className="font-medium">Il y a 2 jours</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-[var(--muted-foreground)]">Env</p>
|
||||||
|
<p className="font-medium">Development</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UserPreferencesProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
12
src/app/settings/advanced/page.tsx
Normal file
12
src/app/settings/advanced/page.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { userPreferencesService } from '@/services/user-preferences';
|
||||||
|
import { AdvancedSettingsPageClient } from '@/components/settings/AdvancedSettingsPageClient';
|
||||||
|
|
||||||
|
// Force dynamic rendering for real-time data
|
||||||
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
|
export default async function AdvancedSettingsPage() {
|
||||||
|
// Fetch data server-side
|
||||||
|
const preferences = await userPreferencesService.getAllPreferences();
|
||||||
|
|
||||||
|
return <AdvancedSettingsPageClient initialPreferences={preferences} />;
|
||||||
|
}
|
||||||
12
src/app/settings/general/page.tsx
Normal file
12
src/app/settings/general/page.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { userPreferencesService } from '@/services/user-preferences';
|
||||||
|
import { GeneralSettingsPageClient } from '@/components/settings/GeneralSettingsPageClient';
|
||||||
|
|
||||||
|
// Force dynamic rendering for real-time data
|
||||||
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
|
export default async function GeneralSettingsPage() {
|
||||||
|
// Fetch data server-side
|
||||||
|
const preferences = await userPreferencesService.getAllPreferences();
|
||||||
|
|
||||||
|
return <GeneralSettingsPageClient initialPreferences={preferences} />;
|
||||||
|
}
|
||||||
18
src/app/settings/integrations/page.tsx
Normal file
18
src/app/settings/integrations/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { userPreferencesService } from '@/services/user-preferences';
|
||||||
|
import { IntegrationsSettingsPageClient } from '@/components/settings/IntegrationsSettingsPageClient';
|
||||||
|
|
||||||
|
// Force dynamic rendering for real-time data
|
||||||
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
|
export default async function IntegrationsSettingsPage() {
|
||||||
|
// Fetch data server-side
|
||||||
|
const preferences = await userPreferencesService.getAllPreferences();
|
||||||
|
const jiraConfig = await userPreferencesService.getJiraConfig();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IntegrationsSettingsPageClient
|
||||||
|
initialPreferences={preferences}
|
||||||
|
initialJiraConfig={jiraConfig}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
import { SettingsPageClient } from '@/components/settings/SettingsPageClient';
|
import { userPreferencesService } from '@/services/user-preferences';
|
||||||
|
import { SettingsIndexPageClient } from '@/components/settings/SettingsIndexPageClient';
|
||||||
|
|
||||||
// Force dynamic rendering (no static generation)
|
// Force dynamic rendering (no static generation)
|
||||||
export const dynamic = 'force-dynamic';
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
export default async function SettingsPage() {
|
export default async function SettingsPage() {
|
||||||
return <SettingsPageClient />;
|
// Fetch basic data for the index page
|
||||||
|
const preferences = await userPreferencesService.getAllPreferences();
|
||||||
|
|
||||||
|
return <SettingsIndexPageClient initialPreferences={preferences} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { createContext, useContext, useEffect, useState, ReactNode } from 'react';
|
import { createContext, useContext, useEffect, useState, ReactNode } from 'react';
|
||||||
import { userPreferencesClient } from '@/clients/user-preferences-client';
|
import { updateViewPreferences } from '@/actions/preferences';
|
||||||
|
|
||||||
type Theme = 'light' | 'dark';
|
type Theme = 'light' | 'dark';
|
||||||
|
|
||||||
@@ -38,11 +38,14 @@ export function ThemeProvider({ children, initialTheme = 'dark' }: ThemeProvider
|
|||||||
const newTheme = theme === 'dark' ? 'light' : 'dark';
|
const newTheme = theme === 'dark' ? 'light' : 'dark';
|
||||||
setThemeState(newTheme);
|
setThemeState(newTheme);
|
||||||
|
|
||||||
// Sauvegarder en base de façon asynchrone via le client
|
// Sauvegarder en base de façon asynchrone via server action
|
||||||
try {
|
try {
|
||||||
await userPreferencesClient.updateViewPreferences({
|
const result = await updateViewPreferences({
|
||||||
theme: newTheme
|
theme: newTheme
|
||||||
});
|
});
|
||||||
|
if (!result.success) {
|
||||||
|
console.error('Erreur lors de la sauvegarde du thème:', result.error);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de la sauvegarde du thème:', error);
|
console.error('Erreur lors de la sauvegarde du thème:', error);
|
||||||
}
|
}
|
||||||
@@ -51,11 +54,14 @@ export function ThemeProvider({ children, initialTheme = 'dark' }: ThemeProvider
|
|||||||
const setTheme = async (newTheme: Theme) => {
|
const setTheme = async (newTheme: Theme) => {
|
||||||
setThemeState(newTheme);
|
setThemeState(newTheme);
|
||||||
|
|
||||||
// Sauvegarder en base de façon asynchrone via le client
|
// Sauvegarder en base de façon asynchrone via server action
|
||||||
try {
|
try {
|
||||||
await userPreferencesClient.updateViewPreferences({
|
const result = await updateViewPreferences({
|
||||||
theme: newTheme
|
theme: newTheme
|
||||||
});
|
});
|
||||||
|
if (!result.success) {
|
||||||
|
console.error('Erreur lors de la sauvegarde du thème:', result.error);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erreur lors de la sauvegarde du thème:', error);
|
console.error('Erreur lors de la sauvegarde du thème:', error);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user