recode and add editor config file

This commit is contained in:
Amirhossein Mahmoodi
2023-07-31 09:34:59 +03:30
parent ba91b97e7c
commit 51b21957b9
108 changed files with 5993 additions and 5770 deletions

View File

@@ -1,128 +1,128 @@
import { Avatar, Box, TextField } from "@mui/material";
import { useState } from "react";
import {Avatar, Box, TextField} from "@mui/material";
import {useState} from "react";
import DeleteIcon from "@mui/icons-material/Delete";
import AddIcon from "@mui/icons-material/Add";
const AvatarUpload = ({ user, setFieldValue, valueAvatar, changeFlag }) => {
const [selectedImage, setSelectedImage] = useState(user.expert_avatar);
const [isHovered, setIsHovered] = useState(false);
const AvatarUpload = ({user, setFieldValue, valueAvatar, changeFlag}) => {
const [selectedImage, setSelectedImage] = useState(user.expert_avatar);
const [isHovered, setIsHovered] = useState(false);
const handleImageChange = (event) => {
const newImage = event.target?.files?.[0];
if (newImage) {
setSelectedImage(URL.createObjectURL(newImage));
setFieldValue(valueAvatar, newImage);
setFieldValue(changeFlag, true);
} else {
setSelectedImage("");
setFieldValue(valueAvatar, null);
}
};
const handleImageChange = (event) => {
const newImage = event.target?.files?.[0];
if (newImage) {
setSelectedImage(URL.createObjectURL(newImage));
setFieldValue(valueAvatar, newImage);
setFieldValue(changeFlag, true);
} else {
setSelectedImage("");
setFieldValue(valueAvatar, null);
}
};
const handleDeleteImage = () => {
setSelectedImage("");
setFieldValue(valueAvatar, null);
setFieldValue(changeFlag, true);
};
const handleDeleteImage = () => {
setSelectedImage("");
setFieldValue(valueAvatar, null);
setFieldValue(changeFlag, true);
};
const handleMouseEnter = () => {
setIsHovered(true);
};
const handleMouseEnter = () => {
setIsHovered(true);
};
const handleMouseLeave = () => {
setIsHovered(false);
};
const handleMouseLeave = () => {
setIsHovered(false);
};
return (
<Box
sx={{
display: "inline-block",
position: "relative",
}}
>
<Box
component="label"
htmlFor="avatar-upload"
sx={{
display: "inline-block",
width: "fit-content",
height: "fit-content",
cursor: "pointer",
}}
>
return (
<Box
component="div"
className={`avatar-container ${isHovered ? "hovered" : ""}`}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
sx={{
position: "relative",
width: 150,
height: 150,
borderRadius: "50%",
overflow: "hidden",
transition: "transform 0.3s ease-in-out",
}}
>
<Avatar
alt="User Avatar"
src={selectedImage}
sx={{
width: 150,
height: 150,
cursor: "pointer",
position: "relative",
display: "inline-block",
position: "relative",
}}
/>
{isHovered && (
>
<Box
component="div"
className="avatar-overlay"
sx={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
backgroundColor: "rgba(0, 0, 0, 0.6)",
display: "flex",
alignItems: "center",
justifyContent: "center",
transition: "transform 0.3s ease-in-out",
transform: `scale(${isHovered ? 1 : 0})`,
}}
component="label"
htmlFor="avatar-upload"
sx={{
display: "inline-block",
width: "fit-content",
height: "fit-content",
cursor: "pointer",
}}
>
{selectedImage ? (
<DeleteIcon
sx={{
color: "#fff",
width: 35,
height: 35,
}}
onClick={handleDeleteImage}
/>
) : (
<AddIcon
sx={{
color: "#fff",
width: 35,
height: 35,
}}
/>
)}
<Box
component="div"
className={`avatar-container ${isHovered ? "hovered" : ""}`}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
sx={{
position: "relative",
width: 150,
height: 150,
borderRadius: "50%",
overflow: "hidden",
transition: "transform 0.3s ease-in-out",
}}
>
<Avatar
alt="User Avatar"
src={selectedImage}
sx={{
width: 150,
height: 150,
cursor: "pointer",
position: "relative",
}}
/>
{isHovered && (
<Box
component="div"
className="avatar-overlay"
sx={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
backgroundColor: "rgba(0, 0, 0, 0.6)",
display: "flex",
alignItems: "center",
justifyContent: "center",
transition: "transform 0.3s ease-in-out",
transform: `scale(${isHovered ? 1 : 0})`,
}}
>
{selectedImage ? (
<DeleteIcon
sx={{
color: "#fff",
width: 35,
height: 35,
}}
onClick={handleDeleteImage}
/>
) : (
<AddIcon
sx={{
color: "#fff",
width: 35,
height: 35,
}}
/>
)}
</Box>
)}
</Box>
</Box>
)}
<TextField
id="avatar-upload"
type="file"
accept="image/*"
sx={{display: "none"}}
onChange={handleImageChange}
/>
</Box>
</Box>
<TextField
id="avatar-upload"
type="file"
accept="image/*"
sx={{ display: "none" }}
onChange={handleImageChange}
/>
</Box>
);
);
};
export default AvatarUpload;

