ar-design
Version:
AR Design is a (react | nextjs) ui library.
148 lines (147 loc) • 6.29 kB
JavaScript
"use client";
import { useEffect, useRef, useState } from "react";
import Utils from "../../../infrastructure/shared/Utils";
const useValidation = function (data, params, step) {
// refs
const _errors = useRef({});
// states
const [errors, setErrors] = useState({});
const [submit, setSubmit] = useState(false);
// methods
const onSubmit = (callback) => {
setSubmit(true);
queueMicrotask(() => {
let result = true;
if (!data || Object.keys(data).length === 0 || params.length === 0)
result = false;
if (step) {
const filteredErrors = Object.fromEntries(Object.entries(_errors.current)
.filter(([key]) => key.startsWith(`${step}_`))
.map(([key, value]) => [key.replace(/^\d+_/, ""), String(value)]));
if (Object.keys(filteredErrors).length > 0)
result = false;
}
else {
if (Object.keys(_errors.current).length > 0)
result = false;
}
callback(result);
});
};
const setError = (key, message, step, trackByValue) => {
let _key = step ? `${step}_${key}` : key;
if (trackByValue !== undefined)
_key = `${_key}_${trackByValue}`;
setErrors((prev) => ({ ...prev, [_key]: message }));
_errors.current = { ..._errors.current, [_key]: message };
};
const handleParams = (param) => {
const value = data[param.key];
// Eğer subkey varsa, onunla işlem yapılacak.
if (param.subkey) {
if (param.subkey.includes(".")) {
// Subkey içinde birden fazla seviye varsa, her seviyeye inerek değer alınacak.
const levels = param.subkey.split(".");
let currentData = value;
for (const key of levels) {
// Eğer currentData null ya da undefined ise, işlem sonlandırılır.
if (!currentData) {
paramsShape(param, currentData);
return;
}
// Seviye bazında ilerleyerek veriye ulaşılır.
currentData = currentData[key];
}
// Son seviyedeki veriyi paramsShape fonksiyonuna gönder.
paramsShape(param, currentData);
}
else {
if (Array.isArray(value)) {
// Eğer value bir dizi ise ve subkey sadece bir seviye ise,
// dizinin her bir elemanına subkey uygulanabilir.
const extractedValues = value.map((item) => ({
value: item?.[param.subkey],
trackByValue: item?.trackByValue,
}));
// Elde edilen değerler topluca paramsShape'e gönderilebilir ya da başka bir şekilde işlenebilir.
extractedValues.map((extractedValue) => paramsShape(param, extractedValue.value, extractedValue.trackByValue));
}
else {
// Value bir obje ise, subkey doğrudan kullanılır.
paramsShape(param, value?.[param.subkey]);
}
}
}
else {
// Eğer subkey yoksa, doğrudan param.key üzerinden işlem yapılır.
paramsShape(param, value);
}
};
const paramsShape = (param, value, trackByValue) => {
const vLenght = value ? value.length : 0;
const getKey = (subkey) => {
if (!subkey)
return param.key;
const levels = subkey.split(".");
return levels[levels.length - 1];
};
const handleValidation = (key, s) => {
if (s.type === "required" && Utils.IsNullOrEmpty(value)) {
setError(key, s.message, param.step, trackByValue);
}
if (s.type === "minimum" && vLenght < s.value) {
setError(key, Utils.StringFormat(s.message, s.value), param.step, trackByValue);
}
if (s.type === "maximum" && vLenght > s.value) {
setError(key, Utils.StringFormat(s.message, s.value), param.step, trackByValue);
}
// Regexes
// const phoneRegex = /^((\+90|0)?([2-5]\d{2})\d{7}|\+[1-9]\d{7,14})$/;
const phoneRegex = /^\d{7,14}$/;
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
const ibanRegex = /^TR\d{24}$/;
const accountNumberRegex = /^\d{6,16}$/;
if (s.type === "phone" && value && !phoneRegex.test(value.replace(/\D/g, ""))) {
setError(key, s.message, param.step, trackByValue);
}
if (s.type === "email" && value && !emailRegex.test(value)) {
setError(key, s.message, param.step, trackByValue);
}
if (s.type === "iban" && value && !ibanRegex.test(value.replace(/\s/g, ""))) {
setError(key, s.message, param.step, trackByValue);
}
if (s.type === "account-number" && value && !accountNumberRegex.test(value)) {
setError(key, s.message, param.step, trackByValue);
}
};
param.shape?.forEach((s) => {
const key = getKey(param.subkey);
if (param.where) {
if (param.where(data)) {
setError(param.subkey ? key : param.key, s.message, param.step, trackByValue);
}
}
else {
handleValidation(key, s);
}
});
};
// useEffects
useEffect(() => {
setErrors({});
_errors.current = {};
if (!submit)
return;
params.forEach((param) => handleParams(param));
}, [submit, data]);
return {
onSubmit,
setSubmit,
errors: step
? Object.fromEntries(Object.entries(errors)
.filter(([key]) => key.startsWith(`${step}_`))
.map(([key, value]) => [key.replace(/^\d+_/, ""), String(value)]))
: errors,
};
};
export default useValidation;