Skip to content

Commit

Permalink
feat: create player notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
ItaloMedici committed Aug 17, 2024
1 parent a3a8225 commit d9d863c
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 60 deletions.
74 changes: 74 additions & 0 deletions app/(dashboard)/room/[roomId]/_components/board-toolbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { useBoard } from "@/context/board";
import { cn } from "@/lib/utils";

const MAX_AVATAR_DISPLAY = 5;

export const BoardToolbar = () => {
const { others, self, handleRevealCards, reveal, handleReset } = useBoard();

if (!others.length) {
return null;
}

const onRevealClick = () => {
if (reveal) {
handleReset();
}
handleRevealCards();
};

const playersAvatar = () => {
let avatarList = [self, ...others].map((player) => ({
name: player.name
.split(" ")
.map((name) => name[0])
.slice(0, 2)
.join(""),
imageUrl: player.imageUrl ?? undefined,
}));

if (avatarList.length > MAX_AVATAR_DISPLAY) {
avatarList = avatarList.slice(0, MAX_AVATAR_DISPLAY);
avatarList.push({
name: `+${others.length - MAX_AVATAR_DISPLAY}`,
imageUrl: undefined,
});
}

return (
<div className="flex items-center gap-[-4px]">
{avatarList.map((player, index) => (
<Avatar
key={player.name}
className={cn("border-2 border-white", {
"-ml-2": index > 0,
})}
>
<AvatarImage src={player.imageUrl ?? undefined} />
<AvatarFallback className="text-xs bg-gradient-to-tr from-sky-300 to-gray-300 ">
{player.name}
</AvatarFallback>
</Avatar>
))}
</div>
);
};

return (
<div className=" border border-gray-200 p-2 rounded-xl flex items-center justify-between gap-2">
<Button onClick={onRevealClick} size={"sm"}>
{reveal ? "Iniciar outro jogo" : "Revelar cartas 👀"}
</Button>

<Button variant={"ghost"} onClick={handleReset} size={"sm"}>
Limpar
</Button>

<hr className="w-[1px] border-l border-gray-200 h-full" />

{playersAvatar()}
</div>
);
};
15 changes: 6 additions & 9 deletions app/(dashboard)/room/[roomId]/_components/board.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
"use client";

import { useBoard } from "@/context/board";
import { BoardNavbar } from "./board-navbar";
import { BoardToolbar } from "./board-toolbar";
import { CardsPicker } from "./cards-picker";
import { PlayersCards } from "./players-cards";
import { Deck } from "./deck";

