diff --git a/app/layout.tsx b/app/layout.tsx index 04624d8..5a2abfd 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -44,6 +44,9 @@ export default function RootLayout({
  • Interactive
  • +
  • + Star Wars +
  • Error
  • diff --git a/app/star-wars/layout.tsx b/app/star-wars/layout.tsx new file mode 100644 index 0000000..5e8efdc --- /dev/null +++ b/app/star-wars/layout.tsx @@ -0,0 +1,15 @@ +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
    +
    +

    + Star Wars +

    +
    + MtFBWY! +
    +
    + {children} +
    + ); +} diff --git a/app/star-wars/loading.tsx b/app/star-wars/loading.tsx new file mode 100644 index 0000000..eb55c4d --- /dev/null +++ b/app/star-wars/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
    + Loading +
    + ); +} diff --git a/app/star-wars/not-found.tsx b/app/star-wars/not-found.tsx new file mode 100644 index 0000000..5c8afb6 --- /dev/null +++ b/app/star-wars/not-found.tsx @@ -0,0 +1,21 @@ +export const metadata = { + title: `Star War Not Found`, +}; + +export default function NotFound() { + return ( + <> +
    +

    + Star War Not Found +

    +
    + + You have failed me for the last time! + +
    +
    +
    + + ); +} diff --git a/app/star-wars/people/[id]/loading.tsx b/app/star-wars/people/[id]/loading.tsx new file mode 100644 index 0000000..3eb45bb --- /dev/null +++ b/app/star-wars/people/[id]/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
    + Loading +
    + ); +} diff --git a/app/star-wars/people/[id]/page.tsx b/app/star-wars/people/[id]/page.tsx new file mode 100644 index 0000000..2c2059e --- /dev/null +++ b/app/star-wars/people/[id]/page.tsx @@ -0,0 +1,46 @@ +import { type Person } from '../../types'; +import { Metadata } from 'next'; +import { notFound } from 'next/navigation'; +import sleep from '@/util/sleep'; + +type Props = { + params: { id: string }; +}; + +async function getPerson(id: string): Promise { + await sleep(); + const res = await fetch(`https://swapi.dev/api/people/${id}`); + + const json = await res.json(); + return json; +} + +export async function generateMetadata({ params }: Props): Promise { + const person = await getPerson(params.id); + + return { + title: person.name, + }; +} + +export default async function Page({ params }: Props) { + const person = await getPerson(params.id); + + if (!person.name) { + notFound(); + } + + return ( +
    +

    {person.name}

    +
    +
    Height
    +
    {person.height}
    +
    Mass
    +
    {person.mass}
    +
    Hair Color
    +
    {person.hair_color}
    +
    +
    + ); +} diff --git a/app/star-wars/people/page.tsx b/app/star-wars/people/page.tsx new file mode 100644 index 0000000..e532322 --- /dev/null +++ b/app/star-wars/people/page.tsx @@ -0,0 +1,37 @@ +import Link from 'next/link'; +import sleep from '@/util/sleep'; +import { type Person } from '../types'; + +async function getPeople(): Promise { + await sleep(); + const res = await fetch('https://swapi.dev/api/people/'); + const json = await res.json(); + return json.results; +} + +export const metadata = { + title: 'Star Wars People', +}; + +export default async function Page() { + const people = await getPeople(); + + return ( +
    +

    Star Wars People

    +
      + {people.map((person) => ( +
    • + + {person.name} + +
    • + ))} +
    +
    + ); +} diff --git a/app/star-wars/types.tsx b/app/star-wars/types.tsx new file mode 100644 index 0000000..8fa55e5 --- /dev/null +++ b/app/star-wars/types.tsx @@ -0,0 +1,18 @@ +export type Person = { + name: string; + height: string; + mass: string; + hair_color: string; + skin_color: string; + eye_color: string; + birth_year: string; + gender: string; + homeworld: string; + films: string[]; + species: string[]; + vehicles: string[]; + starships: string[]; + created: string; + edited: string; + url: string; +}; diff --git a/util/sleep.tsx b/util/sleep.tsx new file mode 100644 index 0000000..c9c34b0 --- /dev/null +++ b/util/sleep.tsx @@ -0,0 +1,5 @@ +export default function sleep(ms = 2000) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +}