This commit is contained in:
2025-02-04 15:05:02 +05:30
34 changed files with 1045 additions and 112 deletions

View File

@@ -15,26 +15,26 @@ const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => {
return (
<HStack position={'relative'} bg="#F2F2F2" backgroundPosition="center" backgroundRepeat="repeat" backgroundSize="cover" gap={0} w="100%" h="100vh" p={2}>
<HStack position={'relative'} bg="#F2F2F2" backgroundPosition="center" backgroundRepeat="repeat" backgroundSize="cover" gap={0} w="100%" h="100vh" p={0}>
<VStack zIndex={1} gap={0} rounded={'lg'} h="100%" w="15%" >
<HStack w={'100%'} p={3} h={'6.5%'} justifyContent={'center'}>
<VStack zIndex={1} gap={0} rounded={'lg'} h="100%" w="16%" overflow={'scroll'} >
<HStack w={'100%'} p={3} h={'8%'} justifyContent={'center'}>
<Image w={55} src={logo} />
</HStack>
<VStack w={'100%'} p={3}>
<VStack w={'100%'} p={4} pt={0}>
{nav?.map(({ title, path, Icon, type, children }, index) => type === 'single' ?
<NavLink className="link" key={index} to={path} style={{ cursor: 'pointer', borderRadius: '8px', padding: '6px', width: '100%', display: 'flex', alignItems: 'center', gap: 6, border: '1px solid #ffffff', backgroundColor:'#fff', color:'#000', boxShadow:'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'}} ><Icon style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>{title}</Text></NavLink> :
<AccordionRoot bg={'#fff'} rounded={'lg'} collapsible>
<AccordionItem boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'} borderBottom={'none'} p={0} key={index} value={title}>
<AccordionItemTrigger color={'#fff'} onClick={() => navigate(path)} gap={0} style={{ cursor: 'pointer', borderRadius: '8px', padding: '5px', width: '100%', display: 'flex', alignItems: 'center', border: '1px solid #ffffff', backgroundColor:'#fff',color:'#000', fontSize: '14px', }}> <Text fontSize={'xs'} gap={1} display={'flex'} alignItems={'center'} ><Icon style={{ fontSize: '20px' }} />{title}</Text></AccordionItemTrigger>
{children?.map(({ title, path, Icon }, index) => <AccordionItemContent className={`linkChild ${location?.pathname === path && 'activeChild'}`} key={index} onClick={()=>navigate(path)} style={{ marginTop: 6, cursor: 'pointer', borderRadius: '8px', padding: '6px', width: '100%', display: 'flex', alignItems: 'center', gap: 6, border: '1px solid #ffffff', backgroundColor:'#fff',color:'#000' }} ><Icon style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>{title}</Text></AccordionItemContent>)}
<AccordionItemTrigger className="Oxygen" color={'#fff'} onClick={() => navigate(path)} gap={0} style={{ cursor: 'pointer', borderRadius: '8px', padding: '5px', width: '100%', display: 'flex', alignItems: 'center', border: '1px solid #ffffff', backgroundColor:'#fff',color:'#000', fontSize: '14px', }}> <Text fontSize={'xs'} gap={1} display={'flex'} alignItems={'center'} ><Icon style={{ fontSize: '20px' }} />{title}</Text></AccordionItemTrigger>
{children?.map(({ title, path, Icon }, index) => <AccordionItemContent className={`linkChild Oxygen ${location?.pathname === path && 'activeChild'}`} key={index} onClick={()=>navigate(path)} style={{ marginTop: 6, cursor: 'pointer', borderRadius: '8px', padding: '6px', width: '100%', display: 'flex', alignItems: 'center', gap: 6, border: '1px solid #ffffff', backgroundColor:'#fff',color:'#919198' }} ><Icon style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>{title}</Text></AccordionItemContent>)}
</AccordionItem>
</AccordionRoot>)}
</VStack>
</VStack>
<VStack gap={0} h="100%" w="85%" >
<HStack h={'6%'} w={'100%'} justifyContent={'flex-end'} pe={3} gap={6}>
<RiNotificationLine color="#013e3e" cursor={'pointer'} style={{ fontSize: '22px' }} />
<HStack h={'8%'} w={'100%'} justifyContent={'flex-end'} pe={3} gap={6}>
<NavLink to={'/manage-notification'}><RiNotificationLine color="#013e3e" cursor={'pointer'} style={{ fontSize: '22px' }} /></NavLink>
<HStack cursor={'pointer'} onClick={() => navigate('/profile')} >
<Avatar size={'sm'} src="https://i.pinimg.com/736x/d6/cd/0f/d6cd0ffd4634b0763d3958a7325ce26e.jpg" />
<VStack color={'#013e3e'} gap={0} alignItems={'flex-start'}>

View File

@@ -1,6 +0,0 @@
const CMS = () => {
return (
<div>CMS</div>
)
}
export default CMS

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const AboutUs = () => {
return (
<MainFrame >
AboutUs
</MainFrame>
)
}
export default AboutUs

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const FAQ = () => {
return (
<MainFrame >
FAQ
</MainFrame>
)
}
export default FAQ

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const Privacy = () => {
return (
<MainFrame >
Privacy
</MainFrame>
)
}
export default Privacy

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const PrivacyPolicy = () => {
return (
<MainFrame >
PrivacyPolicy
</MainFrame>
)
}
export default PrivacyPolicy

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const TermsAndConditions = () => {
return (
<MainFrame >
TermsAndConditions
</MainFrame>
)
}
export default TermsAndConditions

View File

@@ -1,10 +0,0 @@
import MainFrame from "../../components/MainFrame"
const ManageCommunity = () => {
return (
<MainFrame >
</MainFrame>
)
}
export default ManageCommunity

View File

@@ -1,11 +0,0 @@
import MainFrame from "../../components/MainFrame"
const ManagePost = () => {
return (
<MainFrame >
</MainFrame>
)
}
export default ManagePost

View File

@@ -1,11 +1,11 @@
import MainFrame from "../../components/MainFrame"
const Support = () => {
const ManageContact = () => {
return (
<MainFrame >
ManageContact
</MainFrame>
)
}
export default Support
export default ManageContact

View File

@@ -3,7 +3,7 @@ import MainFrame from "../../components/MainFrame"
const ManageGroups = () => {
return (
<MainFrame >
ManageGroups
</MainFrame>
)
}

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../components/MainFrame"
const ManageJobs = () => {
return (
<MainFrame>
ManageJobs
</MainFrame>
)
}
export default ManageJobs

View File

@@ -0,0 +1,12 @@
import MainFrame from '../../components/MainFrame'
const ManagePost = () => {
return (
<MainFrame>
ManagePost
</MainFrame>
)
}
export default ManagePost

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const DeactivatedAccounts = () => {
return (
<MainFrame>
DeactivatedAccounts
</MainFrame>
)
}
export default DeactivatedAccounts

View File

@@ -1,11 +0,0 @@
import MainFrame from "../../components/MainFrame"
const ManageUsers = () => {
return (
<MainFrame >
</MainFrame>
)
}
export default ManageUsers

View File

@@ -0,0 +1,122 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame";
import AlertDailog from "../../../components/AlertDailog";
import { FcCancel } from "react-icons/fc";
import { NavLink } from "react-router-dom";
import { MdOutlineRemoveRedEye } from "react-icons/md";
import { RiDeleteBin5Line } from "react-icons/ri";
import DataTable from "../../../components/DataTable";
import { HiCheck } from "react-icons/hi2";
import { HiX } from "react-icons/hi";
import { Switch } from "../../../components/ui/switch";
import { Button } from "../../../components/ui/button";
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
const tableHeadRow = [
"Sr. No",
"First Name",
"Mobile Number ",
"Gender",
"DOB",
"Type Of User",
"Language",
"Activate/Deactivate",
"Action",
];
const registerUser: any[] = [
...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1,
"First Name": "Ritesh",
"Mobile Number ": "akanksha@gmail.com",
"Gender": "9876543210",
"DOB": "Female",
"Type Of User": "15-01-1990",
"Language": "Mumbai",
"Activate/Deactivate": (
<Box>
<Switch colorPalette={'teal'} />
</Box>
),
"Action": (
<HStack justifyContent="center">
<AlertDailog
AltertTiggerIcon={FcCancel}
alertText="Suspend User"
alertIcon={<Image src={""} h={"39px"} />}
alertCaption="Are you sure you want to deactivate this user?"
onConfirm={() => {
console.log("User deleted:", i + 1);
}}
/>
<NavLink to="/manage-user/active-user/view-active-user">
<MdOutlineRemoveRedEye
style={{ cursor: "pointer", fontSize: "16px" }}
/>
</NavLink>
{/* <RiDeleteBin5Line style={{ cursor: "pointer" }} /> */}
<AlertDailog
AltertTiggerIcon={RiDeleteBin5Line}
alertText="Delete Users"
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
alertCaption="are you sure you want to delete ?"
onConfirm={() => {
console.log("User deleted:", i + 1);
}}
/>
</HStack>
),
})),
];
const RegisterUsers = () => {
return (
<MainFrame>
<Box>
<HStack
w={"100%"}
justifyContent={"space-between"}
mb={4}
py={0}
px={3}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Register Users
</Text>
<HStack>
<InputGroup
startElement={
<LuSearch fontSize={"xs"} style={{position:'relative',left:'10px'}} />
}
color={"#000"}
>
<Input
p={4}
w={300}
bg={"#fff"}
colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }}
rounded={"md"}
size={"2xs"}
fontSize={"2sm"}
placeholder="Search..."
bgColor={'#EEEEEE'}
ps={8}
/>
</InputGroup>
</HStack>
</HStack>
<DataTable
sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow}
data={registerUser}
/>
</Box>
</MainFrame>
);
};
export default RegisterUsers;

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const AgencyMaster = () => {
return (
<MainFrame>
AgencyMaster
</MainFrame>
)
}
export default AgencyMaster

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const Country = () => {
return (
<MainFrame>
Country
</MainFrame>
)
}
export default Country

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const JobStatus = () => {
return (
<MainFrame>
JobStatus
</MainFrame>
)
}
export default JobStatus

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const JobType = () => {
return (
<MainFrame>
JobType
</MainFrame>
)
}
export default JobType

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const TemplateMaster = () => {
return (
<MainFrame>
TemplateMaster
</MainFrame>
)
}
export default TemplateMaster

