Skip to content

Commit

Permalink
Slide UI 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
woohm402 committed Sep 3, 2024
1 parent dc51278 commit b5e7259
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 327 deletions.
4 changes: 1 addition & 3 deletions frontend/lecture/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
"check-types": "tsc",
"lint": "eslint .",
"format": "prettier . --check",
"preview": "vite preview",
"check-all": "yarn check-types && yarn lint && yarn format"
"check-all": "yarn check-types && yarn lint && yarn format && yarn knip"
},
"dependencies": {
"@radix-ui/react-icons": "1.3.0",
Expand All @@ -19,7 +18,6 @@
"@radix-ui/react-tabs": "1.1.0",
"class-variance-authority": "0.7.0",
"clsx": "2.1.1",
"embla-carousel-react": "8.2.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-markdown": "9.0.1",
Expand Down
134 changes: 99 additions & 35 deletions frontend/lecture/src/components/Slides/index.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,117 @@
import { ReactNode } from 'react';
import { ReactNode, useCallback, useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';

import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from '@/designsystem/ui/card';
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from '@/designsystem/ui/carousel';
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
} from '@/designsystem/ui/pagination';
import { Separator } from '@/designsystem/ui/separator';

export const Slides = ({
slides,
}: {
slides: { title: string; content: ReactNode }[];
}) => {
const { page: page, onChangePage: onChangePage } = usePage({
minPage: 1,
maxPage: slides.length,
});

const slide = slides[page - 1];

useEffect(() => {
const keydownHandler = (event: KeyboardEvent) => {
if (event.key === 'ArrowRight') onChangePage(page + 1);
else if (event.key === 'ArrowLeft') onChangePage(page - 1);
};

window.addEventListener('keydown', keydownHandler);
return () => {
window.removeEventListener('keydown', keydownHandler);
};
}, [page, onChangePage]);

if (slide === undefined) return null;

return (
<Carousel className="mx-24 h-full" opts={{ duration: 15 }}>
<CarouselContent className="h-full">
{slides.map((slide, index) => (
<CarouselItem className="h-full" key={slide.title + index.toString()}>
<Card className="flex h-full flex-col overflow-y-scroll">
<CardHeader>
<CardTitle>{slide.title}</CardTitle>
</CardHeader>

<Separator />

<CardContent className="flex flex-1 items-center justify-center py-8">
{slide.content}
</CardContent>

<Separator />

<CardFooter className="flex justify-center pb-2 pt-2 text-xs">
{index + 1}/{slides.length}
</CardFooter>
</Card>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
<div className="flex h-full flex-col gap-4">
<Card key={page} className="flex flex-1 flex-col overflow-y-scroll">
<CardHeader>
<CardTitle>{slide.title}</CardTitle>
</CardHeader>

<Separator />

<CardContent className="flex flex-1 items-center justify-center py-8">
{slide.content}
</CardContent>
</Card>
<Pagination>
<PaginationContent>
{Array.from({ length: slides.length }, (_, i) => {
const itemPage = i + 1;
return (
<PaginationItem
key={itemPage}
onClick={() => {
onChangePage(itemPage);
}}
>
<PaginationLink
isActive={itemPage === page}
className="cursor-pointer"
>
{itemPage}
</PaginationLink>
</PaginationItem>
);
})}
</PaginationContent>
</Pagination>
</div>
);
};

const usePage = ({
maxPage: maxPage,
minPage: minPage,
}: {
maxPage: number;
minPage: number;
}) => {
const key = 'page';
const [searchParams, setSearchParams] = useSearchParams();

const pageParams = searchParams.get(key);

const page = (() => {
const calculatedPage =
pageParams !== null && `${parseInt(pageParams)}` === pageParams
? parseInt(pageParams)
: 1;

if (calculatedPage < minPage) return minPage;
if (calculatedPage > maxPage) return maxPage;
return calculatedPage;
})();

const onChangePage = useCallback(
(newPage: number) => {
if (newPage < 1 || newPage > maxPage) return;
const newSearchParams = new URLSearchParams(searchParams);
newSearchParams.set(key, newPage.toString());
setSearchParams(newSearchParams, { replace: true });
},
[searchParams, setSearchParams, maxPage],
);

return { page, onChangePage };
};
Loading

0 comments on commit b5e7259

Please sign in to comment.