1import { useEffect, useState } from "react";
2import { NoteForm } from "./components/NoteForm.tsx";
3import { NoteList } from "./components/NoteList.tsx";
4import { createNote, listNotes, type Note } from "./lib/api.ts";
5
6export 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};