diff options
Diffstat (limited to 'app/routes/artist-by-uuid.tsx')
| -rw-r--r-- | app/routes/artist-by-uuid.tsx | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/app/routes/artist-by-uuid.tsx b/app/routes/artist-by-uuid.tsx index 6eb06a7..a65525b 100644 --- a/app/routes/artist-by-uuid.tsx +++ b/app/routes/artist-by-uuid.tsx @@ -1,18 +1,29 @@ import { data, Link, useLoaderData } from "react-router"; import type { LoaderFunctionArgs } from "react-router"; -import { getArtistBands, getArtistById, getArtistLinks, getArtistRevisions } from "~/lib/db.server"; +import { getArtistById, getArtistLinks, getArtistMembers, getArtistRevisions, type ArtistMemberRow } 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 memberships = getArtistMembers(artist.id); const revisions = getArtistRevisions(artist.id); - return { artist, links, bands, latest: revisions[0] ?? null }; + return { artist, links, memberships, latest: revisions[0] ?? null }; +} + +function periodLabel(m: ArtistMemberRow): string | null { + if (!m.since && !m.until) return null; + const from = m.since || "?"; + const to = m.until || "現在"; + return `${from} 〜 ${to}`; } export default function ArtistDetail() { - const { artist, links, bands, latest } = useLoaderData<typeof loader>(); + const { artist, links, memberships, latest } = useLoaderData<typeof loader>(); + + // group by band_id + const bandIds = [...new Set(memberships.map((m) => m.band_id))]; + return ( <main> <div className="detail-header"> @@ -23,16 +34,36 @@ export default function ArtistDetail() { </div> </div> - {bands.length > 0 && ( + {bandIds.length > 0 && ( <section> <h2>バンド</h2> <ul className="member-list"> - {bands.map((b) => ( - <li key={b.band_id}> - <Link to={`/bands/of/${b.band_id}`}>{b.band_name}</Link> - {b.role && <span className="muted">{b.role}</span>} - </li> - ))} + {bandIds.map((bandId) => { + const group = memberships.filter((m) => m.band_id === bandId); + const first = group[0]; + return ( + <li key={bandId}> + <div className="member-main"> + <Link to={`/bands/of/${bandId}`}>{first.band_name}</Link> + {first.role && <span className="muted">{first.role}</span>} + </div> + {group.some((m) => m.since || m.until || m.note) && ( + <ul className="period-list"> + {group.map((m) => { + const label = periodLabel(m); + if (!label && !m.note) return null; + return ( + <li key={m.id} className="period-item"> + {label && <span className="period-range">{label}</span>} + {m.note && <span className="period-note">{m.note}</span>} + </li> + ); + })} + </ul> + )} + </li> + ); + })} </ul> </section> )} |
