diff --git a/package.json b/package.json
index 4b5d3f6..19fbd51 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,8 @@
"axios": "^1.7.7",
"next": "14.2.8",
"react": "^18",
- "react-dom": "^18"
+ "react-dom": "^18",
+ "react-icons": "^5.3.0"
},
"devDependencies": {
"@pandacss/dev": "^0.45.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4341f5e..2b29892 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -38,6 +38,9 @@ importers:
react-dom:
specifier: ^18
version: 18.3.1(react@18.3.1)
+ react-icons:
+ specifier: ^5.3.0
+ version: 5.3.0(react@18.3.1)
devDependencies:
'@pandacss/dev':
specifier: ^0.45.2
@@ -1949,6 +1952,11 @@ packages:
peerDependencies:
react: ^18.3.1
+ react-icons@5.3.0:
+ resolution: {integrity: sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==}
+ peerDependencies:
+ react: '*'
+
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@@ -4424,6 +4432,10 @@ snapshots:
react: 18.3.1
scheduler: 0.23.2
+ react-icons@5.3.0(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
react-is@16.13.1: {}
react-remove-scroll-bar@2.3.6(@types/react@18.3.5)(react@18.3.1):
diff --git a/src/components/atoms/Modal/index.tsx b/src/components/atoms/Modal/index.tsx
index fd2ea56..2d458a8 100644
--- a/src/components/atoms/Modal/index.tsx
+++ b/src/components/atoms/Modal/index.tsx
@@ -1,7 +1,6 @@
import {
Dialog,
DialogContent,
- DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
@@ -17,12 +16,14 @@ export const Modal = (props: {
}) => {
return (
);
diff --git a/src/components/atoms/card-view/card.tsx b/src/components/atoms/card-view/card.tsx
index 05530c4..85fc009 100644
--- a/src/components/atoms/card-view/card.tsx
+++ b/src/components/atoms/card-view/card.tsx
@@ -4,9 +4,11 @@ import { Box } from "styled-system/jsx";
export const CardImage = ({
img = "headless_haunt.webp",
position = "top",
+ minH = "300px",
}: {
img?: string;
position?: "top" | "bottom";
+ minH?: string;
}) => {
return (
{" "}
diff --git a/src/components/organisms/GameBoard/Footer/Decks.tsx b/src/components/organisms/GameBoard/Footer/Decks.tsx
index 5d00c92..6082f41 100644
--- a/src/components/organisms/GameBoard/Footer/Decks.tsx
+++ b/src/components/organisms/GameBoard/Footer/Decks.tsx
@@ -22,11 +22,13 @@ export const DecksTray = (props: GameStateActions) => {
return (
{
+ function returnToHand(cardIndex: number) {
+ props.setGridItems(actDrawDiscard(props.gridItems, cardIndex));
+ }
+
+ return (
+
+ {props.cards?.map((card, index) => (
+ returnToHand(index)}
+ />
+ ))}
+
+ );
+};
+
+const Card = ({
+ card,
+ returnToHand,
+}: {
+ card: GameCard;
+ returnToHand(): void;
+}) => {
+ const hoverRef = useRef(null);
+ const isHovering = useHover(hoverRef);
+
+ return (
+
+
+
+
+ );
+};
diff --git a/src/components/organisms/GameBoard/Footer/Grave/index.tsx b/src/components/organisms/GameBoard/Footer/Grave/index.tsx
new file mode 100644
index 0000000..c734a16
--- /dev/null
+++ b/src/components/organisms/GameBoard/Footer/Grave/index.tsx
@@ -0,0 +1,114 @@
+import { DroppableGridItem } from "@/components/molecules/DropGridItem";
+import { GRIDS } from "@/components/organisms/GameBoard/constants";
+import { Box, Grid } from "styled-system/jsx";
+
+import { GiPirateGrave as IconGrave } from "react-icons/gi";
+import { CardImage } from "@/components/atoms/card-view/card";
+import { Modal } from "@/components/atoms/Modal";
+import { useState } from "react";
+import { GameStateActions } from "@/components/organisms/GameBoard";
+import { DiscardModalBody } from "./DiscardModal";
+
+export const GraveTray = (props: GameStateActions) => {
+ const graveCards = props.gridItems[GRIDS.GRAVE];
+ const graveAmount = graveCards?.length ?? 0;
+ const hasCards = graveCards?.length > 0;
+
+ const [preview, setPreview] = useState(false);
+
+ return (
+
+
+ {preview && (
+ }
+ />
+ )}
+
+ {hasCards && (
+ {
+ e.preventDefault();
+ setPreview(true);
+ }}
+ onContextMenu={(e) => {
+ e.preventDefault();
+ setPreview(true);
+ }}
+ >
+ {graveAmount > 0 && (
+
+
+
+ )}
+
+ {graveAmount > 1 && (
+
+
+
+ )}
+
+ {graveAmount > 2 && (
+
+
+
+ )}
+
+ {graveAmount > 3 && (
+
+
+
+ )}
+
+ {graveAmount > 4 && (
+
+
+
+ )}
+
+ )}
+
+
+ );
+};
diff --git a/src/components/organisms/GameBoard/Footer/index.tsx b/src/components/organisms/GameBoard/Footer/index.tsx
index 7116916..9cd4d20 100644
--- a/src/components/organisms/GameBoard/Footer/index.tsx
+++ b/src/components/organisms/GameBoard/Footer/index.tsx
@@ -1,4 +1,4 @@
-import { Box, Grid, HStack } from "styled-system/jsx";
+import { Grid, HStack } from "styled-system/jsx";
import { GRIDS, LAYOUT_HEIGHTS } from "../constants";
import { DroppableGridItem } from "@/components/molecules/DropGridItem";
import {
@@ -10,6 +10,7 @@ import { SortableItem } from "@/components/molecules/SortItem";
import { CardAtlas } from "@/components/atoms/mock-cards/atlas";
import { CardImage } from "@/components/atoms/mock-cards/card";
import { DecksTray } from "./Decks";
+import { GraveTray } from "./Grave";
export const GameFooter = (props: GameStateActions) => {
const gridIndex = GRIDS.HAND;
@@ -25,7 +26,7 @@ export const GameFooter = (props: GameStateActions) => {
}}
>
- Grave
+
+
{card.type === "site" && }
{card.type !== "site" && }
diff --git a/src/components/ui/dialog/index.tsx b/src/components/ui/dialog/index.tsx
index 41f4199..91e315f 100644
--- a/src/components/ui/dialog/index.tsx
+++ b/src/components/ui/dialog/index.tsx
@@ -21,7 +21,14 @@ const Content = React.forwardRef<
{children}
{/* */}
diff --git a/src/utils/actions/discard.ts b/src/utils/actions/discard.ts
new file mode 100644
index 0000000..65b0d49
--- /dev/null
+++ b/src/utils/actions/discard.ts
@@ -0,0 +1,22 @@
+import { GRIDS } from "@/components/organisms/GameBoard/constants";
+import { GameState } from "@/types/card";
+
+export function actDrawDiscard(state: GameState, graveCardIndex: number) {
+ // Create a shallow copy of the previous grid items array
+ const newState = [...state];
+
+ // Make a copy of the deck and hand arrays, preserving their positions
+ const newGrave = [...newState[GRIDS.GRAVE]];
+ const newHand = [...newState[GRIDS.HAND]];
+
+ // Pop a card from the deck and push it to the hand
+ const [card] = newGrave.splice(graveCardIndex, 1);
+ if (card) newHand.push(card);
+
+ // Update the newState array with the updated deck and hand arrays
+ newState[GRIDS.GRAVE] = newGrave;
+ newState[GRIDS.HAND] = newHand;
+
+ // Return the updated newState array to trigger a re-render
+ return newState;
+}