1import { Inject, Body, Controller, Get, Param, Patch, Post, Query, Req } from "@nestjs/common";
2import type { Request } from "express";
3import { z } from "zod";
4import { NOTIFICATION_PREF_MODES, NOTIFICATION_TYPES } from "@factory/shared";
5import { NotificationsService } from "./notifications.service.js";
6import { ZodValidate } from "../../common/pipes/zod-validation.pipe.js";
7import { requireUser } from "../../common/types.js";
8
9const ListQuery = z.object({
10 cursor: z.string().optional(),
11 read: z.enum(["true", "false"]).optional(),
12 limit: z.string().optional()
13});
14
15
16const PrefsDto = z
17 .record(z.enum(NOTIFICATION_TYPES), z.enum(NOTIFICATION_PREF_MODES))
18 .refine((v) => Object.keys(v).length > 0, { message: "Provide at least one preference." });
19
20@Controller("notifications")
21export class NotificationsController {
22 constructor(@Inject(NotificationsService) private readonly notifications: NotificationsService) {}
23
24 @Get()
25 list(
26 @Query(ZodValidate(ListQuery)) query: z.infer<typeof ListQuery>,
27 @Req() req: Request
28 ) {
29 return this.notifications.list(requireUser(req), query);
30 }
31
32 @Get("unread-count")
33 unreadCount(@Req() req: Request) {
34 return this.notifications.unreadCount(requireUser(req));
35 }
36
37 @Post("read-all")
38 readAll(@Req() req: Request) {
39 return this.notifications.markAllRead(requireUser(req));
40 }
41
42 @Post(":id/read")
43 read(@Param("id") id: string, @Req() req: Request) {
44 return this.notifications.markRead(id, requireUser(req));
45 }
46
47
48
49 @Get("preferences")
50 getPreferences(@Req() req: Request) {
51 return this.notifications.getPrefs(requireUser(req));
52 }
53
54 @Patch("preferences")
55 updatePreferences(
56 @Body(ZodValidate(PrefsDto)) body: z.infer<typeof PrefsDto>,
57 @Req() req: Request
58 ) {
59 return this.notifications.updatePrefs(requireUser(req), body);
60 }
61}
62