View File

@@ -0,0 +1,12 @@
import MainFrame from "../../../components/MainFrame"
const WorkspaceMode = () => {
return (
<MainFrame >
WorkspaceMode
</MainFrame>
)
}
export default WorkspaceMode

View File

@@ -1,11 +1,11 @@
import MainFrame from "../../components/MainFrame"
const Reporting = () => {
const MyProfile = () => {
return (
<MainFrame >
MyProfile
</MainFrame>
)
}
export default Reporting
export default MyProfile

View File

@@ -3,7 +3,7 @@ import MainFrame from "../../components/MainFrame"
const Profile = () => {
return (
<MainFrame >
Profile
</MainFrame>
)
}

View File

@@ -4,7 +4,7 @@ const SubAdmin = () => {
return (
<MainFrame >
SubAdmin
</MainFrame>
)
}

View File

@@ -1,77 +1,143 @@
import { LiaUsersSolid } from "react-icons/lia";
import { LuBellDot } from "react-icons/lu";
import { MdOutlineSupportAgent, MdPostAdd } from "react-icons/md";
import { LuBriefcaseBusiness} from "react-icons/lu";
import { MdHeadsetMic, MdOutlineDashboard} from "react-icons/md";
import { GoDotFill } from "react-icons/go";
import { TbFileSettings, TbLayoutDashboard, TbReport, TbUsers, TbUsersGroup } from "react-icons/tb";
import { RiUserSettingsLine } from "react-icons/ri";
import { HiOutlinePencilSquare } from "react-icons/hi2";
import { BiUser, BiUserPin } from "react-icons/bi";
import { PiUsersThree } from "react-icons/pi";
import { BsBoxes, BsPersonBadge } from "react-icons/bs";
import { AiOutlineFileText } from "react-icons/ai";
export const nav = [
{
title: "Dashboard",
path: "/",
Icon: TbLayoutDashboard,
Icon: MdOutlineDashboard,
type:'single'
},
{
title: "Manage Users",
path: "/manage-user",
Icon: TbUsers,
type:'single'
},
{
title: "Manage Groups",
path: "/manage-groups",
Icon: TbUsersGroup,
type:'single'
},
{
title: "Community",
path: "/manage-community",
Icon: LiaUsersSolid,
path: "/register-users",
Icon: BiUserPin,
type:'multiple',
children: [
{
title: "Manage Community",
path: "/manage-community",
title: "Register Users",
path: "/register-users",
Icon: GoDotFill,
},
{
title: "Manage Post",
path: "/manage-post",
title: "Deactivated Accounts",
path: "/deactivated-accounts",
Icon: GoDotFill,
},
],
},
{
title: "Support",
path: "/support",
Icon: MdOutlineSupportAgent,
title: "Manage Post",
path: "/manage-post",
Icon: HiOutlinePencilSquare,
type:'single'
},
{
title: "Sub-Admin",
title: "Manage Sub-Admin",
path: "/sub-admin",
Icon: RiUserSettingsLine,
Icon: BiUser,
type:'single'
},
{
title: "Reporting",
path: "/reporting",
Icon: TbReport,
title: "Manage Jobs",
path: "/manage-jobs",
Icon: LuBriefcaseBusiness,
type:'single'
},
{
title: "CMS",
path: "/cms",
Icon: TbFileSettings,
title: "Manage Groups",
path: "/manage-groups",
Icon: PiUsersThree,
type:'single'
},
{
title: "Manage Notifications",
path: "/manage-notification",
Icon: LuBellDot,
title: "Manage Contact Us",
path: "/manage-contact",
Icon: MdHeadsetMic ,
type:'single'
}
},
{
title: "Manage CMS",
path: "/faq",
Icon: AiOutlineFileText,
type:'multiple',
children: [
{
title: "FAQs",
path: "/faq",
Icon: GoDotFill,
},
{
title: "About Us",
path: "/about-us",
Icon: GoDotFill,
},
{
title: "Privacy Policy",
path: "/privacy-policy",
Icon: GoDotFill,
},
{
title: "Terms And Conditions",
path: "/terms-conditions",
Icon: GoDotFill,
},
{
title: "Privacy",
path: "/privacy",
Icon: GoDotFill,
},
],
},
{
title: "My Profile",
path: "/profile",
Icon: BsPersonBadge,
type:'single'
},
{
title: "Master Module",
path: "/agency-master",
Icon: BsBoxes,
type:'multiple',
children: [
{
title: "Agency Master",
path: "/agency-master",
Icon: GoDotFill,
},
{
title: "Template Master",
path: "/template-master",
Icon: GoDotFill,
},
{
title: "Job Type",
path: "/job-type",
Icon: GoDotFill,
},
{
title: "Workspace Mode",
path: "/workspace-mode",
Icon: GoDotFill,
},
{
title: "Country",
path: "/country",
Icon: GoDotFill,
},
{
title: "Job Status",
path: "/job-status",
Icon: GoDotFill,
},
],
},
];

