All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m16s
186 lines
6.0 KiB
TypeScript
186 lines
6.0 KiB
TypeScript
import { Suspense } from 'react';
|
||
import Link from 'next/link';
|
||
import { auth } from '@/lib/auth';
|
||
import { getSessionsByUserId } from '@/services/sessions';
|
||
import { getMotivatorSessionsByUserId } from '@/services/moving-motivators';
|
||
import { getYearReviewSessionsByUserId } from '@/services/year-review';
|
||
import { getWeeklyCheckInSessionsByUserId } from '@/services/weekly-checkin';
|
||
import { getWeatherSessionsByUserId } from '@/services/weather';
|
||
import { Card, Button } from '@/components/ui';
|
||
import { WorkshopTabs } from './WorkshopTabs';
|
||
|
||
function WorkshopTabsSkeleton() {
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* Tabs skeleton */}
|
||
<div className="flex gap-2 border-b border-border pb-4">
|
||
{[...Array(4)].map((_, i) => (
|
||
<div key={i} className="h-10 w-32 bg-card animate-pulse rounded-lg" />
|
||
))}
|
||
</div>
|
||
{/* Cards skeleton */}
|
||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||
{[...Array(6)].map((_, i) => (
|
||
<div key={i} className="h-40 bg-card animate-pulse rounded-xl" />
|
||
))}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default async function SessionsPage() {
|
||
const session = await auth();
|
||
|
||
if (!session?.user?.id) {
|
||
return null;
|
||
}
|
||
|
||
// Fetch SWOT, Moving Motivators, Year Review, Weekly Check-in, and Weather sessions
|
||
const [swotSessions, motivatorSessions, yearReviewSessions, weeklyCheckInSessions, weatherSessions] =
|
||
await Promise.all([
|
||
getSessionsByUserId(session.user.id),
|
||
getMotivatorSessionsByUserId(session.user.id),
|
||
getYearReviewSessionsByUserId(session.user.id),
|
||
getWeeklyCheckInSessionsByUserId(session.user.id),
|
||
getWeatherSessionsByUserId(session.user.id),
|
||
]);
|
||
|
||
// Add type to each session for unified display
|
||
const allSwotSessions = swotSessions.map((s) => ({
|
||
...s,
|
||
workshopType: 'swot' as const,
|
||
}));
|
||
|
||
const allMotivatorSessions = motivatorSessions.map((s) => ({
|
||
...s,
|
||
workshopType: 'motivators' as const,
|
||
}));
|
||
|
||
const allYearReviewSessions = yearReviewSessions.map((s) => ({
|
||
...s,
|
||
workshopType: 'year-review' as const,
|
||
}));
|
||
|
||
const allWeeklyCheckInSessions = weeklyCheckInSessions.map((s) => ({
|
||
...s,
|
||
workshopType: 'weekly-checkin' as const,
|
||
}));
|
||
|
||
const allWeatherSessions = weatherSessions.map((s) => ({
|
||
...s,
|
||
workshopType: 'weather' as const,
|
||
}));
|
||
|
||
// Combine and sort by updatedAt
|
||
const allSessions = [
|
||
...allSwotSessions,
|
||
...allMotivatorSessions,
|
||
...allYearReviewSessions,
|
||
...allWeeklyCheckInSessions,
|
||
...allWeatherSessions,
|
||
].sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
||
|
||
const hasNoSessions = allSessions.length === 0;
|
||
|
||
return (
|
||
<main className="mx-auto max-w-7xl px-4 py-8">
|
||
{/* Header */}
|
||
<div className="mb-8 flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||
<div>
|
||
<h1 className="text-3xl font-bold text-foreground">Mes Ateliers</h1>
|
||
<p className="mt-1 text-muted">Tous vos ateliers en un seul endroit</p>
|
||
</div>
|
||
<div className="flex gap-2">
|
||
<Link href="/sessions/new">
|
||
<Button variant="outline">
|
||
<span>📊</span>
|
||
Nouveau SWOT
|
||
</Button>
|
||
</Link>
|
||
<Link href="/motivators/new">
|
||
<Button variant="outline">
|
||
<span>🎯</span>
|
||
Nouveau Motivators
|
||
</Button>
|
||
</Link>
|
||
<Link href="/year-review/new">
|
||
<Button variant="outline">
|
||
<span>📅</span>
|
||
Nouveau Year Review
|
||
</Button>
|
||
</Link>
|
||
<Link href="/weekly-checkin/new">
|
||
<Button variant="outline">
|
||
<span>📝</span>
|
||
Nouveau Check-in
|
||
</Button>
|
||
</Link>
|
||
<Link href="/weather/new">
|
||
<Button>
|
||
<span>🌤️</span>
|
||
Nouvelle Météo
|
||
</Button>
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Content */}
|
||
{hasNoSessions ? (
|
||
<Card className="p-12 text-center">
|
||
<div className="text-5xl mb-4">🚀</div>
|
||
<h2 className="text-xl font-semibold text-foreground mb-2">
|
||
Commencez votre premier atelier
|
||
</h2>
|
||
<p className="text-muted mb-6 max-w-md mx-auto">
|
||
Créez un atelier SWOT pour analyser les forces et faiblesses, un Moving Motivators pour
|
||
découvrir les motivations, un Year Review pour faire le bilan de l'année, ou un
|
||
Weekly Check-in pour le suivi hebdomadaire.
|
||
</p>
|
||
<div className="flex gap-3 justify-center flex-wrap">
|
||
<Link href="/sessions/new">
|
||
<Button variant="outline">
|
||
<span>📊</span>
|
||
Créer un SWOT
|
||
</Button>
|
||
</Link>
|
||
<Link href="/motivators/new">
|
||
<Button variant="outline">
|
||
<span>🎯</span>
|
||
Créer un Moving Motivators
|
||
</Button>
|
||
</Link>
|
||
<Link href="/year-review/new">
|
||
<Button variant="outline">
|
||
<span>📅</span>
|
||
Créer un Year Review
|
||
</Button>
|
||
</Link>
|
||
<Link href="/weekly-checkin/new">
|
||
<Button variant="outline">
|
||
<span>📝</span>
|
||
Créer un Check-in
|
||
</Button>
|
||
</Link>
|
||
<Link href="/weather/new">
|
||
<Button>
|
||
<span>🌤️</span>
|
||
Créer une Météo
|
||
</Button>
|
||
</Link>
|
||
</div>
|
||
</Card>
|
||
) : (
|
||
<Suspense fallback={<WorkshopTabsSkeleton />}>
|
||
<WorkshopTabs
|
||
swotSessions={allSwotSessions}
|
||
motivatorSessions={allMotivatorSessions}
|
||
yearReviewSessions={allYearReviewSessions}
|
||
weeklyCheckInSessions={allWeeklyCheckInSessions}
|
||
weatherSessions={allWeatherSessions}
|
||
/>
|
||
</Suspense>
|
||
)}
|
||
</main>
|
||
);
|
||
}
|