style: refactor layout and enhance card UI in WeeklyManager
- Updated `WeeklyManagerPage` layout to use a `<main>` tag for better semantic structure. - Refined `ManagerWeeklySummary` component to display narrative and metrics side by side, improving visual organization. - Enhanced `AchievementCard` and `ChallengeCard` styles for better color differentiation and user experience. - Adjusted spacing and grid layouts for improved responsiveness and clarity in the UI.
This commit is contained in:
@@ -19,15 +19,13 @@ export default async function WeeklyManagerPage() {
|
|||||||
<div className="min-h-screen bg-[var(--background)]">
|
<div className="min-h-screen bg-[var(--background)]">
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<div className="container mx-auto px-4 py-8">
|
<main className="container mx-auto px-6 py-8">
|
||||||
<div className="max-w-6xl mx-auto">
|
<WeeklyManagerPageClient
|
||||||
<WeeklyManagerPageClient
|
initialSummary={summary}
|
||||||
initialSummary={summary}
|
initialTasks={initialTasks}
|
||||||
initialTasks={initialTasks}
|
initialTags={initialTags}
|
||||||
initialTags={initialTags}
|
/>
|
||||||
/>
|
</main>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useState } from 'react';
|
|||||||
import { ManagerSummary } from '@/services/analytics/manager-summary';
|
import { ManagerSummary } from '@/services/analytics/manager-summary';
|
||||||
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
|
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
|
||||||
import { Button } from '@/components/ui/Button';
|
import { Button } from '@/components/ui/Button';
|
||||||
import { MetricCard } from '@/components/ui/MetricCard';
|
|
||||||
import { Tabs, TabItem } from '@/components/ui/Tabs';
|
import { Tabs, TabItem } from '@/components/ui/Tabs';
|
||||||
import { AchievementCard } from '@/components/ui/AchievementCard';
|
import { AchievementCard } from '@/components/ui/AchievementCard';
|
||||||
import { ChallengeCard } from '@/components/ui/ChallengeCard';
|
import { ChallengeCard } from '@/components/ui/ChallengeCard';
|
||||||
@@ -73,76 +72,80 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
{/* Vue Executive / Narrative */}
|
{/* Vue Executive / Narrative */}
|
||||||
{activeView === 'narrative' && (
|
{activeView === 'narrative' && (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Résumé narratif */}
|
{/* Section principale : Résumé + Métriques côte à côte */}
|
||||||
<Card>
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
<CardHeader>
|
{/* Résumé narratif */}
|
||||||
<h2 className="text-lg font-semibold flex items-center gap-2">
|
<Card variant="elevated">
|
||||||
📊 Résumé de la semaine
|
<CardHeader>
|
||||||
</h2>
|
<h2 className="text-lg font-semibold flex items-center gap-2">
|
||||||
</CardHeader>
|
📊 Résumé de la semaine
|
||||||
<CardContent className="space-y-4">
|
</h2>
|
||||||
<div className="outline-card-blue p-4">
|
</CardHeader>
|
||||||
<h3 className="font-medium mb-2">🎯 Points clés accomplis</h3>
|
<CardContent className="space-y-4">
|
||||||
<p>{summary.narrative.weekHighlight}</p>
|
<div className="outline-card-blue p-4">
|
||||||
</div>
|
<h3 className="font-medium mb-2">🎯 Points clés accomplis</h3>
|
||||||
|
<p className="text-sm text-[var(--muted-foreground)]">{summary.narrative.weekHighlight}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="outline-card-yellow p-4">
|
<div className="outline-card-orange p-4">
|
||||||
<h3 className="font-medium mb-2">⚡ Défis traités</h3>
|
<h3 className="font-medium mb-2">⚡ Défis traités</h3>
|
||||||
<p>{summary.narrative.mainChallenges}</p>
|
<p className="text-sm text-[var(--muted-foreground)]">{summary.narrative.mainChallenges}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="outline-card-green p-4">
|
<div className="outline-card-green p-4">
|
||||||
<h3 className="font-medium mb-2">🔮 Focus 7 prochains jours</h3>
|
<h3 className="font-medium mb-2">🔮 Focus 7 prochains jours</h3>
|
||||||
<p>{summary.narrative.nextWeekFocus}</p>
|
<p className="text-sm text-[var(--muted-foreground)]">{summary.narrative.nextWeekFocus}</p>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Métriques rapides */}
|
{/* Métriques rapides */}
|
||||||
<Card>
|
<Card variant="elevated">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h2 className="text-lg font-semibold">📈 Métriques en bref</h2>
|
<h2 className="text-lg font-semibold">📈 Métriques en bref</h2>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<MetricCard
|
<div className="outline-metric-blue">
|
||||||
title="Tâches complétées"
|
<div className="text-2xl font-bold mb-1">{summary.metrics.totalTasksCompleted}</div>
|
||||||
value={summary.metrics.totalTasksCompleted}
|
<div className="text-xs font-medium mb-1">Tâches complétées</div>
|
||||||
subtitle={`dont ${summary.metrics.highPriorityTasksCompleted} priorité haute`}
|
<div className="text-xs text-[var(--muted-foreground)]">dont {summary.metrics.highPriorityTasksCompleted} priorité haute</div>
|
||||||
color="primary"
|
</div>
|
||||||
/>
|
|
||||||
|
|
||||||
<MetricCard
|
<div className="outline-metric-green">
|
||||||
title="Todos complétés"
|
<div className="text-2xl font-bold mb-1">{summary.metrics.totalCheckboxesCompleted}</div>
|
||||||
value={summary.metrics.totalCheckboxesCompleted}
|
<div className="text-xs font-medium mb-1">Todos complétés</div>
|
||||||
subtitle={`dont ${summary.metrics.meetingCheckboxesCompleted} meetings`}
|
<div className="text-xs text-[var(--muted-foreground)]">dont {summary.metrics.meetingCheckboxesCompleted} meetings</div>
|
||||||
color="success"
|
</div>
|
||||||
/>
|
|
||||||
|
|
||||||
<MetricCard
|
<div className="outline-metric-orange">
|
||||||
title="Items à fort impact"
|
<div className="text-2xl font-bold mb-1">{summary.keyAccomplishments.filter(a => a.impact === 'high').length}</div>
|
||||||
value={summary.keyAccomplishments.filter(a => a.impact === 'high').length}
|
<div className="text-xs font-medium mb-1">Items à fort impact</div>
|
||||||
subtitle={`/ ${summary.keyAccomplishments.length} accomplissements`}
|
<div className="text-xs text-[var(--muted-foreground)]">/ {summary.keyAccomplishments.length} accomplissements</div>
|
||||||
color="warning"
|
</div>
|
||||||
/>
|
|
||||||
|
|
||||||
<MetricCard
|
<div className="outline-metric-gray">
|
||||||
title="Priorités critiques"
|
<div className="text-2xl font-bold mb-1">{summary.upcomingChallenges.filter(c => c.priority === 'high').length}</div>
|
||||||
value={summary.upcomingChallenges.filter(c => c.priority === 'high').length}
|
<div className="text-xs font-medium mb-1">Priorités critiques</div>
|
||||||
subtitle={`/ ${summary.upcomingChallenges.length} enjeux`}
|
<div className="text-xs text-[var(--muted-foreground)]">/ {summary.upcomingChallenges.length} enjeux</div>
|
||||||
color="destructive"
|
</div>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</CardContent>
|
||||||
</CardContent>
|
</Card>
|
||||||
</Card>
|
</div>
|
||||||
|
|
||||||
{/* Top accomplissements */}
|
{/* Top accomplissements */}
|
||||||
<Card>
|
<Card variant="elevated">
|
||||||
<CardHeader>
|
<CardHeader className="pb-4" style={{
|
||||||
<h2 className="text-lg font-semibold">🏆 Top accomplissements</h2>
|
borderBottom: '1px solid',
|
||||||
|
borderBottomColor: 'color-mix(in srgb, var(--success) 10%, var(--border))'
|
||||||
|
}}>
|
||||||
|
<h2 className="text-lg font-semibold flex items-center gap-2" style={{ color: 'var(--success)' }}>
|
||||||
|
🏆 Top accomplissements
|
||||||
|
</h2>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
{summary.keyAccomplishments.length === 0 ? (
|
{summary.keyAccomplishments.length === 0 ? (
|
||||||
<div className="col-span-3 text-center py-8 text-[var(--muted-foreground)]">
|
<div className="col-span-3 text-center py-8 text-[var(--muted-foreground)]">
|
||||||
<p>Aucun accomplissement significatif trouvé cette semaine.</p>
|
<p>Aucun accomplissement significatif trouvé cette semaine.</p>
|
||||||
@@ -165,12 +168,17 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Top challenges */}
|
{/* Top challenges */}
|
||||||
<Card>
|
<Card variant="elevated">
|
||||||
<CardHeader>
|
<CardHeader className="pb-4" style={{
|
||||||
<h2 className="text-lg font-semibold">🎯 Top enjeux à venir</h2>
|
borderBottom: '1px solid',
|
||||||
|
borderBottomColor: 'color-mix(in srgb, var(--destructive) 10%, var(--border))'
|
||||||
|
}}>
|
||||||
|
<h2 className="text-lg font-semibold flex items-center gap-2" style={{ color: 'var(--destructive)' }}>
|
||||||
|
🎯 Top enjeux à venir
|
||||||
|
</h2>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
{summary.upcomingChallenges.length === 0 ? (
|
{summary.upcomingChallenges.length === 0 ? (
|
||||||
<div className="col-span-3 text-center py-8 text-[var(--muted-foreground)]">
|
<div className="col-span-3 text-center py-8 text-[var(--muted-foreground)]">
|
||||||
<p>Aucun enjeu prioritaire trouvé.</p>
|
<p>Aucun enjeu prioritaire trouvé.</p>
|
||||||
@@ -196,52 +204,76 @@ export default function ManagerWeeklySummary({ initialSummary }: ManagerWeeklySu
|
|||||||
|
|
||||||
{/* Vue détaillée des accomplissements */}
|
{/* Vue détaillée des accomplissements */}
|
||||||
{activeView === 'accomplishments' && (
|
{activeView === 'accomplishments' && (
|
||||||
<Card>
|
<Card variant="elevated">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h2 className="text-lg font-semibold">✅ Accomplissements des 7 derniers jours</h2>
|
<h2 className="text-lg font-semibold">✅ Accomplissements des 7 derniers jours</h2>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
{summary.keyAccomplishments.length} accomplissements significatifs • {summary.metrics.totalTasksCompleted} tâches • {summary.metrics.totalCheckboxesCompleted} todos complétés
|
{summary.keyAccomplishments.length} accomplissements significatifs • {summary.metrics.totalTasksCompleted} tâches • {summary.metrics.totalCheckboxesCompleted} todos complétés
|
||||||
</p>
|
</p>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent className="space-y-6">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
{summary.keyAccomplishments.length === 0 ? (
|
||||||
{summary.keyAccomplishments.map((accomplishment, index) => (
|
<div className="p-8 text-center rounded-xl border-2" style={{
|
||||||
<AchievementCard
|
backgroundColor: 'color-mix(in srgb, var(--muted) 15%, transparent)',
|
||||||
key={accomplishment.id}
|
borderColor: 'color-mix(in srgb, var(--muted) 40%, var(--border))',
|
||||||
achievement={accomplishment}
|
color: 'var(--muted-foreground)'
|
||||||
availableTags={availableTags as (Tag & { usage: number })[]}
|
}}>
|
||||||
index={index}
|
<div className="text-4xl mb-4">📭</div>
|
||||||
showDescription={true}
|
<p className="text-lg mb-2">Aucun accomplissement significatif trouvé cette semaine.</p>
|
||||||
maxTags={3}
|
<p className="text-sm">Ajoutez des tâches avec priorité haute/medium ou des meetings.</p>
|
||||||
/>
|
</div>
|
||||||
))}
|
) : (
|
||||||
</div>
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
{summary.keyAccomplishments.map((accomplishment, index) => (
|
||||||
|
<AchievementCard
|
||||||
|
key={accomplishment.id}
|
||||||
|
achievement={accomplishment}
|
||||||
|
availableTags={availableTags as (Tag & { usage: number })[]}
|
||||||
|
index={index}
|
||||||
|
showDescription={true}
|
||||||
|
maxTags={3}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Vue détaillée des challenges */}
|
{/* Vue détaillée des challenges */}
|
||||||
{activeView === 'challenges' && (
|
{activeView === 'challenges' && (
|
||||||
<Card>
|
<Card variant="elevated">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<h2 className="text-lg font-semibold">🎯 Enjeux et défis à venir</h2>
|
<h2 className="text-lg font-semibold">🎯 Enjeux et défis à venir</h2>
|
||||||
<p className="text-sm text-[var(--muted-foreground)]">
|
<p className="text-sm text-[var(--muted-foreground)]">
|
||||||
{summary.upcomingChallenges.length} défis identifiés • {summary.upcomingChallenges.filter(c => c.priority === 'high').length} priorité haute • {summary.upcomingChallenges.filter(c => c.blockers.length > 0).length} avec blockers
|
{summary.upcomingChallenges.length} défis identifiés • {summary.upcomingChallenges.filter(c => c.priority === 'high').length} priorité haute • {summary.upcomingChallenges.filter(c => c.blockers.length > 0).length} avec blockers
|
||||||
</p>
|
</p>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent className="space-y-6">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
{summary.upcomingChallenges.length === 0 ? (
|
||||||
{summary.upcomingChallenges.map((challenge, index) => (
|
<div className="p-8 text-center rounded-xl border-2" style={{
|
||||||
<ChallengeCard
|
backgroundColor: 'color-mix(in srgb, var(--muted) 15%, transparent)',
|
||||||
key={challenge.id}
|
borderColor: 'color-mix(in srgb, var(--muted) 40%, var(--border))',
|
||||||
challenge={challenge}
|
color: 'var(--muted-foreground)'
|
||||||
availableTags={availableTags as (Tag & { usage: number })[]}
|
}}>
|
||||||
index={index}
|
<div className="text-4xl mb-4">🎯</div>
|
||||||
showDescription={true}
|
<p className="text-lg mb-2">Aucun enjeu prioritaire trouvé.</p>
|
||||||
maxTags={3}
|
<p className="text-sm">Ajoutez des tâches non complétées avec priorité haute/medium.</p>
|
||||||
/>
|
</div>
|
||||||
))}
|
) : (
|
||||||
</div>
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
{summary.upcomingChallenges.map((challenge, index) => (
|
||||||
|
<ChallengeCard
|
||||||
|
key={challenge.id}
|
||||||
|
challenge={challenge}
|
||||||
|
availableTags={availableTags as (Tag & { usage: number })[]}
|
||||||
|
index={index}
|
||||||
|
showDescription={true}
|
||||||
|
maxTags={3}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ export function AchievementCard({
|
|||||||
className = ''
|
className = ''
|
||||||
}: AchievementCardProps) {
|
}: AchievementCardProps) {
|
||||||
return (
|
return (
|
||||||
<div className={`relative bg-[var(--card)] border border-[var(--border)] rounded-lg p-3 transition-all duration-200 group ${className}`}>
|
<div className={`relative border border-[var(--border)] rounded-lg p-3 transition-all duration-200 group ${className}`} style={{
|
||||||
|
backgroundColor: 'color-mix(in srgb, var(--success) 5%, var(--card))'
|
||||||
|
}}>
|
||||||
{/* Barre colorée gauche */}
|
{/* Barre colorée gauche */}
|
||||||
<div className="absolute left-0 top-0 bottom-0 w-1 bg-green-500 rounded-l-lg"></div>
|
<div className="absolute left-0 top-0 bottom-0 w-1 bg-green-500 rounded-l-lg"></div>
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ export function ChallengeCard({
|
|||||||
className = ''
|
className = ''
|
||||||
}: ChallengeCardProps) {
|
}: ChallengeCardProps) {
|
||||||
return (
|
return (
|
||||||
<div className={`relative bg-[var(--card)] border border-[var(--border)] rounded-lg p-3 transition-all duration-200 group ${className}`}>
|
<div className={`relative border border-[var(--border)] rounded-lg p-3 transition-all duration-200 group ${className}`} style={{
|
||||||
|
backgroundColor: 'color-mix(in srgb, var(--destructive) 5%, var(--card))'
|
||||||
|
}}>
|
||||||
{/* Barre colorée gauche */}
|
{/* Barre colorée gauche */}
|
||||||
<div className="absolute left-0 top-0 bottom-0 w-1 bg-orange-500 rounded-l-lg"></div>
|
<div className="absolute left-0 top-0 bottom-0 w-1 bg-orange-500 rounded-l-lg"></div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user