233 lines
6.3 KiB
TypeScript
233 lines
6.3 KiB
TypeScript
import React, { ReactNode, ReactElement, ButtonHTMLAttributes } from "react";
|
|
import clsx from "clsx";
|
|
import {
|
|
ChartBarIcon,
|
|
DocumentChartBarIcon,
|
|
EyeIcon,
|
|
FolderPlusIcon,
|
|
PencilIcon,
|
|
PencilSquareIcon,
|
|
TrashIcon,
|
|
ViewfinderCircleIcon,
|
|
} from "@heroicons/react/24/outline";
|
|
import {
|
|
bgPrimaryColor,
|
|
mobileBorders,
|
|
textColorOnPrimary,
|
|
} from "../../data/getColorBasedOnMode";
|
|
import { checkIsMobile } from "../../utils/checkIsMobile";
|
|
import { inputWidths } from "../../data/getItemsWidth";
|
|
import { PlusIcon } from "@heroicons/react/24/solid";
|
|
import { useUserProfileStore } from "../../context/zustand-store/userStore";
|
|
import excel from "../../assets/images/svg/excel.svg?react";
|
|
import SVGImage from "../SvgImage/SvgImage";
|
|
import api from "../../utils/axios";
|
|
import { useBackdropStore } from "../../context/zustand-store/appStore";
|
|
import { useToast } from "../../hooks/useToast";
|
|
|
|
type ExcelProps = {
|
|
link: string;
|
|
title: string;
|
|
};
|
|
|
|
type ButtonProps = {
|
|
children?: ReactNode | string;
|
|
icon?: ReactElement;
|
|
direction?: "row" | "row-reverse" | "col" | "col-reverse";
|
|
iconColor?: string;
|
|
iconBgColor?: string;
|
|
iconSize?: number | string;
|
|
className?: string;
|
|
variant?:
|
|
| "submit"
|
|
| "secondary-submit"
|
|
| "edit"
|
|
| "secondary-edit"
|
|
| "detail"
|
|
| "delete"
|
|
| "view"
|
|
| "info"
|
|
| "chart";
|
|
access?: string;
|
|
height?: string | number;
|
|
fullWidth?: boolean;
|
|
excelInfo?: ExcelProps;
|
|
rounded?: boolean;
|
|
size?: "small" | "medium" | "large";
|
|
} & ButtonHTMLAttributes<HTMLButtonElement>;
|
|
|
|
const Button: React.FC<ButtonProps> = ({
|
|
children,
|
|
icon,
|
|
direction = "row",
|
|
iconSize,
|
|
className = "",
|
|
variant = "",
|
|
access = "",
|
|
height,
|
|
fullWidth = false,
|
|
excelInfo,
|
|
rounded = false,
|
|
size = "medium",
|
|
...props
|
|
}) => {
|
|
const directionClass = {
|
|
row: "flex-row",
|
|
"row-reverse": "flex-row-reverse",
|
|
col: "flex-col",
|
|
"col-reverse": "flex-col-reverse",
|
|
}[direction];
|
|
|
|
const sizeStyles = {
|
|
small: {
|
|
padding: "h-[32px] px-2",
|
|
text: "text-xs",
|
|
icon: iconSize ?? 14,
|
|
},
|
|
medium: {
|
|
padding: "h-[40px] px-2",
|
|
text: "text-sm",
|
|
icon: iconSize ?? 18,
|
|
},
|
|
large: {
|
|
padding: "h-[48px] px-2",
|
|
text: "text-base",
|
|
icon: iconSize ?? 20,
|
|
},
|
|
}[size] ?? {
|
|
padding: "px-4 py-2",
|
|
text: "text-sm",
|
|
icon: iconSize ?? 18,
|
|
};
|
|
|
|
const getVariantIcon = () => {
|
|
switch (variant) {
|
|
case "submit":
|
|
return (
|
|
<PlusIcon
|
|
className={`w-5 h-5 ${
|
|
children ? "text-white" : "text-purple-400 dark:text-white"
|
|
}`}
|
|
/>
|
|
);
|
|
case "secondary-submit":
|
|
return (
|
|
<FolderPlusIcon
|
|
className={`w-5 h-5 ${
|
|
children ? "text-white" : "text-purple-400 dark:text-white"
|
|
}`}
|
|
/>
|
|
);
|
|
case "edit":
|
|
return (
|
|
<PencilIcon className="w-5 h-5 text-purple-400 dark:text-purple-100" />
|
|
);
|
|
case "secondary-edit":
|
|
return (
|
|
<PencilSquareIcon className="w-5 h-5 text-purple-400 dark:text-purple-100" />
|
|
);
|
|
case "detail":
|
|
return (
|
|
<EyeIcon className="w-5 h-5 text-purple-400 dark:text-purple-100" />
|
|
);
|
|
case "view":
|
|
return (
|
|
<ViewfinderCircleIcon className="w-5 h-5 text-purple-400 dark:text-purple-100" />
|
|
);
|
|
case "delete":
|
|
return <TrashIcon className="w-5 h-5 text-red-500" />;
|
|
case "info":
|
|
return (
|
|
<DocumentChartBarIcon className="w-5 h-5 text-purple-400 dark:text-purple-100" />
|
|
);
|
|
case "chart":
|
|
return (
|
|
<ChartBarIcon className="w-5 h-5 text-purple-400 dark:text-purple-100" />
|
|
);
|
|
default:
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const { profile } = useUserProfileStore();
|
|
const { openBackdrop, closeBackdrop } = useBackdropStore();
|
|
const showToast = useToast();
|
|
|
|
const ableToSeeButton = () => {
|
|
if (!access) {
|
|
return true;
|
|
} else {
|
|
const permissions = profile?.permissions || [];
|
|
// Check if access exists in the permissions array (simple array of strings)
|
|
return permissions.includes(access);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<button
|
|
{...props}
|
|
className={clsx(
|
|
`${
|
|
ableToSeeButton() ? "flex" : "hidden"
|
|
} flex items-center justify-center gap-1 backdrop-blur-md transition-all duration-200 focus:outline-none cursor-pointer`,
|
|
fullWidth ? "w-full" : inputWidths,
|
|
!className.includes("bg-") ? children && bgPrimaryColor : "hover-",
|
|
directionClass,
|
|
!className.includes("text-") && textColorOnPrimary,
|
|
rounded ? "rounded-2xl" : "rounded-[8px]",
|
|
sizeStyles.padding,
|
|
sizeStyles.text,
|
|
className,
|
|
checkIsMobile() && !icon && !variant && children && mobileBorders
|
|
)}
|
|
style={{ height }}
|
|
>
|
|
<div className="w-full flex justify-center items-center">
|
|
{variant && !icon && <>{getVariantIcon()}</>}
|
|
<span className="whitespace-nowrap">{children}</span>
|
|
{icon && <div>{icon}</div>}
|
|
{excelInfo && (
|
|
<a
|
|
onClick={() => {
|
|
openBackdrop();
|
|
api
|
|
.get(excelInfo?.link || "", {
|
|
responseType: "blob",
|
|
})
|
|
.then((response) => {
|
|
closeBackdrop();
|
|
const url = window.URL.createObjectURL(
|
|
new Blob([response.data])
|
|
);
|
|
|
|
const link = document.createElement("a");
|
|
link.href = url;
|
|
|
|
link.setAttribute("download", `${excelInfo?.title}.xlsx`);
|
|
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
|
|
window.URL.revokeObjectURL(url);
|
|
})
|
|
.catch((error) => {
|
|
console.error("Error downloading file:", error);
|
|
closeBackdrop();
|
|
showToast("خطا در دانلود فایل", "error");
|
|
});
|
|
}}
|
|
>
|
|
<SVGImage
|
|
src={excel}
|
|
className={` text-primary-600 dark:text-primary-100 w-5 h-5`}
|
|
/>
|
|
</a>
|
|
)}
|
|
</div>
|
|
</button>
|
|
);
|
|
};
|
|
|
|
export default Button;
|