- care reminders now fire with plant-specific body ("Time to water Pothos")
via title/body columns on the reminders table (migration 0016)
- bi-directional task sync: checking off a garden-linked task list item
creates a care log; logging care from garden marks the linked task done
(list_items.metadata stores gardenPlantId + gardenCareType linkage)
- upload error response no longer leaks debug detail; error message
corrected from "5 MB" to "100 MB"
57 lines
1.8 KiB
TypeScript
57 lines
1.8 KiB
TypeScript
import {
|
|
index,
|
|
integer,
|
|
jsonb,
|
|
pgTable,
|
|
text,
|
|
timestamp,
|
|
uuid,
|
|
boolean,
|
|
} from "drizzle-orm/pg-core";
|
|
import { households, users } from "../_core/schema";
|
|
|
|
export const lists = pgTable(
|
|
"lists",
|
|
{
|
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
householdId: uuid("household_id")
|
|
.notNull()
|
|
.references(() => households.id, { onDelete: "cascade" }),
|
|
type: text("type").notNull(),
|
|
name: text("name").notNull(),
|
|
archived: boolean("archived").notNull().default(false),
|
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
},
|
|
(t) => [
|
|
index("lists_household_type_idx").on(t.householdId, t.type),
|
|
index("lists_household_archived_idx").on(t.householdId, t.archived),
|
|
],
|
|
);
|
|
|
|
export const listItems = pgTable(
|
|
"list_items",
|
|
{
|
|
id: uuid("id").primaryKey().defaultRandom(),
|
|
listId: uuid("list_id")
|
|
.notNull()
|
|
.references(() => lists.id, { onDelete: "cascade" }),
|
|
text: text("text").notNull(),
|
|
done: boolean("done").notNull().default(false),
|
|
qty: text("qty"),
|
|
notes: text("notes"),
|
|
dueAt: timestamp("due_at", { withTimezone: true }),
|
|
assigneeId: uuid("assignee_id").references(() => users.id, { onDelete: "set null" }),
|
|
position: integer("position").notNull().default(0),
|
|
metadata: jsonb("metadata").$type<Record<string, unknown>>(),
|
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
},
|
|
(t) => [
|
|
index("list_items_list_position_idx").on(t.listId, t.position),
|
|
index("list_items_assignee_idx").on(t.assigneeId),
|
|
],
|
|
);
|
|
|
|
export type List = typeof lists.$inferSelect;
|
|
export type ListItem = typeof listItems.$inferSelect;
|