summaryrefslogtreecommitdiff
path: root/app/routes/band-auto-register.tsx
blob: 227908de478be60acb3687794253e93b1d8dbb2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { Form, Link, redirect, useLoaderData, useNavigation } from "react-router";
import type { ActionFunctionArgs } from "react-router";
import { createParseJob, getIpAddress, listRecentParseJobs } from "~/lib/db.server";

export function loader() {
  return { jobs: listRecentParseJobs(10) };
}

export async function action({ request }: ActionFunctionArgs) {
  const fd = await request.formData();
  const liveText = (fd.get("liveText") as string | null)?.trim() ?? "";
  if (!liveText) return { error: "テキストを入力してください" };
  const job = createParseJob(liveText);
  void getIpAddress(request); // unused but kept for symmetry
  return redirect(`/bands/auto-register/jobs/${job.id}`);
}

const STATUS_LABEL: Record<string, string> = {
  pending:    "待機中",
  processing: "解析中",
  done:       "完了",
  error:      "エラー",
};

const STATUS_COLOR: Record<string, string> = {
  pending:    "#6b7280",
  processing: "#fbbf24",
  done:       "#34d399",
  error:      "#f87171",
};

export default function BandAutoRegister() {
  const { jobs } = useLoaderData<typeof loader>();
  const nav = useNavigation();
  const busy = nav.state !== "idle";

  return (
    <main>
      <div className="page-header">
        <Link to="/bands" className="back">←</Link>
        <h1>ライブ情報から自動登録</h1>
      </div>

      <Form method="post">
        <div>
          <label>ライブ情報テキスト <span className="req">*</span></label>
          <textarea
            name="liveText"
            rows={10}
            placeholder={"出演バンド・アーティストの情報をペーストしてください。\n\n例:\n2024.08.10 @ 渋谷CLUB QUATTRO\nopen 17:30 / start 18:00\n\nband1 / Band Two / バンド三"}
          />
        </div>
        <div className="actions">
          <button type="submit" disabled={busy}>
            {busy ? "送信中..." : "キューに追加する"}
          </button>
        </div>
      </Form>

      {jobs.length > 0 && (
        <section style={{ marginTop: "2rem" }}>
          <h2>最近のジョブ</h2>
          <div className="job-list">
            {jobs.map((job) => (
              <Link
                key={job.id}
                to={`/bands/auto-register/jobs/${job.id}`}
                className="job-row"
              >
                <span
                  className="job-status"
                  style={{ color: STATUS_COLOR[job.status] ?? "#6b7280" }}
                >
                  {STATUS_LABEL[job.status] ?? job.status}
                </span>
                <span className="job-preview">
                  {job.input_text.slice(0, 60).replace(/\n/g, " ")}
                  {job.input_text.length > 60 ? "…" : ""}
                </span>
                <span className="job-time">{job.created_at.slice(0, 16).replace("T", " ")}</span>
              </Link>
            ))}
          </div>
        </section>
      )}
    </main>
  );
}