View File

@@ -1,24 +1,49 @@
import CMS from "../Pages/CMS/CMS";
import Dashboard from "../Pages/Dashboard/Dashboard";
import ManageCommunity from "../Pages/ManageCommunity/ManageCommunity";
import ManagePost from "../Pages/ManageCommunity/ManagePost";
import ManageGroups from "../Pages/ManageGroups/ManageGroups";
import ManageUsers from "../Pages/ManageUsers/ManageUsers";
import ManageJobs from "../Pages/ManageJobs/ManageJobs";
import ManagePost from "../Pages/ManagePost/ManagePost";
import Profile from "../Pages/Profile/Profile";
import Reporting from "../Pages/Reporting/Reporting";
import SubAdmin from "../Pages/SubAdmin/SubAdmin";
import Support from "../Pages/Support/Support";
import ManageContact from "../Pages/ManageContact/ManageContact";
import FAQ from "../Pages/ManageCMS/FAQ/FAQ";
import AboutUs from "../Pages/ManageCMS/AboutUs/AboutUs";
import PrivacyPolicy from "../Pages/ManageCMS/PrivacyPolicy/PrivacyPolicy";
import TermsAndConditions from "../Pages/ManageCMS/TermsAndConditions/TermsAndConditions";
import Privacy from "../Pages/ManageCMS/Privacy/Privacy";
import MyProfile from "../Pages/MyProfile/MyProfile";
import Notification from "../Pages/Notification/Notification";
import AgencyMaster from "../Pages/MasterModule/AgencyMaster/AgencyMaster";
import TemplateMaster from "../Pages/MasterModule/TemplateMaster/TemplateMaster";
import JobType from "../Pages/MasterModule/JobType/JobType";
import WorkspaceMode from "../Pages/MasterModule/WorkspaceMode/WorkspaceMode";
import Country from "../Pages/MasterModule/Country/Country";
import JobStatus from "../Pages/MasterModule/JobStatus/JobStatus";
import RegisterUsers from "../Pages/ManageUsers/RegisterUsers/RegisterUsers";
import DeactivatedAccounts from "../Pages/ManageUsers/DeactivatedAccounts/DeactivatedAccounts";
export const RouteLink = [
{ path: "/", Component: Dashboard },
{ path: "/manage-user", Component: ManageUsers },
{ path: "/manage-groups", Component: ManageGroups },
{ path: "/manage-community", Component: ManageCommunity},
{ path: "/manage-post", Component: ManagePost},
{ path: "/support", Component: Support},
{ path: "/register-users", Component: RegisterUsers },
{ path: "/deactivated-accounts", Component: DeactivatedAccounts },
{ path: "/manage-post", Component: ManagePost },
{ path: "/sub-admin", Component: SubAdmin},
{ path: "/reporting", Component: Reporting},
{ path: "/cms", Component: CMS},
{ path: "/manage-notification", Component: CMS},
{ path: "/manage-jobs", Component: ManageJobs},
{ path: "/manage-groups", Component: ManageGroups },
{ path: "/manage-contact", Component: ManageContact},
{ path: "/faq", Component: FAQ},
{ path: "/about-us", Component: AboutUs},
{ path: "/privacy-policy", Component: PrivacyPolicy},
{ path: "/terms-conditions", Component: TermsAndConditions},
{ path: "/privacy", Component: Privacy},
{ path: "/my-profile", Component: MyProfile},
{ path: "/manage-notification", Component: Notification},
{ path: "/profile", Component: Profile},
{ path: "/agency-master", Component: AgencyMaster},
{ path: "/template-master", Component: TemplateMaster},
{ path: "/job-type", Component: JobType},
{ path: "/workspace-mode", Component: WorkspaceMode},
{ path: "/country", Component: Country},
{ path: "/job-status", Component: JobStatus},
]