View File

@@ -1,174 +1,174 @@
import { ReloadDataTableContext } from "@/lib/app/contexts/ReloadDatatableContext";
import {ReloadDataTableContext} from "@/lib/app/contexts/ReloadDatatableContext";
import useLanguage from "@/lib/app/hooks/useLanguage";
import { Typography } from "@mui/material";
import {Typography} from "@mui/material";
import axios from "axios";
import MaterialReactTable from "material-react-table";
import moment from "moment-jalaali";
import { useTranslations } from "next-intl";
import { useContext, useEffect, useMemo, useState } from "react";
import {useTranslations} from "next-intl";
import {useContext, useEffect, useMemo, useState} from "react";
import useSWR from "swr";
const DataTable = (props) => {
const { reloadDataTable, setReloadDataTable } = useContext(
ReloadDataTableContext
);
const fetcher = (...args) => {
return axios
.get(args, {
headers: {
Authorization: `Bearer ${props.token}`,
},
})
.then((res) => {
setRowCount(res.data.meta.totalRowCount);
return res.data.data;
});
};
const t = useTranslations();
const { languageApp, languageList } = useLanguage();
const [columnFilters, setColumnFilters] = useState([]);
const [columnFilterFns, setColumnFilterFns] = useState(() => {
let output = {};
const list = props.columns.map((item) =>
item.enableColumnFilter ? { [item.id]: item.filterFn } : { [item.id]: "" }
const {reloadDataTable, setReloadDataTable} = useContext(
ReloadDataTableContext
);
for (var key in list) {
var nestedObj = list[key];
for (var nestedKey in nestedObj) {
output[nestedKey] = nestedObj[nestedKey];
}
}
return output;
});
const [sorting, setSorting] = useState([]);
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
const [rowCount, setRowCount] = useState(0);
const [updateTime, setupdateTime] = useState(
moment().format("HH:mm | jYYYY/jM/jD")
);
const tableLocalization = useMemo(
() =>
languageList.find((item) => item.key == languageApp).tableLocalization,
[languageApp, languageList]
);
const fetchUrl = useMemo(() => {
const url = new URL(props.tableUrl /* send your api */);
url.searchParams.set(
"start",
`${pagination.pageIndex * pagination.pageSize}`
);
const filters = columnFilters.map((filter) => {
let datatype;
for (const i in props.columns) {
if (props.columns[i].id == filter.id) {
datatype = props.columns[i].datatype;
const fetcher = (...args) => {
return axios
.get(args, {
headers: {
Authorization: `Bearer ${props.token}`,
},
})
.then((res) => {
setRowCount(res.data.meta.totalRowCount);
return res.data.data;
});
};
const t = useTranslations();
const {languageApp, languageList} = useLanguage();
const [columnFilters, setColumnFilters] = useState([]);
const [columnFilterFns, setColumnFilterFns] = useState(() => {
let output = {};
const list = props.columns.map((item) =>
item.enableColumnFilter ? {[item.id]: item.filterFn} : {[item.id]: ""}
);
for (var key in list) {
var nestedObj = list[key];
for (var nestedKey in nestedObj) {
output[nestedKey] = nestedObj[nestedKey];
}
}
}
return {
...filter,
fn: columnFilterFns[filter.id],
datatype: datatype,
};
return output;
});
url.searchParams.set("size", pagination.pageSize);
url.searchParams.set("filters", JSON.stringify(filters ?? []));
url.searchParams.set("sorting", JSON.stringify(sorting ?? []));
return url;
}, [
props.tableUrl,
columnFilters,
columnFilterFns,
pagination,
sorting,
props.columns,
]);
const { data, isLoading, isValidating, mutate } = useSWR(fetchUrl, fetcher, {
revalidateOnFocus: false,
});
const [sorting, setSorting] = useState([]);
const [pagination, setPagination] = useState({pageIndex: 0, pageSize: 10});
const [rowCount, setRowCount] = useState(0);
const [updateTime, setupdateTime] = useState(
moment().format("HH:mm | jYYYY/jM/jD")
);
useEffect(() => {
if (reloadDataTable) {
mutate(fetchUrl).then(() => {
setReloadDataTable(false); // Set reloadDataTable to false after mutation is complete
});
}
}, [reloadDataTable, setReloadDataTable]);
const tableLocalization = useMemo(
() =>
languageList.find((item) => item.key == languageApp).tableLocalization,
[languageApp, languageList]
);
useEffect(() => {
setupdateTime(moment().format("HH:mm | jYYYY/jM/jD"));
}, [isValidating, languageApp]);
return (
<MaterialReactTable
localization={tableLocalization}
columns={props.columns} /* columns you send */
data={data ?? []}
manualFiltering
manualPagination
manualSorting
enableRowSelection={props.selectableRow} /* send condition */
enablePinning={props.enablePinning} /* send condition */
enableColumnFilters={props.enableColumnFilters} /* send condition */
enableDensityToggle={props.enableDensityToggle} /* send condition */
enableHiding={props.enableHiding} /* send condition */
enableFullScreenToggle={props.enableFullScreenToggle} /* send condition */
enableColumnResizing={props.enableColumnResizing}
muiTableHeadCellProps={{
sx: {
color: "primary.main",
"& .Mui-TableHeadCell-Content": { justifyContent: "space-between" },
},
}}
enableColumnFilterModes
muiTablePaperProps={{ elevation: 0 }}
rowCount={rowCount}
onColumnFilterFnsChange={setColumnFilterFns}
onColumnFiltersChange={setColumnFilters}
onPaginationChange={setPagination}
onSortingChange={setSorting}
positionToolbarAlertBanner="bottom"
renderTopToolbarCustomActions={({ table }) => (
<>
{props.enableCustomToolbar /* send condition */
? props.CustomToolbar /* send component */
: ""}
</>
)}
renderBottomToolbarCustomActions={({ table }) => (
<>
{props.enableLastUpdate /* send condition */ ? (
<Typography
sx={{
color: "primary.main",
alignSelf: "center",
whiteSpace: "nowrap",
maxWidth: { xs: 100, sm: "100%" },
overflowX: "scroll",
}}
variant="caption"
>
{t("last_updated_at")}: {updateTime}
</Typography>
) : (
""
)}
</>
)}
state={{
isLoading,
const fetchUrl = useMemo(() => {
const url = new URL(props.tableUrl /* send your api */);
url.searchParams.set(
"start",
`${pagination.pageIndex * pagination.pageSize}`
);
const filters = columnFilters.map((filter) => {
let datatype;
for (const i in props.columns) {
if (props.columns[i].id == filter.id) {
datatype = props.columns[i].datatype;
}
}
return {
...filter,
fn: columnFilterFns[filter.id],
datatype: datatype,
};
});
url.searchParams.set("size", pagination.pageSize);
url.searchParams.set("filters", JSON.stringify(filters ?? []));
url.searchParams.set("sorting", JSON.stringify(sorting ?? []));
return url;
}, [
props.tableUrl,
columnFilters,
columnFilterFns,
pagination,
sorting,
}}
positionActionsColumn={"last"}
enableRowActions={props.enableRowActions}
{...props}
/>
);
props.columns,
]);
const {data, isLoading, isValidating, mutate} = useSWR(fetchUrl, fetcher, {
revalidateOnFocus: false,
});
useEffect(() => {
if (reloadDataTable) {
mutate(fetchUrl).then(() => {
setReloadDataTable(false); // Set reloadDataTable to false after mutation is complete
});
}
}, [reloadDataTable, setReloadDataTable]);
useEffect(() => {
setupdateTime(moment().format("HH:mm | jYYYY/jM/jD"));
}, [isValidating, languageApp]);
return (
<MaterialReactTable
localization={tableLocalization}
columns={props.columns} /* columns you send */
data={data ?? []}
manualFiltering
manualPagination
manualSorting
enableRowSelection={props.selectableRow} /* send condition */
enablePinning={props.enablePinning} /* send condition */
enableColumnFilters={props.enableColumnFilters} /* send condition */
enableDensityToggle={props.enableDensityToggle} /* send condition */
enableHiding={props.enableHiding} /* send condition */
enableFullScreenToggle={props.enableFullScreenToggle} /* send condition */
enableColumnResizing={props.enableColumnResizing}
muiTableHeadCellProps={{
sx: {
color: "primary.main",
"& .Mui-TableHeadCell-Content": {justifyContent: "space-between"},
},
}}
enableColumnFilterModes
muiTablePaperProps={{elevation: 0}}
rowCount={rowCount}
onColumnFilterFnsChange={setColumnFilterFns}
onColumnFiltersChange={setColumnFilters}
onPaginationChange={setPagination}
onSortingChange={setSorting}
positionToolbarAlertBanner="bottom"
renderTopToolbarCustomActions={({table}) => (
<>
{props.enableCustomToolbar /* send condition */
? props.CustomToolbar /* send component */
: ""}
</>
)}
renderBottomToolbarCustomActions={({table}) => (
<>
{props.enableLastUpdate /* send condition */ ? (
<Typography
sx={{
color: "primary.main",
alignSelf: "center",
whiteSpace: "nowrap",
maxWidth: {xs: 100, sm: "100%"},
overflowX: "scroll",
}}
variant="caption"
>
{t("last_updated_at")}: {updateTime}
</Typography>
) : (
""
)}
</>
)}
state={{
isLoading,
columnFilters,
columnFilterFns,
pagination,
sorting,
}}
positionActionsColumn={"last"}
enableRowActions={props.enableRowActions}
{...props}
/>
);
};
export default DataTable;

View File

@@ -1,15 +1,15 @@
import { DataTableProvider } from "@/lib/app/contexts/DatatableContext";
import {DataTableProvider} from "@/lib/app/contexts/DatatableContext";
import DataTable from "./Datatable";
import { ReloadDataTableProvider } from "@/lib/app/contexts/ReloadDatatableContext";
import {ReloadDataTableProvider} from "@/lib/app/contexts/ReloadDatatableContext";
function DataTableStructure(props) {
return (
<ReloadDataTableProvider>
<DataTableProvider>
<DataTable {...props} token={localStorage.getItem("_token")} />
</DataTableProvider>
</ReloadDataTableProvider>
);
return (
<ReloadDataTableProvider>
<DataTableProvider>
<DataTable {...props} token={localStorage.getItem("_token")}/>
</DataTableProvider>
</ReloadDataTableProvider>
);
}
export default DataTableStructure;

View File

@@ -1,10 +1,11 @@
import { Typography } from "@mui/material";
import {Typography} from "@mui/material";
const FormErrorMessage = (props) => {
return (
<Typography variant="body2" color="error">
{props.children}
</Typography>
);
return (
<Typography variant="body2" color="error">
{props.children}
</Typography>
);
};
export default FormErrorMessage;

View File

@@ -1,22 +1,22 @@
import ImageResize from "image-resize";
const ImageResizer = async (image) => {
const imageResize = new ImageResize({
quality: 1,
format: "jpg",
outputType: "base64",
width: 400,
});
const imageResize = new ImageResize({
quality: 1,
format: "jpg",
outputType: "base64",
width: 400,
});
const get = await imageResize.get(image);
const resize = await imageResize.resize(get).then();
const output = await imageResize.output(resize).then();
const get = await imageResize.get(image);
const resize = await imageResize.resize(get).then();
const output = await imageResize.output(resize).then();
const avatar = await (await import("image-to-file-converter"))
.base64ToFile(output)
.then();
const avatar = await (await import("image-to-file-converter"))
.base64ToFile(output)
.then();
return avatar;
return avatar;
};
export default ImageResizer;

View File

@@ -1,116 +1,116 @@
import MuiLink from "@mui/material/Link";
import { styled } from "@mui/material/styles";
import {styled} from "@mui/material/styles";
import clsx from "clsx";
import NextLink from "next/link";
import { useRouter } from "next/router";
import {useRouter} from "next/router";
import * as React from "react";
// Add support for the sx prop for consistency with the other branches.
const Anchor = styled("a")({});
export const NextLinkComposed = React.forwardRef(function NextLinkComposed(
props,
ref
props,
ref
) {
const {
to,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior = true,
locale,
...other
} = props;
const {
to,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior = true,
locale,
...other
} = props;
return (
<NextLink
href={to}
prefetch={prefetch}
as={linkAs}
replace={replace}
scroll={scroll}
shallow={shallow}
passHref
locale={locale}
legacyBehavior={legacyBehavior}
>
<Anchor ref={ref} {...other} />
</NextLink>
);
return (
<NextLink
href={to}
prefetch={prefetch}
as={linkAs}
replace={replace}
scroll={scroll}
shallow={shallow}
passHref
locale={locale}
legacyBehavior={legacyBehavior}
>
<Anchor ref={ref} {...other} />
</NextLink>
);
});
// A styled version of the Next.js Link component:
// https://nextjs.org/docs/api-reference/next/link
const LinkRouting = React.forwardRef(function Link(props, ref) {
const {
activeClassName = "active",
as,
className: classNameProps,
href,
legacyBehavior,
linkAs: linkAsProp,
locale,
noLinkStyle,
prefetch,
replace,
role, // Link don't have roles.
scroll,
shallow,
...other
} = props;
const {
activeClassName = "active",
as,
className: classNameProps,
href,
legacyBehavior,
linkAs: linkAsProp,
locale,
noLinkStyle,
prefetch,
replace,
role, // Link don't have roles.
scroll,
shallow,
...other
} = props;
const router = useRouter();
const pathname = typeof href === "string" ? href : href.pathname;
const className = clsx(classNameProps, {
[activeClassName]: router.pathname === pathname && activeClassName,
});
const router = useRouter();
const pathname = typeof href === "string" ? href : href.pathname;
const className = clsx(classNameProps, {
[activeClassName]: router.pathname === pathname && activeClassName,
});
const isExternal =
typeof href === "string" &&
(href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
const isExternal =
typeof href === "string" &&
(href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
if (isExternal) {
if (noLinkStyle) {
return <Anchor className={className} href={href} ref={ref} {...other} />;
if (isExternal) {
if (noLinkStyle) {
return <Anchor className={className} href={href} ref={ref} {...other} />;
}
return <MuiLink className={className} href={href} ref={ref} {...other} />;
}
return <MuiLink className={className} href={href} ref={ref} {...other} />;
}
const linkAs = linkAsProp || as;
const nextjsProps = {
to: href,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior,
locale,
};
const linkAs = linkAsProp || as;
const nextjsProps = {
to: href,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior,
locale,
};
if (noLinkStyle) {
return (
<NextLinkComposed
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
);
}
if (noLinkStyle) {
return (
<NextLinkComposed
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
<MuiLink
component={NextLinkComposed}
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
);
}
return (
<MuiLink
component={NextLinkComposed}
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
);
});
export default LinkRouting;

View File

@@ -1,44 +1,44 @@
import { Backdrop, Fade, styled } from "@mui/material";
import {Backdrop, Fade, styled} from "@mui/material";
import StyledImage from "./StyledImage";
const LoadingImage = styled(StyledImage)({
"@keyframes load": {
"0%": {
// opacity: 0,
transform: "scale(1)",
"@keyframes load": {
"0%": {
// opacity: 0,
transform: "scale(1)",
},
"50%": {
// opacity: 1,
transform: "scale(2)",
},
"100%": {
// opacity: 0,
transform: "scale(1)",
},
},
"50%": {
// opacity: 1,
transform: "scale(2)",
},
"100%": {
// opacity: 0,
transform: "scale(1)",
},
},
animation: "load 2s infinite",
animation: "load 2s infinite",
});
const LoadingHardPage = ({ children, loading }) => {
return (
<>
<Backdrop
sx={{ bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1 }}
open={loading}
>
<Fade in={true}>
<LoadingImage
src={"/images/loading_logo.svg"}
alt="loading marhaba"
priority
width={100}
height={100}
/>
</Fade>
</Backdrop>
{children}
</>
);
const LoadingHardPage = ({children, loading}) => {
return (
<>
<Backdrop
sx={{bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1}}
open={loading}
>
<Fade in={true}>
<LoadingImage
src={"/images/loading_logo.svg"}
alt="loading marhaba"
priority
width={100}
height={100}
/>
</Fade>
</Backdrop>
{children}
</>
);
};
export default LoadingHardPage;

View File

@@ -2,21 +2,21 @@ import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import StyledImage from "./StyledImage";
const Message = ({ text, actions }) => {
return (
<FullPageLayout sx={{ p: 1 }}>
<CenterLayout spacing={3}>
<StyledImage
src={"/images/loading_logo.svg"}
alt="loading loan facilities"
width={100}
height={100}
/>
{text}
{actions}
</CenterLayout>
</FullPageLayout>
);
const Message = ({text, actions}) => {
return (
<FullPageLayout sx={{p: 1}}>
<CenterLayout spacing={3}>
<StyledImage
src={"/images/loading_logo.svg"}
alt="loading loan facilities"
width={100}
height={100}
/>
{text}
{actions}
</CenterLayout>
</FullPageLayout>
);
};
export default Message;

View File

@@ -1,35 +1,35 @@
import { LocalizationProvider, DatePicker } from "@mui/x-date-pickers";
import { AdapterDateFnsJalali } from "@mui/x-date-pickers/AdapterDateFnsJalali";
import {DatePicker, LocalizationProvider} from "@mui/x-date-pickers";
import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
import moment from "jalali-moment";
import { useTranslations } from "next-intl";
import {useTranslations} from "next-intl";
export default function MuiDatePicker({
setFieldValue,
selectType,
error,
helperText,
}) {
const t = useTranslations();
setFieldValue,
selectType,
error,
helperText,
}) {
const t = useTranslations();
const handleDateChange = (date) => {
const selectedDate = moment(date).locale("fa"); // should add .format() at the end to format the data
setFieldValue(selectType, selectedDate);
};
const handleDateChange = (date) => {
const selectedDate = moment(date).locale("fa"); // should add .format() at the end to format the data
setFieldValue(selectType, selectedDate);
};
return (
<LocalizationProvider dateAdapter={AdapterDateFnsJalali}>
<DatePicker
sx={{ width: "100%" }}
label={t("MuiDatePicker.date_picker_birthday")}
slotProps={{
textField: {
size: "small",
helperText: helperText ? `${helperText}` : "YYYY-MM-DD",
error: error ? true : false,
},
}}
onChange={handleDateChange}
/>
</LocalizationProvider>
);
return (
<LocalizationProvider dateAdapter={AdapterDateFnsJalali}>
<DatePicker
sx={{width: "100%"}}
label={t("MuiDatePicker.date_picker_birthday")}
slotProps={{
textField: {
size: "small",
helperText: helperText ? `${helperText}` : "YYYY-MM-DD",
error: error ? true : false,
},
}}
onChange={handleDateChange}
/>
</LocalizationProvider>
);
}

View File

@@ -1,33 +1,33 @@
import { useState } from "react";
import { IconButton, InputAdornment, TextField } from "@mui/material";
import { Visibility, VisibilityOff } from "@mui/icons-material";
import { Field } from "formik";
import {useState} from "react";
import {IconButton, InputAdornment, TextField} from "@mui/material";
import {Visibility, VisibilityOff} from "@mui/icons-material";
import {Field} from "formik";
const PasswordField = (props) => {
const [showPassword, setShowPassword] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => {
setShowPassword(!showPassword);
};
const handleClickShowPassword = () => {
setShowPassword(!showPassword);
};
return (
<Field
variant="outlined"
fullWidth
as={TextField}
{...props}
type={showPassword ? "text" : "password"}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleClickShowPassword}>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
);
return (
<Field
variant="outlined"
fullWidth
as={TextField}
{...props}
type={showPassword ? "text" : "password"}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleClickShowPassword}>
{showPassword ? <Visibility/> : <VisibilityOff/>}
</IconButton>
</InputAdornment>
),
}}
/>
);
};
export default PasswordField;

View File

@@ -1,5 +1,5 @@
import { styled } from "@mui/material";
import { Form } from "formik";
import {styled} from "@mui/material";
import {Form} from "formik";
const StyledForm = styled(Form)``;

View File

@@ -1,4 +1,4 @@
import { styled } from "@mui/material";
import {styled} from "@mui/material";
import Image from "next/image";
const StyledImage = styled(Image)``;

View File

@@ -1,15 +1,15 @@
import { useTranslations } from "next-intl";
import {useTranslations} from "next-intl";
import Head from "next/head";
const TitlePage = ({ text }) => {
const t = useTranslations();
return (
<Head>
<title>
{text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
</title>
</Head>
);
const TitlePage = ({text}) => {
const t = useTranslations();
return (
<Head>
<title>
{text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
</title>
</Head>
);
};
export default TitlePage;

View File

@@ -1,176 +1,175 @@
import { Box, Button, Paper, Typography } from "@mui/material";
import { useTranslations } from "next-intl";
import Image from "next/image";
import {Box, Button, Paper, Typography} from "@mui/material";
import {useTranslations} from "next-intl";
import AddIcon from "@mui/icons-material/Add";
import DeleteForeverIcon from "@mui/icons-material/DeleteForever";
import { useRef } from "react";
import {useRef} from "react";
const UploadSystem = ({
selectedImage,
setselectedImage,
handleUploadChange,
fieldname,
setFieldValue,
imageAlt,
imageSize,
fileType,
fileName,
setShowAddIcon,
showAddIcon,
}) => {
const t = useTranslations();
const fileInputRef = useRef(null);
selectedImage,
setselectedImage,
handleUploadChange,
fieldname,
setFieldValue,
imageAlt,
imageSize,
fileType,
fileName,
setShowAddIcon,
showAddIcon,
}) => {
const t = useTranslations();
const fileInputRef = useRef(null);
const handleClick = () => {
fileInputRef.current.click();
};
const handleClick = () => {
fileInputRef.current.click();
};
const handleDeleteImage = () => {
setselectedImage(null);
setFieldValue(fieldname, null);
setShowAddIcon(true);
if (fileInputRef.current) {
fileInputRef.current.value = "";
}
};
const handleDeleteImage = () => {
setselectedImage(null);
setFieldValue(fieldname, null);
setShowAddIcon(true);
if (fileInputRef.current) {
fileInputRef.current.value = "";
}
};
const isDocumentFormat = (fileType) => {
const documentFormats = [
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
];
return documentFormats.includes(fileType);
};
const isDocumentFormat = (fileType) => {
const documentFormats = [
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
];
return documentFormats.includes(fileType);
};
return (
<Box sx={{ width: "100%", my: 1 }}>
{showAddIcon ? (
// Show the add icon and "Upload File" text when no image is selected
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
border: "1px solid #b3b3b3",
borderRadius: "10px",
cursor: "pointer",
padding: "5px",
return (
<Box sx={{width: "100%", my: 1}}>
{showAddIcon ? (
// Show the add icon and "Upload File" text when no image is selected
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
border: "1px solid #b3b3b3",
borderRadius: "10px",
cursor: "pointer",
padding: "5px",
height: imageSize[1],
}}
onClick={handleClick}
>
<AddIcon sx={{ fontSize: "2rem", color: "#a19d9d" }} />
<Typography
variant="subtitle2"
sx={{
fontWeight: 600,
fontSize: "1rem",
color: "#a19d9d",
mt: 1,
}}
textAlign="center"
>
{t("UploadSystem.upload_file")}
</Typography>
</Box>
</>
) : (
// Show the uploaded content along with the delete button when an image or document is selected
<>
{fileType && fileType.startsWith("image/") ? (
<Box
width="100%"
height={imageSize[1]}
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
objectFit: "contain",
border: "1px solid #b3b3b3",
borderTopRightRadius: "10px",
borderTopLeftRadius: "10px",
borderBottom: "unset",
padding: "5px",
overflow: "hidden",
}}
onClick={handleClick}
>
<Paper
elevation={0}
sx={{
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundSize: "contain",
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
backgroundImage: `url(${selectedImage})`,
}}
></Paper>
</Box>
) : (
fileType &&
isDocumentFormat(fileType) && (
<Box
sx={{
height: imageSize[1],
display: "flex",
border: "1px solid #b3b3b3",
borderTopRightRadius: "10px",
borderTopLeftRadius: "10px",
borderBottom: "unset",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
}}
onClick={handleClick}
>
<Typography
margin={2}
sx={{
fontWeight: 600,
fontSize: "1rem",
color: "#a19d9d",
}}
textAlign="center"
>
{fileName}
</Typography>
</Box>
)
)}
<Button
sx={{
width: "100%",
}}
color="error"
endIcon={<DeleteForeverIcon />}
variant="contained"
onClick={handleDeleteImage}
>
{t("UploadSystem.delete")}
</Button>
</>
)}
<input
type="file"
accept="image/*, .pdf, .doc, .docx, .xls, .xlsx"
style={{ display: "none" }}
onChange={handleUploadChange}
ref={fileInputRef}
/>
</Box>
);
height: imageSize[1],
}}
onClick={handleClick}
>
<AddIcon sx={{fontSize: "2rem", color: "#a19d9d"}}/>
<Typography
variant="subtitle2"
sx={{
fontWeight: 600,
fontSize: "1rem",
color: "#a19d9d",
mt: 1,
}}
textAlign="center"
>
{t("UploadSystem.upload_file")}
</Typography>
</Box>
</>
) : (
// Show the uploaded content along with the delete button when an image or document is selected
<>
{fileType && fileType.startsWith("image/") ? (
<Box
width="100%"
height={imageSize[1]}
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
objectFit: "contain",
border: "1px solid #b3b3b3",
borderTopRightRadius: "10px",
borderTopLeftRadius: "10px",
borderBottom: "unset",
padding: "5px",
overflow: "hidden",
}}
onClick={handleClick}
>
<Paper
elevation={0}
sx={{
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundSize: "contain",
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
backgroundImage: `url(${selectedImage})`,
}}
></Paper>
</Box>
) : (
fileType &&
isDocumentFormat(fileType) && (
<Box
sx={{
height: imageSize[1],
display: "flex",
border: "1px solid #b3b3b3",
borderTopRightRadius: "10px",
borderTopLeftRadius: "10px",
borderBottom: "unset",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
}}
onClick={handleClick}
>
<Typography
margin={2}
sx={{
fontWeight: 600,
fontSize: "1rem",
color: "#a19d9d",
}}
textAlign="center"
>
{fileName}
</Typography>
</Box>
)
)}
<Button
sx={{
width: "100%",
}}
color="error"
endIcon={<DeleteForeverIcon/>}
variant="contained"
onClick={handleDeleteImage}
>
{t("UploadSystem.delete")}
</Button>
</>
)}
<input
type="file"
accept="image/*, .pdf, .doc, .docx, .xls, .xlsx"
style={{display: "none"}}
onChange={handleUploadChange}
ref={fileInputRef}
/>
</Box>
);
};
export default UploadSystem;

