diff --git a/.github/workflows/reset-test-branch.yml b/.github/workflows/reset-test-branch.yml new file mode 100644 index 00000000..67223f6c --- /dev/null +++ b/.github/workflows/reset-test-branch.yml @@ -0,0 +1,44 @@ +name: Weekly Reset Test Branch + +on: + #schedule: + # Runs every Sunday at 08:00 UTC (adjust as needed) + # Cron syntax: minute hour day(month) month day(week) + # - cron: "0 8 * * 0" + workflow_dispatch: # Allows manual triggering from the Actions tab + +jobs: + reset_branch: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + # Fetch all history so we can reset to main correctly + fetch-depth: 0 + # Make sure the token has write permissions + persist-credentials: true + + - name: Configure Git User + run: | + git config user.name github-actions[bot] + git config user.email github-actions[bot]@users.noreply.github.com + + - name: Reset Test Branch to Main + run: | + # Ensure main is up-to-date locally + git checkout main + git pull origin main + + # Check out the test branch, or create it if it doesn't exist + git checkout test || git checkout -b test + + # Reset test branch to the state of origin/main + echo "Resetting test branch to origin/main..." + git reset --hard origin/main + + # Force push the reset state to the remote test branch + echo "Force pushing changes to test branch..." + git push origin test --force + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 56b97493..41eba0e7 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,9 @@ Open [http://localhost:3000](http://localhost:3000) in your browser to view the You can modify the main content of the site by editing the following files: -- pages/index.tsx: The main landing page of the website. +- app/pages.tsx: The main landing page of the website. -- pages/\_app.js: The layout file for shared elements like headers or footers. +- app/layout.tsx: The layout file for shared elements like headers or footers. The project auto-updates changes as you edit. diff --git a/app/about/page.tsx b/app/about/page.tsx index 63a53ff4..2ff707af 100644 --- a/app/about/page.tsx +++ b/app/about/page.tsx @@ -1,6 +1,8 @@ import { Container, Row, Col } from "react-bootstrap"; import type { Metadata } from "next"; -//Helpers +// --- Layout --- +import PageLayout from "@/components/PageLayout"; +// --- Helpers --- import { generateGithubLink } from "@/helpers/_silabs/generateGithubLink"; export const metadata: Metadata = { @@ -14,103 +16,108 @@ export default function AboutPage() { { template: "feature-request-template.md" } ); return ( - - -

- About {process.env.NEXT_PUBLIC_APP_NAME} -

- -

About section

-

Tech used to build this site

-
- -
-

Non tech used to build this site

-
+ + + +

+ About {process.env.NEXT_PUBLIC_APP_NAME} +

+ +

About section

+

Tech used to build this site

+
+ +
+

Non tech used to build this site

+
+

+ Even though this site is made primarily by{" "} + OneBuffaloLabs{" "} + we did leverage alot of other tech and sources to help bring + this site to you: +

+ +
+ + +

Contact Us

- Even though this site is made primarily by{" "} - OneBuffaloLabs we - did leverage alot of other tech and sources to help bring this - site to you: + Have you found a bug, an error or just havea cool feature we + should add to the site? Create a ticket on our Github{" "} + + here + {" "} + and we will look into it!

- -
- - -

Contact Us

-

- Have you found a bug, an error or just havea cool feature we should - add to the site? Create a ticket on our Github{" "} - - here - {" "} - and we will look into it! -

- -
-
+ + + + ); } diff --git a/app/feedback/page.tsx b/app/feedback/page.tsx index f17ca36f..a7f89d2b 100644 --- a/app/feedback/page.tsx +++ b/app/feedback/page.tsx @@ -1,6 +1,8 @@ import React, { Suspense } from "react"; import type { Metadata } from "next"; import { Container, Row, Col, Spinner } from "react-bootstrap"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; // Components import FeedbackForm from "@/components/FeedbackForm"; @@ -11,24 +13,26 @@ export const metadata: Metadata = { export default function FeedbackPage() { return ( - -

Feedback

- - - - - Loading Form... - -

Loading Form...

- - } - > - -
- -
-
+ + +

Feedback

+ + + + + Loading Form... + +

Loading Form...