View File

@@ -0,0 +1,125 @@
import React from "react";
import { DialogBody, HStack, Icon, Text } from "@chakra-ui/react";
import { Button } from "./ui/button";
import {
DialogActionTrigger,
DialogCloseTrigger,
DialogContent,
DialogRoot,
DialogTrigger,
} from "./ui/dialog";
interface DeleteConfirmationDialogProps {
onConfirm?: () => void;
alertText?: string;
alertCaption?: string;
alertIcon?: any;
AltertTiggerIcon?: any;
button?: any;
iconColor?: string;
}
const AlertDailog: React.FC<DeleteConfirmationDialogProps> = ({
onConfirm,
alertText,
alertCaption,
alertIcon,
AltertTiggerIcon,
button,
iconColor,
}) => {
return (
<DialogRoot
placement={"center"}
motionPreset="slide-in-bottom"
size={"xs"}
role="alertdialog"
>
<DialogTrigger asChild>
{button ? (
button
) : (
<Icon
cursor={"pointer"}
p={0.5}
_hover={{ bg: "#00000015" }}
rounded={"md"}
boxSize={5}
color={iconColor && iconColor}
>
<AltertTiggerIcon />
</Icon>
)}
</DialogTrigger>
<DialogContent bgColor="#fff">
{/* <DialogHeader display="flex" justifyContent="center"> */}
{/* <Image src={alertIcon} h={"39px"} /> */}
{/* </DialogHeader> */}
<DialogBody
display="flex"
flexDirection="column"
alignItems="center"
color="black"
p={8}
gap={2}
>
{alertIcon && alertIcon}
<Text
mt={3}
fontWeight={600}
fontSize="sm"
color="#000000"
textAlign="center"
as={"span"}
>
{alertText}
</Text>
<Text
as={"span"}
fontSize="sm"
style={{ textAlign: "center", color: "#000000CC", width: "100%" }}
>
{" "}
{alertCaption}
</Text>
<HStack mt={2} w={"100%"}>
<DialogActionTrigger asChild>
<Button
width="50%"
color="black"
_hover={{ bgColor: "white" }}
variant="outline"
borderRadius="sm"
border="1px solid #007F33"
size={"xs"}
>
No
</Button>
</DialogActionTrigger>
<Button
borderRadius="sm"
width="50%"
bgColor="#007F33"
color="white"
// colorPalette="#007F33"
onClick={onConfirm}
size={"xs"}
>
Yes{" "}
</Button>
</HStack>
</DialogBody>
<DialogCloseTrigger
_hover={{ bg: "#00000010" }}
color={"#000"}
colorPalette={"bg"}
/>
</DialogContent>
</DialogRoot>
);
};
export default AlertDailog;

