summaryrefslogtreecommitdiff
path: root/app/routes/api-bands.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'app/routes/api-bands.tsx')
-rw-r--r--app/routes/api-bands.tsx51
1 files changed, 51 insertions, 0 deletions
diff --git a/app/routes/api-bands.tsx b/app/routes/api-bands.tsx
new file mode 100644
index 0000000..64a9269
--- /dev/null
+++ b/app/routes/api-bands.tsx
@@ -0,0 +1,51 @@
+import type { ActionFunctionArgs } from "react-router";
+import { createBand, getIpAddress, listBands, toSlug } from "~/lib/db.server";
+
+export function loader() {
+ return Response.json(listBands());
+}
+
+export async function action({ request }: ActionFunctionArgs) {
+ if (request.method !== "POST") {
+ return Response.json({ error: "Method not allowed" }, { status: 405 });
+ }
+
+ let body: Record<string, unknown>;
+ try {
+ body = await request.json();
+ } catch {
+ return Response.json({ error: "Invalid JSON body" }, { status: 400 });
+ }
+
+ const name = (body.name as string | undefined)?.trim();
+ if (!name) return Response.json({ error: "name is required" }, { status: 400 });
+
+ const slug = (body.slug as string | undefined)?.trim() || toSlug(name);
+ if (!slug) return Response.json({ error: "could not derive slug from name" }, { status: 400 });
+
+ const id = crypto.randomUUID();
+ try {
+ const band = createBand({
+ id,
+ slug,
+ name,
+ area: (body.area as string) || null,
+ description: (body.description as string) || null,
+ status: (body.status as string) || "active",
+ links: (body.links as { label: string; url: string }[]) || [],
+ artists: (body.artists as { id: string; role: string | null }[]) || [],
+ message: (body.message as string) || "API import",
+ ip_address: getIpAddress(request),
+ });
+ return Response.json(band, { status: 201 });
+ } catch (e) {
+ if (e instanceof Error && e.message.includes("UNIQUE constraint failed: bands.slug")) {
+ return Response.json({ error: "slug already in use" }, { status: 409 });
+ }
+ throw e;
+ }
+}
+
+export default function () {
+ return null;
+}