diff --git a/package.json b/package.json index e9ae144..00d9037 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "@dnd-kit/sortable": "^8.0.0", "@radix-ui/react-dialog": "^1.1.1", "@shadow-panda/style-context": "^0.7.1", - "lucide-react": "^0.439.0", "next": "14.2.8", "react": "^18", "react-dom": "^18" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a83bc4a..f72bb42 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,9 +20,6 @@ importers: '@shadow-panda/style-context': specifier: ^0.7.1 version: 0.7.1(@types/react-dom@18.3.0)(@types/react@18.3.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - lucide-react: - specifier: ^0.439.0 - version: 0.439.0(react@18.3.1) next: specifier: 14.2.8 version: 14.2.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1608,11 +1605,6 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lucide-react@0.439.0: - resolution: {integrity: sha512-PafSWvDTpxdtNEndS2HIHxcNAbd54OaqSYJO90/b63rab2HWYqDbH194j0i82ZFdWOAcf0AHinRykXRRK2PJbw==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc - magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} @@ -4052,10 +4044,6 @@ snapshots: lru-cache@10.4.3: {} - lucide-react@0.439.0(react@18.3.1): - dependencies: - react: 18.3.1 - magic-string@0.30.11: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 diff --git a/public/card-backs/atlas.webp b/public/card-backs/atlas.webp new file mode 100644 index 0000000..8de4f20 Binary files /dev/null and b/public/card-backs/atlas.webp differ diff --git a/public/card-backs/m_atlas.png b/public/card-backs/m_atlas.png new file mode 100644 index 0000000..4b0307b Binary files /dev/null and b/public/card-backs/m_atlas.png differ diff --git a/public/card-backs/m_spells.png b/public/card-backs/m_spells.png new file mode 100644 index 0000000..3d634ef Binary files /dev/null and b/public/card-backs/m_spells.png differ diff --git a/src/components/atoms/card-view/card.tsx b/src/components/atoms/card-view/card.tsx index ee528de..41500a2 100644 --- a/src/components/atoms/card-view/card.tsx +++ b/src/components/atoms/card-view/card.tsx @@ -31,7 +31,7 @@ export const CardImage = ({ backgroundRepeat="no-repeat" transition="all 0.25s ease" // bg="gray.400" - />{" "} + /> ); }; diff --git a/src/components/atoms/mock-cards/atlas.tsx b/src/components/atoms/mock-cards/atlas.tsx index 2c84c2c..fccc74f 100644 --- a/src/components/atoms/mock-cards/atlas.tsx +++ b/src/components/atoms/mock-cards/atlas.tsx @@ -1,56 +1,36 @@ -import { useHover } from "@/utils/hooks/useHover"; -import { useKeyPress } from "@/utils/hooks/useKeyPress"; -import { useEffect, useRef, useState } from "react"; import { Box } from "styled-system/jsx"; export const CardAtlas = ({ + height = "90px", img = "atlas_rift_valley.webp", }: { img?: string; + height?: string; }) => { - const hoverRef = useRef(null); - const isHovering = useHover(hoverRef); - - const isPressed = useKeyPress("Alt"); - const [preview, setPreview] = useState(false); - useEffect(() => { - if (isHovering && isPressed) { - setPreview((prev) => !prev); - } - }, [isPressed]); - - // const show = preview && isHovering; // full preview of the card - const show = false; return ( setPreview(false)} + overflow="clip" + style={{ height }} > { const hoverRef = useRef(null); const isHovering = useHover(hoverRef); @@ -32,10 +34,9 @@ export const CardImage = ({ return ( setPreview(false)} + style={{ height }} > { return ( @@ -14,8 +15,8 @@ export const Auras = (props: GameStateActions) => { {Array.from({ length: 12 }).map((_, index) => ( ))} @@ -26,7 +27,7 @@ export const Auras = (props: GameStateActions) => { const Aura = (props: { card: GameCard; gridIndex: number; index: number }) => { const auraCard = props.card; - const auraIndex = props.gridIndex - 21; // normalize to zero + const auraIndex = props.gridIndex - GRIDS.AURA_1; // normalize to zero const topIndex = Math.floor(auraIndex / 4) + 1; // increments every 4 const top = `${topIndex * 25}%`; // in percent const leftIndex = 1 + (auraIndex % 4); // every 4, resets diff --git a/src/components/organisms/GameBoard/Footer/Decks.tsx b/src/components/organisms/GameBoard/Footer/Decks.tsx new file mode 100644 index 0000000..4941240 --- /dev/null +++ b/src/components/organisms/GameBoard/Footer/Decks.tsx @@ -0,0 +1,94 @@ +import { Grid, VStack } from "styled-system/jsx"; +import { GRIDS, LAYOUT_HEIGHTS } from "../constants"; +import { GameStateActions } from ".."; + +export const DecksTray = (props: GameStateActions) => { + function draw(deck: GRIDS.DECK | GRIDS.ATLAS_DECK) { + props.setGridItems((prev) => { + // Create a shallow copy of the previous grid items array + const newGridItems = [...prev]; + + // Make a copy of the deck and hand arrays, preserving their positions + const newDeck = [...newGridItems[deck]]; + const newHand = [...newGridItems[GRIDS.HAND]]; + + // Pop a card from the deck and push it to the hand + const card = newDeck.pop(); + if (card) newHand.push(card); + + // Update the newGridItems array with the updated deck and hand arrays + newGridItems[deck] = newDeck; + newGridItems[GRIDS.HAND] = newHand; + + // Return the updated newGridItems array to trigger a re-render + return newGridItems; + }); + } + + function drawDeck() { + draw(GRIDS.DECK); + } + function drawAtlas() { + draw(GRIDS.ATLAS_DECK); + } + + const atlasRemainingCards = props.gridItems[GRIDS.ATLAS_DECK]?.length; + const deckRemainingCards = props.gridItems[GRIDS.DECK]?.length; + + return ( + + +

+ {atlasRemainingCards} +

+
+ +

+ {deckRemainingCards} +

+
+
+ ); +}; diff --git a/src/components/organisms/GameBoard/Footer/index.tsx b/src/components/organisms/GameBoard/Footer/index.tsx index 2af73c0..7116916 100644 --- a/src/components/organisms/GameBoard/Footer/index.tsx +++ b/src/components/organisms/GameBoard/Footer/index.tsx @@ -1,5 +1,5 @@ -import { Grid, HStack } from "styled-system/jsx"; -import { LAYOUT_HEIGHTS } from "../constants"; +import { Box, Grid, HStack } from "styled-system/jsx"; +import { GRIDS, LAYOUT_HEIGHTS } from "../constants"; import { DroppableGridItem } from "@/components/molecules/DropGridItem"; import { horizontalListSortingStrategy, @@ -9,9 +9,10 @@ import { GameStateActions } from ".."; 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"; export const GameFooter = (props: GameStateActions) => { - const gridIndex = 20; + const gridIndex = GRIDS.HAND; const cardsInHand = props.gridItems[gridIndex] ?? []; return ( @@ -23,9 +24,9 @@ export const GameFooter = (props: GameStateActions) => { overflowX: "auto", }} > - -

Grave

-

Deck

+ + Grave + { )} strategy={horizontalListSortingStrategy} > - + {props.gridItems?.[gridIndex]?.map((card, index) => (
>; }; export const GameBoard = ({ gridItems, setGridItems }: GameStateActions) => { const { handleDragEnd, handleDragStart, activeId, activeCard } = @@ -58,7 +58,7 @@ export const GameBoard = ({ gridItems, setGridItems }: GameStateActions) => { onDragEnd={handleDragEnd} collisionDetection={collision} > - + {gridItems?.slice(0, 20)?.map((cards, gridIndex) => ( { strategy={rectSortingStrategy} > {cards.map((card, cardIndex) => ( - + ))} @@ -91,6 +95,7 @@ export const GameBoard = ({ gridItems, setGridItems }: GameStateActions) => { }; const SortItemWrapper = ({ + amountOfCards = 0, card, gridIndex, cardIndex, @@ -98,8 +103,11 @@ const SortItemWrapper = ({ card: GameCard; gridIndex: number; cardIndex: number; + amountOfCards?: number; }) => { const [preview, setPreview] = useState(false); + const heightCalc = 90 - Math.min(amountOfCards, 4) * 15; + const height = `${heightCalc}px`; return (
- {card.type === "site" && } - {card.type !== "site" && } + {card.type === "site" && } + {card.type !== "site" && } [ - // { - // id: `atlas-ab${gridIndex}`, - // img: "atlas_rift_valley.webp", - // type: "site", - // } as GameCard, // Each droppable starts with a single card -]); -const customCards: GameCard[][] = [ - [ - { - id: "headless-01", - img: "headless_haunt.webp", - type: "minion", - }, - ], - [ - { - id: "atlas-01", - img: "atlas_cloud_city.webp", - type: "site", - }, - ], -]; - const handCards: GameCard[] = [ { id: "atlas-02", @@ -49,25 +26,26 @@ const handCards: GameCard[] = [ }, ]; -const auraCards = Array.from({ length: 12 }, (_, gridIndex) => []); +const deckCards = Array.from({ length: 30 }).map((_, index) => ({ + id: "headless-ab-" + index, + img: "headless_haunt.webp", + type: "minion", +})); -/** - * gridIndexes - * 0-19 grid - * 20 hand - * 21-33 aura - * */ +const atlasCards = Array.from({ length: 10 }).map((_, index) => ({ + id: "atlas-02" + index, + img: "atlas_cloud_city.webp", + type: "site", +})); + +const initCards: GameCard[][] = Array.from({ length: 35 }, () => []); +initCards[GRIDS.HAND] = handCards as GameCard[]; +initCards[GRIDS.DECK] = deckCards as GameCard[]; +initCards[GRIDS.ATLAS_DECK] = atlasCards as GameCard[]; export type GameCard = SorceryCard & { id: string }; // for game position export default function GamePage() { - const [gridItems, setGridItems] = useState([ - ...initCards, - ...customCards, - handCards, - ...auraCards, - ]); - - console.log(gridItems.length, "length"); + const [gridItems, setGridItems] = useState(initCards); return ; }