feat: improve ticket export and navigation
This commit is contained in:
parent
0731c5d1ea
commit
7d6f3bea01
28 changed files with 1612 additions and 609 deletions
|
|
@ -26,9 +26,11 @@ export function PortalShell({ children }: PortalShellProps) {
|
|||
const { session, machineContext } = useAuth()
|
||||
const [isSigningOut, setIsSigningOut] = useState(false)
|
||||
|
||||
const isMachineSession = session?.user.role === "machine"
|
||||
const personaValue = machineContext?.persona ?? session?.user.machinePersona ?? null
|
||||
const displayName = machineContext?.assignedUserName ?? session?.user.name ?? session?.user.email ?? "Cliente"
|
||||
const displayEmail = machineContext?.assignedUserEmail ?? session?.user.email ?? ""
|
||||
const personaLabel = machineContext?.persona === "manager" ? "Gestor" : "Colaborador"
|
||||
const personaLabel = personaValue === "manager" ? "Gestor" : "Colaborador"
|
||||
|
||||
const initials = useMemo(() => {
|
||||
const name = displayName || displayEmail || "Cliente"
|
||||
|
|
@ -64,7 +66,7 @@ export function PortalShell({ children }: PortalShellProps) {
|
|||
<GalleryVerticalEnd className="size-4" />
|
||||
</span>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.28em] text-neutral-500">
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.12em] text-neutral-500">
|
||||
Portal do cliente
|
||||
</span>
|
||||
<span className="text-lg font-semibold text-neutral-900">Raven</span>
|
||||
|
|
@ -100,12 +102,12 @@ export function PortalShell({ children }: PortalShellProps) {
|
|||
<div className="flex flex-col leading-tight">
|
||||
<span className="font-semibold text-neutral-900">{displayName}</span>
|
||||
<span className="text-xs text-neutral-500">{displayEmail}</span>
|
||||
{machineContext ? (
|
||||
{personaValue ? (
|
||||
<span className="text-[10px] uppercase tracking-wide text-neutral-400">{personaLabel}</span>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
{!machineContext ? (
|
||||
{!isMachineSession ? (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
|
|
|
|||
|
|
@ -31,11 +31,12 @@ function toHtml(text: string) {
|
|||
|
||||
export function PortalTicketForm() {
|
||||
const router = useRouter()
|
||||
const { convexUserId, session } = useAuth()
|
||||
const { convexUserId, session, machineContext } = useAuth()
|
||||
const createTicket = useMutation(api.tickets.create)
|
||||
const addComment = useMutation(api.tickets.addComment)
|
||||
|
||||
const tenantId = session?.user.tenantId ?? DEFAULT_TENANT_ID
|
||||
const viewerId = (convexUserId ?? machineContext?.assignedUserId ?? null) as Id<"users"> | null
|
||||
|
||||
const [subject, setSubject] = useState("")
|
||||
const [summary, setSummary] = useState("")
|
||||
|
|
@ -51,7 +52,7 @@ export function PortalTicketForm() {
|
|||
|
||||
async function handleSubmit(event: React.FormEvent) {
|
||||
event.preventDefault()
|
||||
if (!convexUserId || !isFormValid || isSubmitting) return
|
||||
if (!viewerId || !isFormValid || isSubmitting) return
|
||||
|
||||
const trimmedSubject = subject.trim()
|
||||
const trimmedSummary = summary.trim()
|
||||
|
|
@ -66,14 +67,14 @@ export function PortalTicketForm() {
|
|||
toast.loading("Abrindo chamado...", { id: "portal-new-ticket" })
|
||||
try {
|
||||
const id = await createTicket({
|
||||
actorId: convexUserId as Id<"users">,
|
||||
actorId: viewerId,
|
||||
tenantId,
|
||||
subject: trimmedSubject,
|
||||
summary: trimmedSummary || undefined,
|
||||
priority: DEFAULT_PRIORITY,
|
||||
channel: "MANUAL",
|
||||
queueId: undefined,
|
||||
requesterId: convexUserId as Id<"users">,
|
||||
requesterId: viewerId,
|
||||
categoryId: categoryId as Id<"ticketCategories">,
|
||||
subcategoryId: subcategoryId as Id<"ticketSubcategories">,
|
||||
})
|
||||
|
|
@ -89,7 +90,7 @@ export function PortalTicketForm() {
|
|||
}))
|
||||
await addComment({
|
||||
ticketId: id as Id<"tickets">,
|
||||
authorId: convexUserId as Id<"users">,
|
||||
authorId: viewerId,
|
||||
visibility: "PUBLIC",
|
||||
body: htmlBody,
|
||||
attachments: typedAttachments,
|
||||
|
|
@ -186,7 +187,7 @@ export function PortalTicketForm() {
|
|||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={!isFormValid || isSubmitting}
|
||||
disabled={!isFormValid || isSubmitting || !viewerId}
|
||||
className="rounded-full bg-neutral-900 px-6 text-sm font-semibold text-white hover:bg-neutral-900/90"
|
||||
>
|
||||
Registrar chamado
|
||||
|
|
|
|||
|
|
@ -16,14 +16,16 @@ import { Button } from "@/components/ui/button"
|
|||
import { PortalTicketCard } from "@/components/portal/portal-ticket-card"
|
||||
|
||||
export function PortalTicketList() {
|
||||
const { convexUserId, session } = useAuth()
|
||||
const { convexUserId, session, machineContext } = useAuth()
|
||||
|
||||
const viewerId = (convexUserId ?? machineContext?.assignedUserId ?? null) as Id<"users"> | null
|
||||
|
||||
const ticketsRaw = useQuery(
|
||||
api.tickets.list,
|
||||
convexUserId
|
||||
viewerId
|
||||
? {
|
||||
tenantId: session?.user.tenantId ?? DEFAULT_TENANT_ID,
|
||||
viewerId: convexUserId as Id<"users">,
|
||||
viewerId,
|
||||
limit: 100,
|
||||
}
|
||||
: "skip"
|
||||
|
|
@ -34,7 +36,9 @@ export function PortalTicketList() {
|
|||
return mapTicketsFromServerList((ticketsRaw as unknown[]) ?? [])
|
||||
}, [ticketsRaw])
|
||||
|
||||
if (ticketsRaw === undefined) {
|
||||
const isLoading = Boolean(viewerId && ticketsRaw === undefined)
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Card className="rounded-2xl border border-slate-200 bg-white shadow-sm">
|
||||
<CardHeader className="flex items-center gap-2 px-5 py-5">
|
||||
|
|
@ -48,7 +52,7 @@ export function PortalTicketList() {
|
|||
)
|
||||
}
|
||||
|
||||
if (!tickets.length) {
|
||||
if (!viewerId || !tickets.length) {
|
||||
return (
|
||||
<Card className="rounded-2xl border border-slate-200 bg-white shadow-sm">
|
||||
<CardHeader className="px-5 py-5">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue