feat(preferences): setup for prefrences module which allows a user to manage dark mode, notifications, lefty mode for phone user and a lang switch (en, fr)

This commit is contained in:
Matthieu Haineault 2025-10-03 14:03:09 -04:00
parent 3984540edb
commit d8bc05f6e2
8 changed files with 150 additions and 9 deletions

View File

@ -0,0 +1,56 @@
/*
Warnings:
- You are about to drop the column `end_date_time` on the `leave_requests` table. All the data in the column will be lost.
- You are about to drop the column `start_date_time` on the `leave_requests` table. All the data in the column will be lost.
- You are about to drop the column `end_date_time` on the `leave_requests_archive` table. All the data in the column will be lost.
- You are about to drop the column `start_date_time` on the `leave_requests_archive` table. All the data in the column will be lost.
- A unique constraint covering the columns `[employee_id,leave_type,date]` on the table `leave_requests` will be added. If there are existing duplicate values, this will fail.
- A unique constraint covering the columns `[leave_request_id]` on the table `leave_requests_archive` will be added. If there are existing duplicate values, this will fail.
- Added the required column `date` to the `leave_requests` table without a default value. This is not possible if the table is not empty.
- Added the required column `date` to the `leave_requests_archive` table without a default value. This is not possible if the table is not empty.
*/
-- AlterEnum
ALTER TYPE "leave_types" ADD VALUE 'HOLIDAY';
-- AlterTable
ALTER TABLE "leave_requests" DROP COLUMN "end_date_time",
DROP COLUMN "start_date_time",
ADD COLUMN "date" DATE NOT NULL,
ADD COLUMN "payable_hours" DECIMAL(5,2),
ADD COLUMN "requested_hours" DECIMAL(5,2);
-- AlterTable
ALTER TABLE "leave_requests_archive" DROP COLUMN "end_date_time",
DROP COLUMN "start_date_time",
ADD COLUMN "date" DATE NOT NULL,
ADD COLUMN "payable_hours" DECIMAL(5,2),
ADD COLUMN "requested_hours" DECIMAL(5,2);
-- CreateTable
CREATE TABLE "preferences" (
"user_id" UUID NOT NULL,
"notifications" BOOLEAN NOT NULL DEFAULT false,
"dark_mode" BOOLEAN NOT NULL DEFAULT false,
"lang_switch" BOOLEAN NOT NULL DEFAULT false,
"lefty_mode" BOOLEAN NOT NULL DEFAULT false
);
-- CreateIndex
CREATE UNIQUE INDEX "preferences_user_id_key" ON "preferences"("user_id");
-- CreateIndex
CREATE INDEX "leave_requests_employee_id_date_idx" ON "leave_requests"("employee_id", "date");
-- CreateIndex
CREATE UNIQUE INDEX "leave_requests_employee_id_leave_type_date_key" ON "leave_requests"("employee_id", "leave_type", "date");
-- CreateIndex
CREATE INDEX "leave_requests_archive_employee_id_date_idx" ON "leave_requests_archive"("employee_id", "date");
-- CreateIndex
CREATE UNIQUE INDEX "leave_requests_archive_leave_request_id_key" ON "leave_requests_archive"("leave_request_id");
-- AddForeignKey
ALTER TABLE "preferences" ADD CONSTRAINT "preferences_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -28,7 +28,7 @@ model Users {
oauth_sessions OAuthSessions[] @relation("UserOAuthSessions")
employees_archive EmployeesArchive[] @relation("UsersToEmployeesToArchive")
customer_archive CustomersArchive[] @relation("UserToCustomersToArchive")
preferences Preferences? @relation("UserPreferences")
@@map("users")
}
@ -314,6 +314,19 @@ model Attachments {
@@map("attachments")
}
model Preferences {
id Int @id @default(autoincrement())
user Users @relation("UserPreferences", fields: [user_id], references: [id])
user_id String @unique @db.Uuid
notifications Boolean @default(false)
dark_mode Boolean @default(false)
lang_switch Boolean @default(false)
lefty_mode Boolean @default(false)
@@map("preferences")
}
enum AttachmentStatus {
ACTIVE
DELETED

View File

@ -0,0 +1,14 @@
import { Body, Controller, Param, Patch } from "@nestjs/common";
import { PreferencesService } from "../services/preferences.service";
import { PreferencesDto } from "../dtos/preferences.dto";
@Controller('preferences')
export class PreferencesController {
constructor(private readonly service: PreferencesService){}
@Patch(':email')
async updatePreferences(@Param('email') email: string, @Body()payload: PreferencesDto) {
return this.service.updatePreferences(email, payload);
}
}

View File

@ -0,0 +1,16 @@
import { IsBoolean, IsEmail, IsString } from "class-validator";
export class PreferencesDto {
@IsBoolean()
notifications: boolean;
@IsBoolean()
dark_mode: boolean;
@IsBoolean()
lang_switch: boolean;
@IsBoolean()
lefty_mode: boolean;
}

View File

@ -0,0 +1,11 @@
import { Module } from "@nestjs/common";
import { PreferencesController } from "./controllers/preferences.controller";
import { PreferencesService } from "./services/preferences.service";
@Module({
controllers: [ PreferencesController ],
providers: [ PreferencesService ],
exports: [ PreferencesService ],
})
export class PreferencesModule {}

View File

@ -0,0 +1,32 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { Preferences } from "@prisma/client";
import { PrismaService } from "src/prisma/prisma.service";
import { PreferencesDto } from "../dtos/preferences.dto";
@Injectable()
export class PreferencesService {
constructor(private readonly prisma: PrismaService){}
async resolveUserIdWithEmail(email: string): Promise<string> {
const user = await this.prisma.users.findFirst({
where: { email },
select: { id: true },
});
if(!user) throw new NotFoundException(`User with email ${ email } not found`);
return user.id;
}
async updatePreferences(email: string, dto: PreferencesDto ): Promise<Preferences> {
const user_id = await this.resolveUserIdWithEmail(email);
return this.prisma.preferences.update({
where: { user_id },
data: {
notifications: dto.notifications,
dark_mode: dto.dark_mode,
lang_switch: dto.lang_switch,
lefty_mode: dto.lefty_mode,
},
include: { user: true },
});
}
}

View File

@ -19,7 +19,6 @@ export class ShiftsController {
constructor(
private readonly shiftsService: ShiftsQueryService,
private readonly shiftsCommandService: ShiftsCommandService,
private readonly shiftsValidationService: ShiftsQueryService,
){}
@Put('upsert/:email/:date')
@ -85,14 +84,14 @@ export class ShiftsController {
@Get('summary')
async getSummary( @Query() query: GetShiftsOverviewDto): Promise<OverviewRow[]> {
return this.shiftsValidationService.getSummary(query.period_id);
return this.shiftsService.getSummary(query.period_id);
}
@Get('export.csv')
@Header('Content-Type', 'text/csv; charset=utf-8')
@Header('Content-Disposition', 'attachment; filename="shifts-validation.csv"')
async exportCsv(@Query() query: GetShiftsOverviewDto): Promise<Buffer>{
const rows = await this.shiftsValidationService.getSummary(query.period_id);
const rows = await this.shiftsService.getSummary(query.period_id);
//CSV Headers
const header = [