From 231d4d09048bd07ebb625e76e6e0482316b5951b Mon Sep 17 00:00:00 2001 From: "Jibran Absarulislam (L-H)" Date: Thu, 10 Jul 2025 03:28:52 -0400 Subject: [PATCH 1/7] include fact in ambassadorSchema --- src/hooks/useAmbassadors.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hooks/useAmbassadors.tsx b/src/hooks/useAmbassadors.tsx index 21aea302..82132a96 100644 --- a/src/hooks/useAmbassadors.tsx +++ b/src/hooks/useAmbassadors.tsx @@ -53,6 +53,7 @@ const apiAmbassadorSchema = ambassadorSchema.extend({ key: z.string(), title: z.string(), }), + fact: z.string().optional(), }); type Ambassador = z.infer; From 88625c7546b25a56bcaa73402605ceb62a151c36 Mon Sep 17 00:00:00 2001 From: "Jibran Absarulislam (L-H)" Date: Thu, 10 Jul 2025 03:30:41 -0400 Subject: [PATCH 2/7] implement MVP front and back, incorporating 'Did you know?' and fact when applicable --- src/components/AmbassadorCard.tsx | 421 ++++++++++++++++++------------ 1 file changed, 248 insertions(+), 173 deletions(-) diff --git a/src/components/AmbassadorCard.tsx b/src/components/AmbassadorCard.tsx index 25e8bbff..f85b4e9e 100644 --- a/src/components/AmbassadorCard.tsx +++ b/src/components/AmbassadorCard.tsx @@ -1,5 +1,5 @@ import type { CreateTypes } from "canvas-confetti"; -import { type Ref, useCallback, useEffect, useRef } from "react"; +import { type Ref, useCallback, useEffect, useRef, useState } from "react"; import Confetti from "react-canvas-confetti"; import { createPortal } from "react-dom"; @@ -48,6 +48,9 @@ export default function AmbassadorCard(props: AmbassadorCardProps) { } = props; const ambassador = useAmbassador(ambassadorKey); + const [flipped, setFlipped] = useState(false); + const flipCard = useCallback(() => setFlipped((prev) => !prev), []); + const mod = window?.Twitch?.ext?.viewer?.role === "broadcaster" || window?.Twitch?.ext?.viewer?.role === "moderator"; @@ -130,6 +133,14 @@ export default function AmbassadorCard(props: AmbassadorCardProps) { !disableCardEffects && "mb-4", className, )} + style={ + ambassador.fact + ? { + clipPath: + "polygon(0 0, calc(100% - 2.5rem) 0, 100% 2.5rem, 100% 100%, 0 100%)", + } + : undefined + } ref={callbackRef} {...extras} > @@ -151,214 +162,278 @@ export default function AmbassadorCard(props: AmbassadorCardProps) { )} -
- {ambassador.image.alt} - -
- {onClose && ( - - )} + {!flipped && ( +
+ {ambassador.image.alt} -

- {ambassador.name} -

-
-
- {mod && ( -
- Moderator badge +
+ {onClose && ( + + )} + +

+ {ambassador.name} +

+
+
+ {mod && ( +
+ Moderator badge +

+ Show this card to everyone by using{" "} + !{ambassador.commands[0]} in chat. +

+
+ )} + +
+

Species

+

{ambassador.species.name}

- Show this card to everyone by using{" "} - !{ambassador.commands[0]} in chat. + {ambassador.species.scientificName}{" "} + + ({ambassador.species.class.title}) +

- )} -
-

Species

-

{ambassador.species.name}

-

- {ambassador.species.scientificName}{" "} - - ({ambassador.species.class.title}) - -

-
+
+
+

Sex

+

{ambassador.sex || "Unknown"}

+
+
+

Age

+

+ {age[0] === "~" && ( + + ~ + + )} + {age.slice(age[0] === "~" ? 1 : 0)} +

+
+
+

Birthday

+

+ {birth[0] === "~" && ( + + ~ + + )} + {birth.slice(birth[0] === "~" ? 1 : 0)} +

+
+
+ +
+

Story

+

{ambassador.story}

+
-
-

Sex

-

{ambassador.sex || "Unknown"}

+

Conservation Mission

+

{ambassador.mission}

+
-

Age

+ +
+

Conservation Status

+ +
+

- {age[0] === "~" && ( - - ~ - + IUCN:{" "} + {ambassador.species.iucn.id && + ambassador.species.iucn.assessment ? ( + + + {ambassador.species.iucn.title} + {" "} + + + ) : ( + ambassador.species.iucn.title )} - {age.slice(age[0] === "~" ? 1 : 0)}

+ + {ambassador.fact && ( +
+ +
+

Did you know?

+ +
+
+
+ )} + +
+

Native To

+

{ambassador.species.native}

+
+
-

Birthday

+

Species Lifespan

- {birth[0] === "~" && ( - - ~ - + Wild:{" "} + {typeof ambassador.species.lifespan.wild === "string" ? ( + ambassador.species.lifespan.wild + ) : ( + <> + + ~ + + {stringifyLifespan(ambassador.species.lifespan.wild)} years + + )} +

+

+ Captivity:{" "} + {typeof ambassador.species.lifespan.captivity === "string" ? ( + ambassador.species.lifespan.captivity + ) : ( + <> + + ~ + + {stringifyLifespan(ambassador.species.lifespan.captivity)}{" "} + years + )} - {birth.slice(birth[0] === "~" ? 1 : 0)}

-
-
-

Story

-

{ambassador.story}

-
- -
-

Conservation Mission

-

{ambassador.mission}

-
- -
- -
-

Conservation Status

- +
+ - -

- IUCN:{" "} - {ambassador.species.iucn.id && - ambassador.species.iucn.assessment ? ( - - - {ambassador.species.iucn.title} - {" "} - - - ) : ( - ambassador.species.iucn.title - )} -

-
- -
-

Native To

-

{ambassador.species.native}

-
- -
-

Species Lifespan

-

- Wild:{" "} - {typeof ambassador.species.lifespan.wild === "string" ? ( - ambassador.species.lifespan.wild - ) : ( - <> - - ~ - - {stringifyLifespan(ambassador.species.lifespan.wild)} years - - )} -

-

- Captivity:{" "} - {typeof ambassador.species.lifespan.captivity === "string" ? ( - ambassador.species.lifespan.captivity - ) : ( - <> - - ~ - - {stringifyLifespan(ambassador.species.lifespan.captivity)}{" "} - years - - )} -

-
+
+

Arrived at Alveus

+

+ {ambassador.arrival + ? formatDate(ambassador.arrival, false) + : "Unknown"} +

+
+
-
-
-

Enclosure

+ -
-

Arrived at Alveus

-

- {ambassador.arrival - ? formatDate(ambassador.arrival, false) - : "Unknown"} -

-
+
+ )} - + )} From b49bb3e94637328a04d57657f232a916eaf69faf Mon Sep 17 00:00:00 2001 From: "Jibran Absarulislam (L-H)" Date: Sat, 12 Jul 2025 23:35:30 -0400 Subject: [PATCH 3/7] mvp dogear --- src/components/AmbassadorCard.tsx | 4 +++ src/components/Dogear.tsx | 45 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/components/Dogear.tsx diff --git a/src/components/AmbassadorCard.tsx b/src/components/AmbassadorCard.tsx index f85b4e9e..4a51411c 100644 --- a/src/components/AmbassadorCard.tsx +++ b/src/components/AmbassadorCard.tsx @@ -11,11 +11,13 @@ import { useAmbassador } from "../hooks/useAmbassadors"; import moderatorBadge from "../assets/mod.svg"; import partyHat from "../assets/party.svg"; +import Dogear from "./Dogear"; import IconBack from "./icons/IconBack"; import IconExternal from "./icons/IconExternal"; import IconInfo from "./icons/IconInfo"; +import Dogear from "./Dogear"; import Ring from "./Ring"; import TiltCard from "./TiltCard"; import Tooltip from "./Tooltip"; @@ -144,6 +146,8 @@ export default function AmbassadorCard(props: AmbassadorCardProps) { ref={callbackRef} {...extras} > + {ambassador.fact && } + {birthday && ( <> { + alert("Dogear clicked!"); + }} + aria-label="Dogear" + type="button" + > + {/* Credits to https://codepen.io/rachelslurs/pen/xxoPKLg *\/ +
+ +*/ + +export default function CardDogear(props: { onClick?: () => void }) { + return ( + + + + ); +} From 52ffe61dabad9ab61ea46ee0eb945acb8bc55db0 Mon Sep 17 00:00:00 2001 From: "Jibran Absarulislam (L-H)" Date: Sun, 13 Jul 2025 00:00:19 -0400 Subject: [PATCH 4/7] prep for flip hint and animation --- src/components/AmbassadorCard.tsx | 1 - src/components/Dogear.tsx | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/AmbassadorCard.tsx b/src/components/AmbassadorCard.tsx index 4a51411c..f30bddef 100644 --- a/src/components/AmbassadorCard.tsx +++ b/src/components/AmbassadorCard.tsx @@ -11,7 +11,6 @@ import { useAmbassador } from "../hooks/useAmbassadors"; import moderatorBadge from "../assets/mod.svg"; import partyHat from "../assets/party.svg"; -import Dogear from "./Dogear"; import IconBack from "./icons/IconBack"; import IconExternal from "./icons/IconExternal"; diff --git a/src/components/Dogear.tsx b/src/components/Dogear.tsx index 322317a0..e0262d77 100644 --- a/src/components/Dogear.tsx +++ b/src/components/Dogear.tsx @@ -23,7 +23,11 @@ import { classes } from "../utils/classes"; */ -export default function CardDogear(props: { onClick?: () => void }) { +export default function CardDogear(props: { + onClick?: () => void; + onHover?: () => void; + onMouseLeave?: () => void; +}) { return ( -*/ - export default function CardDogear(props: { onClick?: () => void; onHover?: () => void; From 32260b2a91ade8d7e18ccf3b6e9b71fb0f9ef205 Mon Sep 17 00:00:00 2001 From: "Jibran Absarulislam (L-H)" Date: Mon, 29 Sep 2025 22:49:55 -0400 Subject: [PATCH 6/7] dynamic border sizes --- src/components/Dogear.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Dogear.tsx b/src/components/Dogear.tsx index f7395724..a955b5e9 100644 --- a/src/components/Dogear.tsx +++ b/src/components/Dogear.tsx @@ -19,7 +19,7 @@ export default function CardDogear(props: { {/* Credits to https://codepen.io/rachelslurs/pen/xxoPKLg */}
From 89525d08501f1dc21373105851948976b8461599 Mon Sep 17 00:00:00 2001 From: "Jibran Absarulislam (L-H)" Date: Mon, 29 Sep 2025 22:50:35 -0400 Subject: [PATCH 7/7] add box shadow to dogear --- src/components/Dogear.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/Dogear.tsx b/src/components/Dogear.tsx index a955b5e9..34957d43 100644 --- a/src/components/Dogear.tsx +++ b/src/components/Dogear.tsx @@ -21,6 +21,9 @@ export default function CardDogear(props: { className={classes( "absolute top-0 right-0 w-0 border-13 border-solid border-t-transparent border-r-transparent border-b-alveus-green border-l-alveus-green transition-all duration-300 ease-in-out hover:scale-[1.6] sm:border-15 md:border-18 lg:border-20", )} + style={{ + boxShadow: "-4px 4px 2px rgba(0,0,0,0.3)", + }} />