feat: refactor Daily components and enhance UI integration

- Replaced `DailyCalendar` with a new `Calendar` component for improved functionality and consistency.
- Introduced `AlertBanner` to replace `DeadlineReminder`, providing a more flexible way to display urgent tasks.
- Updated `DailyAddForm` to use new options for task types, enhancing user experience when adding tasks.
- Removed unused state and components, streamlining the DailyPageClient for better performance and maintainability.
- Enhanced `DailySection` to utilize new `CheckboxItem` format for better integration with the UI.
- Cleaned up imports and improved overall structure for better readability.
This commit is contained in:
Julien Froidefond
2025-09-29 09:47:13 +02:00
parent 41fdd0c5b5
commit d45a04d347
18 changed files with 1583 additions and 654 deletions

View File

@@ -4,15 +4,111 @@
import { useState } from 'react';
import { Button } from '@/components/ui/Button';
import { Badge } from '@/components/ui/Badge';
import { Alert, AlertTitle, AlertDescription } from '@/components/ui/Alert';
import { Alert as ShadcnAlert, AlertTitle, AlertDescription } from '@/components/ui/Alert';
import { Input } from '@/components/ui/Input';
import { StyledCard } from '@/components/ui/StyledCard';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
import { StatCard, ProgressBar, ActionCard, TaskCard, MetricCard, ToggleButton, SearchInput, ControlPanel, ControlSection, ControlGroup, FilterSummary, FilterChip, ColumnHeader, EmptyState, DropZone } from '@/components/ui';
import { StatCard, ProgressBar, ActionCard, TaskCard, MetricCard, ToggleButton, SearchInput, ControlPanel, ControlSection, ControlGroup, FilterSummary, FilterChip, ColumnHeader, EmptyState, DropZone, Tabs, PriorityBadge, AchievementCard, ChallengeCard } from '@/components/ui';
import { CheckboxItem, CheckboxItemData } from '@/components/ui/CheckboxItem';
import { Calendar } from '@/components/ui/Calendar';
import { DailyAddForm } from '@/components/ui/DailyAddForm';
import { AlertBanner, AlertItem } from '@/components/ui/AlertBanner';
import { CollapsibleSection, CollapsibleItem } from '@/components/ui/CollapsibleSection';
import { Header } from '@/components/ui/Header';
import { TabItem } from '@/components/ui/Tabs';
import { AchievementData } from '@/components/ui/AchievementCard';
import { ChallengeData } from '@/components/ui/ChallengeCard';
export function UIShowcaseClient() {
const [inputValue, setInputValue] = useState('');
const [selectedDate, setSelectedDate] = useState(new Date());
const [checkboxItems, setCheckboxItems] = useState<CheckboxItemData[]>([
{ id: '1', text: 'Tâche complétée', isChecked: true, type: 'task' },
{ id: '2', text: 'Réunion importante', isChecked: false, type: 'meeting' },
{ id: '3', text: 'Tâche en cours', isChecked: false, type: 'task' }
]);
const [alertItems] = useState<AlertItem[]>([
{ id: '1', title: 'Tâche critique', icon: '🔴', urgency: 'critical', metadata: 'Dans 1 jour' },
{ id: '2', title: 'Réunion urgente', icon: '🟠', urgency: 'high', metadata: 'Dans 2 jours' },
{ id: '3', title: 'Rappel', icon: '🟡', urgency: 'medium', metadata: 'Dans 5 jours' }
]);
const [collapsibleItems] = useState<CollapsibleItem[]>([
{
id: '1',
title: 'Tâche en attente',
subtitle: '15 Jan 2024',
metadata: 'Il y a 2 jours',
isChecked: false,
icon: '📋',
actions: [
{ label: 'Déplacer', icon: '📅', onClick: () => console.log('Move'), variant: 'primary' },
{ label: 'Supprimer', icon: '🗑️', onClick: () => console.log('Delete'), variant: 'destructive' }
]
}
]);
// Données pour les composants Weekly Manager
const [activeTab, setActiveTab] = useState('tab1');
const tabItems: TabItem[] = [
{ id: 'tab1', label: 'Vue Executive', icon: '📝' },
{ id: 'tab2', label: 'Accomplissements', icon: '✅', count: 5 },
{ id: 'tab3', label: 'Enjeux', icon: '🎯', count: 3 },
{ id: 'tab4', label: 'Métriques', icon: '📊' }
];
const sampleAchievements: AchievementData[] = [
{
id: '1',
title: 'Refactoring de la page Daily',
description: 'Migration vers les composants UI génériques',
impact: 'high',
completedAt: new Date(),
tags: ['refactoring', 'ui'],
todosCount: 8
},
{
id: '2',
title: 'Implémentation du système de thèmes',
description: 'Ajout de 10 nouveaux thèmes avec CSS variables',
impact: 'medium',
completedAt: new Date(Date.now() - 86400000),
tags: ['themes', 'css'],
todosCount: 3
}
];
const sampleChallenges: ChallengeData[] = [
{
id: '1',
title: 'Migration vers Next.js 15',
description: 'Mise à jour majeure avec nouvelles fonctionnalités',
priority: 'high',
deadline: new Date(Date.now() + 7 * 86400000),
tags: ['migration', 'nextjs'],
todosCount: 12,
blockers: ['Tests à mettre à jour']
},
{
id: '2',
title: 'Optimisation des performances',
description: 'Réduction du temps de chargement',
priority: 'medium',
deadline: new Date(Date.now() + 14 * 86400000),
tags: ['performance', 'optimization'],
todosCount: 5
}
];
const sampleTags = [
{ id: '1', name: 'refactoring', color: '#3b82f6', usage: 5 },
{ id: '2', name: 'ui', color: '#10b981', usage: 8 },
{ id: '3', name: 'themes', color: '#8b5cf6', usage: 3 },
{ id: '4', name: 'css', color: '#f59e0b', usage: 4 },
{ id: '5', name: 'migration', color: '#ef4444', usage: 2 },
{ id: '6', name: 'nextjs', color: '#06b6d4', usage: 3 },
{ id: '7', name: 'performance', color: '#84cc16', usage: 6 },
{ id: '8', name: 'optimization', color: '#f97316', usage: 2 }
];
return (
<div className="min-h-screen bg-[var(--background)]">
@@ -93,40 +189,40 @@ export function UIShowcaseClient() {
</h2>
<div className="space-y-6">
<Alert variant="default">
<ShadcnAlert variant="default">
<AlertTitle>Information</AlertTitle>
<AlertDescription>
Ceci est une alerte par défaut avec des informations importantes.
</AlertDescription>
</Alert>
</ShadcnAlert>
<Alert variant="success">
<ShadcnAlert variant="success">
<AlertTitle>Succès</AlertTitle>
<AlertDescription>
Opération terminée avec succès ! Toutes les données ont é sauvegardées.
</AlertDescription>
</Alert>
</ShadcnAlert>
<Alert variant="destructive">
<ShadcnAlert variant="destructive">
<AlertTitle>Erreur</AlertTitle>
<AlertDescription>
Une erreur s'est produite lors du traitement de votre demande.
</AlertDescription>
</Alert>
</ShadcnAlert>
<Alert variant="warning">
<ShadcnAlert variant="warning">
<AlertTitle>Attention</AlertTitle>
<AlertDescription>
Veuillez vérifier vos informations avant de continuer.
</AlertDescription>
</Alert>
</ShadcnAlert>
<Alert variant="info">
<ShadcnAlert variant="info">
<AlertTitle>Conseil</AlertTitle>
<AlertDescription>
Astuce : Vous pouvez utiliser les raccourcis clavier pour naviguer plus rapidement.
</AlertDescription>
</Alert>
</ShadcnAlert>
</div>
</section>
@@ -322,19 +418,19 @@ export function UIShowcaseClient() {
<CardTitle>Notifications</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<Alert variant="success">
<ShadcnAlert variant="success">
<AlertTitle>Bienvenue !</AlertTitle>
<AlertDescription>
Votre compte a été créé avec succès.
</AlertDescription>
</Alert>
</ShadcnAlert>
<Alert variant="warning">
<ShadcnAlert variant="warning">
<AlertTitle>Mise à jour disponible</AlertTitle>
<AlertDescription>
Une nouvelle version de l'application est disponible.
</AlertDescription>
</Alert>
</ShadcnAlert>
<div className="flex gap-2">
<Button size="sm">Voir les détails</Button>
@@ -985,6 +1081,247 @@ export function UIShowcaseClient() {
</div>
</section>
{/* Daily Components Section */}
<section className="space-y-8">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] border-b border-[var(--border)] pb-3">
Daily Components
</h2>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* CheckboxItem */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">CheckboxItem</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
CheckboxItem - Élément de liste avec checkbox
</div>
<div className="space-y-2">
{checkboxItems.map((item) => (
<CheckboxItem
key={item.id}
item={item}
onToggle={async (id) => {
setCheckboxItems(prev =>
prev.map(item =>
item.id === id ? { ...item, isChecked: !item.isChecked } : item
)
);
}}
onUpdate={async (id, text) => {
setCheckboxItems(prev =>
prev.map(item =>
item.id === id ? { ...item, text } : item
)
);
}}
onDelete={async (id) => {
setCheckboxItems(prev => prev.filter(item => item.id !== id));
}}
saving={false}
/>
))}
</div>
</div>
</div>
</div>
{/* Calendar */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Calendar</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
Calendar - Calendrier avec dates marquées
</div>
<div className="max-w-sm">
<Calendar
currentDate={selectedDate}
onDateSelect={setSelectedDate}
markedDates={['2024-01-15', '2024-01-20', '2024-01-25']}
showTodayButton={true}
showLegend={true}
/>
</div>
</div>
</div>
</div>
{/* AddForm */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">DailyAddForm</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
DailyAddForm - Formulaire d'ajout avec options
</div>
<div className="max-w-md">
<DailyAddForm
onAdd={async (text, option) => {
console.log('Adding:', text, option);
const newItem: CheckboxItemData = {
id: Date.now().toString(),
text,
isChecked: false,
type: option as 'task' | 'meeting'
};
setCheckboxItems(prev => [...prev, newItem]);
}}
placeholder="Ajouter une tâche..."
options={[
{ value: 'task', label: 'Tâche', icon: '', color: 'green' },
{ value: 'meeting', label: 'Réunion', icon: '🗓', color: 'blue' }
]}
defaultOption="task"
/>
</div>
</div>
</div>
</div>
{/* Alert */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Alert</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
Alert - Alerte avec éléments urgents
</div>
<div className="max-w-md">
<AlertBanner
title="Tâches urgentes"
items={alertItems}
icon="⚠️"
variant="warning"
onItemClick={(item) => console.log('Clicked:', item)}
/>
</div>
</div>
</div>
</div>
{/* CollapsibleSection */}
<div className="space-y-6 lg:col-span-2">
<h3 className="text-lg font-medium text-[var(--foreground)]">CollapsibleSection</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
CollapsibleSection - Section repliable avec éléments
</div>
<div className="max-w-2xl">
<CollapsibleSection
title="Tâches en attente"
items={collapsibleItems}
icon="📋"
defaultCollapsed={false}
loading={false}
emptyMessage="Aucune tâche en attente"
onRefresh={() => console.log('Refresh')}
onItemToggle={(id) => console.log('Toggle:', id)}
/>
</div>
</div>
</div>
</div>
</div>
</section>
{/* Weekly Manager Components Section */}
<section className="space-y-8">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] border-b border-[var(--border)] pb-3">
Weekly Manager Components
</h2>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* Tabs */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Tabs</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
Tabs - Navigation par onglets
</div>
<Tabs
items={tabItems}
activeTab={activeTab}
onTabChange={setActiveTab}
/>
<div className="text-xs text-[var(--muted-foreground)]">
Onglet actif: {activeTab}
</div>
</div>
</div>
</div>
{/* PriorityBadge */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">PriorityBadge</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
PriorityBadge - Badge de priorité
</div>
<div className="flex flex-wrap gap-2">
<PriorityBadge priority="high" />
<PriorityBadge priority="medium" />
<PriorityBadge priority="low" />
</div>
</div>
</div>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* AchievementCard */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">AchievementCard</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
AchievementCard - Carte d'accomplissement
</div>
<div className="space-y-3">
{sampleAchievements.map((achievement, index) => (
<AchievementCard
key={achievement.id}
achievement={achievement}
availableTags={sampleTags}
index={index}
showDescription={true}
maxTags={2}
/>
))}
</div>
</div>
</div>
</div>
{/* ChallengeCard */}
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">ChallengeCard</h3>
<div className="space-y-4">
<div className="space-y-2">
<div className="text-xs font-mono text-[var(--muted-foreground)] bg-[var(--card)] px-2 py-1 rounded">
ChallengeCard - Carte de défi
</div>
<div className="space-y-3">
{sampleChallenges.map((challenge, index) => (
<ChallengeCard
key={challenge.id}
challenge={challenge}
availableTags={sampleTags}
index={index}
showDescription={true}
maxTags={2}
/>
))}
</div>
</div>
</div>
</div>
</div>
</section>
{/* Footer */}
<div className="text-center pt-8 border-t border-[var(--border)]">
<p className="text-[var(--muted-foreground)]">