diff options
Diffstat (limited to 'app/routes/band-edit.tsx')
| -rw-r--r-- | app/routes/band-edit.tsx | 112 |
1 files changed, 39 insertions, 73 deletions
diff --git a/app/routes/band-edit.tsx b/app/routes/band-edit.tsx index 0a98bd6..2e29277 100644 --- a/app/routes/band-edit.tsx +++ b/app/routes/band-edit.tsx @@ -97,13 +97,13 @@ export default function BandEdit() { } return ( - <main className="max-w-3xl mx-auto px-4 py-8"> - <div className="flex items-center gap-3 mb-6"> - <Link to={`/bands/of/${band.id}`} className="text-gray-400 hover:text-gray-200 transition-colors">←</Link> - <h1 className="text-xl font-semibold">Edit Band</h1> + <main> + <div className="page-header"> + <Link to={`/bands/of/${band.id}`} className="back">←</Link> + <h1>Edit Band</h1> </div> - <Form method="post" className="space-y-5"> + <Form method="post"> <input type="hidden" name="links" value={JSON.stringify(links)} /> <input type="hidden" @@ -112,47 +112,34 @@ export default function BandEdit() { /> <div> - <label className="block text-sm font-medium text-gray-300 mb-1"> - バンド名 <span className="text-red-400">*</span> - </label> + <label>バンド名 <span className="req">*</span></label> <input name="name" value={name} onChange={(e) => { setName(e.target.value); if (!slugManual) setSlug(toSlug(e.target.value)); }} - className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-100 focus:outline-none focus:border-blue-500" /> - {errors.name && <p className="text-red-400 text-sm mt-1">{errors.name}</p>} + {errors.name && <p className="error">{errors.name}</p>} </div> <div> - <label className="block text-sm font-medium text-gray-300 mb-1"> - Slug <span className="text-red-400">*</span> - </label> + <label>Slug <span className="req">*</span></label> <input name="slug" value={slug} onChange={(e) => { setSlugManual(true); setSlug(e.target.value); }} - className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-100 focus:outline-none focus:border-blue-500 font-mono text-sm" + className="mono" /> - {errors.slug && <p className="text-red-400 text-sm mt-1">{errors.slug}</p>} + {errors.slug && <p className="error">{errors.slug}</p>} </div> <div> - <label className="block text-sm font-medium text-gray-300 mb-1">活動拠点</label> - <input - name="area" - defaultValue={band.area ?? ""} - className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-100 focus:outline-none focus:border-blue-500" - /> + <label>活動拠点</label> + <input name="area" defaultValue={band.area ?? ""} /> </div> <div> - <label className="block text-sm font-medium text-gray-300 mb-1">ステータス</label> - <select - name="status" - defaultValue={band.status} - className="bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-100 focus:outline-none focus:border-blue-500" - > + <label>ステータス</label> + <select name="status" defaultValue={band.status}> <option value="active">活動中</option> <option value="hiatus">活動休止</option> <option value="disbanded">解散</option> @@ -160,24 +147,18 @@ export default function BandEdit() { </div> <div> - <label className="block text-sm font-medium text-gray-300 mb-1">説明</label> - <textarea - name="description" - rows={3} - defaultValue={band.description ?? ""} - className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-100 focus:outline-none focus:border-blue-500 resize-none" - /> + <label>説明</label> + <textarea name="description" rows={3} defaultValue={band.description ?? ""} /> </div> <div> - <label className="block text-sm font-medium text-gray-300 mb-2">リンク</label> - <div className="space-y-2"> + <label>リンク</label> + <div className="links-form"> {links.map((link, i) => ( - <div key={i} className="flex gap-2"> + <div key={i} className="link-row"> <select value={link.label} onChange={(e) => setLinks(links.map((l, idx) => idx === i ? { ...l, label: e.target.value } : l))} - 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> @@ -185,73 +166,65 @@ export default function BandEdit() { value={link.url} onChange={(e) => setLinks(links.map((l, idx) => idx === i ? { ...l, url: e.target.value } : l))} placeholder="https://..." - 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" /> - <button type="button" onClick={() => setLinks(links.filter((_, idx) => idx !== i))} className="text-gray-500 hover:text-red-400 px-2 transition-colors">×</button> + <button type="button" className="btn-icon" onClick={() => setLinks(links.filter((_, idx) => idx !== i))}>×</button> </div> ))} </div> <button type="button" + className="btn-text" onClick={() => setLinks([...links, { label: LINK_TYPES[0].value, url: "" }])} - className="mt-2 text-blue-400 hover:text-blue-300 text-sm transition-colors" > + リンクを追加 </button> </div> <div> - <label className="block text-sm font-medium text-gray-300 mb-2">メンバー</label> + <label>メンバー</label> {picked.length > 0 && ( - <div className="space-y-2 mb-3"> + <div className="members-form"> {picked.map((p) => { const pend = pending[p.id] ?? DEFAULT_PENDING; return ( - <div key={p.id} className="bg-gray-900 rounded-lg p-3"> - <div className="flex items-center justify-between mb-2"> - <span className="text-gray-200 text-sm font-medium">{p.name}</span> + <div key={p.id} className="member-card"> + <div className="card-header"> + <span className="card-name">{p.name}</span> <button type="button" + className="btn-icon" onClick={() => setPicked(picked.filter((a) => a.id !== p.id))} - className="text-gray-500 hover:text-red-400 text-xs transition-colors" > 削除 </button> </div> {p.roles.length > 0 && ( - <div className="flex flex-wrap gap-1.5 mb-2"> + <div className="badges"> {p.roles.map((r, ri) => ( - <span key={ri} className="inline-flex items-center gap-1 bg-gray-800 text-gray-300 text-xs px-2 py-0.5 rounded"> + <span key={ri} className="badge"> {r} - <button type="button" onClick={() => removeRole(p.id, ri)} className="text-gray-500 hover:text-red-400 leading-none">×</button> + <button type="button" onClick={() => removeRole(p.id, ri)}>×</button> </span> ))} </div> )} - <div className="flex gap-2 items-center"> + <div className="role-row"> <select value={pend.type} onChange={(e) => setPending({ ...pending, [p.id]: { ...pend, type: e.target.value } })} - className="bg-gray-800 border border-gray-700 rounded px-2 py-1.5 text-gray-300 text-sm focus:outline-none focus:border-blue-500" > {ARTIST_ROLES.map((r) => <option key={r} value={r}>{r}</option>)} <option value="other">その他...</option> </select> {pend.type === "other" && ( <input + className="custom-input" value={pend.custom} onChange={(e) => setPending({ ...pending, [p.id]: { ...pend, custom: e.target.value } })} placeholder="ロール名" - className="bg-gray-800 border border-gray-700 rounded px-2 py-1.5 text-gray-300 text-sm focus:outline-none focus:border-blue-500 w-32" /> )} - <button - type="button" - onClick={() => addRole(p.id)} - className="text-blue-400 hover:text-blue-300 text-sm transition-colors" - > - + 追加 - </button> + <button type="button" className="btn-text" onClick={() => addRole(p.id)}>+ 追加</button> </div> </div> ); @@ -269,7 +242,6 @@ export default function BandEdit() { } }} defaultValue="" - className="bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-400 focus:outline-none focus:border-blue-500 text-sm" > <option value="">+ アーティストを追加...</option> {available.map((a) => <option key={a.id} value={a.id}>{a.name}</option>)} @@ -278,20 +250,14 @@ export default function BandEdit() { </div> <div> - <label className="block text-sm font-medium text-gray-300 mb-1"> - 更新メッセージ <span className="text-red-400">*</span> - </label> - <input - name="message" - placeholder="例: メンバー追加" - className="w-full bg-gray-800 border border-gray-700 rounded px-3 py-2 text-gray-100 focus:outline-none focus:border-blue-500" - /> - {errors.message && <p className="text-red-400 text-sm mt-1">{errors.message}</p>} + <label>更新メッセージ <span className="req">*</span></label> + <input name="message" placeholder="例: メンバー追加" /> + {errors.message && <p className="error">{errors.message}</p>} </div> - <div className="flex gap-3 pt-2"> - <button type="submit" className="bg-blue-600 hover:bg-blue-500 text-white px-4 py-2 rounded font-medium transition-colors">保存</button> - <Link to={`/bands/of/${band.id}`} className="bg-gray-800 hover:bg-gray-700 text-gray-300 px-4 py-2 rounded transition-colors">キャンセル</Link> + <div className="actions"> + <button type="submit">保存</button> + <Link to={`/bands/of/${band.id}`} className="btn">キャンセル</Link> </div> </Form> </main> |
