From b8d24d292d99c8da285092ce923b5e2b546d8f45 Mon Sep 17 00:00:00 2001 From: yyamashita Date: Sat, 9 May 2026 00:27:19 +0900 Subject: Implement band/artist management with version history Full CRUD for bands and artists: UUID + slug URLs, dynamic link editor, band-artist associations with roles, per-edit revision snapshots (message + IP). Add README and CLAUDE.md. Co-Authored-By: Claude Sonnet 4.6 --- app/routes/artist-by-uuid.tsx | 100 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 app/routes/artist-by-uuid.tsx (limited to 'app/routes/artist-by-uuid.tsx') diff --git a/app/routes/artist-by-uuid.tsx b/app/routes/artist-by-uuid.tsx new file mode 100644 index 0000000..9b8a4b1 --- /dev/null +++ b/app/routes/artist-by-uuid.tsx @@ -0,0 +1,100 @@ +import { data, Link, useLoaderData } from "react-router"; +import type { LoaderFunctionArgs } from "react-router"; +import { getArtistBands, getArtistById, getArtistLinks, getArtistRevisions } from "~/lib/db.server"; + +export async function loader({ params }: LoaderFunctionArgs) { + const artist = getArtistById(params.uuid!); + if (!artist) throw data("Not found", { status: 404 }); + const links = getArtistLinks(artist.id); + const bands = getArtistBands(artist.id); + const revisions = getArtistRevisions(artist.id); + return { artist, links, bands, latest: revisions[0] ?? null }; +} + +export default function ArtistDetail() { + const { artist, links, bands, latest } = useLoaderData(); + return ( +
+
+

{artist.name}

+
+ + 履歴 + + + 編集 + +
+
+ + {bands.length > 0 && ( +
+

+ バンド +

+
    + {bands.map((b) => ( +
  • + + {b.band_name} + + {b.role && ( + {b.role} + )} +
  • + ))} +
+
+ )} + + {links.length > 0 && ( +
+

+ リンク +

+ +
+ )} + +
+
+

/artists/of/{artist.id}

+

+ + /artists/named/{artist.slug} + +

+ {latest && ( +

+ 最終更新: {latest.created_at} — {latest.message} +

+ )} +
+
+ ); +} -- cgit v1.2.3