first commit
This commit is contained in:
232
src/components/Button/Button.tsx
Normal file
232
src/components/Button/Button.tsx
Normal file
@@ -0,0 +1,232 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user