feat: update session links to include tab parameters for improved navigation and add loading skeletons for better user experience
This commit is contained in:
@@ -29,7 +29,7 @@ export default async function MotivatorSessionPage({ params }: MotivatorSessionP
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<div className="flex items-center gap-2 text-sm text-muted mb-2">
|
<div className="flex items-center gap-2 text-sm text-muted mb-2">
|
||||||
<Link href="/sessions" className="hover:text-foreground">
|
<Link href="/sessions?tab=motivators" className="hover:text-foreground">
|
||||||
Moving Motivators
|
Moving Motivators
|
||||||
</Link>
|
</Link>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default function Home() {
|
|||||||
<div className="grid gap-8 md:grid-cols-2 max-w-4xl mx-auto">
|
<div className="grid gap-8 md:grid-cols-2 max-w-4xl mx-auto">
|
||||||
{/* SWOT Workshop Card */}
|
{/* SWOT Workshop Card */}
|
||||||
<WorkshopCard
|
<WorkshopCard
|
||||||
href="/sessions"
|
href="/sessions?tab=swot"
|
||||||
icon="📊"
|
icon="📊"
|
||||||
title="Analyse SWOT"
|
title="Analyse SWOT"
|
||||||
tagline="Analysez. Planifiez. Progressez."
|
tagline="Analysez. Planifiez. Progressez."
|
||||||
@@ -39,7 +39,7 @@ export default function Home() {
|
|||||||
|
|
||||||
{/* Moving Motivators Workshop Card */}
|
{/* Moving Motivators Workshop Card */}
|
||||||
<WorkshopCard
|
<WorkshopCard
|
||||||
href="/sessions"
|
href="/sessions?tab=motivators"
|
||||||
icon="🎯"
|
icon="🎯"
|
||||||
title="Moving Motivators"
|
title="Moving Motivators"
|
||||||
tagline="Révélez ce qui motive vraiment"
|
tagline="Révélez ce qui motive vraiment"
|
||||||
|
|||||||
@@ -2,12 +2,15 @@
|
|||||||
|
|
||||||
import { useState, useTransition } from 'react';
|
import { useState, useTransition } from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { useSearchParams, useRouter } from 'next/navigation';
|
||||||
import { Card, Badge, Button, Modal, ModalFooter, Input, CollaboratorDisplay } from '@/components/ui';
|
import { Card, Badge, Button, Modal, ModalFooter, Input, CollaboratorDisplay } from '@/components/ui';
|
||||||
import { deleteSwotSession, updateSwotSession } from '@/actions/session';
|
import { deleteSwotSession, updateSwotSession } from '@/actions/session';
|
||||||
import { deleteMotivatorSession, updateMotivatorSession } from '@/actions/moving-motivators';
|
import { deleteMotivatorSession, updateMotivatorSession } from '@/actions/moving-motivators';
|
||||||
|
|
||||||
type WorkshopType = 'all' | 'swot' | 'motivators' | 'byPerson';
|
type WorkshopType = 'all' | 'swot' | 'motivators' | 'byPerson';
|
||||||
|
|
||||||
|
const VALID_TABS: WorkshopType[] = ['all', 'swot', 'motivators', 'byPerson'];
|
||||||
|
|
||||||
interface ShareUser {
|
interface ShareUser {
|
||||||
id: string;
|
id: string;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
@@ -122,7 +125,24 @@ function groupByPerson(sessions: AnySession[]): Map<string, AnySession[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function WorkshopTabs({ swotSessions, motivatorSessions }: WorkshopTabsProps) {
|
export function WorkshopTabs({ swotSessions, motivatorSessions }: WorkshopTabsProps) {
|
||||||
const [activeTab, setActiveTab] = useState<WorkshopType>('all');
|
const searchParams = useSearchParams();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// Get tab from URL or default to 'all'
|
||||||
|
const tabParam = searchParams.get('tab');
|
||||||
|
const activeTab: WorkshopType = tabParam && VALID_TABS.includes(tabParam as WorkshopType)
|
||||||
|
? (tabParam as WorkshopType)
|
||||||
|
: 'all';
|
||||||
|
|
||||||
|
const setActiveTab = (tab: WorkshopType) => {
|
||||||
|
const params = new URLSearchParams(searchParams.toString());
|
||||||
|
if (tab === 'all') {
|
||||||
|
params.delete('tab');
|
||||||
|
} else {
|
||||||
|
params.set('tab', tab);
|
||||||
|
}
|
||||||
|
router.push(`/sessions${params.toString() ? `?${params.toString()}` : ''}`);
|
||||||
|
};
|
||||||
|
|
||||||
// Combine and sort all sessions
|
// Combine and sort all sessions
|
||||||
const allSessions: AnySession[] = [...swotSessions, ...motivatorSessions].sort(
|
const allSessions: AnySession[] = [...swotSessions, ...motivatorSessions].sort(
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ export default async function SessionPage({ params }: SessionPageProps) {
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<div className="flex items-center gap-2 text-sm text-muted mb-2">
|
<div className="flex items-center gap-2 text-sm text-muted mb-2">
|
||||||
<Link href="/sessions" className="hover:text-foreground">
|
<Link href="/sessions?tab=swot" className="hover:text-foreground">
|
||||||
Mes Sessions
|
SWOT
|
||||||
</Link>
|
</Link>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<span className="text-foreground">{session.title}</span>
|
<span className="text-foreground">{session.title}</span>
|
||||||
|
|||||||
@@ -1,10 +1,30 @@
|
|||||||
|
import { Suspense } from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { auth } from '@/lib/auth';
|
import { auth } from '@/lib/auth';
|
||||||
import { getSessionsByUserId } from '@/services/sessions';
|
import { getSessionsByUserId } from '@/services/sessions';
|
||||||
import { getMotivatorSessionsByUserId } from '@/services/moving-motivators';
|
import { getMotivatorSessionsByUserId } from '@/services/moving-motivators';
|
||||||
import { Card, CardContent, Badge, Button } from '@/components/ui';
|
import { Card, Button } from '@/components/ui';
|
||||||
import { WorkshopTabs } from './WorkshopTabs';
|
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() {
|
export default async function SessionsPage() {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
|
|
||||||
@@ -88,10 +108,12 @@ export default async function SessionsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
) : (
|
) : (
|
||||||
<WorkshopTabs
|
<Suspense fallback={<WorkshopTabsSkeleton />}>
|
||||||
swotSessions={allSwotSessions}
|
<WorkshopTabs
|
||||||
motivatorSessions={allMotivatorSessions}
|
swotSessions={allSwotSessions}
|
||||||
/>
|
motivatorSessions={allMotivatorSessions}
|
||||||
|
/>
|
||||||
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user