Skip to content

Commit

Permalink
feat: GameRoom 컴포넌트 생성 및 Pagination UI 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
studioOwol committed Nov 5, 2024
1 parent 55e2348 commit 34e5803
Show file tree
Hide file tree
Showing 12 changed files with 364 additions and 40 deletions.
31 changes: 30 additions & 1 deletion fe/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion fe/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"react-router-dom": "^6.27.0",
"tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7",
"uuid": "^11.0.2"
"uuid": "^11.0.2",
"zustand": "^5.0.1"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
Expand Down
36 changes: 0 additions & 36 deletions fe/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,3 @@
padding: 2rem;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}

@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

.card {
padding: 2em;
}

.read-the-docs {
color: #888;
}
36 changes: 36 additions & 0 deletions fe/src/components/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
)

export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}

function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
)
}

export { Badge, badgeVariants }
79 changes: 79 additions & 0 deletions fe/src/components/ui/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import * as React from "react"

import { cn } from "@/lib/utils"

const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-lg border bg-card text-card-foreground shadow-sm",
className
)}
{...props}
/>
))
Card.displayName = "Card"

const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
))
CardHeader.displayName = "CardHeader"

const CardTitle = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"text-2xl font-semibold leading-none tracking-tight",
className
)}
{...props}
/>
))
CardTitle.displayName = "CardTitle"

const CardDescription = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
CardDescription.displayName = "CardDescription"

const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
))
CardContent.displayName = "CardContent"

const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
))
CardFooter.displayName = "CardFooter"

export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
32 changes: 30 additions & 2 deletions fe/src/pages/RoomPage/RoomDialog/RoomDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,23 @@ import {
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import useRoomStore from '@/store/useRoomStore';
import { RoomDialogProps } from '@/types/room';
import { useState } from 'react';

const RoomDialog = ({ open, onOpenChange }: RoomDialogProps) => {
const [roomName, setRoomName] = useState('');
const [nickname, setNickname] = useState('');

const addRoom = useRoomStore((state) => state.addRoom);

const handleSubmit = () => {
addRoom(roomName.trim(), nickname.trim());
setRoomName('');
setNickname('');
onOpenChange(false);
};

return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
Expand All @@ -28,6 +42,10 @@ const RoomDialog = ({ open, onOpenChange }: RoomDialogProps) => {
</Label>
<Input
id="roomName"
value={roomName}
onChange={(e) => {
setRoomName(e.target.value);
}}
placeholder="방 제목을 입력하세요"
className="col-span-3"
/>
Expand All @@ -38,6 +56,10 @@ const RoomDialog = ({ open, onOpenChange }: RoomDialogProps) => {
</Label>
<Input
id="nickname"
value={nickname}
onChange={(e) => {
setNickname(e.target.value);
}}
placeholder="닉네임을 입력하세요"
className="col-span-3"
/>
Expand All @@ -47,11 +69,17 @@ const RoomDialog = ({ open, onOpenChange }: RoomDialogProps) => {
<Button
type="button"
variant="outline"
onClick={() => onOpenChange(false)}
onClick={() => {
setRoomName('');
setNickname('');
onOpenChange(false);
}}
>
취소
</Button>
<Button type="button">확인</Button>
<Button type="button" onClick={handleSubmit}>
확인
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
Expand Down
42 changes: 42 additions & 0 deletions fe/src/pages/RoomPage/RoomList/GameRoom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { GameRoomProps } from '@/types/room';
import { FaCircle, FaCrown, FaUsers } from 'react-icons/fa6';

const GameRoom = ({ room }: GameRoomProps) => {
return (
<Card className="flex w-full mt-2">
<CardHeader className="space-y-1">
<div className="flex items-center justify-between">
<CardTitle className="text-xl">{room.name}</CardTitle>
</div>
<div className="space-y-2 text-md text-muted-foreground px-1">
<div className="flex items-center gap-2">
<FaCrown className="text-yellow-500" />
<span>방장: {room.creator}</span>
</div>
<div className="flex items-center gap-2">
<FaCircle
className={`text-sm ${room.isGameStarted ? 'text-red-500' : 'text-green-500'}`}
/>
<span>
상태:{' '}
<span
className={
room.isGameStarted ? 'text-red-500' : 'text-green-500'
}
>
{room.isGameStarted ? '게임 중' : '대기 중'}
</span>
</span>
</div>
<div className="flex items-center gap-2">
<FaUsers className="text-gray-500" />
<span>인원 수: {room.players.length} / 4</span>
</div>
</div>
</CardHeader>
</Card>
);
};

export default GameRoom;
45 changes: 45 additions & 0 deletions fe/src/pages/RoomPage/RoomList/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Button } from '@/components/ui/button';
import { PaginationProps } from '@/types/room';
import { FaChevronLeft, FaChevronRight } from 'react-icons/fa6';

const Pagination = ({
currentPage,
totalPages,
onPageChange,
}: PaginationProps) => {
return (
<div className="flex items-center justify-center gap-4 mt-6">
<Button
variant="outline"
size="icon"
onClick={() => onPageChange(currentPage - 1)}
disabled={currentPage === 0}
>
<FaChevronLeft className="w-4 h-4" />
</Button>
<div className="flex items-center gap-2">
{Array.from({ length: totalPages }, (_, i) => (
<Button
key={i}
variant={currentPage === i ? 'default' : 'outline'}
size="sm"
onClick={() => onPageChange(i)}
className="w-8 h-8"
>
{i + 1}
</Button>
))}
</div>
<Button
variant="outline"
size="icon"
onClick={() => onPageChange(currentPage + 1)}
disabled={currentPage === totalPages - 1}
>
<FaChevronRight className="w-4 h-4" />
</Button>
</div>
);
};

export default Pagination;
Loading

0 comments on commit 34e5803

Please sign in to comment.