+ + } + > + +
+ +
+
+
); } diff --git a/app/layout.tsx b/app/layout.tsx index 12205782..b742c643 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,13 +1,14 @@ -// app/layout.tsx import { Suspense } from "react"; +// --- Next --- import type { Metadata, Viewport } from "next"; import { Inter } from "next/font/google"; -import MonHeader from "@/components/MonHeader"; -import MonFooter from "@/components/MonFooter"; +// --- Components --- +import GoogleAnalytics from "@/components/_silabs/GoogleAnalytics"; + +// --- Styles --- import "bootstrap/dist/css/bootstrap.min.css"; import "@/public/styles/_fw.css"; import "./globals.css"; -import GoogleAnalytics from "@/components/_silabs/GoogleAnalytics"; // --- Environment Variables --- const GA_TRACKING_ID = process.env.NEXT_PUBLIC_APP_GA_TRACKING_ID; @@ -33,10 +34,9 @@ export const viewport: Viewport = { width: "device-width", initialScale: 1, maximumScale: 1, - // themeColor: "#ffffff", // Optional: Add theme color }; -// Setup a font (example using Inter) +// Setup a font const inter = Inter({ subsets: ["latin"] }); export default function RootLayout({ @@ -47,13 +47,7 @@ export default function RootLayout({ return ( -
- -
- {children} {/* Page content */} -
- -
+ {children} {GA_TRACKING_ID && ( diff --git a/app/not-found.tsx b/app/not-found.tsx index fcdeefcf..d5765006 100644 --- a/app/not-found.tsx +++ b/app/not-found.tsx @@ -2,6 +2,8 @@ import type { Metadata } from "next"; import { Container, Row, Col, Button } from "react-bootstrap"; import Link from "next/link"; import NotFoundRedirector from "@/components/NotFoundRedirector"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; export const metadata: Metadata = { title: "Page Not Found", @@ -10,25 +12,27 @@ export const metadata: Metadata = { export default function NotFound() { return ( - - + + + - - -
-

404

-

Page Not Found

-

- Sorry, the page you are looking for does not exist or might have - been moved. If it has moved recently, you might be redirected - shortly. -

- - - -
- -
-
+ + +
+

404

+

Page Not Found

+

+ Sorry, the page you are looking for does not exist or might have + been moved. If it has moved recently, you might be redirected + shortly. +

+ + + +
+ +
+
+ ); } diff --git a/app/page.tsx b/app/page.tsx index 34c34c7a..bc66e54d 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,42 +1,50 @@ import { Container, Row, Col } from "react-bootstrap"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; +// --- Sections --- import TypesSection from "@/components/pokemon/home/TypesSection"; import PokedexesSection from "@/components/pokemon/home/PokedexesSection"; import RegionsSection from "@/components/pokemon/home/RegionsSection"; +import GenerationsSection from "@/components/pokemon/home/GenerationsSection"; export default function HomePage() { return ( - - - -

- Welcome to {process.env.NEXT_PUBLIC_APP_NAME}! -

-

- Your ultimate destination for exploring the vast world of Pokémon! -

-

- Built with cutting-edge web technologies including{" "} - React, Next.js, and{" "} - Bootstrap, NéxtDex offers a fast, responsive, and - visually appealing experience for trainers of all levels. Dive into - our comprehensive Pokédex section to search, - filter, and learn intricate details about every known{" "} - Pokémon. Beyond the Pokédex, NéxtDex is designed to - be an ever-expanding resource, featuring in-depth information on{" "} - Pokémon games, regions, items, characters, and much - more. Prepare to enhance your Pokémon knowledge - with a sleek interface and a wealth of data right at your - fingertips! -

- - - -
- -
- - -
-
+ + + + +

+ Welcome to {process.env.NEXT_PUBLIC_APP_NAME}! +

+

+ Your ultimate destination for exploring the vast world of Pokémon! +

+

+ Built with cutting-edge web technologies including{" "} + React, Next.js, and{" "} + Bootstrap, NéxtDex offers a fast, responsive, and + visually appealing experience for trainers of all levels. Dive + into our comprehensive Pokédex section to search, + filter, and learn intricate details about every known{" "} + Pokémon. Beyond the Pokédex, NéxtDex is designed + to be an ever-expanding resource, featuring in-depth information + on Pokémon games, regions, items, characters, and + much more. Prepare to enhance your Pokémon{" "} + knowledge with a sleek interface and a wealth of data right at + your fingertips! +

+ + + +
+ +
+ +
+ + +
+
+
); } diff --git a/app/pokedex/page.tsx b/app/pokedex/page.tsx index 303c46c9..8182b4ac 100644 --- a/app/pokedex/page.tsx +++ b/app/pokedex/page.tsx @@ -1,7 +1,9 @@ import React from "react"; import { Container, Row } from "react-bootstrap"; import type { Metadata } from "next"; -// Components +// --- Layout --- +import PageLayout from "@/components/PageLayout"; +// --- Components --- import PokedexClientSection from "@/components/pages/PokedexClientSection"; export const metadata: Metadata = { @@ -10,10 +12,12 @@ export const metadata: Metadata = { export default function PokedexPage() { return ( - - - - - + + + + + + + ); } diff --git a/app/pokemon/ability/page.tsx b/app/pokemon/ability/page.tsx new file mode 100644 index 00000000..43e1faa6 --- /dev/null +++ b/app/pokemon/ability/page.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import { Container, Row } from "react-bootstrap"; +import type { Metadata } from "next"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; + +export const metadata: Metadata = { + title: "Pokémon Ability", +}; + +export default function PokemonAbilityPage() { + return ( + + + + +

Pokémon Ability

+ Coming Soon..... +
+
+
+
+ ); +} diff --git a/app/pokemon/game/page.tsx b/app/pokemon/game/page.tsx index 54ea4357..b7b59fe5 100644 --- a/app/pokemon/game/page.tsx +++ b/app/pokemon/game/page.tsx @@ -1,6 +1,8 @@ import React from "react"; import { Container, Row } from "react-bootstrap"; import type { Metadata } from "next"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; export const metadata: Metadata = { title: "Pokémon Game", @@ -8,13 +10,15 @@ export const metadata: Metadata = { export default function PokemonGamePage() { return ( - - - -

Pokémon Game

- Coming Soon..... + + + + +

Pokémon Game

+ Coming Soon..... +
-
-
+ + ); } diff --git a/app/pokemon/generation/page.tsx b/app/pokemon/generation/page.tsx index 12df6357..b66864f1 100644 --- a/app/pokemon/generation/page.tsx +++ b/app/pokemon/generation/page.tsx @@ -1,6 +1,10 @@ import React from "react"; import { Container, Row } from "react-bootstrap"; import type { Metadata } from "next"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; +// --- Components --- +import PokemonGenerationClientSection from "@/components/pages/PokemonGenerationClientSection"; export const metadata: Metadata = { title: "Pokémon Generation", @@ -8,13 +12,12 @@ export const metadata: Metadata = { export default function PokemonGenerationPage() { return ( - - - -

Pokémon Generation

- Coming Soon..... + + + + -
-
+ + ); } diff --git a/app/pokemon/location/page.tsx b/app/pokemon/location/page.tsx index dfd7cb5a..533ad90d 100644 --- a/app/pokemon/location/page.tsx +++ b/app/pokemon/location/page.tsx @@ -1,6 +1,8 @@ import React from "react"; import { Container, Row } from "react-bootstrap"; import type { Metadata } from "next"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; export const metadata: Metadata = { title: "Pokémon Location", @@ -8,13 +10,15 @@ export const metadata: Metadata = { export default function PokemonLocationPage() { return ( - - - -

Pokémon Location

- Coming Soon..... + + + + +

Pokémon Location

+ Coming Soon..... +
-
-
+ + ); } diff --git a/app/pokemon/move/page.tsx b/app/pokemon/move/page.tsx index ac461841..85dac8fe 100644 --- a/app/pokemon/move/page.tsx +++ b/app/pokemon/move/page.tsx @@ -1,6 +1,8 @@ import React from "react"; import { Container, Row } from "react-bootstrap"; import type { Metadata } from "next"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; export const metadata: Metadata = { title: "Pokémon Move", @@ -8,13 +10,15 @@ export const metadata: Metadata = { export default function PokemonMovePage() { return ( - - - -

Pokémon Move

- Coming Soon..... + + + + +

Pokémon Move

+ Coming Soon..... +
-
-
+ + ); } diff --git a/app/pokemon/page.tsx b/app/pokemon/page.tsx index 4ae8e6f2..29676dea 100644 --- a/app/pokemon/page.tsx +++ b/app/pokemon/page.tsx @@ -1,6 +1,8 @@ import React from "react"; import { Container, Row } from "react-bootstrap"; import type { Metadata } from "next"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; export const metadata: Metadata = { title: "Pokémon", @@ -8,13 +10,15 @@ export const metadata: Metadata = { export default function PokemonPage() { return ( - - - -

Pokémon

- Coming Soon..... + + + + +

Pokémon

+ Coming Soon..... +
-
-
+ + ); } diff --git a/app/pokemon/region/page.tsx b/app/pokemon/region/page.tsx index 2a484131..f966a030 100644 --- a/app/pokemon/region/page.tsx +++ b/app/pokemon/region/page.tsx @@ -1,7 +1,9 @@ import React from "react"; import { Container, Row } from "react-bootstrap"; import type { Metadata } from "next"; -// Components +// --- Layout --- +import PageLayout from "@/components/PageLayout"; +// --- Components --- import PokemonRegionClientSection from "@/components/pages/PokemonRegionClientSection"; export const metadata: Metadata = { @@ -10,10 +12,12 @@ export const metadata: Metadata = { export default function PokemonRegionPage() { return ( - - - - - + + + + + + + ); } diff --git a/app/pokemon/type/page.tsx b/app/pokemon/type/page.tsx index 952c60d2..2f471159 100644 --- a/app/pokemon/type/page.tsx +++ b/app/pokemon/type/page.tsx @@ -1,7 +1,9 @@ import React from "react"; import { Container, Row } from "react-bootstrap"; import type { Metadata } from "next"; -// Components +// --- Layout --- +import PageLayout from "@/components/PageLayout"; +// --- Components --- import PokemonTypeClientSection from "@/components/pages/PokemonTypeClientSection"; export const metadata: Metadata = { @@ -10,10 +12,12 @@ export const metadata: Metadata = { export default function PokedexPage() { return ( - - - - - + + + + + + + ); } diff --git a/app/privacy/page.tsx b/app/privacy/page.tsx index 60665b14..55a47c8f 100644 --- a/app/privacy/page.tsx +++ b/app/privacy/page.tsx @@ -1,6 +1,8 @@ import type { Metadata } from "next"; import Link from "next/link"; import { Container, Row, Col } from "react-bootstrap"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; export const metadata: Metadata = { title: "Privacy Policy", @@ -19,238 +21,246 @@ export default function PrivacyPage() { const appUrl = process.env.NEXT_PUBLIC_APP_URL || ""; return ( - - - - - - -

Privacy Policy

-
+ + + + + + + +

Privacy Policy

+
-

- This Privacy Policy governs the manner in which Techreanimate - collects, uses, maintains and discloses information collected - from users (each, a "User") of the{" "} - - {appUrl} - {" "} - website ("Site"). This privacy policy applies to the - Site and all products and services offered by Techreanimate. -

- -
-

What information do we collect?

-

- We collect information from you when you register on our - site, place an order, subscribe to our newsletter, respond - to a survey or fill out a form. -

-

- When ordering or registering on our site, as appropriate, - you may be asked to enter your: name, e-mail address, - mailing address, phone number or other details. You may, - however, visit our site anonymously. +

+ This Privacy Policy governs the manner in which + Techreanimate collects, uses, maintains and discloses + information collected from users (each, a "User") + of the{" "} + + {appUrl} + {" "} + website ("Site"). This privacy policy applies to + the Site and all products and services offered by + Techreanimate.

-
-
-

What do we use your information for?

-

- Any of the information we collect from you may be used in - one of the following ways: -

-
    -
  • - To personalize your experience: Your - information helps us to better respond to your individual - needs. -
  • -
  • - To improve our website: We continually - strive to improve our website offerings based on the - information and feedback we receive from you. -
  • -
  • - To improve customer service: Your - information helps us to more effectively respond to your - customer service requests and support needs. -
  • -
  • - To process transactions: Your - information, whether public or private, will not be sold, - exchanged, transferred, or given to any other company for - any reason whatsoever, without your consent, other than - for the express purpose of delivering the purchased - product or service requested. -
  • -
  • - To administer features: Such as a - contest, promotion, survey or other site feature. -
  • -
  • - To send periodic emails: The email - address you provide may be used to send you information - and updates, in addition to receiving occasional company - news, updates, etc. - - Note: If at any time you would like to unsubscribe from - receiving future emails, we include detailed unsubscribe - instructions at the bottom of each email. - -
  • -
-
+
+

What information do we collect?

+

+ We collect information from you when you register on our + site, place an order, subscribe to our newsletter, respond + to a survey or fill out a form. +

+

+ When ordering or registering on our site, as appropriate, + you may be asked to enter your: name, e-mail address, + mailing address, phone number or other details. You may, + however, visit our site anonymously. +

+
-
-

How do we protect your information?

-

- We implement a variety of security measures to maintain the - safety of your personal information when you place an order - or enter, submit, or access your personal information. -

-

- We may offer the use of a secure server. All supplied - sensitive/credit information is transmitted via Secure - Socket Layer (SSL) technology and then encrypted into our - Payment gateway provider's database only to be - accessible by those authorized with special access rights to - such systems, and are required to keep the information - confidential. -

-

- After a transaction, your private information (credit cards, - social security numbers, financials, etc.) may not be stored - on our servers. -

-
+
+

What do we use your information for?

+

+ Any of the information we collect from you may be used in + one of the following ways: +

+
    +
  • + To personalize your experience: Your + information helps us to better respond to your + individual needs. +
  • +
  • + To improve our website: We continually + strive to improve our website offerings based on the + information and feedback we receive from you. +
  • +
  • + To improve customer service: Your + information helps us to more effectively respond to your + customer service requests and support needs. +
  • +
  • + To process transactions: Your + information, whether public or private, will not be + sold, exchanged, transferred, or given to any other + company for any reason whatsoever, without your consent, + other than for the express purpose of delivering the + purchased product or service requested. +
  • +
  • + To administer features: Such as a + contest, promotion, survey or other site feature. +
  • +
  • + To send periodic emails: The email + address you provide may be used to send you information + and updates, in addition to receiving occasional company + news, updates, etc. + + Note: If at any time you would like to unsubscribe + from receiving future emails, we include detailed + unsubscribe instructions at the bottom of each email. + +
  • +
+
-
-

Do we use cookies?

-

- Yes. Cookies are small files that a site or its service - provider transfers to your computer's hard drive - through your Web browser (if you allow) that enables the - site's or service provider's systems to recognize - your browser and capture and remember certain information. -

-

- We use cookies to understand and save your preferences for - future visits and compile aggregate data about site traffic - and site interaction so that we can offer better site - experiences and tools in the future. -

-
+
+

How do we protect your information?

+

+ We implement a variety of security measures to maintain + the safety of your personal information when you place an + order or enter, submit, or access your personal + information. +

+

+ We may offer the use of a secure server. All supplied + sensitive/credit information is transmitted via Secure + Socket Layer (SSL) technology and then encrypted into our + Payment gateway provider's database only to be + accessible by those authorized with special access rights + to such systems, and are required to keep the information + confidential. +

+

+ After a transaction, your private information (credit + cards, social security numbers, financials, etc.) may not + be stored on our servers. +

+
-
-

Do we disclose any information to outside parties?

-

- We do not sell, trade, or otherwise transfer to outside - parties your personally identifiable information. This does - not include trusted third parties who assist us in operating - our website, conducting our business, or servicing you, so - long as those parties agree to keep this information - confidential. We may also release your information when we - believe release is appropriate to comply with the law, - enforce our site policies, or protect ours or others rights, - property, or safety. However, non-personally identifiable - visitor information may be provided to other parties for - marketing, advertising, or other uses. -

-
+
+

Do we use cookies?

+

+ Yes. Cookies are small files that a site or its service + provider transfers to your computer's hard drive + through your Web browser (if you allow) that enables the + site's or service provider's systems to + recognize your browser and capture and remember certain + information. +

+

+ We use cookies to understand and save your preferences for + future visits and compile aggregate data about site + traffic and site interaction so that we can offer better + site experiences and tools in the future. +

+
-
-

Third party links

-

- Occasionally, at our discretion, we may include or offer - third party products or services on our website. These third - party sites have separate and independent privacy policies. - We therefore have no responsibility or liability for the - content and activities of these linked sites. Nonetheless, - we seek to protect the integrity of our site and welcome any - feedback about these sites. -

-
+
+

Do we disclose any information to outside parties?

+

+ We do not sell, trade, or otherwise transfer to outside + parties your personally identifiable information. This + does not include trusted third parties who assist us in + operating our website, conducting our business, or + servicing you, so long as those parties agree to keep this + information confidential. We may also release your + information when we believe release is appropriate to + comply with the law, enforce our site policies, or protect + ours or others rights, property, or safety. However, + non-personally identifiable visitor information may be + provided to other parties for marketing, advertising, or + other uses. +

+
-
-

California Online Privacy Protection Act Compliance

-

- Because we value your privacy we have taken the necessary - precautions to be in compliance with the California Online - Privacy Protection Act. We therefore will not distribute - your personal information to outside parties without your - consent. -

-
+
+

Third party links

+

+ Occasionally, at our discretion, we may include or offer + third party products or services on our website. These + third party sites have separate and independent privacy + policies. We therefore have no responsibility or liability + for the content and activities of these linked sites. + Nonetheless, we seek to protect the integrity of our site + and welcome any feedback about these sites. +

+
-
-

Childrens Online Privacy Protection Act Compliance

-

- We are in compliance with the requirements of COPPA - (Childrens Online Privacy Protection Act), we do not - knowingly collect any information from anyone under 13 years - of age. Our website, products and services are all directed - to people who are at least 13 years old or older. -

-
+
+

California Online Privacy Protection Act Compliance

+

+ Because we value your privacy we have taken the necessary + precautions to be in compliance with the California Online + Privacy Protection Act. We therefore will not distribute + your personal information to outside parties without your + consent. +

+
-
-

Online Privacy Policy Only

-

- This online privacy policy applies only to information - collected through our website and not to information - collected offline. -

-
+
+

Childrens Online Privacy Protection Act Compliance

+

+ We are in compliance with the requirements of COPPA + (Childrens Online Privacy Protection Act), we do not + knowingly collect any information from anyone under 13 + years of age. Our website, products and services are all + directed to people who are at least 13 years old or older. +

+
-
-

Terms and Conditions

-

- Please also visit our Terms and Conditions section - establishing the use, disclaimers, and limitations of - liability governing the use of our website at{" "} - Terms and Conditions. -

-
+
+

Online Privacy Policy Only

+

+ This online privacy policy applies only to information + collected through our website and not to information + collected offline. +

+
-
-

Your Consent

-

- By using our site, you consent to our website's privacy - policy. -

-
+
+

Terms and Conditions

+

+ Please also visit our Terms and Conditions section + establishing the use, disclaimers, and limitations of + liability governing the use of our website at{" "} + Terms and Conditions. +

+
-
-

Changes to our Privacy Policy

-

- If we decide to change our privacy policy, we will post - those changes on this page. Policy changes will apply only - to information collected after the date of the change. -

-

- This policy was last modified on October 26, 2013 4:17PM EST -

-
+
+

Your Consent

+

+ By using our site, you consent to our website's + privacy policy. +

+
-
-

Contacting Us

-

- If there are any questions regarding this privacy policy you - may contact us. -

-
- P: 716-698-9236 -
-
- -
-
- -
-
+
+

Changes to our Privacy Policy

+

+ If we decide to change our privacy policy, we will post + those changes on this page. Policy changes will apply only + to information collected after the date of the change. +

+

+ This policy was last modified on October 26, 2013 4:17PM + EST +

+
+ +
+

Contacting Us

+

+ If there are any questions regarding this privacy policy + you may contact us. +

+
+ P: 716-698-9236 +
+
+ +
+
+ +
+
+ ); } diff --git a/app/terms/page.tsx b/app/terms/page.tsx index 142ea9f6..a26f7c52 100644 --- a/app/terms/page.tsx +++ b/app/terms/page.tsx @@ -1,5 +1,7 @@ import type { Metadata } from "next"; import { Container, Row, Col } from "react-bootstrap"; +// --- Layout --- +import PageLayout from "@/components/PageLayout"; export const metadata: Metadata = { title: "Terms And Conditions", @@ -9,249 +11,256 @@ export const metadata: Metadata = { export default function TermsPage() { return ( - - - - - - -
-

- Web Site Terms and Conditions of Use -

-
+ + + + + + + +
+

+ Web Site Terms and Conditions of Use +

+
- {/* --- TERMS CONTENT --- */} -
-

1. Terms

-

- By accessing this web site, you are agreeing to be bound - by these web site Terms and Conditions of Use, all - applicable laws and regulations, and agree that you are - responsible for compliance with any applicable local laws. - If you do not agree with any of these terms, you are - prohibited from using or accessing this site. The - materials contained in this web site are protected by - applicable copyright and trade mark law. -

-
+ {/* --- TERMS CONTENT --- */} +
+

1. Terms

+

+ By accessing this web site, you are agreeing to be bound + by these web site Terms and Conditions of Use, all + applicable laws and regulations, and agree that you are + responsible for compliance with any applicable local + laws. If you do not agree with any of these terms, you + are prohibited from using or accessing this site. The + materials contained in this web site are protected by + applicable copyright and trade mark law. +

+
-
-

2. Use License

-
    -
  1. - Permission is granted to temporarily download one copy - of the materials (information or software) on - Techreanimate's web site for personal, - non-commercial transitory viewing only. This is the - grant of a license, not a transfer of title, and under - this license you may not: -
      -
    1. modify or copy the materials;
    2. -
    3. - use the materials for any commercial purpose, or for - any public display (commercial or non-commercial); -
    4. -
    5. - attempt to decompile or reverse engineer any - software contained on Techreanimate's web site; -
    6. -
    7. - remove any copyright or other proprietary notations - from the materials; or -
    8. -
    9. - transfer the materials to another person or - "mirror" the materials on any other - server. -
    10. -
    -
  2. -
  3. - This license shall automatically terminate if you - violate any of these restrictions and may be terminated - by Techreanimate at any time. Upon terminating your - viewing of these materials or upon the termination of - this license, you must destroy any downloaded materials - in your possession whether in electronic or printed - format. -
  4. -
-
+
+

2. Use License

+
    +
  1. + Permission is granted to temporarily download one copy + of the materials (information or software) on + Techreanimate's web site for personal, + non-commercial transitory viewing only. This is the + grant of a license, not a transfer of title, and under + this license you may not: +
      +
    1. modify or copy the materials;
    2. +
    3. + use the materials for any commercial purpose, or + for any public display (commercial or + non-commercial); +
    4. +
    5. + attempt to decompile or reverse engineer any + software contained on Techreanimate's web + site; +
    6. +
    7. + remove any copyright or other proprietary + notations from the materials; or +
    8. +
    9. + transfer the materials to another person or + "mirror" the materials on any other + server. +
    10. +
    +
  2. +
  3. + This license shall automatically terminate if you + violate any of these restrictions and may be + terminated by Techreanimate at any time. Upon + terminating your viewing of these materials or upon + the termination of this license, you must destroy any + downloaded materials in your possession whether in + electronic or printed format. +
  4. +
+
-
-

3. Disclaimer

-
    -
  1. - The materials on Techreanimate's web site are - provided "as is". Techreanimate makes no - warranties, expressed or implied, and hereby disclaims - and negates all other warranties, including without - limitation, implied warranties or conditions of - merchantability, fitness for a particular purpose, or - non-infringement of intellectual property or other - violation of rights. Further, Techreanimate does not - warrant or make any representations concerning the - accuracy, likely results, or reliability of the use of - the materials on its Internet web site or otherwise - relating to such materials or on any sites linked to - this site. -
  2. -
-
+
+

3. Disclaimer

+
    +
  1. + The materials on Techreanimate's web site are + provided "as is". Techreanimate makes no + warranties, expressed or implied, and hereby disclaims + and negates all other warranties, including without + limitation, implied warranties or conditions of + merchantability, fitness for a particular purpose, or + non-infringement of intellectual property or other + violation of rights. Further, Techreanimate does not + warrant or make any representations concerning the + accuracy, likely results, or reliability of the use of + the materials on its Internet web site or otherwise + relating to such materials or on any sites linked to + this site. +
  2. +
+
-
-

4. Limitations

-

- In no event shall Techreanimate or its suppliers be liable - for any damages (including, without limitation, damages - for loss of data or profit, or due to business - interruption,) arising out of the use or inability to use - the materials on Techreanimate's Internet site, even - if Techreanimate or a Techreanimate authorized - representative has been notified orally or in writing of - the possibility of such damage. Because some jurisdictions - do not allow limitations on implied warranties, or - limitations of liability for consequential or incidental - damages, these limitations may not apply to you. -

-
+
+

4. Limitations

+

+ In no event shall Techreanimate or its suppliers be + liable for any damages (including, without limitation, + damages for loss of data or profit, or due to business + interruption,) arising out of the use or inability to + use the materials on Techreanimate's Internet site, + even if Techreanimate or a Techreanimate authorized + representative has been notified orally or in writing of + the possibility of such damage. Because some + jurisdictions do not allow limitations on implied + warranties, or limitations of liability for + consequential or incidental damages, these limitations + may not apply to you. +

+
-
-

5. Revisions and Errata

-

- The materials appearing on Techreanimate's web site - could include technical, typographical, or photographic - errors. Techreanimate does not warrant that any of the - materials on its web site are accurate, complete, or - current. Techreanimate may make changes to the materials - contained on its web site at any time without notice. - Techreanimate does not, however, make any commitment to - update the materials. -

-
+
+

5. Revisions and Errata

+

+ The materials appearing on Techreanimate's web site + could include technical, typographical, or photographic + errors. Techreanimate does not warrant that any of the + materials on its web site are accurate, complete, or + current. Techreanimate may make changes to the materials + contained on its web site at any time without notice. + Techreanimate does not, however, make any commitment to + update the materials. +

+
-
-

6. Links

-

- Techreanimate has not reviewed all of the sites linked to - its Internet web site and is not responsible for the - contents of any such linked site. The inclusion of any - link does not imply endorsement by Techreanimate of the - site. Use of any such linked web site is at the - user's own risk. -

-
+
+

6. Links

+

+ Techreanimate has not reviewed all of the sites linked + to its Internet web site and is not responsible for the + contents of any such linked site. The inclusion of any + link does not imply endorsement by Techreanimate of the + site. Use of any such linked web site is at the + user's own risk. +

+
-
-

7. Site Terms of Use Modifications

-

- Techreanimate may revise these terms of use for its web - site at any time without notice. By using this web site - you are agreeing to be bound by the then current version - of these Terms and Conditions of Use. -

-
+
+

7. Site Terms of Use Modifications

+

+ Techreanimate may revise these terms of use for its web + site at any time without notice. By using this web site + you are agreeing to be bound by the then current version + of these Terms and Conditions of Use. +

+
-
-

8. Governing Law

-

- Any claim relating to Techreanimate's web site shall - be governed by the laws of the State of New York without - regard to its conflict of law provisions. -

-

- General Terms and Conditions applicable to Use of a Web - Site. -

-
+
+

8. Governing Law

+

+ Any claim relating to Techreanimate's web site + shall be governed by the laws of the State of New York + without regard to its conflict of law provisions. +

+

+ General Terms and Conditions applicable to Use of a Web + Site. +

+
- {/* --- PRIVACY POLICY CONTENT --- */} -
-

Privacy Policy

-
-

- Your privacy is very important to us. Accordingly, we have - developed this Policy in order for you to understand how - we collect, use, communicate and disclose and make use of - personal information. The following outlines our privacy - policy. -

-
    -
  • - - Purpose Identification: - {" "} - Before or at the time of collecting personal - information, we will identify the purposes for which - information is being collected. -
  • -
  • - - Consent & Use Limitation: - {" "} - We will collect and use personal information solely with - the objective of fulfilling those purposes specified by - us and for other compatible purposes, unless we obtain - the consent of the individual concerned or as required - by law. -
  • -
  • - Data Retention: We - will only retain personal information as long as - necessary for the fulfillment of those purposes. -
  • -
  • - Collection Method:{" "} - We will collect personal information by lawful and fair - means and, where appropriate, with the knowledge or - consent of the individual concerned. -
  • -
  • - Data Quality:{" "} - Personal data should be relevant to the purposes for - which it is to be used, and, to the extent necessary for - those purposes, should be accurate, complete, and - up-to-date. -
  • -
  • - - Security Safeguards: - {" "} - We will protect personal information by reasonable - security safeguards against loss or theft, as well as - unauthorized access, disclosure, copying, use or - modification. -
  • -
  • - Openness: We will - make readily available to customers information about - our policies and practices relating to the management of - personal information. -
  • -
-

- We are committed to conducting our business in accordance - with these principles in order to ensure that the - confidentiality of personal information is protected and - maintained. -

-
+ {/* --- PRIVACY POLICY CONTENT --- */} +
+

Privacy Policy

+
+

+ Your privacy is very important to us. Accordingly, we + have developed this Policy in order for you to + understand how we collect, use, communicate and disclose + and make use of personal information. The following + outlines our privacy policy. +

+
    +
  • + + Purpose Identification: + {" "} + Before or at the time of collecting personal + information, we will identify the purposes for which + information is being collected. +
  • +
  • + + Consent & Use Limitation: + {" "} + We will collect and use personal information solely + with the objective of fulfilling those purposes + specified by us and for other compatible purposes, + unless we obtain the consent of the individual + concerned or as required by law. +
  • +
  • + Data Retention:{" "} + We will only retain personal information as long as + necessary for the fulfillment of those purposes. +
  • +
  • + + Collection Method: + {" "} + We will collect personal information by lawful and + fair means and, where appropriate, with the knowledge + or consent of the individual concerned. +
  • +
  • + Data Quality:{" "} + Personal data should be relevant to the purposes for + which it is to be used, and, to the extent necessary + for those purposes, should be accurate, complete, and + up-to-date. +
  • +
  • + + Security Safeguards: + {" "} + We will protect personal information by reasonable + security safeguards against loss or theft, as well as + unauthorized access, disclosure, copying, use or + modification. +
  • +
  • + Openness: We will + make readily available to customers information about + our policies and practices relating to the management + of personal information. +
  • +
+

+ We are committed to conducting our business in + accordance with these principles in order to ensure that + the confidentiality of personal information is protected + and maintained. +

+
-
-

- This document was last updated on October 26, 2013 4:17PM - EST -

-
- -
-
- -
-
+
+

+ This document was last updated on October 26, 2013 4:17PM + EST +

+
+ +
+
+ +
+
+ ); } diff --git a/components/Footer.tsx b/components/Footer.tsx index 889ed45e..5991f5d3 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -4,7 +4,7 @@ import React from "react"; import { Nav } from "react-bootstrap"; import Image from "next/image"; -function Footer() { +export default function Footer() { const showLicense = process.env.NEXT_PUBLIC_FOOTER_SITE !== "" && process.env.NEXT_PUBLIC_FOOTER_COPYRIGHT_URL !== ""; @@ -96,5 +96,3 @@ function Footer() { ); } - -export default Footer; diff --git a/components/Header.tsx b/components/Header.tsx index 4a268adb..e490aa26 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -19,12 +19,14 @@ const defaultNavLinks = [ }, ]; -function Header({ +export default function Header({ className, navLinks = defaultNavLinks, darkLinks = false, showBadge = false, }: HeaderProps) { + navLinks = navLinks.length > 0 ? navLinks : defaultNavLinks; + return ( ); } - -export default Header; diff --git a/components/MonHeader.tsx b/components/MonHeader.tsx index 0182eca4..305a8591 100644 --- a/components/MonHeader.tsx +++ b/components/MonHeader.tsx @@ -24,6 +24,8 @@ function MonHeader({ showBadge = false, navLinks = defaultNavLinks, }: HeaderProps) { + navLinks = navLinks.length > 0 ? navLinks : defaultNavLinks; + return ( + {showHeader && ( + + )} +
{children}
+ {showFooter && } + + ); +} diff --git a/components/pokemon/PokeBadge.tsx b/components/_silabs/SclBadge.tsx similarity index 58% rename from components/pokemon/PokeBadge.tsx rename to components/_silabs/SclBadge.tsx index b2b92958..9d89724a 100644 --- a/components/pokemon/PokeBadge.tsx +++ b/components/_silabs/SclBadge.tsx @@ -4,35 +4,40 @@ import Image from "next/image"; //Helpers import { capitalizeFirstLetter } from "@/helpers/_silabs/capitalizeFirstLetter"; //Styles -import styles from "@/public/styles/modules/typeBadges.module.css"; +import styles from "@/public/styles/components/SclBadges.module.css"; -const PokeBadge = ({ +const SclBadge = ({ name, - className = "", + variant = "", + badgeOverwrite = "", imgSrc = "", - fullWidth = true, + needsDarkText = false, + fullWidth = false, }: { name: string; - className?: string; + variant?: string; + badgeOverwrite?: string; imgSrc?: string; + needsDarkText?: boolean; fullWidth?: boolean; }) => { - const lightBackgroundTypes = ["Electric", "Ice", "Ground", "Steel"]; - const needsDarkText = lightBackgroundTypes.includes(name); - // Base classes that are always applied const badgeClasses = [ "d-flex", "align-items-center", - styles.pokeBadge, - styles[className], + styles.baseBadge, + styles[badgeOverwrite], ]; - // Add classes conditionally based on fullWidth prop + // Add classes conditionally + if (variant) { + badgeClasses.push(variant); + } + if (fullWidth) { badgeClasses.push("w-100", "justify-content-center"); // Add full width and centering only if true } else { - badgeClasses.push("d-inline-flex"); // You might use d-inline-flex if d-flex alone isn't sufficient + badgeClasses.push("d-inline-flex"); } // Add dark text if needed @@ -41,11 +46,14 @@ const PokeBadge = ({ } return ( - + {imgSrc && ( {`${name} ); } - -export default SclCard; diff --git a/components/pages/PokedexClientSection.tsx b/components/pages/PokedexClientSection.tsx index 915383c5..53cf6783 100644 --- a/components/pages/PokedexClientSection.tsx +++ b/components/pages/PokedexClientSection.tsx @@ -2,18 +2,18 @@ import React, { useState, useEffect, Suspense } from "react"; import { Container, Row, Col, Spinner } from "react-bootstrap"; +// --- Next --- import Link from "next/link"; -// Import hooks from 'next/navigation' for App Router import { useRouter, useSearchParams } from "next/navigation"; -//Components +// --- Components --- import { GameClient, Pokedex } from "pokenode-ts"; -import PokemonEntryList from "@/components/pokemon/PokemonEntryList"; -import PokeBadge from "@/components/pokemon/PokeBadge"; +import PokemonGrid from "@/components/pokemon/PokemonGrid"; +import SclBadge from "@/components/_silabs/SclBadge"; import LanguageTable from "@/components/pokemon/LanguageTable"; -//Helpers +// --- Helpers --- import { capitalizeFirstLetter } from "@/helpers/_silabs/capitalizeFirstLetter"; -import { createVersionGroupsSentence } from "@/helpers/createVersionGroupsSentence"; -//Icons +import { createNamedAPIResourceSentence } from "@/helpers/createNamedAPIResourceSentence"; +// --- Icons --- import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCheck, faCircleXmark } from "@fortawesome/free-solid-svg-icons"; @@ -90,14 +90,13 @@ function PokedexClientSection() { {formattedName} (Pokédex) - {" "}

Region

{apiData.region?.name ? (

This Pokédex is from the{" "} - + {capitalizeFirstLetter(apiData.region.name)} {" "} region. @@ -109,8 +108,10 @@ function PokedexClientSection() { <>


Game Versions

- {createVersionGroupsSentence( - `${formattedName} Pokédex`, + {createNamedAPIResourceSentence( + `${formattedName} Pokédex is associated with the version groups:`, + `${formattedName} is not associated with any specific version groups`, + "/pokemon/game", apiData.version_groups )} @@ -162,14 +163,13 @@ function PokedexClientSection() {

Pokémon in the {formattedName} Pokédex{" "} -

- + ) : (

diff --git a/components/pages/PokemonGenerationClientSection.tsx b/components/pages/PokemonGenerationClientSection.tsx new file mode 100644 index 00000000..beac6e4a --- /dev/null +++ b/components/pages/PokemonGenerationClientSection.tsx @@ -0,0 +1,246 @@ +"use client"; + +import React, { useState, useEffect, Suspense } from "react"; +import { Container, Row, Col, Spinner } from "react-bootstrap"; +// --- Next --- +import Link from "next/link"; +import { useRouter, useSearchParams } from "next/navigation"; +// --- Components --- +import { GameClient, Generation } from "pokenode-ts"; +import LanguageTable from "@/components/pokemon/LanguageTable"; +import SclBadge from "@/components/_silabs/SclBadge"; +import PokemonGrid from "@/components/pokemon/PokemonGrid"; +import MoveList from "@/components/pokemon/MoveList"; +// --- Helpers --- +import { capitalizeFirstLetter } from "@/helpers/_silabs/capitalizeFirstLetter"; +import { createNamedAPIResourceSentence } from "@/helpers/createNamedAPIResourceSentence"; + +export default function PokemonGenerationClientSectionWrapper() { + return ( + }> + + + ); +} + +function PokemonGenerationClientSection() { + const router = useRouter(); + const searchParams = useSearchParams(); + + const [isLoading, setIsLoading] = useState(true); + const [apiData, setApiData] = useState(null); + const [formattedName, setFormattedName] = useState(""); + const [errorOccurred, setErrorOccurred] = useState(false); + + useEffect(() => { + const nameParam = searchParams?.get("name"); + + // Handle case where nameParam is missing or empty + if (!nameParam) { + console.warn("No 'name' parameter found in URL."); + setErrorOccurred(true); // Indicate an error state + setIsLoading(false); + return; + } + + // Reset state for new fetch + setIsLoading(true); + setErrorOccurred(false); + setApiData(null); + setFormattedName(capitalizeFirstLetter(nameParam)); + + const api = new GameClient(); + + api + .getGenerationByName(nameParam) + .then((data) => { + setApiData(data); + }) + .catch((error) => { + console.error("Failed to fetch Pokémon Generation data:", error); + setErrorOccurred(true); + }) + .finally(() => { + setIsLoading(false); + }); + }, [searchParams, router]); + + if (isLoading) { + return ; + } + + if (errorOccurred || !apiData) { + return ( + +

+ Could not load Pokémon Generation data. The requested Pokémon + Generation might not exist or there was an error. +

+ Go back to homepage + + ); + } + + // --- Render successful data --- + return ( + <> +

+ {formattedName} (generation) +

+ + + {/*

This is the description

+
*/} +

Region

+ {apiData?.main_region?.name ? ( +

+ The main region for {formattedName} is{" "} + + {apiData.main_region.name} + + . +

+ ) : ( +

There is no main region data for this region

+ )} + {apiData.version_groups && apiData.version_groups.length > 0 && ( + <> +
+

Game Versions

+ {createNamedAPIResourceSentence( + `${formattedName} is associated with the version groups:`, + `${formattedName} is not associated with any specific version groups`, + "/pokemon/game", + apiData.version_groups + )} + + )} +
+

Pokémon Types

+ {createNamedAPIResourceSentence( + `${formattedName} introduced the following pokémon types:`, + `${formattedName} did not introduce any pokémon types.`, + "/pokemon/type", + apiData.types + )} + + + +

{`Introduced in ${formattedName}`}

+
+ {apiData?.pokemon_species && ( + +

+ {apiData?.pokemon_species.length} +

+

Pokémon

+ + )} + {apiData?.types && ( + +

{apiData?.types.length}

+

Pokémon Types

+ + )} + {apiData?.moves && ( + +

{apiData?.moves.length}

+

Moves

+ + )} + {apiData?.abilities && ( + +

{apiData?.abilities.length}

+

Abilities

+ + )} +
+ {apiData?.names && ( + <> +
+ + + )} + +
+ + {apiData?.pokemon_species && ( + <> +

+ {`Pokémon Introduced `} + + + +

+ + + )} + {apiData?.moves && ( + <> +
+

+ {`Moves Introduced `} + + + +

+ + + )} + {apiData?.abilities && ( + <> +
+

+ {`Abilities Introduced `} + + + +

+ {apiData?.abilities.length > 0 ? ( +
+ {apiData.abilities.map((item, index) => ( + + + + ))} +
+ ) : ( +

+ No abilities were introduced in this generation +

+ )} + + )} +
+ + ); +} + +// Reusable Loading Fallback Component +function LoadingFallback() { + return ( + + + Loading... + +

Loading Pokémon Generation Data...

+
+ ); +} diff --git a/components/pages/PokemonRegionClientSection.tsx b/components/pages/PokemonRegionClientSection.tsx index 0115c421..8f103aac 100644 --- a/components/pages/PokemonRegionClientSection.tsx +++ b/components/pages/PokemonRegionClientSection.tsx @@ -2,16 +2,16 @@ import React, { useState, useEffect, Suspense } from "react"; import { Container, Row, Col, Spinner } from "react-bootstrap"; +// --- Next --- import Link from "next/link"; -// Import hooks from 'next/navigation' for App Router import { useRouter, useSearchParams } from "next/navigation"; -//Components +// --- Components --- import { LocationClient, Region } from "pokenode-ts"; import LanguageTable from "@/components/pokemon/LanguageTable"; -import PokeBadge from "@/components/pokemon/PokeBadge"; -//Helpers +import SclBadge from "@/components/_silabs/SclBadge"; +// --- Helpers --- import { capitalizeFirstLetter } from "@/helpers/_silabs/capitalizeFirstLetter"; -import { createVersionGroupsSentence } from "@/helpers/createVersionGroupsSentence"; +import { createNamedAPIResourceSentence } from "@/helpers/createNamedAPIResourceSentence"; export default function PokemonRegionClientSectionWrapper() { return ( @@ -89,7 +89,7 @@ function PokemonRegionClientSection() { {/*

This is the description


*/} -

Region

+

Main Generation

{apiData?.main_generation?.name ? (

The main generation for {formattedName} is{" "} @@ -107,8 +107,10 @@ function PokemonRegionClientSection() { <>


Game Versions

- {createVersionGroupsSentence( - `${formattedName} Region`, + {createNamedAPIResourceSentence( + `${formattedName} Region is associated with the version groups:`, + `${formattedName} is not associated with any specific version groups`, + "/pokemon/game", apiData.version_groups )} @@ -119,7 +121,7 @@ function PokemonRegionClientSection() {

{`Pokédexes `} - @@ -133,9 +135,9 @@ function PokemonRegionClientSection() { className="text-decoration-none" passHref > - ))} @@ -165,7 +167,7 @@ function PokemonRegionClientSection() {

{`${formattedName} Locations `} - @@ -179,9 +181,9 @@ function PokemonRegionClientSection() { className="text-decoration-none" passHref > - ))} diff --git a/components/pages/PokemonTypeClientSection.tsx b/components/pages/PokemonTypeClientSection.tsx index 698ff88c..5918515e 100644 --- a/components/pages/PokemonTypeClientSection.tsx +++ b/components/pages/PokemonTypeClientSection.tsx @@ -2,16 +2,16 @@ import React, { useState, useEffect, Suspense } from "react"; import { Container, Row, Col, Spinner } from "react-bootstrap"; +import { PokemonClient, Type as PokemonTypeData } from "pokenode-ts"; +// --- Next --- import Link from "next/link"; import Image from "next/image"; -// Import hooks from 'next/navigation' for App Router import { useRouter, useSearchParams } from "next/navigation"; -import { PokemonClient, Type as PokemonTypeData } from "pokenode-ts"; //Components import PokemonSpritesDisplay from "@/components/pokemon/PokemonSpritesDisplay"; import PokemonGrid from "@/components/pokemon/PokemonGrid"; import MoveList from "@/components/pokemon/MoveList"; -import PokeBadge from "@/components/pokemon/PokeBadge"; +import SclBadge from "@/components/_silabs/SclBadge"; import LanguageTable from "@/components/pokemon/LanguageTable"; //Helpers import { createDamageRelationSentences } from "@/helpers/createDamageRelationSentences"; @@ -41,13 +41,11 @@ function PokemonTypeClientSection() { const [errorOccurred, setErrorOccurred] = useState(false); useEffect(() => { - const nameParam = searchParams?.get("name"); - const foundType = typesData.find( - (type) => type.name.toLowerCase() === nameParam?.toLowerCase() - ); + const nameParam = searchParams?.get("name") ?? ""; + const foundType = typesData[nameParam.toLowerCase()] ?? null; // Handle case where nameParam is missing or empty - if (!nameParam || !foundType) { + if (!nameParam) { console.warn("No 'name' parameter found in URL."); setErrorOccurred(true); setIsLoading(false); @@ -100,7 +98,7 @@ function PokemonTypeClientSection() { {typeData && ( {`${typeData.name} -

{typeData?.description}

+

{typeData?.description ?? "No description available"}

{apiData?.damage_relations && ( <>
@@ -148,7 +146,7 @@ function PokemonTypeClientSection() { {apiData?.pokemon && (

{apiData?.pokemon.length}

-

{`${formattedName} type Pokémon`}

+

{`${formattedName} Pokémon`}

)} {apiData?.moves && ( @@ -195,9 +193,9 @@ function PokemonTypeClientSection() {

{`${formattedName} type Pokémon `} - @@ -211,9 +209,9 @@ function PokemonTypeClientSection() {

{`${formattedName}-type moves `} - diff --git a/components/pokemon/MoveList.tsx b/components/pokemon/MoveList.tsx index b8446f05..8539d234 100644 --- a/components/pokemon/MoveList.tsx +++ b/components/pokemon/MoveList.tsx @@ -1,7 +1,11 @@ import React from "react"; -import Link from "next/link"; import { Container } from "react-bootstrap"; -import PokeBadge from "@/components/pokemon/PokeBadge"; +// --- Next --- +import Link from "next/link"; +// --- Components --- +import SclBadge from "@/components/_silabs/SclBadge"; +// --- Types --- +import type { NamedAPIResource } from "pokenode-ts"; /** * Renders a list of Pokémon moves as clickable badges with custom background color. @@ -15,7 +19,7 @@ function MoveList({ moves, className = "" }) { if (moveList.length === 0) { return ( -

No moves available.

+

No moves available.

); } @@ -23,14 +27,19 @@ function MoveList({ moves, className = "" }) { return (
- {moveList.map((move) => ( + {moveList.map((move: NamedAPIResource, index: number) => ( - + ))}
diff --git a/components/pokemon/PokemonEntryList.tsx b/components/pokemon/PokemonEntryList.tsx deleted file mode 100644 index 2b9a65ba..00000000 --- a/components/pokemon/PokemonEntryList.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from "react"; -import Link from "next/link"; -import Container from "react-bootstrap/Container"; -import Row from "react-bootstrap/Row"; -import Col from "react-bootstrap/Col"; -import Card from "react-bootstrap/Card"; -//Helpers -import { capitalizeFirstLetter } from "@/helpers/_silabs/capitalizeFirstLetter"; -import { getPokemonIdFromUrl } from "@/helpers/getPokemonIdFromUrl"; -//Styles -import styles from "@/public/styles/components/PokemonGrid.module.css"; -//Types -import { PokemonEntry } from "pokenode-ts"; - -interface PokemonEntryListProps { - data: PokemonEntry[]; -} - -function PokemonEntryList({ data }: PokemonEntryListProps) { - const listToRender = data ?? []; - - if (listToRender.length === 0) { - return ( - -

No Pokémon entries to display.

-
- ); - } - - return ( - - - {listToRender.map((item) => { - const name = item.pokemon_species.name; - const url = item.pokemon_species.url; - const entry_number = item.entry_number; - - const pokemonId = getPokemonIdFromUrl(url); - - const imageUrl = pokemonId - ? `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${pokemonId}.png` - : "/images/pokedex/question_mark.png"; // Fallback image - - return ( - - - - - - - {capitalizeFirstLetter(name)} - - - Entry #: {entry_number} - - - - - - ); - })} - - - ); -} - -export default PokemonEntryList; // Export the new component name diff --git a/components/pokemon/PokemonGrid.tsx b/components/pokemon/PokemonGrid.tsx index a5f1674a..8e54fc2a 100644 --- a/components/pokemon/PokemonGrid.tsx +++ b/components/pokemon/PokemonGrid.tsx @@ -1,19 +1,16 @@ import React from "react"; import Link from "next/link"; -import Container from "react-bootstrap/Container"; -import Row from "react-bootstrap/Row"; -import Col from "react-bootstrap/Col"; -import Card from "react-bootstrap/Card"; +import { Container, Row, Col, Card } from "react-bootstrap"; //Helpers import { capitalizeFirstLetter } from "@/helpers/_silabs/capitalizeFirstLetter"; import { getPokemonIdFromUrl } from "@/helpers/getPokemonIdFromUrl"; //Styles import styles from "@/public/styles/components/PokemonGrid.module.css"; //Types -import { TypePokemon } from "pokenode-ts"; +import type { TypePokemon, PokemonEntry, NamedAPIResource } from "pokenode-ts"; interface PokemonGridProps { - data: TypePokemon[]; + data: TypePokemon[] | PokemonEntry[] | NamedAPIResource[]; } function PokemonGrid({ data }: PokemonGridProps) { @@ -39,9 +36,15 @@ function PokemonGrid({ data }: PokemonGridProps) { className="g-4 justify-content-center" > {listToRender.map((item) => { - const name = item.pokemon.name; - const url = item.pokemon.url; - const slot = item.slot; + const pokemon = item?.pokemon + ? item.pokemon + : item?.pokemon_species + ? item.pokemon_species + : item; + const name = pokemon.name; + const url = pokemon.url; + const slot = item?.slot ?? -1; + const entry_number = item?.entry_number ?? -1; const pokemonId = getPokemonIdFromUrl(url); const imageUrl = pokemonId @@ -74,7 +77,8 @@ function PokemonGrid({ data }: PokemonGridProps) { {capitalizeFirstLetter(name)} - Slot: {slot} + {slot !== -1 && <> Slot: {slot} } + {entry_number !== -1 && <> Entry #: {entry_number} } diff --git a/components/pokemon/home/GenerationsSection.tsx b/components/pokemon/home/GenerationsSection.tsx new file mode 100644 index 00000000..4022c75a --- /dev/null +++ b/components/pokemon/home/GenerationsSection.tsx @@ -0,0 +1,59 @@ +"use client"; +import React, { useEffect, useState } from "react"; +import Link from "next/link"; +import { Col, Row } from "react-bootstrap"; +import { GameClient, NamedAPIResource } from "pokenode-ts"; +// --- Components --- +import SclBadge from "@/components/_silabs/SclBadge"; + +function GenerationsSection() { + const [isLoading, setIsLoading] = useState(true); + const [data, setData] = useState([]); + + useEffect(() => { + (async () => { + const api = new GameClient(); + + await api + .listGenerations(0, 100) + .then((data) => { + setData(data.results); + setIsLoading(false); + }) + .catch((error) => { + console.error(error); + setIsLoading(false); + }); + })(); + }, []); + + return ( + + +

Generations

+ {isLoading ? ( +
Loading Generations...
+ ) : ( +
+ {data.map((value, index) => ( + + + + ))} +
+ )} + +
+ ); +} + +export default GenerationsSection; diff --git a/components/pokemon/home/PokedexesSection.tsx b/components/pokemon/home/PokedexesSection.tsx index 9e460785..38621d98 100644 --- a/components/pokemon/home/PokedexesSection.tsx +++ b/components/pokemon/home/PokedexesSection.tsx @@ -1,14 +1,14 @@ "use client"; import React, { useEffect, useState } from "react"; import Link from "next/link"; -import { Badge, Col, Row } from "react-bootstrap"; +import { Col, Row } from "react-bootstrap"; import { GameClient, NamedAPIResource } from "pokenode-ts"; -//Helpers -import { capitalizeFirstLetter } from "@/helpers/_silabs/capitalizeFirstLetter"; +// --- Components --- +import SclBadge from "@/components/_silabs/SclBadge"; function PokedexesSection() { const [isLoading, setIsLoading] = useState(true); - const [pokedexes, setPokedexes] = useState([]); + const [data, setData] = useState([]); useEffect(() => { (async () => { @@ -17,7 +17,7 @@ function PokedexesSection() { await api .listPokedexes(0, 100) .then((data) => { - setPokedexes(data.results); + setData(data.results); setIsLoading(false); }) .catch((error) => { @@ -29,32 +29,29 @@ function PokedexesSection() { return ( -

Pokédexes

- {isLoading ? ( - Loading Pokédexes... - ) : ( - pokedexes.map((value, index) => ( - - - +

Pokedexes

+ {isLoading ? ( +
Loading Pokedexes...
+ ) : ( +
+ {data.map((value, index) => ( + - {capitalizeFirstLetter(value.name)} - - - - )) - )} + + + ))} +
+ )} +
); } diff --git a/components/pokemon/home/RegionsSection.tsx b/components/pokemon/home/RegionsSection.tsx index b0b73221..2a347366 100644 --- a/components/pokemon/home/RegionsSection.tsx +++ b/components/pokemon/home/RegionsSection.tsx @@ -1,14 +1,14 @@ "use client"; import React, { useEffect, useState } from "react"; import Link from "next/link"; -import { Badge, Col, Row } from "react-bootstrap"; +import { Col, Row } from "react-bootstrap"; import { LocationClient, NamedAPIResource } from "pokenode-ts"; -//Helpers -import { capitalizeFirstLetter } from "@/helpers/_silabs/capitalizeFirstLetter"; +// --- Components --- +import SclBadge from "@/components/_silabs/SclBadge"; function RegionsSection() { const [isLoading, setIsLoading] = useState(true); - const [regions, setRegions] = useState([]); + const [data, setData] = useState([]); useEffect(() => { (async () => { @@ -17,7 +17,7 @@ function RegionsSection() { await api .listRegions(0, 100) .then((data) => { - setRegions(data.results); + setData(data.results); setIsLoading(false); }) .catch((error) => { @@ -29,32 +29,29 @@ function RegionsSection() { return ( -

Regions

- {isLoading ? ( - Loading Regions... - ) : ( - regions.map((value, index) => ( - - - +

Regions

+ {isLoading ? ( +
Loading Regions...
+ ) : ( +
+ {data.map((value, index) => ( + - {capitalizeFirstLetter(value.name)} - - - - )) - )} + + + ))} +
+ )} +
); } diff --git a/components/pokemon/home/TypesSection.tsx b/components/pokemon/home/TypesSection.tsx index 123ecdc1..ed6e703f 100644 --- a/components/pokemon/home/TypesSection.tsx +++ b/components/pokemon/home/TypesSection.tsx @@ -1,29 +1,32 @@ "use client"; + import React from "react"; import Link from "next/link"; import { Col, Row } from "react-bootstrap"; -import PokeBadge from "@/components/pokemon/PokeBadge"; -//Data +// --- Components --- +import SclBadge from "@/components/_silabs/SclBadge"; +// --- Data --- import typesData from "@/json/pokemon/types.json"; -//Types -import { PokemonType } from "@/types/pokemon/Types"; +// --- Types --- +import type { PokemonType } from "@/types/pokemon/Types"; function TypesSection() { - const types: PokemonType[] = typesData ?? []; + const types: Record = typesData ?? {}; return (

Pokémon Types

- {types.map((type) => ( - + {Object.entries(types).map(([typeName, typeDetails]) => ( + - diff --git a/helpers/createNamedAPIResourceSentence.tsx b/helpers/createNamedAPIResourceSentence.tsx new file mode 100644 index 00000000..125663ac --- /dev/null +++ b/helpers/createNamedAPIResourceSentence.tsx @@ -0,0 +1,52 @@ +import React, { JSX } from "react"; +import Link from "next/link"; +import { NamedAPIResource } from "pokenode-ts"; +// Helpers +import { getSentenceSeperator } from "@/helpers/getSentenceSeperator"; + +/** + * Creates a JSX sentence listing NamedAPIResources with links. + * + * @param {string} initialString - The initial string of the subject (e.g., Kanto Pokédex is associated with the version groups:). + * @param {string} emptyString - The empty string of the subject (e.g., Kanto Pokédex is not associated with any specific version groups) + * @param {string} link - The link to send the user to + * @param {NamedAPIResource[]} values - Array of NamedAPIResource objects (name and url). + * @returns {JSX.Element | null} - JSX element representing the sentence, or a paragraph indicating nothing. + */ +export function createNamedAPIResourceSentence( + initialString: string, + emptyString: string, + link: string, + values: NamedAPIResource[] +): JSX.Element { + const numGroups = values ? values.length : 0; + + // Handle empty cases + if (numGroups === 0) { + return

{emptyString}

; + } + + return ( +

+ {initialString}{" "} + {values.map((item, index) => { + const linkHref = `${link}?name=${item.name}`; + + const groupLink = ( + + {item.name} + + ); + + const separator: string | null = getSentenceSeperator(index, numGroups); + + return ( + + {groupLink} + {separator} + + ); + })} +

+ ); +} diff --git a/helpers/createVersionGroupsSentence.tsx b/helpers/createVersionGroupsSentence.tsx deleted file mode 100644 index f4cc85e9..00000000 --- a/helpers/createVersionGroupsSentence.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React, { JSX } from "react"; -import Link from "next/link"; -import { NamedAPIResource } from "pokenode-ts"; -// Helpers -import { getSentenceSeperator } from "@/helpers/getSentenceSeperator"; - -/** - * Creates a JSX sentence listing version groups with links. - * - * @param {string} baseName - The name of the subject (e.g., Kanto Pokédex). - * @param {NamedAPIResource[]} values - Array of version group objects (name and url). - * @returns {JSX.Element | null} - JSX element representing the sentence, or a paragraph indicating no groups. - */ -export function createVersionGroupsSentence( - baseName: string, - values: NamedAPIResource[] -): JSX.Element { - const numGroups = values.length; - - // Handle empty cases - if (numGroups === 0) { - return ( -

The {baseName} is not associated with any specific version groups.

- ); - } - - return ( -

- The {baseName} is associated with the version groups:{" "} - {values.map((versionGroup, index) => { - const linkHref = `/pokemon/game?name=${versionGroup.name}`; - - const groupLink = ( - - {versionGroup.name} - - ); - - const separator: string | null = getSentenceSeperator(index, numGroups); - - return ( - - {groupLink} - {separator} - - ); - })} -

- ); -} diff --git a/json/pokdexes.json b/json/pokdexes.json deleted file mode 100644 index f50f67e1..00000000 --- a/json/pokdexes.json +++ /dev/null @@ -1,130 +0,0 @@ -[ - { - "name": "national", - "url": "https://pokeapi.co/api/v2/pokedex/1/" - }, - { - "name": "kanto", - "url": "https://pokeapi.co/api/v2/pokedex/2/" - }, - { - "name": "original-johto", - "url": "https://pokeapi.co/api/v2/pokedex/3/" - }, - { - "name": "hoenn", - "url": "https://pokeapi.co/api/v2/pokedex/4/" - }, - { - "name": "original-sinnoh", - "url": "https://pokeapi.co/api/v2/pokedex/5/" - }, - { - "name": "extended-sinnoh", - "url": "https://pokeapi.co/api/v2/pokedex/6/" - }, - { - "name": "updated-johto", - "url": "https://pokeapi.co/api/v2/pokedex/7/" - }, - { - "name": "original-unova", - "url": "https://pokeapi.co/api/v2/pokedex/8/" - }, - { - "name": "updated-unova", - "url": "https://pokeapi.co/api/v2/pokedex/9/" - }, - { - "name": "conquest-gallery", - "url": "https://pokeapi.co/api/v2/pokedex/11/" - }, - { - "name": "kalos-central", - "url": "https://pokeapi.co/api/v2/pokedex/12/" - }, - { - "name": "kalos-coastal", - "url": "https://pokeapi.co/api/v2/pokedex/13/" - }, - { - "name": "kalos-mountain", - "url": "https://pokeapi.co/api/v2/pokedex/14/" - }, - { - "name": "updated-hoenn", - "url": "https://pokeapi.co/api/v2/pokedex/15/" - }, - { - "name": "original-alola", - "url": "https://pokeapi.co/api/v2/pokedex/16/" - }, - { - "name": "original-melemele", - "url": "https://pokeapi.co/api/v2/pokedex/17/" - }, - { - "name": "original-akala", - "url": "https://pokeapi.co/api/v2/pokedex/18/" - }, - { - "name": "original-ulaula", - "url": "https://pokeapi.co/api/v2/pokedex/19/" - }, - { - "name": "original-poni", - "url": "https://pokeapi.co/api/v2/pokedex/20/" - }, - { - "name": "updated-alola", - "url": "https://pokeapi.co/api/v2/pokedex/21/" - }, - { - "name": "updated-melemele", - "url": "https://pokeapi.co/api/v2/pokedex/22/" - }, - { - "name": "updated-akala", - "url": "https://pokeapi.co/api/v2/pokedex/23/" - }, - { - "name": "updated-ulaula", - "url": "https://pokeapi.co/api/v2/pokedex/24/" - }, - { - "name": "updated-poni", - "url": "https://pokeapi.co/api/v2/pokedex/25/" - }, - { - "name": "letsgo-kanto", - "url": "https://pokeapi.co/api/v2/pokedex/26/" - }, - { - "name": "galar", - "url": "https://pokeapi.co/api/v2/pokedex/27/" - }, - { - "name": "isle-of-armor", - "url": "https://pokeapi.co/api/v2/pokedex/28/" - }, - { - "name": "crown-tundra", - "url": "https://pokeapi.co/api/v2/pokedex/29/" - }, - { - "name": "hisui", - "url": "https://pokeapi.co/api/v2/pokedex/30/" - }, - { - "name": "paldea", - "url": "https://pokeapi.co/api/v2/pokedex/31/" - }, - { - "name": "kitakami", - "url": "https://pokeapi.co/api/v2/pokedex/32/" - }, - { - "name": "blueberry", - "url": "https://pokeapi.co/api/v2/pokedex/33/" - } -] \ No newline at end of file diff --git a/json/pokemon/types.json b/json/pokemon/types.json index 68848568..f7871228 100644 --- a/json/pokemon/types.json +++ b/json/pokemon/types.json @@ -1,128 +1,110 @@ -[ - { - "name": "Normal", +{ + "normal": { "color": "#A8A77A", "className": "bgNormal", "imgSrc": "normal.svg", "description": "Represents ordinary creatures and adaptability. They have few type advantages but also few weaknesses, often relying on diverse movepools." }, - { - "name": "Fire", + "fire": { "color": "#EE8130", "className": "bgFire", "imgSrc": "fire.svg", "description": "Characterized by intense heat, flames, and combustion. Fire-types often inflict burns and are powerful against plant and ice-based foes." }, - { - "name": "Water", + "water": { "color": "#6390F0", "className": "bgWater", "imgSrc": "water.svg", "description": "Associated with oceans, rivers, and rain. Water-types are versatile, excelling against fire and ground, and often able to control water." }, - { - "name": "Grass", + "grass": { "color": "#7AC74C", "className": "bgGrass", "imgSrc": "grass.svg", "description": "Embodies nature, plants, and life energy. Grass-types often use status conditions like sleep or poison and draw strength from sunlight." }, - { - "name": "Electric", + "electric": { "color": "#F7D02C", "className": "bgElectric", "imgSrc": "electric.svg", "description": "Represents electricity, speed, and modern technology. Electric-types are known for paralysis-inducing moves and effectiveness against water and flying foes." }, - { - "name": "Ice", + "ice": { "color": "#96D9D6", "className": "bgIce", "imgSrc": "ice.svg", "description": "Associated with cold, snow, and glaciers. Ice-types can freeze opponents and are particularly effective against dragons and flying creatures." }, - { - "name": "Fighting", + "fighting": { "color": "#C22E28", "className": "bgFighting", "imgSrc": "fighting.svg", "description": "Symbolizes physical strength, martial arts, and discipline. Fighting-types excel in close combat, breaking through defenses like rock and steel." }, - { - "name": "Poison", + "poison": { "color": "#A33EA1", "className": "bgPoison", "imgSrc": "poison.svg", "description": "Represents toxins, pollution, and debilitating ailments. Poison-types often weaken opponents over time and counter grass and fairy types." }, - { - "name": "Ground", + "ground": { "color": "#E2BF65", "className": "bgGround", "imgSrc": "ground.svg", "description": "Connected to the earth, sand, and seismic power. Ground-types are immune to electric attacks and hit hard against fire, rock, and steel." }, - { - "name": "Flying", + "flying": { "color": "#A98FF3", "className": "bgFlying", "imgSrc": "flying.svg", "description": "Associated with the sky, wind, and aerial agility. Flying-types often evade ground-based attacks and are strong against grass and fighting types." }, - { - "name": "Psychic", + "psychic": { "color": "#F95587", "className": "bgPsychic", "imgSrc": "psychic.svg", "description": "Represents mental prowess, telekinesis, and extrasensory perception. Psychic-types often manipulate the battlefield and counter fighting and poison types." }, - { - "name": "Bug", + "bug": { "color": "#A6B91A", "className": "bgBug", "imgSrc": "bug.svg", "description": "Embodies insects, arthropods, and rapid adaptation. Bug-types often mature quickly and have advantages against grass, psychic, and dark types." }, - { - "name": "Rock", + "rock": { "color": "#B6A136", "className": "bgRock", "imgSrc": "rock.svg", "description": "Symbolizes stone, mountains, and sturdy defense. Rock-types possess high durability and are effective against fire, ice, and flying foes." }, - { - "name": "Ghost", + "ghost": { "color": "#735797", "className": "bgGhost", "imgSrc": "ghost.svg", "description": "Represents the supernatural, spirits, and trickery. Ghost-types can phase through normal attacks and exploit psychic and other ghosts." }, - { - "name": "Dragon", + "dragon": { "color": "#6F35FC", "className": "bgDragon", "imgSrc": "dragon.svg", "description": "Embodies mythical power, ancient lineage, and raw elemental force. Dragon-types are rare and powerful, primarily weak only to ice, fairy, and themselves." }, - { - "name": "Dark", + "dark": { "color": "#705746", "className": "bgDark", "imgSrc": "dark.svg", "description": "Associated with shadows, underhanded tactics, and exploiting weaknesses. Dark-types are immune to psychic moves and effective against ghost and psychic types." }, - { - "name": "Steel", + "steel": { "color": "#B7B7CE", "className": "bgSteel", "imgSrc": "steel.svg", "description": "Represents metal, industry, and impenetrable defense. Steel-types boast numerous resistances, are immune to poison, and counter ice, rock, and fairy types." }, - { - "name": "Fairy", + "fairy": { "color": "#D685AD", "className": "bgFairy", "imgSrc": "fairy.svg", "description": "Embodies magic, enchantment, and otherworldly charm. Fairy-types are immune to dragon attacks and are strong against fighting, dragon, and dark types." } -] +} diff --git a/next.config.mjs b/next.config.mjs index df9307d4..3e56c35d 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -2,6 +2,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { + productionBrowserSourceMaps: false, reactStrictMode: true, output: "export", images: { diff --git a/public/styles/modules/typeBadges.module.css b/public/styles/components/SclBadges.module.css similarity index 94% rename from public/styles/modules/typeBadges.module.css rename to public/styles/components/SclBadges.module.css index ffb85cf2..5e7c8613 100644 --- a/public/styles/modules/typeBadges.module.css +++ b/public/styles/components/SclBadges.module.css @@ -1,11 +1,20 @@ -.pokeBadge { - color: #fff; +.baseBadge { + color: #fff !important; text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.6); padding: 0.5em; background-color: #e53945 !important; } -/* --- Background colors --- */ +.textDark { + color: #333 !important; + text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.4) !important; +} + +.bgGray { + background-color: #6c757e !important; +} + +/* --- Custom Colors --- */ .bgNormal { background-color: #a8a77a !important; } @@ -60,12 +69,3 @@ .bgFairy { background-color: #d685ad !important; } - -.textDark { - color: #333 !important; - text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.4) !important; -} - -.bgGray { - background-color: #6c757e !important; -} diff --git a/types/pokemon/Types.d.ts b/types/pokemon/Types.d.ts index a071a521..2c4f259a 100644 --- a/types/pokemon/Types.d.ts +++ b/types/pokemon/Types.d.ts @@ -1,7 +1,6 @@ import { Type } from "pokenode-ts"; export type PokemonType = { - name: string; color: string; imgSrc: string; description: string;