export function Board() {
const { self, others } = useBoard();

return (
<div className="absolute inset-0 -z-10 h-full w-full bg-gray-50">
<div className="absolute inset-0 -z-10 h-full w-full bg-gray-50 overflow-hidden">
<BoardNavbar />
<div className="flex h-full items-center justify-center px-6">
<PlayersCards />
</div>
<div className="fixed w-full bottom-16 mx-auto px-6">
<div className="flex h-full flex-col items-center justify-between gap-6 p-4 pt-20 pb-12">
<BoardToolbar />
<Deck />
<CardsPicker />
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/(dashboard)/room/[roomId]/_components/cards-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { useBoard } from "@/context/board";
import { cn } from "@/lib/utils";

export const CardsPicker = () => {
const { choiceOptions, handleChoice, self } = useBoard();
const { choiceOptions, handleChoice, selfChoice } = useBoard();

const isSelfOption = (option: string) => self.choice === option;
const isSelfOption = (option: string) => selfChoice == option;

return (
<div className="flex flex-col items-center justify-center flex-wrap gap-6">
Expand Down
25 changes: 25 additions & 0 deletions app/(dashboard)/room/[roomId]/_components/deck.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useBoard } from "@/context/board";
import { PlayerCard } from "./player-card";

export const Deck = () => {
const { others, self } = useBoard();

const players = [self, ...others];

if (!others.length) {
return (
<div className="flex items-center justify-center h-full">
<p className="text-gray-500">Sozinho por aqui... 😴</p>
{/* adicionar botão de convidar */}
</div>
);
}

return (
<div className="grid grid-cols-4 gap-4">
{players.map((player) => (
<PlayerCard key={player.id} player={player} />
))}
</div>
);
};
7 changes: 5 additions & 2 deletions app/(dashboard)/room/[roomId]/_components/player-card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NumericCard } from "@/components/card/numeric-card";
import { useBoard } from "@/context/board";
import { Player } from "@/lib/schemas/player";
import { PlayerNotificationPopup } from "./player-notification-popup";

type PlayerCardProps = {
player: Player;
Expand All @@ -20,19 +21,21 @@ export const PlayerCard = ({ player }: PlayerCardProps) => {
<>
{isSelf ? (
<NumericCard
value={player.choice}
color={player.choice ? "primary" : "gray"}
value={selfChoice}
color={selfChoice ? "primary" : "gray"}
size={"large"}
label={"Você"}
/>
) : (
<PlayerNotificationPopup player={player}>
<NumericCard
value={formatedChoice}
color={reveal && player.choice ? "primary" : "gray"}
bgColor={reveal ? "white" : player.choice ? "primary" : "gray"}
size={"large"}
label={player.name}
/>
</PlayerNotificationPopup>
)}
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { useBoard } from "@/context/board";
import { Player } from "@/lib/schemas/player";
import { cn } from "@/lib/utils";
import { notificationIcons } from "@/messages/notification";
import { EnumNotification } from "@/types/notifications";
import {
Popover,
PopoverContent,
PopoverPortal,
PopoverTrigger,
} from "@radix-ui/react-popover";
import { ReactNode, useState } from "react";

export function PlayerNotificationPopup({
children,
player,
}: {
children: ReactNode;
player: Player;
}) {
const { handleNotifyPlayer } = useBoard();
const [open, setOpen] = useState(false);

const onNotifificationClick = (notification: EnumNotification) => {
setOpen(false);
if (player.choice) return;

handleNotifyPlayer(player.id, notification);
};

return (
<Popover open={open} onOpenChange={(open) => setOpen(open)}>
<PopoverTrigger
onClick={() => setOpen((prev) => !prev)}
disabled={!!player.choice}
>
<div
className={cn(
"before:absolute before:top-1/2 before:-translate-x-1/2 before:-translate-y-full before:z-10 before:scale-0 before:hover:scale-100 before:transition-transform relative",
{
"before:content-['🔉']": !player.choice,
"before:scale-100": open,
}
)}
>
{children}
</div>
</PopoverTrigger>
<PopoverPortal>
<PopoverContent side="top" sideOffset={10}>
<div className="flex items-center rounded-full p-1 bg-white shadow-md gap-4 border border-gray-200">
{Object.keys(notificationIcons).map((notification) => (
<div
key={notification}
role="presentation"
onClick={() =>
onNotifificationClick(notification as EnumNotification)
}
className="p-1 w-10 cursor-pointer aspect-square rounded-full hover:bg-gray-100"
>
<span className="text-2xl flex items-center justify-center">
{notificationIcons[notification as EnumNotification]}
</span>
</div>
))}
</div>
</PopoverContent>
</PopoverPortal>
</Popover>
);
}
45 changes: 0 additions & 45 deletions app/(dashboard)/room/[roomId]/_components/players-cards.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion components/ui/avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const Avatar = React.forwardRef<
<AvatarPrimitive.Root
ref={ref}
className={cn(
"relative flex h-8 w-8 mt-[6px] shrink-0 overflow-hidden rounded-full",
"relative flex h-8 w-8 shrink-0 overflow-hidden rounded-full",
className
)}
{...props}
Expand Down
2 changes: 1 addition & 1 deletion components/user-button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const UserButton = () => {
<div>
<Popover>
<PopoverTrigger>
<Avatar className="outline outline-2 outline-offset-2 outline-sky-500">
<Avatar className="outline outline-2 mt-[6px] outline-offset-2 outline-sky-500">
<AvatarImage src={user.image} />
<AvatarFallback>{fallback()}</AvatarFallback>
</Avatar>
Expand Down
Binary file added public/sounds/car_horn.mp3
Binary file not shown.
Binary file added public/sounds/knock.mp3
Binary file not shown.
Binary file added public/sounds/police.mp3
Binary file not shown.

0 comments on commit d9d863c

Please sign in to comment.