sistema-de-chamados/src/lib/ticket-form-helpers.ts
codex-bot a8333c010f fix(reports): remove truncation cap in range collectors to avoid dropped records
feat(calendar): migrate to react-day-picker v9 and polish UI
- Update classNames and CSS import (style.css)
- Custom Dropdown via shadcn Select
- Nav arrows aligned with caption (around)
- Today highlight with cyan tone, weekdays in sentence case
- Wider layout to avoid overflow; remove inner wrapper

chore(tickets): make 'Patrimônio do computador (se houver)' optional
- Backend hotfix to enforce optional + label on existing tenants
- Hide required asterisk for this field in portal/new-ticket

refactor(new-ticket): remove channel dropdown from admin/agent flow
- Keep default channel as MANUAL

feat(ux): simplify requester section and enlarge combobox trigger
- Remove RequesterPreview redundancy; show company badge in trigger
2025-11-04 11:51:08 -03:00

70 lines
2.1 KiB
TypeScript

import type { Id } from "@/convex/_generated/dataModel"
import type { TicketFormFieldDefinition } from "./ticket-form-types"
type CustomFieldPayload = { fieldId: Id<"ticketFields">; value: unknown }
type NormalizeResult =
| { ok: true; payload: CustomFieldPayload[] }
| { ok: false; message: string }
function isEmptyValue(value: unknown): boolean {
if (value === undefined || value === null) return true
if (typeof value === "string" && value.trim().length === 0) return true
return false
}
export function normalizeCustomFieldInputs(
fields: TicketFormFieldDefinition[],
values: Record<string, unknown>
): NormalizeResult {
const payload: CustomFieldPayload[] = []
for (const field of fields) {
const raw = values[field.id]
if (field.type === "boolean") {
const boolValue = Boolean(raw)
payload.push({ fieldId: field.id as Id<"ticketFields">, value: boolValue })
continue
}
if (isEmptyValue(raw)) {
if (field.required) {
return { ok: false, message: `Preencha o campo "${field.label}".` }
}
continue
}
if (field.type === "number") {
const normalized = typeof raw === "number" ? raw : Number(String(raw).replace(",", "."))
if (!Number.isFinite(normalized)) {
return { ok: false, message: `Informe um valor numérico válido para "${field.label}".` }
}
payload.push({ fieldId: field.id as Id<"ticketFields">, value: normalized })
continue
}
if (field.type === "date") {
payload.push({ fieldId: field.id as Id<"ticketFields">, value: String(raw) })
continue
}
const value = typeof raw === "string" ? raw.trim() : raw
payload.push({ fieldId: field.id as Id<"ticketFields">, value })
}
return { ok: true, payload }
}
export function hasMissingRequiredCustomFields(
fields: TicketFormFieldDefinition[],
values: Record<string, unknown>
): boolean {
return fields.some((field) => {
if (!field.required || field.type === "boolean") {
return false
}
const value = values[field.id]
return isEmptyValue(value)
})
}