feat: granular per-category push notification settings
New Settings → Notifications section with a toggle per category (follow, comment, reply, reaction, rating, mention, leftover-expiring, shared shopping list) — previously it was all-or-nothing (browser permission only). userNotificationPrefs (one row per user, defaults all-on so existing users see no behavior change until they opt out of something). Gated the push send in the three places that dispatch one: lib/notifications.ts (the 6 in-app notification types), the leftover-expiry cron, and shopping-list-notify — in-app notification-center entries and email are unaffected, this only gates the push itself, matching the literal ask. Verified locally: GET/PUT round-trips correctly, disabling a category and confirming the settings page renders all 8 toggles.
This commit is contained in:
@@ -145,10 +145,28 @@ export const userNutritionGoals = pgTable("user_nutrition_goals", {
|
||||
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
||||
});
|
||||
|
||||
export const userNotificationPrefs = pgTable("user_notification_prefs", {
|
||||
id: text("id").primaryKey(),
|
||||
userId: text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }).unique(),
|
||||
follow: boolean("follow").notNull().default(true),
|
||||
comment: boolean("comment").notNull().default(true),
|
||||
reply: boolean("reply").notNull().default(true),
|
||||
reaction: boolean("reaction").notNull().default(true),
|
||||
rating: boolean("rating").notNull().default(true),
|
||||
mention: boolean("mention").notNull().default(true),
|
||||
leftoverExpiring: boolean("leftover_expiring").notNull().default(true),
|
||||
shoppingList: boolean("shopping_list").notNull().default(true),
|
||||
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
||||
});
|
||||
|
||||
export const pushSubscriptionsRelations = relations(pushSubscriptions, ({ one }) => ({
|
||||
user: one(users, { fields: [pushSubscriptions.userId], references: [users.id] }),
|
||||
}));
|
||||
|
||||
export const userNotificationPrefsRelations = relations(userNotificationPrefs, ({ one }) => ({
|
||||
user: one(users, { fields: [userNotificationPrefs.userId], references: [users.id] }),
|
||||
}));
|
||||
|
||||
export const userNutritionGoalsRelations = relations(userNutritionGoals, ({ one }) => ({
|
||||
user: one(users, { fields: [userNutritionGoals.userId], references: [users.id] }),
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user