184 lines
5.7 KiB
JavaScript
184 lines
5.7 KiB
JavaScript
/**
|
|
* useFormValidation — composable para validação de formulários com PrimeVue
|
|
*
|
|
* Retorna funções de validação prontas para usar em :invalid e mensagens de erro.
|
|
*
|
|
* Uso:
|
|
* const { validateCPF, validatePhone, validateEmail, validateCEP } = useFormValidation()
|
|
*
|
|
* // No template:
|
|
* <InputText v-model="cpf" :invalid="errors.cpf" @blur="errors.cpf = !validateCPF(cpf).valid" />
|
|
* <small v-if="errors.cpf" class="p-error">{{ validateCPF(cpf).message }}</small>
|
|
*/
|
|
|
|
import {
|
|
isValidCPF,
|
|
isValidCNPJ,
|
|
isValidPhone,
|
|
isValidEmail,
|
|
isValidCEP,
|
|
fmtCPF,
|
|
fmtCNPJ,
|
|
fmtPhone,
|
|
fmtCEP,
|
|
sanitizeDigits,
|
|
toISODate,
|
|
digitsOnly,
|
|
} from '@/utils/validators'
|
|
|
|
export function useFormValidation() {
|
|
|
|
/** CPF — campo: `cpf` ou `cpf_responsavel` */
|
|
function validateCPF(v, { required = false } = {}) {
|
|
if (!v || digitsOnly(v).length === 0) {
|
|
return required
|
|
? { valid: false, message: 'CPF é obrigatório.' }
|
|
: { valid: true, message: '' }
|
|
}
|
|
if (!isValidCPF(v)) return { valid: false, message: 'CPF inválido.' }
|
|
return { valid: true, message: '' }
|
|
}
|
|
|
|
/** CNPJ */
|
|
function validateCNPJ(v, { required = false } = {}) {
|
|
if (!v || digitsOnly(v).length === 0) {
|
|
return required
|
|
? { valid: false, message: 'CNPJ é obrigatório.' }
|
|
: { valid: true, message: '' }
|
|
}
|
|
if (!isValidCNPJ(v)) return { valid: false, message: 'CNPJ inválido.' }
|
|
return { valid: true, message: '' }
|
|
}
|
|
|
|
/** Telefone — campos: `telefone`, `telefone_alternativo`, `telefone_parente`, `telefone_responsavel` */
|
|
function validatePhone(v, { required = false } = {}) {
|
|
if (!v || digitsOnly(v).length === 0) {
|
|
return required
|
|
? { valid: false, message: 'Telefone é obrigatório.' }
|
|
: { valid: true, message: '' }
|
|
}
|
|
if (!isValidPhone(v)) return { valid: false, message: 'Telefone inválido. Use (XX) XXXXX-XXXX.' }
|
|
return { valid: true, message: '' }
|
|
}
|
|
|
|
/** Email — campos: `email_principal`, `email_alternativo` */
|
|
function validateEmail(v, { required = false } = {}) {
|
|
if (!v || String(v).trim().length === 0) {
|
|
return required
|
|
? { valid: false, message: 'E-mail é obrigatório.' }
|
|
: { valid: true, message: '' }
|
|
}
|
|
if (!isValidEmail(v)) return { valid: false, message: 'E-mail inválido.' }
|
|
return { valid: true, message: '' }
|
|
}
|
|
|
|
/** CEP — campo: `cep` */
|
|
function validateCEP(v, { required = false } = {}) {
|
|
if (!v || digitsOnly(v).length === 0) {
|
|
return required
|
|
? { valid: false, message: 'CEP é obrigatório.' }
|
|
: { valid: true, message: '' }
|
|
}
|
|
if (!isValidCEP(v)) return { valid: false, message: 'CEP inválido. Use 00000-000.' }
|
|
return { valid: true, message: '' }
|
|
}
|
|
|
|
/** Nome completo — campo: `nome_completo` */
|
|
function validateNomeCompleto(v, { required = true, minWords = 2 } = {}) {
|
|
const s = String(v ?? '').trim()
|
|
if (!s) {
|
|
return required
|
|
? { valid: false, message: 'Nome completo é obrigatório.' }
|
|
: { valid: true, message: '' }
|
|
}
|
|
const words = s.split(/\s+/).filter(Boolean)
|
|
if (words.length < minWords) return { valid: false, message: 'Informe o nome completo (mínimo 2 palavras).' }
|
|
return { valid: true, message: '' }
|
|
}
|
|
|
|
/**
|
|
* Valida um objeto de formulário de paciente de uma só vez.
|
|
* Retorna { valid: boolean, errors: { campo: mensagem } }
|
|
*
|
|
* Exemplo:
|
|
* const { valid, errors } = validatePatientForm(form, { cpfRequired: false })
|
|
*/
|
|
function validatePatientForm(form, { cpfRequired = false, emailRequired = false, phoneRequired = false } = {}) {
|
|
const errors = {}
|
|
|
|
const nome = validateNomeCompleto(form.nome_completo)
|
|
if (!nome.valid) errors.nome_completo = nome.message
|
|
|
|
if (form.cpf || cpfRequired) {
|
|
const cpf = validateCPF(form.cpf, { required: cpfRequired })
|
|
if (!cpf.valid) errors.cpf = cpf.message
|
|
}
|
|
|
|
if (form.cpf_responsavel) {
|
|
const cpfResp = validateCPF(form.cpf_responsavel)
|
|
if (!cpfResp.valid) errors.cpf_responsavel = cpfResp.message
|
|
}
|
|
|
|
if (form.telefone || phoneRequired) {
|
|
const tel = validatePhone(form.telefone, { required: phoneRequired })
|
|
if (!tel.valid) errors.telefone = tel.message
|
|
}
|
|
|
|
if (form.telefone_alternativo) {
|
|
const telAlt = validatePhone(form.telefone_alternativo)
|
|
if (!telAlt.valid) errors.telefone_alternativo = telAlt.message
|
|
}
|
|
|
|
if (form.telefone_parente) {
|
|
const telPar = validatePhone(form.telefone_parente)
|
|
if (!telPar.valid) errors.telefone_parente = telPar.message
|
|
}
|
|
|
|
if (form.telefone_responsavel) {
|
|
const telResp = validatePhone(form.telefone_responsavel)
|
|
if (!telResp.valid) errors.telefone_responsavel = telResp.message
|
|
}
|
|
|
|
if (form.email_principal || emailRequired) {
|
|
const email = validateEmail(form.email_principal, { required: emailRequired })
|
|
if (!email.valid) errors.email_principal = email.message
|
|
}
|
|
|
|
if (form.email_alternativo) {
|
|
const emailAlt = validateEmail(form.email_alternativo)
|
|
if (!emailAlt.valid) errors.email_alternativo = emailAlt.message
|
|
}
|
|
|
|
if (form.cep) {
|
|
const cep = validateCEP(form.cep)
|
|
if (!cep.valid) errors.cep = cep.message
|
|
}
|
|
|
|
return { valid: Object.keys(errors).length === 0, errors }
|
|
}
|
|
|
|
return {
|
|
// Validadores individuais
|
|
validateCPF,
|
|
validateCNPJ,
|
|
validatePhone,
|
|
validateEmail,
|
|
validateCEP,
|
|
validateNomeCompleto,
|
|
|
|
// Validação completa do formulário de paciente
|
|
validatePatientForm,
|
|
|
|
// Re-exporta formatadores para usar junto
|
|
fmtCPF,
|
|
fmtCNPJ,
|
|
fmtPhone,
|
|
fmtCEP,
|
|
|
|
// Re-exporta utilitários
|
|
sanitizeDigits,
|
|
toISODate,
|
|
digitsOnly,
|
|
}
|
|
}
|