diff --git a/frontend/pages/portal/projects/[id]/index.vue b/frontend/pages/portal/projects/[id]/index.vue index 05aaff1..a5a82ac 100644 --- a/frontend/pages/portal/projects/[id]/index.vue +++ b/frontend/pages/portal/projects/[id]/index.vue @@ -30,34 +30,46 @@ {{ $t('clientTicket.noTickets') }} -
+ +
-
-
- CT-{{ String(ticket.number).padStart(3, '0') }} - - {{ $t(`clientTicket.type.${ticket.type}`) }} - +
+
+

{{ col.label }}

+ + {{ col.tickets.length }} + +
+
+
+
+ CT-{{ String(ticket.number).padStart(3, '0') }} + + {{ $t(`clientTicket.type.${ticket.type}`) }} + +
+

{{ ticket.title }}

+

{{ formatDate(ticket.createdAt) }}

-

{{ ticket.title }}

-

- {{ formatDate(ticket.createdAt) }} +

+ {{ $t('clientTicket.noTickets') }}

- - {{ $t(`clientTicket.status.${ticket.status}`) }} -
@@ -65,6 +77,7 @@
@@ -101,7 +114,26 @@ const projectName = computed(() => { }) const isClient = computed(() => auth.user?.roles?.includes('ROLE_CLIENT') ?? false) -const { typeBadgeClass, statusBadgeClass, formatDate } = useClientTicketHelpers() +const { typeBadgeClass, formatDate } = useClientTicketHelpers() + +const statuses = ['new', 'in_progress', 'done', 'rejected'] as const + +function statusDotClass(status: string): string { + switch (status) { + case 'new': return 'bg-blue-500' + case 'in_progress': return 'bg-yellow-500' + case 'done': return 'bg-green-500' + case 'rejected': return 'bg-red-500' + default: return 'bg-neutral-400' + } +} + +const columns = computed(() => statuses.map(status => ({ + status, + label: t(`clientTicket.status.${status}`), + dotClass: statusDotClass(status), + tickets: tickets.value.filter(tk => tk.status === status), +}))) function openDetail(ticket: ClientTicket) { selectedTicket.value = ticket