From cc68c85246d038035d606f86284fd1d5950c37d5 Mon Sep 17 00:00:00 2001 From: Esdras Renan Date: Thu, 13 Nov 2025 09:48:54 -0300 Subject: [PATCH] Adjust ticket filters visibility and add date range --- src/app/tickets/page.tsx | 9 +- src/components/tickets/tickets-filters.tsx | 188 +++++++++++---------- src/components/tickets/tickets-view.tsx | 4 +- 3 files changed, 110 insertions(+), 91 deletions(-) diff --git a/src/app/tickets/page.tsx b/src/app/tickets/page.tsx index e12a2b9..a390d4f 100644 --- a/src/app/tickets/page.tsx +++ b/src/app/tickets/page.tsx @@ -21,6 +21,7 @@ function getParamValue(value: string | string[] | undefined): string | undefined function deriveInitialFilters(params: Record): Partial { const initial: Partial = {} + const isValidDateParam = (value?: string) => Boolean(value && /^\d{4}-\d{2}-\d{2}$/.test(value)) const view = getParamValue(params.view) if (view === "completed" || view === "active") { initial.view = view @@ -41,10 +42,10 @@ function deriveInitialFilters(params: Record void + queues?: QueueOption[] + companies?: string[] + assignees?: Array<{ id: string; name: string }> + categories?: Array<{ id: string; name: string }> + initialState?: Partial + viewerRole?: string | null +} + +const ALL_VALUE = "ALL" const statusOptions: Array<{ value: TicketStatus; label: string }> = [ { value: "PENDING", label: "Pendente" }, @@ -63,19 +79,6 @@ const channelOptions = ticketChannelSchema.options.map((channel) => ({ }[channel], })) -type QueueOption = string - -interface TicketsFiltersProps { - onChange?: (filters: TicketFiltersState) => void - queues?: QueueOption[] - companies?: string[] - assignees?: Array<{ id: string; name: string }> - categories?: Array<{ id: string; name: string }> - initialState?: Partial -} - -const ALL_VALUE = "ALL" - export function TicketsFilters({ onChange, queues = [], @@ -83,6 +86,7 @@ export function TicketsFilters({ assignees = [], categories = [], initialState, + viewerRole, }: TicketsFiltersProps) { const mergedDefaults = useMemo( () => ({ @@ -101,19 +105,21 @@ export function TicketsFilters({ setFilters((prev) => ({ ...prev, ...partial })) } - // Propaga as mudancas de filtros para o componente pai sem disparar durante a renderizacao useEffect(() => { onChange?.(filters) }, [filters, onChange]) + const normalizedRole = viewerRole?.toLowerCase() ?? null + const canUseAdvancedFilters = normalizedRole === "admin" || normalizedRole === "agent" + const activeFilters = useMemo(() => { const chips: string[] = [] if (filters.status) chips.push(`Status: ${statusLabelMap[filters.status] ?? filters.status}`) if (filters.priority) chips.push(`Prioridade: ${filters.priority}`) - if (filters.queue) chips.push(`Fila: ${filters.queue}`) + if (filters.queue && canUseAdvancedFilters) chips.push(`Fila: ${filters.queue}`) if (filters.channel) chips.push(`Canal: ${filters.channel}`) - if (filters.company) chips.push(`Empresa: ${filters.company}`) - if (filters.assigneeId) { + if (filters.company && canUseAdvancedFilters) chips.push(`Empresa: ${filters.company}`) + if (filters.assigneeId && canUseAdvancedFilters) { const found = assignees.find((a) => a.id === filters.assigneeId) chips.push(`Responsável: ${found?.name ?? filters.assigneeId}`) } @@ -126,50 +132,54 @@ export function TicketsFilters({ if (filters.dateFrom || filters.dateTo) chips.push(formatDateRangeChip(filters.dateFrom, filters.dateTo)) if (filters.sort === "oldest") chips.push("Ordenados por mais antigos") return chips - }, [filters, assignees, categories]) + }, [filters, assignees, categories, canUseAdvancedFilters]) return (
-
+
setPartial({ search: event.target.value })} className="md:max-w-sm" /> - - + {canUseAdvancedFilters ? ( + + ) : null} + {canUseAdvancedFilters ? ( + + ) : null}
-
- +
+ {canUseAdvancedFilters ? ( + + ) : null}
-
-

- Período -

-
- setPartial({ dateFrom: event.target.value || null })} - /> - setPartial({ dateTo: event.target.value || null })} - /> -
-
+
+
+

Período

+
+
+
+ + setPartial({ dateFrom: value })} + placeholder="Selecionar data" + /> +
+
+ + setPartial({ dateTo: value })} + placeholder="Selecionar data" + /> +
+
+
{activeFilters.length > 0 && (
{activeFilters.map((chip) => ( diff --git a/src/components/tickets/tickets-view.tsx b/src/components/tickets/tickets-view.tsx index 9a8340b..65b06eb 100644 --- a/src/components/tickets/tickets-view.tsx +++ b/src/components/tickets/tickets-view.tsx @@ -37,7 +37,7 @@ export function TicketsView({ initialFilters }: TicketsViewProps = {}) { setFilters(mergedInitialFilters) }, [mergedInitialFilters]) - const { session, convexUserId, isStaff } = useAuth() + const { session, convexUserId, isStaff, role } = useAuth() const userId = session?.user?.id ?? null const tenantId = session?.user?.tenantId ?? DEFAULT_TENANT_ID const viewModeStorageKey = useMemo(() => { @@ -111,7 +111,6 @@ export function TicketsView({ initialFilters }: TicketsViewProps = {}) { } }, []) - // load saved filters as defaults per user useEffect(() => { if (!convexUserId) return try { @@ -230,6 +229,7 @@ export function TicketsView({ initialFilters }: TicketsViewProps = {}) { assignees={(agents ?? []).map((a) => ({ id: a._id, name: a.name }))} categories={ticketCategories.map((category) => ({ id: category.id, name: category.name }))} initialState={mergedInitialFilters} + viewerRole={role} />