View File

@@ -1,8 +1,8 @@
import { NoSsr } from "@mui/material";
import {NoSsr} from "@mui/material";
const NoSsrHandler = ({ isBot, children }) => {
if (isBot) return children;
return <NoSsr>{children}</NoSsr>;
const NoSsrHandler = ({isBot, children}) => {
if (isBot) return children;
return <NoSsr>{children}</NoSsr>;
};
export default NoSsrHandler;

View File

@@ -1,40 +1,40 @@
import DangerousIcon from "@mui/icons-material/Dangerous";
import { Box, Typography } from "@mui/material";
import { toast } from "react-toastify";
import {Box, Typography} from "@mui/material";
import {toast} from "react-toastify";
const ErrorNotification = (directionApp, status, t, message) => {
toast(
() => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<DangerousIcon color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography color="error" variant="button">
{t("notifications.error")} ({t("notifications.code")}: {status})
</Typography>
<Typography variant="caption">
{message || t("notifications.error_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
toast(
() => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{display: "flex", alignItems: "center"}}>
<DangerousIcon color="error" sx={{mr: 1.6}}/>
<Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="error" variant="button">
{t("notifications.error")} ({t("notifications.code")}: {status})
</Typography>
<Typography variant="caption">
{message || t("notifications.error_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
};
export default ErrorNotification;

View File

@@ -1,43 +1,43 @@
import BeenhereIcon from "@mui/icons-material/Beenhere";
import { Box, Typography } from "@mui/material";
import { toast } from "react-toastify";
import {Box, Typography} from "@mui/material";
import {toast} from "react-toastify";
const SuccessNotification = (directionApp, status, t) => {
toast(
() => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<BeenhereIcon color="success" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography color="success.main" variant="button">
{t("notifications.success")} ({t("notifications.code")}:{" "}
{status})
</Typography>
<Typography variant="caption">
{t("notifications.success_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);
toast(
() => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{display: "flex", alignItems: "center"}}>
<BeenhereIcon color="success" sx={{mr: 1.6}}/>
<Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="success.main" variant="button">
{t("notifications.success")} ({t("notifications.code")}:{" "}
{status})
</Typography>
<Typography variant="caption">
{t("notifications.success_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);
};
export default SuccessNotification;

View File

@@ -1,37 +1,37 @@
import DangerousIcon from "@mui/icons-material/Dangerous";
import { Box, Typography } from "@mui/material";
import { toast } from "react-toastify";
import {Box, Typography} from "@mui/material";
import {toast} from "react-toastify";
const UploadFileNotification = (directionApp, t) => {
toast(
({ closeToast }) => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<DangerousIcon color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography color="error" variant="button">
{t("UploadSystem.uploadfile_error")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
toast(
({closeToast}) => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{display: "flex", alignItems: "center"}}>
<DangerousIcon color="error" sx={{mr: 1.6}}/>
<Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="error" variant="button">
{t("UploadSystem.uploadfile_error")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
};
export default UploadFileNotification;

View File

@@ -1,41 +1,41 @@
import ReportIcon from "@mui/icons-material/Report";
import { Box, Typography } from "@mui/material";
import { toast } from "react-toastify";
import {Box, Typography} from "@mui/material";
import {toast} from "react-toastify";
const WarningNotification = (directionApp, status, t) => {
toast(
() => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<ReportIcon color="warning" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography color="warning.main" variant="button">
{t("notifications.warning")} ({t("notifications.code")}:{" "}
{status})
</Typography>
<Typography variant="caption">
{t("notifications.warning_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
toast(
() => (
<>
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{display: "flex", alignItems: "center"}}>
<ReportIcon color="warning" sx={{mr: 1.6}}/>
<Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="warning.main" variant="button">
{t("notifications.warning")} ({t("notifications.code")}:{" "}
{status})
</Typography>
<Typography variant="caption">
{t("notifications.warning_static_text")}
</Typography>
</Box>
</Box>
</Box>
</>
),
{
position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
};
export default WarningNotification;

View File

@@ -3,37 +3,37 @@ import WarningNotification from "./WarningNotification";
import SuccessNotification from "./SuccessNotification";
const Notifications = async (directionApp, response, t) => {
const { status, data } = response;
const {status, data} = response;
switch (status) {
case 200:
SuccessNotification(directionApp, status, t);
break;
case 400:
ErrorNotification(directionApp, status, t);
break;
case 401:
ErrorNotification(directionApp, status, t);
break;
case 403:
ErrorNotification(directionApp, status, t);
break;
case 422:
ErrorNotification(directionApp, status, t, data.message);
break;
case 500:
WarningNotification(directionApp, status, t);
break;
case 503:
WarningNotification(directionApp, status, t);
break;
case 504:
WarningNotification(directionApp, status, t);
break;
default:
// Handle other cases if needed
break;
}
switch (status) {
case 200:
SuccessNotification(directionApp, status, t);
break;
case 400:
ErrorNotification(directionApp, status, t);
break;
case 401:
ErrorNotification(directionApp, status, t);
break;
case 403:
ErrorNotification(directionApp, status, t);
break;
case 422:
ErrorNotification(directionApp, status, t, data.message);
break;
case 500:
WarningNotification(directionApp, status, t);
break;
case 503:
WarningNotification(directionApp, status, t);
break;
case 504:
WarningNotification(directionApp, status, t);
break;
default:
// Handle other cases if needed
break;
}
};
export default Notifications;