generated from nhcarrigan/template
feat: add character family tree
Some checks failed
Node.js CI / Lint and Test (push) Failing after 3m11s
Some checks failed
Node.js CI / Lint and Test (push) Failing after 3m11s
This commit is contained in:
parent
9c3870ab60
commit
d1ea7d41d7
195
src/app/legacy/page.tsx
Normal file
195
src/app/legacy/page.tsx
Normal file
@ -0,0 +1,195 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
/* eslint-disable react/no-multi-comp */
|
||||
"use client";
|
||||
import { useState, type JSX } from "react";
|
||||
import { CharacterComponent } from "../../components/character";
|
||||
import { Characters } from "../../config/Legacy";
|
||||
|
||||
const HorizontalConnector = ({
|
||||
colour,
|
||||
}: {
|
||||
readonly colour: string;
|
||||
}): JSX.Element => {
|
||||
return (
|
||||
<div className="w-full h-1 m-auto" style={{ background: colour }}></div>
|
||||
);
|
||||
};
|
||||
|
||||
const TopToRightConnector = ({
|
||||
colour,
|
||||
}: {
|
||||
readonly colour: string;
|
||||
}): JSX.Element => {
|
||||
return (
|
||||
<div className="w-full h-full grid grid-cols-2">
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{ borderRight: `2px solid ${colour}` }}
|
||||
></div>
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{
|
||||
borderBottom: `2px solid ${colour}`,
|
||||
borderLeft: `2px solid ${colour}`,
|
||||
}}
|
||||
></div>
|
||||
<div className="w-full h-full m-auto"></div>
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{ borderTop: `2px solid ${colour}` }}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const TopToLeftConnector = ({
|
||||
colour,
|
||||
}: {
|
||||
readonly colour: string;
|
||||
}): JSX.Element => {
|
||||
return (
|
||||
<div className="w-full h-full grid grid-cols-2">
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{
|
||||
borderBottom: `2px solid ${colour}`,
|
||||
borderRight: `2px solid ${colour}`,
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{ borderLeft: `2px solid ${colour}` }}
|
||||
></div>
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{ borderTop: `2px solid ${colour}` }}
|
||||
></div>
|
||||
<div className="w-full h-full m-auto"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const TopToRightToBottomConnector = ({
|
||||
colour,
|
||||
}: {
|
||||
readonly colour: string;
|
||||
}): JSX.Element => {
|
||||
return (
|
||||
<div className="w-full h-full grid grid-cols-2">
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{ borderRight: `2px solid ${colour}` }}
|
||||
></div>
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{
|
||||
borderBottom: `2px solid ${colour}`,
|
||||
borderLeft: `2px solid ${colour}`,
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{ borderRight: `2px solid ${colour}` }}
|
||||
></div>
|
||||
<div
|
||||
className="w-full h-full m-auto"
|
||||
style={{
|
||||
borderLeft: `2px solid ${colour}`,
|
||||
borderTop: `2px solid ${colour}`,
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders the /legacy page.
|
||||
* @returns A React Component.
|
||||
*/
|
||||
const Legacy = (): JSX.Element => {
|
||||
const [ focused, setFocused ] = useState("naomi-carrigan");
|
||||
|
||||
const handleClick = (id: string) => {
|
||||
return (): void => {
|
||||
setFocused(id);
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="w-4/5 text-center max-w-4xl m-auto mt-16 mb-16 rounded-lg">
|
||||
<h1 className="text-5xl">{`The Carrigan Legacy`}</h1>
|
||||
<section>
|
||||
<p className="mt-2">
|
||||
{`This page serves to show off all of our characters, who are all part of the same family (and thus, the same legacy).`}
|
||||
</p>
|
||||
<p>{`Click on a character to learn more about them!`}</p>
|
||||
<div className="grid grid-cols-6">
|
||||
<CharacterComponent
|
||||
focused={focused === "naomi-carrigan"}
|
||||
id={"naomi-carrigan"}
|
||||
onClick={handleClick("naomi-carrigan")}
|
||||
/>
|
||||
<HorizontalConnector colour="pink" />
|
||||
<CharacterComponent
|
||||
focused={focused === "melody-iuvo"}
|
||||
id={"melody-iuvo"}
|
||||
onClick={handleClick("melody-iuvo")}
|
||||
/>
|
||||
<HorizontalConnector colour="green" />
|
||||
<CharacterComponent
|
||||
focused={focused === "aria-iuvo"}
|
||||
id={"aria-iuvo"}
|
||||
onClick={handleClick("aria-iuvo")}
|
||||
/>
|
||||
<div></div>
|
||||
<TopToRightToBottomConnector colour="blue" />
|
||||
<CharacterComponent
|
||||
focused={focused === "becca-lyria"}
|
||||
id={"becca-lyria"}
|
||||
onClick={handleClick("becca-lyria")}
|
||||
/>
|
||||
<HorizontalConnector colour="pink" />
|
||||
<CharacterComponent
|
||||
focused={focused === "rosalia-nightsong"}
|
||||
id={"rosalia-nightsong"}
|
||||
onClick={handleClick("rosalia-nightsong")}
|
||||
/>
|
||||
<TopToRightConnector colour="blue" />
|
||||
<CharacterComponent
|
||||
focused={focused === "cordelia-taryne"}
|
||||
id={"cordelia-taryne"}
|
||||
onClick={handleClick("cordelia-taryne")}
|
||||
/>
|
||||
<CharacterComponent
|
||||
focused={focused === "gwen-carrigan"}
|
||||
id={"gwen-carrigan"}
|
||||
onClick={handleClick("gwen-carrigan")}
|
||||
/>
|
||||
<HorizontalConnector colour="pink" />
|
||||
<HorizontalConnector colour="pink" />
|
||||
<CharacterComponent
|
||||
focused={focused === "maylin-taryne"}
|
||||
id={"maylin-taryne"}
|
||||
onClick={handleClick("maylin-taryne")}
|
||||
/>
|
||||
<HorizontalConnector colour="blue" />
|
||||
<TopToLeftConnector colour="blue" />
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<h2 className="text-2xl">{Characters[focused]?.name}</h2>
|
||||
<p>{Characters[focused]?.class}</p>
|
||||
<p className="italic">{`${Characters[focused]?.age.toString() ?? "unknown"} years old`}</p>
|
||||
{Characters[focused]?.bio.map((paragraph) => {
|
||||
return <p key={paragraph}>{paragraph}</p>;
|
||||
})}
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
export default Legacy;
|
38
src/components/character.tsx
Normal file
38
src/components/character.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
import Image from "next/image";
|
||||
import type { JSX } from "react";
|
||||
|
||||
interface CharacterProperties {
|
||||
readonly id: string;
|
||||
readonly onClick?: ()=> void;
|
||||
readonly focused: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the view for a legacy character.
|
||||
* @param properties - The character to render.
|
||||
* @returns A JSX element.
|
||||
*/
|
||||
export const CharacterComponent = (
|
||||
properties: CharacterProperties,
|
||||
): JSX.Element => {
|
||||
const { id, onClick, focused } = properties;
|
||||
|
||||
return (
|
||||
<Image
|
||||
alt={id}
|
||||
className="m-h-[525px] m-w-[400px] object-contain"
|
||||
height={525}
|
||||
onClick={onClick}
|
||||
src={`https://cdn.nhcarrigan.com/characters/${id}.png`}
|
||||
style={focused
|
||||
? { border: "4px solid yellow" }
|
||||
: {}}
|
||||
width={400}
|
||||
/>
|
||||
);
|
||||
};
|
87
src/config/Legacy.ts
Normal file
87
src/config/Legacy.ts
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @copyright nhcarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
|
||||
const Characters: Record<string, { age: number; class: string; name: string; bio: Array<string> }> = {
|
||||
"aria-iuvo": {
|
||||
age: 103,
|
||||
bio: [
|
||||
"Aria Iuvo is far more chaotic and mischievous than her sister Melody.",
|
||||
"As an elf, Aria Iuvo is actually quite older than her sister, but she is far more spry and youthful in appearance.",
|
||||
],
|
||||
class: "Thief",
|
||||
name: "Aria Iuvo",
|
||||
},
|
||||
"becca-lyria": {
|
||||
age: 21,
|
||||
bio: [
|
||||
"Becca Lyria commands a complete mastery over death, able to raise the dead and control them as she sees fit.",
|
||||
"She was orphaned at a young age, with little memory of her parents. Naomi had found her quite a few years later and took her in as her own child.",
|
||||
],
|
||||
class: "Necromancer",
|
||||
name: "Becca Lyria",
|
||||
},
|
||||
"cordelia-taryne": {
|
||||
age: 85,
|
||||
bio: [
|
||||
"Cordelia Taryne was Aria's child, and in her early life appeared to be human.",
|
||||
"However, in her young adult life, she had fallen sway to a nefarious cult. As part of her initiation, she was bitten by a vampire and turned into a thrall.",
|
||||
"When she finally overthrew her master and unlocked her full powers, her latent elvish traits also began to show.",
|
||||
],
|
||||
class: "Vampyr",
|
||||
name: "Cordelia Taryne",
|
||||
},
|
||||
"gwen-carrigan": {
|
||||
age: 28,
|
||||
bio: [
|
||||
"Gwen is Naomi's other adopted child. She was actually adopted first, and when Becca was taken in she took off in a huff.",
|
||||
"She had spent a few years honing her skills with the blade, getting into fights (and even losing some, one of which took her eye).",
|
||||
"As she's matured, she has started to reconnect with the family she had left behind.",
|
||||
],
|
||||
class: "Warrior",
|
||||
name: "Gwen Carrigan",
|
||||
},
|
||||
"maylin-taryne": {
|
||||
age: 32,
|
||||
bio: [
|
||||
"Maylin was a thrall to the same master as Cordelia, but when Cordelia took his place Maylin's vampiric powers faded.",
|
||||
"Out of a sense of guilt, Cordelia took her in as the only human she's ever been close to.",
|
||||
"While she may not have elvish blood, Maylin has found a strong connection with nature and serves as a talented ranger.",
|
||||
],
|
||||
class: "Ranger",
|
||||
name: "Maylin Taryne",
|
||||
},
|
||||
"melody-iuvo": {
|
||||
age: 26,
|
||||
bio: [
|
||||
"Melody Iuvo is a master of stealth and deception.",
|
||||
"She had actually started as Naomi's assistant, but the two quickly began to develop feelings for each other and later became married.",
|
||||
"Unlike her sister, Melody did not inherit the elven genes of their mother.",
|
||||
],
|
||||
class: "Assassin",
|
||||
name: "Melody Iuvo",
|
||||
},
|
||||
"naomi-carrigan": {
|
||||
age: 30,
|
||||
bio: [
|
||||
"Naomi Carrigan is a technomancer - she uses magic to manipulate the technology around her.",
|
||||
"She is the matriarch of the family. Despite being younger than some of the other members, her power and her leadership capabilities have earned her the spot at the head of the family.",
|
||||
],
|
||||
class: "Technomancer",
|
||||
name: "Naomi Carrigan",
|
||||
},
|
||||
"rosalia-nightsong": {
|
||||
age: 18,
|
||||
bio: [
|
||||
"Born to noble parents, Rosalia wanted for little in life. She spent her time devoted to her Goddess.",
|
||||
"The day came when she was called to take up the sword and right the wrongs in the world, and she has been on that path ever since.",
|
||||
"While she and Becca may be married, they don't always see eye-to-eye -- and Rosalia still hopes that one day Becca will turn away from the path of darkness.",
|
||||
],
|
||||
class: "Paladin",
|
||||
name: "Rosalia Nightsong",
|
||||
},
|
||||
};
|
||||
|
||||
export { Characters };
|
Loading…
x
Reference in New Issue
Block a user