Správa používateľov + notifikačný systém

- Pridaná kompletná správa používateľov (CRUD, reset hesla, zmena roly) pre ROOT/ADMIN
- Backend: POST /users endpoint, createUser controller, validácia
- Frontend: UserManagement, UserForm, PasswordResetModal komponenty
- Settings prístupné pre ROOT aj ADMIN (AdminRoute)
- Notifikačný systém s snooze funkcionalitou
- Aktualizácia HELPDESK_INIT_V2.md dokumentácie

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 15:30:27 +01:00
parent cbdd952bc1
commit 2ca0c4f4d8
36 changed files with 3116 additions and 522 deletions

View File

@@ -67,6 +67,7 @@ model User {
taskAttachments TaskAttachment[] @relation("TaskAttachmentUploader")
createdCustomers Customer[]
notifications Notification[]
@@index([email])
@@index([roleId])
@@ -374,11 +375,12 @@ model Task {
createdById String
createdBy User @relation("TaskCreator", fields: [createdById], references: [id])
assignees TaskAssignee[]
reminders Reminder[]
comments Comment[]
tags TaskTag[]
attachments TaskAttachment[]
assignees TaskAssignee[]
reminders Reminder[]
comments Comment[]
tags TaskTag[]
attachments TaskAttachment[]
notifications Notification[]
@@index([projectId])
@@index([parentId])
@@ -633,6 +635,7 @@ model RMA {
statusHistory RMAStatusHistory[]
comments RMAComment[]
tags RMATag[]
notifications Notification[]
@@index([rmaNumber])
@@index([customerId])
@@ -706,6 +709,40 @@ model RMATag {
@@id([rmaId, tagId])
}
// ==================== NOTIFICATIONS ====================
model Notification {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
type String // TASK_ASSIGNED, TASK_STATUS_CHANGED, TASK_COMMENT, TASK_DEADLINE, RMA_ASSIGNED, etc.
taskId String?
task Task? @relation(fields: [taskId], references: [id], onDelete: Cascade)
rmaId String?
rma RMA? @relation(fields: [rmaId], references: [id], onDelete: Cascade)
title String
message String
data Json? // Extra data (oldStatus, newStatus, etc.)
isRead Boolean @default(false)
readAt DateTime?
snoozedUntil DateTime?
createdAt DateTime @default(now())
@@index([userId])
@@index([userId, isRead])
@@index([taskId])
@@index([rmaId])
@@index([createdAt])
}
// ==================== ACTIVITY LOG ====================
model ActivityLog {

View File

@@ -203,6 +203,19 @@ async function seed() {
label: 'Zapnúť real-time aktualizácie (WebSocket)',
dataType: 'boolean',
},
{
key: 'NOTIFICATION_SNOOZE_OPTIONS',
value: [
{ label: '30 minút', minutes: 30 },
{ label: '1 hodina', minutes: 60 },
{ label: '3 hodiny', minutes: 180 },
{ label: 'Zajtra ráno', type: 'tomorrow', hour: 9 },
],
category: 'NOTIFICATIONS',
label: 'Možnosti odloženia notifikácií',
description: 'Pole objektov. Každý má "label" a buď "minutes" (relatívny čas) alebo "type" + "hour" (konkrétny čas). Type: "today" (ak čas prešiel, skryje sa), "tomorrow".',
dataType: 'json',
},
],
});