import { Inject, Body, Controller, Get, Param, Patch, Post, Query, Req } from "@nestjs/common"; import type { Request } from "express"; import { z } from "zod"; import { NOTIFICATION_PREF_MODES, NOTIFICATION_TYPES } from "@factory/shared"; import { NotificationsService } from "./notifications.service.js"; import { ZodValidate } from "../../common/pipes/zod-validation.pipe.js"; import { requireUser } from "../../common/types.js"; const ListQuery = z.object({ cursor: z.string().optional(), read: z.enum(["true", "false"]).optional(), limit: z.string().optional() }); /** Partial map of NotificationType → pref mode (R6: only the given types change). */ const PrefsDto = z .record(z.enum(NOTIFICATION_TYPES), z.enum(NOTIFICATION_PREF_MODES)) .refine((v) => Object.keys(v).length > 0, { message: "Provide at least one preference." }); @Controller("notifications") export class NotificationsController { constructor(@Inject(NotificationsService) private readonly notifications: NotificationsService) {} @Get() list( @Query(ZodValidate(ListQuery)) query: z.infer, @Req() req: Request ) { return this.notifications.list(requireUser(req), query); } @Get("unread-count") unreadCount(@Req() req: Request) { return this.notifications.unreadCount(requireUser(req)); } @Post("read-all") readAll(@Req() req: Request) { return this.notifications.markAllRead(requireUser(req)); } @Post(":id/read") read(@Param("id") id: string, @Req() req: Request) { return this.notifications.markRead(id, requireUser(req)); } // ---------- per-type EMAIL preferences (TASK-0094 R6) ---------- @Get("preferences") getPreferences(@Req() req: Request) { return this.notifications.getPrefs(requireUser(req)); } @Patch("preferences") updatePreferences( @Body(ZodValidate(PrefsDto)) body: z.infer, @Req() req: Request ) { return this.notifications.updatePrefs(requireUser(req), body); } }