feat(08-01): add status column to threadCandidates and wire through backend
- Schema: status TEXT NOT NULL DEFAULT 'researching' on thread_candidates - Zod: candidateStatusSchema enum (researching/ordered/arrived) added to createCandidateSchema - Service: getThreadWithCandidates selects status, createCandidate sets status, updateCandidate accepts status - Client hooks: CandidateWithCategory and CandidateResponse types include status field - Migration generated and applied Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ interface CandidateResponse {
|
||||
notes: string | null;
|
||||
productUrl: string | null;
|
||||
imageFilename: string | null;
|
||||
status: "researching" | "ordered" | "arrived";
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ interface CandidateWithCategory {
|
||||
notes: string | null;
|
||||
productUrl: string | null;
|
||||
imageFilename: string | null;
|
||||
status: "researching" | "ordered" | "arrived";
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
categoryName: string;
|
||||
|
||||
@@ -58,6 +58,7 @@ export const threadCandidates = sqliteTable("thread_candidates", {
|
||||
notes: text("notes"),
|
||||
productUrl: text("product_url"),
|
||||
imageFilename: text("image_filename"),
|
||||
status: text("status").notNull().default("researching"),
|
||||
createdAt: integer("created_at", { mode: "timestamp" })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
|
||||
@@ -72,6 +72,7 @@ export function getThreadWithCandidates(db: Db = prodDb, threadId: number) {
|
||||
notes: threadCandidates.notes,
|
||||
productUrl: threadCandidates.productUrl,
|
||||
imageFilename: threadCandidates.imageFilename,
|
||||
status: threadCandidates.status,
|
||||
createdAt: threadCandidates.createdAt,
|
||||
updatedAt: threadCandidates.updatedAt,
|
||||
categoryName: categories.name,
|
||||
@@ -149,6 +150,7 @@ export function createCandidate(
|
||||
notes: data.notes ?? null,
|
||||
productUrl: data.productUrl ?? null,
|
||||
imageFilename: data.imageFilename ?? null,
|
||||
status: data.status ?? "researching",
|
||||
})
|
||||
.returning()
|
||||
.get();
|
||||
@@ -165,6 +167,7 @@ export function updateCandidate(
|
||||
notes: string;
|
||||
productUrl: string;
|
||||
imageFilename: string;
|
||||
status: "researching" | "ordered" | "arrived";
|
||||
}>,
|
||||
) {
|
||||
const existing = db
|
||||
|
||||
@@ -36,6 +36,9 @@ export const updateThreadSchema = z.object({
|
||||
categoryId: z.number().int().positive().optional(),
|
||||
});
|
||||
|
||||
// Candidate status
|
||||
export const candidateStatusSchema = z.enum(["researching", "ordered", "arrived"]);
|
||||
|
||||
// Candidate schemas (same fields as items)
|
||||
export const createCandidateSchema = z.object({
|
||||
name: z.string().min(1, "Name is required"),
|
||||
@@ -45,6 +48,7 @@ export const createCandidateSchema = z.object({
|
||||
notes: z.string().optional(),
|
||||
productUrl: z.string().url().optional().or(z.literal("")),
|
||||
imageFilename: z.string().optional(),
|
||||
status: candidateStatusSchema.optional(),
|
||||
});
|
||||
|
||||
export const updateCandidateSchema = createCandidateSchema.partial();
|
||||
|
||||
Reference in New Issue
Block a user