From 7fb080e76c7e7d95af05dc13a82a0e48607d869c Mon Sep 17 00:00:00 2001 From: HugoHMZ Date: Thu, 19 Dec 2024 20:56:35 +0900 Subject: [PATCH] [+] PopupManager: Adding Provider and the PopupShell, that can be used with Basic, Mulligan and Concede Variants --- .../_sharedcomponents/Popup/Popup.styles.ts | 69 +++++++++++++++++++ .../_sharedcomponents/Popup/Popup.tsx | 46 +++++++++++++ .../_sharedcomponents/Popup/Popup.types.ts | 19 +++++ .../Popup/PopupVariant/ConcedePopup.tsx | 36 ++++++++++ .../Popup/PopupVariant/DefaultPopup.tsx | 29 ++++++++ .../Popup/PopupVariant/MulliganPopup.tsx | 32 +++++++++ src/app/_contexts/Popup.context.tsx | 59 ++++++++++++++++ src/app/layout.tsx | 25 ++++--- 8 files changed, 306 insertions(+), 9 deletions(-) create mode 100644 src/app/_components/_sharedcomponents/Popup/Popup.styles.ts create mode 100644 src/app/_components/_sharedcomponents/Popup/Popup.tsx create mode 100644 src/app/_components/_sharedcomponents/Popup/Popup.types.ts create mode 100644 src/app/_components/_sharedcomponents/Popup/PopupVariant/ConcedePopup.tsx create mode 100644 src/app/_components/_sharedcomponents/Popup/PopupVariant/DefaultPopup.tsx create mode 100644 src/app/_components/_sharedcomponents/Popup/PopupVariant/MulliganPopup.tsx create mode 100644 src/app/_contexts/Popup.context.tsx diff --git a/src/app/_components/_sharedcomponents/Popup/Popup.styles.ts b/src/app/_components/_sharedcomponents/Popup/Popup.styles.ts new file mode 100644 index 00000000..48612093 --- /dev/null +++ b/src/app/_components/_sharedcomponents/Popup/Popup.styles.ts @@ -0,0 +1,69 @@ +export const buttonStyle = { + borderRadius: "15px", + backgroundColor: "#1E2D32", + padding: "1rem 1.5rem", + + border: "2px solid transparent", + background: + "linear-gradient(#1E2D32, #1E2D32) padding-box, linear-gradient(to top, #038FC3, #595A5B) border-box", + "&:hover": { + background: "hsl(195, 25%, 16%)", + }, +}; + +export const overlayStyle = { + position: "fixed" as const, + inset: "0", + backgroundColor: "rgba(0, 0, 0, 0.5)", + display: "flex", + justifyContent: "center", + alignItems: "center", + zIndex: 50, +}; + +export const concedeButtonStyle = { + padding: "1rem 1.5rem", + borderRadius: "15px", + backgroundImage: "linear-gradient(#1E2D32, #1E2D32)", + border: "2px solid transparent", + background: + "linear-gradient(#380707, #380707) padding-box, linear-gradient(to top, #C30101, #7D0807) border-box", +}; + +export const contentStyle = { + padding: "2rem", + borderRadius: "15px", + width: "90%", + maxWidth: "500px", + height: "260px", + position: "relative" as const, + + border: "2px solid transparent", + background: + "linear-gradient(#0F1F27, #030C13) padding-box, linear-gradient(to top, #30434B, #50717D) border-box", +}; + +export const containerStyle = { + alignItems: "center", + justifyContent: "center", + display: "flex", + flexDirection: "column", + textAlign: "center", +}; + +export const minimalButtonStyle = { + position: "absolute", + top: "0.5rem", + right: "0.5rem", + color: "white", +}; + +export const titleStyle = { + color: "white", + fontSize: "1.25rem", + fontWeight: "bold", +}; + +export const textStyle = { + color: "#C7C7C7", +}; diff --git a/src/app/_components/_sharedcomponents/Popup/Popup.tsx b/src/app/_components/_sharedcomponents/Popup/Popup.tsx new file mode 100644 index 00000000..2a3c4e40 --- /dev/null +++ b/src/app/_components/_sharedcomponents/Popup/Popup.tsx @@ -0,0 +1,46 @@ +"use client"; +import { PopupData, PopupType, usePopup } from "@/app/_contexts/Popup.context"; +import { Box, IconButton } from "@mui/material"; +import React from "react"; +import { BiMinus } from "react-icons/bi"; +import { contentStyle, minimalButtonStyle, overlayStyle } from "./Popup.styles"; +import { ConcedePopup, DefaultPopup, MulliganPopup } from "./Popup.types"; +import { ConcededPopupModal } from "./PopupVariant/ConcedePopup"; +import { DefaultPopupModal } from "./PopupVariant/DefaultPopup"; +import { MulliganPopupModal } from "./PopupVariant/MulliganPopup"; + +const PopupShell: React.FC = () => { + const { type, data, closePopup } = usePopup(); + + if (!type || !data) return null; // No popup to display + + const renderPopup = (type: PopupType, data: PopupData) => { + switch (type) { + case "default": + return ; + case "mulligan": + return ; + case "concede": + return ; + default: + return null; + } + }; + + return ( + + + + + + {renderPopup(type, data)} + + + ); +}; + +export default PopupShell; diff --git a/src/app/_components/_sharedcomponents/Popup/Popup.types.ts b/src/app/_components/_sharedcomponents/Popup/Popup.types.ts new file mode 100644 index 00000000..204592f1 --- /dev/null +++ b/src/app/_components/_sharedcomponents/Popup/Popup.types.ts @@ -0,0 +1,19 @@ +export type DefaultPopup = { + type: "default"; + title: string; + description: string; + onConfirm: () => void; + onCancel: () => void; +}; + +export type MulliganPopup = { + type: "mulligan"; + onDraw: () => void; + onKeep: () => void; +}; + +export type ConcedePopup = { + type: "concede"; + onConcede: () => void; + onCancel: () => void; +}; diff --git a/src/app/_components/_sharedcomponents/Popup/PopupVariant/ConcedePopup.tsx b/src/app/_components/_sharedcomponents/Popup/PopupVariant/ConcedePopup.tsx new file mode 100644 index 00000000..5041b19f --- /dev/null +++ b/src/app/_components/_sharedcomponents/Popup/PopupVariant/ConcedePopup.tsx @@ -0,0 +1,36 @@ +import { Box, Button, Typography } from "@mui/material"; +import { + buttonStyle, + concedeButtonStyle, + containerStyle, + textStyle, + titleStyle, +} from "../Popup.styles"; +import { ConcedePopup } from "../Popup.types"; + +interface ButtonProps { + data: ConcedePopup; +} + +export const ConcededPopupModal = ({ data }: ButtonProps) => { + return ( + + Would you like to concede? + + Concede will end the game and declare you as the loser. + + + + + + + ); +}; diff --git a/src/app/_components/_sharedcomponents/Popup/PopupVariant/DefaultPopup.tsx b/src/app/_components/_sharedcomponents/Popup/PopupVariant/DefaultPopup.tsx new file mode 100644 index 00000000..b7245cf7 --- /dev/null +++ b/src/app/_components/_sharedcomponents/Popup/PopupVariant/DefaultPopup.tsx @@ -0,0 +1,29 @@ +import { Box, Button, Typography } from "@mui/material"; +import { + buttonStyle, + containerStyle, + textStyle, + titleStyle, +} from "../Popup.styles"; +import { DefaultPopup } from "../Popup.types"; + +interface ButtonProps { + data: DefaultPopup; +} + +export const DefaultPopupModal = ({ data }: ButtonProps) => { + return ( + + {data.title} + {data.description} + + + + + + ); +}; diff --git a/src/app/_components/_sharedcomponents/Popup/PopupVariant/MulliganPopup.tsx b/src/app/_components/_sharedcomponents/Popup/PopupVariant/MulliganPopup.tsx new file mode 100644 index 00000000..3127ecd2 --- /dev/null +++ b/src/app/_components/_sharedcomponents/Popup/PopupVariant/MulliganPopup.tsx @@ -0,0 +1,32 @@ +import { Box, Button, Typography } from "@mui/material"; +import { + buttonStyle, + containerStyle, + textStyle, + titleStyle, +} from "../Popup.styles"; +import { MulliganPopup } from "../Popup.types"; + +interface ButtonProps { + data: MulliganPopup; +} + +export const MulliganPopupModal = ({ data }: ButtonProps) => { + return ( + + Would you like to mulligan? + + Mulligan will replace your initial 6 cards with another 6 new\nones. + This action can only be done one time! + + + + + + + ); +}; diff --git a/src/app/_contexts/Popup.context.tsx b/src/app/_contexts/Popup.context.tsx new file mode 100644 index 00000000..98a59cef --- /dev/null +++ b/src/app/_contexts/Popup.context.tsx @@ -0,0 +1,59 @@ +"use client"; +import React, { createContext, useContext, useState } from "react"; +import { + ConcedePopup, + DefaultPopup, + MulliganPopup, +} from "../_components/_sharedcomponents/Popup/Popup.types"; + +// TODO: SelectCardsPopup | LeaderAbilityPopup | DrawPopup | SelectCardsWithAspectPopup +export type PopupData = DefaultPopup | MulliganPopup | ConcedePopup; + +export type PopupType = PopupData["type"]; + +export type PopupDataMap = { + default: Omit; + mulligan: Omit; + concede: Omit; +}; + +interface PopupContextProps { + type?: PopupType; + data?: PopupData; + openPopup: (type: T, data: PopupDataMap[T]) => void; + closePopup: () => void; +} + +const PopupContext = createContext(undefined); + +export const PopupProvider: React.FC<{ children: React.ReactNode }> = ({ + children, +}) => { + const [type, setType] = useState(undefined); + const [data, setData] = useState(undefined); + + const openPopup = (type: T, data: PopupDataMap[T]) => { + setType(type); + setData({ type, ...data } as PopupData); + }; + + const closePopup = () => { + console.log("Closing popup"); + setType(undefined); + setData(undefined); + }; + + return ( + + {children} + + ); +}; + +export const usePopup = () => { + const context = useContext(PopupContext); + if (!context) { + throw new Error("usePopup must be used within a PopupProvider"); + } + return context; +}; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index cfacee27..ec8221da 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,26 +1,33 @@ // layout.tsx import type { Metadata } from "next"; -import React from 'react'; -import ClientLayout from './ClientLayout'; import { Barlow } from "next/font/google"; +import React from "react"; +import { PopupProvider } from "./_contexts/Popup.context"; import "./_utils/s3Utils"; +import ClientLayout from "./ClientLayout"; const barlow = Barlow({ - subsets: ["latin"], - weight: ["400", "600", "800"], - variable: "--font-barlow", + subsets: ["latin"], + weight: ["400", "600", "800"], + variable: "--font-barlow", }); export const metadata: Metadata = { - title: "Karabast", + title: "Karabast", }; -export default function RootLayout({ children }: { children: React.ReactNode }) { +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { return ( - {children} + + {children} + ); -} \ No newline at end of file +}