diff --git a/src/components/AmbassadorCard.tsx b/src/components/AmbassadorCard.tsx index 25e8bbff..f30bddef 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"; @@ -16,6 +16,7 @@ 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"; @@ -48,6 +49,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,9 +134,19 @@ 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} > + {ambassador.fact && } + {birthday && ( <> )} -
- {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"} -

-
+
+ )} - + )} diff --git a/src/components/Dogear.tsx b/src/components/Dogear.tsx new file mode 100644 index 00000000..34957d43 --- /dev/null +++ b/src/components/Dogear.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import Tooltip from "./Tooltip"; +import { classes } from "../utils/classes"; + +export default function CardDogear(props: { + onClick?: () => void; + onHover?: () => void; + onMouseLeave?: () => void; +}) { + return ( + + + + ); +} 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;