View File

@@ -0,0 +1,130 @@
import { useState } from "react";
import { HStack, Stack, Table } from "@chakra-ui/react";
import { PaginationItems, PaginationNextTrigger, PaginationPrevTrigger, PaginationRoot } from "./ui/pagination";
// import {
// PaginationItems,
// PaginationNextTrigger,
// PaginationPrevTrigger,
// PaginationRoot,
// } from "./ui/pagination";
interface TableProps {
tableHeadRow: string[];
data: Record<string, any>[];
sortableColumns?: string[]; // Specify which columns are sortable
}
const DataTable: React.FC<TableProps> = ({
tableHeadRow,
data,
sortableColumns = [],
}) => {
const [sortedData, setSortedData] = useState(data);
const [sortConfig, setSortConfig] = useState<{
key: string;
direction: "asc" | "desc";
} | null>(null);
const handleSort = (column: string) => {
if (!sortableColumns.includes(column)) return;
let direction: "asc" | "desc" = "asc";
if (
sortConfig &&
sortConfig.key === column &&
sortConfig.direction === "asc"
) {
direction = "desc";
}
const sortedArray = [...sortedData].sort((a, b) => {
if (a[column] < b[column]) return direction === "asc" ? -1 : 1;
if (a[column] > b[column]) return direction === "asc" ? 1 : -1;
return 0;
});
setSortedData(sortedArray);
setSortConfig({ key: column, direction });
};
return (
<Stack mt={0} color={"#000000CC"}>
<Table.ScrollArea mb={3}>
<Table.Root size="sm" variant={"line"} stickyHeader>
<Table.Header>
<Table.Row bg={"#02A0A0"}>
{tableHeadRow.map((item, index) => (
<Table.ColumnHeader
color="white"
fontSize={"xs"}
fontWeight={600}
px={4}
p={3}
textAlign={
index === tableHeadRow.length - 1 ? "center" : "left"
}
key={index}
border={"none"}
onClick={() => handleSort(item)}
cursor={
sortableColumns.includes(item) ? "pointer" : "default"
}
_hover={
sortableColumns.includes(item)
? { textDecoration: "underline" }
: {}
}
>
{item}
{sortableColumns.includes(item) &&
sortConfig?.key === item && (
<span style={{ marginLeft: "4px" }}>
{sortConfig.direction === "asc" ? "\u25B2" : "\u25BC"}
</span>
)}
</Table.ColumnHeader>
))}
</Table.Row>
</Table.Header>
<Table.Body>
{sortedData.map((item: any, index) => (
<Table.Row
key={index}
bg={index % 2 === 0 ? "#fff" : "#007F3310"}
>
{tableHeadRow.map((heading, colIndex) => (
<Table.Cell
// className="oxygen"
px={4}
p={2}
key={`${index}-${colIndex}`}
fontSize={"xs"}
fontWeight={500}
border={"none"}
>
{item[heading]}
</Table.Cell>
))}
</Table.Row>
))}
</Table.Body>
</Table.Root>
</Table.ScrollArea>
<PaginationRoot
size={"xs"}
count={20}
pageSize={2}
defaultPage={1}
mb={4}
>
<HStack justifyContent="flex-end">
<PaginationPrevTrigger />
<PaginationItems />
<PaginationNextTrigger />
</HStack>
</PaginationRoot>
</Stack>
);
};
export default DataTable;

