feat(10-01): wire pros/cons through client hooks, form, and card indicator
- CandidateResponse: add pros/cons string|null fields - CandidateForm: add pros/cons to FormData, INITIAL_FORM, pre-fill, payload - CandidateForm: add Pros/Cons textarea inputs (after Notes, before Product Link) - CandidateCard: add pros/cons props, render purple +/- Notes badge when present - Thread detail route: pass pros/cons props to CandidateCard
This commit is contained in:
@@ -19,6 +19,8 @@ interface FormData {
|
||||
notes: string;
|
||||
productUrl: string;
|
||||
imageFilename: string | null;
|
||||
pros: string;
|
||||
cons: string;
|
||||
}
|
||||
|
||||
const INITIAL_FORM: FormData = {
|
||||
@@ -29,6 +31,8 @@ const INITIAL_FORM: FormData = {
|
||||
notes: "",
|
||||
productUrl: "",
|
||||
imageFilename: null,
|
||||
pros: "",
|
||||
cons: "",
|
||||
};
|
||||
|
||||
export function CandidateForm({
|
||||
@@ -61,6 +65,8 @@ export function CandidateForm({
|
||||
notes: candidate.notes ?? "",
|
||||
productUrl: candidate.productUrl ?? "",
|
||||
imageFilename: candidate.imageFilename,
|
||||
pros: candidate.pros ?? "",
|
||||
cons: candidate.cons ?? "",
|
||||
});
|
||||
}
|
||||
} else if (mode === "add") {
|
||||
@@ -110,6 +116,8 @@ export function CandidateForm({
|
||||
notes: form.notes.trim() || undefined,
|
||||
productUrl: form.productUrl.trim() || undefined,
|
||||
imageFilename: form.imageFilename ?? undefined,
|
||||
pros: form.pros.trim() || undefined,
|
||||
cons: form.cons.trim() || undefined,
|
||||
};
|
||||
|
||||
if (mode === "add") {
|
||||
@@ -239,6 +247,42 @@ export function CandidateForm({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Pros */}
|
||||
<div>
|
||||
<label
|
||||
htmlFor="candidate-pros"
|
||||
className="block text-sm font-medium text-gray-700 mb-1"
|
||||
>
|
||||
Pros
|
||||
</label>
|
||||
<textarea
|
||||
id="candidate-pros"
|
||||
value={form.pros}
|
||||
onChange={(e) => setForm((f) => ({ ...f, pros: e.target.value }))}
|
||||
rows={3}
|
||||
className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent resize-none"
|
||||
placeholder="One pro per line..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Cons */}
|
||||
<div>
|
||||
<label
|
||||
htmlFor="candidate-cons"
|
||||
className="block text-sm font-medium text-gray-700 mb-1"
|
||||
>
|
||||
Cons
|
||||
</label>
|
||||
<textarea
|
||||
id="candidate-cons"
|
||||
value={form.cons}
|
||||
onChange={(e) => setForm((f) => ({ ...f, cons: e.target.value }))}
|
||||
rows={3}
|
||||
className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent resize-none"
|
||||
placeholder="One con per line..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Product Link */}
|
||||
<div>
|
||||
<label
|
||||
|
||||
Reference in New Issue
Block a user