From b8548d029760ecfa59cafedd23899a91e6120b5f Mon Sep 17 00:00:00 2001
From: yyamashita <yyamashita@mosquit.one>
Date: Sat, 9 May 2026 00:51:08 +0900
Subject: Add predefined link types and artist roles
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- app/lib/constants.ts: LINK_TYPES (12種) and ARTIST_ROLES (13種)
- Band link forms: label input → type select (公式サイト, X, Instagram, ...)
- Band member forms: role text → role select (Vocal, Guitar, Bass, ...)
- Band detail: resolve link type key to display label via LINK_TYPE_LABEL

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
 app/routes/band-new.tsx | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

(limited to 'app/routes/band-new.tsx')

diff --git a/app/routes/band-new.tsx b/app/routes/band-new.tsx
index b4d49e2..86222a3 100644
--- a/app/routes/band-new.tsx
+++ b/app/routes/band-new.tsx
@@ -2,6 +2,7 @@ import { useState } from "react";
 import { Form, Link, redirect, useActionData, useLoaderData } from "react-router";
 import type { ActionFunctionArgs } from "react-router";
 import { createBand, getIpAddress, listArtists } from "~/lib/db.server";
+import { ARTIST_ROLES, LINK_TYPES } from "~/lib/constants";
 
 export function loader() {
   return { artists: listArtists() };
@@ -53,6 +54,7 @@ export default function BandNew() {
   const [slug, setSlug] = useState("");
   const [slugManual, setSlugManual] = useState(false);
   const [links, setLinks] = useState<{ label: string; url: string }[]>([]);
+  const DEFAULT_LINK_TYPE = LINK_TYPES[0].value;
   const [picked, setPicked] = useState<{ id: string; name: string; role: string }[]>([]);
 
   const available = artists.filter((a) => !picked.some((p) => p.id === a.id));
@@ -136,12 +138,15 @@ export default function BandNew() {
           <div className="space-y-2">
             {links.map((link, i) => (
               <div key={i} className="flex gap-2">
-                <input
+                <select
                   value={link.label}
                   onChange={(e) => setLinks(links.map((l, idx) => idx === i ? { ...l, label: e.target.value } : l))}
-                  placeholder="ラベル (例: X)"
-                  className="w-28 bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-100 focus:outline-none focus:border-blue-500 text-sm"
-                />
+                  className="w-36 bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-100 focus:outline-none focus:border-blue-500 text-sm"
+                >
+                  {LINK_TYPES.map((t) => (
+                    <option key={t.value} value={t.value}>{t.label}</option>
+                  ))}
+                </select>
                 <input
                   value={link.url}
                   onChange={(e) => setLinks(links.map((l, idx) => idx === i ? { ...l, url: e.target.value } : l))}
@@ -160,7 +165,7 @@ export default function BandNew() {
           </div>
           <button
             type="button"
-            onClick={() => setLinks([...links, { label: "", url: "" }])}
+            onClick={() => setLinks([...links, { label: DEFAULT_LINK_TYPE, url: "" }])}
             className="mt-2 text-blue-400 hover:text-blue-300 text-sm transition-colors"
           >
             + リンクを追加
@@ -173,12 +178,16 @@ export default function BandNew() {
             {picked.map((p, i) => (
               <div key={p.id} className="flex gap-2 items-center">
                 <span className="text-gray-200 text-sm w-32 truncate">{p.name}</span>
-                <input
+                <select
                   value={p.role}
                   onChange={(e) => setPicked(picked.map((a, idx) => idx === i ? { ...a, role: e.target.value } : a))}
-                  placeholder="パート (例: Guitar)"
                   className="flex-1 bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-100 focus:outline-none focus:border-blue-500 text-sm"
-                />
+                >
+                  <option value="">— パートを選択 —</option>
+                  {ARTIST_ROLES.map((r) => (
+                    <option key={r} value={r}>{r}</option>
+                  ))}
+                </select>
                 <button
                   type="button"
                   onClick={() => setPicked(picked.filter((_, idx) => idx !== i))}
-- 
cgit v1.2.3

