>([])
const [isSubmitting, setIsSubmitting] = useState(false)
+ const [hasSubcategoryOptions, setHasSubcategoryOptions] = useState(false)
const isFormValid = useMemo(() => {
- return Boolean(subject.trim() && description.trim() && categoryId && subcategoryId)
- }, [subject, description, categoryId, subcategoryId])
+ return Boolean(
+ subject.trim() &&
+ description.trim() &&
+ categoryId &&
+ (hasSubcategoryOptions ? subcategoryId : true)
+ )
+ }, [subject, description, categoryId, subcategoryId, hasSubcategoryOptions])
+
+ const handleSecondaryOptionsChange = useCallback((hasOptions: boolean) => {
+ setHasSubcategoryOptions((prev) => (prev === hasOptions ? prev : hasOptions))
+ }, [])
async function handleSubmit(event: React.FormEvent) {
event.preventDefault()
@@ -76,7 +86,7 @@ export function PortalTicketForm() {
queueId: undefined,
requesterId: viewerId,
categoryId: categoryId as Id<"ticketCategories">,
- subcategoryId: subcategoryId as Id<"ticketSubcategories">,
+ subcategoryId: subcategoryId ? (subcategoryId as Id<"ticketSubcategories">) : undefined,
})
if (plainDescription.length > 0) {
@@ -159,9 +169,10 @@ export function PortalTicketForm() {
subcategoryId={subcategoryId}
onCategoryChange={setCategoryId}
onSubcategoryChange={setSubcategoryId}
+ onSecondaryOptionsChange={handleSecondaryOptionsChange}
layout="stacked"
categoryLabel="Categoria *"
- subcategoryLabel="Subcategoria *"
+ subcategoryLabel={hasSubcategoryOptions ? "Subcategoria *" : "Subcategoria (opcional)"}
secondaryEmptyLabel="Selecione uma categoria"
/>
diff --git a/src/components/tickets/category-select.tsx b/src/components/tickets/category-select.tsx
index 679e860..7701f0f 100644
--- a/src/components/tickets/category-select.tsx
+++ b/src/components/tickets/category-select.tsx
@@ -18,7 +18,8 @@ interface CategorySelectProps {
categoryId: string | null
subcategoryId: string | null
onCategoryChange: (categoryId: string) => void
- onSubcategoryChange: (subcategoryId: string) => void
+ onSubcategoryChange: (subcategoryId: string | null) => void
+ onSecondaryOptionsChange?: (hasSecondary: boolean) => void
autoSelectFirst?: boolean
disabled?: boolean
categoryLabel?: string
@@ -39,6 +40,7 @@ export function CategorySelectFields({
subcategoryId,
onCategoryChange,
onSubcategoryChange,
+ onSecondaryOptionsChange,
autoSelectFirst = true,
disabled = false,
categoryLabel = "Primária",
@@ -72,10 +74,22 @@ export function CategorySelectFields({
const first = secondaryOptions[0]
if (first) {
onSubcategoryChange(first.id)
+ } else {
+ onSubcategoryChange(null)
}
}
}, [categoryId, secondaryOptions, subcategoryId, onSubcategoryChange])
+ useEffect(() => {
+ onSecondaryOptionsChange?.(secondaryOptions.length > 0)
+ }, [secondaryOptions, onSecondaryOptionsChange])
+
+ useEffect(() => {
+ if (secondaryOptions.length === 0 && subcategoryId) {
+ onSubcategoryChange(null)
+ }
+ }, [secondaryOptions, subcategoryId, onSubcategoryChange])
+
const containerClass = layout === "stacked" ? "flex flex-col gap-3" : "grid gap-3 sm:grid-cols-2"
return (
diff --git a/src/components/tickets/new-ticket-dialog.tsx b/src/components/tickets/new-ticket-dialog.tsx
index 2831853..45dd97e 100644
--- a/src/components/tickets/new-ticket-dialog.tsx
+++ b/src/components/tickets/new-ticket-dialog.tsx
@@ -112,7 +112,7 @@ export function NewTicketDialog() {
}
}
- const handleSubcategoryChange = (value: string) => {
+ const handleSubcategoryChange = (value: string | null) => {
const previous = form.getValues("subcategoryId") ?? ""
const next = value ?? ""
form.setValue("subcategoryId", next, {