From 25efbb1b90edcd717b2197d19c5c8cf0a3b08e27 Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Thu, 14 Nov 2024 05:10:48 +0000 Subject: [PATCH] feat: add mobile games (#42) ### Explanation _No response_ ### Issue _No response_ ### Attestations - [x] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/) - [x] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). - [x] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/). ### Dependencies - [ ] I have pinned the dependencies to a specific patch version. ### Style - [x] I have run the linter and resolved any errors. - [x] My pull request uses an appropriate title, matching the conventional commit standards. - [x] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request. ### Tests - [x] My contribution adds new code, and I have added tests to cover it. - [ ] My contribution modifies existing code, and I have updated the tests to reflect these changes. - [x] All new and existing tests pass locally with my changes. - [x] Code coverage remains at or above the configured threshold. ### Documentation _No response_ ### Versioning Minor - My pull request introduces a new non-breaking feature. Reviewed-on: https://codeberg.org/nhcarrigan/portfolio/pulls/42 Co-authored-by: Naomi Carrigan Co-committed-by: Naomi Carrigan --- src/app/play/page.tsx | 37 +++++++++++++ src/components/play.tsx | 115 +++++++++++++++++++++++++++++++++++++++ src/config/NavItems.ts | 1 + src/config/Play.ts | 87 +++++++++++++++++++++++++++++ test/config/Play.spec.ts | 19 +++++++ 5 files changed, 259 insertions(+) create mode 100644 src/app/play/page.tsx create mode 100644 src/components/play.tsx create mode 100644 src/config/Play.ts create mode 100644 test/config/Play.spec.ts diff --git a/src/app/play/page.tsx b/src/app/play/page.tsx new file mode 100644 index 0000000..bd23ed3 --- /dev/null +++ b/src/app/play/page.tsx @@ -0,0 +1,37 @@ +/** + * @copyright nhcarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ +import { PlayComponent } from "../../components/play"; +import { Rule } from "../../components/rule"; +import { Play } from "../../config/Play"; +import type { JSX } from "react"; + +/** + * Renders the /play page. + * @returns A React Component. + */ +const PlayPage = (): JSX.Element => { + return ( +
+

{`Play with Naomi`}

+
+

+ {`I play some silly li'l mobile games to keep myself from working non-stop. Here's what I'm currently playing - will you play with me?`} +

+ +
+ {Play.toSorted((a, b) => { + return a.name.localeCompare(b.name); + }).map((game) => { + return ; + })} +
+
+
+ ); +}; + +export default PlayPage; diff --git a/src/components/play.tsx b/src/components/play.tsx new file mode 100644 index 0000000..42cb93e --- /dev/null +++ b/src/components/play.tsx @@ -0,0 +1,115 @@ +/** + * @copyright nhcarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ +/* eslint-disable react/jsx-no-bind */ +"use client"; +import { faAndroid, faAppStore } from "@fortawesome/free-brands-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useState, type JSX } from "react"; + +interface PlayProperties { + name: string; + userId: string; + android: string; + ios: string; + server?: string; + guild?: { + name: string; + id: string; + }; +} + +const copyToClipboard = (text: string): void => { + void navigator.clipboard.writeText(text); +}; + +/** + * Renders the view for a mobile game. + * @param properties - The game to render. + * @returns A JSX element. + */ +export const PlayComponent = (properties: PlayProperties): JSX.Element => { + const { name, android, ios, server, guild, userId } = properties; + + const [ isFriendCodeCopied, setIsFriendCodeCopied ] + = useState(false); + const [ isGuildIdCopied, setIsGuildIdCopied ] + = useState(false); + + const columns = guild + ? "grid-cols-[2fr,1fr,200px]" + : "grid-cols-[2fr,200px]"; + + return ( +
+ + {guild + ? + : null} + +
+ ); +}; diff --git a/src/config/NavItems.ts b/src/config/NavItems.ts index 56888f5..c703514 100644 --- a/src/config/NavItems.ts +++ b/src/config/NavItems.ts @@ -22,6 +22,7 @@ export const NavItems = [ { href: "/art", text: "Art" }, { href: "/manifesto", text: "Transfemme Manifesto" }, { href: "/ask", text: "Ask Me Anything!" }, + { href: "/play", text: "Play with Naomi" }, ].sort((a, b) => { return a.text.localeCompare(b.text); }); diff --git a/src/config/Play.ts b/src/config/Play.ts new file mode 100644 index 0000000..8e5b143 --- /dev/null +++ b/src/config/Play.ts @@ -0,0 +1,87 @@ +/** + * @copyright nhcarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ + +export const Play: Array<{ + name: string; + userId: string; + android: string; + ios: string; + server?: string; + guild?: { + name: string; + id: string; + }; +}> = [ + { + android: "https://play.google.com/store/apps/details?id=jp.pokemon.pokemontcgp", + ios: "https://apps.apple.com/us/app/pok%C3%A9mon-tcg-pocket/id6479970832", + name: "Pokémon TCG Pocket", + userId: "3382202283069817", + }, + { + android: "https://play.google.com/store/apps/details?id=com.mujoysg.hxbb", + guild: { + id: "92 (Battle Zone 271)", + name: "NHCarrigan", + }, + ios: "https://apps.apple.com/us/app/idle-angels-goddess-warfare/id1478505280", + name: "Idle Angels", + userId: "6c2c7ce4a60544a3aee8670d8dddf1ed", + }, + { + android: "https://play.google.com/store/apps/details?id=com.proximabeta.nikke", + guild: { + id: "28325", + name: "NHC", + }, + ios: "https://apps.apple.com/us/app/goddess-of-victory-nikke/id1585915174", + name: "Goddess of Victory: Nikke", + userId: "05362866", + }, + { + android: "https://play.google.com/store/apps/details?id=com.yoozoo.jgame.us", + ios: "https://apps.apple.com/us/app/echocalypse-scarlet-covenant/id6446244975", + name: "Echocalypse: Scarlet Covenant", + server: "Aurora (3054310105)", + userId: "17754", + }, + { + android: "https://play.google.com/store/apps/details?id=jp.pokemon.pokemonsleep", + ios: "https://apps.apple.com/us/app/pok%C3%A9mon-sleep/id1579464667", + name: "Pokémon Sleep", + userId: "9952-8565-4043", + }, + { + android: "https://play.google.com/store/apps/details?id=com.goddessidle.global.android", + guild: { + id: "NHCarrigan", + name: "NHCarrigan", + }, + ios: "https://apps.apple.com/us/app/goddess-era-2331-draws/id1626294447", + name: "Goddess Era", + server: "S971", + userId: "449", + }, + { + android: "https://play.google.com/store/apps/details?id=com.nintendo.zaba", + ios: "https://apps.apple.com/us/app/fire-emblem-heroes/id1181774280", + name: "Fire Emblem: Heroes", + userId: "1305386686", + }, + { + android: "https://play.google.com/store/apps/details?id=com.HoYoverse.hkrpgoversea", + ios: "https://apps.apple.com/us/app/honkai-star-rail/id1599719154", + name: "Honkai Star Rail", + server: "America", + userId: "620952550", + }, + { + android: "https://play.google.com/store/apps/details?id=com.nintendo.zaca", + ios: "https://apps.apple.com/us/app/animal-crossing-pocket-camp/id1179915619", + name: "Animal Crossing: Pocket Camp", + userId: "3848 6071 011", + }, +]; diff --git a/test/config/Play.spec.ts b/test/config/Play.spec.ts new file mode 100644 index 0000000..0b96f0a --- /dev/null +++ b/test/config/Play.spec.ts @@ -0,0 +1,19 @@ +/** + * @copyright nhcarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ +import { describe, it, expect } from "vitest"; +import { Play } from "../../src/config/Play"; + +describe("play objects", () => { + it("should have unique names", () => { + expect.assertions(1); + const set = new Set( + Play.map((p) => { + return p.name; + }), + ); + expect(set, "are not unique").toHaveLength(Play.length); + }); +});