| 1 | import { useEffect, useState } from "react"; |
| 2 | import { NoteForm } from "./components/NoteForm.tsx"; |
| 3 | import { NoteList } from "./components/NoteList.tsx"; |
| 4 | import { createNote, listNotes, type Note } from "./lib/api.ts"; |
| 5 | |
| 6 | export const App = ({ platform }: { platform: string }) => { |
| 7 | const [notes, setNotes] = useState<Note[]>([]); |
| 8 | const [error, setError] = useState<string | undefined>(); |
| 9 | |
| 10 | const refresh = async () => { |
| 11 | const next = await listNotes(); |
| 12 | setNotes(next); |
| 13 | }; |
| 14 | |
| 15 | useEffect(() => { |
| 16 | void refresh().catch((cause: unknown) => { |
| 17 | setError(cause instanceof Error ? cause.message : String(cause)); |
| 18 | }); |
| 19 | }, []); |
| 20 | |
| 21 | return ( |
| 22 | <main className="mx-auto flex min-h-screen max-w-xl flex-col gap-8 px-6 py-16"> |
| 23 | <header className="flex flex-col gap-2"> |
| 24 | <p className="text-sm font-medium uppercase tracking-[0.16em] text-sky-400"> |
| 25 | alchemy + {platform} |
| 26 | </p> |
| 27 | <h1 className="text-4xl font-semibold tracking-tight">Notes</h1> |
| 28 | <p className="text-slate-400"> |
| 29 | A Tailwind React app that posts to an Effect API backed by Postgres. |
| 30 | </p> |
| 31 | </header> |
| 32 | {error !== undefined ? ( |
| 33 | <p className="rounded-xl border border-rose-900 bg-rose-950/60 px-4 py-3 text-rose-200"> |
| 34 | {error} |
| 35 | </p> |
| 36 | ) : undefined} |
| 37 | <NoteForm |
| 38 | onCreate={async (body) => { |
| 39 | setError(undefined); |
| 40 | const note = await createNote(body); |
| 41 | setNotes((current) => [note, ...current]); |
| 42 | }} |
| 43 | /> |
| 44 | <NoteList notes={notes} /> |
| 45 | </main> |
| 46 | ); |
| 47 | }; |