refactor: improve component formatting in Header, RoomCard, and ThemeSwitcher

This commit is contained in:
Rémi 2025-01-04 17:58:23 +01:00
parent e6f84ad95e
commit 096a10b9c1
3 changed files with 111 additions and 98 deletions

View File

@ -1,4 +1,4 @@
"use client"; 'use client';
import { import {
Avatar, Avatar,
Button, Button,
@ -9,24 +9,24 @@ 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;
}; };
@ -38,70 +38,76 @@ export const Header = () => {
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"> {userProfile?.role === 'ADMIN' ? (
<NavbarItem>
<Button
size='sm'
variant='flat'
className='min-w-0'
onPress={() => router.push('/admin')}
>
🔧
</Button>
</NavbarItem>
) : null}
<NavbarItem>
<ThemeSwitcher />
</NavbarItem>
<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} {session?.user?.name}
</p> </p>
</DropdownItem> </DropdownItem>
<DropdownItem key="settings">Settings</DropdownItem> <DropdownItem key='settings'>Settings</DropdownItem>
<DropdownItem <DropdownItem
key="logout" key='logout'
color="danger" color='danger'
href="/auth/logout" href='/auth/logout'
> >
Logout Logout
</DropdownItem> </DropdownItem>
</DropdownMenu> </DropdownMenu>
</Dropdown> </Dropdown>
<NavbarItem>
<ThemeSwitcher />
</NavbarItem>
{userProfile?.role === "ADMIN" ? (
<NavbarItem>
<Button onPress={() => router.push("/admin")}>
🔧
</Button>
</NavbarItem>
) : null}
</NavbarContent> </NavbarContent>
</Navbar> </Navbar>
); );

View File

@ -1,6 +1,6 @@
"use client"; 'use client';
import { parseDate, Time } from "@internationalized/date"; import { parseDate, Time } from '@internationalized/date';
import { import {
Button, Button,
@ -9,70 +9,72 @@ import {
CardHeader, CardHeader,
DateInput, DateInput,
Divider, Divider,
TimeInput, TimeInput
} from "@nextui-org/react"; } from '@nextui-org/react';
import { Room } from "./Room"; import { Room } from './Room';
import moment from "moment"; import moment from 'moment';
import { useRouter } from "next/navigation"; import { useRouter } from 'next/navigation';
export const RoomCard = ({ id, name, date, Times, Presentator }: Room) => { export const RoomCard = ({ id, name, date, Times, Presentator }: Room) => {
const router = useRouter(); const router = useRouter();
return ( return (
<Card className="w-[300px]"> <Card className='w-[300px]'>
<CardHeader> <CardHeader>
<div className="flex flex-col min-h-20"> <div className='flex flex-col min-h-20'>
<p className="text-md">{name}</p> <p className='text-md'>{name}</p>
<p className="text-small text-default-500"> <p className='text-small text-default-500'>
{Presentator.username} {Presentator.username}
</p> </p>
</div> </div>
</CardHeader> </CardHeader>
<Divider /> <Divider />
<CardBody> <CardBody>
{Times.map((time) => ( <div className='flex flex-col gap-2' key={`times.${id}`}>
<div className="flex flex-col gap-2" key={`${time.id}`}>
<DateInput <DateInput
isReadOnly isReadOnly
label="Date" label='Date'
value={parseDate(moment(date).format("YYYY-MM-DD"))} value={parseDate(moment(date).format('YYYY-MM-DD'))}
/> />
<div className="flex items-center gap-2"> {Times.map(time => (
<div key={`time.${time.id}`}>
<div className='flex items-center gap-2'>
<TimeInput <TimeInput
isReadOnly isReadOnly
label="Start" label='Start'
hourCycle={24} hourCycle={24}
value={ value={
new Time( new Time(
moment(time.startTime).hours(), moment(time.startTime).hours(),
moment(time.startTime).minutes(), moment(time.startTime).minutes()
) )
} }
/> />
<span>-</span> <span>-</span>
<TimeInput <TimeInput
isReadOnly isReadOnly
label="End" label='End'
hourCycle={24} hourCycle={24}
value={ value={
new Time( new Time(
moment(time.endTime).hours(), moment(time.endTime).hours(),
moment(time.endTime).minutes(), moment(time.endTime).minutes()
) )
} }
/> />
</div> </div>
</div> </div>
))} ))}
</div>
</CardBody> </CardBody>
{moment(date).dayOfYear() === moment().dayOfYear() && ( {moment(date).dayOfYear() === moment().dayOfYear() && (
<div className="flex p-2"> <div className='flex p-2'>
<Button <Button
className={""} className={''}
color="primary" color='primary'
radius="full" radius='full'
size="sm" size='sm'
variant={"flat"} variant={'flat'}
onPress={() => { onPress={() => {
router.push(`/room/${id}`); router.push(`/room/${id}`);
}} }}

View File

@ -1,7 +1,7 @@
"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"; import { useEffect, useState } from 'react';
export const ThemeSwitcher = () => { export const ThemeSwitcher = () => {
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
@ -14,8 +14,13 @@ export const ThemeSwitcher = () => {
if (!mounted) return null; if (!mounted) return null;
return ( return (
<Button onPress={() => setTheme(theme === "light" ? "dark" : "light")}> <Button
{theme === "light" ? "🌑" : "☀️"} size='sm'
variant='flat'
className='min-w-0'
onPress={() => setTheme(theme === 'light' ? 'dark' : 'light')}
>
{theme === 'light' ? '🌑' : '☀️'}
</Button> </Button>
); );
}; };