diff --git a/CLAUDE.md b/CLAUDE.md index 8222c4d..9b82ca6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -104,16 +104,16 @@ legacy/ # Original HTML tools for reference | 4 | **Registratura** | `/registratura` | 0.4.0 | CRUD registry, dynamic doc types, bidirectional Address Book, threads, backdating, **legal deadline tracking**, recipient registration, document expiry, **NAS network path attachments** (A/O/P/T drives, copy-to-clipboard), **detail sheet side panel**, **configurable column visibility**, **QuickLook attachment preview** (images: zoom/pan, PDFs: native viewer, multi-file navigation) | | 5 | **Tag Manager** | `/tag-manager` | 0.2.0 | CRUD tags, category/scope/color, US/SDT seeds, mandatory categories, **ManicTime bidirectional sync** | | 6 | **IT Inventory** | `/it-inventory` | 0.2.0 | Dynamic equipment types, rented status (purple pulse), **42U rack visualization**, type/status/company filters | -| 7 | **Address Book** | `/address-book` | 0.1.1 | CRUD contacts, card grid, vCard export, Registratura reverse lookup, **dynamic types (creatable)**, **alphabetically sorted type dropdown** | +| 7 | **Address Book** | `/address-book` | 0.1.1 | CRUD contacts, card grid, vCard export, Registratura reverse lookup, **dynamic types (creatable)**, **alphabetically sorted type dropdown** | | 8 | **Password Vault** | `/password-vault` | 0.3.0 | CRUD credentials, 9 categorii cu iconițe, **WiFi QR code real**, context-aware form, strength meter, company scope, **AES-256-GCM encryption** | -| 9 | **Mini Utilities** | `/mini-utilities` | 0.1.1 | Text case, char counter, percentage, **TVA calculator (19%)**, area converter, U→R, num→text, artifact cleaner, MDLPA, PDF reducer, OCR, color palette | +| 9 | **Mini Utilities** | `/mini-utilities` | 0.1.1 | Text case, char counter, percentage, **TVA calculator (19%)**, area converter, U→R, num→text, artifact cleaner, MDLPA, PDF reducer, OCR, color palette | | 10 | **Prompt Generator** | `/prompt-generator` | 0.2.0 | Template-driven prompt builder, **18 templates** (14 text + 4 image), search bar, target type filter | | 11 | **Digital Signatures** | `/digital-signatures` | 0.1.0 | CRUD assets, drag-and-drop file upload, tag chips | | 12 | **Word Templates** | `/word-templates` | 0.1.0 | Template library, 8 categories, version tracking, .docx placeholder auto-detection | | 13 | **AI Chat** | `/ai-chat` | 0.2.0 | Multi-provider (OpenAI/Claude/Ollama/demo), **project linking via Tag Manager**, provider status badge | -| 14 | **Hot Desk** | `/hot-desk` | 0.1.1 | 4 desks, week-ahead calendar, room layout (window+door proportioned), reserve/cancel | +| 14 | **Hot Desk** | `/hot-desk` | 0.1.1 | 4 desks, week-ahead calendar, room layout (window+door proportioned), reserve/cancel | | 15 | **ParcelSync** | `/parcel-sync` | 0.5.0 | eTerra ANCPI integration, **PostGIS database**, background sync, 23-layer catalog, enrichment pipeline, owner search, **per-UAT analytics dashboard**, **health check + maintenance detection** | -| 16 | **Visual Copilot** | `/visual-copilot` | 0.1.0 | AI-powered image analysis — **developed in separate repo** (`https://git.beletage.ro/gitadmin/vim`), placeholder in ArchiTools, will be merged as module later | +| 16 | **Visual Copilot** | `/visual-copilot` | 0.1.0 | AI-powered image analysis — **developed in separate repo** (`https://git.beletage.ro/gitadmin/vim`), placeholder in ArchiTools, will be merged as module later | ### Registratura — Legal Deadline Tracking (Termene Legale) diff --git a/ROADMAP.md b/ROADMAP.md index bfa149e..1774719 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -724,59 +724,64 @@ Env vars (hardcoded in docker-compose.yml for Portainer CE): ### 4B.04 `[STANDARD]` Registratura — Legal Deadline Workflow Fixes **What:** Fix gaps in the legal deadline tracking logic: + - Chain deadline workflow (resolving one → prompt to add next in sequence) - Backward deadline edge cases (e.g., AC extension 45 working days BEFORE expiry) - Tacit approval auto-detection when overdue + applicable type - UI polish for deadline dashboard (filters, sorting, edge states) -**Files:** `src/modules/registratura/services/deadline-service.ts`, `components/deadline-dashboard.tsx`, `components/deadline-add-dialog.tsx` -**Status:** TODO + **Files:** `src/modules/registratura/services/deadline-service.ts`, `components/deadline-dashboard.tsx`, `components/deadline-add-dialog.tsx` + **Status:** TODO --- ### 4B.05 `[STANDARD]` Tag Manager — Logic/Workflow Fix + ERP API **What:** + - Fix tag assignment and filtering logic/workflow issues - Expose tags via API for external ERP integration (read-only endpoint for tag list + project assignments) - Verify ManicTime bidirectional sync still works -**Files:** `src/modules/tag-manager/`, `src/app/api/` (new tags API route) -**Status:** TODO + **Files:** `src/modules/tag-manager/`, `src/app/api/` (new tags API route) + **Status:** TODO --- ### 4B.06 `[STANDARD]` Prompt Generator — Bug Fixes + New Features **What:** Address known bugs and implement new ideas (details TBD from user testing): + - Fix any template rendering issues - Add new templates as requested - Implement user-suggested feature improvements -**Files:** `src/modules/prompt-generator/` -**Status:** TODO — awaiting user feedback from testing + **Files:** `src/modules/prompt-generator/` + **Status:** TODO — awaiting user feedback from testing --- ### 4B.07 `[HEAVY]` Authentik SSO — Verify & Fix **What:** End-to-end verification that Authentik OIDC login works: + - Verify auth.beletage.ro accessibility - Test login flow (redirect → auth → callback → session) - Verify group→role/company mapping - Fix any issues with NextAuth v4 + Authentik provider config - Ensure session persistence and token refresh -**Files:** `src/core/auth/`, `src/app/api/auth/`, `.env` / `docker-compose.yml` -**Status:** TODO — critical for multi-user testing + **Files:** `src/core/auth/`, `src/app/api/auth/`, `.env` / `docker-compose.yml` + **Status:** TODO — critical for multi-user testing --- ### 4B.08 `[STANDARD]` DB/Storage — End-to-End Verification **What:** Verify all 14 modules correctly persist to PostgreSQL: + - Test CRUD operations for each module - Verify data survives container restart - Check storage adapter fallback behavior - Validate MinIO file storage connection (adapter pending) -**Files:** `src/core/storage/`, `src/app/api/storage/`, `prisma/schema.prisma` -**Status:** TODO + **Files:** `src/core/storage/`, `src/app/api/storage/`, `prisma/schema.prisma` + **Status:** TODO --- diff --git a/src/modules/hot-desk/components/desk-room-layout.tsx b/src/modules/hot-desk/components/desk-room-layout.tsx index bc6b759..5d8c59b 100644 --- a/src/modules/hot-desk/components/desk-room-layout.tsx +++ b/src/modules/hot-desk/components/desk-room-layout.tsx @@ -19,10 +19,10 @@ export function DeskRoomLayout({ return (
{/* Room container — styled like a top-down floor plan */} -
+
{/* Window indicator — LEFT wall (landmark for orientation) */} -
-
+
+
{Array.from({ length: 3 }).map((_, i) => (
))}
- {/* Window label */} -
- Fereastră -
{/* Door indicator — RIGHT wall */} -
-
- Ușă -
+
{/* Central table */} -
+
{/* Top row desks */} -
+
{DESKS.filter((d) => d.position.startsWith("top")).map((desk) => { const reservation = getReservationForDesk( desk.id, @@ -65,10 +58,10 @@ export function DeskRoomLayout({
{/* The table surface */} -
+
{/* Bottom row desks */} -
+
{DESKS.filter((d) => d.position.startsWith("bottom")).map( (desk) => { const reservation = getReservationForDesk( @@ -111,7 +104,7 @@ function DeskSlot({ label, reservation, side, onClick }: DeskSlotProps) { type="button" onClick={onClick} className={cn( - "group relative flex w-[125px] cursor-pointer flex-col items-center rounded-lg border p-3 transition-all", + "group relative flex w-[116px] cursor-pointer flex-col items-center rounded-lg border p-3 transition-all", side === "top" ? "rounded-b-sm" : "rounded-t-sm", isBooked ? "border-primary/30 bg-primary/8 hover:border-primary/50 hover:bg-primary/12" diff --git a/src/modules/hot-desk/components/hot-desk-module.tsx b/src/modules/hot-desk/components/hot-desk-module.tsx index 006b765..c15f2e3 100644 --- a/src/modules/hot-desk/components/hot-desk-module.tsx +++ b/src/modules/hot-desk/components/hot-desk-module.tsx @@ -199,9 +199,6 @@ export function HotDeskModule() { Persoana - - Note - @@ -216,9 +213,6 @@ export function HotDeskModule() { r.deskId} {r.userName} - - {r.notes || "—"} - ))} diff --git a/src/modules/hot-desk/components/reservation-dialog.tsx b/src/modules/hot-desk/components/reservation-dialog.tsx index 7de2827..d5b3c56 100644 --- a/src/modules/hot-desk/components/reservation-dialog.tsx +++ b/src/modules/hot-desk/components/reservation-dialog.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import { Dialog, DialogContent, @@ -11,11 +11,21 @@ import { import { Button } from "@/shared/components/ui/button"; import { Input } from "@/shared/components/ui/input"; import { Label } from "@/shared/components/ui/label"; -import { Textarea } from "@/shared/components/ui/textarea"; +import { useAuth } from "@/core/auth"; +import { cn } from "@/shared/lib/utils"; import type { DeskId, DeskReservation } from "../types"; import { getDeskLabel } from "../types"; import { formatDateRo, isDateBookable } from "../services/reservation-service"; +const TEAM_NAMES = [ + "Alexandra", + "Mihaela", + "Ștefan", + "Mara", + "Denisa", + "Daria", +]; + interface ReservationDialogProps { open: boolean; onClose: () => void; @@ -36,8 +46,22 @@ export function ReservationDialog({ onCancel, }: ReservationDialogProps) { const [userName, setUserName] = useState(""); - const [notes, setNotes] = useState(""); const [submitting, setSubmitting] = useState(false); + const { user } = useAuth(); + + // Auto-fill first name from Authentik session + useEffect(() => { + if (open && !userName && user?.name) { + const firstName = user.name.split(" ")[0]; + if (firstName) setUserName(firstName); + } + }, [open, user?.name]); // eslint-disable-line react-hooks/exhaustive-deps + + const filteredNames = userName.trim() + ? TEAM_NAMES.filter((n) => + n.toLowerCase().startsWith(userName.toLowerCase()), + ) + : TEAM_NAMES; const bookable = isDateBookable(dateKey); const isBooked = !!existingReservation; @@ -46,9 +70,8 @@ export function ReservationDialog({ if (!userName.trim()) return; setSubmitting(true); try { - await onBook(userName.trim(), notes.trim()); + await onBook(userName.trim(), ""); setUserName(""); - setNotes(""); onClose(); } finally { setSubmitting(false); @@ -84,12 +107,6 @@ export function ReservationDialog({ {existingReservation.userName}
- {existingReservation.notes && ( -
- Note: - {existingReservation.notes} -
- )}
) : bookable ? ( @@ -104,17 +121,23 @@ export function ReservationDialog({ onKeyDown={(e) => e.key === "Enter" && handleBook()} autoFocus /> -
-
- -