|
|
@@ -1,8 +1,17 @@
|
|
|
+import { format, isValid, parse } from "date-fns";
|
|
|
import { useI18n } from "vue-i18n";
|
|
|
|
|
|
export const useInputRules = () => {
|
|
|
const { t } = useI18n();
|
|
|
|
|
|
+ const hasValue = (value) => {
|
|
|
+ if (value === null || value === undefined) return false;
|
|
|
+ if (typeof value === "string") return value.trim().length > 0;
|
|
|
+ if (Array.isArray(value)) return value.length > 0;
|
|
|
+
|
|
|
+ return true;
|
|
|
+ };
|
|
|
+
|
|
|
const cepPattern = /^[0-9]{5}-[0-9]{3}$/;
|
|
|
|
|
|
const emailPattern =
|
|
|
@@ -11,14 +20,54 @@ export const useInputRules = () => {
|
|
|
const passwordPattern = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/;
|
|
|
|
|
|
const inputRules = {
|
|
|
+ afterTime: (getStartTime) => (value) => {
|
|
|
+ const startTime =
|
|
|
+ typeof getStartTime === "function" ? getStartTime() : getStartTime;
|
|
|
+
|
|
|
+ return (
|
|
|
+ !hasValue(startTime) ||
|
|
|
+ !hasValue(value) ||
|
|
|
+ value > startTime ||
|
|
|
+ t("validation.rules.after_time")
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
cep: (value) => {
|
|
|
if (!value) return true;
|
|
|
+
|
|
|
return cepPattern.test(value) || t("validation.rules.cep");
|
|
|
},
|
|
|
|
|
|
cnpj: (value) => !value || isValidCNPJ(value) || t("validation.rules.cnpj"),
|
|
|
+
|
|
|
cpf: (value) => !value || isValidCPF(value) || t("validation.rules.cpf"),
|
|
|
|
|
|
+ date: (value) => {
|
|
|
+ if (!hasValue(value)) return true;
|
|
|
+
|
|
|
+ const formats = ["dd/MM/yyyy", "yyyy-MM-dd"];
|
|
|
+
|
|
|
+ const valid = formats.some((dateFormat) => {
|
|
|
+ const parsedDate = parse(value, dateFormat, new Date());
|
|
|
+
|
|
|
+ return (
|
|
|
+ isValid(parsedDate) &&
|
|
|
+ format(parsedDate, dateFormat) === value
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ return valid || t("validation.rules.date");
|
|
|
+ },
|
|
|
+
|
|
|
+ durationHours: (value) => {
|
|
|
+ const minutes = Number(value) * 60;
|
|
|
+
|
|
|
+ return (
|
|
|
+ (Number.isInteger(minutes) && minutes >= 1 && minutes <= 1440) ||
|
|
|
+ t("validation.rules.duration_hours")
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
email: (value) =>
|
|
|
!value || emailPattern.test(value) || t("validation.rules.email"),
|
|
|
|
|
|
@@ -33,20 +82,51 @@ export const useInputRules = () => {
|
|
|
);
|
|
|
},
|
|
|
|
|
|
- min: (min) => (value) =>
|
|
|
- value.length >= min ||
|
|
|
- `${t("validation.rules.min")} ${min} ${t("validation.rules.characters")}`,
|
|
|
+ forValue: (rules, getValue) =>
|
|
|
+ rules.map((rule) => {
|
|
|
+ const wrapped = (...args) => rule(getValue(), ...args);
|
|
|
+
|
|
|
+ if (rule?.$id) wrapped.$id = rule.$id;
|
|
|
+
|
|
|
+ return wrapped;
|
|
|
+ }),
|
|
|
+
|
|
|
+ integer: (value) =>
|
|
|
+ !hasValue(value) ||
|
|
|
+ Number.isInteger(Number(value)) ||
|
|
|
+ t("validation.rules.integer"),
|
|
|
+
|
|
|
+ integerRange:
|
|
|
+ (min, max = null) =>
|
|
|
+ (value) => {
|
|
|
+ if (!hasValue(value)) return true;
|
|
|
+
|
|
|
+ const number = Number(value);
|
|
|
+ const withinRange = number >= min && (max == null || number <= max);
|
|
|
+
|
|
|
+ if (Number.isInteger(number) && withinRange) return true;
|
|
|
+
|
|
|
+ return max == null
|
|
|
+ ? t("validation.rules.integer_min", { min })
|
|
|
+ : t("validation.rules.integer_range", { min, max });
|
|
|
+ },
|
|
|
|
|
|
max: (max) => (value) =>
|
|
|
- value.length <= max ||
|
|
|
+ !hasValue(value) ||
|
|
|
+ String(value).length <= max ||
|
|
|
`${t("validation.rules.max")} ${max} ${t("validation.rules.characters")}`,
|
|
|
|
|
|
- minValue: (min) => (value) =>
|
|
|
- value >= min || `${t("validation.rules.min")} ${min}`,
|
|
|
-
|
|
|
maxValue: (max) => (value) =>
|
|
|
value <= max || `${t("validation.rules.max")} ${max}`,
|
|
|
|
|
|
+ min: (min) => (value) =>
|
|
|
+ !hasValue(value) ||
|
|
|
+ String(value).length >= min ||
|
|
|
+ `${t("validation.rules.min")} ${min} ${t("validation.rules.characters")}`,
|
|
|
+
|
|
|
+ minValue: (min) => (value) =>
|
|
|
+ value >= min || `${t("validation.rules.min")} ${min}`,
|
|
|
+
|
|
|
notSameDocument: (allDocuments) => (value) => {
|
|
|
if (!value) return true;
|
|
|
|
|
|
@@ -65,16 +145,44 @@ export const useInputRules = () => {
|
|
|
return true;
|
|
|
},
|
|
|
|
|
|
+ oneOf: (allowedValues) => (value) =>
|
|
|
+ !hasValue(value) ||
|
|
|
+ allowedValues.includes(value) ||
|
|
|
+ t("validation.rules.one_of"),
|
|
|
+
|
|
|
password: (value) =>
|
|
|
!value || passwordPattern.test(value) || t("validation.rules.password"),
|
|
|
|
|
|
+ positive: (value) =>
|
|
|
+ Number(value) > 0 || t("validation.rules.positive"),
|
|
|
+
|
|
|
samePassword: (otherValue) => (value) =>
|
|
|
value === otherValue || t("validation.rules.same_password"),
|
|
|
|
|
|
+ slug: (value) =>
|
|
|
+ !hasValue(value) ||
|
|
|
+ /^[A-Z0-9_]+$/.test(value) ||
|
|
|
+ t("validation.rules.slug"),
|
|
|
+
|
|
|
+ time: (value) => {
|
|
|
+ if (!hasValue(value)) return true;
|
|
|
+
|
|
|
+ const match = /^(\d{2}):(\d{2})$/.exec(value);
|
|
|
+
|
|
|
+ return (
|
|
|
+ (!!match && Number(match[1]) <= 23 && Number(match[2]) <= 59) ||
|
|
|
+ t("validation.rules.time")
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
+ whenValue: (getDependency, rule) => (value) =>
|
|
|
+ !hasValue(getDependency()) || rule(value),
|
|
|
+
|
|
|
//
|
|
|
|
|
|
- required: (value) => !!value || t("validation.rules.required"),
|
|
|
- requiredHideMessage: (value) => !!value,
|
|
|
+ required: (value) => hasValue(value) || t("validation.rules.required"),
|
|
|
+
|
|
|
+ requiredHideMessage: (value) => hasValue(value),
|
|
|
|
|
|
requiredNumber: (value) =>
|
|
|
(value !== null &&
|
|
|
@@ -85,8 +193,8 @@ export const useInputRules = () => {
|
|
|
};
|
|
|
|
|
|
inputRules.required.$id = "required";
|
|
|
- inputRules.requiredNumber.$id = "required";
|
|
|
inputRules.requiredHideMessage.$id = "required";
|
|
|
+ inputRules.requiredNumber.$id = "required";
|
|
|
|
|
|
return {
|
|
|
inputRules,
|
|
|
@@ -133,7 +241,7 @@ const isValidCNPJ = (cnpj) => {
|
|
|
if (result !== parseInt(digits.charAt(1))) return false;
|
|
|
|
|
|
return true;
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
const isValidCPF = (cpf) => {
|
|
|
if (!cpf) return false;
|
|
|
@@ -145,7 +253,9 @@ const isValidCPF = (cpf) => {
|
|
|
|
|
|
let sum = 0;
|
|
|
|
|
|
- for (let i = 0; i < 9; i++) sum += parseInt(cpf.charAt(i)) * (10 - i);
|
|
|
+ for (let i = 0; i < 9; i++) {
|
|
|
+ sum += parseInt(cpf.charAt(i)) * (10 - i);
|
|
|
+ }
|
|
|
|
|
|
let rev = 11 - (sum % 11);
|
|
|
|
|
|
@@ -154,7 +264,9 @@ const isValidCPF = (cpf) => {
|
|
|
|
|
|
sum = 0;
|
|
|
|
|
|
- for (let i = 0; i < 10; i++) sum += parseInt(cpf.charAt(i)) * (11 - i);
|
|
|
+ for (let i = 0; i < 10; i++) {
|
|
|
+ sum += parseInt(cpf.charAt(i)) * (11 - i);
|
|
|
+ }
|
|
|
|
|
|
rev = 11 - (sum % 11);
|
|
|
|
|
|
@@ -162,4 +274,4 @@ const isValidCPF = (cpf) => {
|
|
|
if (rev !== parseInt(cpf.charAt(10))) return false;
|
|
|
|
|
|
return true;
|
|
|
-}
|
|
|
+};
|