feat: add Room component and refactor Conference components, implement custom scrollbar styles and smooth
This commit is contained in:
parent
37a34dc004
commit
f9aef69cfa
5
.prettierrc
Normal file
5
.prettierrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"tabWidth": 4,
|
||||||
|
"useTabs": true,
|
||||||
|
"semi": true
|
||||||
|
}
|
@ -1,24 +0,0 @@
|
|||||||
"use client"
|
|
||||||
import { ConferenceCard } from "./Card";
|
|
||||||
import { Room } from "./Conference";
|
|
||||||
|
|
||||||
export const ConferenceList = ({
|
|
||||||
rooms,
|
|
||||||
}: {
|
|
||||||
rooms: Room[];
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<div className="flex gap-2">
|
|
||||||
{rooms.map((room) => (
|
|
||||||
<ConferenceCard
|
|
||||||
key={room.id}
|
|
||||||
id={room.id}
|
|
||||||
name={room.name}
|
|
||||||
date={room.date}
|
|
||||||
Presentator={room.Presentator}
|
|
||||||
Times={room.Times}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,3 +1,4 @@
|
|||||||
|
'use client'
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
Button,
|
Button,
|
||||||
@ -8,85 +9,79 @@ import {
|
|||||||
Navbar,
|
Navbar,
|
||||||
NavbarBrand,
|
NavbarBrand,
|
||||||
NavbarContent,
|
NavbarContent,
|
||||||
NavbarItem,
|
NavbarItem
|
||||||
} from "@nextui-org/react";
|
} from '@nextui-org/react'
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from 'next-auth/react'
|
||||||
import { ThemeSwitcher } from "../ThemeSwitcher/ThemeSwitcher";
|
import { ThemeSwitcher } from '../ThemeSwitcher/ThemeSwitcher'
|
||||||
import { axiosInstance } from "@/app/lib/axios";
|
import { axiosInstance } from '@/app/lib/axios'
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react'
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from 'next/navigation'
|
||||||
|
|
||||||
const getInitials = (name: string) => {
|
const getInitials = (name: string) => {
|
||||||
if (!name) return "";
|
if (!name) return ''
|
||||||
|
|
||||||
const nameParts = name.split(" ");
|
const nameParts = name.split(' ')
|
||||||
if (nameParts.length === 1) {
|
if (nameParts.length === 1) {
|
||||||
return name;
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstInitial = nameParts[0]?.[0] || "";
|
const firstInitial = nameParts[0]?.[0] || ''
|
||||||
const secondInitial = nameParts[1]?.[0] || nameParts[0]?.[1] || "";
|
const secondInitial = nameParts[1]?.[0] || nameParts[0]?.[1] || ''
|
||||||
|
|
||||||
return firstInitial + secondInitial;
|
return firstInitial + secondInitial
|
||||||
};
|
}
|
||||||
|
|
||||||
export const Header = () => {
|
export const Header = () => {
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession()
|
||||||
const router = useRouter();
|
const router = useRouter()
|
||||||
|
|
||||||
const [userProfile, setUserProfile] = useState<{
|
const [userProfile, setUserProfile] = useState<{
|
||||||
id: string;
|
id: string
|
||||||
username: string;
|
username: string
|
||||||
role: "ADMIN" | "STUDENT";
|
role: 'ADMIN' | 'STUDENT'
|
||||||
}>();
|
}>()
|
||||||
|
|
||||||
const initials = session?.user?.name ? getInitials(session.user.name) : "";
|
const initials = session?.user?.name ? getInitials(session.user.name) : ''
|
||||||
|
|
||||||
const fetchUserProfile = async () => {
|
const fetchUserProfile = async () => {
|
||||||
return await axiosInstance<{
|
return await axiosInstance<{
|
||||||
id: string;
|
id: string
|
||||||
username: string;
|
username: string
|
||||||
role: "ADMIN" | "STUDENT";
|
role: 'ADMIN' | 'STUDENT'
|
||||||
}>("/@me");
|
}>('/@me')
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUserProfile().then(r => {
|
fetchUserProfile().then(r => {
|
||||||
setUserProfile(r.data);
|
setUserProfile(r.data)
|
||||||
});
|
})
|
||||||
}, []);
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Navbar className="mb-2">
|
<Navbar className='mb-2'>
|
||||||
<NavbarBrand>
|
<NavbarBrand>
|
||||||
<p className="font-bold text-inherit">Toogether</p>
|
<p className='font-bold text-inherit'>Toogether</p>
|
||||||
</NavbarBrand>
|
</NavbarBrand>
|
||||||
|
|
||||||
<NavbarContent as="div" justify="end">
|
<NavbarContent as='div' justify='end'>
|
||||||
<Dropdown placement="bottom-end">
|
<Dropdown placement='bottom-end'>
|
||||||
<DropdownTrigger>
|
<DropdownTrigger>
|
||||||
<Avatar
|
<Avatar
|
||||||
isBordered
|
isBordered
|
||||||
as="button"
|
as='button'
|
||||||
className="transition-transform"
|
className='transition-transform'
|
||||||
color="secondary"
|
color='secondary'
|
||||||
name={initials}
|
name={initials}
|
||||||
size="sm"
|
size='sm'
|
||||||
/>
|
/>
|
||||||
</DropdownTrigger>
|
</DropdownTrigger>
|
||||||
<DropdownMenu aria-label="Profile Actions" variant="flat">
|
<DropdownMenu aria-label='Profile Actions' variant='flat'>
|
||||||
<DropdownItem key="profile" className="h-14 gap-2">
|
<DropdownItem key='profile' className='h-14 gap-2'>
|
||||||
<p>Signed in as</p>
|
<p>Signed in as</p>
|
||||||
<p className="font-semibold">
|
<p className='font-semibold'>{session?.user?.name}</p>
|
||||||
{session?.user?.name}
|
|
||||||
</p>
|
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
<DropdownItem key="settings">Settings</DropdownItem>
|
<DropdownItem key='settings'>Settings</DropdownItem>
|
||||||
<DropdownItem
|
<DropdownItem key='logout' color='danger' href='/auth/logout'>
|
||||||
key="logout"
|
|
||||||
color="danger"
|
|
||||||
href="/auth/logout"
|
|
||||||
>
|
|
||||||
Logout
|
Logout
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
@ -94,18 +89,12 @@ export const Header = () => {
|
|||||||
<NavbarItem>
|
<NavbarItem>
|
||||||
<ThemeSwitcher />
|
<ThemeSwitcher />
|
||||||
</NavbarItem>
|
</NavbarItem>
|
||||||
{
|
{userProfile?.role === 'ADMIN' ? (
|
||||||
userProfile?.role === "ADMIN" ? (
|
<NavbarItem>
|
||||||
<NavbarItem>
|
<Button onPress={() => router.push('/admin')}>🔧</Button>
|
||||||
<Button
|
</NavbarItem>
|
||||||
onPress={() => router.push("/admin")}
|
) : null}
|
||||||
>
|
|
||||||
🔧
|
|
||||||
</Button>
|
|
||||||
</NavbarItem>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
</NavbarContent>
|
</NavbarContent>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
@ -1,74 +1,74 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { parseDate, Time } from "@internationalized/date";
|
import { parseDate, Time } from "@internationalized/date";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
CardBody,
|
CardBody,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
DateInput,
|
DateInput,
|
||||||
Divider,
|
Divider,
|
||||||
TimeInput,
|
TimeInput,
|
||||||
} from "@nextui-org/react";
|
} from "@nextui-org/react";
|
||||||
import { Room } from "./Conference";
|
import { Room } from "./Room";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
export const ConferenceCard = ({
|
export const RoomCard = ({
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
date,
|
date,
|
||||||
Times,
|
Times,
|
||||||
Presentator
|
Presentator
|
||||||
}: Room) => {
|
}: Room) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="max-w-[600px]">
|
<Card className="w-[300px]">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<p className="text-md">{name}</p>
|
<p className="text-md">{name}</p>
|
||||||
<p className="text-small text-default-500">{Presentator.username}</p>
|
<p className="text-small text-default-500">{Presentator.username}</p>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<Divider />
|
<Divider />
|
||||||
<CardBody>
|
<CardBody>
|
||||||
{Times.map((time) => (
|
{Times.map((time) => (
|
||||||
<div className="flex flex-col gap-2" key={`${time.id}`}>
|
<div className="flex flex-col gap-2" key={`${time.id}`}>
|
||||||
<DateInput isReadOnly label="Date" value={parseDate(moment(date).format("YYYY-MM-DD"))} />
|
<DateInput isReadOnly label="Date" value={parseDate(moment(date).format("YYYY-MM-DD"))} />
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<TimeInput
|
<TimeInput
|
||||||
isReadOnly
|
isReadOnly
|
||||||
label="Start"
|
label="Start"
|
||||||
hourCycle={24}
|
hourCycle={24}
|
||||||
value={
|
value={
|
||||||
new Time(moment(time.startTime).hours(), moment(time.startTime).minutes())
|
new Time(moment(time.startTime).hours(), moment(time.startTime).minutes())
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<span>-</span>
|
<span>-</span>
|
||||||
<TimeInput
|
<TimeInput
|
||||||
isReadOnly
|
isReadOnly
|
||||||
label="End"
|
label="End"
|
||||||
hourCycle={24}
|
hourCycle={24}
|
||||||
value={new Time(moment(time.endTime).hours(), moment(time.endTime).minutes())}
|
value={new Time(moment(time.endTime).hours(), moment(time.endTime).minutes())}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
<div className="flex p-2">
|
<div className="flex p-2">
|
||||||
<Button
|
<Button
|
||||||
className={"bg-transparent text-foreground border-default-200"}
|
className={"bg-transparent text-foreground border-default-200"}
|
||||||
color="primary"
|
color="primary"
|
||||||
radius="full"
|
radius="full"
|
||||||
size="sm"
|
size="sm"
|
||||||
variant={"bordered"}
|
variant={"bordered"}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(`/room/${id}`);
|
router.push(`/room/${id}`);
|
||||||
}}
|
}}
|
||||||
>Join</Button>
|
>Join</Button>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
57
src/app/components/Room/List.tsx
Normal file
57
src/app/components/Room/List.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
'use client';
|
||||||
|
import { useEffect, useRef } from 'react';
|
||||||
|
import { RoomCard } from './Card';
|
||||||
|
import { Room } from './Room';
|
||||||
|
|
||||||
|
export const RoomList = ({ rooms }: { rooms: Room[] }) => {
|
||||||
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleWheel = (event: WheelEvent) => {
|
||||||
|
if (event.deltaY === 0) return;
|
||||||
|
event.preventDefault();
|
||||||
|
const scrollContainer = scrollContainerRef.current;
|
||||||
|
if (!scrollContainer) return;
|
||||||
|
|
||||||
|
const scrollAmount = 10;
|
||||||
|
const direction = event.deltaY > 0 ? 1 : -1;
|
||||||
|
let scrollCount = 0;
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
scrollContainer.scrollLeft += scrollAmount * direction;
|
||||||
|
scrollCount += scrollAmount;
|
||||||
|
if (scrollCount >= 100) {
|
||||||
|
clearInterval(interval);
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const scrollContainer = scrollContainerRef.current;
|
||||||
|
if (!scrollContainer) return;
|
||||||
|
|
||||||
|
scrollContainer.addEventListener('wheel', handleWheel);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
scrollContainer.removeEventListener('wheel', handleWheel);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={scrollContainerRef} className='overflow-x-auto scrollbar-hide rounded-xl'>
|
||||||
|
<ul className='flex gap-2'>
|
||||||
|
{rooms.map(room => (
|
||||||
|
<li key={room.id}>
|
||||||
|
<RoomCard
|
||||||
|
id={room.id}
|
||||||
|
name={room.name}
|
||||||
|
date={room.date}
|
||||||
|
Presentator={room.Presentator}
|
||||||
|
Times={room.Times}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@ -1,17 +1,17 @@
|
|||||||
export interface Room {
|
export interface Room {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
date: string;
|
date: string;
|
||||||
Times: {
|
Times: {
|
||||||
id: number;
|
id: number;
|
||||||
startTime: string;
|
startTime: string;
|
||||||
endTime: string;
|
endTime: string;
|
||||||
roomId: string;
|
roomId: string;
|
||||||
}[];
|
}[];
|
||||||
Presentator: {
|
Presentator: {
|
||||||
id: string;
|
id: string;
|
||||||
username: string;
|
username: string;
|
||||||
role: string;
|
role: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,21 @@
|
|||||||
"use client";
|
'use client'
|
||||||
import { Button } from "@nextui-org/react";
|
import { Button } from '@nextui-org/react'
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from 'next-themes'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
export const ThemeSwitcher = () => {
|
export const ThemeSwitcher = () => {
|
||||||
const { theme, setTheme } = useTheme();
|
const [mounted, setMounted] = useState(false)
|
||||||
|
const { theme, setTheme } = useTheme()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMounted(true)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if (!mounted) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onPress={() => setTheme(theme === "light" ? "dark" : "light")}>
|
<Button onPress={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
|
||||||
{theme === "light" ? "🌑" : "☀️"}
|
{theme === 'light' ? '🌑' : '☀️'}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer utilities {
|
||||||
|
.scrollbar::-webkit-scrollbar {
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar::-webkit-scrollbar-track {
|
||||||
|
border-radius: 100vh;
|
||||||
|
background: #5a5a5a54;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar::-webkit-scrollbar-thumb {
|
||||||
|
background: #414141;
|
||||||
|
border-radius: 100vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
151
src/app/page.tsx
151
src/app/page.tsx
@ -1,37 +1,39 @@
|
|||||||
"use client";
|
'use client';
|
||||||
import { Card, Divider, Skeleton } from "@nextui-org/react";
|
import { Card, Divider, Skeleton } from '@nextui-org/react';
|
||||||
import moment from "moment";
|
import moment from 'moment';
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import { Room } from "./components/Conference/Conference";
|
import { Room } from './components/Room/Room';
|
||||||
import { ConferenceList } from "./components/Conference/List";
|
import { RoomList } from './components/Room/List';
|
||||||
import { Header } from "./components/Header";
|
import { Header } from './components/Header';
|
||||||
import { axiosInstance } from "./lib/axios";
|
import { axiosInstance } from './lib/axios';
|
||||||
|
|
||||||
const SkeletonCard = () => {
|
const SkeletonCard = () => {
|
||||||
return <Card className="w-[200px] space-y-5 p-4" radius="lg">
|
return (
|
||||||
<div className="flex flex-col gap-2">
|
<Card className='w-[200px] space-y-5 p-4' radius='lg'>
|
||||||
<Skeleton className="w-4/5 rounded-lg">
|
<div className='flex flex-col gap-2'>
|
||||||
<div className="h-3 w-4/5 rounded-lg bg-default-200" />
|
<Skeleton className='w-4/5 rounded-lg'>
|
||||||
|
<div className='h-3 w-4/5 rounded-lg bg-default-200' />
|
||||||
|
</Skeleton>
|
||||||
|
<Skeleton className='w-2/5 rounded-lg'>
|
||||||
|
<div className='h-3 w-2/5 rounded-lg bg-default-300' />
|
||||||
|
</Skeleton>
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
|
<Skeleton className='rounded-lg'>
|
||||||
|
<div className='h-12 rounded-lg bg-default-300' />
|
||||||
</Skeleton>
|
</Skeleton>
|
||||||
<Skeleton className="w-2/5 rounded-lg">
|
<div className='flex items-center gap-2'>
|
||||||
<div className="h-3 w-2/5 rounded-lg bg-default-300" />
|
<Skeleton className='rounded-lg w-1/2'>
|
||||||
</Skeleton>
|
<div className='h-10 rounded-lg bg-default-300' />
|
||||||
</div>
|
</Skeleton>
|
||||||
<Divider />
|
<span>-</span>
|
||||||
<Skeleton className="rounded-lg">
|
<Skeleton className='rounded-lg w-1/2'>
|
||||||
<div className="h-12 rounded-lg bg-default-300" />
|
<div className='h-10 rounded-lg bg-default-300' />
|
||||||
</Skeleton>
|
</Skeleton>
|
||||||
<div className="flex items-center gap-2">
|
</div>
|
||||||
<Skeleton className="rounded-lg w-1/2">
|
</Card>
|
||||||
<div className="h-10 rounded-lg bg-default-300" />
|
);
|
||||||
</Skeleton>
|
};
|
||||||
<span>-</span>
|
|
||||||
<Skeleton className="rounded-lg w-1/2">
|
|
||||||
<div className="h-10 rounded-lg bg-default-300" />
|
|
||||||
</Skeleton>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
}
|
|
||||||
|
|
||||||
const HomePage = () => {
|
const HomePage = () => {
|
||||||
const [roomsLoading, setRoomsLoading] = useState(true);
|
const [roomsLoading, setRoomsLoading] = useState(true);
|
||||||
@ -46,70 +48,93 @@ const HomePage = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
axiosInstance.get<{ id: string, name: string, createdAt: string }[]>("/@me/class")
|
axiosInstance
|
||||||
.then((classResponse) => {
|
.get<{ id: string; name: string; createdAt: string }[]>(
|
||||||
|
'/@me/class'
|
||||||
|
)
|
||||||
|
.then(classResponse => {
|
||||||
if (classResponse.data.length)
|
if (classResponse.data.length)
|
||||||
axiosInstance.get<Room[]>(`/@me/class/${classResponse.data[0].id}/rooms`)
|
axiosInstance
|
||||||
|
.get<Room[]>(
|
||||||
|
`/@me/class/${classResponse.data[0].id}/rooms`
|
||||||
|
)
|
||||||
.then(classes => {
|
.then(classes => {
|
||||||
// Filter rooms by date, get future, actual and past rooms
|
// Filter rooms by date, get future, actual and past rooms
|
||||||
const future = classes.data.filter(room => moment(room.date).isAfter(moment(), "day"));
|
const future = classes.data.filter(room =>
|
||||||
const actual = classes.data.filter(room => moment(room.date).isSame(moment(), "day"));
|
moment(room.date).isAfter(moment(), 'day')
|
||||||
const past = classes.data.filter(room => moment(room.date).isBefore(moment()));
|
);
|
||||||
|
const actual = classes.data.filter(room =>
|
||||||
|
moment(room.date).isSame(moment(), 'day')
|
||||||
|
);
|
||||||
|
const past = classes.data.filter(room =>
|
||||||
|
moment(room.date).isBefore(moment())
|
||||||
|
);
|
||||||
|
|
||||||
setRooms({ future, actual, past });
|
setRooms({ future, actual, past });
|
||||||
setRoomsLoading(false);
|
setRoomsLoading(false);
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
<main className="flex flex-col gap-8 p-4">
|
<main className='flex flex-col gap-8 p-4'>
|
||||||
{roomsLoading
|
{roomsLoading ? (
|
||||||
? <>
|
<>
|
||||||
<section className="flex flex-col gap-2">
|
<section className='flex flex-col gap-2'>
|
||||||
<h2 className="font-semibold text-lg">Cours a venir</h2>
|
<h2 className='font-semibold text-lg'>
|
||||||
<div className="flex gap-4">
|
Cours a venir
|
||||||
|
</h2>
|
||||||
|
<div className='flex gap-4'>
|
||||||
<SkeletonCard />
|
<SkeletonCard />
|
||||||
<SkeletonCard />
|
<SkeletonCard />
|
||||||
<SkeletonCard />
|
<SkeletonCard />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className="flex flex-col gap-2">
|
<section className='flex flex-col gap-2'>
|
||||||
<h2 className="font-semibold text-lg">Cours actuels</h2>
|
<h2 className='font-semibold text-lg'>
|
||||||
<div className="flex gap-4">
|
Cours actuels
|
||||||
|
</h2>
|
||||||
|
<div className='flex gap-4'>
|
||||||
<SkeletonCard />
|
<SkeletonCard />
|
||||||
<SkeletonCard />
|
<SkeletonCard />
|
||||||
<SkeletonCard />
|
<SkeletonCard />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className="flex flex-col gap-2">
|
<section className='flex flex-col gap-2'>
|
||||||
<h2 className="font-semibold text-lg">Cours passés</h2>
|
<h2 className='font-semibold text-lg'>
|
||||||
<div className="flex gap-4">
|
Cours passés
|
||||||
|
</h2>
|
||||||
|
<div className='flex gap-4'>
|
||||||
<SkeletonCard />
|
<SkeletonCard />
|
||||||
<SkeletonCard />
|
<SkeletonCard />
|
||||||
<SkeletonCard />
|
<SkeletonCard />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</>
|
</>
|
||||||
: <>
|
) : (
|
||||||
<section className="flex flex-col gap-2">
|
<>
|
||||||
<h2 className="font-semibold text-lg">Cours a venir</h2>
|
<section className='flex flex-col gap-2'>
|
||||||
<ConferenceList rooms={rooms.future} />
|
<h2 className='font-semibold text-lg'>
|
||||||
|
Cours a venir
|
||||||
|
</h2>
|
||||||
|
<RoomList rooms={rooms.future} />
|
||||||
</section>
|
</section>
|
||||||
<section className="flex flex-col gap-2">
|
<section className='flex flex-col gap-2'>
|
||||||
<h2 className="font-semibold text-lg">Cours actuels</h2>
|
<h2 className='font-semibold text-lg'>
|
||||||
<ConferenceList rooms={rooms.actual} />
|
Cours actuels
|
||||||
|
</h2>
|
||||||
|
<RoomList rooms={rooms.actual} />
|
||||||
</section>
|
</section>
|
||||||
<section className="flex flex-col gap-2">
|
<section className='flex flex-col gap-2'>
|
||||||
<h2 className="font-semibold text-lg">Cours passés</h2>
|
<h2 className='font-semibold text-lg'>
|
||||||
<ConferenceList rooms={rooms.past} />
|
Cours passés
|
||||||
|
</h2>
|
||||||
|
<RoomList rooms={rooms.past} />
|
||||||
</section>
|
</section>
|
||||||
</>
|
</>
|
||||||
|
)}
|
||||||
}
|
|
||||||
</main>
|
</main>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user