@avament-pub/support-navbar-create 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../SupportNavbarCreateDialog.tsx","../createSupportTicket.ts","../useSupportNavbarCreateTicket.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { createSupportTicket } from \"./createSupportTicket\";\n\nexport type SupportNavbarCreateDialogLabels = {\n title: string;\n shortLabel: string;\n detailsLabel: string;\n submit: string;\n cancel: string;\n shortRequired: string;\n submitError: string;\n};\n\nexport type SupportNavbarCreateDialogProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n apiBaseUrl: string;\n getAccessToken: () => string | null;\n labels: SupportNavbarCreateDialogLabels;\n};\n\nexport function SupportNavbarCreateDialog({\n open,\n onOpenChange,\n apiBaseUrl,\n getAccessToken,\n labels,\n}: SupportNavbarCreateDialogProps) {\n const [shortText, setShortText] = React.useState(\"\");\n const [details, setDetails] = React.useState(\"\");\n const [error, setError] = React.useState<string | null>(null);\n const [submitting, setSubmitting] = React.useState(false);\n\n React.useEffect(() => {\n if (!open) {\n setShortText(\"\");\n setDetails(\"\");\n setError(null);\n setSubmitting(false);\n }\n }, [open]);\n\n if (!open) return null;\n\n const close = () => onOpenChange(false);\n\n const handleSubmit = async (event: React.FormEvent) => {\n event.preventDefault();\n const trimmed = shortText.trim();\n if (!trimmed) {\n setError(labels.shortRequired);\n return;\n }\n setError(null);\n setSubmitting(true);\n try {\n await createSupportTicket(apiBaseUrl, getAccessToken(), {\n shortDescription: trimmed,\n longDescriptionHtml: details.trim() || undefined,\n });\n close();\n } catch {\n setError(labels.submitError);\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 z-[200] flex items-center justify-center bg-black/50 p-4\"\n role=\"presentation\"\n onMouseDown={(event) => {\n if (event.target === event.currentTarget) close();\n }}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"support-navbar-create-title\"\n className=\"w-full max-w-lg rounded-lg border border-theme bg-theme p-4 shadow-lg\"\n onMouseDown={(event) => event.stopPropagation()}\n >\n <h2\n id=\"support-navbar-create-title\"\n className=\"mb-3 text-lg font-semibold text-theme-primary\"\n >\n {labels.title}\n </h2>\n <form className=\"space-y-3\" onSubmit={(event) => void handleSubmit(event)}>\n <label className=\"block space-y-1\">\n <span className=\"text-sm font-medium text-theme-primary\">\n {labels.shortLabel}\n </span>\n <input\n type=\"text\"\n value={shortText}\n onChange={(event) => setShortText(event.target.value)}\n className=\"w-full rounded-md border border-theme bg-input-theme px-3 py-2 text-sm text-theme-primary\"\n autoFocus\n />\n </label>\n <label className=\"block space-y-1\">\n <span className=\"text-sm font-medium text-theme-primary\">\n {labels.detailsLabel}\n </span>\n <textarea\n value={details}\n onChange={(event) => setDetails(event.target.value)}\n rows={4}\n className=\"w-full rounded-md border border-theme bg-input-theme px-3 py-2 text-sm text-theme-primary\"\n />\n </label>\n {error ? (\n <p className=\"text-sm text-red-600\" role=\"alert\">{error}</p>\n ) : null}\n <div className=\"flex justify-end gap-2 pt-1\">\n <button\n type=\"button\"\n className=\"rounded-md border border-theme px-3 py-1.5 text-sm text-theme-primary\"\n onClick={close}\n disabled={submitting}\n >\n {labels.cancel}\n </button>\n <button\n type=\"submit\"\n className=\"rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-white disabled:opacity-50\"\n disabled={submitting}\n >\n {labels.submit}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n","export type CreateSupportTicketInput = {\n shortDescription: string;\n longDescriptionHtml?: string;\n};\n\nexport async function createSupportTicket(\n apiBaseUrl: string,\n accessToken: string | null,\n input: CreateSupportTicketInput,\n): Promise<void> {\n const base = apiBaseUrl.replace(/\\/$/, \"\");\n const response = await fetch(`${base}/api/support/tickets`, {\n method: \"POST\",\n credentials: \"include\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),\n },\n body: JSON.stringify({\n shortDescription: input.shortDescription.trim(),\n longDescriptionHtml: input.longDescriptionHtml?.trim() || null,\n typeKey: \"task\",\n priority: \"medium\",\n statusKey: \"open\",\n }),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => \"\");\n throw new Error(text || `Support ticket create failed (${response.status})`);\n }\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n SupportNavbarCreateDialog,\n type SupportNavbarCreateDialogLabels,\n} from \"./SupportNavbarCreateDialog\";\n\nexport type UseSupportNavbarCreateTicketOptions = {\n apiBaseUrl: string;\n getAccessToken: () => string | null;\n labels: SupportNavbarCreateDialogLabels;\n};\n\nexport function useSupportNavbarCreateTicket({\n apiBaseUrl,\n getAccessToken,\n labels,\n}: UseSupportNavbarCreateTicketOptions) {\n const [open, setOpen] = React.useState(false);\n const onSupportClick = React.useCallback(() => setOpen(true), []);\n\n const dialog = (\n <SupportNavbarCreateDialog\n open={open}\n onOpenChange={setOpen}\n apiBaseUrl={apiBaseUrl}\n getAccessToken={getAccessToken}\n labels={labels}\n />\n );\n\n return { onSupportClick, dialog, open, setOpen };\n}\n"],"mappings":"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","names":["React","jsx"]}
1
+ {"version":3,"sources":["../src/lib/utils.ts","../src/components/ui/button.tsx","../src/hooks/useLatestRef.ts","../src/components/tickets/TicketRichTextEditor.tsx","../src/components/tickets/CreateTicketDialog.tsx","../src/components/tickets/TicketDeadlinePicker.tsx","../src/components/ui/calendar.tsx","../src/components/ui/popover.tsx","../src/hooks/useUserSettings.ts","../src/api/client.ts","../src/lib/auth/tokenService.ts","../src/lib/auth/constants.ts","../src/lib/auth/cookieDomain.ts","../src/lib/services/index.ts","../support-api-runtime.ts","../src/lib/date-utils.ts","../src/components/tickets/TicketEventSelect.tsx","../src/components/tickets/TicketCatalogDeleteConfirmDialog.tsx","../src/components/ui/dialog.tsx","../src/components/ui/input.tsx","../src/components/ui/label.tsx","../src/components/ui/color-picker/color-picker-utils.ts","../src/components/ui/color-picker/color-picker.tsx","../src/components/ui/color-picker/use-color-picker.ts","../src/hooks/useTicketEvents.ts","../src/api/staff.ts","../src/lib/tickets/ticketAttachments.ts","../src/api/ticketForm.ts","../src/api/ticket.ts","../src/hooks/queries/query-keys.ts","../src/lib/tickets/ticketCatalogColors.ts","../src/hooks/useTickets.ts","../src/lib/tickets/ticketRow.ts","../src/lib/tickets/ticketAssignment.ts","../src/lib/auth/isStaffRole.ts","../src/hooks/useUserInfo.ts","../src/lib/workspaceContext.ts","../src/api/auth.ts","../src/hooks/useTicketCatalogUsageMemory.ts","../src/lib/tickets/ticketCatalogUsageMemory.ts","../src/lib/tickets/catalogNames.ts","../src/lib/tickets/ticketCatalogDeleteCopy.ts","../src/components/tickets/TicketCatalogColorField.tsx","../src/components/tickets/SupportTicketTypeSelect.tsx","../src/lib/tickets/supportTicketTypes.ts","../src/components/tickets/SupportTicketTypeIcon.tsx","../src/hooks/useTicketTypes.ts","../src/hooks/useLocalTicketAttachments.ts","../src/lib/auth/roles.ts","../src/components/tickets/PlanImagesReel.tsx","../src/components/tickets/TicketAttachmentAddButton.tsx","../src/components/tickets/TicketAttachmentPreviews.tsx","../src/api/files.ts","../src/components/tickets/TicketAttachmentMediaViewer.tsx","../src/components/tickets/TicketAttachmentVideoPlayer.tsx","../src/components/tickets/TicketImageEditor.tsx","../src/lib/tickets/ticketImageEditor.ts","../src/components/ui/image-previewer/use-resolved-media-url.ts","../src/components/ui/image-previewer/use-image-previewer.ts","../src/components/tickets/TicketAttachmentGallery.tsx","../src/hooks/useTicketAttachmentPreviews.ts","../src/components/tickets/TicketStoredAttachmentPreviews.tsx","../src/components/ui/checkbox.tsx","../src/components/ui/select.tsx","../src/components/tickets/CreateTicketBufferedInput.tsx","../src/components/tickets/TicketCreateSuccessOverlay.tsx","../src/lib/tickets/createTicketFieldOrder.ts","../src/lib/tickets/createTicketFieldVisibility.ts","../src/components/tickets/TicketResponsibleField.tsx","../src/hooks/useTicketResponsibles.ts","../src/lib/tickets/ticketResponsibleCatalog.ts","../src/hooks/queries/use-ticket-detail.ts","../src/lib/tickets/persistEditedTicketAttachment.ts","../src/hooks/useCreateTicketFieldVisibility.ts","../src/lib/tickets/createTicketKeepFields.ts","../src/api/ticketCreatePreferences.ts","../src/hooks/useTicketSequences.ts","../src/api/ticketSequence.ts","../src/lib/tickets/ticketTableColumns.ts","../src/lib/tickets/ticketCreateValidation.ts","../SupportApiRuntimeProvider.tsx","../useSupportNavbarCreateTicket.tsx"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n outline:\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","\"use client\";\n\nimport * as React from \"react\";\n\n/** Syncs a ref to the latest value after render (eslint-safe latest-ref pattern). */\nexport function useLatestRef<T>(value: T): React.RefObject<T> {\n const ref = React.useRef(value);\n React.useLayoutEffect(() => {\n ref.current = value;\n });\n return ref;\n}\n\n/** Returns a stable callback that always invokes the latest function reference. */\nexport function useLatestCallback<T extends (...args: never[]) => unknown>(\n fn: T,\n): T {\n const fnRef = useLatestRef(fn);\n return React.useCallback(\n (...args: Parameters<T>) => fnRef.current(...args),\n [fnRef],\n ) as T;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport Bold from \"lucide-react/dist/esm/icons/bold\";\nimport Italic from \"lucide-react/dist/esm/icons/italic\";\nimport List from \"lucide-react/dist/esm/icons/list\";\nimport ListOrdered from \"lucide-react/dist/esm/icons/list-ordered\";\nimport Strikethrough from \"lucide-react/dist/esm/icons/strikethrough\";\nimport Underline from \"lucide-react/dist/esm/icons/underline\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { useLatestRef } from \"@/hooks/useLatestRef\";\nimport { cn } from \"@/lib/utils\";\n\ntype FormatCommand =\n | \"bold\"\n | \"italic\"\n | \"underline\"\n | \"strikeThrough\"\n | \"insertUnorderedList\"\n | \"insertOrderedList\";\n\ntype TicketRichTextEditorProps = {\n value: string;\n /**\n * Fired on every input. Prefer updating a ref + sparse flags here;\n * avoid elevating full HTML into a mega-parent on each keystroke.\n */\n onChange: (html: string, textLength: number) => void;\n /** Fired when the editor loses focus (good place to commit parent state). */\n onBlurCommit?: (html: string, textLength: number) => void;\n maxLength: number;\n placeholder: string;\n className?: string;\n disabled?: boolean;\n};\n\nconst FORMAT_BUTTONS: {\n command: FormatCommand;\n icon: React.ComponentType<{ className?: string }>;\n labelKey: string;\n}[] = [\n { command: \"bold\", icon: Bold, labelKey: \"bold\" },\n { command: \"italic\", icon: Italic, labelKey: \"italic\" },\n { command: \"underline\", icon: Underline, labelKey: \"underline\" },\n { command: \"strikeThrough\", icon: Strikethrough, labelKey: \"strikethrough\" },\n];\n\nexport const TicketRichTextEditor = React.memo(function TicketRichTextEditor({\n value,\n onChange,\n onBlurCommit,\n maxLength,\n placeholder,\n className,\n disabled = false,\n}: TicketRichTextEditorProps) {\n const { t } = useTranslation();\n const editorRef = React.useRef<HTMLDivElement>(null);\n const onChangeRef = useLatestRef(onChange);\n const onBlurCommitRef = useLatestRef(onBlurCommit);\n // Sentinel so the first layout sync always writes `value` into the empty\n // contentEditable — even when the parent already hydrated the prop before mount\n // (dynamic import / dialog remount after applyTicketDetail).\n const lastExternalValueRef = React.useRef<string | null>(null);\n const [textLength, setTextLength] = React.useState(0);\n const [isEmpty, setIsEmpty] = React.useState(() => value.trim().length === 0);\n\n const readEditor = React.useCallback(() => {\n const el = editorRef.current;\n if (!el) return { html: \"\", textLength: 0 };\n const text = el.innerText.replace(/\\u00a0/g, \" \").trimEnd();\n return { html: el.innerHTML, textLength: text.length };\n }, []);\n\n const syncFromEditor = React.useCallback(() => {\n const { html, textLength: length } = readEditor();\n setTextLength(length);\n setIsEmpty(length === 0);\n onChangeRef.current(html, length);\n }, [onChangeRef, readEditor]);\n\n const applyFormat = (command: FormatCommand) => {\n const el = editorRef.current;\n if (!el) return;\n el.focus();\n document.execCommand(command, false);\n syncFromEditor();\n };\n\n const handleToolbarMouseDown = (e: React.MouseEvent) => {\n e.preventDefault();\n };\n\n React.useLayoutEffect(() => {\n const el = editorRef.current;\n if (!el) return;\n // Only apply external resets/loads — never clobber in-progress typing\n // when the parent intentionally skips per-keystroke HTML state.\n if (value === lastExternalValueRef.current) return;\n lastExternalValueRef.current = value;\n if (value !== el.innerHTML) {\n el.innerHTML = value;\n }\n const text = el.innerText.replace(/\\u00a0/g, \" \").trimEnd();\n setTextLength(text.length);\n setIsEmpty(text.length === 0);\n }, [value]);\n\n return (\n <div\n className={cn(\n \"overflow-hidden rounded-md border border-input bg-background\",\n disabled && \"bg-muted/30 opacity-80\",\n className,\n )}\n >\n <div\n className={cn(\n \"flex items-center gap-0.5 border-b border-input bg-muted/40 px-1 py-1\",\n disabled && \"pointer-events-none opacity-60\",\n )}\n >\n {FORMAT_BUTTONS.map(({ command, icon: Icon, labelKey }) => (\n <Button\n key={command}\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 text-foreground hover:bg-accent\"\n aria-label={t(`ticket.create_dialog.formatting.${labelKey}`)}\n onMouseDown={handleToolbarMouseDown}\n onClick={() => applyFormat(command)}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n </Button>\n ))}\n <span className=\"mx-1 h-4 w-px bg-border\" />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 text-foreground hover:bg-accent\"\n aria-label={t(\"ticket.create_dialog.formatting.bullet_list\")}\n onMouseDown={handleToolbarMouseDown}\n onClick={() => applyFormat(\"insertUnorderedList\")}\n >\n <List className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 text-foreground hover:bg-accent\"\n aria-label={t(\"ticket.create_dialog.formatting.numbered_list\")}\n onMouseDown={handleToolbarMouseDown}\n onClick={() => applyFormat(\"insertOrderedList\")}\n >\n <ListOrdered className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n\n <div className=\"relative min-h-[140px]\">\n {isEmpty ? (\n <p className=\"pointer-events-none absolute start-3 top-2 text-sm text-muted-foreground\">\n {placeholder}\n </p>\n ) : null}\n <div\n ref={editorRef}\n contentEditable={!disabled}\n suppressContentEditableWarning\n role=\"textbox\"\n aria-multiline\n aria-readonly={disabled || undefined}\n className={cn(\n \"min-h-[140px] resize-y overflow-auto px-3 py-2 text-sm outline-none focus-visible:ring-0 [&_ol]:ms-5 [&_ol]:list-decimal [&_ul]:ms-5 [&_ul]:list-disc\",\n disabled && \"cursor-default select-text\",\n )}\n onInput={syncFromEditor}\n onBlur={() => {\n const snapshot = readEditor();\n setTextLength(snapshot.textLength);\n setIsEmpty(snapshot.textLength === 0);\n onChangeRef.current(snapshot.html, snapshot.textLength);\n onBlurCommitRef.current?.(snapshot.html, snapshot.textLength);\n }}\n onPaste={(e) => {\n e.preventDefault();\n const pasted = e.clipboardData.getData(\"text/plain\");\n const el = editorRef.current;\n if (!el) return;\n const remaining = maxLength - textLength;\n if (remaining <= 0) return;\n document.execCommand(\"insertText\", false, pasted.slice(0, remaining));\n syncFromEditor();\n }}\n onBeforeInput={(e) => {\n const el = editorRef.current;\n const native = e.nativeEvent;\n if (!el || !(native instanceof InputEvent)) return;\n const current = el.innerText.replace(/\\u00a0/g, \" \").trimEnd().length;\n const isDeletion =\n native.inputType.startsWith(\"delete\") ||\n native.inputType === \"historyUndo\";\n if (!isDeletion && current >= maxLength) {\n e.preventDefault();\n }\n }}\n />\n </div>\n\n <p className=\"px-3 py-1.5 text-xs text-muted-foreground\">\n {t(\"ticket.create_dialog.char_count\", {\n count: textLength,\n max: maxLength,\n })}\n </p>\n </div>\n );\n});\n","\"use client\";\n\nimport * as React from \"react\";\nimport Loader2 from \"lucide-react/dist/esm/icons/loader-2\";\nimport MoreHorizontal from \"lucide-react/dist/esm/icons/more-horizontal\";\nimport X from \"lucide-react/dist/esm/icons/x\";\nimport { useTranslation } from \"react-i18next\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\nimport type { TicketFormFields } from \"@/api/ticket\";\nimport type { TicketDetailDto } from \"@/api/dto/ticket.dto\";\nimport { TicketDeadlinePicker } from \"@/components/tickets/TicketDeadlinePicker\";\nimport { TicketEventSelect } from \"@/components/tickets/TicketEventSelect\";\nimport { SupportTicketTypeSelect } from \"@/components/tickets/SupportTicketTypeSelect\";\nimport { useLocalTicketAttachments } from \"@/hooks/useLocalTicketAttachments\";\nimport { useUserInfo } from \"@/hooks/useUserInfo\";\nimport { usePlanImagesUi } from \"@/components/tickets/PlanImagesReel\";\nimport {\n canSetSupportStaffCreateFields,\n isGuestUser,\n} from \"@/lib/auth/roles\";\nimport { Button } from \"@/components/ui/button\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport {\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@/components/ui/dialog\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\";\nimport { CreateTicketBufferedInput } from \"@/components/tickets/CreateTicketBufferedInput\";\nimport { TicketCreateSuccessOverlay } from \"@/components/tickets/TicketCreateSuccessOverlay\";\nimport {\n CREATE_TICKET_FIELD_IDS,\n CREATE_TICKET_FIELD_COLUMN,\n type CreateTicketFieldId,\n} from \"@/lib/tickets/createTicketFieldOrder\";\nimport {\n CREATE_DIALOG_VISIBILITY_FIELD_IDS,\n CREATE_TICKET_VISIBILITY_FIELD_IDS,\n DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS,\n type CreateTicketVisibilityFieldId,\n} from \"@/lib/tickets/createTicketFieldVisibility\";\nimport { type KeepOnAddFieldId } from \"@/lib/tickets/createTicketKeepFields\";\nimport { DEFAULT_SUPPORT_TICKET_PRIORITY_KEY, DEFAULT_SUPPORT_TICKET_TYPE_KEY } from \"@/lib/tickets/supportTicketTypes\";\nimport {\n TICKET_PRIORITY_KEYS,\n type TicketPriorityKey,\n type TicketStatusKey,\n MAX_TICKET_TITLE_LENGTH,\n MAX_TICKET_DESCRIPTION_LENGTH,\n} from \"@/lib/tickets/ticketRow\";\nimport { TicketResponsibleField } from \"@/components/tickets/TicketResponsibleField\";\nimport type { TicketAssignmentType } from \"@/components/tickets/TicketResponsibleField\";\nimport { useCreateTicket, useUpdateTicket } from \"@/hooks/useTickets\";\nimport { useTicket } from \"@/hooks/queries/use-ticket-detail\";\nimport {\n ticketAttachmentPreviewKeys,\n ticketCommentKeys,\n ticketKeys,\n} from \"@/hooks/queries/query-keys\";\nimport { persistReplacedTicketAttachment } from \"@/lib/tickets/persistEditedTicketAttachment\";\nimport { revokeEditorObjectUrls } from \"@/lib/tickets/ticketImageEditor\";\nimport { useCreateTicketFieldVisibility } from \"@/hooks/useCreateTicketFieldVisibility\";\nimport { useTicketSequences } from \"@/hooks/useTicketSequences\";\nimport { useTicketResponsibles } from \"@/hooks/useTicketResponsibles\";\nimport { getTicketResponsibleCatalogId } from \"@/lib/tickets/ticketResponsibleCatalog\";\nimport {\n getResponsibleEntryId,\n singleAssignmentType,\n toResponsibleWriteList,\n} from \"@/lib/tickets/ticketAssignment\";\nimport {\n buildCreateTicketFormSnapshot,\n createTicketFormSnapshotsEqual,\n hasMeaningfulCreateField,\n type CreateTicketFormSnapshot,\n type TicketCreateMeaningfulFields,\n} from \"@/lib/tickets/ticketCreateValidation\";\nimport { MAX_TICKET_ATTACHMENTS } from \"@/lib/tickets/ticketAttachments\";\nimport { cn } from \"@/lib/utils\";\n\nconst FIELD_LABEL_KEYS: Record<CreateTicketFieldId, string> = {\n short_description: \"ticket.create_dialog.short_text\",\n long_description: \"ticket.create_dialog.details\",\n attachments: \"ticket.create_dialog.attachments\",\n type: \"ticket.create_dialog.labels.type\",\n event: \"ticket.create_dialog.labels.event\",\n status: \"ticket.create_dialog.labels.status\",\n priority: \"ticket.create_dialog.labels.priority\",\n deadline: \"ticket.create_dialog.labels.deadline\",\n company: \"ticket.create_dialog.labels.company\",\n};\n\nconst DETAILS_MAX = MAX_TICKET_DESCRIPTION_LENGTH;\n\nconst TicketRichTextEditor = React.lazy(() =>\n import(\"@/components/tickets/TicketRichTextEditor\").then((mod) => ({\n default: mod.TicketRichTextEditor,\n })),\n);\n\nconst RichTextFallback = (\n <div className=\"min-h-[180px] animate-pulse rounded-md border border-input bg-muted/30\" />\n);\n\ntype CreateSubmitPhase =\n | { status: \"form\" }\n | { status: \"success\"; serial: string; keepAdding: boolean };\n\nfunction FloatingLabel({\n label,\n required = false,\n children,\n className,\n}: {\n label: string;\n required?: boolean;\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn(\"relative\", className)}>\n <span className=\"pointer-events-none absolute -top-2.5 start-3 z-10 bg-background px-1 text-xs text-theme-secondary\">\n {label}\n {required ? (\n <span className=\"text-destructive\" aria-hidden=\"true\">\n {\" \"}\n *\n </span>\n ) : null}\n </span>\n {children}\n </div>\n );\n}\n\nimport type { CreateTicketDialogProps } from \"@/components/tickets/create-ticket-dialog.types\";\n\nexport function CreateTicketDialog({\n open,\n onOpenChange,\n ticketId = null,\n allowKeepAdding = true,\n onSaved,\n}: CreateTicketDialogProps) {\n const isEdit = Boolean(ticketId);\n const projectId = \"support\";\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n const { userInfo } = useUserInfo();\n const { data: sequences = [], isLoading: sequencesLoading } =\n useTicketSequences();\n const { responsibles: ticketResponsibles = [], isLoading: usersLoading } =\n useTicketResponsibles();\n const { data: ticketDetail, isLoading: ticketDetailLoading } = useTicket(\n ticketId,\n { enabled: open && isEdit },\n );\n const [shortText, setShortText] = React.useState(\"\");\n const [details, setDetails] = React.useState(\"\");\n const shortTextRef = React.useRef(shortText);\n const detailsRef = React.useRef(details);\n const [typeKey, setTypeKey] = React.useState<string>(\n DEFAULT_SUPPORT_TICKET_TYPE_KEY,\n );\n const [eventId, setEventId] = React.useState<string>(\"\");\n const [statusKey, setStatusKey] = React.useState(\"open\");\n const [priorityKey, setPriorityKey] = React.useState<TicketPriorityKey | \"\">(\n DEFAULT_SUPPORT_TICKET_PRIORITY_KEY,\n );\n const [deadline, setDeadline] = React.useState(\"\");\n const [assignmentType, setAssignmentType] =\n React.useState<TicketAssignmentType>(singleAssignmentType());\n const [sequenceId, setSequenceId] = React.useState<string>(\"\");\n const [responsibleUserId, setResponsibleUserId] = React.useState(\"\");\n const [responsibleIds, setResponsibleIds] = React.useState<string[]>([]);\n const [hasDetailsText, setHasDetailsText] = React.useState(false);\n const [detailsRevision, setDetailsRevision] = React.useState(0);\n\n const setShortTextHot = React.useCallback((value: string) => {\n shortTextRef.current = value;\n React.startTransition(() => setShortText(value));\n }, []);\n const setDetailsHot = React.useCallback((html: string, textLength: number) => {\n detailsRef.current = html;\n setHasDetailsText((prev) => {\n const next = textLength > 0;\n return prev === next ? prev : next;\n });\n setDetailsRevision((revision) => revision + 1);\n }, []);\n const commitDetails = React.useCallback((html: string, textLength: number) => {\n detailsRef.current = html;\n setHasDetailsText(textLength > 0);\n setDetailsRevision((revision) => revision + 1);\n React.startTransition(() => setDetails(html));\n }, []);\n\n React.useLayoutEffect(() => {\n shortTextRef.current = shortText;\n }, [shortText]);\n React.useLayoutEffect(() => {\n detailsRef.current = details;\n }, [details]);\n const [existingAttachmentIds, setExistingAttachmentIds] = React.useState<\n string[]\n >([]);\n const {\n attachments,\n attachmentError,\n readyFiles,\n isProcessing: attachmentsProcessing,\n addFiles: addAttachmentFiles,\n removeAttachment,\n replaceAttachmentFile,\n appendReadyFile,\n clearAttachments,\n setAttachmentError,\n } = useLocalTicketAttachments({\n existingCount: existingAttachmentIds.length,\n });\n const [visibilityMenuOpen, setVisibilityMenuOpen] = React.useState(false);\n const {\n visibleFieldIds: persistedVisibleFieldIds,\n keepAdding,\n keepFieldIds: persistedKeepFieldIds,\n saveVisibleFieldIds: persistVisibleFieldIds,\n saveKeepAdding: persistKeepAdding,\n saveKeepFieldIds: persistKeepFieldIds,\n flushPendingSave: flushCreatePreferencesSave,\n } = useCreateTicketFieldVisibility(projectId, {\n enabled: !isEdit,\n });\n\n const visibleFieldIds = React.useMemo(() => {\n if (isEdit) return new Set(CREATE_TICKET_VISIBILITY_FIELD_IDS);\n const ids =\n persistedVisibleFieldIds.length > 0\n ? persistedVisibleFieldIds\n : DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS;\n return new Set(ids);\n }, [isEdit, persistedVisibleFieldIds]);\n\n const keepFields = React.useMemo(\n () => new Set(persistedKeepFieldIds),\n [persistedKeepFieldIds],\n );\n\n React.useEffect(() => {\n if (open) return;\n flushCreatePreferencesSave();\n }, [open, flushCreatePreferencesSave]);\n\n const canChooseAssignment = canSetSupportStaffCreateFields(userInfo);\n const canSetStaffFields = canChooseAssignment;\n const isGuest = isGuestUser(userInfo);\n\n const activeVisibleFieldIds = React.useMemo(() => {\n const next = new Set<CreateTicketVisibilityFieldId>(visibleFieldIds);\n if (isEdit) next.add(\"status\");\n else next.delete(\"status\");\n if (!canSetStaffFields) {\n next.delete(\"deadline\");\n next.delete(\"company\");\n }\n return next;\n }, [canSetStaffFields, isEdit, visibleFieldIds]);\n\n const responsibleUsers = React.useMemo(\n () =>\n [...ticketResponsibles]\n .filter(\n (responsible) =>\n Boolean(responsible.userId) || responsible.kind === \"user\",\n )\n .sort((a, b) =>\n (a.name ?? \"\").localeCompare(b.name ?? \"\", undefined, {\n sensitivity: \"base\",\n }),\n ),\n [ticketResponsibles],\n );\n\n const totalAttachmentCount =\n existingAttachmentIds.length + attachments.length;\n const atAttachmentLimit = totalAttachmentCount >= MAX_TICKET_ATTACHMENTS;\n const [submitError, setSubmitError] = React.useState<string | null>(null);\n const [createSubmitPhase, setCreateSubmitPhase] =\n React.useState<CreateSubmitPhase>({ status: \"form\" });\n const [keepAddingBaseline, setKeepAddingBaseline] =\n React.useState<CreateTicketFormSnapshot | null>(null);\n const [keepBaselineEpoch, setKeepBaselineEpoch] = React.useState(0);\n\n const keepMenuFieldIds = React.useMemo(\n (): CreateTicketVisibilityFieldId[] =>\n CREATE_DIALOG_VISIBILITY_FIELD_IDS.filter((fieldId) =>\n activeVisibleFieldIds.has(fieldId),\n ),\n [activeVisibleFieldIds],\n );\n\n React.useEffect(() => {\n if (isEdit) return;\n const next = persistedKeepFieldIds.filter(\n (fieldId) =>\n fieldId === \"status\" ||\n activeVisibleFieldIds.has(fieldId as CreateTicketVisibilityFieldId),\n );\n if (\n next.length === persistedKeepFieldIds.length &&\n persistedKeepFieldIds.every((fieldId) => next.includes(fieldId))\n ) {\n return;\n }\n persistKeepFieldIds(next);\n }, [\n activeVisibleFieldIds,\n isEdit,\n persistKeepFieldIds,\n persistedKeepFieldIds,\n ]);\n\n const shortTextInputRef = React.useRef<HTMLInputElement>(null);\n const createTicketMutation = useCreateTicket();\n const updateTicketMutation = useUpdateTicket();\n const isSaving =\n createTicketMutation.isPending || updateTicketMutation.isPending;\n\n const setDetailsExternal = React.useCallback((html: string) => {\n detailsRef.current = html;\n const textLength = html\n .replace(/<[^>]*>/g, \" \")\n .replace(/&nbsp;/gi, \" \")\n .trim().length;\n setHasDetailsText(textLength > 0);\n setDetails(html);\n }, []);\n\n const resetForm = React.useCallback(() => {\n setShortText(\"\");\n setDetailsExternal(\"\");\n setTypeKey(DEFAULT_SUPPORT_TICKET_TYPE_KEY);\n setEventId(\"\");\n setStatusKey(\"open\");\n setPriorityKey(DEFAULT_SUPPORT_TICKET_PRIORITY_KEY);\n setDeadline(\"\");\n setAssignmentType(singleAssignmentType());\n setSequenceId(\"\");\n setResponsibleUserId(\"\");\n setResponsibleIds([]);\n clearAttachments();\n setExistingAttachmentIds([]);\n setSubmitError(null);\n setKeepAddingBaseline(null);\n setKeepBaselineEpoch(0);\n setDetailsRevision(0);\n }, [clearAttachments, setDetailsExternal]);\n\n const resetFormForNextTicket = React.useCallback(\n (fieldsToKeep: Set<KeepOnAddFieldId>) => {\n if (!fieldsToKeep.has(\"short_description\")) setShortText(\"\");\n if (!fieldsToKeep.has(\"long_description\")) setDetailsExternal(\"\");\n if (!fieldsToKeep.has(\"attachments\")) clearAttachments();\n if (!fieldsToKeep.has(\"type\")) setTypeKey(DEFAULT_SUPPORT_TICKET_TYPE_KEY);\n if (!fieldsToKeep.has(\"event\")) setEventId(\"\");\n if (!fieldsToKeep.has(\"status\")) setStatusKey(\"open\");\n if (!fieldsToKeep.has(\"priority\"))\n setPriorityKey(DEFAULT_SUPPORT_TICKET_PRIORITY_KEY);\n if (!fieldsToKeep.has(\"deadline\")) setDeadline(\"\");\n if (!fieldsToKeep.has(\"company\")) {\n setAssignmentType(singleAssignmentType());\n setSequenceId(\"\");\n setResponsibleUserId(\"\");\n setResponsibleIds([]);\n }\n setSubmitError(null);\n },\n [clearAttachments, setDetailsExternal],\n );\n\n const toggleKeepField = React.useCallback(\n (fieldId: KeepOnAddFieldId) => {\n const next = new Set(keepFields);\n if (next.has(fieldId)) next.delete(fieldId);\n else next.add(fieldId);\n persistKeepFieldIds(next);\n },\n [keepFields, persistKeepFieldIds],\n );\n\n const applyTicketDetail = React.useCallback(\n (detail: TicketDetailDto) => {\n setShortText(detail.shortText);\n setDetailsExternal(detail.longDescriptionHtml ?? \"\");\n setTypeKey(detail.typeKey ?? \"\");\n setEventId(detail.eventId ?? \"\");\n setStatusKey(detail.statusKey);\n setPriorityKey(detail.priority ?? \"\");\n setDeadline(detail.deadline ?? \"\");\n setAssignmentType(\n detail.assignmentType === \"sequence\"\n ? \"sequence\"\n : detail.assignmentType === \"multi\"\n ? \"multi\"\n : singleAssignmentType(),\n );\n setSequenceId(detail.sequenceId ?? \"\");\n setResponsibleUserId(detail.responsibleUserId ?? \"\");\n setResponsibleIds(\n detail.assignmentType === \"multi\" && detail.responsibles?.length\n ? detail.responsibles\n .map((entry) => getResponsibleEntryId(entry))\n .filter((id): id is string => Boolean(id))\n : [],\n );\n setExistingAttachmentIds(detail.attachmentFileIds ?? []);\n clearAttachments();\n },\n [clearAttachments, setDetailsExternal],\n );\n\n const appliedEditTicketIdRef = React.useRef<string | null>(null);\n\n React.useEffect(() => {\n if (!open) {\n resetForm();\n setVisibilityMenuOpen(false);\n setCreateSubmitPhase({ status: \"form\" });\n appliedEditTicketIdRef.current = null;\n }\n }, [open, resetForm]);\n\n const createSubmitPhaseRef = React.useRef(createSubmitPhase);\n React.useLayoutEffect(() => {\n createSubmitPhaseRef.current = createSubmitPhase;\n }, [createSubmitPhase]);\n\n const handleCreateSuccessComplete = React.useCallback(() => {\n const phase = createSubmitPhaseRef.current;\n if (phase.status !== \"success\") return;\n\n if (phase.keepAdding) {\n resetFormForNextTicket(keepFields);\n setKeepBaselineEpoch((epoch) => epoch + 1);\n setCreateSubmitPhase({ status: \"form\" });\n requestAnimationFrame(() => shortTextInputRef.current?.focus());\n return;\n }\n\n setCreateSubmitPhase({ status: \"form\" });\n onOpenChange(false);\n onSaved?.();\n }, [keepFields, onOpenChange, onSaved, resetFormForNextTicket]);\n\n React.useLayoutEffect(() => {\n if (keepBaselineEpoch === 0) return;\n setKeepAddingBaseline(\n buildCreateTicketFormSnapshot({\n shortDescription: shortText,\n longDescriptionHtml: details,\n typeKey,\n eventId,\n priorityKey,\n deadline,\n assignmentType,\n sequenceId,\n responsibleUserId,\n responsibleIds,\n localAttachmentIds: attachments.map((attachment) => attachment.id),\n existingAttachmentIds,\n }),\n );\n // Capture post keep-adding form only when epoch bumps (batched with reset).\n // eslint-disable-next-line react-hooks/exhaustive-deps -- intentional epoch gate\n }, [keepBaselineEpoch]);\n\n React.useEffect(() => {\n if (!open || !isEdit || !ticketDetail) return;\n if (appliedEditTicketIdRef.current === ticketDetail.id) return;\n appliedEditTicketIdRef.current = ticketDetail.id;\n applyTicketDetail(ticketDetail);\n }, [open, isEdit, ticketDetail, applyTicketDetail]);\n\n const removeExistingAttachment = React.useCallback((fileId: string) => {\n setExistingAttachmentIds((prev) => prev.filter((id) => id !== fileId));\n setAttachmentError(null);\n }, [setAttachmentError]);\n\n const replaceExistingAttachmentImage = React.useCallback(\n async (fileId: string, file: File) => {\n if (!isEdit || !ticketId || !ticketDetail) {\n setExistingAttachmentIds((prev) => prev.filter((id) => id !== fileId));\n appendReadyFile(file);\n return;\n }\n\n setSubmitError(null);\n try {\n const updated = await persistReplacedTicketAttachment({\n ticketId,\n statusKey: ticketDetail.statusKey,\n existingAttachmentIds,\n replacedFileId: fileId,\n file,\n });\n\n setExistingAttachmentIds(updated.attachmentFileIds ?? []);\n\n queryClient.setQueryData(\n ticketKeys.detail(ticketId),\n (previous: TicketDetailDto | undefined) =>\n previous\n ? {\n ...previous,\n attachmentFileIds: updated.attachmentFileIds ?? [],\n }\n : updated,\n );\n void queryClient.invalidateQueries({ queryKey: ticketKeys.all });\n void queryClient.invalidateQueries({\n queryKey: ticketAttachmentPreviewKeys.all,\n });\n void queryClient.invalidateQueries({\n queryKey: ticketCommentKeys.byTicketRoot(ticketId),\n });\n revokeEditorObjectUrls([fileId]);\n } catch (error) {\n setSubmitError(t(\"ticket.image_editor.persist_failed\"));\n throw error;\n }\n },\n [\n appendReadyFile,\n existingAttachmentIds,\n isEdit,\n queryClient,\n t,\n ticketDetail,\n ticketId,\n ],\n );\n\n const deferredShortText = React.useDeferredValue(shortText);\n const deferredHasDetailsText = React.useDeferredValue(hasDetailsText);\n\n const canSubmitCreate = React.useMemo(() => {\n if (attachmentsProcessing) {\n return false;\n }\n if (isEdit) return true;\n const useSequence =\n canChooseAssignment && !isGuest && assignmentType === \"sequence\";\n const useMulti =\n canChooseAssignment && !isGuest && assignmentType === \"multi\";\n const hasMeaningful = hasMeaningfulCreateField(\n {\n shortDescription: deferredShortText.trim(),\n longDescriptionHtml: deferredHasDetailsText\n ? detailsRef.current\n : \"\",\n typeKey: typeKey || undefined,\n eventId: eventId || undefined,\n sequenceId: useSequence ? sequenceId || undefined : undefined,\n responsibleUserId:\n !useSequence && !useMulti ? responsibleUserId || undefined : undefined,\n responsibleIds: useMulti ? responsibleIds : undefined,\n deadline: deadline || undefined,\n },\n attachments.length,\n { countAssignment: canChooseAssignment && !isGuest },\n );\n if (!hasMeaningful) return false;\n if (\n keepAdding &&\n keepAddingBaseline &&\n createTicketFormSnapshotsEqual(\n buildCreateTicketFormSnapshot({\n shortDescription: shortText,\n longDescriptionHtml: detailsRef.current,\n typeKey,\n eventId,\n priorityKey,\n deadline,\n assignmentType,\n sequenceId,\n responsibleUserId,\n responsibleIds,\n localAttachmentIds: attachments.map((attachment) => attachment.id),\n existingAttachmentIds,\n }),\n keepAddingBaseline,\n )\n ) {\n return false;\n }\n return true;\n }, [\n assignmentType,\n attachments,\n attachmentsProcessing,\n canChooseAssignment,\n canSetStaffFields,\n deadline,\n deferredHasDetailsText,\n deferredShortText,\n detailsRevision,\n eventId,\n existingAttachmentIds,\n isEdit,\n isGuest,\n keepAdding,\n keepAddingBaseline,\n priorityKey,\n responsibleIds,\n responsibleUserId,\n sequenceId,\n shortText,\n typeKey,\n ]);\n\n const handleSubmit = React.useCallback(async () => {\n setSubmitError(null);\n\n if (attachmentsProcessing) {\n return;\n }\n\n const trimmedShort = shortTextRef.current.trim();\n if (isEdit && !trimmedShort) {\n setSubmitError(t(\"ticket.create_dialog.short_text_required\"));\n return;\n }\n if (trimmedShort.length > MAX_TICKET_TITLE_LENGTH) {\n setSubmitError(\n t(\"ticket.create_dialog.short_text_too_long\", {\n max: MAX_TICKET_TITLE_LENGTH,\n }),\n );\n return;\n }\n\n const useSequence =\n !isEdit && canChooseAssignment && !isGuest && assignmentType === \"sequence\";\n const useMulti =\n !isEdit && canChooseAssignment && !isGuest && assignmentType === \"multi\";\n const isSequenceEdit =\n isEdit && ticketDetail?.assignmentType === \"sequence\";\n const isMultiEdit = isEdit && ticketDetail?.assignmentType === \"multi\";\n const omitResponsibleUserId =\n useSequence || useMulti || isSequenceEdit || isMultiEdit;\n\n if (!isEdit) {\n if (useMulti && responsibleIds.length < 2) {\n setSubmitError(t(\"ticket.sequence.multi_required\"));\n return;\n }\n if (useSequence && !sequenceId.trim()) {\n setSubmitError(t(\"ticket.sequence.sequence_required\"));\n return;\n }\n const detailsHtml = detailsRef.current;\n const meaningfulFields: TicketCreateMeaningfulFields = {\n shortDescription: trimmedShort || undefined,\n longDescriptionHtml: detailsHtml,\n typeKey: typeKey || undefined,\n eventId: eventId || undefined,\n sequenceId: useSequence ? sequenceId || undefined : undefined,\n responsibleUserId:\n !useSequence && !useMulti ? responsibleUserId || undefined : undefined,\n responsibleIds: useMulti ? responsibleIds : undefined,\n deadline: deadline || undefined,\n };\n if (\n !hasMeaningfulCreateField(meaningfulFields, attachments.length, {\n countAssignment: canChooseAssignment && !isGuest,\n })\n ) {\n setSubmitError(t(\"ticket.create_dialog.meaningful_field_required\"));\n return;\n }\n if (\n keepAdding &&\n keepAddingBaseline &&\n createTicketFormSnapshotsEqual(\n buildCreateTicketFormSnapshot({\n shortDescription: trimmedShort,\n longDescriptionHtml: detailsHtml,\n typeKey,\n eventId,\n priorityKey,\n deadline,\n assignmentType,\n sequenceId,\n responsibleUserId,\n responsibleIds,\n localAttachmentIds: attachments.map((attachment) => attachment.id),\n existingAttachmentIds,\n }),\n keepAddingBaseline,\n )\n ) {\n return;\n }\n }\n\n const clearFields: string[] = [];\n if (isEdit && ticketDetail) {\n if (!typeKey.trim() && ticketDetail.typeKey) clearFields.push(\"typeKey\");\n if (!eventId.trim() && ticketDetail.eventId) clearFields.push(\"eventId\");\n if (!priorityKey && ticketDetail.priority) clearFields.push(\"priority\");\n if (\n canChooseAssignment &&\n !isSequenceEdit &&\n !isMultiEdit &&\n !responsibleUserId.trim() &&\n ticketDetail.responsibleUserId\n ) {\n clearFields.push(\"responsibleUserId\");\n }\n }\n\n const fields: TicketFormFields = {\n shortDescription: isEdit ? trimmedShort : trimmedShort || undefined,\n longDescriptionHtml: detailsRef.current.trim() || null,\n typeKey: isEdit ? typeKey : typeKey || null,\n eventId: isEdit ? eventId : eventId || null,\n statusKey:\n useSequence || useMulti ? \"open\" : (statusKey as TicketStatusKey),\n priority: priorityKey || (isEdit ? \"\" : undefined),\n deadline: canSetStaffFields ? deadline || null : null,\n assignmentType:\n useSequence || isSequenceEdit\n ? \"sequence\"\n : useMulti || isMultiEdit\n ? \"multi\"\n : \"single\",\n sequenceId: useSequence ? sequenceId : null,\n responsibleUserId: omitResponsibleUserId\n ? null\n : canChooseAssignment\n ? responsibleUserId || null\n : null,\n responsibles: useMulti ? toResponsibleWriteList(responsibleIds) : null,\n existingAttachmentIds: isEdit ? existingAttachmentIds : undefined,\n clearFields: clearFields.length ? clearFields : undefined,\n };\n\n try {\n if (isEdit && ticketId) {\n await updateTicketMutation.mutateAsync({\n ticketId,\n fields,\n images: readyFiles,\n });\n } else {\n const created = await createTicketMutation.mutateAsync({\n fields,\n images: readyFiles,\n });\n\n setCreateSubmitPhase({\n status: \"success\",\n serial: created.serial,\n keepAdding: Boolean(allowKeepAdding && keepAdding),\n });\n return;\n }\n\n onOpenChange(false);\n onSaved?.();\n } catch {\n setSubmitError(\n isEdit\n ? t(\"ticket.edit_dialog.save_failed\")\n : t(\"ticket.create_dialog.create_failed\"),\n );\n }\n }, [\n allowKeepAdding,\n assignmentType,\n attachments,\n attachmentsProcessing,\n canChooseAssignment,\n createTicketMutation,\n canSetStaffFields,\n deadline,\n eventId,\n existingAttachmentIds,\n isEdit,\n isGuest,\n keepAdding,\n keepAddingBaseline,\n onOpenChange,\n onSaved,\n priorityKey,\n readyFiles,\n responsibleIds,\n responsibleUserId,\n sequenceId,\n statusKey,\n t,\n ticketDetail,\n ticketId,\n typeKey,\n updateTicketMutation,\n ]);\n\n const getFieldLabel = React.useCallback(\n (fieldId: CreateTicketFieldId) => t(FIELD_LABEL_KEYS[fieldId]),\n [t],\n );\n\n const getVisibilityFieldLabel = React.useCallback(\n (fieldId: CreateTicketVisibilityFieldId) => {\n if (fieldId === \"attachments\") {\n return t(\"ticket.create_dialog.attachments_add\");\n }\n return getFieldLabel(fieldId);\n },\n [getFieldLabel, t],\n );\n\n const clearHiddenFieldValue = React.useCallback(\n (fieldId: CreateTicketVisibilityFieldId) => {\n switch (fieldId) {\n case \"long_description\":\n setDetailsExternal(\"\");\n break;\n case \"attachments\":\n setExistingAttachmentIds([]);\n clearAttachments();\n break;\n case \"type\":\n setTypeKey(\"\");\n break;\n case \"event\":\n setEventId(\"\");\n break;\n case \"status\":\n setStatusKey(\"open\");\n break;\n case \"priority\":\n setPriorityKey(\"\");\n break;\n case \"deadline\":\n setDeadline(\"\");\n break;\n case \"short_description\":\n case \"company\":\n break;\n }\n },\n [clearAttachments, setDetailsExternal],\n );\n\n const toggleFieldVisibility = React.useCallback(\n (fieldId: CreateTicketVisibilityFieldId) => {\n if (isEdit) return;\n const next = new Set(visibleFieldIds);\n if (next.has(fieldId)) {\n next.delete(fieldId);\n clearHiddenFieldValue(fieldId);\n } else {\n next.add(fieldId);\n }\n persistVisibleFieldIds(next);\n },\n [clearHiddenFieldValue, isEdit, persistVisibleFieldIds, visibleFieldIds],\n );\n\n const renderField = React.useCallback(\n (fieldId: CreateTicketFieldId) => {\n switch (fieldId) {\n case \"short_description\":\n return (\n <FloatingLabel required={isEdit} label={getFieldLabel(fieldId)}>\n <CreateTicketBufferedInput\n ref={shortTextInputRef}\n value={shortText}\n onChange={setShortTextHot}\n placeholder={t(\"ticket.create_dialog.short_text_placeholder\")}\n className=\"h-10 pt-1\"\n maxLength={MAX_TICKET_TITLE_LENGTH}\n required={isEdit}\n aria-required={isEdit}\n />\n </FloatingLabel>\n );\n case \"long_description\":\n return (\n <FloatingLabel label={getFieldLabel(fieldId)}>\n <React.Suspense fallback={RichTextFallback}>\n <TicketRichTextEditor\n value={details}\n onChange={setDetailsHot}\n onBlurCommit={commitDetails}\n maxLength={DETAILS_MAX}\n placeholder={t(\"ticket.create_dialog.details_placeholder\")}\n />\n </React.Suspense>\n </FloatingLabel>\n );\n case \"attachments\":\n return null;\n case \"type\":\n return (\n <FloatingLabel label={getFieldLabel(fieldId)}>\n <SupportTicketTypeSelect\n value={typeKey}\n onChange={setTypeKey}\n placeholder={t(\"ticket.create_dialog.select_placeholder\")}\n />\n </FloatingLabel>\n );\n case \"event\":\n return (\n <FloatingLabel label={getFieldLabel(fieldId)}>\n <TicketEventSelect\n value={eventId}\n onChange={setEventId}\n />\n </FloatingLabel>\n );\n case \"status\":\n return (\n <FloatingLabel label={getFieldLabel(fieldId)}>\n <Select value={statusKey} onValueChange={setStatusKey}>\n <SelectTrigger className=\"h-10\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"open\">\n {t(\"ticket.create_dialog.status.open\")}\n </SelectItem>\n <SelectItem value=\"in_work\">\n {t(\"ticket.create_dialog.status.in_work\")}\n </SelectItem>\n <SelectItem value=\"resolved\">\n {t(\"ticket.create_dialog.status.resolved\")}\n </SelectItem>\n <SelectItem value=\"done\">\n {t(\"ticket.create_dialog.status.done\")}\n </SelectItem>\n </SelectContent>\n </Select>\n </FloatingLabel>\n );\n case \"priority\":\n return (\n <FloatingLabel label={getFieldLabel(fieldId)}>\n <div className=\"flex h-10 items-center rounded-md border border-input pe-1\">\n <Select\n value={priorityKey}\n onValueChange={(value) =>\n setPriorityKey(value as TicketPriorityKey)\n }\n >\n <SelectTrigger className=\"h-9 flex-1 border-0 shadow-none focus:ring-0\">\n <SelectValue\n placeholder={t(\"ticket.create_dialog.select_placeholder\")}\n />\n </SelectTrigger>\n <SelectContent>\n {TICKET_PRIORITY_KEYS.map((key) => (\n <SelectItem key={key} value={key}>\n {t(`ticket.table.priority.${key}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {priorityKey ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0\"\n aria-label={t(\"ticket.create_dialog.priority_clear\")}\n onClick={() => setPriorityKey(\"\")}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n ) : null}\n </div>\n </FloatingLabel>\n );\n case \"deadline\":\n return (\n <FloatingLabel label={getFieldLabel(fieldId)}>\n <TicketDeadlinePicker value={deadline} onChange={setDeadline} />\n </FloatingLabel>\n );\n case \"company\": {\n const lockedAssignment =\n isEdit &&\n (ticketDetail?.assignmentType === \"sequence\" ||\n ticketDetail?.assignmentType === \"multi\");\n const resolvedAssignmentType: TicketAssignmentType = lockedAssignment\n ? ticketDetail?.assignmentType === \"multi\"\n ? \"multi\"\n : \"sequence\"\n : assignmentType;\n return (\n <div className=\"space-y-5\">\n <TicketResponsibleField\n assignmentType={resolvedAssignmentType}\n onAssignmentTypeChange={\n !isEdit && canChooseAssignment && !isGuest\n ? (type) => {\n setAssignmentType(type);\n if (type === \"multi\") {\n setResponsibleUserId(\"\");\n setSequenceId(\"\");\n } else if (type === \"sequence\") {\n setResponsibleUserId(\"\");\n setResponsibleIds([]);\n } else {\n setSequenceId(\"\");\n setResponsibleIds([]);\n }\n }\n : undefined\n }\n sequenceId={sequenceId}\n onSequenceIdChange={setSequenceId}\n responsibleUserId={responsibleUserId}\n onResponsibleUserIdChange={setResponsibleUserId}\n responsibleIds={responsibleIds}\n onResponsibleIdsChange={setResponsibleIds}\n responsibleEntries={\n lockedAssignment && ticketDetail?.assignmentType === \"multi\"\n ? ticketDetail.responsibles\n : null\n }\n canChooseAssignment={\n canChooseAssignment && !isGuest && !lockedAssignment\n }\n readOnly={lockedAssignment}\n sequences={sequences}\n users={responsibleUsers}\n catalogResponsibles={ticketResponsibles}\n sequencesLoading={sequencesLoading}\n usersLoading={usersLoading}\n sequenceName={ticketDetail?.sequenceName}\n sequenceStepNumber={ticketDetail?.sequenceStepNumber}\n sequenceStepCount={ticketDetail?.sequenceStepCount}\n currentUserName={\n ticketDetail?.responsibleUserName ??\n responsibleUsers.find(\n (user) =>\n getTicketResponsibleCatalogId(user) === responsibleUserId,\n )?.name ??\n null\n }\n />\n </div>\n );\n }\n default:\n return null;\n }\n },\n [\n assignmentType,\n canChooseAssignment,\n commitDetails,\n deadline,\n details,\n eventId,\n getFieldLabel,\n isEdit,\n isGuest,\n priorityKey,\n responsibleIds,\n responsibleUserId,\n responsibleUsers,\n sequenceId,\n sequences,\n sequencesLoading,\n setDetailsHot,\n setShortTextHot,\n shortText,\n statusKey,\n t,\n ticketDetail?.assignmentType,\n ticketDetail?.responsibleUserName,\n ticketDetail?.responsibles,\n ticketDetail?.sequenceName,\n ticketDetail?.sequenceStepCount,\n ticketDetail?.sequenceStepNumber,\n ticketResponsibles,\n typeKey,\n usersLoading,\n ],\n );\n\n const leftFieldIds = React.useMemo(\n () =>\n CREATE_TICKET_FIELD_IDS.filter(\n (id) =>\n id !== \"attachments\" &&\n activeVisibleFieldIds.has(id) &&\n CREATE_TICKET_FIELD_COLUMN[id] === \"left\",\n ),\n [activeVisibleFieldIds],\n );\n\n const rightFieldIds = React.useMemo(\n () =>\n CREATE_TICKET_FIELD_IDS.filter(\n (id) =>\n activeVisibleFieldIds.has(id) &&\n CREATE_TICKET_FIELD_COLUMN[id] === \"right\",\n ),\n [activeVisibleFieldIds],\n );\n\n const generalAttachmentPool = React.useMemo(\n () => ({\n existingIds: existingAttachmentIds,\n items: attachments,\n onRemoveLocal: removeAttachment,\n onRemoveExisting: removeExistingAttachment,\n onReplaceLocal: replaceAttachmentFile,\n onReplaceExisting: replaceExistingAttachmentImage,\n }),\n [\n attachments,\n existingAttachmentIds,\n removeAttachment,\n removeExistingAttachment,\n replaceAttachmentFile,\n replaceExistingAttachmentImage,\n ],\n );\n\n const { generalReel } = usePlanImagesUi({\n disabled: isSaving,\n atLimit: atAttachmentLimit,\n processing: attachmentsProcessing,\n generalError: attachmentError,\n general: generalAttachmentPool,\n onAddFiles: addAttachmentFiles,\n });\n\n const attachmentsField = generalReel;\n\n return (\n <Dialog\n open={open}\n onOpenChange={(nextOpen) => {\n if (!nextOpen && createSubmitPhase.status === \"success\") {\n const shouldNotifySaved = !createSubmitPhase.keepAdding;\n setCreateSubmitPhase({ status: \"form\" });\n onOpenChange(false);\n if (shouldNotifySaved) onSaved?.();\n return;\n }\n onOpenChange(nextOpen);\n }}\n >\n <DialogContent\n size=\"full\"\n className=\"max-w-[calc(96rem-19rem-1.5rem)] gap-0 overflow-hidden p-0 sm:rounded-xl\"\n onPointerDownOutside={(event) => event.preventDefault()}\n >\n <div className=\"relative flex min-h-0 flex-1 flex-col overflow-hidden\">\n <TicketCreateSuccessOverlay\n open={createSubmitPhase.status === \"success\"}\n serial={\n createSubmitPhase.status === \"success\"\n ? createSubmitPhase.serial\n : null\n }\n onComplete={handleCreateSuccessComplete}\n />\n <DialogHeader className=\"shrink-0 border-b border-border px-6 py-4\">\n <div className=\"flex flex-wrap items-center gap-2 pe-8\">\n <DialogTitle className=\"text-theme-primary\">\n {isEdit\n ? t(\"ticket.edit_dialog.title\", {\n serial: ticketDetail?.serial ?? \"\",\n })\n : t(\"ticket.create_dialog.title\")}\n </DialogTitle>\n {!isEdit ? (\n <Popover\n open={visibilityMenuOpen}\n onOpenChange={setVisibilityMenuOpen}\n >\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant={visibilityMenuOpen ? \"default\" : \"outline\"}\n size=\"sm\"\n className=\"h-7 text-xs\"\n >\n {t(\"ticket.create_dialog.reorder_fields\")}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"z-[120] w-64 p-2\"\n onOpenAutoFocus={(event) => event.preventDefault()}\n >\n <p className=\"px-2 pb-1.5 text-xs text-muted-foreground\">\n {t(\"ticket.create_dialog.reorder_hint\")}\n </p>\n <div className=\"max-h-72 space-y-0.5 overflow-y-auto\">\n {CREATE_DIALOG_VISIBILITY_FIELD_IDS.filter((fieldId) => {\n if (\n !canSetStaffFields &&\n (fieldId === \"deadline\" || fieldId === \"company\")\n ) {\n return false;\n }\n return true;\n }).map((fieldId) => (\n <label\n key={fieldId}\n className=\"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 hover:bg-accent\"\n >\n <Checkbox\n checked={activeVisibleFieldIds.has(fieldId)}\n onCheckedChange={() => toggleFieldVisibility(fieldId)}\n />\n <span className=\"text-sm leading-tight\">\n {getVisibilityFieldLabel(fieldId)}\n </span>\n </label>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n ) : null}\n </div>\n </DialogHeader>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain\">\n {isEdit && ticketDetailLoading ? (\n <div className=\"flex items-center justify-center gap-2 py-16 text-sm text-muted-foreground\">\n <Loader2 className=\"h-5 w-5 animate-spin\" aria-hidden />\n {t(\"ticket.edit_dialog.loading\")}\n </div>\n ) : (\n <div className=\"space-y-6 px-6 py-5 pb-6\">\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1fr)_17rem] lg:items-start\">\n <div className=\"space-y-5\">\n {leftFieldIds.map((fieldId) => (\n <React.Fragment key={fieldId}>\n <div>{renderField(fieldId)}</div>\n {fieldId === \"long_description\" ? (\n <div className=\"space-y-3\">\n {activeVisibleFieldIds.has(\"attachments\")\n ? attachmentsField\n : null}\n </div>\n ) : null}\n </React.Fragment>\n ))}\n {!activeVisibleFieldIds.has(\"long_description\") ? (\n <div className=\"space-y-3\">\n {activeVisibleFieldIds.has(\"attachments\")\n ? attachmentsField\n : null}\n </div>\n ) : null}\n </div>\n <div className=\"space-y-4\">\n {rightFieldIds.map((fieldId) => (\n <div key={fieldId}>{renderField(fieldId)}</div>\n ))}\n </div>\n </div>\n </div>\n )}\n </div>\n\n {!(isEdit && ticketDetailLoading) ? (\n <DialogFooter className=\"shrink-0 flex-col gap-3 border-t border-border px-6 py-4 sm:flex-col\">\n {submitError ? (\n <p className=\"w-full text-sm text-destructive\">{submitError}</p>\n ) : null}\n <div className=\"relative flex w-full flex-wrap items-center justify-between gap-3\">\n {!isEdit && allowKeepAdding ? (\n <div className=\"flex items-center gap-0.5\">\n <label className=\"flex cursor-pointer items-center gap-2 rounded-md px-1 py-1\">\n <Checkbox\n checked={keepAdding}\n onCheckedChange={(checked) => {\n const next = checked === true;\n persistKeepAdding(next);\n if (!next) {\n setKeepAddingBaseline(null);\n setKeepBaselineEpoch(0);\n }\n }}\n />\n <span className=\"text-sm text-foreground\">\n {t(\"ticket.create_dialog.keep_adding\")}\n </span>\n </label>\n <Popover>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8 shrink-0\"\n disabled={!keepAdding}\n aria-label={t(\n \"ticket.create_dialog.keep_fields_menu\",\n )}\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n side=\"top\"\n className=\"z-[120] w-52 p-2\"\n >\n <p className=\"px-2 pb-1.5 text-xs text-muted-foreground\">\n {t(\"ticket.create_dialog.keep_fields_hint\")}\n </p>\n <div className=\"max-h-52 space-y-0.5 overflow-y-auto\">\n {keepMenuFieldIds.map((fieldId) => (\n <label\n key={fieldId}\n className=\"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 hover:bg-accent\"\n >\n <Checkbox\n checked={keepFields.has(fieldId)}\n onCheckedChange={() => toggleKeepField(fieldId)}\n />\n <span className=\"text-sm leading-tight\">\n {getVisibilityFieldLabel(fieldId)}\n </span>\n </label>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n ) : (\n <span />\n )}\n <div className=\"flex items-center gap-2 ms-auto\">\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={isSaving}\n onClick={() => onOpenChange(false)}\n >\n {t(\"cancel\")}\n </Button>\n <Button\n type=\"button\"\n disabled={isSaving || !canSubmitCreate}\n onClick={() => void handleSubmit()}\n >\n {isSaving ? (\n <>\n <Loader2\n className=\"me-2 h-4 w-4 animate-spin\"\n aria-hidden\n />\n {isEdit\n ? t(\"ticket.edit_dialog.saving\")\n : t(\"ticket.create_dialog.creating\")}\n </>\n ) : (\n t(\"common.save\")\n )}\n </Button>\n </div>\n </div>\n </DialogFooter>\n ) : null}\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { format, startOfToday } from \"date-fns\";\nimport CalendarIcon from \"lucide-react/dist/esm/icons/calendar\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Calendar } from \"@/components/ui/calendar\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { useUserSettings } from \"@/hooks/useUserSettings\";\nimport {\n formatUserDateForPicker,\n getUserDateFnsLocale,\n parseUserIsoDate,\n} from \"@/lib/date-utils\";\nimport { cn } from \"@/lib/utils\";\n\ntype TicketDeadlinePickerProps = {\n value: string;\n onChange: (value: string) => void;\n disabled?: boolean;\n className?: string;\n placeholder?: string;\n disablePastDates?: boolean;\n};\n\nexport const TicketDeadlinePicker = React.memo(function TicketDeadlinePicker({\n value,\n onChange,\n disabled = false,\n className,\n placeholder,\n disablePastDates = true,\n}: TicketDeadlinePickerProps) {\n const { t, i18n } = useTranslation();\n const { userSettings } = useUserSettings(true);\n const [open, setOpen] = React.useState(false);\n\n const language = userSettings?.language ?? i18n.language;\n const locale = getUserDateFnsLocale(language);\n\n const selected = React.useMemo(\n () => (value ? parseUserIsoDate(value) : undefined),\n [value],\n );\n\n const displayLabel = selected\n ? formatUserDateForPicker(selected, language)\n : null;\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled={disabled}\n className={cn(\n \"h-10 w-full justify-start border-input bg-background px-3 text-start font-normal shadow-sm hover:bg-background\",\n !displayLabel && \"text-muted-foreground\",\n className,\n )}\n >\n <CalendarIcon\n className=\"me-2 h-4 w-4 shrink-0 text-muted-foreground\"\n aria-hidden\n />\n <span className=\"truncate\">\n {displayLabel ??\n placeholder ??\n t(\"ticket.create_dialog.deadline_placeholder\")}\n </span>\n </Button>\n </PopoverTrigger>\n <PopoverContent\n className=\"z-[120] w-auto p-0\"\n align=\"start\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n >\n <Calendar\n showOutsideDays={false}\n mode=\"single\"\n selected={selected}\n onSelect={(date) => {\n if (!date) return;\n onChange(format(date, \"yyyy-MM-dd\"));\n setOpen(false);\n }}\n locale={locale}\n disabled={disablePastDates ? { before: startOfToday() } : undefined}\n defaultMonth={selected ?? new Date()}\n />\n {value ? (\n <div className=\"border-t border-border px-1.5 py-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 w-full text-xs\"\n onClick={() => {\n onChange(\"\");\n setOpen(false);\n }}\n >\n {t(\"ticket.create_dialog.deadline_clear\")}\n </Button>\n </div>\n ) : null}\n </PopoverContent>\n </Popover>\n );\n});\n","\"use client\";\n\nimport * as React from \"react\";\nimport ChevronLeft from \"lucide-react/dist/esm/icons/chevron-left\";\nimport ChevronRight from \"lucide-react/dist/esm/icons/chevron-right\";\nimport { DayPicker } from \"react-day-picker\";\nimport \"react-day-picker/style.css\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport type CalendarProps = React.ComponentProps<typeof DayPicker>;\n\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n ...props\n}: CalendarProps) {\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\"rdp-root ticket-calendar-compact p-1.5\", className)}\n style={\n {\n \"--rdp-accent-color\": \"hsl(var(--primary))\",\n \"--rdp-accent-background-color\": \"hsl(var(--accent))\",\n \"--rdp-day-height\": \"28px\",\n \"--rdp-day-width\": \"28px\",\n \"--rdp-day_button-height\": \"26px\",\n \"--rdp-day_button-width\": \"26px\",\n \"--rdp-nav_button-height\": \"1.5rem\",\n \"--rdp-nav_button-width\": \"1.5rem\",\n \"--rdp-nav-height\": \"2rem\",\n \"--rdp-weekday-padding\": \"0.125rem 0\",\n \"--rdp-months-gap\": \"0.5rem\",\n } as React.CSSProperties\n }\n classNames={{\n today: \"font-semibold text-primary\",\n selected:\n \"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground\",\n ...classNames,\n }}\n components={{\n Chevron: ({ orientation, className: chevronClass, ...chevronProps }) => {\n const Icon =\n orientation === \"left\" ? ChevronLeft : ChevronRight;\n return (\n <Icon\n className={cn(\"h-3.5 w-3.5\", chevronClass)}\n {...chevronProps}\n />\n );\n },\n }}\n {...props}\n />\n );\n}\n\nCalendar.displayName = \"Calendar\";\n\nexport { Calendar };\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Popover = PopoverPrimitive.Root\n\nconst PopoverTrigger = PopoverPrimitive.Trigger\n\nconst PopoverAnchor = PopoverPrimitive.Anchor\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef<typeof PopoverPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = \"center\", sideOffset = 4, collisionPadding = 16, onWheel, onTouchMove, ...props }, ref) => (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n collisionBoundary={[]}\n sticky=\"partial\"\n translate=\"no\"\n className={cn(\n \"z-50 max-h-[var(--radix-popover-content-available-height)] w-[min(18rem,var(--radix-popover-content-available-width))] overflow-y-auto rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]\",\n className\n )}\n onWheel={(event) => {\n event.stopPropagation()\n onWheel?.(event)\n }}\n onTouchMove={(event) => {\n event.stopPropagation()\n onTouchMove?.(event)\n }}\n {...props}\n />\n </PopoverPrimitive.Portal>\n))\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }\n","\"use client\";\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { UserSettingsDto } from \"@/api/dto/user-settings.dto\";\nimport apiClient from \"@/api/client\";\nimport type { TimeFormat } from \"@/lib/date-utils\";\n\nexport interface UpdateUserSettingsDto {\n syncWifiOnly?: boolean;\n addTimestampToImages?: boolean;\n imagesPerPage?: number;\n language?: string;\n theme?: \"dark\" | \"light\";\n unitSystem?: string;\n dateFormat?: \"24\" | \"12\";\n}\n\nexport const userSettingsQueryKeys = {\n all: [\"userSettings\"] as const,\n details: () => [...userSettingsQueryKeys.all, \"detail\"] as const,\n};\n\nexport const useUserSettings = (enabled: boolean) => {\n const queryClient = useQueryClient();\n\n const userSettingsQuery = useQuery({\n queryKey: userSettingsQueryKeys.details(),\n queryFn: async (): Promise<UserSettingsDto | null> => {\n const response = await apiClient.get<UserSettingsDto>(\"/settings\");\n return response.data ?? null;\n },\n staleTime: 0,\n refetchOnWindowFocus: true,\n enabled,\n });\n\n const updateSettingsMutation = useMutation({\n mutationFn: async (\n settings: UpdateUserSettingsDto,\n ): Promise<UserSettingsDto | null> => {\n const response = await apiClient.put<UserSettingsDto>(\"/settings\", settings);\n return response.data ?? null;\n },\n onMutate: async (newSettings) => {\n await queryClient.cancelQueries({ queryKey: userSettingsQueryKeys.details() });\n const previousSettings = queryClient.getQueryData<UserSettingsDto | null>(\n userSettingsQueryKeys.details(),\n );\n\n queryClient.setQueryData(\n userSettingsQueryKeys.details(),\n (old: UserSettingsDto | null) => (old ? { ...old, ...newSettings } : old),\n );\n\n return { previousSettings };\n },\n onError: (_err, _newSettings, context) => {\n queryClient.setQueryData(\n userSettingsQueryKeys.details(),\n context?.previousSettings ?? null,\n );\n },\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey: userSettingsQueryKeys.details() });\n },\n });\n\n const settings = userSettingsQuery.data;\n const timeFormat: TimeFormat =\n settings?.dateFormat === \"12\" || settings?.dateFormat === \"24\"\n ? settings.dateFormat\n : \"24\";\n\n return {\n userSettings: settings,\n /** Language preference for date formatting (falls back when settings not loaded). */\n language: settings?.language,\n /** 12h / 24h preference from settings (`dateFormat` field on the API). */\n timeFormat,\n isLoading: userSettingsQuery.isLoading,\n error: userSettingsQuery.error,\n refetch: userSettingsQuery.refetch,\n updateSettings: updateSettingsMutation.mutate,\n isUpdating: updateSettingsMutation.isPending,\n };\n};\n","import axios, {\n AxiosHeaders,\n AxiosInstance,\n InternalAxiosRequestConfig,\n AxiosError,\n} from \"axios\";\nimport { storageService, STORAGE_KEYS } from \"@/lib/services\";\nimport i18n from \"@/localization/i18n\";\nimport { getSupportApiRuntime, resolveApiBaseUrl } from \"../../support-api-runtime\";\n\nconst apiClient: AxiosInstance = axios.create({\n baseURL: resolveApiBaseUrl(),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n timeout: 300000,\n withCredentials: true,\n});\n\napiClient.interceptors.request.use(\n (config: InternalAxiosRequestConfig) => {\n const runtime = getSupportApiRuntime();\n const token =\n runtime?.getAccessToken?.() ??\n storageService.getString(STORAGE_KEYS.ACCESS_TOKEN);\n const headers = AxiosHeaders.from(config.headers);\n\n const baseUrl = runtime?.apiBaseUrl?.replace(/\\/$/, \"\") ?? resolveApiBaseUrl();\n if (baseUrl) {\n config.baseURL = baseUrl;\n }\n\n if (token) {\n headers.set(\"Authorization\", `Bearer ${token}`);\n }\n\n // FormData must use browser multipart boundary — default json Content-Type\n // makes ASP.NET fail binding (shortDescription required) or return 415.\n if (typeof FormData !== \"undefined\" && config.data instanceof FormData) {\n headers.delete(\"Content-Type\");\n headers.delete(\"content-type\");\n // Axios 1.x: false clears and prevents defaults from re-applying json.\n headers.setContentType(false);\n }\n\n config.headers = headers;\n return config;\n },\n (error: AxiosError) => Promise.reject(error),\n);\n\napiClient.interceptors.response.use(\n (response) => response,\n (error: AxiosError) => {\n // Do not clear SSO cookies or redirect to avament.com on 401.\n // Support STAFF share `.avament.com` cookies; bouncing to the main site\n // caused an auth flash loop. Callers surface errors in-app instead.\n return Promise.reject(error);\n },\n);\n\nexport default apiClient;\n\nconst API_BASE = resolveApiBaseUrl();\n\nexport function resolveApiMediaUrl(url: string): string | null {\n const trimmed = url.trim();\n if (!trimmed) return null;\n if (/^(blob:|data:)/i.test(trimmed)) return trimmed;\n if (trimmed.startsWith(\"/\")) {\n if (!API_BASE) return trimmed;\n // NEXT_PUBLIC_API_URL ends with `/api` — avoid `/api/api/...`.\n const path =\n API_BASE.endsWith(\"/api\") && trimmed.startsWith(\"/api/\")\n ? trimmed.slice(4)\n : trimmed;\n return `${API_BASE}${path.startsWith(\"/\") ? path : `/${path}`}`;\n }\n return trimmed;\n}\n\nexport function isApiHostedMediaUrl(url: string): boolean {\n const trimmed = url.trim();\n if (!trimmed) return false;\n if (/^(blob:|data:)/i.test(trimmed)) return false;\n if (trimmed.startsWith(\"/api/\") || trimmed.startsWith(\"/\")) return true;\n if (API_BASE && trimmed.startsWith(API_BASE)) return true;\n return false;\n}\n\nexport function normalizeApiDownloadUrl(url: string): string {\n const trimmed = url.trim();\n if (!trimmed) return trimmed;\n if (trimmed.startsWith(\"/\")) return trimmed;\n if (API_BASE && trimmed.startsWith(API_BASE)) {\n const path = trimmed.slice(API_BASE.length);\n return path.startsWith(\"/\") ? path : `/${path}`;\n }\n return trimmed;\n}\n\nexport const getProjectId = (): string | null => {\n return storageService.getString(STORAGE_KEYS.PROJECT_ID);\n};\n\n/** Project-scoped API path (Lean). Base URL already includes `/api`. */\nexport const buildLeanUrl = (path: string): string => {\n const projectId = getProjectId();\n if (!projectId) {\n throw new Error(String(i18n.t(\"api_errors.project_id_required\")));\n }\n return `/lean/${projectId}${path}`;\n};\n\n/** Project-scoped API path (`/{projectId}{path}` — relative to `NEXT_PUBLIC_API_URL`). Not used by the tenant-wide support-reports API, kept for any project-scoped calls (e.g. project lookups). */\nexport const buildProjectUrl = (path: string, projectId?: string | null): string => {\n const pid = projectId ?? getProjectId();\n if (!pid) {\n throw new Error(String(i18n.t(\"api_errors.project_id_required\")));\n }\n return `/${pid}${path}`;\n};\n\n/**\n * Support module API path under `/api/support`.\n * `NEXT_PUBLIC_API_URL` already ends with `/api`, so callers use `/support/...`.\n */\nexport function supportPath(suffix = \"\"): string {\n const normalized = suffix.startsWith(\"/\") ? suffix : suffix ? `/${suffix}` : \"\";\n return `/support${normalized}`;\n}\n","import Cookies from \"js-cookie\";\nimport { AUTH_CONSTANTS } from \"./constants\";\nimport {\n clearHostOnlySharedCookies,\n removeSharedCookie,\n sharedCookieAttributes,\n} from \"./cookieDomain\";\n\nexport interface TokenPairDto {\n refreshToken: string;\n token: string;\n tokenExpiry: string;\n}\n\nconst defaultCookieOptions = () => ({\n ...sharedCookieAttributes(),\n expires: AUTH_CONSTANTS.COOKIE_EXPIRES,\n});\n\nfunction removeLegacyJwtCookie(): void {\n removeSharedCookie(AUTH_CONSTANTS.LEGACY_JWT_COOKIE);\n}\n\nexport const tokenService = {\n clearTokens: () => {\n // Purge host-only shadows first, then dual-expire shared-domain cookies\n // (same order as ticket-frontend tokenService.clearTokens).\n clearHostOnlySharedCookies();\n\n for (const tokenKey of [\n AUTH_CONSTANTS.ACCESS_TOKEN,\n AUTH_CONSTANTS.REFRESH_TOKEN,\n AUTH_CONSTANTS.IS_AUTHENTICATED,\n AUTH_CONSTANTS.LEGACY_JWT_COOKIE,\n ]) {\n removeSharedCookie(tokenKey);\n }\n },\n\n getAccessToken: (): string | undefined => {\n const value = Cookies.get(AUTH_CONSTANTS.ACCESS_TOKEN);\n if (value) return value;\n\n const legacy = Cookies.get(AUTH_CONSTANTS.LEGACY_JWT_COOKIE);\n if (legacy) {\n tokenService.setAccessToken(legacy);\n removeLegacyJwtCookie();\n return legacy;\n }\n\n return undefined;\n },\n\n getIsAuthenticated: (): string | undefined => {\n return Cookies.get(AUTH_CONSTANTS.IS_AUTHENTICATED);\n },\n\n getRefreshToken: (): string | undefined => {\n return Cookies.get(AUTH_CONSTANTS.REFRESH_TOKEN);\n },\n\n hasRefreshToken: (): boolean => {\n return !!tokenService.getRefreshToken();\n },\n\n setAccessToken: (token: string) => {\n clearHostOnlySharedCookies();\n Cookies.set(AUTH_CONSTANTS.ACCESS_TOKEN, token, {\n ...defaultCookieOptions(),\n sameSite: \"lax\",\n });\n },\n\n setAccessSession: (token: string) => {\n clearHostOnlySharedCookies();\n const options = defaultCookieOptions();\n Cookies.set(AUTH_CONSTANTS.ACCESS_TOKEN, token, options);\n Cookies.set(AUTH_CONSTANTS.IS_AUTHENTICATED, \"true\", options);\n },\n\n setTokens: (tokens: TokenPairDto) => {\n clearHostOnlySharedCookies();\n const options = defaultCookieOptions();\n Cookies.set(AUTH_CONSTANTS.ACCESS_TOKEN, tokens.token, options);\n Cookies.set(AUTH_CONSTANTS.REFRESH_TOKEN, tokens.refreshToken, options);\n Cookies.set(AUTH_CONSTANTS.IS_AUTHENTICATED, \"true\", options);\n },\n};\n","/** Auth URLs and cookie names aligned with ava-protocol / Lean for cross-product SSO. */\nexport const AUTH_CONSTANTS = {\n ACCESS_TOKEN: \"access_token\",\n /**\n * Main Avament site — explicit logout and manual \"Sign in\" only.\n * Never used for automatic auth-failure bounces (those stay on Support).\n */\n AUTH_PATH: process.env.NEXT_PUBLIC_AUTH_PATH?.trim() || \"https://avament.com\",\n /** Absolute main-site origin for logout (never relative / never Support). */\n MAIN_APP_URL: \"https://avament.com\",\n /** sessionStorage flag: after logout, Support must bounce to main — not \"Sign in required\". */\n LOGOUT_REDIRECT_FLAG: \"support_logout_to_main\",\n COOKIE_EXPIRES: 70,\n CROSS_SITE_DOMAIN: \"avament.com\",\n // Public routes that skip the shared-cookie session gate in UserInfoLoader.\n EXCLUDED_REDIRECT_ROUTES: [\n \"/login\",\n \"/register\",\n \"/invitation\",\n \"/test\",\n \"/reset-password\",\n \"/landing\",\n \"/privacy-policy\",\n \"/terms-consent\",\n ] as Array<string>,\n IS_AUTHENTICATED: \"is_authenticated\",\n LEGACY_JWT_COOKIE: \"jwt_token\",\n REFRESH_TOKEN: \"refresh_token\",\n} as const;\n\nexport const isAuthRedirectExcludedPath = (pathname: string): boolean => {\n return AUTH_CONSTANTS.EXCLUDED_REDIRECT_ROUTES.some(\n (route) => pathname === route || pathname.startsWith(`${route}/`),\n );\n};\n\nexport function getMainAppUrl(): string {\n const configured = AUTH_CONSTANTS.AUTH_PATH;\n if (configured.startsWith(\"http://\") || configured.startsWith(\"https://\")) {\n try {\n const url = new URL(configured);\n // Never treat Support itself as the logout destination.\n if (url.hostname === \"support.avament.com\") {\n return AUTH_CONSTANTS.MAIN_APP_URL;\n }\n return configured;\n } catch {\n return AUTH_CONSTANTS.MAIN_APP_URL;\n }\n }\n return AUTH_CONSTANTS.MAIN_APP_URL;\n}\n\nexport function markLogoutRedirect(): void {\n try {\n sessionStorage.setItem(AUTH_CONSTANTS.LOGOUT_REDIRECT_FLAG, String(Date.now()));\n } catch {\n /* ignore */\n }\n}\n\n/**\n * True for ~30s after logout so a main-app bounce back to Support cannot leave\n * the user stuck on the in-app \"Sign in required\" screen.\n */\nexport function shouldRedirectAfterLogout(): boolean {\n try {\n const raw = sessionStorage.getItem(AUTH_CONSTANTS.LOGOUT_REDIRECT_FLAG);\n if (!raw) return false;\n const startedAt = Number(raw);\n if (!Number.isFinite(startedAt)) {\n sessionStorage.removeItem(AUTH_CONSTANTS.LOGOUT_REDIRECT_FLAG);\n return false;\n }\n if (Date.now() - startedAt > 30_000) {\n sessionStorage.removeItem(AUTH_CONSTANTS.LOGOUT_REDIRECT_FLAG);\n return false;\n }\n return true;\n } catch {\n return false;\n }\n}\n\n/** Hard-navigate to the main Avament site (logout / post-logout recovery). */\nexport function redirectToMainApp(): void {\n if (typeof window === \"undefined\") return;\n window.location.replace(getMainAppUrl());\n}\n","import { AUTH_CONSTANTS } from \"./constants\";\n\nexport const SHARED_COOKIE_KEYS = [\n AUTH_CONSTANTS.ACCESS_TOKEN,\n AUTH_CONSTANTS.REFRESH_TOKEN,\n AUTH_CONSTANTS.IS_AUTHENTICATED,\n AUTH_CONSTANTS.LEGACY_JWT_COOKIE,\n \"tenant_id\",\n \"project_id\",\n \"user\",\n] as const;\n\nexport type SharedCookieKey = (typeof SHARED_COOKIE_KEYS)[number];\n\nexport function getSharedCookieDomain(hostname?: string): string | undefined {\n const host =\n hostname ??\n (typeof globalThis.location === \"undefined\"\n ? \"\"\n : globalThis.location.hostname);\n\n if (!host || host.includes(\"localhost\") || host === \"127.0.0.1\") {\n return undefined;\n }\n\n if (\n host === AUTH_CONSTANTS.CROSS_SITE_DOMAIN ||\n host.endsWith(`.${AUTH_CONSTANTS.CROSS_SITE_DOMAIN}`)\n ) {\n return `.${AUTH_CONSTANTS.CROSS_SITE_DOMAIN}`;\n }\n\n return undefined;\n}\n\nexport function isSharedCookieContext(hostname?: string): boolean {\n return getSharedCookieDomain(hostname) !== undefined;\n}\n\nexport function isSharedCookieKey(key: string): key is SharedCookieKey {\n return (SHARED_COOKIE_KEYS as readonly string[]).includes(key);\n}\n\n/**\n * Dual-expire host-only + `.avament.com` variants (cloned from ticket-frontend\n * `removeSharedCookie`).\n */\nexport function removeSharedCookie(name: string, hostname?: string): void {\n if (typeof document === \"undefined\") return;\n\n const domain = getSharedCookieDomain(hostname);\n const secure =\n typeof globalThis.location !== \"undefined\" &&\n globalThis.location.protocol === \"https:\";\n const securePart = secure ? \"; Secure\" : \"\";\n\n document.cookie = `${name}=; Max-Age=0; path=/${securePart}`;\n if (domain) {\n document.cookie = `${name}=; Max-Age=0; path=/; domain=${domain}${securePart}`;\n }\n}\n\n/**\n * Host-only cookies on subdomains (e.g. support.avament.com) shadow the shared\n * `.avament.com` SSO cookies. Drop those copies so logout/login can reach the\n * shared domain cookies (cloned from ticket-frontend `purgeHostOnlyAuthCookies`).\n */\nexport function clearHostOnlySharedCookies(hostname?: string): void {\n if (!isSharedCookieContext(hostname)) return;\n if (typeof document === \"undefined\") return;\n\n const secure =\n typeof globalThis.location !== \"undefined\" &&\n globalThis.location.protocol === \"https:\";\n const securePart = secure ? \"; Secure\" : \"\";\n\n for (const name of SHARED_COOKIE_KEYS) {\n document.cookie = `${name}=; Max-Age=0; path=/${securePart}`;\n }\n}\n\nexport function sharedCookieAttributes(hostname?: string): {\n domain?: string;\n path: \"/\";\n secure: boolean;\n sameSite: \"strict\";\n} {\n const domain = getSharedCookieDomain(hostname);\n const secure =\n typeof globalThis.location !== \"undefined\" &&\n globalThis.location.protocol === \"https:\";\n\n return {\n path: \"/\",\n sameSite: \"strict\",\n secure,\n ...(domain ? { domain } : {}),\n };\n}\n","import { tokenService } from \"@/lib/auth/tokenService\";\nimport { AUTH_CONSTANTS } from \"@/lib/auth/constants\";\nimport {\n clearHostOnlySharedCookies,\n isSharedCookieContext,\n isSharedCookieKey,\n removeSharedCookie,\n sharedCookieAttributes,\n} from \"@/lib/auth/cookieDomain\";\n\nexport const STORAGE_KEYS = {\n ACCESS_TOKEN: AUTH_CONSTANTS.ACCESS_TOKEN,\n TENANT_ID: \"tenant_id\",\n PROJECT_ID: \"project_id\",\n TIMELINE_ID: \"timeline_id\",\n USER: \"user\",\n} as const;\n\nexport const LEGACY_JWT_STORAGE_KEY = \"jwt_token\";\nconst isProjectKey = (key: string): boolean => key === STORAGE_KEYS.PROJECT_ID;\n\nconst usesSharedCookiesOnly = (): boolean => isSharedCookieContext();\n\nconst setCookie = (name: string, value: string, days = 7) => {\n if (typeof document === \"undefined\") return;\n clearHostOnlySharedCookies();\n const attrs = sharedCookieAttributes();\n const expires = new Date(Date.now() + days * 864e5).toUTCString();\n const domainPart = attrs.domain ? `; domain=${attrs.domain}` : \"\";\n const securePart = attrs.secure ? \"; Secure\" : \"\";\n document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/${domainPart}; SameSite=${attrs.sameSite}${securePart}`;\n};\n\nconst getCookie = (name: string): string | null => {\n if (typeof document === \"undefined\") return null;\n const match = document.cookie.match(new RegExp(\"(^| )\" + name + \"=([^;]+)\"));\n if (match) {\n try {\n return decodeURIComponent(match[2]);\n } catch {\n return match[2];\n }\n }\n return null;\n};\n\nconst deleteCookie = (name: string) => {\n removeSharedCookie(name);\n};\n\nconst readSharedString = (key: string): string | null => {\n if (key === STORAGE_KEYS.ACCESS_TOKEN) {\n return tokenService.getAccessToken() ?? null;\n }\n return getCookie(key);\n};\n\nconst writeSharedString = (key: string, value: string): void => {\n if (key === STORAGE_KEYS.ACCESS_TOKEN) {\n tokenService.setAccessSession(value);\n return;\n }\n setCookie(key, value);\n};\n\nconst removeSharedString = (key: string): void => {\n if (key === STORAGE_KEYS.ACCESS_TOKEN) {\n tokenService.clearTokens();\n return;\n }\n localStorage.removeItem(key);\n removeSharedCookie(key);\n};\n\nexport const storageService = {\n getString: (key: string): string | null => {\n if (typeof window === \"undefined\") return null;\n\n if (usesSharedCookiesOnly() && isSharedCookieKey(key)) {\n return readSharedString(key);\n }\n\n if (key === STORAGE_KEYS.ACCESS_TOKEN) {\n const fromToken = tokenService.getAccessToken();\n if (fromToken) {\n localStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, fromToken);\n return fromToken;\n }\n let val = localStorage.getItem(STORAGE_KEYS.ACCESS_TOKEN);\n if (!val) {\n val = localStorage.getItem(LEGACY_JWT_STORAGE_KEY);\n if (val) {\n localStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, val);\n localStorage.removeItem(LEGACY_JWT_STORAGE_KEY);\n tokenService.setAccessSession(val);\n }\n }\n if (!val) {\n val =\n getCookie(STORAGE_KEYS.ACCESS_TOKEN) ??\n getCookie(AUTH_CONSTANTS.LEGACY_JWT_COOKIE);\n if (val) {\n localStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, val);\n tokenService.setAccessSession(val);\n }\n }\n return val;\n }\n\n if (isProjectKey(key)) {\n localStorage.removeItem(STORAGE_KEYS.PROJECT_ID);\n return getCookie(STORAGE_KEYS.PROJECT_ID);\n }\n\n let val = localStorage.getItem(key);\n\n if (!val) {\n val = getCookie(key);\n if (val) {\n localStorage.setItem(key, val);\n }\n }\n\n return val;\n },\n\n setString: (key: string, value: string): void => {\n if (typeof window === \"undefined\") return;\n\n if (usesSharedCookiesOnly() && isSharedCookieKey(key)) {\n writeSharedString(key, value);\n return;\n }\n\n if (key === STORAGE_KEYS.ACCESS_TOKEN) {\n localStorage.setItem(STORAGE_KEYS.ACCESS_TOKEN, value);\n localStorage.removeItem(LEGACY_JWT_STORAGE_KEY);\n tokenService.setAccessSession(value);\n return;\n }\n\n if (isProjectKey(key)) {\n localStorage.removeItem(STORAGE_KEYS.PROJECT_ID);\n setCookie(STORAGE_KEYS.PROJECT_ID, value);\n return;\n }\n\n localStorage.setItem(key, value);\n if (\n key === STORAGE_KEYS.PROJECT_ID ||\n key === STORAGE_KEYS.TENANT_ID ||\n key === STORAGE_KEYS.USER\n ) {\n setCookie(key, value);\n }\n },\n\n get: <T>(key: string): T | null => {\n if (typeof window === \"undefined\") return null;\n\n if (usesSharedCookiesOnly() && isSharedCookieKey(key)) {\n const cookieValue = readSharedString(key);\n if (!cookieValue) return null;\n try {\n return JSON.parse(cookieValue) as T;\n } catch {\n return null;\n }\n }\n\n if (isProjectKey(key)) {\n localStorage.removeItem(STORAGE_KEYS.PROJECT_ID);\n const cookieValue = getCookie(STORAGE_KEYS.PROJECT_ID);\n if (!cookieValue) return null;\n try {\n return JSON.parse(cookieValue) as T;\n } catch {\n return null;\n }\n }\n\n let value = localStorage.getItem(key);\n\n if (!value) {\n value = getCookie(key);\n if (value) {\n localStorage.setItem(key, value);\n }\n }\n\n if (!value) return null;\n try {\n return JSON.parse(value) as T;\n } catch {\n return null;\n }\n },\n\n set: <T>(key: string, value: T): void => {\n if (typeof window === \"undefined\") return;\n const strVal = JSON.stringify(value);\n\n if (usesSharedCookiesOnly() && isSharedCookieKey(key)) {\n writeSharedString(key, strVal);\n return;\n }\n\n if (isProjectKey(key)) {\n localStorage.removeItem(STORAGE_KEYS.PROJECT_ID);\n setCookie(STORAGE_KEYS.PROJECT_ID, strVal);\n return;\n }\n\n localStorage.setItem(key, strVal);\n if (\n key === STORAGE_KEYS.PROJECT_ID ||\n key === STORAGE_KEYS.TENANT_ID ||\n key === STORAGE_KEYS.USER\n ) {\n setCookie(key, strVal);\n }\n },\n\n remove: (key: string): void => {\n if (typeof window === \"undefined\") return;\n\n if (key === STORAGE_KEYS.ACCESS_TOKEN) {\n localStorage.removeItem(STORAGE_KEYS.ACCESS_TOKEN);\n localStorage.removeItem(LEGACY_JWT_STORAGE_KEY);\n tokenService.clearTokens();\n return;\n }\n\n if (isProjectKey(key)) {\n localStorage.removeItem(key);\n removeSharedCookie(key);\n return;\n }\n\n if (usesSharedCookiesOnly() && isSharedCookieKey(key)) {\n removeSharedString(key);\n return;\n }\n\n localStorage.removeItem(key);\n if (isSharedCookieKey(key)) {\n removeSharedCookie(key);\n } else {\n deleteCookie(key);\n }\n },\n\n clear: (): void => {\n if (typeof window === \"undefined\") return;\n if (usesSharedCookiesOnly()) {\n for (const key of [\n STORAGE_KEYS.ACCESS_TOKEN,\n STORAGE_KEYS.TENANT_ID,\n STORAGE_KEYS.PROJECT_ID,\n STORAGE_KEYS.USER,\n ]) {\n removeSharedString(key);\n }\n localStorage.removeItem(STORAGE_KEYS.TIMELINE_ID);\n return;\n }\n localStorage.clear();\n tokenService.clearTokens();\n const cookies = document.cookie.split(\";\");\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i];\n const eqPos = cookie.indexOf(\"=\");\n const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;\n deleteCookie(name.trim());\n }\n },\n};\n","export type SupportApiRuntime = {\n apiBaseUrl: string;\n getAccessToken: () => string | null;\n};\n\nlet runtime: SupportApiRuntime | null = null;\n\nexport function setSupportApiRuntime(next: SupportApiRuntime | null): void {\n runtime = next;\n}\n\nexport function getSupportApiRuntime(): SupportApiRuntime | null {\n return runtime;\n}\n\nexport function resolveApiBaseUrl(): string {\n const fromRuntime = runtime?.apiBaseUrl?.replace(/\\/$/, \"\");\n if (fromRuntime) return fromRuntime;\n return (process.env.NEXT_PUBLIC_API_URL ?? \"\").replace(/\\/$/, \"\");\n}\n","import { format, isValid, parse, type Locale } from \"date-fns\";\nimport { ar, de, enUS, fr } from \"date-fns/locale\";\n\nexport type TimeFormat = \"12\" | \"24\";\nexport type UserTimeFormat = TimeFormat;\n\nfunction pad2(value: number): string {\n return String(value).padStart(2, \"0\");\n}\n\nfunction languageCode(language: string): string {\n return language.split(\"-\")[0]?.toLowerCase() || \"en\";\n}\n\n/** Date part only — de: DD.MM.YYYY; en: MM/DD/YYYY; others: DD/MM/YYYY. */\nexport function formatDate(isoDate: string, language: string): string {\n const date = new Date(isoDate);\n const day = pad2(date.getDate());\n const month = pad2(date.getMonth() + 1);\n const year = date.getFullYear();\n const lang = languageCode(language);\n\n if (lang === \"de\") {\n return `${day}.${month}.${year}`;\n }\n if (lang === \"en\") {\n return `${month}/${day}/${year}`;\n }\n return `${day}/${month}/${year}`;\n}\n\n/** Time part only — respects 12h (AM/PM) or 24h from user settings. */\nexport function formatTime(isoDate: string, timeFormat: TimeFormat = \"24\"): string {\n const date = new Date(isoDate);\n const hours = date.getHours();\n const minutes = pad2(date.getMinutes());\n\n if (timeFormat === \"12\") {\n const period = hours >= 12 ? \"PM\" : \"AM\";\n const displayHours = hours % 12 || 12;\n return `${displayHours}:${minutes} ${period}`;\n }\n\n return `${pad2(hours)}:${minutes}`;\n}\n\n/** Combined date + time using language-driven date and settings-driven time. */\nexport function formatDateTime(\n isoDate: string,\n language: string,\n timeFormat: TimeFormat = \"24\",\n): string {\n return `${formatDate(isoDate, language)}, ${formatTime(isoDate, timeFormat)}`;\n}\n\nconst DATE_FNS_LOCALES: Record<string, Locale> = {\n en: enUS,\n de,\n fr,\n ar,\n};\n\nfunction userLanguageKey(locale: string): string {\n return locale.split(\"-\")[0]?.toLowerCase() || \"en\";\n}\n\nfunction toDate(value: Date | string): Date {\n return value instanceof Date ? value : new Date(value);\n}\n\nexport function formatUserDate(value: Date | string, language: string): string {\n const date = toDate(value);\n if (Number.isNaN(date.getTime())) return \"\";\n\n const day = pad2(date.getDate());\n const month = pad2(date.getMonth() + 1);\n const year = date.getFullYear();\n const lang = userLanguageKey(language);\n\n if (lang === \"de\") return `${day}.${month}.${year}`;\n if (lang === \"en\") return `${month}/${day}/${year}`;\n return `${day}/${month}/${year}`;\n}\n\nexport function formatUserDateTime(\n value: Date | string,\n language: string,\n timeFormat: UserTimeFormat = \"24\",\n): string {\n const date = toDate(value);\n if (Number.isNaN(date.getTime())) return \"\";\n\n const datePart = formatUserDate(date, language);\n const hours = date.getHours();\n const minutes = pad2(date.getMinutes());\n const seconds = pad2(date.getSeconds());\n\n if (timeFormat === \"12\") {\n const period = hours >= 12 ? \"PM\" : \"AM\";\n const displayHours = hours % 12 || 12;\n return `${datePart}, ${displayHours}:${minutes}:${seconds} ${period}`;\n }\n\n return `${datePart}, ${pad2(hours)}:${minutes}:${seconds}`;\n}\n\nexport function getUserDateFnsLocale(language: string): Locale {\n return DATE_FNS_LOCALES[userLanguageKey(language)] ?? enUS;\n}\n\nexport function getUserDatePickerPattern(language: string): string {\n const lang = userLanguageKey(language);\n if (lang === \"de\") return \"dd.MM.yyyy\";\n if (lang === \"en\") return \"MM/dd/yyyy\";\n return \"dd/MM/yyyy\";\n}\n\nexport function formatUserDateForPicker(value: Date, language: string): string {\n if (Number.isNaN(value.getTime())) return \"\";\n return format(value, getUserDatePickerPattern(language), {\n locale: getUserDateFnsLocale(language),\n });\n}\n\nexport function parseUserIsoDate(value: string): Date | undefined {\n const parsed = parse(value, \"yyyy-MM-dd\", new Date());\n return isValid(parsed) ? parsed : undefined;\n}\n\nexport function formatUserTrendDate(value: string, language: string): string {\n const [, month, day] = value.split(\"-\");\n if (!day || !month) return value;\n return userLanguageKey(language) === \"de\" ? `${day}.${month}` : `${day}-${month}`;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport Palette from \"lucide-react/dist/esm/icons/palette\";\nimport Pencil from \"lucide-react/dist/esm/icons/pencil\";\nimport Plus from \"lucide-react/dist/esm/icons/plus\";\nimport Trash2 from \"lucide-react/dist/esm/icons/trash-2\";\nimport { AxiosError } from \"axios\";\nimport { useTranslation } from \"react-i18next\";\nimport {\n Select as CatalogSelect,\n type SelectOption,\n} from \"@avament-pub/select\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { TicketCatalogDeleteConfirmDialog } from \"@/components/tickets/TicketCatalogDeleteConfirmDialog\";\nimport {\n Dialog,\n DialogBody,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@/components/ui/dialog\";\nimport { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { ColorPickerPanel } from \"@/components/ui/color-picker\";\nimport { useTicketEvents } from \"@/hooks/useTicketEvents\";\nimport { useTickets } from \"@/hooks/useTickets\";\nimport { isSupportStaffUser } from \"@/lib/auth/isStaffRole\";\nimport { useUserInfo } from \"@/hooks/useUserInfo\";\nimport { useTicketCatalogUsageMemory } from \"@/hooks/useTicketCatalogUsageMemory\";\nimport { catalogNameExists } from \"@/lib/tickets/catalogNames\";\nimport {\n countTicketsUsingEvent,\n getTicketIdsUsingEvent,\n ticketEventDeleteDescription,\n} from \"@/lib/tickets/ticketCatalogDeleteCopy\";\nimport {\n TICKET_CATALOG_DEFAULT_COLOR,\n ticketCatalogColorForUpdate,\n} from \"@/lib/tickets/ticketCatalogColors\";\nimport {\n TicketCatalogColorField,\n TicketCatalogColorSwatch,\n} from \"@/components/tickets/TicketCatalogColorField\";\nimport { cn } from \"@/lib/utils\";\n\ntype TicketEventSelectProps = {\n value: string;\n onChange: (eventId: string) => void;\n disabled?: boolean;\n className?: string;\n};\n\nexport const TicketEventSelect = React.memo(function TicketEventSelect({\n value,\n onChange,\n disabled = false,\n className,\n}: TicketEventSelectProps) {\n const { t } = useTranslation();\n const { userInfo } = useUserInfo();\n const canManageEvents = isSupportStaffUser(userInfo);\n const {\n events,\n createEvent,\n updateEvent,\n deleteEvent,\n isMutating,\n } = useTicketEvents();\n const { record: recordEventUsage, getRecentIds } = useTicketCatalogUsageMemory(\n \"event\",\n \"support\",\n );\n const [addDialogOpen, setAddDialogOpen] = React.useState(false);\n const [newEventName, setNewEventName] = React.useState(\"\");\n const [newEventColor, setNewEventColor] = React.useState<string>(\n TICKET_CATALOG_DEFAULT_COLOR,\n );\n const [editingEvent, setEditingEvent] = React.useState<\n (typeof events)[number] | null\n >(null);\n const [editEventName, setEditEventName] = React.useState(\"\");\n const [colorEditEvent, setColorEditEvent] = React.useState<\n (typeof events)[number] | null\n >(null);\n const [colorDraft, setColorDraft] = React.useState(\"\");\n const [colorSaving, setColorSaving] = React.useState(false);\n const [deleteEventTarget, setDeleteEventTarget] = React.useState<\n (typeof events)[number] | null\n >(null);\n const { data: tickets = [] } = useTickets({\n enabled: Boolean(deleteEventTarget),\n });\n const [addError, setAddError] = React.useState<string | null>(null);\n const [editError, setEditError] = React.useState<string | null>(null);\n const [deleteError, setDeleteError] = React.useState<string | null>(null);\n\n React.useEffect(() => {\n if (value && !events.some((event) => event.id === value)) {\n onChange(\"\");\n }\n }, [events, value, onChange]);\n\n const eventById = React.useMemo(() => {\n const map = new Map(events.map((event) => [event.id, event]));\n return map;\n }, [events]);\n\n const options = React.useMemo<SelectOption[]>(\n () =>\n events.map((event) => ({\n value: event.id,\n label: event.name,\n icon: <TicketCatalogColorSwatch color={event.color} />,\n })),\n [events],\n );\n\n const recentValues = React.useMemo(\n () => getRecentIds(events.map((event) => event.id)),\n [events, getRecentIds],\n );\n\n const eventErrorMessage = (error: unknown, fallbackKey: string) => {\n if (error instanceof AxiosError && error.response?.status === 409) {\n return t(\"ticket.create_dialog.events.duplicate\");\n }\n return t(fallbackKey);\n };\n\n const handleChange = (next: string | null) => {\n if (!next) {\n onChange(\"\");\n return;\n }\n recordEventUsage(next);\n onChange(next);\n };\n\n const handleCreateEvent = async () => {\n if (!canManageEvents) return;\n const trimmed = newEventName.trim();\n if (!trimmed) {\n setAddError(t(\"ticket.create_dialog.events.name_required\"));\n return;\n }\n if (catalogNameExists(events.map((event) => event.name), trimmed)) {\n setAddError(t(\"ticket.create_dialog.events.duplicate\"));\n return;\n }\n try {\n const created = await createEvent({ name: trimmed, color: newEventColor });\n if (!created) {\n setAddError(t(\"ticket.create_dialog.events.create_failed\"));\n return;\n }\n onChange(created.id);\n recordEventUsage(created.id);\n setAddDialogOpen(false);\n setNewEventName(\"\");\n setNewEventColor(TICKET_CATALOG_DEFAULT_COLOR);\n setAddError(null);\n } catch (error) {\n setAddError(\n eventErrorMessage(error, \"ticket.create_dialog.events.create_failed\"),\n );\n }\n };\n\n const handleUpdateEvent = async () => {\n if (!editingEvent) return;\n const trimmed = editEventName.trim();\n if (!trimmed) {\n setEditError(t(\"ticket.create_dialog.events.name_required\"));\n return;\n }\n try {\n await updateEvent(editingEvent.id, {\n name: trimmed,\n colorUnchanged: true,\n });\n setEditingEvent(null);\n setEditEventName(\"\");\n setEditError(null);\n } catch (error) {\n setEditError(\n eventErrorMessage(error, \"ticket.create_dialog.events.update_failed\"),\n );\n }\n };\n\n const handleSaveColor = async () => {\n if (!colorEditEvent) return;\n setColorSaving(true);\n try {\n const patchColor = ticketCatalogColorForUpdate(colorDraft, false);\n await updateEvent(colorEditEvent.id, {\n name: colorEditEvent.name,\n colorUnchanged: false,\n color: patchColor ?? null,\n });\n setColorEditEvent(null);\n } finally {\n setColorSaving(false);\n }\n };\n\n const handleDeleteEvent = async () => {\n if (!deleteEventTarget) return;\n try {\n await deleteEvent(deleteEventTarget.id, {\n unassignTicketIds: getTicketIdsUsingEvent(tickets, deleteEventTarget),\n });\n if (value === deleteEventTarget.id) onChange(\"\");\n setDeleteError(null);\n setDeleteEventTarget(null);\n } catch (error) {\n const message =\n error instanceof AxiosError && error.response?.status === 409\n ? t(\"ticket.create_dialog.events.delete_conflict\")\n : t(\"ticket.create_dialog.events.delete_failed\");\n setDeleteError(message);\n }\n };\n\n const stopAction = (event: React.SyntheticEvent) => {\n event.preventDefault();\n event.stopPropagation();\n };\n\n return (\n <>\n <div className={cn(\"min-w-0\", className)}>\n <CatalogSelect\n mode=\"searchable\"\n options={options}\n value={value || null}\n onChange={handleChange}\n disabled={disabled}\n clearable\n placeholder={t(\"ticket.create_dialog.select_placeholder\")}\n showRecent\n recentValues={recentValues}\n sortAlphabetically\n optionActionsVisibility=\"hover\"\n labels={{\n searchPlaceholder: t(\"ticket.table.search_placeholder\"),\n emptyMessage: t(\"ticket.create_dialog.events.empty\", {\n defaultValue: \"No events\",\n }),\n }}\n header={\n canManageEvents ? (\n <button\n type=\"button\"\n className=\"flex w-full items-center gap-2 px-3 py-2 text-sm font-medium text-primary hover:bg-muted/60\"\n onClick={() => {\n setNewEventName(\"\");\n setNewEventColor(TICKET_CATALOG_DEFAULT_COLOR);\n setAddError(null);\n setAddDialogOpen(true);\n }}\n >\n <Plus className=\"h-3.5 w-3.5\" aria-hidden />\n {t(\"ticket.create_dialog.events.add\")}\n </button>\n ) : null\n }\n renderOptionActions={\n canManageEvents\n ? (option) => {\n const event = eventById.get(option.value);\n if (!event) return null;\n return (\n <>\n <button\n type=\"button\"\n className=\"rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground\"\n aria-label={t(\"ticket.catalog.color_edit\")}\n onPointerDown={stopAction}\n onClick={(e) => {\n stopAction(e);\n setColorEditEvent(event);\n setColorDraft(event.color || TICKET_CATALOG_DEFAULT_COLOR);\n }}\n >\n <span className=\"relative inline-flex\">\n <Palette className=\"h-3.5 w-3.5\" aria-hidden />\n <span\n className=\"absolute -bottom-0.5 -end-0.5 h-1.5 w-1.5 rounded-full border border-background\"\n style={{ backgroundColor: event.color || \"#000\" }}\n aria-hidden\n />\n </span>\n </button>\n <button\n type=\"button\"\n className=\"rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground\"\n aria-label={t(\"ticket.create_dialog.events.edit\")}\n onPointerDown={stopAction}\n onClick={(e) => {\n stopAction(e);\n setEditingEvent(event);\n setEditEventName(event.name);\n setEditError(null);\n }}\n >\n <Pencil className=\"h-3.5 w-3.5\" aria-hidden />\n </button>\n <button\n type=\"button\"\n className=\"rounded p-1 text-muted-foreground hover:bg-destructive hover:text-destructive-foreground\"\n aria-label={t(\"ticket.create_dialog.events.delete\")}\n disabled={isMutating}\n onPointerDown={stopAction}\n onClick={(e) => {\n stopAction(e);\n setDeleteEventTarget(event);\n setDeleteError(null);\n }}\n >\n <Trash2 className=\"h-3.5 w-3.5\" aria-hidden />\n </button>\n </>\n );\n }\n : undefined\n }\n footer={\n canManageEvents && colorEditEvent ? (\n <div className=\"border-t border-border p-2\">\n <ColorPickerPanel\n color={colorDraft}\n onChange={setColorDraft}\n onCancel={() => setColorEditEvent(null)}\n onSave={() => void handleSaveColor()}\n saving={colorSaving}\n labels={{\n cancelLabel: t(\"cancel\"),\n saveLabel: t(\"common.save\"),\n }}\n />\n </div>\n ) : null\n }\n />\n </div>\n\n {canManageEvents ? (\n <Dialog open={addDialogOpen} onOpenChange={setAddDialogOpen}>\n <DialogContent size=\"confirm\" className=\"z-[130] sm:rounded-xl\">\n <DialogHeader>\n <DialogTitle>\n {t(\"ticket.create_dialog.events.add_title\")}\n </DialogTitle>\n </DialogHeader>\n <DialogBody>\n <div className=\"space-y-2 py-1\">\n <Label htmlFor=\"ticket-new-event-name\" className=\"text-sm\">\n {t(\"ticket.create_dialog.events.name_label\")}\n </Label>\n <Input\n id=\"ticket-new-event-name\"\n value={newEventName}\n onChange={(e) => {\n setNewEventName(e.target.value);\n setAddError(null);\n }}\n placeholder={t(\"ticket.create_dialog.events.name_placeholder\")}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n void handleCreateEvent();\n }\n }}\n autoFocus\n />\n {addError ? (\n <p className=\"text-xs text-destructive\">{addError}</p>\n ) : null}\n <div className=\"flex items-center gap-2\">\n <Label className=\"text-sm text-muted-foreground\">\n {t(\"ticket.catalog.color_label\")}\n </Label>\n <TicketCatalogColorSwatch color={newEventColor} />\n <TicketCatalogColorField\n value={newEventColor}\n onChange={setNewEventColor}\n />\n </div>\n </div>\n </DialogBody>\n <DialogFooter className=\"gap-2 sm:gap-0\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setAddDialogOpen(false)}\n >\n {t(\"ticket.create_dialog.plan_cancel\")}\n </Button>\n <Button type=\"button\" onClick={() => void handleCreateEvent()}>\n {t(\"ticket.create_dialog.events.add_confirm\")}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n ) : null}\n\n {canManageEvents ? (\n <Dialog\n open={Boolean(editingEvent)}\n onOpenChange={(open) => {\n if (!open && !isMutating) {\n setEditingEvent(null);\n setEditError(null);\n }\n }}\n >\n <DialogContent size=\"confirm\" className=\"z-[130] sm:rounded-xl\">\n <DialogHeader>\n <DialogTitle>\n {t(\"ticket.create_dialog.events.edit\")}\n </DialogTitle>\n </DialogHeader>\n <DialogBody>\n <div className=\"space-y-2 py-1\">\n <Label htmlFor=\"ticket-edit-event-name\" className=\"text-sm\">\n {t(\"ticket.create_dialog.events.name_label\")}\n </Label>\n <Input\n id=\"ticket-edit-event-name\"\n value={editEventName}\n onChange={(e) => {\n setEditEventName(e.target.value);\n setEditError(null);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n void handleUpdateEvent();\n }\n }}\n autoFocus\n />\n {editError ? (\n <p className=\"text-xs text-destructive\">{editError}</p>\n ) : null}\n </div>\n </DialogBody>\n <DialogFooter className=\"gap-2 sm:gap-0\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setEditingEvent(null)}\n >\n {t(\"cancel\")}\n </Button>\n <Button type=\"button\" onClick={() => void handleUpdateEvent()}>\n {t(\"common.save\")}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n ) : null}\n\n {canManageEvents ? (\n <TicketCatalogDeleteConfirmDialog\n open={Boolean(deleteEventTarget)}\n title={t(\"ticket.create_dialog.events.delete\")}\n description={\n deleteEventTarget\n ? ticketEventDeleteDescription(\n t,\n deleteEventTarget.name,\n countTicketsUsingEvent(tickets, deleteEventTarget),\n )\n : \"\"\n }\n error={deleteError}\n isDeleting={isMutating}\n onOpenChange={(open) => {\n if (!open && !isMutating) {\n setDeleteEventTarget(null);\n setDeleteError(null);\n }\n }}\n onConfirm={() => void handleDeleteEvent()}\n cancelLabel={t(\"cancel\")}\n confirmLabel={t(\"ticket.create_dialog.events.delete_action\")}\n deletingLabel={t(\"ticket.create_dialog.events.deleting\")}\n />\n ) : null}\n </>\n );\n});\n","\"use client\";\n\nimport * as React from \"react\";\nimport AlertTriangle from \"lucide-react/dist/esm/icons/alert-triangle\";\nimport Loader2 from \"lucide-react/dist/esm/icons/loader-2\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n Dialog,\n DialogBody,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@/components/ui/dialog\";\n\ntype TicketCatalogDeleteConfirmDialogProps = {\n open: boolean;\n title: string;\n description: string;\n error?: string | null;\n isDeleting?: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void;\n cancelLabel: string;\n confirmLabel: string;\n deletingLabel: string;\n};\n\nexport function TicketCatalogDeleteConfirmDialog({\n open,\n title,\n description,\n error = null,\n isDeleting = false,\n onOpenChange,\n onConfirm,\n cancelLabel,\n confirmLabel,\n deletingLabel,\n}: TicketCatalogDeleteConfirmDialogProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent size=\"confirm\" className=\"z-[140] sm:rounded-xl\">\n <DialogHeader>\n <div className=\"flex items-start gap-3\">\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-destructive/10 text-destructive\">\n <AlertTriangle className=\"h-4 w-4\" aria-hidden />\n </span>\n <div className=\"space-y-1 text-left\">\n <DialogTitle className=\"text-base\">{title}</DialogTitle>\n <DialogDescription className=\"text-xs\">\n {description}\n </DialogDescription>\n </div>\n </div>\n </DialogHeader>\n\n <DialogBody>\n {error ? (\n <p className=\"text-xs text-destructive\" role=\"alert\">\n {error}\n </p>\n ) : null}\n </DialogBody>\n\n <DialogFooter className=\"gap-2 sm:gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={isDeleting}\n onClick={() => onOpenChange(false)}\n >\n {cancelLabel}\n </Button>\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n disabled={isDeleting}\n onClick={onConfirm}\n >\n {isDeleting ? (\n <>\n <Loader2 className=\"me-2 h-3.5 w-3.5 animate-spin\" />\n {deletingLabel}\n </>\n ) : (\n confirmLabel\n )}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport X from \"lucide-react/dist/esm/icons/x\";\n\nimport { cn } from \"@/lib/utils\"\n\nconst Dialog = DialogPrimitive.Root\n\nconst DialogTrigger = DialogPrimitive.Trigger\n\nconst DialogPortal = DialogPrimitive.Portal\n\nconst DialogClose = DialogPrimitive.Close\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"fixed inset-0 z-[110] bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className\n )}\n {...props}\n />\n))\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName\n\nconst isPortaledOverlayTarget = (target: EventTarget | null) =>\n target instanceof Element &&\n (target.closest(\"[data-radix-select-content]\") !== null ||\n target.closest(\"[data-radix-popper-content-wrapper]\") !== null ||\n // ImagePreviewer portals to document.body above dialogs.\n target.closest(\"[data-image-previewer]\") !== null ||\n // Ticket image editor may portal / sit above dialog content.\n target.closest(\"[data-ticket-image-editor]\") !== null);\n\n/** Fixed width + height presets so dialogs do not resize with content.\n * `confirm` is content-sized (compact) for short confirmation dialogs.\n */\nexport type DialogContentSize =\n | \"confirm\"\n | \"sm\"\n | \"md\"\n | \"lg\"\n | \"xl\"\n | \"2xl\"\n | \"full\";\n\nconst DIALOG_SIZE_CLASSES: Record<DialogContentSize, string> = {\n confirm:\n \"h-auto max-h-[min(90vh,28rem)] w-[calc(100%-2rem)] max-w-sm sm:w-[22rem]\",\n sm: \"h-auto max-h-[min(90vh,28rem)] w-[calc(100%-2rem)] max-w-sm sm:w-96\",\n md: \"h-[min(90vh,32rem)] w-[calc(100%-2rem)] max-w-md sm:w-[28rem]\",\n lg: \"h-[min(90vh,36rem)] w-[calc(100%-2rem)] max-w-lg sm:w-[32rem]\",\n xl: \"h-[min(90vh,42.5rem)] w-[calc(100%-2rem)] max-w-3xl sm:w-[48rem]\",\n \"2xl\": \"h-[min(90vh,48rem)] w-[calc(100%-2rem)] max-w-4xl sm:w-[56rem]\",\n full: \"h-[min(92dvh,56rem)] w-[calc(100%-2rem)] max-w-[96rem]\",\n};\n\ntype DialogContentProps = React.ComponentPropsWithoutRef<\n typeof DialogPrimitive.Content\n> & {\n /** Fixed size preset. Defaults to `lg`. */\n size?: DialogContentSize;\n};\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n DialogContentProps\n>(({\n className,\n children,\n size = \"lg\",\n onPointerDownOutside,\n onFocusOutside,\n \"aria-describedby\": ariaDescribedBy,\n ...props\n}, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n aria-describedby={ariaDescribedBy}\n translate=\"no\"\n data-dialog-size={size}\n className={cn(\n \"fixed left-[50%] top-[50%] z-[110] flex flex-col gap-0 overflow-hidden border bg-background p-0 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n \"group/dialog translate-x-[-50%] translate-y-[-50%]\",\n DIALOG_SIZE_CLASSES[size],\n className\n )}\n onPointerDownOutside={(event) => {\n if (isPortaledOverlayTarget(event.target)) {\n event.preventDefault();\n }\n onPointerDownOutside?.(event);\n }}\n onFocusOutside={(event) => {\n if (isPortaledOverlayTarget(event.target)) {\n event.preventDefault();\n }\n onFocusOutside?.(event);\n }}\n {...props}\n >\n {children}\n <DialogPrimitive.Close className=\"absolute right-4 top-4 z-10 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-0 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground\">\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">Close</span>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPortal>\n))\nDialogContent.displayName = DialogPrimitive.Content.displayName\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex shrink-0 flex-col space-y-1.5 px-6 py-4 text-center sm:text-left\",\n \"group-data-[dialog-size=confirm]/dialog:px-4 group-data-[dialog-size=confirm]/dialog:py-3\",\n className\n )}\n {...props}\n />\n)\nDialogHeader.displayName = \"DialogHeader\"\n\n/** Scrollable middle region between fixed header and footer. */\nconst DialogBody = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"min-h-0 overflow-y-auto overscroll-contain px-6 py-2\",\n \"group-data-[dialog-size=confirm]/dialog:px-4 group-data-[dialog-size=confirm]/dialog:py-1.5\",\n \"group-data-[dialog-size=md]/dialog:flex-1 group-data-[dialog-size=lg]/dialog:flex-1 group-data-[dialog-size=xl]/dialog:flex-1 group-data-[dialog-size=2xl]/dialog:flex-1 group-data-[dialog-size=full]/dialog:flex-1\",\n className\n )}\n {...props}\n />\n)\nDialogBody.displayName = \"DialogBody\"\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex shrink-0 flex-col-reverse gap-2 px-6 py-4 sm:flex-row sm:justify-end sm:space-x-2 sm:gap-0\",\n \"group-data-[dialog-size=confirm]/dialog:px-4 group-data-[dialog-size=confirm]/dialog:py-3\",\n className\n )}\n {...props}\n />\n)\nDialogFooter.displayName = \"DialogFooter\"\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\n \"text-lg font-semibold leading-none tracking-tight\",\n className\n )}\n {...props}\n />\n))\nDialogTitle.displayName = DialogPrimitive.Title.displayName\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n))\nDialogDescription.displayName = DialogPrimitive.Description.displayName\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogTrigger,\n DialogClose,\n DialogContent,\n DialogHeader,\n DialogBody,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n}\n","import * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport type InputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n \"flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nInput.displayName = \"Input\";\n\nexport { Input };\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils\";\n\nconst labelVariants = cva(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants>\n>(({ className, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(labelVariants(), className)}\n {...props}\n />\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label };\n","import type { HexColor } from \"./color-picker.types\";\n\nexport const COLOR_PICKER_DEFAULT_HEX = \"#000000\" as const satisfies HexColor;\n\nconst HEX_6_OR_8_RE = /^#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;\n\n/** True for `#rrggbb` or `#rrggbbaa`. */\nexport function isValidHexColor(value: string): boolean {\n return HEX_6_OR_8_RE.test(value.trim());\n}\n\n/** Ensure a leading `#` for draft editing. */\nexport function ensureHexPrefix(value: string): string {\n const trimmed = value.trim();\n if (!trimmed) return \"#\";\n return trimmed.startsWith(\"#\") ? trimmed : `#${trimmed}`;\n}\n\n/**\n * Strip alpha for the saturation/hue picker (`#rrggbb`).\n * Leaves other values unchanged so invalid drafts stay editable.\n */\nexport function hexColorForPicker(color: string): string {\n const trimmed = color.trim();\n if (trimmed.length === 9 && trimmed.startsWith(\"#\")) {\n return trimmed.slice(0, 7);\n }\n return trimmed;\n}\n\n/** Normalize a saved color to lowercase `#rrggbb` / `#rrggbbaa`, or `null` if invalid. */\nexport function normalizeHexColor(value: string): HexColor | null {\n const normalized = hexColorForPicker(ensureHexPrefix(value)).toLowerCase();\n if (!isValidHexColor(normalized)) return null;\n return normalized as HexColor;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { HexColorInput, HexColorPicker } from \"react-colorful\";\nimport Loader2 from \"lucide-react/dist/esm/icons/loader-2\";\nimport Palette from \"lucide-react/dist/esm/icons/palette\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n Popover,\n PopoverAnchor,\n PopoverContent,\n} from \"@/components/ui/popover\";\nimport { cn } from \"@/lib/utils\";\n\nimport {\n COLOR_PICKER_DEFAULT_HEX,\n hexColorForPicker,\n isValidHexColor,\n} from \"./color-picker-utils\";\nimport type {\n ColorPickerFieldProps,\n ColorPickerLabels,\n ColorPickerPanelProps,\n ColorPickerPopoverProps,\n ColorSwatchProps,\n} from \"./color-picker.types\";\nimport { useColorPicker } from \"./use-color-picker\";\n\nconst DEFAULT_LABELS: Required<ColorPickerLabels> = {\n editAriaLabel: \"Change color\",\n pickerAriaLabel: \"Pick a color\",\n hexLabel: \"HEX\",\n cancelLabel: \"Cancel\",\n saveLabel: \"Save\",\n};\n\nfunction resolveLabels(labels?: ColorPickerLabels): Required<ColorPickerLabels> {\n return { ...DEFAULT_LABELS, ...labels };\n}\n\n/** Small color chip for list rows / labels. */\nexport function ColorSwatch({ color, className }: ColorSwatchProps) {\n return (\n <span\n className={cn(\n \"inline-block h-3 w-3 shrink-0 rounded-sm border border-border\",\n className,\n )}\n style={{ backgroundColor: color || COLOR_PICKER_DEFAULT_HEX }}\n aria-hidden\n />\n );\n}\n\n/**\n * Controlled HEX picker panel (saturation pad + hue + input + Cancel/Save).\n * Embed in a popover, dialog, or inline layout.\n */\nexport function ColorPickerPanel({\n color,\n onChange,\n onCancel,\n onSave,\n disabled = false,\n saving = false,\n labels,\n className,\n}: ColorPickerPanelProps) {\n const resolved = resolveLabels(labels);\n const pickerColor = hexColorForPicker(color) || COLOR_PICKER_DEFAULT_HEX;\n const draftValid = isValidHexColor(pickerColor);\n const isBusy = disabled || saving;\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n <HexColorPicker\n color={pickerColor}\n onChange={onChange}\n className=\"ui-color-picker !h-36 !w-44\"\n />\n <div className=\"flex items-center gap-2\">\n <span\n className=\"h-7 w-7 shrink-0 rounded-md border border-border\"\n style={{ backgroundColor: pickerColor }}\n aria-hidden\n />\n <div className=\"flex min-w-0 flex-1 items-center gap-1.5\">\n <span className=\"text-[10px] font-medium uppercase tracking-wide text-muted-foreground\">\n {resolved.hexLabel}\n </span>\n <HexColorInput\n color={pickerColor}\n onChange={onChange}\n prefixed\n aria-label={resolved.pickerAriaLabel}\n className={cn(\n \"h-7 w-full min-w-0 rounded-md border border-input bg-background px-2\",\n \"font-mono text-xs uppercase outline-none\",\n \"focus-visible:ring-1 focus-visible:ring-ring\",\n )}\n />\n </div>\n </div>\n <div className=\"flex items-center justify-end gap-1.5 pt-0.5\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 px-2 text-xs\"\n disabled={isBusy}\n onClick={onCancel}\n >\n {resolved.cancelLabel}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"h-7 px-2.5 text-xs\"\n disabled={isBusy || !draftValid}\n onClick={() => void onSave()}\n >\n {saving ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" aria-hidden />\n ) : (\n resolved.saveLabel\n )}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Palette trigger that opens a modal-safe HEX popover.\n * Only Save / Cancel dismiss it (outside click / Escape are blocked).\n */\nexport function ColorPickerPopover({\n color,\n onSave,\n disabled = false,\n className,\n triggerClassName,\n labels,\n onOpenChange,\n side = \"left\",\n align = \"start\",\n zIndexClassName = \"z-[200]\",\n}: ColorPickerPopoverProps) {\n const resolved = resolveLabels(labels);\n const [open, setOpen] = React.useState(false);\n\n const openPicker = React.useCallback(() => {\n if (disabled || open) return;\n setOpen(true);\n onOpenChange?.(true);\n }, [disabled, onOpenChange, open]);\n\n const closePicker = React.useCallback(() => {\n setOpen(false);\n onOpenChange?.(false);\n }, [onOpenChange]);\n\n const {\n draft,\n pending,\n handleDraftChange,\n handleCancel,\n handleSave,\n } = useColorPicker({\n color,\n open,\n onSave,\n onClose: closePicker,\n });\n\n const isBusy = disabled || pending;\n\n const stopPropagation = (event: React.SyntheticEvent) => {\n event.stopPropagation();\n };\n\n const handleOpenChange = React.useCallback(\n (nextOpen: boolean) => {\n if (nextOpen) openPicker();\n },\n [openPicker],\n );\n\n return (\n <Popover modal={false} open={open} onOpenChange={handleOpenChange}>\n <PopoverAnchor asChild>\n <button\n type=\"button\"\n className={cn(\n \"relative rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground\",\n isBusy && \"opacity-60\",\n triggerClassName,\n className,\n )}\n aria-label={resolved.editAriaLabel}\n aria-expanded={open}\n disabled={isBusy}\n onPointerDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n openPicker();\n }}\n >\n {pending ? (\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" aria-hidden />\n ) : (\n <Palette className=\"h-3.5 w-3.5\" aria-hidden />\n )}\n <span\n className=\"absolute bottom-0.5 end-0.5 h-1.5 w-1.5 rounded-full border border-background\"\n style={{ backgroundColor: color || COLOR_PICKER_DEFAULT_HEX }}\n aria-hidden\n />\n </button>\n </PopoverAnchor>\n <PopoverContent\n align={align}\n side={side}\n sideOffset={8}\n className={cn(\"w-auto p-3\", zIndexClassName)}\n onOpenAutoFocus={(event) => event.preventDefault()}\n onCloseAutoFocus={(event) => event.preventDefault()}\n onPointerDown={stopPropagation}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n onInteractOutside={(event) => event.preventDefault()}\n onFocusOutside={(event) => event.preventDefault()}\n onEscapeKeyDown={(event) => event.preventDefault()}\n >\n <ColorPickerPanel\n color={draft}\n onChange={handleDraftChange}\n onCancel={handleCancel}\n onSave={handleSave}\n disabled={disabled}\n saving={pending}\n labels={resolved}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\n/**\n * Same as {@link ColorPickerPopover}, but `onChange` is sync (e.g. local draft\n * in an \"Add\" dialog). Prefer Popover + `onSave` for persisted catalog colors.\n */\nexport function ColorPickerField({\n value,\n onChange,\n disabled = false,\n className,\n triggerClassName,\n labels,\n onOpenChange,\n side,\n align,\n zIndexClassName,\n}: ColorPickerFieldProps) {\n return (\n <ColorPickerPopover\n color={value}\n onSave={onChange}\n disabled={disabled}\n className={className}\n triggerClassName={triggerClassName}\n labels={labels}\n onOpenChange={onOpenChange}\n side={side}\n align={align}\n zIndexClassName={zIndexClassName}\n />\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n ensureHexPrefix,\n hexColorForPicker,\n isValidHexColor,\n normalizeHexColor,\n} from \"./color-picker-utils\";\n\ntype UseColorPickerArgs = {\n color: string;\n open: boolean;\n onSave: (color: string) => void | Promise<void>;\n onClose: () => void;\n};\n\n/**\n * Draft / save / cancel state for a HEX color picker session.\n * Host owns `open`; this hook owns the draft while open.\n */\nexport function useColorPicker({\n color,\n open,\n onSave,\n onClose,\n}: UseColorPickerArgs) {\n const [draft, setDraft] = React.useState(() => hexColorForPicker(color));\n const [pending, setPending] = React.useState(false);\n\n React.useEffect(() => {\n if (!open) {\n setDraft(hexColorForPicker(color));\n }\n }, [color, open]);\n\n const resetDraft = React.useCallback(() => {\n setDraft(hexColorForPicker(color));\n }, [color]);\n\n const handleDraftChange = React.useCallback((next: string) => {\n setDraft(ensureHexPrefix(next));\n }, []);\n\n const draftValid = isValidHexColor(hexColorForPicker(draft));\n\n const handleCancel = React.useCallback(() => {\n if (pending) return;\n resetDraft();\n onClose();\n }, [onClose, pending, resetDraft]);\n\n const handleSave = React.useCallback(async () => {\n if (pending) return;\n const normalized = normalizeHexColor(draft);\n if (!normalized) return;\n\n const current = normalizeHexColor(color);\n if (!current || normalized !== current) {\n setPending(true);\n try {\n await onSave(normalized);\n } finally {\n setPending(false);\n }\n }\n\n onClose();\n }, [color, draft, onClose, onSave, pending]);\n\n return {\n draft,\n draftValid,\n pending,\n resetDraft,\n handleDraftChange,\n handleCancel,\n handleSave,\n };\n}\n","\"use client\";\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\n\nimport type { TicketEventDto } from \"@/api/dto/ticket.dto\";\nimport {\n createTicketEvent,\n deleteTicketEvent,\n fetchTicketEvents,\n updateTicketEvent,\n} from \"@/api/ticket\";\nimport { ticketEventKeys, ticketKeys } from \"@/hooks/queries/query-keys\";\nimport { ticketCatalogColorForCreate } from \"@/lib/tickets/ticketCatalogColors\";\n\nexport type TicketEvent = TicketEventDto;\n\nexport type CreateTicketEventInput = {\n name: string;\n color?: string | null;\n};\n\nexport type UpdateTicketEventInput = {\n name: string;\n color?: string | null;\n colorUnchanged?: boolean;\n};\n\nexport type DeleteTicketEventOptions = {\n unassignTicketIds?: string[];\n};\n\n/** Platform ticket-events catalog (`GET /api/support/ticket-events`). */\nexport function useTicketEvents() {\n const queryClient = useQueryClient();\n\n const query = useQuery({\n queryKey: ticketEventKeys.list(),\n queryFn: () => fetchTicketEvents(),\n staleTime: 60_000,\n });\n\n const createMutation = useMutation({\n mutationFn: (input: CreateTicketEventInput) =>\n createTicketEvent({\n name: input.name.trim(),\n color: ticketCatalogColorForCreate(input.color),\n }),\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: ticketEventKeys.all });\n },\n });\n\n const updateMutation = useMutation({\n mutationFn: ({\n eventId,\n input,\n }: {\n eventId: string;\n input: UpdateTicketEventInput;\n }) =>\n updateTicketEvent(eventId, {\n name: input.name.trim(),\n color: input.colorUnchanged ? undefined : input.color,\n }),\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: ticketEventKeys.all });\n await queryClient.invalidateQueries({ queryKey: ticketKeys.all });\n },\n });\n\n const deleteMutation = useMutation({\n mutationFn: (eventId: string) => deleteTicketEvent(eventId),\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: ticketEventKeys.all });\n await queryClient.invalidateQueries({ queryKey: ticketKeys.all });\n },\n });\n\n return {\n catalogEditable: true as const,\n isMutating:\n createMutation.isPending ||\n updateMutation.isPending ||\n deleteMutation.isPending,\n events: query.data ?? [],\n isLoading: query.isLoading,\n isError: query.isError,\n refresh: query.refetch,\n createEvent: (input: CreateTicketEventInput) =>\n createMutation.mutateAsync(input),\n updateEvent: (eventId: string, input: UpdateTicketEventInput) =>\n updateMutation.mutateAsync({ eventId, input }),\n deleteEvent: async (\n eventId: string,\n _options?: DeleteTicketEventOptions,\n ) => {\n await deleteMutation.mutateAsync(eventId);\n },\n };\n}\n","import apiClient from \"./client\";\nimport type { StaffJob } from \"./types\";\nimport {\n COLOR_PICKER_DEFAULT_HEX,\n isValidHexColor,\n} from \"@/components/ui/color-picker/color-picker-utils\";\n\n/** Display color when a support assignee has no custom staff color. */\nexport const SUPPORT_ASSIGNEE_DEFAULT_COLOR = COLOR_PICKER_DEFAULT_HEX;\n\nexport type AuthStaffRow = {\n userId: string;\n email: string;\n displayName: string;\n staffJob: StaffJob;\n /** `null` when unset. Assignees still render this as `#000000`. */\n color: string | null;\n};\n\nexport type UpdateAuthStaffColorRequest = {\n userId: string;\n /** `#rrggbb` / `#rrggbbaa`, or `null` / `\"\"` to clear. */\n color: string | null;\n};\n\nfunction asRecordList(data: unknown): unknown[] {\n if (Array.isArray(data)) return data;\n if (data && typeof data === \"object\") {\n const record = data as Record<string, unknown>;\n for (const key of [\"items\", \"staff\", \"users\", \"data\", \"results\", \"$values\"] as const) {\n const value = record[key];\n if (Array.isArray(value)) return value;\n }\n }\n return [];\n}\n\nfunction readString(record: Record<string, unknown>, ...keys: string[]): string {\n for (const key of keys) {\n const value = record[key];\n if (typeof value === \"string\" && value.trim()) return value.trim();\n }\n return \"\";\n}\n\nfunction readStaffJob(value: unknown): StaffJob | null {\n if (typeof value !== \"string\") return null;\n const job = value.trim().toLowerCase();\n if (job === \"support\" || job === \"programmer\") return job;\n return null;\n}\n\n/** Stored staff color. Empty or invalid means unset (`null`). */\nexport function readStaffColor(value: unknown): string | null {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n if (!trimmed || !isValidHexColor(trimmed)) return null;\n return trimmed;\n}\n\n/**\n * Assignee color is always present.\n * STAFF with `staff_color` → that hex. Unset STAFF, OWNER, and DEV → `#000000`.\n */\nexport function readAssigneeColor(value: unknown): string {\n if (typeof value === \"string\" && isValidHexColor(value.trim())) {\n return value.trim();\n }\n return SUPPORT_ASSIGNEE_DEFAULT_COLOR;\n}\n\n/** Registration staff directory. Color is `null` when unset. OWNER / DEV only. */\nexport async function fetchAuthStaff(): Promise<AuthStaffRow[]> {\n const { data } = await apiClient.get<unknown>(\"/auth/staff\");\n const rows: AuthStaffRow[] = [];\n for (const raw of asRecordList(data)) {\n if (!raw || typeof raw !== \"object\") continue;\n const item = raw as Record<string, unknown>;\n const email = readString(item, \"email\");\n const staffJob = readStaffJob(item.staffJob ?? item.job);\n if (!email || !staffJob) continue;\n rows.push({\n userId: readString(item, \"userId\", \"id\"),\n email,\n displayName:\n readString(item, \"displayName\", \"name\", \"fullName\") || email,\n staffJob,\n color: readStaffColor(item.color),\n });\n }\n return rows;\n}\n\n/**\n * Set or clear a STAFF user's color.\n * `PATCH /api/auth/staff/{userId}` · body `{ \"color\": \"#a52929\" }`\n * OWNER / DEV only. STAFF receives 403. Invalid hex receives 400.\n * Clear with `null` or `\"\"`. Support ticket routes do not patch assignee colors.\n */\nexport async function updateAuthStaffColor(\n body: UpdateAuthStaffColorRequest,\n): Promise<void> {\n const userId = body.userId.trim();\n if (!userId) throw new Error(\"Staff userId is required\");\n const color =\n body.color == null || body.color.trim() === \"\" ? null : body.color.trim();\n await apiClient.patch(`/auth/staff/${encodeURIComponent(userId)}`, {\n color,\n });\n}\n","import type { CSSProperties } from \"react\";\n\nexport const MAX_TICKET_ATTACHMENTS = 15;\nexport const MAX_TICKET_VIDEO_BYTES = 25 * 1024 * 1024;\n/** Longest edge after HEIC convert / large-image normalize. */\nexport const MAX_TICKET_IMAGE_EDGE = 2048;\nexport const HEIC_JPEG_QUALITY = 0.78;\nexport const ATTACHMENT_PROCESS_CONCURRENCY = 3;\n\n/** Image post-process options applied before upload. */\nexport type TicketAttachmentPrepareOptions = {\n guestBorder?: boolean;\n};\n\nexport const TICKET_ATTACHMENT_ACCEPT =\n \"image/*,video/*,.heic,.heif,image/heic,image/heif\";\n\n/** Plan-image pool: images only (no video). */\nexport const TICKET_PLAN_IMAGE_ACCEPT =\n \"image/*,.heic,.heif,image/heic,image/heif\";\n\n/** Fixed square tiles — identical HxW in create and edit. */\nexport const TICKET_ATTACHMENT_TILE_PX = 128;\n\nexport const TICKET_ATTACHMENT_TILE_STYLE = {\n width: TICKET_ATTACHMENT_TILE_PX,\n height: TICKET_ATTACHMENT_TILE_PX,\n minWidth: TICKET_ATTACHMENT_TILE_PX,\n minHeight: TICKET_ATTACHMENT_TILE_PX,\n maxWidth: TICKET_ATTACHMENT_TILE_PX,\n maxHeight: TICKET_ATTACHMENT_TILE_PX,\n flexShrink: 0,\n boxSizing: \"border-box\",\n} as const satisfies CSSProperties;\n\n/** Utility classes (size also enforced via TICKET_ATTACHMENT_TILE_STYLE). */\nexport const TICKET_ATTACHMENT_TILE_CLASS =\n \"box-border size-32 shrink-0 grow-0 self-start overflow-hidden\";\n\nexport const TICKET_ATTACHMENT_TILE_GRID_CLASS =\n \"flex flex-wrap items-start gap-2\";\n\nexport type TicketAttachmentErrorCode =\n | \"invalid_type\"\n | \"empty\"\n | \"video_too_large\"\n | \"max_exceeded\"\n | \"heic_convert_failed\";\n\nexport type LocalTicketAttachmentStatus = \"ready\" | \"processing\" | \"error\";\n\nexport type LocalTicketAttachment = {\n id: string;\n /** Original selected file (may be HEIC). */\n original: File;\n /** File ready for preview/upload; null while processing or on error. */\n file: File | null;\n status: LocalTicketAttachmentStatus;\n error: TicketAttachmentErrorCode | null;\n};\n\n/** Chrome/Windows often reports empty or octet-stream MIME for HEIC/HEIF. */\nfunction isHeicFileName(name: string | null | undefined): boolean {\n if (!name) return false;\n const lower = name.toLowerCase();\n return lower.endsWith(\".heic\") || lower.endsWith(\".heif\");\n}\n\nexport function isHeicAttachmentFile(file: File): boolean {\n return (\n isHeicFileName(file?.name) ||\n file?.type === \"image/heic\" ||\n file?.type === \"image/heif\"\n );\n}\n\nexport function normalizeTicketAttachmentFile(file: File): File {\n if (!file?.name || !isHeicFileName(file.name)) return file;\n const type = file.name.toLowerCase().endsWith(\".heif\")\n ? \"image/heif\"\n : \"image/heic\";\n if (file.type === type) return file;\n return new File([file], file.name, {\n type,\n lastModified: file.lastModified,\n });\n}\n\nexport function createLocalAttachmentId(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `att-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nfunction shouldProcessAttachmentFile(\n file: File,\n needsImageDecorate: boolean,\n): boolean {\n if (isTicketVideoFile(file)) return false;\n if (isHeicAttachmentFile(file)) return true;\n return needsImageDecorate && isTicketImageFile(file);\n}\n\n/** Instant local item — HEIC / decorated images start as processing; others are ready. */\nexport function createLocalTicketAttachment(\n file: File,\n options?: { decorateImages?: boolean; imageOnly?: boolean },\n): LocalTicketAttachment {\n const id = createLocalAttachmentId();\n const normalized = normalizeTicketAttachmentFile(file);\n const validationError = options?.imageOnly\n ? validateTicketPlanImageFile(normalized)\n : validateTicketFile(normalized);\n if (validationError) {\n return {\n id,\n original: normalized,\n file: null,\n status: \"error\",\n error: validationError,\n };\n }\n if (\n shouldProcessAttachmentFile(normalized, Boolean(options?.decorateImages))\n ) {\n return {\n id,\n original: normalized,\n file: null,\n status: \"processing\",\n error: null,\n };\n }\n return {\n id,\n original: normalized,\n file: normalized,\n status: \"ready\",\n error: null,\n };\n}\n\nexport function createReadyLocalTicketAttachment(file: File): LocalTicketAttachment {\n const normalized = normalizeTicketAttachmentFile(file);\n return {\n id: createLocalAttachmentId(),\n original: normalized,\n file: normalized,\n status: \"ready\",\n error: null,\n };\n}\n\nexport function getReadyAttachmentFiles(\n items: LocalTicketAttachment[],\n): File[] {\n return items\n .filter(\n (item): item is LocalTicketAttachment & { file: File } =>\n item.status === \"ready\" && item.file != null,\n )\n .map((item) => item.file);\n}\n\nexport function hasProcessingAttachments(\n items: LocalTicketAttachment[],\n): boolean {\n return items.some((item) => item.status === \"processing\");\n}\n\nasync function resizeImageFileIfNeeded(\n file: File,\n maxEdge: number = MAX_TICKET_IMAGE_EDGE,\n quality: number = HEIC_JPEG_QUALITY,\n): Promise<File> {\n if (!file.type.startsWith(\"image/\") || isHeicAttachmentFile(file)) {\n return file;\n }\n\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(file);\n } catch {\n return file;\n }\n\n const { width, height } = bitmap;\n const longest = Math.max(width, height);\n if (longest <= maxEdge) {\n bitmap.close();\n return file;\n }\n\n const scale = maxEdge / longest;\n const targetW = Math.max(1, Math.round(width * scale));\n const targetH = Math.max(1, Math.round(height * scale));\n\n try {\n const canvas = document.createElement(\"canvas\");\n canvas.width = targetW;\n canvas.height = targetH;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n bitmap.close();\n return file;\n }\n ctx.drawImage(bitmap, 0, 0, targetW, targetH);\n bitmap.close();\n\n const blob = await new Promise<Blob | null>((resolve) => {\n canvas.toBlob(resolve, \"image/jpeg\", quality);\n });\n if (!blob) return file;\n\n const jpegName = file.name.replace(/\\.[^.]+$/i, \".jpg\");\n return new File([blob], jpegName.endsWith(\".jpg\") ? jpegName : `${file.name}.jpg`, {\n type: \"image/jpeg\",\n lastModified: Date.now(),\n });\n } catch {\n bitmap.close();\n return file;\n }\n}\n\nfunction drawGuestBorderOnCanvas(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n): void {\n const lineWidth = Math.max(4, Math.round(Math.min(width, height) * 0.012));\n const inset = lineWidth / 2;\n\n ctx.save();\n ctx.strokeStyle = \"#FF0000\";\n ctx.lineWidth = lineWidth;\n ctx.strokeRect(inset, inset, width - lineWidth, height - lineWidth);\n ctx.restore();\n}\n\nfunction needsImageOverlay(options?: TicketAttachmentPrepareOptions | null): boolean {\n return Boolean(options?.guestBorder);\n}\n\n/** Burns optional guest red border into an image file. Timestamp overlay is backend-owned. */\nexport async function decorateTicketImageFile(\n file: File,\n options?: TicketAttachmentPrepareOptions | null,\n quality: number = HEIC_JPEG_QUALITY,\n): Promise<File> {\n if (\n !file.type.startsWith(\"image/\") ||\n isHeicAttachmentFile(file) ||\n !needsImageOverlay(options)\n ) {\n return file;\n }\n\n let bitmap: ImageBitmap;\n try {\n bitmap = await createImageBitmap(file);\n } catch {\n return file;\n }\n\n try {\n const canvas = document.createElement(\"canvas\");\n canvas.width = bitmap.width;\n canvas.height = bitmap.height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n bitmap.close();\n return file;\n }\n\n ctx.drawImage(bitmap, 0, 0);\n bitmap.close();\n\n if (options?.guestBorder) {\n drawGuestBorderOnCanvas(ctx, canvas.width, canvas.height);\n }\n\n const outputType =\n file.type === \"image/png\" || file.type === \"image/webp\"\n ? file.type\n : \"image/jpeg\";\n const blob = await new Promise<Blob | null>((resolve) => {\n canvas.toBlob(resolve, outputType, quality);\n });\n if (!blob) return file;\n\n const name =\n outputType === \"image/jpeg\" && !/\\.jpe?g$/i.test(file.name)\n ? file.name.replace(/\\.[^.]+$/i, \".jpg\")\n : file.name;\n\n return new File([blob], name, {\n type: outputType,\n lastModified: Date.now(),\n });\n } catch {\n bitmap.close();\n return file;\n }\n}\n\n/** Converts HEIC/HEIF to JPEG (resized) and optionally decorates the image. */\nexport async function prepareTicketAttachmentFile(\n file: File,\n options?: TicketAttachmentPrepareOptions | null,\n): Promise<{ file: File; error: TicketAttachmentErrorCode | null }> {\n const normalized = normalizeTicketAttachmentFile(file);\n const validationError = validateTicketFile(normalized);\n if (validationError) {\n return { file: normalized, error: validationError };\n }\n\n let output = normalized;\n\n if (isHeicAttachmentFile(normalized)) {\n try {\n const heic2any = (await import(\"heic2any\")).default;\n const result = await heic2any({\n blob: normalized,\n toType: \"image/jpeg\",\n quality: HEIC_JPEG_QUALITY,\n });\n const blob = Array.isArray(result) ? result[0] : result;\n if (!blob) {\n return { file: normalized, error: \"heic_convert_failed\" };\n }\n const jpegName = normalized.name.replace(/\\.(heic|heif)$/i, \".jpg\");\n const jpegFile = new File([blob], jpegName, {\n type: \"image/jpeg\",\n lastModified: Date.now(),\n });\n output = await resizeImageFileIfNeeded(jpegFile);\n } catch {\n return { file: normalized, error: \"heic_convert_failed\" };\n }\n }\n\n if (\n needsImageOverlay(options) &&\n isTicketImageFile(output) &&\n !isTicketVideoFile(output) &&\n !isHeicAttachmentFile(output)\n ) {\n output = await decorateTicketImageFile(output, options);\n }\n\n return { file: output, error: null };\n}\n\n/** Process a pending local attachment (HEIC convert + resize + optional decorate). */\nexport async function processLocalTicketAttachment(\n item: LocalTicketAttachment,\n options?: TicketAttachmentPrepareOptions | null,\n): Promise<LocalTicketAttachment> {\n if (item.status !== \"processing\") return item;\n const { file, error } = await prepareTicketAttachmentFile(\n item.original,\n options,\n );\n if (error) {\n return {\n ...item,\n file: null,\n status: \"error\",\n error,\n };\n }\n return {\n ...item,\n file,\n status: \"ready\",\n error: null,\n };\n}\n\nexport function isTicketImageFile(file: File): boolean {\n return file.type.startsWith(\"image/\") || isHeicFileName(file.name);\n}\n\nexport function isTicketVideoFile(file: File): boolean {\n return file.type.startsWith(\"video/\");\n}\n\nexport function isTicketAttachmentFile(file: File): boolean {\n return isTicketImageFile(file) || isTicketVideoFile(file);\n}\n\nexport function isImageContentType(contentType: string): boolean {\n return contentType.startsWith(\"image/\");\n}\n\nexport function isVideoContentType(contentType: string): boolean {\n return contentType.startsWith(\"video/\");\n}\n\nexport function validateTicketFile(file: File): TicketAttachmentErrorCode | null {\n if (!isTicketAttachmentFile(file)) {\n return \"invalid_type\";\n }\n if (file.size === 0) {\n return \"empty\";\n }\n if (isTicketVideoFile(file) && file.size > MAX_TICKET_VIDEO_BYTES) {\n return \"video_too_large\";\n }\n return null;\n}\n\nexport function validateTicketPlanImageFile(\n file: File,\n): TicketAttachmentErrorCode | null {\n if (!isTicketImageFile(file)) {\n return \"invalid_type\";\n }\n if (file.size === 0) {\n return \"empty\";\n }\n return null;\n}\n\nexport function validateTicketFiles(\n files: File[],\n existingCount = 0,\n): TicketAttachmentErrorCode | null {\n if (existingCount + files.length > MAX_TICKET_ATTACHMENTS) {\n return \"max_exceeded\";\n }\n for (const file of files) {\n const err = validateTicketFile(file);\n if (err) return err;\n }\n return null;\n}\n\n/** Shared ≤15 across general attachments + plan images + pending Cam drafts. */\nexport function validateTicketAttachmentPools(\n generalFiles: File[],\n planImageFiles: File[],\n existingGeneralCount = 0,\n existingPlanImageCount = 0,\n camPhotoCount = 0,\n): TicketAttachmentErrorCode | null {\n const total =\n existingGeneralCount +\n existingPlanImageCount +\n generalFiles.length +\n planImageFiles.length +\n camPhotoCount;\n if (total > MAX_TICKET_ATTACHMENTS) {\n return \"max_exceeded\";\n }\n for (const file of generalFiles) {\n const err = validateTicketFile(file);\n if (err) return err;\n }\n for (const file of planImageFiles) {\n const err = validateTicketPlanImageFile(file);\n if (err) return err;\n }\n return null;\n}\n","import type {\n TicketPriorityKey,\n TicketStatusKey,\n} from \"@/lib/tickets/ticketRow\";\nimport { normalizeTicketAttachmentFile } from \"@/lib/tickets/ticketAttachments\";\n\nexport type TicketResponsibleWriteField = { userId: string };\n\nexport type TicketFormFields = {\n shortDescription?: string;\n longDescriptionHtml?: string | null;\n typeKey?: string | null;\n eventId?: string | null;\n statusKey?: TicketStatusKey;\n priority?: TicketPriorityKey | null | \"\";\n link?: string | null;\n deadline?: string | null;\n sequenceId?: string | null;\n responsibleUserId?: string | null;\n /** Multi assignment — min 2 Support project users. */\n responsibles?: TicketResponsibleWriteField[] | null;\n assignmentType?: \"single\" | \"sequence\" | \"multi\";\n existingAttachmentIds?: string[];\n clearFields?: string[];\n};\n\nfunction appendOptional(\n form: FormData,\n key: string,\n value: string | number | null | undefined,\n) {\n if (value === undefined || value === null || value === \"\") return;\n form.append(key, String(value));\n}\n\nfunction appendClearableOptional(\n form: FormData,\n key: string,\n value: string | number | null | undefined,\n) {\n if (value === undefined || value === null) return;\n form.append(key, String(value));\n}\n\n/**\n * With files: multipart field name `images` (repeat per file). Do not set\n * Content-Type — the client interceptor clears it so the browser adds the boundary.\n * Without files: callers send `buildTicketJsonBody` as application/json.\n */\nexport function buildTicketFormData(\n fields: TicketFormFields,\n images: File[] = [],\n): FormData {\n const form = new FormData();\n appendOptional(form, \"shortDescription\", fields.shortDescription?.trim() ?? \"\");\n appendOptional(form, \"longDescriptionHtml\", fields.longDescriptionHtml ?? \"\");\n appendClearableOptional(form, \"typeKey\", fields.typeKey);\n appendClearableOptional(form, \"eventId\", fields.eventId);\n if (fields.statusKey) {\n appendOptional(form, \"statusKey\", fields.statusKey);\n }\n appendClearableOptional(form, \"priority\", fields.priority);\n appendClearableOptional(form, \"link\", fields.link);\n appendOptional(form, \"deadline\", fields.deadline);\n\n if (fields.assignmentType === \"multi\" && fields.responsibles?.length) {\n form.append(\"responsibles\", JSON.stringify(fields.responsibles));\n } else if (fields.assignmentType === \"sequence\" && fields.sequenceId) {\n form.append(\"sequenceId\", fields.sequenceId);\n } else if (fields.assignmentType === \"single\" && fields.responsibleUserId) {\n form.append(\"responsibleUserId\", fields.responsibleUserId);\n }\n\n if (fields.existingAttachmentIds !== undefined) {\n form.append(\n \"existingAttachmentIds\",\n JSON.stringify(fields.existingAttachmentIds),\n );\n }\n\n if (fields.clearFields?.length) {\n form.append(\"clearFields\", JSON.stringify(fields.clearFields));\n }\n\n for (const file of images) {\n form.append(\"images\", normalizeTicketAttachmentFile(file));\n }\n\n return form;\n}\n\n/** No-file create/update body. Assignment is exactly one of the three shapes. */\nexport function buildTicketJsonBody(\n fields: TicketFormFields,\n): Record<string, unknown> {\n const body: Record<string, unknown> = {};\n const shortDescription = fields.shortDescription?.trim();\n if (shortDescription) body.shortDescription = shortDescription;\n\n if (fields.longDescriptionHtml?.trim()) {\n body.longDescriptionHtml = fields.longDescriptionHtml;\n }\n if (fields.typeKey?.trim()) body.typeKey = fields.typeKey.trim();\n if (fields.eventId?.trim()) body.eventId = fields.eventId.trim();\n if (fields.statusKey) body.statusKey = fields.statusKey;\n if (fields.priority) body.priority = fields.priority;\n if (fields.link?.trim()) body.link = fields.link.trim();\n if (fields.deadline?.trim()) body.deadline = fields.deadline.trim();\n\n if (fields.assignmentType === \"multi\" && fields.responsibles?.length) {\n body.responsibles = fields.responsibles;\n } else if (fields.assignmentType === \"sequence\" && fields.sequenceId?.trim()) {\n body.sequenceId = fields.sequenceId.trim();\n } else if (\n fields.assignmentType === \"single\" &&\n fields.responsibleUserId?.trim()\n ) {\n body.responsibleUserId = fields.responsibleUserId.trim();\n }\n\n if (fields.existingAttachmentIds !== undefined) {\n body.existingAttachmentIds = fields.existingAttachmentIds;\n }\n if (fields.clearFields?.length) body.clearFields = fields.clearFields;\n\n return body;\n}\n","import apiClient, { supportPath } from \"./client\";\nimport { readAssigneeColor } from \"./staff\";\nimport { buildTicketFormData, buildTicketJsonBody, type TicketFormFields } from \"./ticketForm\";\nimport type {\n BulkTicketDeleteRequestDto,\n BulkTicketRequestDto,\n BulkTicketResultDto,\n ChangeTicketAssignmentRequest,\n CreateTicketCommentRequest,\n CreateTicketEventDto,\n TicketComment,\n TicketDetailDto,\n TicketEventDto,\n TicketListItemDto,\n TicketResponsibleDto,\n TicketStatisticsDto,\n TicketStatisticsQuery,\n UpdateTicketEventDto,\n} from \"./dto/ticket.dto\";\n\nexport type { TicketFormFields } from \"./ticketForm\";\n\nfunction ticketsPath(suffix = \"\"): string {\n return supportPath(`/tickets${suffix}`);\n}\n\nfunction normalizeLongDescriptionHtml(item: {\n longDescriptionHtml?: string | null;\n longDescription?: string | null;\n}): string | null {\n return (\n item.longDescriptionHtml?.trim() || item.longDescription?.trim() || null\n );\n}\n\nfunction asTicketList(\n data: unknown,\n): Array<TicketListItemDto & { longDescription?: string | null }> {\n if (Array.isArray(data)) return data;\n if (data && typeof data === \"object\") {\n const record = data as Record<string, unknown>;\n for (const key of [\"items\", \"tickets\", \"data\", \"results\"] as const) {\n const value = record[key];\n if (Array.isArray(value)) {\n return value as Array<\n TicketListItemDto & { longDescription?: string | null }\n >;\n }\n }\n }\n return [];\n}\n\nexport type SupportTicketListResponse = {\n items: TicketListItemDto[];\n total: number;\n};\n\nconst SUPPORT_TICKETS_MAX_TAKE = 200;\n\nfunction clampTake(take: number | undefined): number {\n if (take == null || Number.isNaN(take)) return 50;\n return Math.min(SUPPORT_TICKETS_MAX_TAKE, Math.max(1, Math.floor(take)));\n}\n\nfunction readArchivedFlag(record: Record<string, unknown>): boolean {\n const candidates = [record.isArchived, record.IsArchived, record.archived];\n for (const value of candidates) {\n if (typeof value === \"boolean\") return value;\n if (value === 1) return true;\n if (value === 0) return false;\n if (typeof value === \"string\") {\n const normalized = value.trim().toLowerCase();\n if (normalized === \"true\" || normalized === \"1\") return true;\n if (normalized === \"false\" || normalized === \"0\") return false;\n }\n }\n return false;\n}\n\nfunction parseTicketListResponse(data: unknown): SupportTicketListResponse {\n const rawItems = asTicketList(data);\n const items = rawItems.map((item) => ({\n ...item,\n isArchived: readArchivedFlag(item as unknown as Record<string, unknown>),\n longDescriptionHtml: normalizeLongDescriptionHtml(item),\n }));\n\n if (Array.isArray(data)) {\n return { items, total: items.length };\n }\n\n if (data && typeof data === \"object\") {\n const record = data as Record<string, unknown>;\n const totalRaw = record.total ?? record.count;\n const total =\n typeof totalRaw === \"number\" && Number.isFinite(totalRaw)\n ? Math.max(0, Math.floor(totalRaw))\n : items.length;\n return { items, total };\n }\n\n return { items: [], total: 0 };\n}\n\nexport type SupportTicketListQuery = {\n statusKey?: string;\n priority?: string;\n typeKey?: string;\n eventId?: string;\n responsibleUserId?: string;\n search?: string;\n skip?: number;\n take?: number;\n includeArchived?: boolean;\n};\n\n/** Single offset page: `GET /api/support/tickets` */\nexport async function fetchTicketsPage(\n options?: SupportTicketListQuery,\n): Promise<SupportTicketListResponse> {\n const skip = Math.max(0, Math.floor(options?.skip ?? 0));\n const take = clampTake(options?.take);\n const params: Record<string, string | number | boolean> = { skip, take };\n if (options?.statusKey) params.statusKey = options.statusKey;\n if (options?.priority) params.priority = options.priority;\n if (options?.typeKey) params.typeKey = options.typeKey;\n if (options?.eventId) params.eventId = options.eventId;\n if (options?.responsibleUserId) {\n params.responsibleUserId = options.responsibleUserId;\n }\n if (options?.search) params.search = options.search;\n if (options?.includeArchived) params.includeArchived = true;\n\n const { data } = await apiClient.get<unknown>(ticketsPath(), { params });\n return parseTicketListResponse(data);\n}\n\n/**\n * One offset page. Prefer `useTickets` infinite query over fetching every page on mount.\n */\nexport async function fetchTickets(\n options?: SupportTicketListQuery,\n): Promise<TicketListItemDto[]> {\n const page = await fetchTicketsPage({\n ...options,\n skip: options?.skip ?? 0,\n take: options?.take ?? SUPPORT_TICKETS_MAX_TAKE,\n });\n return page.items;\n}\n\n/** Full filtered Support set aggregates (staff). `GET /api/support/tickets/statistics` */\nexport async function fetchTicketStatistics(\n options?: TicketStatisticsQuery,\n): Promise<TicketStatisticsDto> {\n const params: Record<string, string | boolean> = {};\n if (options?.includeArchived) params.includeArchived = true;\n if (options?.from) params.from = options.from;\n if (options?.to) params.to = options.to;\n if (options?.typeKey !== undefined && options.typeKey !== \"\") {\n params.typeKey = options.typeKey;\n }\n if (options?.statusKey) params.statusKey = options.statusKey;\n if (options?.priority) params.priority = options.priority;\n\n const { data } = await apiClient.get<TicketStatisticsDto>(\n ticketsPath(\"/statistics\"),\n { params },\n );\n return data;\n}\n\nexport async function fetchTicket(\n ticketId: string,\n options?: { includeArchived?: boolean },\n): Promise<TicketDetailDto> {\n const { data } = await apiClient.get<\n TicketDetailDto & { longDescription?: string | null }\n >(ticketsPath(`/${ticketId}`), {\n params: options?.includeArchived ? { includeArchived: true } : undefined,\n });\n return {\n ...data,\n longDescriptionHtml: normalizeLongDescriptionHtml(data),\n };\n}\n\nfunction ticketCommentsPath(ticketId: string, suffix = \"\") {\n return ticketsPath(`/${ticketId}/comments${suffix}`);\n}\n\nexport async function fetchTicketComments(\n ticketId: string,\n language?: string | null,\n): Promise<TicketComment[]> {\n const lang = language?.trim().split(\"-\")[0]?.toLowerCase();\n const { data } = await apiClient.get<TicketComment[]>(\n ticketCommentsPath(ticketId),\n {\n params: lang ? { language: lang } : undefined,\n },\n );\n return data;\n}\n\nexport async function createTicketComment(\n ticketId: string,\n body: CreateTicketCommentRequest,\n): Promise<TicketComment> {\n const { data } = await apiClient.post<TicketComment>(\n ticketCommentsPath(ticketId),\n body,\n );\n return data;\n}\n\nexport async function createTicket(\n fields: TicketFormFields,\n images: File[] = [],\n): Promise<TicketDetailDto> {\n if (images.length === 0) {\n const { data } = await apiClient.post<TicketDetailDto>(\n ticketsPath(),\n buildTicketJsonBody(fields),\n );\n return data;\n }\n\n const { data } = await apiClient.post<TicketDetailDto>(\n ticketsPath(),\n buildTicketFormData(fields, images),\n );\n return data;\n}\n\nexport async function updateTicket(\n ticketId: string,\n fields: TicketFormFields,\n images: File[] = [],\n): Promise<TicketDetailDto> {\n const path = ticketsPath(`/${ticketId}`);\n if (images.length === 0) {\n const { data } = await apiClient.patch<TicketDetailDto>(\n path,\n buildTicketJsonBody(fields),\n );\n return data;\n }\n\n const { data } = await apiClient.patch<TicketDetailDto>(\n path,\n buildTicketFormData(fields, images),\n );\n return data;\n}\n\nexport async function deleteTicket(ticketId: string): Promise<void> {\n await apiClient.delete(ticketsPath(`/${ticketId}`));\n}\n\nexport async function bulkUpdateTickets(\n body: BulkTicketRequestDto,\n): Promise<BulkTicketResultDto> {\n const { data } = await apiClient.patch<BulkTicketResultDto>(\n ticketsPath(\"/bulk\"),\n body,\n );\n return data;\n}\n\nexport async function bulkDeleteTickets(\n body: BulkTicketDeleteRequestDto,\n): Promise<BulkTicketResultDto> {\n const { data } = await apiClient.delete<BulkTicketResultDto>(\n ticketsPath(\"/bulk\"),\n { data: body },\n );\n return data;\n}\n\nexport async function changeTicketAssignment(\n ticketId: string,\n body: ChangeTicketAssignmentRequest,\n): Promise<TicketDetailDto> {\n const { data } = await apiClient.patch<TicketDetailDto>(\n ticketsPath(`/${ticketId}/assignment`),\n body,\n );\n return data;\n}\n\n/** Support assignees: `[{ userId, email, displayName, color }]`. Color is always present. */\nfunction asAssigneeList(data: unknown): unknown[] {\n if (Array.isArray(data)) return data;\n if (data && typeof data === \"object\") {\n const record = data as Record<string, unknown>;\n for (const key of [\n \"items\",\n \"assignees\",\n \"users\",\n \"data\",\n \"results\",\n \"$values\",\n ] as const) {\n const value = record[key];\n if (Array.isArray(value)) return value;\n }\n }\n return [];\n}\n\nfunction readAssigneeString(\n record: Record<string, unknown>,\n ...keys: string[]\n): string {\n for (const key of keys) {\n const value = record[key];\n if (typeof value === \"string\" && value.trim()) return value.trim();\n }\n return \"\";\n}\n\n/** Support project users available for assignment (staff). */\nexport async function fetchSupportAssignees(): Promise<TicketResponsibleDto[]> {\n const { data } = await apiClient.get<unknown>(supportPath(\"/assignees\"));\n\n const assignees: TicketResponsibleDto[] = [];\n for (const raw of asAssigneeList(data)) {\n if (!raw || typeof raw !== \"object\") continue;\n const item = raw as Record<string, unknown>;\n const userId = readAssigneeString(item, \"userId\", \"id\");\n if (!userId) continue;\n\n const email = readAssigneeString(item, \"email\");\n assignees.push({\n kind: \"user\",\n userId,\n email: email || undefined,\n name:\n readAssigneeString(item, \"displayName\", \"name\", \"fullName\") ||\n email ||\n userId,\n color: readAssigneeColor(item.color),\n });\n }\n return assignees;\n}\n\nfunction ticketEventsPath(suffix = \"\"): string {\n return supportPath(`/ticket-events${suffix}`);\n}\n\nfunction asEventList(data: unknown): TicketEventDto[] {\n if (Array.isArray(data)) return data as TicketEventDto[];\n if (data && typeof data === \"object\") {\n const record = data as Record<string, unknown>;\n for (const key of [\"items\", \"events\", \"data\", \"results\"] as const) {\n const value = record[key];\n if (Array.isArray(value)) return value as TicketEventDto[];\n }\n }\n return [];\n}\n\nexport async function fetchTicketEvents(): Promise<TicketEventDto[]> {\n const { data } = await apiClient.get<unknown>(ticketEventsPath());\n return asEventList(data);\n}\n\nexport async function createTicketEvent(\n body: CreateTicketEventDto,\n): Promise<TicketEventDto> {\n const { data } = await apiClient.post<TicketEventDto>(\n ticketEventsPath(),\n body,\n );\n return data;\n}\n\nexport async function updateTicketEvent(\n eventId: string,\n body: UpdateTicketEventDto,\n): Promise<TicketEventDto> {\n const { data } = await apiClient.patch<TicketEventDto>(\n ticketEventsPath(`/${eventId}`),\n body,\n );\n return data;\n}\n\nexport async function deleteTicketEvent(eventId: string): Promise<void> {\n await apiClient.delete(ticketEventsPath(`/${eventId}`));\n}\n","import type { SupportTicketListQuery } from \"@/api/ticket\";\nimport type { TicketStatisticsQuery } from \"@/api/dto/ticket.dto\";\n\nexport type TicketListQueryOptions = Pick<\n SupportTicketListQuery,\n | \"includeArchived\"\n | \"statusKey\"\n | \"priority\"\n | \"typeKey\"\n | \"eventId\"\n | \"responsibleUserId\"\n | \"search\"\n>;\n\n/** Ticket list and detail */\nexport const ticketKeys = {\n all: [\"tickets\"] as const,\n lists: () => [...ticketKeys.all, \"list\"] as const,\n list: (options: TicketListQueryOptions = {}) =>\n [\n \"tickets\",\n \"support\",\n {\n includeArchived: options.includeArchived ?? false,\n statusKey: options.statusKey ?? \"\",\n priority: options.priority ?? \"\",\n typeKey: options.typeKey ?? \"\",\n eventId: options.eventId ?? \"\",\n responsibleUserId: options.responsibleUserId ?? \"\",\n search: options.search ?? \"\",\n },\n ] as const,\n details: () => [\"ticket\"] as const,\n detail: (ticketId: string) => [\"ticket\", \"support\", ticketId] as const,\n bulkEdit: (ticketIds: readonly string[]) =>\n [\"bulk-edit-tickets\", \"support\", [...ticketIds].sort().join(\",\")] as const,\n};\n\n/** @deprecated Use ticketKeys.list */\nexport const ticketsQueryKey = ticketKeys.list;\n\nexport type TicketQueryOptions = TicketListQueryOptions;\n\nexport const ticketStatisticsKeys = {\n all: [\"ticket-statistics\"] as const,\n detail: (options: TicketStatisticsQuery = {}) =>\n [\n \"ticket-statistics\",\n \"support\",\n {\n includeArchived: options.includeArchived ?? false,\n from: options.from ?? \"\",\n to: options.to ?? \"\",\n typeKey: options.typeKey ?? \"\",\n statusKey: options.statusKey ?? \"\",\n priority: options.priority ?? \"\",\n },\n ] as const,\n};\n\nexport const ticketCommentKeys = {\n all: [\"ticket-comments\"] as const,\n byTicketRoot: (ticketId: string) => [\"ticket-comments\", ticketId] as const,\n byTicket: (ticketId: string, language?: string | null) =>\n [\n ...ticketCommentKeys.byTicketRoot(ticketId),\n (language ?? \"en\").split(\"-\")[0]?.toLowerCase() || \"en\",\n ] as const,\n};\n\n/** @deprecated Use ticketCommentKeys.byTicket */\nexport const ticketCommentsQueryKey = ticketCommentKeys.byTicket;\n\nexport const ticketSequenceKeys = {\n all: [\"ticket-sequences\"] as const,\n list: () => [\"ticket-sequences\", \"support\"] as const,\n};\n\n/** @deprecated Use ticketSequenceKeys.list */\nexport const ticketSequencesQueryKey = ticketSequenceKeys.list;\n\nexport const ticketEventKeys = {\n all: [\"ticket-events\"] as const,\n list: () => [\"ticket-events\", \"support\"] as const,\n};\n\n/** @deprecated Use ticketEventKeys.list */\nexport const ticketEventsQueryKey = ticketEventKeys.list;\n\nexport const ticketTypeKeys = {\n all: [\"ticket-types\"] as const,\n list: () => [\"ticket-types\", \"support\"] as const,\n};\n\n/** @deprecated Use ticketTypeKeys.list */\nexport const ticketTypesQueryKey = ticketTypeKeys.list;\n\nexport const ticketAuthorKeys = {\n all: [\"ticket-authors\"] as const,\n list: () => [\"ticket-authors\", \"support\"] as const,\n};\n\n/** @deprecated Use ticketAuthorKeys.list */\nexport const ticketAuthorsQueryKey = ticketAuthorKeys.list;\n\nexport const ticketResponsibleKeys = {\n all: [\"ticket-responsibles\"] as const,\n list: () => [\"ticket-responsibles\", \"support\"] as const,\n};\n\n/** `GET /api/auth/staff` — registration directory used to write staff colors. */\nexport const authStaffKeys = {\n all: [\"auth-staff\"] as const,\n list: () => [\"auth-staff\", \"list\"] as const,\n};\n\n/** @deprecated Use ticketResponsibleKeys.list */\nexport const ticketResponsiblesQueryKey = ticketResponsibleKeys.list;\n\nexport const createTicketFieldVisibilityKeys = {\n all: [\"create-ticket-field-visibility\"] as const,\n detail: () => [\"create-ticket-field-visibility\", \"support\"] as const,\n};\n\n/** @deprecated Use createTicketFieldVisibilityKeys.detail */\nexport const createTicketFieldVisibilityQueryKey =\n createTicketFieldVisibilityKeys.detail;\n\nexport const ticketAttachmentPreviewKeys = {\n all: [\"ticket-attachment-previews\"] as const,\n list: (idsKey: string) => [\"ticket-attachment-previews\", idsKey] as const,\n};\n\nexport const userDataKeys = {\n all: [\"userData\"] as const,\n detail: () => [\"userData\"] as const,\n};\n\n/** @deprecated Use userDataKeys.detail */\nexport const userDataQueryKey = userDataKeys.detail();\n\nexport const userSettingsKeys = {\n all: [\"userSettings\"] as const,\n details: () => [...userSettingsKeys.all, \"detail\"] as const,\n};\n\nexport const appVersionKeys = {\n all: [\"appVersion\"] as const,\n version: () => [...appVersionKeys.all, \"version\"] as const,\n};\n","import type {\n TicketAuthorDto,\n TicketEventDto,\n TicketResponsibleDto,\n TicketTypeDto,\n} from \"@/api/dto/ticket.dto\";\nimport {\n COLOR_PICKER_DEFAULT_HEX,\n hexColorForPicker,\n isValidHexColor,\n} from \"@/components/ui/color-picker\";\n\nexport type TicketCatalogColor = `#${string}`;\n\nexport const TICKET_CATALOG_DEFAULT_COLOR = COLOR_PICKER_DEFAULT_HEX;\n\nexport function isValidTicketCatalogColor(value: string): boolean {\n return isValidHexColor(value);\n}\n\n/** True when unset or default black (meaning \"no custom color\"). */\nexport function isTicketCatalogDefaultColor(\n color: string | null | undefined,\n): boolean {\n if (!color) return true;\n const normalized = color.trim().toLowerCase();\n return (\n normalized === TICKET_CATALOG_DEFAULT_COLOR.toLowerCase() ||\n normalized === \"#000\"\n );\n}\n\n/**\n * Inline text color for catalog labels.\n * Default black is omitted so theme `text-foreground` remains readable in dark mode.\n */\nexport function ticketCatalogTextStyle(\n color: string | null | undefined,\n): { color: string } | undefined {\n if (isTicketCatalogDefaultColor(color) || !color) return undefined;\n return { color };\n}\n\n/** Strip alpha channel for native color input (#rrggbb). */\nexport function ticketCatalogColorForPicker(color: string): string {\n return hexColorForPicker(color);\n}\n\n/** Omit color on create when unset or default black. */\nexport function ticketCatalogColorForCreate(\n color: string | null | undefined,\n): string | undefined {\n if (!color || color === TICKET_CATALOG_DEFAULT_COLOR) return undefined;\n return color;\n}\n\n/**\n * Build PATCH color field.\n * - `unchanged`: omit from body\n * - cleared/default: send null\n * - custom: send hex\n */\nexport function ticketCatalogColorForUpdate(\n color: string | null | undefined,\n unchanged: boolean,\n): string | null | undefined {\n if (unchanged) return undefined;\n if (!color || color === TICKET_CATALOG_DEFAULT_COLOR) return null;\n return color;\n}\n\nexport function resolveTicketTypeColor(\n types: TicketTypeDto[],\n typeKey: string | null | undefined,\n): string {\n if (!typeKey) return TICKET_CATALOG_DEFAULT_COLOR;\n return types.find((t) => t.key === typeKey)?.color ?? TICKET_CATALOG_DEFAULT_COLOR;\n}\n\nexport function resolveTicketEventColor(\n events: TicketEventDto[],\n eventId: string | null | undefined,\n): string {\n if (!eventId) return TICKET_CATALOG_DEFAULT_COLOR;\n return events.find((e) => e.id === eventId)?.color ?? TICKET_CATALOG_DEFAULT_COLOR;\n}\n\n/** List tickets expose event name, not id — resolve color by catalog name. */\nexport function resolveTicketEventColorByName(\n events: TicketEventDto[],\n eventName: string | null | undefined,\n): string {\n if (!eventName) return TICKET_CATALOG_DEFAULT_COLOR;\n return events.find((e) => e.name === eventName)?.color ?? TICKET_CATALOG_DEFAULT_COLOR;\n}\n\nexport function resolveTicketAuthorColor(\n authors: TicketAuthorDto[],\n userId: string | null | undefined,\n): string {\n if (!userId) return TICKET_CATALOG_DEFAULT_COLOR;\n return (\n authors.find((author) => author.userId === userId)?.color ??\n TICKET_CATALOG_DEFAULT_COLOR\n );\n}\n\n/** List tickets may lack user id — resolve color by catalog display name. */\nexport function resolveTicketAuthorColorByName(\n authors: TicketAuthorDto[],\n authorName: string | null | undefined,\n): string {\n if (!authorName) return TICKET_CATALOG_DEFAULT_COLOR;\n return (\n authors.find((author) => author.name === authorName)?.color ??\n TICKET_CATALOG_DEFAULT_COLOR\n );\n}\n\nexport function resolveTicketResponsibleColor(\n responsibles: TicketResponsibleDto[],\n catalogId: string | null | undefined,\n): string {\n if (!catalogId) return TICKET_CATALOG_DEFAULT_COLOR;\n return (\n responsibles.find(\n (responsible) =>\n responsible.companyId === catalogId ||\n responsible.userId === catalogId,\n )?.color ?? TICKET_CATALOG_DEFAULT_COLOR\n );\n}\n\n/** List tickets expose company name, not id — resolve color by catalog name. */\nexport function resolveTicketResponsibleColorByName(\n responsibles: TicketResponsibleDto[],\n companyName: string | null | undefined,\n): string {\n if (!companyName) return TICKET_CATALOG_DEFAULT_COLOR;\n return (\n responsibles.find((responsible) => responsible.name === companyName)\n ?.color ?? TICKET_CATALOG_DEFAULT_COLOR\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n keepPreviousData,\n useInfiniteQuery,\n useMutation,\n useQueryClient,\n} from \"@tanstack/react-query\";\n\nimport {\n bulkDeleteTickets,\n bulkUpdateTickets,\n createTicket,\n deleteTicket,\n fetchTicketsPage,\n changeTicketAssignment,\n updateTicket,\n} from \"@/api/ticket\";\nimport type { TicketFormFields } from \"@/api/ticket\";\nimport type {\n BulkTicketPatchDto,\n ChangeTicketAssignmentRequest,\n TicketListItemDto,\n} from \"@/api/dto/ticket.dto\";\nimport {\n ticketCommentKeys,\n ticketKeys,\n ticketStatisticsKeys,\n ticketsQueryKey,\n type TicketQueryOptions,\n} from \"@/hooks/queries/query-keys\";\nimport {\n isTicketPriorityKey,\n isTicketStatusKey,\n type TicketRow,\n} from \"@/lib/tickets/ticketRow\";\nimport { formatMultiResponsiblesLabel } from \"@/lib/tickets/ticketAssignment\";\n\nexport {\n ticketKeys,\n ticketsQueryKey,\n type TicketQueryOptions,\n} from \"@/hooks/queries/query-keys\";\n\nconst SUPPORT_TICKETS_PAGE_SIZE = 200;\n\nfunction toTicketRow(dto: TicketListItemDto): TicketRow {\n const multiLabel =\n dto.assignmentType === \"multi\"\n ? formatMultiResponsiblesLabel(dto.responsibles)\n : null;\n\n return {\n id: dto.serial,\n ticketId: dto.id,\n shortText: dto.shortText ?? \"\",\n longDescriptionHtml: dto.longDescriptionHtml?.trim() || null,\n typeKey: dto.typeKey ?? null,\n event: dto.event ?? null,\n eventId: dto.eventId?.trim() || null,\n statusKey: isTicketStatusKey(dto.statusKey) ? dto.statusKey : \"open\",\n link: dto.link ?? null,\n statusChangeDate: dto.statusChangeDate?.trim() || null,\n priority:\n dto.priority && isTicketPriorityKey(dto.priority) ? dto.priority : null,\n isArchived: dto.isArchived,\n createdAt: dto.createdAt,\n updatedAt: dto.updatedAt?.trim() || null,\n deadline: dto.deadline ?? null,\n company: multiLabel ?? dto.responsibleUserName ?? null,\n companyId: null,\n responsibleUserId: dto.responsibleUserId?.trim() || null,\n responsibleUserName: dto.responsibleUserName?.trim() || null,\n assignmentType: dto.assignmentType ?? null,\n responsibles: dto.responsibles ?? null,\n sequenceName: dto.sequenceName ?? null,\n sequenceStepNumber: dto.sequenceStepNumber ?? null,\n sequenceStepCount: dto.sequenceStepCount ?? null,\n createdBy: dto.createdBy?.trim() || null,\n createdByName: dto.createdByName?.trim() || null,\n updatedBy: dto.updatedBy?.trim() || null,\n updatedByName: dto.updatedByName?.trim() || null,\n lastEditedByResponsible: dto.lastEditedByResponsible ?? null,\n lastComment: dto.lastComment?.trim() || null,\n };\n}\n\nfunction invalidateSupportTickets(queryClient: ReturnType<typeof useQueryClient>) {\n void queryClient.invalidateQueries({ queryKey: ticketKeys.all });\n void queryClient.invalidateQueries({ queryKey: ticketStatisticsKeys.all });\n}\n\nexport function useTickets(options?: TicketQueryOptions & { enabled?: boolean }) {\n const includeArchived = options?.includeArchived ?? false;\n const enabled = options?.enabled ?? true;\n const queryOptions: TicketQueryOptions = {\n includeArchived,\n statusKey: options?.statusKey,\n priority: options?.priority,\n typeKey: options?.typeKey,\n eventId: options?.eventId,\n responsibleUserId: options?.responsibleUserId,\n search: options?.search,\n };\n\n const query = useInfiniteQuery({\n queryKey: ticketsQueryKey(queryOptions),\n queryFn: ({ pageParam }) =>\n fetchTicketsPage({\n ...queryOptions,\n skip: pageParam,\n take: SUPPORT_TICKETS_PAGE_SIZE,\n }),\n initialPageParam: 0,\n getNextPageParam: (lastPage, allPages) => {\n const loaded = allPages.reduce(\n (sum, page) => sum + page.items.length,\n 0,\n );\n if (loaded >= lastPage.total) return undefined;\n if (lastPage.items.length === 0) return undefined;\n return loaded;\n },\n enabled,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n });\n\n const data = React.useMemo(() => {\n const items: TicketListItemDto[] =\n query.data?.pages.flatMap((page) => page.items) ?? [];\n return items.map(toTicketRow);\n }, [query.data]);\n\n const total = query.data?.pages[0]?.total ?? data.length;\n\n return {\n ...query,\n data,\n total,\n };\n}\n\nexport function useChangeTicketAssignment() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({\n ticketId,\n body,\n }: {\n ticketId: string;\n body: ChangeTicketAssignmentRequest;\n }) => changeTicketAssignment(ticketId, body),\n onSuccess: (_data, variables) => {\n invalidateSupportTickets(queryClient);\n void queryClient.invalidateQueries({\n queryKey: ticketKeys.detail(variables.ticketId),\n });\n },\n });\n}\n\nexport function useCreateTicket() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({\n fields,\n images = [],\n }: {\n fields: TicketFormFields;\n images?: File[];\n }) => createTicket(fields, images),\n onSuccess: () => {\n invalidateSupportTickets(queryClient);\n },\n });\n}\n\nexport function useUpdateTicket() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({\n ticketId,\n fields,\n images = [],\n }: {\n ticketId: string;\n fields: TicketFormFields;\n images?: File[];\n }) => updateTicket(ticketId, fields, images),\n onSuccess: (_data, variables) => {\n invalidateSupportTickets(queryClient);\n void queryClient.invalidateQueries({\n queryKey: ticketKeys.detail(variables.ticketId),\n });\n void queryClient.invalidateQueries({\n queryKey: ticketCommentKeys.byTicketRoot(variables.ticketId),\n });\n },\n });\n}\n\nexport function useDeleteTicket() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (ticketId: string) => deleteTicket(ticketId),\n onSuccess: (_data, ticketId) => {\n invalidateSupportTickets(queryClient);\n void queryClient.invalidateQueries({\n queryKey: ticketCommentKeys.byTicketRoot(ticketId),\n });\n },\n });\n}\n\nexport function useBulkUpdateTickets() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({\n ticketIds,\n patch,\n }: {\n ticketIds: string[];\n patch: BulkTicketPatchDto;\n }) => bulkUpdateTickets({ ticketIds, patch }),\n onSuccess: (_data, variables) => {\n invalidateSupportTickets(queryClient);\n for (const ticketId of variables.ticketIds) {\n void queryClient.invalidateQueries({\n queryKey: ticketKeys.detail(ticketId),\n });\n void queryClient.invalidateQueries({\n queryKey: ticketCommentKeys.byTicketRoot(ticketId),\n });\n }\n void queryClient.invalidateQueries({\n queryKey: [\"bulk-edit-tickets\", \"support\"],\n });\n },\n });\n}\n\nexport function useBulkDeleteTickets() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (ticketIds: string[]) => bulkDeleteTickets({ ticketIds }),\n onSuccess: () => {\n invalidateSupportTickets(queryClient);\n },\n });\n}\n","import type { SupportTicketTypeKey } from \"@/lib/tickets/supportTicketTypes\";\nimport type { TicketResponsibleEntryDto } from \"@/api/dto/ticket.dto\";\nimport { differenceInCalendarDays, isValid, parse, startOfDay } from \"date-fns\";\n\nexport const TICKET_STATUS_KEYS = [\n \"open\",\n \"in_work\",\n \"resolved\",\n \"done\",\n] as const;\n\nexport type TicketStatusKey = (typeof TICKET_STATUS_KEYS)[number];\n\nexport function isTicketStatusKey(value: string): value is TicketStatusKey {\n return (TICKET_STATUS_KEYS as readonly string[]).includes(value);\n}\n\nexport const TICKET_PRIORITY_KEYS = [\n \"highest\",\n \"high\",\n \"medium\",\n \"low\",\n \"lowest\",\n] as const;\n\nexport type TicketPriorityKey = (typeof TICKET_PRIORITY_KEYS)[number];\n\nexport function isTicketPriorityKey(value: string): value is TicketPriorityKey {\n return (TICKET_PRIORITY_KEYS as readonly string[]).includes(value);\n}\n\nconst TICKET_PRIORITY_SORT_RANK = new Map<TicketPriorityKey, number>(\n TICKET_PRIORITY_KEYS.map((key, index) => [key, index]),\n);\n\n/** Lower rank = higher urgency. Unset/unknown priorities sort last. */\nexport function getTicketPrioritySortRank(\n priority: TicketPriorityKey | null | undefined,\n): number {\n if (priority == null) return TICKET_PRIORITY_KEYS.length;\n return TICKET_PRIORITY_SORT_RANK.get(priority) ?? TICKET_PRIORITY_KEYS.length;\n}\n\nexport function compareTicketPriority(\n left: TicketPriorityKey | null | undefined,\n right: TicketPriorityKey | null | undefined,\n): number {\n return getTicketPrioritySortRank(left) - getTicketPrioritySortRank(right);\n}\n\nexport const MAX_TICKET_TITLE_LENGTH = 170;\nexport const MAX_TICKET_DESCRIPTION_LENGTH = 2000;\n\nexport type TicketRow = {\n /** Display serial (per-platform number). */\n id: string;\n /** MongoDB ticket id for API update/delete. */\n ticketId: string;\n shortText: string;\n longDescriptionHtml: string | null;\n typeKey: SupportTicketTypeKey | string | null;\n event: string | null;\n eventId: string | null;\n statusKey: TicketStatusKey;\n link: string | null;\n statusChangeDate: string | null;\n priority: TicketPriorityKey | null;\n isArchived: boolean;\n createdAt: string;\n updatedAt: string | null;\n deadline: string | null;\n /** Assignee display label (user name, sequence, or multi summary). */\n company: string | null;\n companyId: string | null;\n responsibleUserId: string | null;\n responsibleUserName: string | null;\n assignmentType?: \"single\" | \"sequence\" | \"multi\" | null;\n responsibles?: TicketResponsibleEntryDto[] | null;\n sequenceName?: string | null;\n sequenceStepNumber?: number | null;\n sequenceStepCount?: number | null;\n createdBy: string | null;\n createdByName: string | null;\n updatedBy: string | null;\n updatedByName: string | null;\n lastEditedByResponsible: boolean | null;\n lastComment: string | null;\n};\n\nexport const TICKET_DEADLINE_SOON_WITHIN_DAYS = 3;\n\nexport type TicketDeadlineUrgency = \"none\" | \"soon\" | \"overdue\";\n\nexport function parseTicketDeadlineDate(deadline: string): Date | null {\n const trimmed = deadline.trim();\n if (!trimmed) return null;\n\n const parsed = parse(trimmed, \"yyyy-MM-dd\", new Date());\n if (isValid(parsed)) return parsed;\n\n const fallback = new Date(trimmed);\n return isValid(fallback) ? fallback : null;\n}\n\nexport function getTicketDeadlineUrgency(\n deadline: string | null | undefined,\n withinDays = TICKET_DEADLINE_SOON_WITHIN_DAYS,\n now: Date = new Date(),\n): TicketDeadlineUrgency {\n if (!deadline?.trim()) return \"none\";\n const deadlineDate = parseTicketDeadlineDate(deadline);\n if (!deadlineDate) return \"none\";\n\n const daysUntil = differenceInCalendarDays(deadlineDate, startOfDay(now));\n if (daysUntil < 0) return \"overdue\";\n if (daysUntil <= withinDays) return \"soon\";\n return \"none\";\n}\n\nexport function isTicketDeadlineUrgent(\n deadline: string | null | undefined,\n withinDays = TICKET_DEADLINE_SOON_WITHIN_DAYS,\n now: Date = new Date(),\n): boolean {\n return getTicketDeadlineUrgency(deadline, withinDays, now) !== \"none\";\n}\n\nexport {\n formatUserDate as formatTicketDate,\n formatUserDateTime as formatTicketDateTime,\n} from \"@/lib/date-utils\";\nexport type { UserTimeFormat } from \"@/lib/date-utils\";\n","import type {\n AssignmentType,\n ChangeTicketAssignmentRequest,\n TicketResponsibleEntryDto,\n TicketResponsibleWriteDto,\n} from \"@/api/dto/ticket.dto\";\nimport type { TicketRow, TicketStatusKey } from \"@/lib/tickets/ticketRow\";\nimport { isTicketStatusKey } from \"@/lib/tickets/ticketRow\";\n\nexport type TicketUiAssignmentType = AssignmentType;\n\n/** Support is always internal — Single maps to API `single`. */\nexport function singleAssignmentType(): \"single\" {\n return \"single\";\n}\n\nexport function isMultiAssignment(\n assignmentType: AssignmentType | null | undefined,\n): boolean {\n return assignmentType === \"multi\";\n}\n\nexport function isSequenceAssignment(\n assignmentType: AssignmentType | null | undefined,\n): boolean {\n return assignmentType === \"sequence\";\n}\n\n/**\n * List payloads omit `assignmentType` — detect via `sequenceName` as well.\n */\nexport function isTicketSequenceAssignee(\n ticket: Pick<TicketRow, \"assignmentType\" | \"sequenceName\">,\n): boolean {\n return (\n isSequenceAssignment(ticket.assignmentType) ||\n Boolean(ticket.sequenceName?.trim())\n );\n}\n\n/** Display label for sequence assignee cells (name · step/count). */\nexport function formatTicketSequenceColumnLabel(\n ticket: Pick<\n TicketRow,\n \"sequenceName\" | \"sequenceStepNumber\" | \"sequenceStepCount\"\n >,\n): string | null {\n const sequenceName = ticket.sequenceName?.trim();\n if (!sequenceName) return null;\n\n if (\n ticket.sequenceStepNumber != null &&\n ticket.sequenceStepCount != null\n ) {\n return `${sequenceName} · ${ticket.sequenceStepNumber}/${ticket.sequenceStepCount}`;\n }\n\n return sequenceName;\n}\n\n/**\n * List payloads may omit `assignmentType` — detect multi via responsibles too.\n */\nexport function isTicketMultiAssignee(\n ticket: Pick<TicketRow, \"assignmentType\" | \"responsibles\">,\n): boolean {\n return (\n isMultiAssignment(ticket.assignmentType) ||\n (ticket.responsibles?.length ?? 0) >= 2\n );\n}\n\n/** Stable filter/sort token for multi assignment in the responsible column. */\nexport const TICKET_MULTI_RESPONSIBLE_COLUMN_VALUE = \"multi\" as const;\n\n/** True when the ticket has any assignee (user, multi, or sequence). */\nexport function ticketHasResponsibleAssignee(\n ticket: Pick<\n TicketRow,\n | \"assignmentType\"\n | \"sequenceName\"\n | \"company\"\n | \"companyId\"\n | \"responsibleUserId\"\n | \"responsibleUserName\"\n | \"responsibles\"\n >,\n): boolean {\n if (isTicketSequenceAssignee(ticket)) return true;\n if (isTicketMultiAssignee(ticket)) return true;\n if (ticket.responsibleUserId?.trim() || ticket.responsibleUserName?.trim()) {\n return true;\n }\n return false;\n}\n\n/** Filter/sort value for the responsible column (user name or multi token). */\nexport function getTicketResponsibleColumnValue(\n ticket: Pick<\n TicketRow,\n | \"company\"\n | \"assignmentType\"\n | \"responsibles\"\n | \"responsibleUserName\"\n | \"responsibleUserId\"\n >,\n catalog?: ReadonlyArray<{ userId?: string; name?: string }>,\n): string {\n if (isTicketMultiAssignee(ticket)) {\n return TICKET_MULTI_RESPONSIBLE_COLUMN_VALUE;\n }\n const userId = ticket.responsibleUserId?.trim() || \"\";\n if (userId && catalog?.length) {\n for (const entry of catalog) {\n if (entry.userId?.trim() === userId) {\n const catalogName = entry.name?.trim();\n if (catalogName && !isUnresolvedResponsibleUserId(catalogName)) {\n return catalogName;\n }\n }\n }\n }\n const named =\n humanResponsibleLabel(ticket.responsibleUserName) ||\n humanResponsibleLabel(ticket.company);\n if (named) return named;\n if (userId && !isUnresolvedResponsibleUserId(userId)) return userId;\n return \"\";\n}\n\nfunction humanResponsibleLabel(value: string | null | undefined): string {\n const trimmed = value?.trim() || \"\";\n if (!trimmed || isUnresolvedResponsibleUserId(trimmed)) return \"\";\n return trimmed;\n}\n\nconst OBJECT_ID_RE = /^[a-f0-9]{24}$/i;\n\n/** True when a filter/label is a bare Mongo-style user id (no display name). */\nexport function isUnresolvedResponsibleUserId(value: string): boolean {\n return OBJECT_ID_RE.test(value.trim());\n}\n\n/**\n * Full-inbox responsible counts from statistics, keyed by display name.\n * Empty string is the unknown-assignee bucket.\n * Never derived from the loaded ticket page.\n */\nexport function responsibleCountsFromStatistics(\n rows: ReadonlyArray<{\n companyId?: string | null;\n companyName?: string | null;\n count?: number | null;\n }> | null | undefined,\n catalog: ReadonlyArray<{ userId?: string; name?: string }>,\n missingCompany = 0,\n): Map<string, number> {\n const nameById = new Map<string, string>();\n const nameByLower = new Map<string, string>();\n for (const entry of catalog) {\n const id = entry.userId?.trim() || \"\";\n const name = humanResponsibleLabel(entry.name);\n if (name) nameByLower.set(name.toLowerCase(), name);\n if (id && name) nameById.set(id, name);\n }\n\n const counts = new Map<string, number>();\n const add = (key: string, count: number) => {\n if (!Number.isFinite(count) || count <= 0) return;\n counts.set(key, (counts.get(key) ?? 0) + count);\n };\n\n let sawEmptyBucket = false;\n for (const row of rows ?? []) {\n const id = row.companyId?.trim() || \"\";\n const rawName = row.companyName?.trim() || \"\";\n const count = Number(row.count ?? 0);\n const catalogName =\n (id && nameById.get(id)) ||\n nameByLower.get(rawName.toLowerCase()) ||\n \"\";\n if (catalogName) {\n add(catalogName, count);\n continue;\n }\n const named = humanResponsibleLabel(rawName);\n if (!named || isUnresolvedResponsibleUserId(id)) {\n sawEmptyBucket = true;\n add(\"\", count);\n continue;\n }\n add(named, count);\n }\n\n if (!sawEmptyBucket) add(\"\", missingCompany);\n return counts;\n}\n\n/**\n * Fill `responsibleUserName` / `company` from the assignees catalog (and\n * any ticket that already has a name for the same userId) so filters and\n * cells never show a raw id when a display name is known.\n */\nexport function enrichTicketsWithResponsibleNames(\n tickets: TicketRow[],\n catalog: ReadonlyArray<{ userId?: string; name?: string }>,\n): TicketRow[] {\n if (tickets.length === 0) return tickets;\n\n const nameByUserId = new Map<string, string>();\n for (const entry of catalog) {\n const id = entry.userId?.trim();\n const name = entry.name?.trim();\n if (id && name) nameByUserId.set(id, name);\n }\n for (const ticket of tickets) {\n if (isTicketMultiAssignee(ticket)) continue;\n const id = ticket.responsibleUserId?.trim();\n if (!id || nameByUserId.has(id)) continue;\n const name =\n ticket.responsibleUserName?.trim() ||\n (ticket.company?.trim() &&\n ticket.company.trim() !== id &&\n !OBJECT_ID_RE.test(ticket.company.trim())\n ? ticket.company.trim()\n : \"\");\n if (name) nameByUserId.set(id, name);\n }\n\n if (nameByUserId.size === 0) return tickets;\n\n let changed = false;\n const next = tickets.map((ticket) => {\n if (isTicketMultiAssignee(ticket)) return ticket;\n const id = ticket.responsibleUserId?.trim();\n if (!id) return ticket;\n const resolved = nameByUserId.get(id);\n if (!resolved) return ticket;\n if (\n ticket.responsibleUserName?.trim() === resolved &&\n ticket.company?.trim() === resolved\n ) {\n return ticket;\n }\n changed = true;\n return {\n ...ticket,\n responsibleUserName: resolved,\n company: resolved,\n };\n });\n return changed ? next : tickets;\n}\n\n/** Assignees locked on normal ticket PATCH — use PATCH …/assignment instead. */\nexport function usesAssignmentEndpoint(\n assignmentType: AssignmentType | null | undefined,\n): boolean {\n return assignmentType === \"multi\" || assignmentType === \"sequence\";\n}\n\nexport function normalizeResponsibleStatusKey(\n value: string | null | undefined,\n): TicketStatusKey {\n if (value && isTicketStatusKey(value)) return value;\n return \"open\";\n}\n\nexport function getResponsibleEntryId(\n entry: Pick<TicketResponsibleEntryDto, \"userId\" | \"companyId\">,\n): string | null {\n return entry.userId?.trim() || null;\n}\n\nexport function getResponsibleEntryName(\n entry: TicketResponsibleEntryDto,\n): string {\n return (\n entry.userName?.trim() ||\n entry.userId?.trim() ||\n entry.companyName?.trim() ||\n entry.companyId?.trim() ||\n \"\"\n );\n}\n\nexport function formatMultiResponsiblesLabel(\n responsibles: TicketResponsibleEntryDto[] | null | undefined,\n): string | null {\n if (!responsibles?.length) return null;\n const names = responsibles\n .map((entry) => getResponsibleEntryName(entry))\n .filter(Boolean);\n return names.length ? names.join(\", \") : null;\n}\n\nexport function toResponsibleWriteList(\n ids: readonly string[],\n): TicketResponsibleWriteDto[] {\n const unique = [...new Set(ids.map((id) => id.trim()).filter(Boolean))];\n return unique.map((userId) => ({ userId }));\n}\n\nexport function buildChangeAssignmentRequest(params: {\n assignmentType: TicketUiAssignmentType | \"user\" | \"company\";\n responsibleUserId?: string | null;\n sequenceId?: string | null;\n responsibleIds?: readonly string[];\n}): ChangeTicketAssignmentRequest | null {\n const assignmentType =\n params.assignmentType === \"user\" || params.assignmentType === \"company\"\n ? \"single\"\n : params.assignmentType;\n\n if (assignmentType === \"multi\") {\n const responsibles = toResponsibleWriteList(params.responsibleIds ?? []);\n if (responsibles.length < 2) return null;\n return { assignmentType: \"multi\", responsibles };\n }\n\n if (assignmentType === \"sequence\") {\n const sequenceId = params.sequenceId?.trim();\n if (!sequenceId) return null;\n return { assignmentType: \"sequence\", sequenceId };\n }\n\n const responsibleUserId = params.responsibleUserId?.trim();\n if (!responsibleUserId) return null;\n return { assignmentType: \"single\", responsibleUserId };\n}\n","import type { StaffJob, User, UserCapabilities } from \"@/api/types\";\n\n/** Platform support staff = `STAFF` / `DEV` / `OWNER` (contract §Roles). */\nexport function isStaffRole(role?: string | null): boolean {\n const normalized = role?.toUpperCase();\n return normalized === \"OWNER\" || normalized === \"DEV\" || normalized === \"STAFF\";\n}\n\n/** OWNER/DEV only — staff-user management, elevated settings, etc. */\nexport function isPlatformAdminRole(role?: string | null): boolean {\n const normalized = role?.toUpperCase();\n return normalized === \"OWNER\" || normalized === \"DEV\";\n}\n\n/**\n * Who may `POST /support-reports` (contract §6b).\n * Prefer `capabilities.isPlatformElevated`; STAFF never creates.\n */\nexport function canCreateSupportReport(\n user?: Pick<User, \"role\" | \"capabilities\"> | null,\n): boolean {\n if (!user) return false;\n const role = user.role?.toUpperCase();\n if (role === \"STAFF\") return false;\n if (user.capabilities?.isPlatformElevated === true) return true;\n if (isPlatformAdminRole(role)) return true;\n return role === \"USER\";\n}\n\ntype SupportStaffIdentity = Pick<\n User,\n \"staffJob\" | \"capabilities\" | \"assignments\"\n>;\n\n/** Top-level `staffJob`, or nested on an assignment entry (live `/auth/me` shape). */\nexport function resolveStaffJob(\n user?: SupportStaffIdentity | null,\n): StaffJob | null {\n if (!user) return null;\n if (user.staffJob === \"support\" || user.staffJob === \"programmer\") {\n return user.staffJob;\n }\n for (const assignment of user.assignments ?? []) {\n const job = assignment.staffJob;\n if (job === \"support\" || job === \"programmer\") return job;\n }\n return null;\n}\n\n/**\n * Support-job STAFF who must stay on `support.avament.com` (no home/back to main).\n * Programmers use Support for inbox when `isSupportStaff`, but still leave for\n * product apps / workspaces — never treat them as support-only.\n */\nexport function isSupportOnlyStaff(\n user?: SupportStaffIdentity | null,\n): boolean {\n if (!user) return false;\n if (user.capabilities?.isPlatformElevated === true) return false;\n\n const job = resolveStaffJob(user);\n if (job === \"programmer\") return false;\n if (job === \"support\") return true;\n\n // Assignment-scoped STAFF without an explicit job are programmers.\n if ((user.assignments?.length ?? 0) > 0) return false;\n\n const caps: UserCapabilities | null | undefined = user.capabilities;\n return Boolean(caps?.isSupportStaff && !caps?.isPlatformElevated);\n}\n\n/**\n * Map BE `defaultRoute` onto this Support app origin.\n * Bare `\"/support\"` is Support home — not `https://avament.com/support`.\n */\nexport function resolveSupportAppPath(defaultRoute?: string | null): string {\n if (!defaultRoute) return \"/\";\n\n let path = defaultRoute.trim();\n try {\n if (path.startsWith(\"http://\") || path.startsWith(\"https://\")) {\n path = new URL(path).pathname;\n }\n } catch {\n return \"/\";\n }\n\n if (!path.startsWith(\"/\")) {\n path = `/${path}`;\n }\n\n if (path === \"/support\" || path === \"/support/\") {\n return \"/\";\n }\n\n return path;\n}\n\n/**\n * Support staff inbox (OWNER / DEV / STAFF or capability flags).\n * Matches contract: IsSupportStaff → list/get all, PATCH, assign, sequences, statistics.\n */\nexport function isSupportStaffUser(\n user?: Pick<User, \"role\" | \"capabilities\" | \"tenantRole\" | \"staffJob\" | \"assignments\"> | null,\n): boolean {\n if (!user) return false;\n if (user.capabilities?.isSupportStaff === true) return true;\n if (user.capabilities?.isPlatformElevated === true) return true;\n if (isStaffRole(user.role) || isPlatformAdminRole(user.role)) return true;\n if (isPlatformAdminRole(user.tenantRole ?? null)) return true;\n return resolveStaffJob(user) != null;\n}\n\n/**\n * OWNER / DEV may set assignee colors via `PATCH /api/auth/staff/{userId}`.\n * STAFF is always denied (403), including a scoped programmer whose tenant role is DEV.\n */\nexport function canManageStaffColors(\n user?: Pick<\n User,\n | \"role\"\n | \"capabilities\"\n | \"tenantRole\"\n | \"platformRole\"\n | \"staffJob\"\n | \"assignments\"\n > | null,\n): boolean {\n if (!user) return false;\n if (user.role?.toUpperCase() === \"STAFF\") return false;\n if (resolveStaffJob(user) != null) return false;\n return canConfigureSupportSettings(user);\n}\n\n/** OWNER / DEV only — configure Support project via PUT /api/support/settings. */\nexport function canConfigureSupportSettings(\n user?: Pick<User, \"role\" | \"capabilities\" | \"tenantRole\" | \"platformRole\"> | null,\n): boolean {\n if (!user) return false;\n if (user.capabilities?.isPlatformElevated === true) return true;\n if (isPlatformAdminRole(user.role)) return true;\n if (isPlatformAdminRole(user.platformRole ?? null)) return true;\n return isPlatformAdminRole(user.tenantRole ?? null);\n}\n\n/**\n * Assignee picker: OWNER/DEV + all STAFF (support + programmer).\n */\nexport function canAssignSupportReports(role?: string | null): boolean {\n if (isPlatformAdminRole(role)) return true;\n return role?.toUpperCase() === \"STAFF\";\n}\n\n/**\n * Single / Sequence / Multi — staff can choose; reporters stay on single.\n */\nexport function canChooseSupportAssignmentMode(\n user?: Pick<User, \"role\" | \"capabilities\" | \"tenantRole\" | \"staffJob\" | \"assignments\"> | null,\n): boolean {\n return isSupportStaffUser(user);\n}\n","\"use client\";\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport apiClient from \"@/api/client\";\nimport { authService } from \"@/api/auth\";\nimport type { User } from \"@/api/types\";\n\nexport interface UserUpdateDto {\n firstName: string;\n lastName: string;\n phoneNumber: string;\n companyName: string;\n}\n\nexport interface UserResponseDTO extends User {\n phoneNumber?: string;\n companyName?: string | null;\n}\n\nexport const userDataQueryKey = [\"userData\"] as const;\n\nexport const useUserInfo = () => {\n const queryClient = useQueryClient();\n\n const userInfoQuery = useQuery({\n queryKey: userDataQueryKey,\n queryFn: async (): Promise<UserResponseDTO | null> => {\n const response = await apiClient.get<UserResponseDTO>(\"/auth/me\");\n return response.data ?? null;\n },\n });\n\n const updateUserInfoMutation = useMutation({\n mutationFn: async (userData: UserUpdateDto): Promise<UserResponseDTO | null> => {\n const response = await apiClient.post<UserResponseDTO>(\n \"/auth/update-profile\",\n userData,\n );\n return response.data ?? null;\n },\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: userDataQueryKey });\n await authService.getCurrentUser();\n },\n });\n\n return {\n userInfo: userInfoQuery.data,\n isLoading: userInfoQuery.isLoading,\n isError: userInfoQuery.isError,\n error: userInfoQuery.error,\n updateUserInfo: updateUserInfoMutation.mutate,\n isUpdating: updateUserInfoMutation.isPending,\n refetch: userInfoQuery.refetch,\n };\n};\n","export const WORKSPACE_CONTEXT_CHANGED_EVENT = \"support-workspace-context-changed\";\n\nexport function dispatchWorkspaceContextChanged(): void {\n if (typeof window === \"undefined\") return;\n window.dispatchEvent(new CustomEvent(WORKSPACE_CONTEXT_CHANGED_EVENT));\n}\n\nexport function subscribeWorkspaceContextChanged(handler: () => void): () => void {\n if (typeof window === \"undefined\") return () => {};\n window.addEventListener(WORKSPACE_CONTEXT_CHANGED_EVENT, handler);\n return () => window.removeEventListener(WORKSPACE_CONTEXT_CHANGED_EVENT, handler);\n}\n\nexport const PROJECT_CONTEXT_CHANGED_EVENT = \"support-project-context-changed\";\n\nexport function dispatchProjectContextChanged(): void {\n if (typeof window === \"undefined\") return;\n window.dispatchEvent(new CustomEvent(PROJECT_CONTEXT_CHANGED_EVENT));\n}\n\nexport function subscribeProjectContextChanged(handler: () => void): () => void {\n if (typeof window === \"undefined\") return () => {};\n window.addEventListener(PROJECT_CONTEXT_CHANGED_EVENT, handler);\n return () => window.removeEventListener(PROJECT_CONTEXT_CHANGED_EVENT, handler);\n}\n","import apiClient from \"./client\";\nimport {\n markLogoutRedirect,\n redirectToMainApp,\n} from \"@/lib/auth/constants\";\nimport { isSharedCookieContext } from \"@/lib/auth/cookieDomain\";\nimport { tokenService } from \"@/lib/auth/tokenService\";\nimport { storageService, STORAGE_KEYS } from \"@/lib/services\";\nimport {\n dispatchProjectContextChanged,\n dispatchWorkspaceContextChanged,\n} from \"@/lib/workspaceContext\";\nimport type {\n RegisterRequest,\n LoginRequest,\n AuthResponse,\n SelectTenantRequest,\n SelectProjectRequest,\n Workspace,\n Project,\n User,\n} from \"./types\";\n\nexport const authService = {\n register: async (data: RegisterRequest): Promise<AuthResponse> => {\n const response = await apiClient.post<AuthResponse>(\"/auth/register\", data);\n if (response.data.token) {\n storageService.setString(STORAGE_KEYS.ACCESS_TOKEN, response.data.token);\n if (response.data.tenant?.id) {\n storageService.setString(STORAGE_KEYS.TENANT_ID, response.data.tenant.id);\n }\n if (response.data.user) {\n storageService.set(STORAGE_KEYS.USER, response.data.user);\n }\n }\n return response.data;\n },\n\n login: async (data: LoginRequest): Promise<AuthResponse> => {\n const response = await apiClient.post<AuthResponse>(\"/auth/login\", data);\n if (response.data.token) {\n storageService.setString(STORAGE_KEYS.ACCESS_TOKEN, response.data.token);\n if (response.data.tenants && response.data.tenants.length > 0) {\n storageService.setString(\n STORAGE_KEYS.TENANT_ID,\n response.data.tenants[0].tenantId || \"\",\n );\n }\n if (response.data.user) {\n storageService.set(STORAGE_KEYS.USER, response.data.user);\n }\n }\n return response.data;\n },\n\n /**\n * Wipe shared SSO cookies and leave Support for avament.com.\n * Best-effort BE logout first so HttpOnly cookies can be cleared server-side.\n */\n logout: async (): Promise<void> => {\n markLogoutRedirect();\n\n try {\n await apiClient.post(\"/auth/logout\");\n } catch {\n /* client-side clear + redirect still proceed */\n }\n\n storageService.remove(STORAGE_KEYS.ACCESS_TOKEN);\n storageService.remove(STORAGE_KEYS.TIMELINE_ID);\n storageService.remove(STORAGE_KEYS.PROJECT_ID);\n storageService.remove(STORAGE_KEYS.TENANT_ID);\n storageService.remove(STORAGE_KEYS.USER);\n\n redirectToMainApp();\n },\n\n selectTenant: async (data: SelectTenantRequest): Promise<AuthResponse> => {\n const response = await apiClient.post<AuthResponse>(\"/auth/select-tenant\", data);\n if (response.data.token) {\n storageService.setString(STORAGE_KEYS.ACCESS_TOKEN, response.data.token);\n if (response.data.tenant?.id) {\n storageService.setString(STORAGE_KEYS.TENANT_ID, response.data.tenant.id);\n }\n }\n return response.data;\n },\n\n getMyWorkspace: async (): Promise<Workspace> => {\n const response = await apiClient.get<Workspace>(\"/auth/my-workspace\");\n return response.data;\n },\n\n getAllWorkspaces: async (): Promise<Workspace[]> => {\n const response = await apiClient.get<unknown>(\"/auth/workspaces\");\n const data = response.data;\n if (Array.isArray(data)) return data as Workspace[];\n if (data && typeof data === \"object\") {\n const record = data as Record<string, unknown>;\n for (const key of [\"items\", \"data\", \"workspaces\", \"results\"] as const) {\n const value = record[key];\n if (Array.isArray(value)) return value as Workspace[];\n }\n }\n return [];\n },\n\n getProjects: async (): Promise<Project[]> => {\n const response = await apiClient.get<Project[]>(\"/projects\");\n return response.data;\n },\n\n selectProject: async (\n data: SelectProjectRequest,\n ): Promise<AuthResponse & { projectId: string }> => {\n const previousProjectId = storageService.getString(STORAGE_KEYS.PROJECT_ID);\n const response = await apiClient.post<AuthResponse & { projectId: string }>(\n \"/auth/select-project\",\n data,\n );\n if (response.data.token) {\n storageService.setString(STORAGE_KEYS.ACCESS_TOKEN, response.data.token);\n }\n const nextProjectId = response.data.projectId ?? null;\n const projectChanged = Boolean(nextProjectId && nextProjectId !== previousProjectId);\n if (projectChanged) {\n storageService.remove(STORAGE_KEYS.TIMELINE_ID);\n }\n if (response.data.projectId) {\n storageService.setString(STORAGE_KEYS.PROJECT_ID, response.data.projectId);\n }\n if (projectChanged) {\n dispatchProjectContextChanged();\n }\n return response.data;\n },\n\n getCurrentUser: async (): Promise<User> => {\n const response = await apiClient.get<User>(\"/auth/me\");\n if (response.data) {\n const user = response.data;\n storageService.set(STORAGE_KEYS.USER, user);\n\n const hasRemoteTenantContext =\n Object.prototype.hasOwnProperty.call(user, \"currentTenantId\") ||\n Object.prototype.hasOwnProperty.call(user, \"tenantId\");\n const hasRemoteProjectContext =\n Object.prototype.hasOwnProperty.call(user, \"selectedProjectId\") ||\n Object.prototype.hasOwnProperty.call(user, \"projectId\");\n const remoteTenantId = user.currentTenantId ?? user.tenantId ?? null;\n const remoteProjectId = user.selectedProjectId ?? user.projectId ?? null;\n const prevTenantId = storageService.getString(STORAGE_KEYS.TENANT_ID);\n const prevProjectId = storageService.getString(STORAGE_KEYS.PROJECT_ID);\n const sharedCookies = isSharedCookieContext();\n\n if (!sharedCookies) {\n if (hasRemoteTenantContext && remoteTenantId && remoteTenantId !== prevTenantId) {\n storageService.setString(STORAGE_KEYS.TENANT_ID, remoteTenantId);\n storageService.remove(STORAGE_KEYS.PROJECT_ID);\n storageService.remove(STORAGE_KEYS.TIMELINE_ID);\n dispatchWorkspaceContextChanged();\n }\n\n if (hasRemoteProjectContext && remoteProjectId && remoteProjectId !== prevProjectId) {\n storageService.setString(STORAGE_KEYS.PROJECT_ID, remoteProjectId);\n storageService.remove(STORAGE_KEYS.TIMELINE_ID);\n dispatchProjectContextChanged();\n }\n\n if (hasRemoteProjectContext && !remoteProjectId && prevProjectId) {\n storageService.remove(STORAGE_KEYS.PROJECT_ID);\n storageService.remove(STORAGE_KEYS.TIMELINE_ID);\n dispatchProjectContextChanged();\n }\n }\n }\n return response.data;\n },\n\n isAuthenticated: (): boolean => {\n // Shared SSO may expose access_token, refresh_token, and/or is_authenticated.\n return Boolean(\n storageService.getString(STORAGE_KEYS.ACCESS_TOKEN) ||\n tokenService.getRefreshToken() ||\n tokenService.getIsAuthenticated() === \"true\",\n );\n },\n\n getStoredUser: (): User | null => {\n return storageService.get<User>(STORAGE_KEYS.USER);\n },\n};\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n getRecentCatalogIds,\n loadCatalogRecentIds,\n recordCatalogUsage,\n TICKET_CATALOG_RECENT_LIMIT,\n type TicketCatalogUsageKind,\n} from \"@/lib/tickets/ticketCatalogUsageMemory\";\n\nexport function useTicketCatalogUsageMemory(\n kind: TicketCatalogUsageKind,\n projectId: string | null | undefined,\n) {\n const [version, setVersion] = React.useState(0);\n\n const recentIds = React.useMemo(() => {\n void version;\n return loadCatalogRecentIds(projectId, kind);\n }, [kind, projectId, version]);\n\n const record = React.useCallback(\n (id: string) => {\n recordCatalogUsage(projectId, kind, id);\n setVersion((current) => current + 1);\n },\n [kind, projectId],\n );\n\n const getRecentIds = React.useCallback(\n (availableIds: Iterable<string>, limit = TICKET_CATALOG_RECENT_LIMIT) =>\n getRecentCatalogIds(recentIds, availableIds, limit),\n [recentIds],\n );\n\n return { record, getRecentIds };\n}\n","export type TicketCatalogUsageKind = \"type\" | \"event\";\n\nexport const TICKET_CATALOG_RECENT_LIMIT = 3;\n\nconst STORAGE_PREFIX = \"ticket-catalog-usage\";\n\nfunction storageKey(\n projectId: string,\n kind: TicketCatalogUsageKind,\n): string {\n return `${STORAGE_PREFIX}:${projectId}:${kind}`;\n}\n\n/**\n * Parses stored recent ids (most-recent first).\n * Migrates legacy frequency maps `{ id: count }` once by count desc.\n */\nfunction parseRecentIds(raw: string | null): string[] {\n if (!raw) return [];\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (Array.isArray(parsed)) {\n const seen = new Set<string>();\n const ids: string[] = [];\n for (const value of parsed) {\n if (typeof value !== \"string\") continue;\n const id = value.trim();\n if (!id || seen.has(id)) continue;\n seen.add(id);\n ids.push(id);\n }\n return ids;\n }\n if (parsed && typeof parsed === \"object\") {\n const entries: Array<{ id: string; count: number }> = [];\n for (const [rawId, value] of Object.entries(parsed)) {\n const id = rawId.trim();\n if (\n !id ||\n typeof value !== \"number\" ||\n !Number.isFinite(value) ||\n value <= 0\n ) {\n continue;\n }\n entries.push({ id, count: Math.floor(value) });\n }\n return entries\n .sort((a, b) => b.count - a.count || a.id.localeCompare(b.id))\n .map((entry) => entry.id);\n }\n return [];\n } catch {\n return [];\n }\n}\n\nfunction persistRecentIds(\n projectId: string,\n kind: TicketCatalogUsageKind,\n ids: readonly string[],\n): void {\n try {\n localStorage.setItem(\n storageKey(projectId, kind),\n JSON.stringify(ids.slice(0, TICKET_CATALOG_RECENT_LIMIT)),\n );\n } catch {\n /* ignore quota / private mode */\n }\n}\n\nexport function loadCatalogRecentIds(\n projectId: string | null | undefined,\n kind: TicketCatalogUsageKind,\n): string[] {\n if (typeof window === \"undefined\" || !projectId) return [];\n try {\n return parseRecentIds(localStorage.getItem(storageKey(projectId, kind)));\n } catch {\n return [];\n }\n}\n\nexport function recordCatalogUsage(\n projectId: string | null | undefined,\n kind: TicketCatalogUsageKind,\n id: string,\n): string[] {\n const trimmed = id.trim();\n if (typeof window === \"undefined\" || !projectId || !trimmed) {\n return loadCatalogRecentIds(projectId, kind);\n }\n\n const previous = loadCatalogRecentIds(projectId, kind);\n const next = [\n trimmed,\n ...previous.filter((existing) => existing !== trimmed),\n ].slice(0, TICKET_CATALOG_RECENT_LIMIT);\n\n persistRecentIds(projectId, kind, next);\n return next;\n}\n\n/** Most-recent ids first among those still available. */\nexport function getRecentCatalogIds(\n recentIds: readonly string[],\n availableIds: Iterable<string>,\n limit = TICKET_CATALOG_RECENT_LIMIT,\n): string[] {\n const available = new Set(availableIds);\n return recentIds.filter((id) => available.has(id)).slice(0, limit);\n}\n\n/**\n * Splits items into an elevated recent section and the full list.\n * Recent items stay in `rest` so elevation does not remove them from below.\n */\nexport function partitionCatalogByRecent<T>(\n items: readonly T[],\n getId: (item: T) => string,\n recentIds: readonly string[],\n): { recent: T[]; rest: T[] } {\n if (recentIds.length === 0) {\n return { recent: [], rest: [...items] };\n }\n\n const byId = new Map(items.map((item) => [getId(item), item]));\n const recent: T[] = [];\n for (const id of recentIds) {\n const item = byId.get(id);\n if (item) recent.push(item);\n }\n return { recent, rest: [...items] };\n}\n","export function catalogNameExists(\n existingNames: Iterable<string | null | undefined>,\n candidate: string,\n): boolean {\n const normalized = candidate.trim().toLocaleLowerCase();\n if (!normalized) return false;\n\n for (const name of existingNames) {\n if (name?.trim().toLocaleLowerCase() === normalized) return true;\n }\n\n return false;\n}\n","import type { TFunction } from \"i18next\";\n\nimport type { TicketRow } from \"@/lib/tickets/ticketRow\";\n\nfunction ticketsUsingType(tickets: TicketRow[], typeKey: string): TicketRow[] {\n return tickets.filter((ticket) => ticket.typeKey === typeKey);\n}\n\nfunction ticketsUsingEvent(\n tickets: TicketRow[],\n event: { id: string; name: string },\n): TicketRow[] {\n return tickets.filter(\n (ticket) =>\n ticket.eventId === event.id || ticket.event === event.name,\n );\n}\n\nexport function countTicketsUsingType(\n tickets: TicketRow[],\n typeKey: string,\n): number {\n return ticketsUsingType(tickets, typeKey).length;\n}\n\nexport function countTicketsUsingEvent(\n tickets: TicketRow[],\n event: { id: string; name: string },\n): number {\n return ticketsUsingEvent(tickets, event).length;\n}\n\nexport function getTicketIdsUsingType(\n tickets: TicketRow[],\n typeKey: string,\n): string[] {\n return ticketsUsingType(tickets, typeKey).map((ticket) => ticket.id);\n}\n\nexport function getTicketIdsUsingEvent(\n tickets: TicketRow[],\n event: { id: string; name: string },\n): string[] {\n return ticketsUsingEvent(tickets, event).map((ticket) => ticket.id);\n}\n\nexport function ticketTypeDeleteDescription(\n t: TFunction,\n label: string,\n assignedCount: number,\n): string {\n if (assignedCount > 0) {\n return t(\"ticket.create_dialog.types.delete_confirm_in_use\", {\n label,\n count: assignedCount,\n });\n }\n return t(\"ticket.create_dialog.types.delete_confirm\", { label });\n}\n\nexport function ticketEventDeleteDescription(\n t: TFunction,\n name: string,\n assignedCount: number,\n): string {\n if (assignedCount > 0) {\n return t(\"ticket.create_dialog.events.delete_confirm_in_use\", {\n name,\n count: assignedCount,\n });\n }\n return t(\"ticket.create_dialog.events.delete_confirm\", { name });\n}\n\nexport function ticketResponsibleDeleteDescription(\n t: TFunction,\n name: string,\n): string {\n return t(\"ticket.create_dialog.responsibles.delete_confirm\", { name });\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport {\n ColorPickerField as SharedColorPickerField,\n ColorPickerPopover as SharedColorPickerPopover,\n ColorSwatch,\n} from \"@/components/ui/color-picker\";\nimport type { ColorPickerLabels } from \"@/components/ui/color-picker\";\n\nexport { ColorSwatch as TicketCatalogColorSwatch };\n\nfunction useTicketCatalogColorLabels(): ColorPickerLabels {\n const { t } = useTranslation();\n return React.useMemo(\n () => ({\n editAriaLabel: t(\"ticket.catalog.color_edit\"),\n pickerAriaLabel: t(\"ticket.catalog.color_picker\"),\n hexLabel: \"HEX\",\n cancelLabel: t(\"cancel\"),\n saveLabel: t(\"common.save\"),\n }),\n [t],\n );\n}\n\ntype TicketCatalogColorPopoverProps = {\n color: string;\n onSave: (color: string) => Promise<void>;\n disabled?: boolean;\n className?: string;\n onOpenChange?: (open: boolean) => void;\n};\n\n/** Palette button that opens a HEX-first color picker; Save/Cancel close it. */\nexport function TicketCatalogColorPopover({\n color,\n onSave,\n disabled = false,\n className,\n onOpenChange,\n}: TicketCatalogColorPopoverProps) {\n const labels = useTicketCatalogColorLabels();\n return (\n <SharedColorPickerPopover\n color={color}\n onSave={onSave}\n disabled={disabled}\n className={className}\n labels={labels}\n onOpenChange={onOpenChange}\n />\n );\n}\n\n/** Palette button for add dialogs — HEX-first picker; Save/Cancel close it. */\nexport function TicketCatalogColorField({\n value,\n onChange,\n disabled = false,\n className,\n onOpenChange,\n}: {\n value: string;\n onChange: (color: string) => void;\n disabled?: boolean;\n className?: string;\n onOpenChange?: (open: boolean) => void;\n}) {\n const labels = useTicketCatalogColorLabels();\n return (\n <SharedColorPickerField\n value={value}\n onChange={onChange}\n disabled={disabled}\n className={className}\n labels={labels}\n onOpenChange={onOpenChange}\n />\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { Select as CatalogSelect, type SelectOption } from \"@avament-pub/select\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { SupportTicketTypeIcon } from \"@/components/tickets/SupportTicketTypeIcon\";\nimport { useTicketTypes } from \"@/hooks/useTicketTypes\";\nimport { useTicketCatalogUsageMemory } from \"@/hooks/useTicketCatalogUsageMemory\";\nimport { cn } from \"@/lib/utils\";\n\ntype SupportTicketTypeSelectProps = {\n value: string;\n onChange: (typeKey: string) => void;\n disabled?: boolean;\n clearable?: boolean;\n placeholder?: string;\n className?: string;\n};\n\n/**\n * Fixed Support types (idea / problem / question / task).\n * Same catalog Select as ticket, without add/edit/delete — that catalog is fixed.\n */\nexport function SupportTicketTypeSelect({\n value,\n onChange,\n disabled = false,\n clearable = true,\n placeholder,\n className,\n}: SupportTicketTypeSelectProps) {\n const { t } = useTranslation();\n const { types } = useTicketTypes();\n const { record: recordTypeUsage, getRecentIds } = useTicketCatalogUsageMemory(\n \"type\",\n \"support\",\n );\n\n const options = React.useMemo<SelectOption[]>(\n () =>\n types.map((type) => ({\n value: type.key,\n label: type.label,\n icon: <SupportTicketTypeIcon typeKey={type.key} />,\n })),\n [types],\n );\n\n const recentValues = React.useMemo(\n () => getRecentIds(types.map((type) => type.key)),\n [getRecentIds, types],\n );\n\n return (\n <div className={cn(\"min-w-0\", className)}>\n <CatalogSelect\n mode=\"searchable\"\n options={options}\n value={value || null}\n onChange={(next) => {\n if (!next) {\n onChange(\"\");\n return;\n }\n recordTypeUsage(next);\n onChange(next);\n }}\n disabled={disabled}\n clearable={clearable}\n placeholder={placeholder ?? t(\"ticket.create_dialog.select_placeholder\")}\n showRecent\n recentValues={recentValues}\n sortAlphabetically\n labels={{\n searchPlaceholder: t(\"ticket.table.search_placeholder\"),\n clearAriaLabel: t(\"ticket.create_dialog.type_clear\"),\n emptyMessage: t(\"ticket.create_dialog.types.empty\", {\n defaultValue: \"No types\",\n }),\n }}\n />\n </div>\n );\n}\n","import type { LucideIcon } from \"lucide-react\";\nimport Lightbulb from \"lucide-react/dist/esm/icons/lightbulb\";\nimport Bug from \"lucide-react/dist/esm/icons/bug\";\nimport CircleHelp from \"lucide-react/dist/esm/icons/circle-help\";\nimport FileText from \"lucide-react/dist/esm/icons/file-text\";\n\nimport type { TicketPriorityKey } from \"@/lib/tickets/ticketRow\";\n\n/** Fixed Support ticket types — not a project catalog. */\nexport const SUPPORT_TICKET_TYPE_KEYS = [\n \"idea\",\n \"problem\",\n \"question\",\n \"task\",\n] as const;\n\nexport type SupportTicketTypeKey = (typeof SUPPORT_TICKET_TYPE_KEYS)[number];\n\n/** Default type pre-selected when creating a new Support report. */\nexport const DEFAULT_SUPPORT_TICKET_TYPE_KEY: SupportTicketTypeKey = \"task\";\n\n/** Default priority pre-selected when creating a new Support report. */\nexport const DEFAULT_SUPPORT_TICKET_PRIORITY_KEY: TicketPriorityKey = \"medium\";\n\nexport const SUPPORT_TICKET_TYPE_COLORS: Record<SupportTicketTypeKey, string> = {\n idea: \"#7c3aed\",\n problem: \"#dc2626\",\n question: \"#2563eb\",\n task: \"#0d9488\",\n};\n\nexport const SUPPORT_TICKET_TYPE_ICONS: Record<SupportTicketTypeKey, LucideIcon> =\n {\n idea: Lightbulb,\n problem: Bug,\n question: CircleHelp,\n task: FileText,\n };\n\nexport function isSupportTicketTypeKey(\n value: string | null | undefined,\n): value is SupportTicketTypeKey {\n return (\n typeof value === \"string\" &&\n (SUPPORT_TICKET_TYPE_KEYS as readonly string[]).includes(value)\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n isSupportTicketTypeKey,\n SUPPORT_TICKET_TYPE_COLORS,\n SUPPORT_TICKET_TYPE_ICONS,\n} from \"@/lib/tickets/supportTicketTypes\";\nimport { cn } from \"@/lib/utils\";\n\ntype SupportTicketTypeIconProps = {\n typeKey: string | null | undefined;\n className?: string;\n /** When true, tint the icon with the type color. */\n colored?: boolean;\n};\n\nexport function SupportTicketTypeIcon({\n typeKey,\n className,\n colored = true,\n}: SupportTicketTypeIconProps) {\n if (!isSupportTicketTypeKey(typeKey)) return null;\n const Icon = SUPPORT_TICKET_TYPE_ICONS[typeKey];\n const color = SUPPORT_TICKET_TYPE_COLORS[typeKey];\n return (\n <Icon\n className={cn(\"h-3.5 w-3.5 shrink-0\", className)}\n style={colored ? { color } : undefined}\n aria-hidden\n />\n );\n}\n\ntype SupportTicketTypeLabelProps = {\n typeKey: string;\n label: string;\n className?: string;\n showIcon?: boolean;\n};\n\nexport function SupportTicketTypeLabel({\n typeKey,\n label,\n className,\n showIcon = true,\n}: SupportTicketTypeLabelProps) {\n const color = isSupportTicketTypeKey(typeKey)\n ? SUPPORT_TICKET_TYPE_COLORS[typeKey]\n : undefined;\n\n return (\n <span className={cn(\"inline-flex min-w-0 items-center gap-2\", className)}>\n {showIcon ? <SupportTicketTypeIcon typeKey={typeKey} /> : null}\n <span className=\"truncate font-medium\" style={color ? { color } : undefined}>\n {label}\n </span>\n </span>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useTranslation } from \"react-i18next\";\n\nimport type { TicketTypeDto } from \"@/api/dto/ticket.dto\";\nimport { getProjectId } from \"@/api/client\";\nimport { ticketTypeKeys, ticketKeys } from \"@/hooks/queries/query-keys\";\nimport {\n SUPPORT_TICKET_TYPE_COLORS,\n SUPPORT_TICKET_TYPE_KEYS,\n type SupportTicketTypeKey,\n} from \"@/lib/tickets/supportTicketTypes\";\n\nexport type TicketType = TicketTypeDto;\n\nexport type CreateTicketTypeInput = {\n label: string;\n key?: string | null;\n color?: string | null;\n};\n\nexport type UpdateTicketTypeInput = {\n label: string;\n color?: string | null;\n colorUnchanged?: boolean;\n};\n\nfunction buildFixedSupportTypes(\n t: (key: string, options?: { defaultValue?: string }) => string,\n): TicketTypeDto[] {\n return SUPPORT_TICKET_TYPE_KEYS.map((key) => ({\n id: key,\n key,\n label: t(`support.type.${key}`, {\n defaultValue: key.charAt(0).toUpperCase() + key.slice(1),\n }),\n isDefault: true,\n color: SUPPORT_TICKET_TYPE_COLORS[key as SupportTicketTypeKey],\n }));\n}\n\n/**\n * Support types are a fixed catalog (idea / problem / question / task).\n * No create/edit/delete API under `/api/support`.\n */\nexport function useTicketTypes(_projectId?: string | null) {\n const { t } = useTranslation();\n const queryClient = useQueryClient();\n\n const types = React.useMemo(() => buildFixedSupportTypes(t), [t]);\n\n const query = useQuery({\n queryKey: ticketTypeKeys.list(),\n queryFn: async (): Promise<TicketTypeDto[]> => types,\n staleTime: Infinity,\n });\n\n const invalidate = async () => {\n await queryClient.invalidateQueries({ queryKey: ticketKeys.all });\n };\n\n return {\n projectId: getProjectId(),\n /** Fixed Support catalog — UI must not offer add/edit/delete. */\n catalogEditable: false as const,\n isMutating: false,\n types,\n isLoading: query.isLoading,\n isError: false,\n refresh: query.refetch,\n createType: async (_input: CreateTicketTypeInput): Promise<TicketTypeDto> => {\n throw new Error(\"Support ticket types are fixed.\");\n },\n updateType: async (\n _typeId: string,\n _input: UpdateTicketTypeInput,\n ): Promise<TicketTypeDto> => {\n throw new Error(\"Support ticket types are fixed.\");\n },\n deleteType: async (\n _typeId: string,\n _options?: { unassignTicketIds?: string[] },\n ) => {\n await invalidate();\n },\n };\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { useLatestRef } from \"@/hooks/useLatestRef\";\nimport { useUserInfo } from \"@/hooks/useUserInfo\";\nimport { isGuestUser } from \"@/lib/auth/roles\";\nimport {\n ATTACHMENT_PROCESS_CONCURRENCY,\n createLocalTicketAttachment,\n createReadyLocalTicketAttachment,\n getReadyAttachmentFiles,\n hasProcessingAttachments,\n isHeicAttachmentFile,\n isTicketImageFile,\n isTicketVideoFile,\n MAX_TICKET_ATTACHMENTS,\n normalizeTicketAttachmentFile,\n processLocalTicketAttachment,\n type LocalTicketAttachment,\n type TicketAttachmentErrorCode,\n type TicketAttachmentPrepareOptions,\n} from \"@/lib/tickets/ticketAttachments\";\n\nconst ATTACHMENT_ERROR_KEYS: Record<TicketAttachmentErrorCode, string> = {\n invalid_type: \"ticket.create_dialog.attachments_invalid_type\",\n empty: \"ticket.create_dialog.attachments_empty\",\n video_too_large: \"ticket.create_dialog.attachments_video_too_large\",\n max_exceeded: \"ticket.create_dialog.attachments_max\",\n heic_convert_failed: \"ticket.create_dialog.attachments_heic_convert_failed\",\n};\n\nconst PLAN_IMAGE_ERROR_KEYS: Record<TicketAttachmentErrorCode, string> = {\n ...ATTACHMENT_ERROR_KEYS,\n invalid_type: \"ticket.create_dialog.plan_images_invalid_type\",\n};\n\ntype UseLocalTicketAttachmentsOptions = {\n /** Stored files already counting toward the shared max (both pools). */\n existingCount: number;\n /** Local items in the sibling pool; read at add time. */\n getSiblingCount?: () => number;\n /** When true, reject videos (plan-image pool). */\n imageOnly?: boolean;\n};\n\nexport function useLocalTicketAttachments({\n existingCount,\n getSiblingCount,\n imageOnly = false,\n}: UseLocalTicketAttachmentsOptions) {\n const { t } = useTranslation();\n const { userInfo } = useUserInfo();\n const isGuest = isGuestUser(userInfo);\n const errorKeys = imageOnly ? PLAN_IMAGE_ERROR_KEYS : ATTACHMENT_ERROR_KEYS;\n const getSiblingCountRef = useLatestRef(getSiblingCount);\n\n const prepareOptions = React.useMemo<TicketAttachmentPrepareOptions>(\n () => ({\n guestBorder: isGuest,\n }),\n [isGuest],\n );\n const prepareOptionsRef = useLatestRef(prepareOptions);\n\n const decorateImages = Boolean(prepareOptions.guestBorder);\n\n const [attachments, setAttachments] = React.useState<LocalTicketAttachment[]>(\n [],\n );\n const [attachmentError, setAttachmentError] = React.useState<string | null>(\n null,\n );\n const cancelledIdsRef = React.useRef(new Set<string>());\n const activeJobsRef = React.useRef(0);\n const queueRef = React.useRef<LocalTicketAttachment[]>([]);\n const attachmentsRef = useLatestRef(attachments);\n const pumpQueueRef = React.useRef<() => void>(() => {});\n\n const clearAttachments = React.useCallback(() => {\n for (const item of attachmentsRef.current) {\n cancelledIdsRef.current.add(item.id);\n }\n queueRef.current = [];\n setAttachments([]);\n setAttachmentError(null);\n }, [attachmentsRef]);\n\n const pumpQueue = React.useCallback(() => {\n while (\n activeJobsRef.current < ATTACHMENT_PROCESS_CONCURRENCY &&\n queueRef.current.length > 0\n ) {\n const item = queueRef.current.shift();\n if (!item) break;\n if (cancelledIdsRef.current.has(item.id)) continue;\n\n activeJobsRef.current += 1;\n void processLocalTicketAttachment(item, prepareOptionsRef.current)\n .then((result) => {\n if (cancelledIdsRef.current.has(item.id)) return;\n setAttachments((prev) => {\n const index = prev.findIndex((candidate) => candidate.id === item.id);\n if (index < 0) return prev;\n const next = [...prev];\n next[index] = result;\n return next;\n });\n if (result.status === \"error\" && result.error) {\n setAttachmentError(\n t(errorKeys[result.error], {\n max: MAX_TICKET_ATTACHMENTS,\n }),\n );\n }\n })\n .finally(() => {\n activeJobsRef.current -= 1;\n pumpQueueRef.current();\n });\n }\n }, [errorKeys, prepareOptionsRef, t]);\n\n React.useLayoutEffect(() => {\n pumpQueueRef.current = pumpQueue;\n });\n\n const enqueueProcessing = React.useCallback(\n (items: LocalTicketAttachment[]) => {\n const pending = items.filter((item) => item.status === \"processing\");\n if (!pending.length) return;\n queueRef.current.push(...pending);\n pumpQueue();\n },\n [pumpQueue],\n );\n\n const addFiles = React.useCallback(\n (files: FileList | File[]) => {\n const incoming = Array.from(files).filter(\n (file): file is File => file instanceof File && Boolean(file.name),\n );\n if (!incoming.length) return;\n\n const prev = attachmentsRef.current;\n const sibling = getSiblingCountRef.current?.() ?? 0;\n const remaining =\n MAX_TICKET_ATTACHMENTS - existingCount - sibling - prev.length;\n if (remaining <= 0) {\n setAttachmentError(\n t(errorKeys.max_exceeded, {\n max: MAX_TICKET_ATTACHMENTS,\n }),\n );\n return;\n }\n\n const created = incoming.map((file) =>\n createLocalTicketAttachment(file, { decorateImages, imageOnly }),\n );\n const accepted = created.slice(0, remaining);\n const overflow = created.length > remaining;\n const firstInstantError = accepted.find(\n (item) => item.status === \"error\" && item.error,\n );\n const toAdd = accepted.filter((item) => item.status !== \"error\");\n\n if (firstInstantError?.error) {\n setAttachmentError(\n t(errorKeys[firstInstantError.error], {\n max: MAX_TICKET_ATTACHMENTS,\n }),\n );\n } else if (overflow) {\n setAttachmentError(\n t(errorKeys.max_exceeded, {\n max: MAX_TICKET_ATTACHMENTS,\n }),\n );\n } else {\n setAttachmentError(null);\n }\n\n if (!toAdd.length) return;\n\n setAttachments((current) => [...current, ...toAdd]);\n enqueueProcessing(toAdd);\n },\n [attachmentsRef, decorateImages, enqueueProcessing, errorKeys, existingCount, getSiblingCountRef, imageOnly, t],\n );\n\n const removeAttachment = React.useCallback((id: string) => {\n cancelledIdsRef.current.add(id);\n queueRef.current = queueRef.current.filter((item) => item.id !== id);\n setAttachments((prev) => prev.filter((item) => item.id !== id));\n setAttachmentError(null);\n }, []);\n\n const replaceAttachmentFile = React.useCallback(\n (id: string, file: File) => {\n if (imageOnly && isTicketVideoFile(file)) {\n setAttachmentError(t(errorKeys.invalid_type));\n return;\n }\n\n const normalized = normalizeTicketAttachmentFile(file);\n const needsProcess =\n isHeicAttachmentFile(normalized) ||\n (decorateImages &&\n isTicketImageFile(normalized) &&\n !isTicketVideoFile(normalized));\n\n if (needsProcess) {\n const pending: LocalTicketAttachment = {\n id,\n original: normalized,\n file: null,\n status: \"processing\",\n error: null,\n };\n setAttachments((prev) =>\n prev.map((item) => (item.id === id ? pending : item)),\n );\n setAttachmentError(null);\n enqueueProcessing([pending]);\n return;\n }\n\n const next = createReadyLocalTicketAttachment(file);\n setAttachments((prev) =>\n prev.map((item) =>\n item.id === id\n ? { ...next, id } // keep stable list id\n : item,\n ),\n );\n setAttachmentError(null);\n },\n [decorateImages, enqueueProcessing, errorKeys, imageOnly, t],\n );\n\n const appendReadyFile = React.useCallback(\n (file: File) => {\n const prev = attachmentsRef.current;\n const sibling = getSiblingCountRef.current?.() ?? 0;\n const remaining =\n MAX_TICKET_ATTACHMENTS - existingCount - sibling - prev.length;\n if (remaining <= 0) {\n setAttachmentError(\n t(errorKeys.max_exceeded, {\n max: MAX_TICKET_ATTACHMENTS,\n }),\n );\n return;\n }\n\n const next = createLocalTicketAttachment(file, {\n decorateImages,\n imageOnly,\n });\n if (next.status === \"error\") {\n if (next.error) {\n setAttachmentError(\n t(errorKeys[next.error], {\n max: MAX_TICKET_ATTACHMENTS,\n }),\n );\n }\n return;\n }\n\n setAttachments((current) => [...current, next]);\n setAttachmentError(null);\n enqueueProcessing([next]);\n },\n [attachmentsRef, decorateImages, enqueueProcessing, errorKeys, existingCount, getSiblingCountRef, imageOnly, t],\n );\n\n const readyFiles = React.useMemo(\n () => getReadyAttachmentFiles(attachments),\n [attachments],\n );\n const isProcessing = hasProcessingAttachments(attachments);\n const totalCount = existingCount + attachments.length;\n\n return {\n attachments,\n attachmentError,\n readyFiles,\n isProcessing,\n totalCount,\n addFiles,\n removeAttachment,\n replaceAttachmentFile,\n appendReadyFile,\n clearAttachments,\n setAttachmentError,\n };\n}\n","import { storageService, STORAGE_KEYS } from \"@/lib/services\";\nimport { isSupportStaffUser, resolveStaffJob } from \"@/lib/auth/isStaffRole\";\n\nexport type AuthMe = {\n platformRole?: string | null;\n tenantRole?: string | null;\n staffJob?: string | null;\n /** @deprecated Prefer platformRole + tenantRole */\n role?: string | null;\n accountType?: string | null;\n capabilities?: {\n isPlatformElevated?: boolean;\n isScopedProgrammer?: boolean;\n isSupportStaff?: boolean;\n } | null;\n};\n\ntype ModuleNeed = \"read\" | \"write\" | \"admin\";\n\nconst MODULE_RANK: Record<ModuleNeed, number> = {\n read: 1,\n write: 2,\n admin: 3,\n};\n\nexport function normalizeRole(role: unknown): string {\n return String(role ?? \"\")\n .trim()\n .toUpperCase()\n .replace(/[\\s-]+/g, \"_\");\n}\n\nexport function isGuestUser(\n user: { accountType?: string | null } | null | undefined,\n): boolean {\n return normalizeRole(user?.accountType) === \"GUEST\";\n}\n\nfunction decodeJwtPayload(\n token: string | null | undefined,\n): Record<string, unknown> | null {\n if (!token || typeof atob !== \"function\") return null;\n const parts = token.split(\".\");\n if (parts.length < 2) return null;\n try {\n const base64 = parts[1].replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = base64.padEnd(\n base64.length + ((4 - (base64.length % 4)) % 4),\n \"=\",\n );\n const parsed = JSON.parse(atob(padded)) as unknown;\n if (!parsed || typeof parsed !== \"object\") return null;\n return parsed as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction getAccessTokenPayload(): Record<string, unknown> | null {\n if (typeof window === \"undefined\") return null;\n return decodeJwtPayload(storageService.getString(STORAGE_KEYS.ACCESS_TOKEN));\n}\n\nfunction claimString(\n payload: Record<string, unknown> | null,\n key: string,\n): string | null {\n if (!payload) return null;\n const value = payload[key];\n return typeof value === \"string\" ? value : null;\n}\n\n/** Registration / all-tenants admin — NOT module gates */\nexport function isPlatformElevated(me: AuthMe | null | undefined): boolean {\n if (me?.capabilities?.isPlatformElevated === true) return true;\n const platformRole =\n me?.platformRole ??\n claimString(getAccessTokenPayload(), \"platformRole\");\n const r = normalizeRole(platformRole);\n return r === \"OWNER\" || r === \"DEV\";\n}\n\n/**\n * Tenant elevated (OWNER / DEV / TENANT).\n * Staff-programmer in scope has tenantRole === \"DEV\" → true.\n * Falls back to JWT tenantRole, then legacy `role`.\n */\nexport function isTenantElevated(me: AuthMe | null | undefined): boolean {\n const payload = getAccessTokenPayload();\n const tenantRole =\n me?.tenantRole ??\n claimString(payload, \"tenantRole\") ??\n me?.role ??\n claimString(payload, \"role\");\n const r = normalizeRole(tenantRole);\n return r === \"OWNER\" || r === \"DEV\" || r === \"TENANT\";\n}\n\n/** Platform or tenant role is OWNER or DEV (excludes TENANT). */\nexport function isOwnerOrDevUser(me: AuthMe | null | undefined): boolean {\n if (isPlatformElevated(me)) return true;\n\n const payload = getAccessTokenPayload();\n const tenantRole = normalizeRole(\n me?.tenantRole ??\n claimString(payload, \"tenantRole\") ??\n me?.role ??\n claimString(payload, \"role\"),\n );\n return tenantRole === \"OWNER\" || tenantRole === \"DEV\";\n}\n\n/** Same as backend ModulePermissionAttribute elevated bypass */\nexport function isModuleElevated(me: AuthMe | null | undefined): boolean {\n return isPlatformElevated(me) || isTenantElevated(me);\n}\n\nexport function getModuleClaim(moduleKey: string): string | null {\n const payload = getAccessTokenPayload();\n if (!payload) return null;\n const value = payload[`module:${moduleKey}`];\n return typeof value === \"string\" ? value : null;\n}\n\n/**\n * Module access: elevated OR JWT module claim.\n * claim = jwt[\"module:ticket\"] etc. (\"read\"|\"write\"|\"admin\")\n */\nexport function canModule(\n me: AuthMe | null | undefined,\n moduleKey: string,\n need: ModuleNeed,\n moduleClaim?: string | null,\n): boolean {\n if (isModuleElevated(me)) return true;\n const claim = moduleClaim ?? getModuleClaim(moduleKey);\n if (!claim) return false;\n const have = MODULE_RANK[claim.trim().toLowerCase() as ModuleNeed] ?? 0;\n return have >= MODULE_RANK[need];\n}\n\nexport function canSelectTicketCompany(\n me: AuthMe | null | undefined,\n): boolean {\n return canManageTicketGuests(me);\n}\n\n/** Guests / company employees (non-admin) — blocked from create in internal mode. */\nexport function isCompanyScopedTicketUser(\n me: AuthMe | null | undefined,\n userCompanyId: string | null | undefined,\n): boolean {\n if (isGuestUser(me)) return true;\n if (canSelectTicketCompany(me)) return false;\n return Boolean(userCompanyId?.trim());\n}\n\nexport function canManageTicketGuests(\n me: AuthMe | null | undefined,\n): boolean {\n return canModule(me, \"ticket\", \"admin\");\n}\n\nexport function canAdminTicketSequences(\n me: AuthMe | null | undefined,\n): boolean {\n return isSupportStaffUser(me as Parameters<typeof isSupportStaffUser>[0]);\n}\n\nexport function canWriteTicketSequences(\n me: AuthMe | null | undefined,\n): boolean {\n if (isGuestUser(me)) return false;\n return canModule(me, \"ticket\", \"write\") || !isGuestUser(me);\n}\n\nexport function canEditTicketAllowDirectDone(\n me: AuthMe | null | undefined,\n): boolean {\n return !isGuestUser(me);\n}\n\n/** Platform or tenant role is DEV (staff programmer). */\nexport function isDevRoleUser(me: AuthMe | null | undefined): boolean {\n if (me?.capabilities?.isScopedProgrammer === true) return true;\n\n const payload = getAccessTokenPayload();\n const platformRole = normalizeRole(\n me?.platformRole ?? claimString(payload, \"platformRole\"),\n );\n if (platformRole === \"DEV\") return true;\n\n const tenantRole = normalizeRole(\n me?.tenantRole ??\n claimString(payload, \"tenantRole\") ??\n me?.role ??\n claimString(payload, \"role\"),\n );\n return tenantRole === \"DEV\";\n}\n\nexport function canCreateTicketBatch(\n me: AuthMe | null | undefined,\n): boolean {\n return isDevRoleUser(me);\n}\n\n/**\n * Staff-only fields: deadline, assignment (single/sequence/multi).\n * Reporters cannot set or change assignment.\n */\nexport function canSetSupportStaffCreateFields(\n me: AuthMe | null | undefined,\n): boolean {\n return isSupportStaffUser(me as Parameters<typeof isSupportStaffUser>[0]);\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { TicketAttachmentAddButton } from \"@/components/tickets/TicketAttachmentAddButton\";\nimport { TicketAttachmentPreviews } from \"@/components/tickets/TicketAttachmentPreviews\";\nimport { TicketStoredAttachmentPreviews } from \"@/components/tickets/TicketStoredAttachmentPreviews\";\nimport {\n MAX_TICKET_ATTACHMENTS,\n TICKET_ATTACHMENT_ACCEPT,\n TICKET_ATTACHMENT_TILE_GRID_CLASS,\n type LocalTicketAttachment,\n} from \"@/lib/tickets/ticketAttachments\";\n\ntype AttachmentPoolUi = {\n existingIds: string[];\n items: LocalTicketAttachment[];\n onRemoveLocal: (id: string) => void;\n onRemoveExisting: (id: string) => void;\n onReplaceLocal?: (id: string, file: File) => void;\n onReplaceExisting?: (fileId: string, file: File) => void | Promise<void>;\n};\n\ntype TicketAttachmentsUiProps = {\n disabled?: boolean;\n atLimit: boolean;\n processing?: boolean;\n generalError?: string | null;\n general: AttachmentPoolUi;\n onAddFiles: (files: FileList | File[]) => void;\n};\n\nfunction poolCount(pool: AttachmentPoolUi): number {\n return pool.existingIds.length + pool.items.length;\n}\n\nconst PoolTiles = React.memo(function PoolTiles({\n pool,\n disabled,\n}: {\n pool: AttachmentPoolUi;\n disabled?: boolean;\n}) {\n return (\n <>\n {pool.existingIds.length > 0 ? (\n <TicketStoredAttachmentPreviews\n fileIds={pool.existingIds}\n disabled={disabled}\n onRemove={pool.onRemoveExisting}\n onReplaceImage={pool.onReplaceExisting}\n inline\n />\n ) : null}\n <TicketAttachmentPreviews\n items={pool.items}\n disabled={disabled}\n onRemove={pool.onRemoveLocal}\n onReplaceFile={pool.onReplaceLocal}\n inline\n />\n </>\n );\n});\n\n/** Support ticket attachments (images/videos) — no plan or CAM pools. */\nexport function usePlanImagesUi({\n disabled = false,\n atLimit,\n processing = false,\n generalError,\n general,\n onAddFiles,\n}: TicketAttachmentsUiProps) {\n const { t } = useTranslation();\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n const openUploadPicker = React.useCallback(() => {\n if (disabled || atLimit) return;\n inputRef.current?.click();\n }, [atLimit, disabled]);\n\n const handleFileChange = React.useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n onAddFiles(event.target.files ?? []);\n event.target.value = \"\";\n },\n [onAddFiles],\n );\n\n const generalReel = React.useMemo(\n () => (\n <div className=\"space-y-1.5\">\n <p className=\"border-b border-border pb-1 text-end text-xs text-muted-foreground\">\n {t(\"ticket.create_dialog.attachments_hint\")}\n </p>\n <input\n ref={inputRef}\n type=\"file\"\n accept={TICKET_ATTACHMENT_ACCEPT}\n multiple\n className=\"hidden\"\n disabled={disabled || atLimit}\n onChange={handleFileChange}\n />\n <div className={TICKET_ATTACHMENT_TILE_GRID_CLASS}>\n {!atLimit ? (\n <TicketAttachmentAddButton\n disabled={disabled}\n loading={processing}\n onUploadClick={openUploadPicker}\n onDrop={onAddFiles}\n />\n ) : null}\n <PoolTiles pool={general} disabled={disabled} />\n </div>\n {generalError ? (\n <p className=\"text-xs text-destructive\">{generalError}</p>\n ) : null}\n </div>\n ),\n [\n atLimit,\n disabled,\n general,\n generalError,\n handleFileChange,\n onAddFiles,\n openUploadPicker,\n processing,\n t,\n ],\n );\n\n return { generalReel };\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport Loader2 from \"lucide-react/dist/esm/icons/loader-2\";\nimport { useTranslation } from \"react-i18next\";\n\nimport {\n TICKET_ATTACHMENT_TILE_CLASS,\n TICKET_ATTACHMENT_TILE_STYLE,\n} from \"@/lib/tickets/ticketAttachments\";\nimport { cn } from \"@/lib/utils\";\n\ntype TicketAttachmentAddButtonProps = {\n disabled?: boolean;\n loading?: boolean;\n /** Omit to hide the camera-library half of the tile (not available on Support). */\n onCamClick?: () => void;\n onUploadClick: () => void;\n onDrop?: (files: FileList) => void;\n};\n\nexport function TicketAttachmentAddButton({\n disabled = false,\n loading = false,\n onCamClick,\n onUploadClick,\n onDrop,\n}: TicketAttachmentAddButtonProps) {\n const { t } = useTranslation();\n const isDisabled = disabled || loading;\n const camLabel = t(\"ticket.create_dialog.attachments_cam_photo\");\n const uploadLabel = t(\"ticket.create_dialog.attachments_upload_photo\");\n\n return (\n <div\n role=\"group\"\n aria-label={t(\"ticket.create_dialog.attachments_add\")}\n aria-busy={loading || undefined}\n title={\n loading\n ? t(\"ticket.create_dialog.attachments_processing\")\n : t(\"ticket.create_dialog.attachments_hint\")\n }\n onDragOver={(event) => {\n if (isDisabled) return;\n event.preventDefault();\n }}\n onDrop={(event) => {\n if (isDisabled) return;\n event.preventDefault();\n onDrop?.(event.dataTransfer.files);\n }}\n style={TICKET_ATTACHMENT_TILE_STYLE}\n className={cn(\n \"box-border size-32 shrink-0 grow-0 self-start overflow-hidden\",\n TICKET_ATTACHMENT_TILE_CLASS,\n \"relative flex flex-col rounded-md border-2 border-dashed border-muted-foreground/55 bg-muted/20 text-muted-foreground transition-colors\",\n isDisabled\n ? \"cursor-not-allowed opacity-50\"\n : \"hover:border-primary/70 hover:bg-primary/5\",\n loading && \"opacity-100\",\n )}\n >\n {loading ? (\n <div className=\"flex h-full w-full items-center justify-center\">\n <Loader2\n className=\"h-5 w-5 animate-spin text-muted-foreground\"\n aria-hidden\n />\n <span className=\"sr-only\">\n {t(\"ticket.create_dialog.attachments_processing\")}\n </span>\n </div>\n ) : (\n <>\n {onCamClick ? (\n <button\n type=\"button\"\n disabled={isDisabled}\n onClick={onCamClick}\n className={cn(\n \"flex min-h-0 flex-1 items-center justify-center border-b border-dashed border-muted-foreground/40 px-1.5 text-center text-xs font-medium leading-snug\",\n isDisabled\n ? \"cursor-not-allowed\"\n : \"cursor-pointer hover:bg-primary/10 hover:text-foreground\",\n )}\n >\n {camLabel}\n </button>\n ) : null}\n <button\n type=\"button\"\n disabled={isDisabled}\n onClick={onUploadClick}\n className={cn(\n \"flex min-h-0 flex-1 items-center justify-center px-1.5 text-center text-xs font-medium leading-snug\",\n isDisabled\n ? \"cursor-not-allowed\"\n : \"cursor-pointer hover:bg-primary/10 hover:text-foreground\",\n )}\n >\n {uploadLabel}\n </button>\n </>\n )}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport Loader2 from \"lucide-react/dist/esm/icons/loader-2\";\nimport X from \"lucide-react/dist/esm/icons/x\";\nimport { useTranslation } from \"react-i18next\";\n\nimport type { TicketAttachmentPreviewData } from \"@/api/files\";\nimport { guessContentTypeFromUrl } from \"@/api/files\";\nimport type { FileStorageDto } from \"@/api/dto/ticket.dto\";\nimport { TicketAttachmentMediaViewer } from \"@/components/tickets/TicketAttachmentMediaViewer\";\nimport {\n isHeicAttachmentFile,\n isTicketVideoFile,\n type LocalTicketAttachment,\n TICKET_ATTACHMENT_TILE_CLASS,\n TICKET_ATTACHMENT_TILE_GRID_CLASS,\n TICKET_ATTACHMENT_TILE_STYLE,\n} from \"@/lib/tickets/ticketAttachments\";\nimport { cn } from \"@/lib/utils\";\n\ntype TicketAttachmentPreviewsProps = {\n items: LocalTicketAttachment[];\n disabled?: boolean;\n onRemove: (id: string) => void;\n onReplaceFile?: (id: string, file: File) => void | Promise<void>;\n inline?: boolean;\n};\n\nexport function TicketAttachmentPreviews({\n items,\n disabled = false,\n onRemove,\n onReplaceFile,\n inline = false,\n}: TicketAttachmentPreviewsProps) {\n const { t } = useTranslation();\n const [previewUrls, setPreviewUrls] = React.useState<\n Record<string, string>\n >({});\n const [viewerOpen, setViewerOpen] = React.useState(false);\n const [activeIndex, setActiveIndex] = React.useState(0);\n\n React.useEffect(() => {\n const urls: Record<string, string> = {};\n for (const item of items) {\n if (!item.file || isHeicAttachmentFile(item.file)) continue;\n urls[item.id] = URL.createObjectURL(item.file);\n }\n setPreviewUrls(urls);\n return () => {\n Object.values(urls).forEach((url) => URL.revokeObjectURL(url));\n };\n }, [items]);\n\n const previewableItems = React.useMemo(\n () => items.filter((item) => item.file && previewUrls[item.id]),\n [items, previewUrls],\n );\n\n const viewerItems = React.useMemo<TicketAttachmentPreviewData[]>(\n () =>\n previewableItems.map((item) => {\n const file = item.file!;\n const meta: FileStorageDto = {\n id: `local-${item.id}`,\n fileName: file.name,\n contentType: file.type || guessContentTypeFromUrl(file.name),\n size: file.size,\n uploadDate: new Date(file.lastModified).toISOString(),\n };\n return {\n id: `local-${item.id}`,\n meta,\n directUrl: previewUrls[item.id] ?? null,\n contentType: meta.contentType,\n };\n }),\n [previewableItems, previewUrls],\n );\n\n const getLabel = React.useCallback(\n (item: TicketAttachmentPreviewData, index: number) =>\n item.meta?.fileName?.trim() ||\n previewableItems[index]?.file?.name ||\n previewableItems[index]?.original.name ||\n t(\"ticket.view_dialog.attachment_alt\", { index: index + 1 }),\n [previewableItems, t],\n );\n\n const openPreview = (item: LocalTicketAttachment) => {\n if (!previewUrls[item.id]) return;\n const index = previewableItems.findIndex(\n (candidate) => candidate.id === item.id,\n );\n if (index < 0) return;\n setActiveIndex(index);\n setViewerOpen(true);\n };\n\n if (items.length === 0) return null;\n\n const tiles = items.map((item) => {\n const displayName = item.file?.name ?? item.original.name;\n const previewUrl = previewUrls[item.id];\n const previewFile = item.file;\n const isProcessing = item.status === \"processing\";\n\n return (\n <div\n key={item.id}\n className={cn(\n TICKET_ATTACHMENT_TILE_CLASS,\n \"group relative rounded-md border border-input bg-muted/30\",\n )}\n style={TICKET_ATTACHMENT_TILE_STYLE}\n title={displayName}\n >\n <button\n type=\"button\"\n className=\"h-full w-full\"\n onClick={() => openPreview(item)}\n disabled={!previewUrl}\n aria-label={t(\"ticket.view_dialog.attachment_open\", {\n name: displayName,\n })}\n >\n {previewUrl && previewFile ? (\n isTicketVideoFile(previewFile) ? (\n <video\n src={previewUrl}\n className=\"h-full w-full object-cover\"\n muted\n playsInline\n preload=\"metadata\"\n />\n ) : (\n // eslint-disable-next-line @next/next/no-img-element -- blob preview URLs\n <img\n src={previewUrl}\n alt={displayName}\n className=\"h-full w-full object-cover\"\n />\n )\n ) : (\n <div className=\"flex h-full w-full flex-col items-center justify-center gap-1 bg-muted px-1\">\n <span className=\"line-clamp-2 break-all px-1 text-center text-[10px] text-muted-foreground\">\n {displayName}\n </span>\n </div>\n )}\n </button>\n {isProcessing ? (\n <div\n className=\"pointer-events-none absolute inset-0 flex items-center justify-center bg-background/55\"\n aria-busy\n aria-label={t(\"ticket.create_dialog.attachments_processing\")}\n >\n <Loader2\n className=\"h-5 w-5 animate-spin text-muted-foreground\"\n aria-hidden\n />\n </div>\n ) : null}\n {!disabled ? (\n <button\n type=\"button\"\n className={cn(\n \"absolute end-1 top-1 flex h-6 w-6 items-center justify-center rounded-full\",\n \"bg-background/95 text-foreground shadow-sm\",\n \"opacity-90 hover:bg-destructive hover:text-destructive-foreground\",\n )}\n onClick={() => onRemove(item.id)}\n aria-label={t(\"ticket.create_dialog.attachments_remove\", {\n name: displayName,\n })}\n >\n <X className=\"h-3.5 w-3.5\" aria-hidden />\n </button>\n ) : null}\n </div>\n );\n });\n\n const viewer = (\n <TicketAttachmentMediaViewer\n open={viewerOpen}\n items={viewerItems.filter((item) => item.directUrl)}\n activeIndex={activeIndex}\n onActiveIndexChange={setActiveIndex}\n onClose={() => setViewerOpen(false)}\n getLabel={getLabel}\n onSaveEditedImage={\n onReplaceFile && !disabled\n ? async (item, file) => {\n const localId = item.id.replace(/^local-/, \"\");\n await onReplaceFile(localId, file);\n setViewerOpen(false);\n }\n : undefined\n }\n />\n );\n\n if (inline) {\n return (\n <>\n {tiles}\n {viewer}\n </>\n );\n }\n\n return (\n <>\n <div className={TICKET_ATTACHMENT_TILE_GRID_CLASS}>{tiles}</div>\n {viewer}\n </>\n );\n}\n","import type { FileStorageDto } from \"@/api/dto/ticket.dto\";\nimport apiClient, { supportPath } from \"./client\";\nimport { resolveApiBaseUrl } from \"../../support-api-runtime\";\n\nconst API_BASE = resolveApiBaseUrl();\n\ntype FileUrlItem = {\n fileId: string;\n downloadUrl: string;\n};\n\nfunction parseFileUrlItems(data: unknown): FileUrlItem[] {\n if (!data) return [];\n if (Array.isArray(data)) return data as FileUrlItem[];\n if (typeof data === \"object\" && data !== null && \"items\" in data) {\n const items = (data as { items?: unknown }).items;\n return Array.isArray(items) ? (items as FileUrlItem[]) : [];\n }\n return [];\n}\n\nfunction resolveApiPath(url: string): string | null {\n const trimmed = url.trim();\n if (!trimmed) return null;\n if (trimmed.startsWith(\"/\")) return trimmed;\n if (API_BASE && trimmed.startsWith(API_BASE)) {\n const path = trimmed.slice(API_BASE.length);\n return path.startsWith(\"/\") ? path : `/${path}`;\n }\n return null;\n}\n\nexport function guessContentTypeFromUrl(\n url: string,\n fileName?: string | null,\n): string {\n const candidates = [fileName, url]\n .filter((value): value is string => Boolean(value?.trim()))\n .map((value) => value.toLowerCase().split(\"?\")[0] ?? \"\");\n\n for (const path of candidates) {\n if (path.endsWith(\".png\")) return \"image/png\";\n if (path.endsWith(\".jpg\") || path.endsWith(\".jpeg\")) return \"image/jpeg\";\n if (path.endsWith(\".webp\")) return \"image/webp\";\n if (path.endsWith(\".gif\")) return \"image/gif\";\n if (path.endsWith(\".heic\")) return \"image/heic\";\n if (path.endsWith(\".heif\")) return \"image/heif\";\n if (path.endsWith(\".mp4\") || path.includes(\".mp4\")) return \"video/mp4\";\n if (path.endsWith(\".webm\") || path.includes(\".webm\")) return \"video/webm\";\n if (path.endsWith(\".mov\") || path.includes(\".mov\")) return \"video/quicktime\";\n if (path.endsWith(\".m4v\")) return \"video/mp4\";\n }\n\n return \"image/jpeg\";\n}\n\nexport function isExternalDownloadUrl(url: string): boolean {\n return resolveApiPath(url) == null;\n}\n\nexport async function fetchFileDownloadUrl(\n fileId: string,\n): Promise<string | null> {\n if (!fileId?.trim()) return null;\n try {\n const { data } = await apiClient.get<{\n fileId?: string;\n downloadUrl: string;\n }>(supportPath(`/files/url/${encodeURIComponent(fileId)}`));\n return data.downloadUrl?.trim() ? data.downloadUrl : null;\n } catch {\n return null;\n }\n}\n\nexport async function fetchFileDownloadUrls(\n fileIds: string[],\n): Promise<Map<string, string>> {\n const ids = fileIds.filter((id) => id?.trim());\n const map = new Map<string, string>();\n if (!ids.length) return map;\n\n try {\n const { data } = await apiClient.post<unknown>(supportPath(\"/files/urls\"), {\n ids,\n });\n for (const item of parseFileUrlItems(data)) {\n const url = item.downloadUrl?.trim();\n if (item.fileId && url) {\n map.set(item.fileId, url);\n }\n }\n } catch {\n // batch failed — fall back to per-file URL lookup\n }\n\n const missing = ids.filter((id) => !map.has(id));\n if (missing.length) {\n await Promise.all(\n missing.map(async (id) => {\n const url = await fetchFileDownloadUrl(id);\n if (url) map.set(id, url);\n }),\n );\n }\n\n return map;\n}\n\nexport type TicketAttachmentPreviewData = {\n id: string;\n meta: FileStorageDto | null;\n directUrl: string | null;\n contentType: string;\n};\n\n/** Load download URLs only (fast). Skips metadata GET that 405s on production API. */\nexport async function fetchTicketAttachmentPreviews(\n fileIds: string[],\n): Promise<TicketAttachmentPreviewData[]> {\n const ids = fileIds.filter((id) => id?.trim());\n if (!ids.length) return [];\n\n const urlMap = await fetchFileDownloadUrls(ids);\n\n return ids.map((id) => {\n const directUrl = urlMap.get(id) ?? null;\n return {\n id,\n meta: null,\n directUrl,\n contentType: directUrl\n ? guessContentTypeFromUrl(directUrl)\n : \"image/jpeg\",\n };\n });\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport ChevronLeft from \"lucide-react/dist/esm/icons/chevron-left\";\nimport ChevronRight from \"lucide-react/dist/esm/icons/chevron-right\";\nimport Download from \"lucide-react/dist/esm/icons/download\";\nimport Minus from \"lucide-react/dist/esm/icons/minus\";\nimport Pencil from \"lucide-react/dist/esm/icons/pencil\";\nimport Plus from \"lucide-react/dist/esm/icons/plus\";\nimport X from \"lucide-react/dist/esm/icons/x\";\nimport { useTranslation } from \"react-i18next\";\n\nimport type { TicketAttachmentPreviewData } from \"@/api/files\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Dialog,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n} from \"@/components/ui/dialog\";\nimport { TicketAttachmentVideoPlayer } from \"@/components/tickets/TicketAttachmentVideoPlayer\";\nimport { TicketImageEditor } from \"@/components/tickets/TicketImageEditor\";\nimport { useResolvedMediaUrl } from \"@/components/ui/image-previewer/use-resolved-media-url\";\nimport { clampImagePreviewZoom } from \"@/components/ui/image-previewer/use-image-previewer\";\nimport {\n isImageContentType,\n isVideoContentType,\n} from \"@/lib/tickets/ticketAttachments\";\nimport {\n ensureEditorObjectUrl,\n getCachedEditorObjectUrl,\n isStoredTicketFileId,\n loadImageSourceBlob,\n revokeEditorObjectUrls,\n} from \"@/lib/tickets/ticketImageEditor\";\nimport { cn } from \"@/lib/utils\";\n\ntype TicketAttachmentMediaViewerProps = {\n open: boolean;\n items: TicketAttachmentPreviewData[];\n activeIndex: number;\n onActiveIndexChange: (index: number) => void;\n onClose: () => void;\n getLabel: (item: TicketAttachmentPreviewData, index: number) => string;\n onMediaError?: (fileId: string) => void;\n /** When set, images can be annotated and saved as a replacement file. */\n onSaveEditedImage?: (\n item: TicketAttachmentPreviewData,\n file: File,\n ) => void | Promise<void>;\n};\n\nconst ZOOM_STEP = 0.1;\n\nconst HEADER_ICON_BUTTON_CLASS =\n \"h-8 w-8 shrink-0 text-white/90 hover:bg-white/15 hover:text-white\";\n\nfunction extensionForContentType(contentType: string): string {\n const type = contentType.toLowerCase().split(\";\")[0]?.trim() ?? \"\";\n if (type === \"image/png\") return \".png\";\n if (type === \"image/webp\") return \".webp\";\n if (type === \"image/gif\") return \".gif\";\n if (type === \"image/heic\") return \".heic\";\n if (type === \"image/heif\") return \".heif\";\n if (type === \"video/webm\") return \".webm\";\n if (type === \"video/quicktime\") return \".mov\";\n if (type.startsWith(\"video/\")) return \".mp4\";\n if (type === \"image/jpeg\" || type === \"image/jpg\") return \".jpg\";\n return \".jpg\";\n}\n\nfunction downloadFileName(\n item: TicketAttachmentPreviewData,\n label: string,\n): string {\n const named = item.meta?.fileName?.trim();\n if (named) return named;\n\n const sanitized = label\n .trim()\n .replace(/[^\\w.\\-()+ ]+/g, \"_\")\n .replace(/\\s+/g, \" \")\n .slice(0, 80);\n const base = sanitized || `attachment-${item.id.slice(0, 8)}`;\n if (/\\.[a-z0-9]{2,5}$/i.test(base)) return base;\n return `${base}${extensionForContentType(item.contentType)}`;\n}\n\n/**\n * Prefer cached editor bytes, then Files stream / same-origin proxy.\n * Direct CDN fetch fails without CORS (Backblaze).\n */\nasync function resolveAttachmentBlob(\n item: TicketAttachmentPreviewData,\n): Promise<Blob> {\n const url = item.directUrl!;\n const cached = getCachedEditorObjectUrl(item.id);\n if (cached) {\n try {\n const response = await fetch(cached);\n if (response.ok) {\n const blob = await response.blob();\n if (blob.size > 0) return blob;\n }\n } catch {\n // fall through to stream/proxy\n }\n }\n\n return loadImageSourceBlob(url, {\n fileId: isStoredTicketFileId(item.id) ? item.id : undefined,\n });\n}\n\nfunction triggerBlobDownload(blob: Blob, fileName: string): void {\n const objectUrl = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = objectUrl;\n link.download = fileName;\n link.rel = \"noopener\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n // Defer revoke so the browser can start writing the file.\n window.setTimeout(() => URL.revokeObjectURL(objectUrl), 2_000);\n}\n\nfunction AttachmentImageStage({\n imageUrl,\n imageAlt,\n onError,\n}: {\n imageUrl: string;\n imageAlt: string;\n onError?: () => void;\n}) {\n const { t } = useTranslation();\n const [zoom, setZoom] = React.useState(1);\n const { src: resolvedUrl, isLoading } = useResolvedMediaUrl(imageUrl);\n\n React.useEffect(() => {\n setZoom(1);\n }, [imageUrl]);\n\n const zoomPercent = Math.round(zoom * 100);\n const zoomIn = () =>\n setZoom((prev) => clampImagePreviewZoom(prev + ZOOM_STEP));\n const zoomOut = () =>\n setZoom((prev) => clampImagePreviewZoom(prev - ZOOM_STEP));\n const zoomReset = () => setZoom(1);\n\n const onWheelZoom = (event: React.WheelEvent) => {\n event.preventDefault();\n const delta = event.deltaY > 0 ? -ZOOM_STEP : ZOOM_STEP;\n setZoom((prev) => clampImagePreviewZoom(prev + delta));\n };\n\n return (\n <div className=\"pointer-events-none relative flex h-full w-full min-h-0 min-w-0 items-center justify-center overflow-hidden\">\n {resolvedUrl ? (\n // eslint-disable-next-line @next/next/no-img-element -- arbitrary remote/blob URLs\n <img\n src={resolvedUrl}\n alt={imageAlt}\n draggable={false}\n onClick={(event) => event.stopPropagation()}\n onWheel={onWheelZoom}\n onError={onError}\n className=\"pointer-events-auto max-h-full max-w-full select-none object-contain transition-transform duration-150 ease-out\"\n style={{\n transform: `scale(${zoom})`,\n transformOrigin: \"center center\",\n }}\n />\n ) : (\n <span className=\"px-8 py-16 text-sm text-white/70\">\n {isLoading\n ? t(\"common.loading\")\n : t(\"common.image_preview_unavailable\")}\n </span>\n )}\n\n <div\n className=\"pointer-events-auto absolute bottom-3 left-1/2 z-[2] flex -translate-x-1/2 items-center gap-0.5 rounded-full border border-white/10 bg-black/80 px-2 py-1.5 shadow-lg backdrop-blur-md sm:gap-1 sm:px-2.5\"\n onClick={(event) => event.stopPropagation()}\n >\n <button\n type=\"button\"\n onClick={zoomOut}\n className=\"flex h-8 w-8 items-center justify-center rounded-full text-white/90 transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50\"\n title={t(\"common.image_preview_zoom_out\")}\n aria-label={t(\"common.image_preview_zoom_out\")}\n >\n <Minus className=\"h-3.5 w-3.5\" strokeWidth={2.5} />\n </button>\n <button\n type=\"button\"\n onClick={zoomReset}\n className=\"min-w-[3.25rem] rounded-full px-2 py-1.5 text-xs font-medium tabular-nums text-white/95 transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50\"\n title={t(\"common.image_preview_reset_zoom\")}\n aria-label={t(\"common.image_preview_reset_zoom\")}\n >\n {zoomPercent}%\n </button>\n <button\n type=\"button\"\n onClick={zoomIn}\n className=\"flex h-8 w-8 items-center justify-center rounded-full text-white/90 transition-colors hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/50\"\n title={t(\"common.image_preview_zoom_in\")}\n aria-label={t(\"common.image_preview_zoom_in\")}\n >\n <Plus className=\"h-3.5 w-3.5\" strokeWidth={2.5} />\n </button>\n </div>\n </div>\n );\n}\n\nexport function TicketAttachmentMediaViewer({\n open,\n items,\n activeIndex,\n onActiveIndexChange,\n onClose,\n getLabel,\n onMediaError,\n onSaveEditedImage,\n}: TicketAttachmentMediaViewerProps) {\n const { t } = useTranslation();\n const [editing, setEditing] = React.useState(false);\n const [isDownloading, setIsDownloading] = React.useState(false);\n const [editSessionSrc, setEditSessionSrc] = React.useState<string | null>(\n null,\n );\n const [editSessionFileId, setEditSessionFileId] = React.useState<\n string | undefined\n >(undefined);\n /** Bumps when preload cache fills so Edit can use blob: immediately. */\n const [, setPreloadEpoch] = React.useState(0);\n\n const activeItem = items[activeIndex] ?? null;\n const hasMultiple = items.length > 1;\n const activeLabel = activeItem\n ? getLabel(activeItem, activeIndex)\n : t(\"ticket.view_dialog.attachment_preview\");\n const isVideo =\n Boolean(activeItem) && isVideoContentType(activeItem?.contentType ?? \"\");\n const canEditImage =\n Boolean(onSaveEditedImage) &&\n Boolean(activeItem?.directUrl) &&\n isImageContentType(activeItem?.contentType ?? \"\") &&\n !isVideo;\n\n const startEditing = React.useCallback(() => {\n if (!activeItem?.directUrl) return;\n const cached = getCachedEditorObjectUrl(activeItem.id);\n setEditSessionSrc(cached ?? activeItem.directUrl);\n setEditSessionFileId(\n cached ||\n activeItem.directUrl.startsWith(\"blob:\") ||\n activeItem.directUrl.startsWith(\"data:\")\n ? undefined\n : isStoredTicketFileId(activeItem.id)\n ? activeItem.id\n : undefined,\n );\n setEditing(true);\n }, [activeItem]);\n\n const stopEditing = React.useCallback(() => {\n setEditing(false);\n setEditSessionSrc(null);\n setEditSessionFileId(undefined);\n }, []);\n\n React.useEffect(() => {\n if (!open) stopEditing();\n }, [open, stopEditing]);\n\n React.useEffect(() => {\n stopEditing();\n setIsDownloading(false);\n }, [activeIndex, stopEditing]);\n\n // Preload editor-ready blob URLs while preview is open (active + neighbors).\n React.useEffect(() => {\n if (!open || !onSaveEditedImage) return;\n\n const targets: TicketAttachmentPreviewData[] = [];\n const pushIfEditable = (item: TicketAttachmentPreviewData | undefined) => {\n if (!item?.directUrl) return;\n if (!isImageContentType(item.contentType)) return;\n if (isVideoContentType(item.contentType)) return;\n targets.push(item);\n };\n\n pushIfEditable(items[activeIndex]);\n if (items.length > 1) {\n pushIfEditable(items[(activeIndex + 1) % items.length]);\n pushIfEditable(\n items[(activeIndex - 1 + items.length) % items.length],\n );\n }\n\n let cancelled = false;\n for (const item of targets) {\n if (getCachedEditorObjectUrl(item.id)) continue;\n void ensureEditorObjectUrl(item.directUrl!, {\n cacheKey: item.id,\n fileId: isStoredTicketFileId(item.id) ? item.id : undefined,\n })\n .then(() => {\n if (!cancelled) setPreloadEpoch((n) => n + 1);\n })\n .catch(() => {\n // Best-effort preload; editor retries and surfaces loadFailed on open.\n });\n }\n\n return () => {\n cancelled = true;\n };\n }, [open, onSaveEditedImage, items, activeIndex]);\n\n // Revoke cached blobs when the viewer closes.\n React.useEffect(() => {\n if (open) return;\n revokeEditorObjectUrls(items.map((item) => item.id));\n }, [open, items]);\n\n React.useEffect(() => {\n if (!open || editing) return;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"ArrowLeft\" && hasMultiple) {\n event.preventDefault();\n onActiveIndexChange(\n (activeIndex - 1 + items.length) % items.length,\n );\n } else if (event.key === \"ArrowRight\" && hasMultiple) {\n event.preventDefault();\n onActiveIndexChange((activeIndex + 1) % items.length);\n }\n };\n\n window.addEventListener(\"keydown\", onKeyDown, true);\n return () => window.removeEventListener(\"keydown\", onKeyDown, true);\n }, [\n open,\n editing,\n activeIndex,\n hasMultiple,\n items.length,\n onActiveIndexChange,\n ]);\n\n const itemsLength = items.length;\n const goPrev = React.useCallback(() => {\n if (itemsLength < 2) return;\n onActiveIndexChange((activeIndex - 1 + itemsLength) % itemsLength);\n }, [activeIndex, itemsLength, onActiveIndexChange]);\n\n const goNext = React.useCallback(() => {\n if (itemsLength < 2) return;\n onActiveIndexChange((activeIndex + 1) % itemsLength);\n }, [activeIndex, itemsLength, onActiveIndexChange]);\n\n const handleSaveEdited = async (file: File) => {\n if (!onSaveEditedImage || !activeItem) return;\n await onSaveEditedImage(activeItem, file);\n stopEditing();\n };\n\n const handleDownload = React.useCallback(async () => {\n if (!activeItem?.directUrl || isDownloading) return;\n setIsDownloading(true);\n try {\n const blob = await resolveAttachmentBlob(activeItem);\n triggerBlobDownload(blob, downloadFileName(activeItem, activeLabel));\n } catch {\n // Best-effort download; keep preview usable if fetch fails.\n } finally {\n setIsDownloading(false);\n }\n }, [activeItem, activeLabel, isDownloading]);\n\n if (!activeItem?.directUrl) return null;\n\n const showEditor =\n editing && canEditImage && Boolean(editSessionSrc);\n\n return (\n <Dialog\n open={open}\n onOpenChange={(next) => {\n if (next) return;\n // Keep the attachment open while annotating; Escape cancels the editor first.\n if (editing) stopEditing();\n else onClose();\n }}\n >\n <DialogPortal>\n <DialogOverlay className=\"z-[200] bg-black/30 backdrop-blur-2xl\" />\n <DialogPrimitive.Content\n className={cn(\n \"fixed inset-0 z-[200] flex h-[100dvh] max-h-[100dvh] flex-col overflow-hidden border-0 bg-transparent p-0 text-white shadow-none outline-none\",\n \"data-[state=open]:animate-in data-[state=closed]:animate-out\",\n \"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n showEditor && \"bg-black\",\n )}\n onOpenAutoFocus={(event) => event.preventDefault()}\n onPointerDownOutside={(event) => event.preventDefault()}\n onInteractOutside={(event) => event.preventDefault()}\n >\n <DialogTitle className=\"sr-only\">\n {showEditor\n ? t(\"ticket.image_editor.title\")\n : t(\"ticket.view_dialog.attachment_preview\")}\n </DialogTitle>\n\n {showEditor && editSessionSrc ? (\n <div\n data-ticket-image-editor=\"\"\n className=\"flex h-full min-h-0 w-full flex-col overflow-hidden\"\n >\n <TicketImageEditor\n src={editSessionSrc}\n fileId={editSessionFileId}\n fileName={activeItem.meta?.fileName ?? activeLabel}\n onCancel={stopEditing}\n onSave={handleSaveEdited}\n />\n </div>\n ) : (\n <>\n <header className=\"flex h-12 shrink-0 items-center gap-3 border-b border-white/15 bg-white/10 px-3 backdrop-blur-md sm:px-4\">\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-white\">\n {activeLabel}\n </p>\n {hasMultiple ? (\n <p className=\"text-xs text-white/70\">\n {t(\"ticket.view_dialog.attachment_counter\", {\n current: activeIndex + 1,\n total: items.length,\n })}\n </p>\n ) : null}\n </div>\n\n <div className=\"flex shrink-0 items-center gap-0.5\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className={HEADER_ICON_BUTTON_CLASS}\n onClick={() => {\n void handleDownload();\n }}\n disabled={isDownloading}\n title={t(\"ticket.view_dialog.attachment_download\")}\n aria-label={t(\"ticket.view_dialog.attachment_download\")}\n >\n <Download className=\"h-4 w-4\" />\n </Button>\n {canEditImage ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className={HEADER_ICON_BUTTON_CLASS}\n onClick={startEditing}\n title={t(\"common.edit\")}\n aria-label={t(\"common.edit\")}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n ) : null}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className={HEADER_ICON_BUTTON_CLASS}\n onClick={onClose}\n aria-label={t(\"ticket.view_dialog.attachment_close\")}\n >\n <X className=\"h-5 w-5\" />\n </Button>\n </div>\n </header>\n\n <div\n className={cn(\n \"relative flex min-h-0 flex-1 cursor-default items-stretch justify-center overflow-hidden py-2\",\n hasMultiple ? \"px-12 sm:px-16\" : \"px-2\",\n )}\n onClick={onClose}\n >\n {hasMultiple ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute left-2 top-1/2 z-10 h-10 w-10 -translate-y-1/2 rounded-full border border-white/15 bg-white/10 text-white backdrop-blur-md hover:bg-white/20 hover:text-white sm:left-4 sm:h-11 sm:w-11\"\n onClick={(event) => {\n event.stopPropagation();\n goPrev();\n }}\n aria-label={t(\"ticket.view_dialog.attachment_prev\")}\n >\n <ChevronLeft className=\"h-6 w-6\" aria-hidden />\n </Button>\n ) : null}\n\n <div className=\"pointer-events-none relative z-20 flex h-full min-h-0 w-full min-w-0 items-center justify-center\">\n {isVideo ? (\n <div\n className=\"pointer-events-auto flex h-full w-full min-h-0 min-w-0 items-center justify-center\"\n onClick={(event) => event.stopPropagation()}\n >\n <TicketAttachmentVideoPlayer\n key={activeItem.id}\n src={activeItem.directUrl}\n label={activeLabel}\n onError={() => onMediaError?.(activeItem.id)}\n className=\"h-full max-h-full w-full max-w-full\"\n />\n </div>\n ) : (\n <AttachmentImageStage\n key={activeItem.id}\n imageUrl={activeItem.directUrl}\n imageAlt={activeLabel}\n onError={() => onMediaError?.(activeItem.id)}\n />\n )}\n </div>\n\n {hasMultiple ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-2 top-1/2 z-10 h-10 w-10 -translate-y-1/2 rounded-full border border-white/15 bg-white/10 text-white backdrop-blur-md hover:bg-white/20 hover:text-white sm:right-4 sm:h-11 sm:w-11\"\n onClick={(event) => {\n event.stopPropagation();\n goNext();\n }}\n aria-label={t(\"ticket.view_dialog.attachment_next\")}\n >\n <ChevronRight className=\"h-6 w-6\" aria-hidden />\n </Button>\n ) : null}\n </div>\n </>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n </Dialog>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport Maximize from \"lucide-react/dist/esm/icons/maximize\";\nimport Pause from \"lucide-react/dist/esm/icons/pause\";\nimport Play from \"lucide-react/dist/esm/icons/play\";\nimport Volume2 from \"lucide-react/dist/esm/icons/volume-2\";\nimport VolumeX from \"lucide-react/dist/esm/icons/volume-x\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype TicketAttachmentVideoPlayerProps = {\n src: string;\n label: string;\n className?: string;\n onError?: () => void;\n};\n\nfunction formatMediaTime(seconds: number): string {\n if (!Number.isFinite(seconds) || seconds < 0) return \"0:00\";\n const whole = Math.floor(seconds);\n const m = Math.floor(whole / 60);\n const s = whole % 60;\n return `${m}:${s.toString().padStart(2, \"0\")}`;\n}\n\nconst controlButtonClass =\n \"inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-white transition-colors hover:bg-white/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/40\";\n\nconst PLAYBACK_RATES = [0.5, 0.75, 1, 1.25, 1.5, 2] as const;\n\nexport function TicketAttachmentVideoPlayer({\n src,\n label,\n className,\n onError,\n}: TicketAttachmentVideoPlayerProps) {\n const { t } = useTranslation();\n const containerRef = React.useRef<HTMLDivElement>(null);\n const videoRef = React.useRef<HTMLVideoElement>(null);\n const [playing, setPlaying] = React.useState(false);\n const [currentTime, setCurrentTime] = React.useState(0);\n const [duration, setDuration] = React.useState(0);\n const [muted, setMuted] = React.useState(false);\n const [playbackRate, setPlaybackRate] = React.useState(1);\n\n React.useEffect(() => {\n setPlaybackRate(1);\n setPlaying(false);\n setCurrentTime(0);\n setDuration(0);\n }, [src]);\n\n React.useEffect(() => {\n const video = videoRef.current;\n if (video) {\n video.playbackRate = playbackRate;\n }\n }, [playbackRate, src]);\n\n const syncTime = React.useCallback(() => {\n const video = videoRef.current;\n if (!video) return;\n setCurrentTime(video.currentTime);\n if (Number.isFinite(video.duration)) {\n setDuration(video.duration);\n }\n }, []);\n\n const togglePlay = React.useCallback(() => {\n const video = videoRef.current;\n if (!video) return;\n if (video.paused) {\n void video.play().catch(() => undefined);\n } else {\n video.pause();\n }\n }, []);\n\n const toggleMute = React.useCallback(() => {\n const video = videoRef.current;\n if (!video) return;\n video.muted = !video.muted;\n setMuted(video.muted);\n }, []);\n\n const toggleFullscreen = React.useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n if (document.fullscreenElement) {\n void document.exitFullscreen();\n return;\n }\n void container.requestFullscreen?.();\n }, []);\n\n const seekToPercent = React.useCallback(\n (percent: number) => {\n const video = videoRef.current;\n if (!video || !Number.isFinite(video.duration) || video.duration <= 0) {\n return;\n }\n const nextTime = (percent / 100) * video.duration;\n video.currentTime = nextTime;\n setCurrentTime(nextTime);\n },\n [],\n );\n\n const progress = duration > 0 ? (currentTime / duration) * 100 : 0;\n\n return (\n <div\n ref={containerRef}\n className={cn(\n \"pointer-events-auto flex h-full w-full min-h-0 min-w-0 flex-col overflow-hidden bg-black/50\",\n className,\n )}\n onPointerDown={(event) => event.stopPropagation()}\n >\n <div className=\"relative min-h-0 flex-1 bg-black\">\n <video\n ref={videoRef}\n src={src}\n className=\"absolute inset-0 h-full w-full object-contain\"\n playsInline\n preload=\"metadata\"\n onClick={togglePlay}\n onPlay={() => setPlaying(true)}\n onPause={() => setPlaying(false)}\n onTimeUpdate={syncTime}\n onLoadedMetadata={syncTime}\n onDurationChange={syncTime}\n onEnded={() => setPlaying(false)}\n onError={onError}\n />\n </div>\n\n <div\n className=\"pointer-events-auto relative z-10 flex items-center gap-2 border-t border-white/15 bg-white/10 px-3 py-2 backdrop-blur-md\"\n onPointerDown={(event) => event.stopPropagation()}\n onClick={(event) => event.stopPropagation()}\n >\n <button\n type=\"button\"\n className={controlButtonClass}\n onClick={togglePlay}\n aria-label={\n playing\n ? t(\"ticket.view_dialog.attachment_video_pause\")\n : t(\"ticket.view_dialog.attachment_video_play\")\n }\n >\n {playing ? (\n <Pause className=\"h-4 w-4\" aria-hidden />\n ) : (\n <Play className=\"h-4 w-4 fill-current\" aria-hidden />\n )}\n </button>\n\n <span className=\"shrink-0 text-xs tabular-nums text-white/80\">\n {formatMediaTime(currentTime)} / {formatMediaTime(duration)}\n </span>\n\n <input\n type=\"range\"\n min={0}\n max={100}\n step={0.1}\n value={progress}\n onInput={(event) => {\n seekToPercent(Number.parseFloat(event.currentTarget.value));\n }}\n onChange={(event) => {\n seekToPercent(Number.parseFloat(event.currentTarget.value));\n }}\n className=\"pointer-events-auto h-1.5 min-w-0 flex-1 cursor-pointer accent-[#0c66e4]\"\n aria-label={label}\n />\n\n <button\n type=\"button\"\n className={controlButtonClass}\n onClick={toggleMute}\n aria-label={\n muted\n ? t(\"ticket.view_dialog.attachment_video_unmute\")\n : t(\"ticket.view_dialog.attachment_video_mute\")\n }\n >\n {muted ? (\n <VolumeX className=\"h-4 w-4\" aria-hidden />\n ) : (\n <Volume2 className=\"h-4 w-4\" aria-hidden />\n )}\n </button>\n\n <select\n value={playbackRate}\n onChange={(event) => {\n setPlaybackRate(Number.parseFloat(event.currentTarget.value));\n }}\n className=\"h-8 shrink-0 cursor-pointer rounded-md border border-white/20 bg-black/40 px-1.5 text-xs text-white outline-none focus-visible:ring-2 focus-visible:ring-white/40\"\n aria-label={t(\"ticket.view_dialog.attachment_video_speed\")}\n >\n {PLAYBACK_RATES.map((rate) => (\n <option key={rate} value={rate} className=\"text-foreground\">\n {rate === 1 ? \"1x\" : `${rate}x`}\n </option>\n ))}\n </select>\n\n <button\n type=\"button\"\n className={controlButtonClass}\n onClick={toggleFullscreen}\n aria-label={t(\"ticket.view_dialog.attachment_video_fullscreen\")}\n >\n <Maximize className=\"h-4 w-4\" aria-hidden />\n </button>\n </div>\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport {\n ImageEditor,\n type ImageEditorLabels,\n} from \"@avament-pub/image-editor\";\n\nimport { ensureEditorObjectUrl } from \"@/lib/tickets/ticketImageEditor\";\n\ntype TicketImageEditorProps = {\n src: string;\n /** Stored Files API id — loads via `/api/ticket-file/[id]` when remote CORS fails. */\n fileId?: string;\n fileName?: string;\n onCancel: () => void;\n onSave: (file: File) => void | Promise<void>;\n};\n\nexport function TicketImageEditor({\n src,\n fileId,\n fileName,\n onCancel,\n onSave,\n}: TicketImageEditorProps) {\n const { t } = useTranslation();\n\n const labels = React.useMemo<Partial<ImageEditorLabels>>(\n () => ({\n cancel: t(\"ticket.image_editor.cancel\"),\n save: t(\"ticket.image_editor.save\"),\n loading: t(\"ticket.image_editor.loading\"),\n loadFailed: t(\"ticket.image_editor.load_failed\"),\n saveFailed: t(\"ticket.image_editor.save_failed\"),\n cropFailed: t(\"ticket.image_editor.crop_failed\"),\n rotateFailed: t(\"ticket.image_editor.rotate_failed\"),\n applyCrop: t(\"ticket.image_editor.apply_crop\"),\n toolSelect: t(\"ticket.image_editor.tool_select\"),\n toolPen: t(\"ticket.image_editor.tool_pen\"),\n toolLine: t(\"ticket.image_editor.tool_line\"),\n toolArrow: t(\"ticket.image_editor.tool_arrow\"),\n toolRect: t(\"ticket.image_editor.tool_rect\"),\n toolEllipse: t(\"ticket.image_editor.tool_ellipse\"),\n toolText: t(\"ticket.image_editor.tool_text\"),\n toolEraser: t(\"ticket.image_editor.tool_eraser\"),\n toolCrop: t(\"ticket.image_editor.tool_crop\"),\n rotateCcw: t(\"ticket.image_editor.rotate_ccw\"),\n rotateCw: t(\"ticket.image_editor.rotate_cw\"),\n undo: t(\"ticket.image_editor.undo\"),\n redo: t(\"ticket.image_editor.redo\"),\n stroke: t(\"ticket.image_editor.stroke\"),\n shapeOutline: t(\"ticket.image_editor.shape_outline\"),\n shapeFilled: t(\"ticket.image_editor.shape_filled\"),\n textPlaceholder: t(\"ticket.image_editor.text_placeholder\"),\n applyText: t(\"ticket.image_editor.apply_text\"),\n }),\n [t],\n );\n\n const resolveSrc = React.useCallback(\n (imageSrc: string) =>\n ensureEditorObjectUrl(imageSrc, {\n cacheKey: fileId?.trim() || imageSrc,\n fileId,\n }),\n [fileId],\n );\n\n return (\n <ImageEditor\n src={src}\n fileName={fileName}\n labels={labels}\n resolveSrc={resolveSrc}\n onCancel={onCancel}\n onSave={onSave}\n />\n );\n}\n","import apiClient from \"@/api/client\";\nimport { STORAGE_KEYS, storageService } from \"@/lib/services\";\nimport { ensureEditorObjectUrl as ensurePackageEditorObjectUrl } from \"@avament-pub/image-editor\";\n\nexport {\n getCachedEditorObjectUrl,\n revokeEditorObjectUrls,\n} from \"@avament-pub/image-editor\";\n\nconst CORS_TIMEOUT_MS = 3_000;\nconst PROXY_TIMEOUT_MS = 20_000;\n\n/** Stored Files API ids (not local draft preview ids like `local-…`). */\nexport function isStoredTicketFileId(\n fileId: string | undefined,\n): fileId is string {\n const id = fileId?.trim();\n if (!id) return false;\n return !id.startsWith(\"local-\");\n}\n\nfunction abortSignalTimeout(ms: number): AbortSignal {\n if (typeof AbortSignal !== \"undefined\" && \"timeout\" in AbortSignal) {\n return AbortSignal.timeout(ms);\n }\n const controller = new AbortController();\n window.setTimeout(() => controller.abort(), ms);\n return controller.signal;\n}\n\nfunction assertImageBlob(blob: Blob): Blob {\n if (!blob.size) throw new Error(\"image_load_failed\");\n const type = blob.type.toLowerCase();\n // Axios/fetch may surface API error JSON as a Blob on some paths.\n if (type.includes(\"json\") || type.startsWith(\"text/\")) {\n throw new Error(\"image_load_failed\");\n }\n return blob;\n}\n\nfunction isHttpDownloadUrl(url: string | undefined): url is string {\n return Boolean(\n url && (url.startsWith(\"http://\") || url.startsWith(\"https://\")),\n );\n}\n\nasync function fetchViaTicketFileProxy(\n fileId: string,\n downloadUrl?: string,\n): Promise<Blob> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n const token = storageService.getString(STORAGE_KEYS.ACCESS_TOKEN);\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n\n const hasUrl = isHttpDownloadUrl(downloadUrl);\n\n const response = await fetch(\n `/api/ticket-file/${encodeURIComponent(fileId)}`,\n {\n method: \"POST\",\n credentials: \"include\",\n cache: \"no-store\",\n headers,\n body: JSON.stringify(hasUrl ? { url: downloadUrl } : {}),\n signal: abortSignalTimeout(PROXY_TIMEOUT_MS),\n },\n );\n if (!response.ok) throw new Error(\"image_load_failed\");\n return assertImageBlob(await response.blob());\n}\n\n/**\n * Stored attachments: same-origin proxy → optional CORS.\n */\nasync function fetchStoredTicketFileBlob(\n fileId: string,\n downloadUrl?: string,\n): Promise<Blob> {\n try {\n return await fetchViaTicketFileProxy(fileId, downloadUrl);\n } catch {\n // fall through\n }\n\n try {\n return await fetchViaTicketFileProxy(fileId);\n } catch {\n // fall through\n }\n\n if (!isHttpDownloadUrl(downloadUrl)) {\n throw new Error(\"image_load_failed\");\n }\n\n try {\n return await fetchCorsBlob(downloadUrl);\n } catch {\n return decodeCorsImageToBlob(downloadUrl);\n }\n}\n\nasync function fetchCorsBlob(src: string): Promise<Blob> {\n const response = await fetch(src, {\n mode: \"cors\",\n credentials: \"omit\",\n cache: \"force-cache\",\n signal: abortSignalTimeout(CORS_TIMEOUT_MS),\n });\n if (!response.ok) throw new Error(\"image_load_failed\");\n return response.blob();\n}\n\nasync function decodeCorsImageToBlob(src: string): Promise<Blob> {\n const img = new Image();\n img.crossOrigin = \"anonymous\";\n img.decoding = \"async\";\n\n await new Promise<void>((resolve, reject) => {\n const timer = window.setTimeout(\n () => reject(new Error(\"image_load_failed\")),\n CORS_TIMEOUT_MS,\n );\n img.onload = () => {\n window.clearTimeout(timer);\n resolve();\n };\n img.onerror = () => {\n window.clearTimeout(timer);\n reject(new Error(\"image_load_failed\"));\n };\n img.src = src;\n });\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = img.naturalWidth || 1;\n canvas.height = img.naturalHeight || 1;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"image_load_failed\");\n ctx.drawImage(img, 0, 0);\n\n return new Promise<Blob>((resolve, reject) => {\n canvas.toBlob(\n (result) =>\n result ? resolve(result) : reject(new Error(\"image_load_failed\")),\n \"image/jpeg\",\n 0.92,\n );\n });\n}\n\n/**\n * Load image bytes for Fabric.\n * Stored attachments → Files stream / same-origin proxy (Backblaze CORS).\n * Other remote URLs → CORS paths only.\n */\nexport async function loadImageSourceBlob(\n src: string,\n options?: { fileId?: string },\n): Promise<Blob> {\n if (src.startsWith(\"blob:\") || src.startsWith(\"data:\")) {\n const response = await fetch(src);\n if (!response.ok) throw new Error(\"image_load_failed\");\n return response.blob();\n }\n\n const fileId = options?.fileId?.trim();\n if (isStoredTicketFileId(fileId)) {\n return fetchStoredTicketFileBlob(fileId, src);\n }\n\n try {\n return await fetchCorsBlob(src);\n } catch {\n return decodeCorsImageToBlob(src);\n }\n}\n\n/**\n * Resolve a blob: object URL for the editor (cached + deduped in-flight).\n * Uses the ticket file proxy for stored attachments.\n */\nexport function ensureEditorObjectUrl(\n src: string,\n options: { cacheKey: string; fileId?: string },\n): Promise<string> {\n const { cacheKey, fileId } = options;\n return ensurePackageEditorObjectUrl(src, {\n cacheKey,\n loadBlob: (url) => loadImageSourceBlob(url, { fileId }),\n });\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport apiClient, {\n isApiHostedMediaUrl,\n normalizeApiDownloadUrl,\n resolveApiMediaUrl,\n} from \"@/api/client\";\n\n/**\n * Resolve API media for `<img>` / `next/image`.\n * API-hosted paths are fetched with the authenticated client (Bearer + cookies)\n * and exposed as blob URLs — browser `<img>` cannot send Authorization headers.\n */\nexport function useResolvedMediaUrl(url: string | null | undefined): {\n src: string | null;\n isLoading: boolean;\n} {\n const [src, setSrc] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(Boolean(url?.trim()));\n\n useEffect(() => {\n const trimmed = url?.trim() ?? \"\";\n if (!trimmed) {\n setSrc(null);\n setIsLoading(false);\n return;\n }\n\n if (/^(blob:|data:)/i.test(trimmed)) {\n setSrc(trimmed);\n setIsLoading(false);\n return;\n }\n\n const resolved = resolveApiMediaUrl(trimmed);\n if (!resolved) {\n setSrc(null);\n setIsLoading(false);\n return;\n }\n\n if (!isApiHostedMediaUrl(trimmed) && !isApiHostedMediaUrl(resolved)) {\n setSrc(resolved);\n setIsLoading(false);\n return;\n }\n\n let cancelled = false;\n let objectUrl: string | null = null;\n // Drop the previous gallery frame immediately so nav isn't stuck on a\n // revoked blob while the next authenticated download is in flight.\n setSrc(null);\n setIsLoading(true);\n\n void apiClient\n .get<Blob>(normalizeApiDownloadUrl(trimmed), { responseType: \"blob\" })\n .then((response) => {\n if (cancelled) return;\n objectUrl = URL.createObjectURL(response.data);\n setSrc(objectUrl);\n })\n .catch(() => {\n if (!cancelled) setSrc(resolved);\n })\n .finally(() => {\n if (!cancelled) setIsLoading(false);\n });\n\n return () => {\n cancelled = true;\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n };\n }, [url]);\n\n return { src, isLoading };\n}\n","\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useEffectEvent,\n useState,\n type WheelEvent,\n} from \"react\";\n\nconst ZOOM_MIN = 0.25;\nconst ZOOM_MAX = 4;\nconst ZOOM_STEP = 0.1;\n\nexport function clampImagePreviewZoom(value: number): number {\n return Math.max(ZOOM_MIN, Math.min(ZOOM_MAX, value));\n}\n\ntype UseImagePreviewerArgs = {\n open: boolean;\n /** When the viewed URL changes (gallery nav), zoom resets. */\n imageUrl?: string | null;\n onClose: () => void;\n onPrevious?: () => void;\n onNext?: () => void;\n};\n\nexport function useImagePreviewer({\n open,\n imageUrl,\n onClose,\n onPrevious,\n onNext,\n}: UseImagePreviewerArgs) {\n const [zoom, setZoom] = useState(1);\n const [portalReady, setPortalReady] = useState(false);\n\n useEffect(() => {\n setPortalReady(true);\n }, []);\n\n const resetZoom = useEffectEvent(() => {\n setZoom(1);\n });\n\n useEffect(() => {\n if (open) resetZoom();\n }, [open, imageUrl]);\n\n useEffect(() => {\n if (!open) return;\n const prevOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = prevOverflow;\n };\n }, [open]);\n\n const handleClose = useCallback(() => {\n setZoom(1);\n onClose();\n }, [onClose]);\n\n const goPrevious = useEffectEvent(() => {\n onPrevious?.();\n });\n\n const goNext = useEffectEvent(() => {\n onNext?.();\n });\n\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n handleClose();\n return;\n }\n if (e.key === \"ArrowLeft\" && onPrevious) {\n e.preventDefault();\n goPrevious();\n return;\n }\n if (e.key === \"ArrowRight\" && onNext) {\n e.preventDefault();\n goNext();\n }\n };\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [open, handleClose, onPrevious, onNext]);\n\n const zoomIn = useCallback(() => {\n setZoom((prev) => clampImagePreviewZoom(prev + ZOOM_STEP));\n }, []);\n\n const zoomOut = useCallback(() => {\n setZoom((prev) => clampImagePreviewZoom(prev - ZOOM_STEP));\n }, []);\n\n const zoomReset = useCallback(() => {\n setZoom(1);\n }, []);\n\n const onWheelZoom = useCallback((e: WheelEvent) => {\n e.preventDefault();\n const delta = e.deltaY > 0 ? -ZOOM_STEP : ZOOM_STEP;\n setZoom((prev) => clampImagePreviewZoom(prev + delta));\n }, []);\n\n return {\n zoom,\n zoomPercent: Math.round(zoom * 100),\n portalReady,\n handleClose,\n zoomIn,\n zoomOut,\n zoomReset,\n onWheelZoom,\n };\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport Loader2 from \"lucide-react/dist/esm/icons/loader-2\";\nimport Play from \"lucide-react/dist/esm/icons/play\";\nimport X from \"lucide-react/dist/esm/icons/x\";\nimport { useTranslation } from \"react-i18next\";\n\nimport type { TicketAttachmentPreviewData } from \"@/api/files\";\nimport { TicketAttachmentMediaViewer } from \"@/components/tickets/TicketAttachmentMediaViewer\";\nimport {\n EMPTY_ATTACHMENT_ITEMS,\n useTicketAttachmentPreviews,\n} from \"@/hooks/useTicketAttachmentPreviews\";\nimport {\n isVideoContentType,\n TICKET_ATTACHMENT_TILE_CLASS,\n TICKET_ATTACHMENT_TILE_STYLE,\n} from \"@/lib/tickets/ticketAttachments\";\nimport { cn } from \"@/lib/utils\";\n\ntype TicketAttachmentGalleryProps = {\n fileIds: string[];\n enabled?: boolean;\n disabled?: boolean;\n onRemove?: (fileId: string) => void;\n /** Replace a stored image with an edited File (may persist immediately upstream). */\n onReplaceImage?: (fileId: string, file: File) => void | Promise<void>;\n className?: string;\n inline?: boolean;\n loadingMessage?: string;\n unavailableMessage?: string;\n};\n\nfunction attachmentLabel(\n fileName: string | undefined,\n id: string,\n index: number,\n t: (key: string, options?: Record<string, unknown>) => string,\n): string {\n return (\n fileName?.trim() ||\n t(\"ticket.view_dialog.attachment_alt\", { index: index + 1 }) ||\n id\n );\n}\n\nexport function TicketAttachmentGallery({\n fileIds,\n enabled = true,\n disabled = false,\n onRemove,\n onReplaceImage,\n className,\n inline = false,\n loadingMessage,\n unavailableMessage,\n}: TicketAttachmentGalleryProps) {\n const { t } = useTranslation();\n const { data, isLoading } = useTicketAttachmentPreviews(fileIds, enabled);\n const items = data ?? EMPTY_ATTACHMENT_ITEMS;\n const [viewerOpen, setViewerOpen] = React.useState(false);\n const [activeIndex, setActiveIndex] = React.useState(0);\n const [failedIds, setFailedIds] = React.useState<Set<string>>(\n () => new Set(),\n );\n const fileIdsKey = fileIds.join(\",\");\n\n React.useEffect(() => {\n setFailedIds((prev) => (prev.size === 0 ? prev : new Set()));\n setViewerOpen(false);\n setActiveIndex(0);\n }, [fileIdsKey]);\n\n const visibleItems = React.useMemo(\n () => items.filter((item) => item.directUrl && !failedIds.has(item.id)),\n [items, failedIds],\n );\n\n const getLabel = React.useCallback(\n (item: TicketAttachmentPreviewData, index: number) =>\n attachmentLabel(item.meta?.fileName, item.id, index, t),\n [t],\n );\n\n const openPreview = (id: string) => {\n const index = visibleItems.findIndex((item) => item.id === id);\n if (index < 0) return;\n setActiveIndex(index);\n setViewerOpen(true);\n };\n\n const markFailed = React.useCallback((fileId: string) => {\n setFailedIds((prev) =>\n prev.has(fileId) ? prev : new Set(prev).add(fileId),\n );\n setViewerOpen(false);\n }, []);\n\n if (fileIds.length === 0) return null;\n\n if (isLoading) {\n if (inline) {\n return (\n <div\n className={cn(\n TICKET_ATTACHMENT_TILE_CLASS,\n \"animate-pulse rounded-md border border-input bg-muted/30\",\n )}\n style={TICKET_ATTACHMENT_TILE_STYLE}\n />\n );\n }\n\n return (\n <div className=\"flex items-center gap-2 py-2 text-xs text-muted-foreground\">\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" aria-hidden />\n {loadingMessage ?? t(\"ticket.create_dialog.attachments_existing_loading\")}\n </div>\n );\n }\n\n if (items.length > 0 && visibleItems.length === 0 && unavailableMessage) {\n return (\n <p className=\"text-sm text-muted-foreground\">{unavailableMessage}</p>\n );\n }\n\n const tiles = visibleItems.map((item, index) => {\n const label = getLabel(item, index);\n const src = item.directUrl!;\n const isVideo = isVideoContentType(item.contentType);\n\n return (\n <div\n key={item.id}\n className={cn(\n \"group relative\",\n inline ? TICKET_ATTACHMENT_TILE_CLASS : \"h-20 w-20\",\n )}\n style={inline ? TICKET_ATTACHMENT_TILE_STYLE : undefined}\n >\n <button\n type=\"button\"\n className={cn(\n \"relative h-full w-full overflow-hidden rounded-md border border-border bg-muted/30\",\n \"transition-shadow hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#0c66e4]\",\n )}\n title={label}\n onClick={() => openPreview(item.id)}\n aria-label={t(\"ticket.view_dialog.attachment_open\", {\n name: label,\n })}\n >\n {isVideo ? (\n <video\n src={src}\n className=\"h-full w-full object-cover\"\n muted\n playsInline\n preload=\"metadata\"\n onError={() => markFailed(item.id)}\n />\n ) : (\n // eslint-disable-next-line @next/next/no-img-element -- blob preview URLs\n <img\n src={src}\n alt={label}\n className=\"h-full w-full object-cover\"\n loading=\"lazy\"\n decoding=\"async\"\n onError={() => markFailed(item.id)}\n />\n )}\n {isVideo ? (\n <span className=\"pointer-events-none absolute inset-0 flex items-center justify-center bg-black/25\">\n <Play className=\"h-6 w-6 fill-white text-white drop-shadow\" />\n </span>\n ) : null}\n </button>\n\n {onRemove && !disabled ? (\n <button\n type=\"button\"\n className={cn(\n \"absolute -end-1.5 -top-1.5 flex h-5 w-5 items-center justify-center rounded-full\",\n \"border border-border bg-background text-foreground shadow-sm\",\n \"opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100\",\n \"hover:bg-destructive hover:text-destructive-foreground\",\n )}\n onClick={() => onRemove(item.id)}\n aria-label={t(\"ticket.create_dialog.attachments_remove\", {\n name: label,\n })}\n >\n <X className=\"h-3 w-3\" aria-hidden />\n </button>\n ) : null}\n </div>\n );\n });\n\n const viewer = (\n <TicketAttachmentMediaViewer\n open={viewerOpen}\n items={visibleItems}\n activeIndex={activeIndex}\n onActiveIndexChange={setActiveIndex}\n onClose={() => setViewerOpen(false)}\n getLabel={getLabel}\n onMediaError={markFailed}\n onSaveEditedImage={\n onReplaceImage && !disabled\n ? async (item, file) => {\n await onReplaceImage(item.id, file);\n setViewerOpen(false);\n }\n : undefined\n }\n />\n );\n\n if (inline) {\n return (\n <>\n {tiles}\n {viewer}\n </>\n );\n }\n\n return (\n <>\n <div className={cn(\"flex flex-wrap gap-2\", className)}>{tiles}</div>\n {viewer}\n </>\n );\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport {\n fetchTicketAttachmentPreviews,\n type TicketAttachmentPreviewData,\n} from \"@/api/files\";\nimport { ticketAttachmentPreviewKeys } from \"@/hooks/queries/query-keys\";\n\nexport type TicketAttachmentPreviewItem = TicketAttachmentPreviewData;\n\nconst EMPTY_ATTACHMENT_ITEMS: TicketAttachmentPreviewItem[] = [];\n\nexport function useTicketAttachmentPreviews(\n fileIds: string[],\n enabled = true,\n) {\n const idsKey = fileIds.join(\",\");\n\n return useQuery({\n queryKey: ticketAttachmentPreviewKeys.list(idsKey),\n queryFn: () => fetchTicketAttachmentPreviews(fileIds),\n enabled: enabled && fileIds.length > 0,\n staleTime: 5 * 60 * 1000,\n });\n}\n\nexport { EMPTY_ATTACHMENT_ITEMS };\n","\"use client\";\n\nimport { TicketAttachmentGallery } from \"@/components/tickets/TicketAttachmentGallery\";\n\ntype TicketStoredAttachmentPreviewsProps = {\n fileIds: string[];\n disabled?: boolean;\n onRemove: (fileId: string) => void;\n onReplaceImage?: (fileId: string, file: File) => void | Promise<void>;\n inline?: boolean;\n};\n\nexport function TicketStoredAttachmentPreviews({\n fileIds,\n disabled = false,\n onRemove,\n onReplaceImage,\n inline = false,\n}: TicketStoredAttachmentPreviewsProps) {\n return (\n <TicketAttachmentGallery\n fileIds={fileIds}\n disabled={disabled}\n onRemove={onRemove}\n onReplaceImage={onReplaceImage}\n inline={inline}\n className=\"grid-cols-3 sm:grid-cols-4 md:grid-cols-5\"\n />\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { Check, Minus } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\n\nconst Checkbox = React.forwardRef<\n React.ElementRef<typeof CheckboxPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <CheckboxPrimitive.Root\n ref={ref}\n className={cn(\n \"peer h-4 w-4 shrink-0 rounded-sm border border-input shadow-sm focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground data-[state=indeterminate]:border-primary\",\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n className={cn(\"flex items-center justify-center text-current\")}\n >\n {props.checked === \"indeterminate\" ? (\n <Minus className=\"h-3 w-3\" />\n ) : (\n <Check className=\"h-3 w-3\" />\n )}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n));\nCheckbox.displayName = CheckboxPrimitive.Root.displayName;\n\nexport { Checkbox };\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n SelectRoot,\n SelectContent as PackageSelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n} from \"@avament-pub/select\";\n\n/**\n * App Select root — maps package `SelectRoot` to the familiar `Select` name\n * used across ticket screens (avoids clashing with the high-level catalog Select).\n */\nconst Select = SelectRoot;\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof PackageSelectContent>,\n React.ComponentPropsWithoutRef<typeof PackageSelectContent>\n>(function SelectContent(\n { collisionPadding = 16, style, ...props },\n ref,\n) {\n return (\n <PackageSelectContent\n ref={ref}\n collisionPadding={collisionPadding}\n collisionBoundary={[]}\n sticky=\"partial\"\n style={{ zIndex: 160, ...style }}\n {...props}\n />\n );\n});\nSelectContent.displayName = \"SelectContent\";\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n};\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { Input } from \"@/components/ui/input\";\nimport type { CreateTicketBufferedInputProps } from \"@/components/tickets/create-ticket-buffered-input.types\";\n\n/**\n * Keeps keystrokes in local state so the parent dialog can update at\n * transition priority without blocking the caret.\n */\nexport const CreateTicketBufferedInput = React.memo(\n React.forwardRef<HTMLInputElement, CreateTicketBufferedInputProps>(\n function CreateTicketBufferedInput(\n { value, onChange, ...props },\n ref,\n ) {\n const [localValue, setLocalValue] = React.useState(value);\n const externalValueRef = React.useRef(value);\n\n if (value !== externalValueRef.current) {\n externalValueRef.current = value;\n setLocalValue(value);\n }\n\n return (\n <Input\n {...props}\n ref={ref}\n value={localValue}\n onChange={(event) => {\n const next = event.target.value;\n setLocalValue(next);\n onChange(next);\n }}\n />\n );\n },\n ),\n);\n\nCreateTicketBufferedInput.displayName = \"CreateTicketBufferedInput\";\n","\"use client\";\n\nimport * as React from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport Check from \"lucide-react/dist/esm/icons/check\";\nimport { useTranslation } from \"react-i18next\";\n\nimport type { TicketCreateSuccessOverlayProps } from \"@/components/tickets/ticket-create-success-overlay.types\";\n\nconst HOLD_MS = 1200;\nconst PARTICLE_COUNT = 10;\n\nconst PARTICLES = Array.from({ length: PARTICLE_COUNT }, (_, index) => {\n const angle = (Math.PI * 2 * index) / PARTICLE_COUNT;\n return {\n id: index,\n x: Math.cos(angle) * 56,\n y: Math.sin(angle) * 56,\n };\n});\n\nexport function TicketCreateSuccessOverlay({\n open,\n serial,\n onComplete,\n}: TicketCreateSuccessOverlayProps) {\n const { t } = useTranslation();\n const completedRef = React.useRef(false);\n\n React.useEffect(() => {\n if (!open) {\n completedRef.current = false;\n return;\n }\n\n const timer = window.setTimeout(() => {\n if (completedRef.current) return;\n completedRef.current = true;\n onComplete();\n }, HOLD_MS);\n\n return () => window.clearTimeout(timer);\n }, [open, onComplete]);\n\n return (\n <AnimatePresence>\n {open ? (\n <motion.div\n key=\"ticket-create-success\"\n role=\"status\"\n aria-live=\"polite\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={{ duration: 0.2, ease: \"easeOut\" }}\n className=\"absolute inset-0 z-50 flex flex-col items-center justify-center bg-background/95 backdrop-blur-sm\"\n >\n <div className=\"relative flex h-28 w-28 items-center justify-center\">\n {PARTICLES.map((particle) => (\n <motion.span\n key={particle.id}\n aria-hidden\n className=\"absolute h-1.5 w-1.5 rounded-full bg-primary\"\n initial={{ opacity: 0, x: 0, y: 0, scale: 0.4 }}\n animate={{\n opacity: [0, 1, 0],\n x: particle.x,\n y: particle.y,\n scale: [0.4, 1, 0.2],\n }}\n transition={{\n duration: 0.7,\n delay: 0.18,\n ease: \"easeOut\",\n }}\n />\n ))}\n\n <motion.div\n aria-hidden\n className=\"absolute inset-0 rounded-full border-2 border-primary/25\"\n initial={{ scale: 0.6, opacity: 0 }}\n animate={{ scale: [0.6, 1.35, 1.55], opacity: [0.55, 0.2, 0] }}\n transition={{ duration: 0.85, ease: \"easeOut\", delay: 0.12 }}\n />\n\n <motion.div\n className=\"relative flex h-16 w-16 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-md\"\n initial={{ scale: 0.5, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n transition={{\n type: \"spring\",\n stiffness: 420,\n damping: 18,\n delay: 0.05,\n }}\n >\n <motion.span\n initial={{ opacity: 0, scale: 0.6 }}\n animate={{ opacity: 1, scale: 1 }}\n transition={{ delay: 0.22, duration: 0.25, ease: \"easeOut\" }}\n className=\"flex\"\n >\n <Check className=\"h-8 w-8\" strokeWidth={2.5} aria-hidden />\n </motion.span>\n </motion.div>\n </div>\n\n <motion.p\n className=\"mt-5 text-base font-semibold text-foreground\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ delay: 0.28, duration: 0.25, ease: \"easeOut\" }}\n >\n {t(\"ticket.create_dialog.create_success\")}\n </motion.p>\n\n {serial ? (\n <motion.p\n className=\"mt-1 text-sm text-muted-foreground\"\n initial={{ opacity: 0, y: 6 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ delay: 0.36, duration: 0.25, ease: \"easeOut\" }}\n >\n {t(\"ticket.create_dialog.create_success_serial\", { serial })}\n </motion.p>\n ) : null}\n </motion.div>\n ) : null}\n </AnimatePresence>\n );\n}\n","export const CREATE_TICKET_FIELD_IDS = [\n \"short_description\",\n \"long_description\",\n \"attachments\",\n \"type\",\n \"event\",\n \"status\",\n \"priority\",\n \"deadline\",\n \"company\",\n] as const;\n\nexport type CreateTicketFieldId = (typeof CREATE_TICKET_FIELD_IDS)[number];\n\nexport const DEFAULT_CREATE_TICKET_FIELD_ORDER: CreateTicketFieldId[] = [\n ...CREATE_TICKET_FIELD_IDS,\n];\n\nexport const CREATE_TICKET_FIELD_COLUMN: Record<\n CreateTicketFieldId,\n \"left\" | \"right\" | \"full\"\n> = {\n short_description: \"left\",\n long_description: \"left\",\n attachments: \"left\",\n type: \"right\",\n event: \"right\",\n status: \"right\",\n priority: \"right\",\n deadline: \"right\",\n company: \"right\",\n};\n\nexport function reorderCreateTicketFields(\n order: CreateTicketFieldId[],\n draggedId: CreateTicketFieldId,\n targetId: CreateTicketFieldId,\n): CreateTicketFieldId[] {\n const from = order.indexOf(draggedId);\n const to = order.indexOf(targetId);\n if (from === -1 || to === -1 || from === to) return order;\n\n const next = [...order];\n next.splice(from, 1);\n next.splice(to, 0, draggedId);\n return next;\n}\n","import {\n CREATE_TICKET_FIELD_IDS,\n type CreateTicketFieldId,\n} from \"@/lib/tickets/createTicketFieldOrder\";\n\nexport const CREATE_TICKET_VISIBILITY_FIELD_IDS = [\n ...CREATE_TICKET_FIELD_IDS,\n] as const;\n\nexport type CreateTicketVisibilityFieldId =\n (typeof CREATE_TICKET_VISIBILITY_FIELD_IDS)[number];\n\nexport const CREATE_DIALOG_VISIBILITY_FIELD_IDS =\n CREATE_TICKET_VISIBILITY_FIELD_IDS.filter(\n (id): id is Exclude<CreateTicketVisibilityFieldId, \"status\"> =>\n id !== \"status\",\n );\n\nexport type CreateDialogVisibilityFieldId =\n (typeof CREATE_DIALOG_VISIBILITY_FIELD_IDS)[number];\n\nexport const DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS: CreateDialogVisibilityFieldId[] =\n [...CREATE_DIALOG_VISIBILITY_FIELD_IDS];\n\n/** @deprecated Legacy localStorage key — used only for one-time migration to backend. */\nexport const FIELD_VISIBILITY_STORAGE_KEY = \"ticket-create-field-visibility\";\n\nexport function normalizeVisibleFieldIds(\n ids: Iterable<string>,\n): CreateDialogVisibilityFieldId[] {\n const seen = new Set<CreateDialogVisibilityFieldId>();\n for (const id of ids) {\n if (\n typeof id === \"string\" &&\n (CREATE_DIALOG_VISIBILITY_FIELD_IDS as readonly string[]).includes(id)\n ) {\n seen.add(id as CreateDialogVisibilityFieldId);\n }\n }\n return [...seen];\n}\n\nexport function loadLegacyVisibleFieldIdsFromStorage(): CreateDialogVisibilityFieldId[] {\n if (typeof window === \"undefined\") return [];\n try {\n const raw = localStorage.getItem(FIELD_VISIBILITY_STORAGE_KEY);\n if (!raw) return [];\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) return [];\n return normalizeVisibleFieldIds(parsed);\n } catch {\n return [];\n }\n}\n\nexport function clearLegacyVisibleFieldIdsFromStorage(): void {\n try {\n localStorage.removeItem(FIELD_VISIBILITY_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n}\n\nexport function isCreateTicketFieldId(\n id: CreateTicketVisibilityFieldId,\n): id is CreateTicketFieldId {\n return (CREATE_TICKET_FIELD_IDS as readonly string[]).includes(id);\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport Palette from \"lucide-react/dist/esm/icons/palette\";\nimport { AxiosError } from \"axios\";\nimport { Select as CatalogSelect, type SelectOption } from \"@avament-pub/select\";\nimport { useTranslation } from \"react-i18next\";\n\nimport type {\n AssignmentType,\n TicketResponsibleDto,\n TicketResponsibleEntryDto,\n} from \"@/api/dto/ticket.dto\";\nimport type { TicketSequenceDto } from \"@/api/dto/ticket-sequence.dto\";\nimport { TicketCatalogColorSwatch } from \"@/components/tickets/TicketCatalogColorField\";\nimport { ColorPickerPanel } from \"@/components/ui/color-picker\";\nimport { Input } from \"@/components/ui/input\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\";\nimport {\n getResponsibleEntryId,\n getResponsibleEntryName,\n normalizeResponsibleStatusKey,\n singleAssignmentType,\n} from \"@/lib/tickets/ticketAssignment\";\nimport {\n TICKET_CATALOG_DEFAULT_COLOR,\n resolveTicketResponsibleColor,\n ticketCatalogColorForUpdate,\n ticketCatalogTextStyle,\n} from \"@/lib/tickets/ticketCatalogColors\";\nimport { useTicketResponsibles } from \"@/hooks/useTicketResponsibles\";\nimport { getTicketResponsibleCatalogId } from \"@/lib/tickets/ticketResponsibleCatalog\";\nimport { cn } from \"@/lib/utils\";\n\n/** Support assignment shape: Single (API `single`), Sequence, or Multi. */\nexport type TicketAssignmentType = AssignmentType;\n\ntype TicketResponsibleFieldProps = {\n assignmentType: TicketAssignmentType;\n onAssignmentTypeChange?: (type: TicketAssignmentType) => void;\n sequenceId: string;\n onSequenceIdChange?: (sequenceId: string) => void;\n responsibleUserId?: string;\n onResponsibleUserIdChange?: (userId: string) => void;\n /** Selected user ids for multi assignment. */\n responsibleIds?: string[];\n onResponsibleIdsChange?: (ids: string[]) => void;\n /** Detail rows with per-responsible status (multi tickets). */\n responsibleEntries?: TicketResponsibleEntryDto[] | null;\n canChooseAssignment: boolean;\n readOnly?: boolean;\n sequences: TicketSequenceDto[];\n users?: TicketResponsibleDto[];\n /** Full responsibles catalog used for text colors. */\n catalogResponsibles?: TicketResponsibleDto[];\n sequencesLoading?: boolean;\n usersLoading?: boolean;\n /** Optional pre-filtered list for single-select (defaults to sorted `users`). */\n filteredUsers?: TicketResponsibleDto[];\n sequenceName?: string | null;\n sequenceStepNumber?: number | null;\n sequenceStepCount?: number | null;\n currentUserName?: string | null;\n className?: string;\n required?: boolean;\n};\n\nfunction FloatingLabel({\n label,\n required = false,\n children,\n}: {\n label: string;\n required?: boolean;\n children: React.ReactNode;\n}) {\n return (\n <div className=\"relative\">\n <span className=\"pointer-events-none absolute -top-2.5 start-3 z-10 bg-background px-1 text-xs text-theme-secondary\">\n {label}\n {required ? (\n <span className=\"text-destructive\" aria-hidden=\"true\">\n {\" \"}\n *\n </span>\n ) : null}\n </span>\n {children}\n </div>\n );\n}\n\nfunction AssignmentTypeTabs({\n value,\n onChange,\n}: {\n value: AssignmentType;\n onChange: (type: TicketAssignmentType) => void;\n}) {\n const { t } = useTranslation();\n const options: Array<{\n key: AssignmentType;\n label: string;\n type: TicketAssignmentType;\n }> = [\n {\n key: \"single\",\n label: t(\"ticket.sequence.single_company\"),\n type: singleAssignmentType(),\n },\n {\n key: \"sequence\",\n label: t(\"ticket.sequence.sequence\"),\n type: \"sequence\",\n },\n {\n key: \"multi\",\n label: t(\"ticket.sequence.multi\"),\n type: \"multi\",\n },\n ];\n\n return (\n <div\n role=\"tablist\"\n aria-label={t(\"ticket.sequence.assignment_type\")}\n className=\"relative inline-grid h-8 shrink-0 grid-cols-3 items-stretch overflow-hidden rounded-md border border-border bg-background text-xs\"\n >\n {options.map((option) => {\n const selected = value === option.key;\n return (\n <button\n key={option.key}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n className={cn(\n \"cursor-pointer whitespace-nowrap px-3 py-2 text-center font-medium transition-all duration-150\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1\",\n selected\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted/30 text-foreground/80 hover:bg-muted/70 hover:text-foreground\",\n )}\n onClick={() => onChange(option.type)}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport const TicketResponsibleField = React.memo(function TicketResponsibleField({\n assignmentType,\n onAssignmentTypeChange,\n sequenceId,\n onSequenceIdChange,\n responsibleUserId = \"\",\n onResponsibleUserIdChange,\n responsibleIds = [],\n onResponsibleIdsChange,\n responsibleEntries = null,\n canChooseAssignment,\n readOnly = false,\n sequences,\n users = [],\n catalogResponsibles,\n sequencesLoading = false,\n usersLoading = false,\n filteredUsers,\n sequenceName,\n sequenceStepNumber,\n sequenceStepCount,\n currentUserName,\n className,\n required = false,\n}: TicketResponsibleFieldProps) {\n const { t } = useTranslation();\n const { updateResponsibleColor, isResponsibleColorEditable } =\n useTicketResponsibles();\n const [colorEditId, setColorEditId] = React.useState<string | null>(null);\n const [colorDraft, setColorDraft] = React.useState(\"\");\n const [colorSaving, setColorSaving] = React.useState(false);\n const [colorError, setColorError] = React.useState<string | null>(null);\n\n const shape: AssignmentType = assignmentType;\n\n const colorCatalog = catalogResponsibles ?? users;\n\n const getOptionColor = React.useCallback(\n (id: string, fallback?: string | null) => {\n if (colorCatalog.length > 0) {\n const resolved = resolveTicketResponsibleColor(colorCatalog, id);\n if (resolved) return resolved;\n }\n return fallback ?? \"\";\n },\n [colorCatalog],\n );\n\n const sortedUsers = React.useMemo(\n () =>\n [...users].sort((a, b) =>\n a.name.localeCompare(b.name, undefined, { sensitivity: \"base\" }),\n ),\n [users],\n );\n\n const singleUsers = filteredUsers ?? sortedUsers;\n\n const statusByResponsibleId = React.useMemo(() => {\n const map = new Map<string, string>();\n for (const entry of responsibleEntries ?? []) {\n const id = getResponsibleEntryId(entry);\n if (!id) continue;\n map.set(id, normalizeResponsibleStatusKey(entry.statusKey));\n }\n return map;\n }, [responsibleEntries]);\n\n const toUserOption = React.useCallback(\n (user: TicketResponsibleDto, withStatus: boolean): SelectOption | null => {\n const id = getTicketResponsibleCatalogId(user);\n if (!id) return null;\n const color = getOptionColor(id, user.color);\n const statusKey = withStatus ? statusByResponsibleId.get(id) : undefined;\n return {\n value: id,\n label: user.name,\n icon: <TicketCatalogColorSwatch color={color} />,\n endAdornment:\n withStatus && statusKey && responsibleIds.includes(id) ? (\n <span className=\"text-xs text-muted-foreground\">\n {t(`ticket.table.status.${statusKey}`)}\n </span>\n ) : undefined,\n };\n },\n [getOptionColor, responsibleIds, statusByResponsibleId, t],\n );\n\n const showColorActions = React.useMemo(\n () =>\n users.some((user) => {\n const id = getTicketResponsibleCatalogId(user);\n return Boolean(id && isResponsibleColorEditable(id));\n }),\n [isResponsibleColorEditable, users],\n );\n\n const stopAction = (event: React.SyntheticEvent) => {\n event.preventDefault();\n event.stopPropagation();\n };\n\n const handleSaveColor = async () => {\n if (!colorEditId || !isResponsibleColorEditable(colorEditId)) return;\n setColorSaving(true);\n setColorError(null);\n try {\n const patchColor = ticketCatalogColorForUpdate(colorDraft, false);\n await updateResponsibleColor(colorEditId, patchColor ?? null);\n setColorEditId(null);\n } catch (error) {\n setColorError(\n error instanceof AxiosError && error.response?.status === 400\n ? t(\"ticket.catalog.color_invalid\")\n : t(\"ticket.catalog.color_save_failed\"),\n );\n } finally {\n setColorSaving(false);\n }\n };\n\n const colorPickerFooter = colorEditId ? (\n <div className=\"border-t border-border p-2\">\n {colorError ? (\n <p className=\"mb-2 text-xs text-destructive\">{colorError}</p>\n ) : null}\n <ColorPickerPanel\n color={colorDraft}\n onChange={setColorDraft}\n onCancel={() => {\n setColorEditId(null);\n setColorError(null);\n }}\n onSave={() => void handleSaveColor()}\n saving={colorSaving}\n labels={{\n cancelLabel: t(\"cancel\"),\n saveLabel: t(\"common.save\"),\n }}\n />\n </div>\n ) : null;\n\n const renderColorAction = (option: SelectOption) => {\n if (!isResponsibleColorEditable(option.value)) return null;\n const color = getOptionColor(option.value) || TICKET_CATALOG_DEFAULT_COLOR;\n return (\n <button\n type=\"button\"\n className=\"rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground\"\n aria-label={t(\"ticket.catalog.color_edit\")}\n disabled={colorSaving}\n onPointerDown={stopAction}\n onClick={(event) => {\n stopAction(event);\n setColorError(null);\n setColorEditId(option.value);\n setColorDraft(color);\n }}\n >\n <span className=\"relative inline-flex\">\n <Palette className=\"h-3.5 w-3.5\" aria-hidden />\n <span\n className=\"absolute -bottom-0.5 -end-0.5 h-1.5 w-1.5 rounded-full border border-background\"\n style={{ backgroundColor: color }}\n aria-hidden\n />\n </span>\n </button>\n );\n };\n\n const singleUserOptions = React.useMemo(\n () =>\n singleUsers\n .map((user) => toUserOption(user, false))\n .filter((option): option is SelectOption => option != null),\n [singleUsers, toUserOption],\n );\n\n const multiUserOptions = React.useMemo(\n () =>\n sortedUsers\n .map((user) => toUserOption(user, true))\n .filter((option): option is SelectOption => option != null),\n [sortedUsers, toUserOption],\n );\n\n const actorName =\n currentUserName ??\n users.find(\n (user) => getTicketResponsibleCatalogId(user) === responsibleUserId,\n )?.name ??\n \"\";\n const showSequenceInfo =\n shape === \"sequence\" &&\n sequenceName &&\n sequenceStepNumber != null &&\n sequenceStepCount != null;\n\n const multiEntries: TicketResponsibleEntryDto[] = responsibleEntries?.length\n ? responsibleEntries\n : responsibleIds.map((id) => {\n const user = users.find(\n (entry) => getTicketResponsibleCatalogId(entry) === id,\n );\n return {\n userId: id,\n userName: user?.name,\n statusKey: \"open\" as const,\n };\n });\n\n if (readOnly || !canChooseAssignment) {\n return (\n <div className={cn(\"space-y-3\", className)}>\n {showSequenceInfo ? (\n <FloatingLabel label={t(\"ticket.sequence.assignment_label\")}>\n <Input\n value={t(\"ticket.sequence.step_header\", {\n name: sequenceName,\n step: sequenceStepNumber,\n count: sequenceStepCount,\n company: actorName,\n })}\n readOnly\n disabled\n className=\"h-10\"\n />\n </FloatingLabel>\n ) : shape === \"multi\" && multiEntries.length > 0 ? (\n <FloatingLabel label={t(\"ticket.sequence.multi_label\")}>\n <ul className=\"max-h-40 space-y-1 overflow-y-auto rounded-md border border-input px-2.5 py-2 text-sm\">\n {multiEntries.map((entry) => {\n const id =\n getResponsibleEntryId(entry) ?? getResponsibleEntryName(entry);\n const statusKey = normalizeResponsibleStatusKey(entry.statusKey);\n return (\n <li\n key={id}\n className=\"flex items-center justify-between gap-2 py-0.5\"\n >\n <span\n className=\"min-w-0 truncate\"\n style={ticketCatalogTextStyle(\n getOptionColor(\n getResponsibleEntryId(entry) ?? \"\",\n undefined,\n ),\n )}\n >\n {getResponsibleEntryName(entry) ||\n t(\"ticket.table.empty_value\")}\n </span>\n {responsibleEntries?.length || entry.statusKey ? (\n <span className=\"shrink-0 text-xs text-muted-foreground\">\n {t(`ticket.table.status.${statusKey}`)}\n </span>\n ) : null}\n </li>\n );\n })}\n </ul>\n </FloatingLabel>\n ) : (\n <FloatingLabel label={t(\"ticket.create_dialog.labels.company\")}>\n <Input\n value={\n usersLoading\n ? t(\"ticket.create_dialog.users_loading\")\n : actorName || t(\"ticket.table.empty_value\")\n }\n readOnly\n disabled\n className=\"h-10\"\n style={ticketCatalogTextStyle(\n getOptionColor(responsibleUserId, undefined),\n )}\n />\n </FloatingLabel>\n )}\n </div>\n );\n }\n\n const canChangeAssignmentType = Boolean(onAssignmentTypeChange);\n\n return (\n <div\n className={cn(\n canChangeAssignmentType ? \"space-y-5\" : \"space-y-2\",\n className,\n )}\n >\n {canChangeAssignmentType ? (\n <AssignmentTypeTabs value={shape} onChange={onAssignmentTypeChange!} />\n ) : null}\n\n <FloatingLabel\n label={\n shape === \"sequence\"\n ? t(\"ticket.sequence.sequence\")\n : shape === \"multi\"\n ? t(\"ticket.sequence.multi_label\")\n : t(\"ticket.create_dialog.labels.company\")\n }\n required={required}\n >\n {shape === \"sequence\" ? (\n <Select\n value={sequenceId || undefined}\n onValueChange={(value) => onSequenceIdChange?.(value)}\n disabled={sequencesLoading}\n >\n <SelectTrigger className=\"h-9\">\n <SelectValue\n placeholder={\n sequencesLoading\n ? t(\"ticket.sequence.loading\")\n : t(\"ticket.sequence.select_placeholder\")\n }\n />\n </SelectTrigger>\n <SelectContent>\n {sequences.length === 0 && !sequencesLoading ? (\n <div className=\"px-2 py-4 text-center text-xs text-muted-foreground\">\n {t(\"ticket.sequence.empty\")}\n </div>\n ) : (\n sequences.map((sequence) => (\n <SelectItem key={sequence.id} value={sequence.id}>\n {sequence.name} ({sequence.steps.length})\n </SelectItem>\n ))\n )}\n </SelectContent>\n </Select>\n ) : shape === \"multi\" ? (\n <CatalogSelect\n mode=\"searchable\"\n selection=\"multiple\"\n selectAll\n options={multiUserOptions}\n value={responsibleIds}\n onChange={(next) => onResponsibleIdsChange?.(next)}\n disabled={readOnly || usersLoading || (users.length === 0 && !usersLoading)}\n sortAlphabetically\n optionActionsVisibility={showColorActions ? \"hover\" : undefined}\n renderOptionActions={\n showColorActions ? renderColorAction : undefined\n }\n placeholder={t(\"ticket.sequence.multi_placeholder\", {\n defaultValue: \"Select responsibles\",\n })}\n selectedCountLabel={(count) =>\n t(\"ticket.sequence.multi_selected\", { count })\n }\n labels={{\n searchPlaceholder: t(\"ticket.table.search_placeholder\"),\n selectAllLabel: t(\"ticket.sequence.multi_select_all\"),\n emptyMessage: t(\"ticket.create_dialog.users_empty\"),\n }}\n footer={\n colorPickerFooter ?? (\n <p className=\"border-t border-border px-2.5 py-1.5 text-[11px] text-muted-foreground\">\n {responsibleIds.length < 2\n ? t(\"ticket.sequence.multi_min\")\n : t(\"ticket.sequence.multi_selected\", {\n count: responsibleIds.length,\n })}\n </p>\n )\n }\n />\n ) : (\n <CatalogSelect\n mode=\"searchable\"\n options={singleUserOptions}\n value={responsibleUserId || null}\n onChange={(next) => onResponsibleUserIdChange?.(next ?? \"\")}\n disabled={usersLoading}\n clearable\n sortAlphabetically\n optionActionsVisibility={showColorActions ? \"hover\" : undefined}\n renderOptionActions={\n showColorActions ? renderColorAction : undefined\n }\n footer={colorPickerFooter}\n placeholder={\n usersLoading\n ? t(\"ticket.create_dialog.users_loading\")\n : t(\"ticket.create_dialog.select_user_placeholder\")\n }\n labels={{\n searchPlaceholder: t(\"ticket.table.search_placeholder\"),\n emptyMessage: t(\"ticket.create_dialog.users_empty\"),\n }}\n />\n )}\n </FloatingLabel>\n </div>\n );\n});\n","\"use client\";\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\n\nimport type { TicketResponsibleDto } from \"@/api/dto/ticket.dto\";\nimport {\n fetchAuthStaff,\n SUPPORT_ASSIGNEE_DEFAULT_COLOR,\n updateAuthStaffColor,\n type AuthStaffRow,\n} from \"@/api/staff\";\nimport { fetchSupportAssignees } from \"@/api/ticket\";\nimport { canManageStaffColors } from \"@/lib/auth/isStaffRole\";\nimport { useUserInfo } from \"@/hooks/useUserInfo\";\nimport { authStaffKeys, ticketResponsibleKeys, ticketKeys } from \"@/hooks/queries/query-keys\";\n\nexport type TicketResponsible = TicketResponsibleDto;\n\n/** Support assignees (`GET /api/support/assignees`) — staff only on API. */\nexport function useTicketResponsibles() {\n const queryClient = useQueryClient();\n const { userInfo } = useUserInfo();\n const canManageResponsibleColors = canManageStaffColors(userInfo);\n\n const query = useQuery({\n queryKey: ticketResponsibleKeys.list(),\n queryFn: fetchSupportAssignees,\n });\n\n const staffQuery = useQuery({\n queryKey: authStaffKeys.list(),\n queryFn: fetchAuthStaff,\n enabled: canManageResponsibleColors,\n });\n\n const staffByAssigneeId = React.useMemo(() => {\n const map = new Map<string, AuthStaffRow>();\n if (!canManageResponsibleColors) return map;\n\n const assignees = query.data ?? [];\n const assigneeIdByEmail = new Map<string, string>();\n for (const assignee of assignees) {\n const id = assignee.userId?.trim();\n const email = assignee.email?.trim().toLowerCase();\n if (id && email) assigneeIdByEmail.set(email, id);\n }\n\n for (const row of staffQuery.data ?? []) {\n const staffUserId = row.userId.trim();\n if (\n staffUserId &&\n assignees.some((assignee) => assignee.userId === staffUserId)\n ) {\n map.set(staffUserId, row);\n }\n const assigneeId = assigneeIdByEmail.get(row.email.trim().toLowerCase());\n if (assigneeId) map.set(assigneeId, row);\n }\n return map;\n }, [canManageResponsibleColors, query.data, staffQuery.data]);\n\n const editableResponsibleIds = React.useMemo(\n () => new Set(staffByAssigneeId.keys()),\n [staffByAssigneeId],\n );\n const staffByAssigneeIdRef = React.useRef(staffByAssigneeId);\n staffByAssigneeIdRef.current = staffByAssigneeId;\n\n const isResponsibleColorEditable = React.useCallback(\n (userId: string) => editableResponsibleIds.has(userId),\n [editableResponsibleIds],\n );\n\n const invalidateCatalog = React.useCallback(async () => {\n await Promise.all([\n queryClient.invalidateQueries({\n queryKey: ticketResponsibleKeys.all,\n }),\n queryClient.invalidateQueries({ queryKey: ticketKeys.all }),\n queryClient.invalidateQueries({ queryKey: authStaffKeys.all }),\n ]);\n }, [queryClient]);\n\n const updateMutation = useMutation({\n mutationFn: async ({\n userId,\n color,\n }: {\n userId: string;\n color: string | null;\n }) => {\n const staff = staffByAssigneeIdRef.current.get(userId);\n if (!staff?.userId) {\n throw new Error(\"Staff color applies to STAFF users only\");\n }\n // PATCH /api/auth/staff/{userId} — registration staff id, not ticket routes.\n const staffUserId = staff.userId;\n await updateAuthStaffColor({ userId: staffUserId, color });\n return { userId, staffUserId, color };\n },\n onSuccess: ({ userId, staffUserId, color }) => {\n const storedColor = color?.trim() ? color.trim() : null;\n const displayColor = storedColor ?? SUPPORT_ASSIGNEE_DEFAULT_COLOR;\n queryClient.setQueryData<TicketResponsible[]>(\n ticketResponsibleKeys.list(),\n (current = []) =>\n current.map((responsible) =>\n responsible.userId === userId\n ? { ...responsible, color: displayColor }\n : responsible,\n ),\n );\n queryClient.setQueryData<AuthStaffRow[]>(\n authStaffKeys.list(),\n (current = []) =>\n current.map((row) =>\n row.userId === staffUserId\n ? { ...row, color: storedColor }\n : row,\n ),\n );\n },\n });\n\n const updateResponsibleColor = React.useCallback(\n async (userId: string, color: string | null) => {\n await updateMutation.mutateAsync({ userId, color });\n },\n [updateMutation],\n );\n\n return {\n isMutating: updateMutation.isPending,\n responsibles: query.data ?? [],\n isLoading: query.isLoading,\n isError: query.isError,\n error: query.error,\n refresh: query.refetch,\n invalidateCatalog,\n canManageResponsibleColors,\n editableResponsibleIds,\n isResponsibleColorEditable,\n updateResponsibleColor,\n };\n}\n","import type { TicketResponsibleDto } from \"@/api/dto/ticket.dto\";\n\n/** Catalog row id used for PATCH …/ticket-responsibles/{id}. */\nexport function getTicketResponsibleCatalogId(\n responsible: Pick<TicketResponsibleDto, \"kind\" | \"companyId\" | \"userId\">,\n): string {\n if (responsible.kind === \"user\") {\n return responsible.userId?.trim() || \"\";\n }\n if (responsible.kind === \"company\") {\n return responsible.companyId?.trim() || \"\";\n }\n return (\n responsible.userId?.trim() ||\n responsible.companyId?.trim() ||\n \"\"\n );\n}\n\nexport function isTicketResponsibleUser(\n responsible: Pick<TicketResponsibleDto, \"kind\" | \"userId\" | \"companyId\">,\n): boolean {\n if (responsible.kind === \"user\") return true;\n if (responsible.kind === \"company\") return false;\n return Boolean(responsible.userId?.trim()) && !responsible.companyId?.trim();\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\n\nimport { fetchTicket } from \"@/api/ticket\";\nimport { ticketKeys } from \"@/hooks/queries/query-keys\";\n\ntype UseTicketOptions = {\n enabled?: boolean;\n includeArchived?: boolean;\n};\n\nexport function useTicket(\n ticketId: string | null | undefined,\n options: UseTicketOptions = {},\n) {\n const includeArchived = options.includeArchived ?? true;\n const enabled = options.enabled !== false && Boolean(ticketId);\n\n return useQuery({\n queryKey: ticketKeys.detail(ticketId ?? \"\"),\n queryFn: () => fetchTicket(ticketId!, { includeArchived }),\n enabled,\n });\n}\n\ntype UseBulkEditTicketsOptions = {\n enabled?: boolean;\n};\n\nexport function useBulkEditTickets(\n ticketIds: readonly string[],\n options: UseBulkEditTicketsOptions = {},\n) {\n const enabled = options.enabled !== false && ticketIds.length > 0;\n\n return useQuery({\n queryKey: ticketKeys.bulkEdit(ticketIds),\n queryFn: () =>\n Promise.all(\n ticketIds.map((id) => fetchTicket(id, { includeArchived: true })),\n ),\n enabled,\n staleTime: 0,\n refetchOnMount: \"always\",\n });\n}\n","import type { TicketDetailDto } from \"@/api/dto/ticket.dto\";\nimport { updateTicket } from \"@/api/ticket\";\nimport type { TicketFormFields } from \"@/api/ticketForm\";\nimport type { TicketStatusKey } from \"@/lib/tickets/ticketRow\";\n\nexport type TicketAttachmentPool = \"general\";\n\n/** Minimal PATCH body for attachment-only updates (reporters after open). */\nexport function buildAttachmentOnlyTicketFields(\n existingAttachmentIds: string[],\n options?: { statusKey?: TicketStatusKey },\n): TicketFormFields {\n const fields: TicketFormFields = {\n existingAttachmentIds,\n };\n if (options?.statusKey) {\n fields.statusKey = options.statusKey;\n }\n return fields;\n}\n\n/**\n * Persist an edited image immediately: drop the old file id and upload the new\n * file into the ticket attachments.\n */\nexport async function persistReplacedTicketAttachment(options: {\n ticketId: string;\n statusKey?: TicketStatusKey;\n pool?: TicketAttachmentPool;\n existingAttachmentIds: readonly string[];\n replacedFileId: string;\n file: File;\n}): Promise<TicketDetailDto> {\n const { ticketId, statusKey, existingAttachmentIds, replacedFileId, file } =\n options;\n\n const nextGeneral = existingAttachmentIds.filter((id) => id !== replacedFileId);\n\n return updateTicket(\n ticketId,\n buildAttachmentOnlyTicketFields(nextGeneral, statusKey ? { statusKey } : undefined),\n [file],\n );\n}\n","\"use client\";\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\n\nimport type {\n TicketCreatePreferencesDto,\n UpdateTicketCreatePreferencesRequest,\n} from \"@/api/dto/ticket-create-preferences.dto\";\nimport {\n fetchTicketCreatePreferences,\n saveTicketCreatePreferences,\n} from \"@/api/ticketCreatePreferences\";\nimport { getProjectId } from \"@/api/client\";\nimport {\n clearLegacyVisibleFieldIdsFromStorage,\n DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS,\n loadLegacyVisibleFieldIdsFromStorage,\n normalizeVisibleFieldIds,\n type CreateDialogVisibilityFieldId,\n} from \"@/lib/tickets/createTicketFieldVisibility\";\nimport {\n clearLegacyKeepAddingFromStorage,\n clearLegacyKeepFieldsFromStorage,\n DEFAULT_KEEP_ON_ADD_FIELDS,\n hasLegacyKeepAddingInStorage,\n loadLegacyKeepAddingFromStorage,\n loadLegacyKeepFieldsFromStorage,\n normalizeKeepFieldIds,\n type KeepOnAddFieldId,\n} from \"@/lib/tickets/createTicketKeepFields\";\nimport { createTicketFieldVisibilityKeys } from \"@/hooks/queries/query-keys\";\nimport { subscribeProjectContextChanged } from \"@/lib/workspaceContext\";\n\nconst SAVE_DEBOUNCE_MS = 400;\n\ntype UseCreateTicketFieldVisibilityOptions = {\n enabled?: boolean;\n};\n\nfunction isEmptyPatch(patch: UpdateTicketCreatePreferencesRequest): boolean {\n return (\n patch.visibleFieldIds === undefined &&\n patch.keepAdding === undefined &&\n patch.keepFieldIds === undefined\n );\n}\n\nfunction mergePreferences(\n projectId: string,\n previous: TicketCreatePreferencesDto | undefined,\n patch: UpdateTicketCreatePreferencesRequest,\n): TicketCreatePreferencesDto {\n return {\n projectId,\n visibleFieldIds:\n patch.visibleFieldIds ??\n previous?.visibleFieldIds ??\n DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS,\n keepAdding: patch.keepAdding ?? previous?.keepAdding ?? false,\n keepFieldIds:\n patch.keepFieldIds ??\n previous?.keepFieldIds ??\n DEFAULT_KEEP_ON_ADD_FIELDS,\n updatedAt: previous?.updatedAt ?? null,\n };\n}\n\nfunction normalizePreferencesDto(\n data: TicketCreatePreferencesDto,\n): TicketCreatePreferencesDto {\n return {\n projectId: data.projectId,\n visibleFieldIds: normalizeVisibleFieldIds(data.visibleFieldIds ?? []),\n keepAdding: Boolean(data.keepAdding),\n keepFieldIds: normalizeKeepFieldIds(\n data.keepFieldIds ?? DEFAULT_KEEP_ON_ADD_FIELDS,\n ),\n updatedAt: data.updatedAt ?? null,\n };\n}\n\nexport function useCreateTicketFieldVisibility(\n projectId: string | null,\n { enabled = true }: UseCreateTicketFieldVisibilityOptions = {},\n) {\n const queryClient = useQueryClient();\n const queryKey = createTicketFieldVisibilityKeys.detail();\n const migrationAttemptedRef = React.useRef<string | null>(null);\n const saveTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingSaveRef =\n React.useRef<UpdateTicketCreatePreferencesRequest | null>(null);\n\n const query = useQuery({\n queryKey,\n queryFn: async () =>\n normalizePreferencesDto(await fetchTicketCreatePreferences(projectId!)),\n enabled: Boolean(projectId) && enabled,\n staleTime: 1000 * 60 * 5,\n });\n\n React.useEffect(() => {\n return subscribeProjectContextChanged(() => {\n const pid = getProjectId();\n queryClient.invalidateQueries({\n queryKey: createTicketFieldVisibilityKeys.detail(),\n });\n });\n }, [queryClient]);\n\n const saveMutation = useMutation({\n mutationFn: (patch: UpdateTicketCreatePreferencesRequest) =>\n saveTicketCreatePreferences(projectId!, patch),\n onMutate: async (patch) => {\n await queryClient.cancelQueries({ queryKey });\n const previous = queryClient.getQueryData<TicketCreatePreferencesDto>(\n queryKey,\n );\n queryClient.setQueryData<TicketCreatePreferencesDto>(\n queryKey,\n mergePreferences(projectId!, previous, patch),\n );\n return { previous };\n },\n onError: (_error, _variables, context) => {\n queryClient.setQueryData(queryKey, context?.previous ?? null);\n },\n onSuccess: (saved) => {\n queryClient.setQueryData(queryKey, normalizePreferencesDto(saved));\n },\n });\n const mutateSaveRef = React.useRef(saveMutation.mutate);\n mutateSaveRef.current = saveMutation.mutate;\n\n const applyOptimistic = React.useCallback(\n (patch: UpdateTicketCreatePreferencesRequest) => {\n if (!projectId) return;\n queryClient.setQueryData<TicketCreatePreferencesDto>(queryKey, (old) =>\n mergePreferences(projectId, old, patch),\n );\n },\n [projectId, queryClient, queryKey],\n );\n\n const flushPendingSave = React.useCallback(() => {\n if (!projectId || !pendingSaveRef.current) return;\n const patch = pendingSaveRef.current;\n pendingSaveRef.current = null;\n if (isEmptyPatch(patch)) return;\n mutateSaveRef.current(patch);\n }, [projectId]);\n\n const scheduleSave = React.useCallback(\n (patch: UpdateTicketCreatePreferencesRequest) => {\n if (!projectId || isEmptyPatch(patch)) return;\n applyOptimistic(patch);\n pendingSaveRef.current = {\n ...(pendingSaveRef.current ?? {}),\n ...patch,\n };\n if (saveTimerRef.current) clearTimeout(saveTimerRef.current);\n saveTimerRef.current = setTimeout(() => {\n saveTimerRef.current = null;\n flushPendingSave();\n }, SAVE_DEBOUNCE_MS);\n },\n [applyOptimistic, flushPendingSave, projectId],\n );\n\n React.useEffect(() => {\n return () => {\n if (saveTimerRef.current) clearTimeout(saveTimerRef.current);\n };\n }, []);\n\n React.useEffect(() => {\n if (!projectId || !enabled || !query.data) return;\n if (migrationAttemptedRef.current === projectId) return;\n migrationAttemptedRef.current = projectId;\n\n const patch: UpdateTicketCreatePreferencesRequest = {};\n\n if (query.data.updatedAt === null) {\n const legacyVisibility = loadLegacyVisibleFieldIdsFromStorage();\n if (legacyVisibility.length > 0) {\n patch.visibleFieldIds = legacyVisibility;\n }\n }\n\n if (hasLegacyKeepAddingInStorage()) {\n patch.keepAdding = loadLegacyKeepAddingFromStorage();\n }\n\n const legacyKeepFields = loadLegacyKeepFieldsFromStorage();\n if (legacyKeepFields !== null) {\n patch.keepFieldIds = legacyKeepFields;\n }\n\n if (isEmptyPatch(patch)) return;\n\n applyOptimistic(patch);\n void saveTicketCreatePreferences(projectId, patch).then((saved) => {\n queryClient.setQueryData(queryKey, normalizePreferencesDto(saved));\n if (patch.visibleFieldIds !== undefined) {\n clearLegacyVisibleFieldIdsFromStorage();\n }\n if (patch.keepAdding !== undefined) {\n clearLegacyKeepAddingFromStorage();\n }\n if (patch.keepFieldIds !== undefined) {\n clearLegacyKeepFieldsFromStorage();\n }\n });\n }, [\n applyOptimistic,\n enabled,\n projectId,\n query.data,\n queryClient,\n queryKey,\n ]);\n\n const visibleFieldIds = React.useMemo(() => {\n const ids = query.data?.visibleFieldIds;\n if (ids && ids.length > 0) {\n return normalizeVisibleFieldIds(ids);\n }\n return DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS;\n }, [query.data]);\n\n const keepAdding = query.data?.keepAdding ?? false;\n\n const keepFieldIds = React.useMemo(() => {\n const ids = query.data?.keepFieldIds;\n if (ids && ids.length > 0) {\n return normalizeKeepFieldIds(ids);\n }\n return DEFAULT_KEEP_ON_ADD_FIELDS;\n }, [query.data]);\n\n const saveVisibleFieldIds = React.useCallback(\n (ids: Iterable<string>) => {\n scheduleSave({ visibleFieldIds: normalizeVisibleFieldIds(ids) });\n },\n [scheduleSave],\n );\n\n const saveKeepAdding = React.useCallback(\n (value: boolean) => {\n scheduleSave({ keepAdding: value });\n },\n [scheduleSave],\n );\n\n const saveKeepFieldIds = React.useCallback(\n (ids: Iterable<string>) => {\n scheduleSave({ keepFieldIds: normalizeKeepFieldIds(ids) });\n },\n [scheduleSave],\n );\n\n return {\n visibleFieldIds,\n keepAdding,\n keepFieldIds,\n isLoading: query.isLoading,\n isSaving: saveMutation.isPending,\n saveVisibleFieldIds,\n saveKeepAdding,\n saveKeepFieldIds,\n flushPendingSave,\n refetch: query.refetch,\n };\n}\n\nexport type { CreateDialogVisibilityFieldId, KeepOnAddFieldId };\nexport { createTicketFieldVisibilityQueryKey } from \"@/hooks/queries/query-keys\";\n","import {\n CREATE_TICKET_FIELD_IDS,\n type CreateTicketFieldId,\n} from \"@/lib/tickets/createTicketFieldOrder\";\n\nexport const KEEP_ON_ADD_FIELD_IDS = [...CREATE_TICKET_FIELD_IDS] as const;\n\nexport type KeepOnAddFieldId = (typeof KEEP_ON_ADD_FIELD_IDS)[number];\n\n/** @deprecated Legacy localStorage key — used only for one-time migration to backend. */\nexport const KEEP_ON_ADD_STORAGE_KEY = \"ticket-create-keep-adding\";\n/** @deprecated Legacy localStorage key — used only for one-time migration to backend. */\nexport const KEEP_FIELDS_STORAGE_KEY = \"ticket-create-keep-fields\";\n\nexport const DEFAULT_KEEP_ON_ADD_FIELDS: KeepOnAddFieldId[] = [\n \"company\",\n \"type\",\n \"event\",\n \"status\",\n];\n\nexport function normalizeKeepFieldIds(\n ids: Iterable<string>,\n): KeepOnAddFieldId[] {\n const seen = new Set<KeepOnAddFieldId>();\n for (const id of ids) {\n if (\n typeof id === \"string\" &&\n (KEEP_ON_ADD_FIELD_IDS as readonly string[]).includes(id)\n ) {\n seen.add(id as KeepOnAddFieldId);\n }\n }\n return [...seen];\n}\n\nexport function hasLegacyKeepAddingInStorage(): boolean {\n if (typeof window === \"undefined\") return false;\n try {\n return localStorage.getItem(KEEP_ON_ADD_STORAGE_KEY) !== null;\n } catch {\n return false;\n }\n}\n\nexport function loadLegacyKeepAddingFromStorage(): boolean {\n if (typeof window === \"undefined\") return false;\n try {\n return localStorage.getItem(KEEP_ON_ADD_STORAGE_KEY) === \"true\";\n } catch {\n return false;\n }\n}\n\nexport function clearLegacyKeepAddingFromStorage(): void {\n try {\n localStorage.removeItem(KEEP_ON_ADD_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n}\n\n/** Returns `null` when no legacy key is present. */\nexport function loadLegacyKeepFieldsFromStorage(): KeepOnAddFieldId[] | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(KEEP_FIELDS_STORAGE_KEY);\n if (raw === null) return null;\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) return [...DEFAULT_KEEP_ON_ADD_FIELDS];\n return normalizeKeepFieldIds(parsed);\n } catch {\n return [...DEFAULT_KEEP_ON_ADD_FIELDS];\n }\n}\n\nexport function clearLegacyKeepFieldsFromStorage(): void {\n try {\n localStorage.removeItem(KEEP_FIELDS_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n}\n\nexport function isCreateTicketFieldId(\n id: KeepOnAddFieldId,\n): id is CreateTicketFieldId {\n return (CREATE_TICKET_FIELD_IDS as readonly string[]).includes(id);\n}\n","import type {\n TicketCreatePreferencesDto,\n UpdateTicketCreatePreferencesRequest,\n} from \"./dto/ticket-create-preferences.dto\";\nimport { DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS } from \"@/lib/tickets/createTicketFieldVisibility\";\nimport { DEFAULT_KEEP_ON_ADD_FIELDS } from \"@/lib/tickets/createTicketKeepFields\";\n\nconst STORAGE_KEY = \"support-ticket-create-preferences\";\n\nfunction defaultPreferences(): TicketCreatePreferencesDto {\n return {\n projectId: \"support\",\n visibleFieldIds: [...DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS],\n keepAdding: false,\n keepFieldIds: [...DEFAULT_KEEP_ON_ADD_FIELDS],\n updatedAt: null,\n };\n}\n\nfunction readLocal(): TicketCreatePreferencesDto {\n if (typeof window === \"undefined\") {\n return defaultPreferences();\n }\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return defaultPreferences();\n const parsed = JSON.parse(raw) as TicketCreatePreferencesDto;\n const visibleFieldIds = Array.isArray(parsed.visibleFieldIds)\n ? parsed.visibleFieldIds\n : [];\n const keepFieldIds = Array.isArray(parsed.keepFieldIds)\n ? parsed.keepFieldIds\n : [];\n return {\n projectId: \"support\",\n visibleFieldIds:\n visibleFieldIds.length > 0\n ? visibleFieldIds\n : [...DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS],\n keepAdding: Boolean(parsed.keepAdding),\n keepFieldIds:\n keepFieldIds.length > 0\n ? keepFieldIds\n : [...DEFAULT_KEEP_ON_ADD_FIELDS],\n updatedAt: parsed.updatedAt ?? null,\n };\n } catch {\n return defaultPreferences();\n }\n}\n\nfunction writeLocal(data: TicketCreatePreferencesDto): void {\n if (typeof window === \"undefined\") return;\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\n}\n\n/** Local-only create-dialog preferences (not in `/api/support` contract). */\nexport async function fetchTicketCreatePreferences(\n _projectId?: string,\n): Promise<TicketCreatePreferencesDto> {\n return readLocal();\n}\n\nexport async function saveTicketCreatePreferences(\n _projectId: string,\n patch: UpdateTicketCreatePreferencesRequest,\n): Promise<TicketCreatePreferencesDto> {\n const previous = readLocal();\n const nextVisible =\n patch.visibleFieldIds !== undefined\n ? patch.visibleFieldIds\n : previous.visibleFieldIds;\n const nextKeepFields =\n patch.keepFieldIds !== undefined\n ? patch.keepFieldIds\n : previous.keepFieldIds;\n const next: TicketCreatePreferencesDto = {\n projectId: \"support\",\n visibleFieldIds:\n nextVisible.length > 0\n ? nextVisible\n : [...DEFAULT_CREATE_DIALOG_VISIBLE_FIELD_IDS],\n keepAdding: patch.keepAdding ?? previous.keepAdding,\n keepFieldIds:\n nextKeepFields.length > 0\n ? nextKeepFields\n : [...DEFAULT_KEEP_ON_ADD_FIELDS],\n updatedAt: new Date().toISOString(),\n };\n writeLocal(next);\n return next;\n}\n","\"use client\";\n\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\n\nimport {\n createTicketSequence,\n deleteTicketSequence,\n fetchTicketSequences,\n updateTicketSequence,\n} from \"@/api/ticketSequence\";\nimport type {\n CreateTicketSequenceRequest,\n UpdateTicketSequenceRequest,\n} from \"@/api/dto/ticket-sequence.dto\";\nimport { ticketSequenceKeys } from \"@/hooks/queries/query-keys\";\n\nexport function useTicketSequences() {\n return useQuery({\n queryKey: ticketSequenceKeys.list(),\n queryFn: fetchTicketSequences,\n staleTime: 30_000,\n });\n}\n\nexport function useCreateTicketSequence() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (body: CreateTicketSequenceRequest) => createTicketSequence(body),\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: ticketSequenceKeys.all,\n });\n },\n });\n}\n\nexport function useUpdateTicketSequence() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: ({\n sequenceId,\n body,\n }: {\n sequenceId: string;\n body: UpdateTicketSequenceRequest;\n }) => updateTicketSequence(sequenceId, body),\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: ticketSequenceKeys.all,\n });\n },\n });\n}\n\nexport function useDeleteTicketSequence() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (sequenceId: string) => deleteTicketSequence(sequenceId),\n onSuccess: async () => {\n await queryClient.invalidateQueries({\n queryKey: ticketSequenceKeys.all,\n });\n },\n });\n}\n\nexport { ticketSequencesQueryKey } from \"@/hooks/queries/query-keys\";\n","import apiClient, { supportPath } from \"./client\";\nimport type {\n CreateTicketSequenceRequest,\n TicketSequenceDto,\n UpdateTicketSequenceRequest,\n} from \"./dto/ticket-sequence.dto\";\n\nfunction sequencesPath(suffix = \"\"): string {\n return supportPath(`/sequences${suffix}`);\n}\n\nexport async function fetchTicketSequences(): Promise<TicketSequenceDto[]> {\n const { data } = await apiClient.get<TicketSequenceDto[]>(sequencesPath());\n return data;\n}\n\nexport async function fetchTicketSequence(\n sequenceId: string,\n): Promise<TicketSequenceDto> {\n const { data } = await apiClient.get<TicketSequenceDto>(\n sequencesPath(`/${sequenceId}`),\n );\n return data;\n}\n\nexport async function createTicketSequence(\n body: CreateTicketSequenceRequest,\n): Promise<TicketSequenceDto> {\n const { data } = await apiClient.post<TicketSequenceDto>(\n sequencesPath(),\n body,\n );\n return data;\n}\n\nexport async function updateTicketSequence(\n sequenceId: string,\n body: UpdateTicketSequenceRequest,\n): Promise<TicketSequenceDto> {\n const { data } = await apiClient.patch<TicketSequenceDto>(\n sequencesPath(`/${sequenceId}`),\n body,\n );\n return data;\n}\n\nexport async function deleteTicketSequence(sequenceId: string): Promise<void> {\n await apiClient.delete(sequencesPath(`/${sequenceId}`));\n}\n","export const TICKET_TABLE_COLUMN_IDS = [\n \"id\",\n \"priority\",\n \"shortText\",\n \"longDescriptionHtml\",\n \"lastComment\",\n \"typeKey\",\n \"event\",\n \"statusKey\",\n \"updatedAt\",\n \"link\",\n \"createdAt\",\n \"createdByName\",\n \"deadline\",\n \"sequenceName\",\n \"company\",\n] as const;\n\nexport type TicketTableColumnId = (typeof TICKET_TABLE_COLUMN_IDS)[number];\n\nexport type TicketTableColumnVisibility = Record<TicketTableColumnId, boolean>;\nexport type TicketTableSortingState = Array<{\n id: string;\n desc: boolean;\n}>;\nexport type TicketTableColumnSizing = Record<string, number>;\n\nexport const TICKET_TABLE_COLUMN_VISIBILITY_STORAGE_KEY =\n \"ticket-table-column-visibility\";\nexport const TICKET_TABLE_COLUMN_ORDER_STORAGE_KEY =\n \"ticket-table-column-order\";\nexport const TICKET_TABLE_SORTING_STORAGE_KEY = \"ticket-table-sorting\";\nexport const TICKET_TABLE_COLUMN_SIZING_STORAGE_KEY =\n \"ticket-table-column-sizing\";\n\nexport const DEFAULT_TICKET_TABLE_COLUMN_VISIBILITY: TicketTableColumnVisibility =\n {\n id: true,\n priority: true,\n shortText: true,\n longDescriptionHtml: false,\n lastComment: true,\n typeKey: true,\n event: true,\n statusKey: true,\n updatedAt: false,\n link: false,\n createdAt: true,\n createdByName: true,\n deadline: true,\n sequenceName: true,\n company: true,\n };\n\nexport function loadTicketTableColumnVisibility(): TicketTableColumnVisibility {\n if (typeof window === \"undefined\") {\n return { ...DEFAULT_TICKET_TABLE_COLUMN_VISIBILITY };\n }\n try {\n const raw = localStorage.getItem(TICKET_TABLE_COLUMN_VISIBILITY_STORAGE_KEY);\n if (!raw) return { ...DEFAULT_TICKET_TABLE_COLUMN_VISIBILITY };\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== \"object\") {\n return { ...DEFAULT_TICKET_TABLE_COLUMN_VISIBILITY };\n }\n const next = { ...DEFAULT_TICKET_TABLE_COLUMN_VISIBILITY };\n for (const id of TICKET_TABLE_COLUMN_IDS) {\n const value = (parsed as Record<string, unknown>)[id];\n if (typeof value === \"boolean\") next[id] = value;\n }\n return next;\n } catch {\n return { ...DEFAULT_TICKET_TABLE_COLUMN_VISIBILITY };\n }\n}\n\nexport function saveTicketTableColumnVisibility(\n visibility: TicketTableColumnVisibility,\n): void {\n try {\n localStorage.setItem(\n TICKET_TABLE_COLUMN_VISIBILITY_STORAGE_KEY,\n JSON.stringify(visibility),\n );\n } catch {\n /* ignore */\n }\n}\n\nexport function loadTicketTableColumnOrder(): TicketTableColumnId[] {\n if (typeof window === \"undefined\") {\n return [...TICKET_TABLE_COLUMN_IDS];\n }\n try {\n const raw = localStorage.getItem(TICKET_TABLE_COLUMN_ORDER_STORAGE_KEY);\n if (!raw) return [...TICKET_TABLE_COLUMN_IDS];\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) return [...TICKET_TABLE_COLUMN_IDS];\n\n const valid = parsed.filter((id): id is TicketTableColumnId =>\n (TICKET_TABLE_COLUMN_IDS as readonly string[]).includes(String(id)),\n );\n return [\n ...valid,\n ...TICKET_TABLE_COLUMN_IDS.filter((id) => !valid.includes(id)),\n ];\n } catch {\n return [...TICKET_TABLE_COLUMN_IDS];\n }\n}\n\nexport function saveTicketTableColumnOrder(order: TicketTableColumnId[]): void {\n try {\n localStorage.setItem(\n TICKET_TABLE_COLUMN_ORDER_STORAGE_KEY,\n JSON.stringify(order),\n );\n } catch {\n /* ignore */\n }\n}\n\nexport function loadTicketTableSorting(): TicketTableSortingState | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(TICKET_TABLE_SORTING_STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as unknown;\n if (!Array.isArray(parsed)) return null;\n const valid = parsed.filter(\n (item): item is { id: string; desc: boolean } =>\n Boolean(item) &&\n typeof item === \"object\" &&\n typeof (item as Record<string, unknown>).id === \"string\" &&\n typeof (item as Record<string, unknown>).desc === \"boolean\",\n );\n return valid;\n } catch {\n return null;\n }\n}\n\nexport function saveTicketTableSorting(sorting: TicketTableSortingState): void {\n try {\n localStorage.setItem(\n TICKET_TABLE_SORTING_STORAGE_KEY,\n JSON.stringify(sorting),\n );\n } catch {\n /* ignore */\n }\n}\n\n/** Drop sort entries for columns that are not currently visible. */\nexport function filterSortingByVisibility(\n sorting: TicketTableSortingState,\n visibility: Partial<Record<string, boolean>>,\n): TicketTableSortingState {\n return sorting.filter((entry) => visibility[entry.id] !== false);\n}\n\nexport function loadTicketTableColumnSizing(): TicketTableColumnSizing {\n if (typeof window === \"undefined\") return {};\n try {\n const raw = localStorage.getItem(TICKET_TABLE_COLUMN_SIZING_STORAGE_KEY);\n if (!raw) return {};\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== \"object\") return {};\n const sizing: TicketTableColumnSizing = {};\n for (const [columnId, size] of Object.entries(\n parsed as Record<string, unknown>,\n )) {\n if (typeof size === \"number\" && Number.isFinite(size) && size > 0) {\n sizing[columnId] = size;\n }\n }\n return sizing;\n } catch {\n return {};\n }\n}\n\nexport function saveTicketTableColumnSizing(\n sizing: TicketTableColumnSizing,\n): void {\n try {\n localStorage.setItem(\n TICKET_TABLE_COLUMN_SIZING_STORAGE_KEY,\n JSON.stringify(sizing),\n );\n } catch {\n /* ignore */\n }\n}\n\nexport function countVisibleTicketTableColumns(\n visibility: TicketTableColumnVisibility,\n): number {\n return TICKET_TABLE_COLUMN_IDS.filter((id) => visibility[id]).length;\n}\n\nexport function stripHtmlToText(html: string): string {\n return html\n .replace(/<[^>]*>/g, \" \")\n .replace(/&nbsp;/gi, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n","import { stripHtmlToText } from \"@/lib/tickets/ticketTableColumns\";\r\n\r\nexport type TicketCreateMeaningfulFields = {\r\n shortDescription?: string;\r\n longDescriptionHtml?: string;\r\n typeKey?: string;\r\n eventId?: string;\r\n link?: string;\r\n sequenceId?: string;\r\n responsibleUserId?: string;\r\n responsibleIds?: string[];\r\n deadline?: string;\r\n};\r\n\r\nexport type HasMeaningfulCreateFieldOptions = {\r\n /**\r\n * When false, assignment fields do not satisfy the minimum (reporters on create).\r\n * `statusKey` and `priority` never count — they are not part of this type.\r\n */\r\n countAssignment?: boolean;\r\n};\r\n\r\n/** Fingerprint of create-form values used to detect post keep-adding unchanged state. */\r\nexport type CreateTicketFormSnapshot = {\r\n shortDescription: string;\r\n longDescriptionHtml: string;\r\n typeKey: string;\r\n eventId: string;\r\n priorityKey: string;\r\n deadline: string;\r\n assignmentType: string;\r\n sequenceId: string;\r\n responsibleUserId: string;\r\n responsibleIdsKey: string;\r\n attachmentKey: string;\r\n};\r\n\r\nexport type BuildCreateTicketFormSnapshotInput = {\r\n shortDescription: string;\r\n longDescriptionHtml: string;\r\n typeKey: string;\r\n eventId: string;\r\n priorityKey: string;\r\n deadline: string;\r\n assignmentType: string;\r\n sequenceId: string;\r\n responsibleUserId: string;\r\n responsibleIds: readonly string[];\r\n localAttachmentIds: readonly string[];\r\n existingAttachmentIds: readonly string[];\r\n};\r\n\r\nfunction idsFingerprint(ids: readonly string[]): string {\r\n return [...ids].sort().join(\",\");\r\n}\r\n\r\nexport function buildCreateTicketFormSnapshot(\r\n input: BuildCreateTicketFormSnapshotInput,\r\n): CreateTicketFormSnapshot {\r\n return {\r\n shortDescription: input.shortDescription.trim(),\r\n longDescriptionHtml: input.longDescriptionHtml,\r\n typeKey: input.typeKey,\r\n eventId: input.eventId,\r\n priorityKey: input.priorityKey,\r\n deadline: input.deadline,\r\n assignmentType: input.assignmentType,\r\n sequenceId: input.sequenceId,\r\n responsibleUserId: input.responsibleUserId,\r\n responsibleIdsKey: idsFingerprint(input.responsibleIds),\r\n attachmentKey: [\r\n idsFingerprint(input.localAttachmentIds),\r\n idsFingerprint(input.existingAttachmentIds),\r\n ].join(\";\"),\r\n };\r\n}\r\n\r\nexport function createTicketFormSnapshotsEqual(\r\n a: CreateTicketFormSnapshot,\r\n b: CreateTicketFormSnapshot,\r\n): boolean {\r\n return (\r\n a.shortDescription === b.shortDescription &&\r\n a.longDescriptionHtml === b.longDescriptionHtml &&\r\n a.typeKey === b.typeKey &&\r\n a.eventId === b.eventId &&\r\n a.priorityKey === b.priorityKey &&\r\n a.deadline === b.deadline &&\r\n a.assignmentType === b.assignmentType &&\r\n a.sequenceId === b.sequenceId &&\r\n a.responsibleUserId === b.responsibleUserId &&\r\n a.responsibleIdsKey === b.responsibleIdsKey &&\r\n a.attachmentKey === b.attachmentKey\r\n );\r\n}\r\n\r\n/**\r\n * True when the payload has at least one API \"ticket detail\".\r\n * Status and priority alone do not count; assignment counts only when allowed (staff).\r\n */\r\nexport function hasMeaningfulCreateField(\r\n form: TicketCreateMeaningfulFields,\r\n imageCount = 0,\r\n options: HasMeaningfulCreateFieldOptions = {},\r\n): boolean {\r\n const countAssignment = options.countAssignment !== false;\r\n\r\n if (form.shortDescription?.trim()) return true;\r\n if (stripHtmlToText(form.longDescriptionHtml ?? \"\").trim()) return true;\r\n if (form.typeKey?.trim()) return true;\r\n if (form.eventId?.trim()) return true;\r\n if (form.link?.trim()) return true;\r\n if (form.deadline?.trim()) return true;\r\n if (imageCount > 0) return true;\r\n\r\n if (countAssignment) {\r\n if (form.sequenceId?.trim()) return true;\r\n if (form.responsibleUserId?.trim()) return true;\r\n if ((form.responsibleIds?.length ?? 0) >= 2) return true;\r\n }\r\n\r\n return false;\r\n}\r\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n setSupportApiRuntime,\n type SupportApiRuntime,\n} from \"./support-api-runtime\";\n\nexport function SupportApiRuntimeProvider({\n apiBaseUrl,\n getAccessToken,\n children,\n}: SupportApiRuntime & { children: React.ReactNode }) {\n React.useEffect(() => {\n setSupportApiRuntime({ apiBaseUrl, getAccessToken });\n return () => setSupportApiRuntime(null);\n }, [apiBaseUrl, getAccessToken]);\n\n return <>{children}</>;\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport { CreateTicketDialog } from \"@/components/tickets/CreateTicketDialog\";\nimport { SupportApiRuntimeProvider } from \"./SupportApiRuntimeProvider\";\n\nexport type UseSupportNavbarCreateTicketOptions = {\n apiBaseUrl: string;\n getAccessToken: () => string | null;\n};\n\nexport function useSupportNavbarCreateTicket({\n apiBaseUrl,\n getAccessToken,\n}: UseSupportNavbarCreateTicketOptions) {\n const [open, setOpen] = React.useState(false);\n const onSupportClick = React.useCallback(() => setOpen(true), []);\n\n const dialog = open ? (\n <SupportApiRuntimeProvider\n apiBaseUrl={apiBaseUrl}\n getAccessToken={getAccessToken}\n >\n <CreateTicketDialog open onOpenChange={setOpen} />\n </SupportApiRuntimeProvider>\n ) : null;\n\n return { onSupportClick, dialog, open, setOpen };\n}\n"],"mappings":"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","names":["React","React","useTranslation","jsx","jsxs","TicketRichTextEditor","React","Loader2","X","useTranslation","useQueryClient","React","format","jsx","React","jsx","val","runtime","settings","jsx","TicketDeadlinePicker","format","React","Palette","AxiosError","useTranslation","React","jsx","jsxs","jsx","jsxs","jsx","jsxs","React","jsx","React","cva","jsx","React","Loader2","React","jsx","jsxs","Loader2","useMutation","useQuery","useQueryClient","data","useQueryClient","useQuery","useMutation","React","useMutation","useQueryClient","isValid","parse","useQueryClient","useMutation","useMutation","useQuery","useQueryClient","userDataQueryKey","useQueryClient","useQuery","useMutation","React","React","useTranslation","jsx","useTranslation","jsx","Fragment","jsx","jsxs","TicketEventSelect","useTranslation","AxiosError","Palette","React","CatalogSelect","useTranslation","jsx","jsxs","React","useQuery","useQueryClient","useTranslation","useTranslation","useQueryClient","useQuery","jsx","useTranslation","CatalogSelect","React","useTranslation","useTranslation","React","useTranslation","Loader2","useTranslation","Fragment","jsx","jsxs","useTranslation","Loader2","React","Loader2","X","useTranslation","API_BASE","React","DialogPrimitive","ChevronLeft","ChevronRight","Pencil","Plus","X","useTranslation","React","useTranslation","jsx","jsxs","React","useTranslation","jsx","useTranslation","useEffect","useState","useState","useEffect","useCallback","useEffect","useState","Fragment","jsx","jsxs","useTranslation","Plus","Pencil","X","ChevronLeft","ChevronRight","Fragment","jsx","jsxs","useTranslation","Loader2","X","React","Loader2","Play","X","useTranslation","useQuery","useQuery","Fragment","jsx","jsxs","useTranslation","Loader2","Play","X","jsx","Fragment","jsx","jsxs","PoolTiles","jsxs","Fragment","jsx","useTranslation","React","Minus","jsx","React","jsx","SelectContent","React","jsx","CreateTicketBufferedInput","React","Check","useTranslation","jsx","jsxs","React","Palette","AxiosError","CatalogSelect","useTranslation","useMutation","useQuery","useQueryClient","React","useQueryClient","useQuery","useMutation","jsx","jsxs","useTranslation","TicketResponsibleField","AxiosError","Palette","CatalogSelect","useQuery","useQuery","useMutation","useQuery","useQueryClient","React","useQueryClient","useQuery","useMutation","useMutation","useQuery","useQueryClient","useQuery","Fragment","jsx","jsxs","TicketRichTextEditor","FloatingLabel","useTranslation","useQueryClient","X","Loader2","React","Fragment","jsx","React","jsx"]}