ar-design
Version:
AR Design is a (react | nextjs) ui library.
159 lines (158 loc) • 6.4 kB
JavaScript
import { useContext, useEffect, useRef, useState } from "react";
import { ConfigContext } from "../contexts/Config";
import { NotificationContext } from "../contexts/Notification";
import Utils from "../../../infrastructure/shared/Utils";
import { LanguageContext } from "../contexts/Language";
import { LoadingContext } from "../contexts/Loading";
import { NotificationTR, NotificationEN } from "../locales";
export const useLayout = () => {
const context = useContext(ConfigContext);
if (!context)
throw new Error("useLayout must be used within a LayoutProvider");
return context;
};
export const useLoading = () => useContext(LoadingContext);
export const useLanguage = () => useContext(LanguageContext);
export const useTranslation = function (currentLanguage, translations) {
const merged = {
tr: { ...translations?.tr, ...NotificationTR },
en: { ...translations?.en, ...NotificationEN },
};
const t = (key, ...args) => {
return Utils.StringFormat(merged[currentLanguage ?? "tr"][key], args) ?? "";
};
return { t, currentLanguage };
};
export const useNotification = () => {
// contexts
const { setTitle, setMessage, setStatus, setTrigger, setIsPopupOpen, setPopupButtons } = useContext(NotificationContext);
// methods
const notification = ({ title, message, status }) => {
setTitle && setTitle(title);
setMessage && setMessage(message ?? "");
setStatus && setStatus(status);
setTrigger && setTrigger((trigger) => !trigger);
};
const popup = ({ title, message, status, }, buttons) => {
setTitle && setTitle(title);
setMessage && setMessage(message ?? "");
setStatus && setStatus(status);
setIsPopupOpen && setIsPopupOpen((trigger) => !trigger);
setPopupButtons && setPopupButtons(buttons ?? null);
};
return { notification, popup };
};
export 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);
setTimeout(() => {
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);
}, 0);
};
const setError = (key, message, step) => {
const _key = step ? `${step}_${key}` : key;
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 {
// Subkey sadece bir seviye ise, 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) => {
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);
}
if (s.type === "minimum" && vLenght < s.value) {
setError(key, Utils.StringFormat(s.message, s.value), param.step);
}
if (s.type === "maximum" && vLenght > s.value) {
setError(key, Utils.StringFormat(s.message, s.value), param.step);
}
if (s.type === "email" && value && !/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value)) {
setError(key, s.message, param.step);
}
};
param.shape?.forEach((s) => {
const key = getKey(param.subkey);
if (param.where) {
if (s.type === "required" && !param.where(data)) {
Utils.IsNullOrEmpty(value) && setError(param.subkey ? key : param.key, s.message, param.step);
}
}
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,
};
};