fix: reduce paid proposal intake friction
All checks were successful
CI and Production Smoke / smoke (push) Successful in 7s
All checks were successful
CI and Production Smoke / smoke (push) Successful in 7s
This commit is contained in:
@@ -94,8 +94,8 @@ export async function createDemandProposal(formData: FormData) {
|
||||
if (!title || title.length < 6) {
|
||||
throw new Error("請提供至少 6 個字元的需求標題。");
|
||||
}
|
||||
if (!description || description.length < 30) {
|
||||
throw new Error("請提供至少 30 個字元的需求描述,讓 AI Agent 可以判斷範圍。");
|
||||
if (!description || description.length < 12) {
|
||||
throw new Error("請提供至少 12 個字元的需求簡述,讓平台可以建立付款與 scoping 紀錄。");
|
||||
}
|
||||
if (!proposerEmail || !proposerEmail.includes("@")) {
|
||||
throw new Error("請提供有效 email,方便後續 scope review 聯繫。");
|
||||
|
||||
@@ -173,114 +173,8 @@ export default async function ProposePage({ searchParams }: { searchParams?: Sea
|
||||
<input type="hidden" name="campaign" value={campaign} />
|
||||
<input type="hidden" name="source" value={source} />
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
聯絡人
|
||||
<input
|
||||
name="proposerName"
|
||||
autoComplete="name"
|
||||
defaultValue={prefill.proposerName}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="你的姓名"
|
||||
/>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
Email
|
||||
<input
|
||||
required
|
||||
name="proposerEmail"
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
defaultValue={prefill.proposerEmail}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="name@company.com"
|
||||
/>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
公司或團隊
|
||||
<input
|
||||
name="company"
|
||||
autoComplete="organization"
|
||||
defaultValue={prefill.company}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="可留空"
|
||||
/>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
預估任務預算 USD
|
||||
<input
|
||||
required
|
||||
name="budgetUsd"
|
||||
inputMode="decimal"
|
||||
defaultValue={prefill.budgetUsd}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 grid gap-4">
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
需求標題
|
||||
<input
|
||||
required
|
||||
name="title"
|
||||
minLength={6}
|
||||
defaultValue={prefill.title}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="例如:自動整理客戶表單並生成報價草稿"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
需求描述
|
||||
<textarea
|
||||
required
|
||||
name="description"
|
||||
minLength={30}
|
||||
rows={6}
|
||||
defaultValue={prefill.description}
|
||||
className="resize-y rounded-md border border-zinc-700 bg-zinc-950 px-3 py-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="描述目前流程、需要自動化的輸入輸出、系統限制、交付期待。請不要貼密碼或私鑰。"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
希望成果
|
||||
<input
|
||||
name="desiredOutcome"
|
||||
defaultValue={prefill.desiredOutcome}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="可驗收的結果"
|
||||
/>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
技術或工具
|
||||
<input
|
||||
name="requiredStack"
|
||||
defaultValue={prefill.requiredStack}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="Next.js, Python, Zapier"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
時程
|
||||
<select
|
||||
name="urgency"
|
||||
defaultValue={prefill.urgency}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
>
|
||||
<option value="normal">一般</option>
|
||||
<option value="this_week">本週內</option>
|
||||
<option value="urgent">急件</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<fieldset className="mt-6">
|
||||
<legend className="mb-3 text-sm font-semibold text-zinc-100">提案導流方案</legend>
|
||||
<fieldset>
|
||||
<legend className="mb-3 text-sm font-semibold text-zinc-100">1. 選擇付費方案</legend>
|
||||
<div className="grid gap-2">
|
||||
{PROPOSAL_PACKAGES.map((item) => (
|
||||
<label
|
||||
@@ -308,7 +202,7 @@ export default async function ProposePage({ searchParams }: { searchParams?: Sea
|
||||
</fieldset>
|
||||
|
||||
<fieldset className="mt-6">
|
||||
<legend className="mb-3 text-sm font-semibold text-zinc-100">付款方式</legend>
|
||||
<legend className="mb-3 text-sm font-semibold text-zinc-100">2. 付款方式</legend>
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
<label className="flex cursor-pointer items-center gap-3 rounded-md border border-zinc-700 bg-zinc-950 p-4 hover:border-emerald-400">
|
||||
<input type="radio" name="paymentMethod" value="wallet" defaultChecked={walletPaymentAvailable} className="h-4 w-4 accent-emerald-400" />
|
||||
@@ -329,11 +223,118 @@ export default async function ProposePage({ searchParams }: { searchParams?: Sea
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div className="mt-6 grid gap-4">
|
||||
<div className="grid gap-4 md:grid-cols-2">
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
Email
|
||||
<input
|
||||
required
|
||||
name="proposerEmail"
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
defaultValue={prefill.proposerEmail}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="name@company.com"
|
||||
/>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
需求標題
|
||||
<input
|
||||
required
|
||||
name="title"
|
||||
minLength={6}
|
||||
defaultValue={prefill.title}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="例如:客戶表單自動報價"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
需求簡述
|
||||
<textarea
|
||||
required
|
||||
name="description"
|
||||
minLength={12}
|
||||
rows={4}
|
||||
defaultValue={prefill.description}
|
||||
className="resize-y rounded-md border border-zinc-700 bg-zinc-950 px-3 py-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="一句話描述要自動化、分析、修復或整合的工作。"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<details className="rounded-md border border-zinc-800 bg-zinc-950/70 p-4">
|
||||
<summary className="cursor-pointer text-sm font-semibold text-sky-200">補充資料</summary>
|
||||
<div className="mt-4 grid gap-4 md:grid-cols-2">
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
聯絡人
|
||||
<input
|
||||
name="proposerName"
|
||||
autoComplete="name"
|
||||
defaultValue={prefill.proposerName}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="你的姓名"
|
||||
/>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
公司或團隊
|
||||
<input
|
||||
name="company"
|
||||
autoComplete="organization"
|
||||
defaultValue={prefill.company}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="可留空"
|
||||
/>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
預估任務預算 USD
|
||||
<input
|
||||
required
|
||||
name="budgetUsd"
|
||||
inputMode="decimal"
|
||||
defaultValue={prefill.budgetUsd}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
/>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
時程
|
||||
<select
|
||||
name="urgency"
|
||||
defaultValue={prefill.urgency}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
>
|
||||
<option value="normal">一般</option>
|
||||
<option value="this_week">本週內</option>
|
||||
<option value="urgent">急件</option>
|
||||
</select>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
希望成果
|
||||
<input
|
||||
name="desiredOutcome"
|
||||
defaultValue={prefill.desiredOutcome}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="可驗收的結果"
|
||||
/>
|
||||
</label>
|
||||
<label className="grid gap-2 text-sm font-medium text-zinc-200">
|
||||
技術或工具
|
||||
<input
|
||||
name="requiredStack"
|
||||
defaultValue={prefill.requiredStack}
|
||||
className="h-11 rounded-md border border-zinc-700 bg-zinc-950 px-3 text-white outline-none focus:border-sky-400"
|
||||
placeholder="Next.js, Python, Zapier"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="mt-6 inline-flex h-12 w-full items-center justify-center gap-2 rounded-md bg-sky-400 px-5 text-sm font-semibold text-zinc-950 transition hover:bg-sky-300 md:w-auto"
|
||||
>
|
||||
送出並付款
|
||||
取得付款指示
|
||||
<ArrowRight className="h-4 w-4" />
|
||||
</button>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user