File size: 3,715 Bytes
b834652
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import React, { useState } from "react";
import Field from "./Field";
import { generateEmail, lintText, GenerateReq } from "@/lib/api";

type Props = {
  onResult: (r: any) => void;
};

export default function GeneratorForm({ onResult }: Props) {
  const [loading, setLoading] = useState(false);
  const [form, setForm] = useState<GenerateReq>({
    language: "ja",
    industry: "ITサービス",
    target_company: "株式会社○○",
    target_persona: "情報システム部の部長",
    pain_points: "SaaS乱立によるコスト・運用負荷増大",
    value_prop: "運用統合と可視化によりTCOを30%削減",
    product_name: "Aroundabout Suite",
    cta: "15分のオンライン面談をご提案",
    tone: "フォーマルで簡潔",
    variables: { company: "株式会社○○", person: "山田様" },
    length_hint: "中",
    extra_instr: ""
  });

  const update = (k: keyof GenerateReq) => (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) =>
    setForm(f => ({ ...f, [k]: e.target.value }));

  async function onSubmit(e: React.FormEvent) {
    e.preventDefault();
    setLoading(true);
    try {
      const res = await generateEmail({ ...form, variables: form.variables });
      // 追加の簡易Lint
      const lint = await lintText(res.body);
      onResult({ ...res, lint });
    } catch (err) {
      onResult({ error: String(err) });
    } finally {
      setLoading(false);
    }
  }

  return (
    <form onSubmit={onSubmit} style={{ display: "grid", gap: 12 }}>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
        <Field label="言語">
          <select value={form.language} onChange={update("language")}>
            <option value="ja">日本語</option>
            <option value="en">English</option>
          </select>
        </Field>
        <Field label="トーン">
          <input value={form.tone} onChange={update("tone")} />
        </Field>
        <Field label="業界">
          <input value={form.industry} onChange={update("industry")} />
        </Field>
        <Field label="相手企業">
          <input value={form.target_company} onChange={update("target_company")} />
        </Field>
        <Field label="担当者ペルソナ">
          <input value={form.target_persona} onChange={update("target_persona")} />
        </Field>
        <Field label="文章ボリューム">
          <select value={form.length_hint} onChange={update("length_hint")}>
            <option></option><option></option><option></option>
          </select>
        </Field>
      </div>

      <Field label="相手の課題">
        <textarea value={form.pain_points} onChange={update("pain_points")} rows={3} />
      </Field>
      <Field label="提供価値(成果/差別化)">
        <textarea value={form.value_prop} onChange={update("value_prop")} rows={3} />
      </Field>
      <Field label="製品/サービス名">
        <input value={form.product_name} onChange={update("product_name")} />
      </Field>
      <Field label="CTA(次アクション)">
        <input value={form.cta} onChange={update("cta")} />
      </Field>
      <Field label="追加指示(禁止表現など)">
        <input value={form.extra_instr ?? ""} onChange={update("extra_instr")} />
      </Field>

      <button
        type="submit"
        disabled={loading}
        style={{
          padding: "10px 14px",
          borderRadius: 12,
          border: "1px solid #ddd",
          cursor: "pointer",
          background: loading ? "#f3f3f3" : "white"
        }}
      >
        {loading ? "生成中..." : "生成する"}
      </button>
    </form>
  );
}