View File

@@ -13,13 +13,15 @@ interface MainFrameProps {
const MainFrame: FC<MainFrameProps> = ({ children, title }) => {
return (
<MotionVStack {...OPACITY_ON_LOAD} w="100%" h="94%" p={4} pb={0} >
<MotionVStack {...OPACITY_ON_LOAD} w="100%" h="90%" p={0} pb={0}>
<Box
w="100%"
h="97%"
h="100%"
bg="#ffffff"
rounded="md"
overflow={'scroll'}
// rounded="md"
boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'}
pt={3}
>
{children}
</Box>

View File

@@ -0,0 +1,12 @@
"use client"
import type { HTMLChakraProps, RecipeProps } from "@chakra-ui/react"
import { createRecipeContext } from "@chakra-ui/react"
export interface LinkButtonProps
extends HTMLChakraProps<"a", RecipeProps<"button">> {}
const { withContext } = createRecipeContext({ key: "button" })
// Replace "a" with your framework's link component
export const LinkButton = withContext<HTMLAnchorElement, LinkButtonProps>("a")

View File

@@ -0,0 +1,237 @@
"use client";
import type { ButtonProps, TextProps } from "@chakra-ui/react";
import {
Button,
Pagination as ChakraPagination,
HStack,
IconButton,
Text,
createContext,
usePaginationContext,
} from "@chakra-ui/react";
import * as React from "react";
import { HiChevronLeft, HiChevronRight } from "react-icons/hi2";
import { LinkButton } from "./link-button";
interface ButtonVariantMap {
current: ButtonProps["variant"];
default: ButtonProps["variant"];
ellipsis: ButtonProps["variant"];
}
type PaginationVariant = "outline" | "solid" | "subtle";
interface ButtonVariantContext {
size: ButtonProps["size"];
variantMap: ButtonVariantMap;
getHref?: (page: number) => string;
}
const [RootPropsProvider, useRootProps] = createContext<ButtonVariantContext>({
name: "RootPropsProvider",
});
export interface PaginationRootProps
extends Omit<ChakraPagination.RootProps, "type"> {
size?: ButtonProps["size"];
variant?: PaginationVariant;
getHref?: (page: number) => string;
}
const variantMap: Record<PaginationVariant, ButtonVariantMap> = {
outline: { default: "ghost", ellipsis: "plain", current: "solid" },
solid: { default: "outline", ellipsis: "outline", current: "solid" },
subtle: { default: "ghost", ellipsis: "plain", current: "subtle" },
};
export const PaginationRoot = React.forwardRef<
HTMLDivElement,
PaginationRootProps
>(function PaginationRoot(props, ref) {
const { size = "sm", variant = "outline", getHref, ...rest } = props;
return (
<RootPropsProvider
value={{ size, variantMap: variantMap[variant], getHref }}
>
<ChakraPagination.Root
ref={ref}
type={getHref ? "link" : "button"}
{...rest}
/>
</RootPropsProvider>
);
});
export const PaginationEllipsis = React.forwardRef<
HTMLDivElement,
ChakraPagination.EllipsisProps
>(function PaginationEllipsis(props, ref) {
const { size, variantMap } = useRootProps();
return (
<ChakraPagination.Ellipsis ref={ref} {...props} asChild>
<Button as="span" variant={variantMap.ellipsis} size={size}>
...
</Button>
</ChakraPagination.Ellipsis>
);
});
export const PaginationItem = React.forwardRef<
HTMLButtonElement,
ChakraPagination.ItemProps
>(function PaginationItem(props, ref) {
const { page } = usePaginationContext();
const { size, variantMap, getHref } = useRootProps();
const current = page === props.value;
const variant = current ? variantMap.current : variantMap.default;
if (getHref) {
return (
<LinkButton
href={getHref(props.value)}
variant={variant}
size={size}
bg={current ? "#02A0A0" : "white"}
color={current ? "black" : "black"}
_hover={{ bg: "#02A0A0", color: "black" }}
>
{props.value}
</LinkButton>
);
}
return (
<ChakraPagination.Item ref={ref} {...props} asChild>
<Button
bg={current ? "#F5F8FB" : "white"}
color={current ? "black" : "black"}
variant={variant}
size={size}
_hover={{ bg: "#F5F8FB", color: "black" }}
border="none"
>
{props.value}
</Button>
</ChakraPagination.Item>
);
});
export const PaginationPrevTrigger = React.forwardRef<
HTMLButtonElement,
ChakraPagination.PrevTriggerProps
>(function PaginationPrevTrigger(props, ref) {
const { size, variantMap, getHref } = useRootProps();
const { previousPage } = usePaginationContext();
if (getHref) {
return (
<LinkButton
href={previousPage != null ? getHref(previousPage) : undefined}
variant={variantMap.default}
size={size}
_hover={{ bg: "#F5F8FB", color: "black" }}
>
<HiChevronLeft />
</LinkButton>
);
}
return (
<ChakraPagination.PrevTrigger ref={ref} asChild {...props}>
<IconButton variant={variantMap.default} size={size}>
<HiChevronLeft />
</IconButton>
</ChakraPagination.PrevTrigger>
);
});
export const PaginationNextTrigger = React.forwardRef<
HTMLButtonElement,
ChakraPagination.NextTriggerProps
>(function PaginationNextTrigger(props, ref) {
const { size, variantMap, getHref } = useRootProps();
const { nextPage } = usePaginationContext();
if (getHref) {
return (
<LinkButton
href={nextPage != null ? getHref(nextPage) : undefined}
variant={variantMap.default}
// size={size}
borderRadius="94px"
bg="#F5F8FB"
color="white"
w="136px"
fontSize="sm"
_hover={{ bg: "#026060" }}
>
Next
</LinkButton>
);
}
return (
<ChakraPagination.NextTrigger ref={ref} asChild {...props}>
<Text
w="136px"
// borderRadius="94px"
// bg="#02A0A0"
color="black"
// variant={variantMap.default}
// size={size}
cursor="pointer"
// _hover={{ bg: "#026060" }}
display="flex"
gap="12px"
alignItems="center"
fontSize="xs"
justifyContent="center"
>
Next
<HiChevronRight />
</Text>
</ChakraPagination.NextTrigger>
);
});
export const PaginationItems = (props: React.HTMLAttributes<HTMLElement>) => {
return (
<ChakraPagination.Context>
{({ pages }) =>
pages.map((page, index) => (
<PaginationItem
key={index}
type="page"
value={page.value}
{...props}
/>
))
}
</ChakraPagination.Context>
);
};
interface PageTextProps extends TextProps {
format?: "short" | "compact" | "long";
}
export const PaginationPageText = React.forwardRef<
HTMLParagraphElement,
PageTextProps
>(function PaginationPageText(props, ref) {
const { format = "compact", ...rest } = props;
const { page, totalPages, pageRange, count } = usePaginationContext();
const content = React.useMemo(() => {
if (format === "short") return `${page} / ${totalPages}`;
if (format === "compact") return `${page} of ${totalPages}`;
return `${pageRange.start + 1} - ${Math.min(pageRange.end, count)} of ${count}`;
}, [format, page, totalPages, pageRange, count]);
return (
<Text fontWeight="medium" ref={ref} {...rest}>
{content}
</Text>
);
});

View File

@@ -0,0 +1,39 @@
import { Switch as ChakraSwitch } from "@chakra-ui/react"
import * as React from "react"
export interface SwitchProps extends ChakraSwitch.RootProps {
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
rootRef?: React.Ref<HTMLLabelElement>
trackLabel?: { on: React.ReactNode; off: React.ReactNode }
thumbLabel?: { on: React.ReactNode; off: React.ReactNode }
}
export const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
function Switch(props, ref) {
const { inputProps, children, rootRef, trackLabel, thumbLabel, ...rest } =
props
return (
<ChakraSwitch.Root ref={rootRef} {...rest}>
<ChakraSwitch.HiddenInput ref={ref} {...inputProps} />
<ChakraSwitch.Control>
<ChakraSwitch.Thumb>
{thumbLabel && (
<ChakraSwitch.ThumbIndicator fallback={thumbLabel?.off}>
{thumbLabel?.on}
</ChakraSwitch.ThumbIndicator>
)}
</ChakraSwitch.Thumb>
{trackLabel && (
<ChakraSwitch.Indicator fallback={trackLabel.off}>
{trackLabel.on}
</ChakraSwitch.Indicator>
)}
</ChakraSwitch.Control>
{children != null && (
<ChakraSwitch.Label>{children}</ChakraSwitch.Label>
)}
</ChakraSwitch.Root>
)
},
)

View File

@@ -1,3 +1,8 @@
@import url('https://fonts.googleapis.com/css2?family=Oxygen:wght@300;400;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap');
*{
margin: 0;
padding: 0;
@@ -5,6 +10,17 @@
}
body {
margin: 0;
padding: 0;
font-family: "Roboto", serif;
}
.Oxygen{
font-family: "Oxygen", serif
}
.active {
background-color: #02A0A0 !important;
color: #fff !important;
@@ -116,3 +132,32 @@
right: 40%;
}
/* Style the scrollbar */
::-webkit-scrollbar {
width: 6px; /* Width of the vertical scrollbar */
height: 12px; /* Height of the horizontal scrollbar */
}
/* Style the scrollbar track (the background area) */
::-webkit-scrollbar-track {
background-color: #f1f1f1;
border-radius: 10px;
}
/* Style the scrollbar thumb (the draggable part) */
::-webkit-scrollbar-thumb {
background-color: #c8c8c8cf;
/* Gray color for the thumb */
border-radius: 10px;
border: 1px solid #f1f1f1; /* Border around the thumb */
}
/* Style the scrollbar thumb on hover */
::-webkit-scrollbar-thumb:hover {
background-color: #555; /* Darker gray when hovered */
}
input:focus-visible {
border: none !important;
}