Table Optimize 🙋♀️
This commit is contained in:
@@ -34,6 +34,11 @@ const craftedMsg = "Crafted with ❤️ by WDI Team for a better web.";
|
||||
<!-- <script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script> -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- <script>
|
||||
document.addEventListener('contextmenu', function (event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
</script> -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
#7a45fb,
|
||||
/* #764aaf67, */
|
||||
#de41b5
|
||||
); /* Gradient background */
|
||||
-webkit-background-clip: text; /* Clip text to the background area */
|
||||
|
||||
@@ -20,8 +20,8 @@ const DataTable = ({
|
||||
tableHeadRow,
|
||||
emptyMessage,
|
||||
centered,
|
||||
total,
|
||||
}) => {
|
||||
|
||||
console.log(data);
|
||||
|
||||
const columnWidth =
|
||||
@@ -29,30 +29,39 @@ const DataTable = ({
|
||||
? `${(100 / Object.keys(data[0]).length).toFixed(2)}%`
|
||||
: "auto";
|
||||
return (
|
||||
<TableContainer overflowX={"hidden"} className="h-auto mb-3 w-100">
|
||||
<TableContainer
|
||||
overflowX={"auto"}
|
||||
className="h-auto w-100 table-scroll"
|
||||
>
|
||||
{data?.length === 0 ? (
|
||||
<EmptySearchList message={emptyMessage} />
|
||||
) : (
|
||||
<Table size="sm">
|
||||
<TableCaption>Tanami v1.0.0</TableCaption>
|
||||
<Thead backgroundColor="gray.50">
|
||||
<TableCaption p={total ? 0 : null}>
|
||||
{total ? total : "OptiFii v1.0.0"}
|
||||
</TableCaption>
|
||||
<Thead
|
||||
// bgGradient="linear(to-r, gray.50, gray.50)"
|
||||
bg="#6311cb37"
|
||||
>
|
||||
<Tr>
|
||||
{tableHeadRow.map((heading, index) => (
|
||||
<Th
|
||||
color={"purple.900"}
|
||||
// fontSize={'sm'}
|
||||
textAlign={
|
||||
tableHeadRow.length - 1 === index || centered
|
||||
? "center"
|
||||
: "left"
|
||||
}
|
||||
key={index}
|
||||
p={3}
|
||||
width="20px" // Adjust width as needed
|
||||
color={"#004118"}
|
||||
p={4}
|
||||
// width="20px" // Adjust width as needed
|
||||
// color={"#fff"}
|
||||
whiteSpace="normal" // Allow text to wrap
|
||||
wordBreak="normal" // Ensure long words break properly
|
||||
overflowWrap="normal" // Break long words if necessary
|
||||
textTransform={'none'}
|
||||
|
||||
textTransform={"none"}
|
||||
>
|
||||
{isLoading ? <Skeleton height="20px" /> : heading}
|
||||
{/* {heading} */}
|
||||
@@ -62,26 +71,29 @@ const DataTable = ({
|
||||
</Thead>
|
||||
<Tbody className="web-text-small">
|
||||
{isLoading
|
||||
? Array.from({ length: TABLE_PAGINATION?.size }).map((_, index) => (
|
||||
<Tr key={index}>
|
||||
? Array.from({ length: TABLE_PAGINATION?.size }).map(
|
||||
(_, index) => (
|
||||
<Tr bg={index % 2 === 0 ? "" : "#6311cb14"} key={index}>
|
||||
{tableHeadRow.map((_, i) => (
|
||||
<Td
|
||||
width={'fit-content'}
|
||||
// width={"fit-content"}
|
||||
key={i}
|
||||
style={{
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
}}
|
||||
|
||||
className="web-text-small"
|
||||
w={columnWidth}
|
||||
// w={columnWidth}
|
||||
>
|
||||
<Skeleton height="20px" mb={1} mt={1} />
|
||||
</Td>
|
||||
))}
|
||||
</Tr>
|
||||
))
|
||||
)
|
||||
)
|
||||
: data?.map((item, index) => (
|
||||
<Tr key={index}>
|
||||
<Tr bg={index % 2 === 0 ? "" : "#6311cb14"} key={index}>
|
||||
{tableHeadRow.map((heading, i) => (
|
||||
<Td
|
||||
textAlign={
|
||||
@@ -91,6 +103,7 @@ const DataTable = ({
|
||||
}
|
||||
color={"gray.600"}
|
||||
key={i}
|
||||
fontWeight={500}
|
||||
style={{
|
||||
whiteSpace: "nowrap",
|
||||
textOverflow: "ellipsis",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Box, Image, Text } from "@chakra-ui/react"
|
||||
// import EmptySearchListImage from "../assets/empty_state_empty_folder.svg"
|
||||
import EmptySearchListImage from "../assets/EmptySearchList.png"
|
||||
// import EmptySearchListImage from "../assets/EmptySearchList.png"
|
||||
|
||||
const EmptySearchList = ({message}) => {
|
||||
return (
|
||||
@@ -11,7 +11,7 @@ const EmptySearchList = ({message}) => {
|
||||
flexDirection={'column'}
|
||||
w={"100%"} h={"40vh"}
|
||||
>
|
||||
<Image w={200} mb={8} src={EmptySearchListImage} alt='empty list' />
|
||||
{/* <Image w={200} mb={8} src={EmptySearchListImage} alt='empty list' /> */}
|
||||
{/* <Text className=" fw-bold fs-5" >{message}</Text> */}
|
||||
<Text className=" fw-bold fs-5" >We do not have any records</Text>
|
||||
{/* <Text as={'p'} className="web-text-medium">Posts of tanami will appear here.</Text> */}
|
||||
|
||||
@@ -49,7 +49,7 @@ const HeaderMain = ({
|
||||
return (
|
||||
<Box
|
||||
w={"100%"}
|
||||
h={"8%"}
|
||||
h={{base:"8%", lg:"6%"}}
|
||||
position={"relative"}
|
||||
className={` pt-2 pb-2 fw-400 border-bottom d-flex ${
|
||||
slideDirecttion ? " ps-2" : ""
|
||||
@@ -88,7 +88,7 @@ const HeaderMain = ({
|
||||
{isDrawerOpen ? (
|
||||
<ArrowLeftIcon className="web-text-small" color={"#6311CB"} />
|
||||
) : (
|
||||
<ArrowRightIcon className="web-text-small " />
|
||||
<ArrowRightIcon className="web-text-small " color={"#6311CB"} />
|
||||
)}
|
||||
</Button>
|
||||
</Box>
|
||||
@@ -108,15 +108,15 @@ const HeaderMain = ({
|
||||
</InputGroup>
|
||||
</Box>
|
||||
<Box display={"flex"} justifyContent={"space-between"}>
|
||||
<Box display={"flex"}>
|
||||
<Box me={10}>
|
||||
<Button bg={"none"} p={0}>
|
||||
<Box display={"flex"} gap={2}>
|
||||
<Box display={"flex"} gap={2} alignItems={'center'} me={10}>
|
||||
<Button size={'sm'} bg={"none"} p={0}>
|
||||
<MdOutlineHeadsetMic fontSize={"18px"} />
|
||||
</Button>
|
||||
<Button bg={"none"} p={0}>
|
||||
<Button size={'sm'} bg={"none"} p={0}>
|
||||
<RiWallet3Line fontSize={"18px"} />
|
||||
</Button>
|
||||
<Button bg={"none"} p={0}>
|
||||
<Button size={'sm'} bg={"none"} p={0}>
|
||||
<MdNotificationsNone fontSize={"20px"} />
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
@@ -1,33 +1,48 @@
|
||||
import { ArrowBackIcon } from '@chakra-ui/icons';
|
||||
import { Box, HStack, Icon, Text, VStack } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ArrowBackIcon } from "@chakra-ui/icons";
|
||||
import { Box, HStack, Icon, Text, VStack } from "@chakra-ui/react";
|
||||
import React from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const MiniHeader = ({title, subTitle, backButton}) => {
|
||||
const navigate = useNavigate()
|
||||
const MiniHeader = ({ title, subTitle, backButton }) => {
|
||||
const navigate = useNavigate();
|
||||
const [firstPart, secondPart] = title.split(/ (.+)/);
|
||||
|
||||
return (
|
||||
<HStack gap={3}>
|
||||
{backButton&&<Icon onClick={()=> navigate(-1)} as={ArrowBackIcon} boxSize={7} bg={'#fff'} p={1} rounded={'full'} />}
|
||||
<VStack alignItems={'start'} gap={1} >
|
||||
<Box as='span' display={'flex'} gap={2}>
|
||||
<Text fontSize={'lg'} as={'span'} fontWeight={600}>
|
||||
<HStack gap={3} mb={4}>
|
||||
{backButton && (
|
||||
<Icon
|
||||
cursor={"pointer"}
|
||||
onClick={() => navigate(-1)}
|
||||
as={ArrowBackIcon}
|
||||
boxSize={7}
|
||||
bg={"#fff"}
|
||||
p={1}
|
||||
rounded={"full"}
|
||||
/>
|
||||
)}
|
||||
<VStack alignItems={"start"} gap={1}>
|
||||
<Box as="span" display={"flex"} gap={2}>
|
||||
<Text fontSize={"lg"} as={"span"} fontWeight={600}>
|
||||
{firstPart}
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
bgGradient='linear(to-l, #3725EA, #5E0FCD)'
|
||||
bgClip='text' fontSize={'lg'} as={'span'} fontWeight={600}>
|
||||
bgGradient="linear(to-l, #3725EA, #5E0FCD)"
|
||||
bgClip="text"
|
||||
fontSize={"lg"}
|
||||
as={"span"}
|
||||
fontWeight={600}
|
||||
>
|
||||
{secondPart}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Text fontSize={'xs'} color={'gray.500'} fontWeight={500} as={'span'}>{subTitle}</Text>
|
||||
|
||||
<Text fontSize={"xs"} color={"gray.500"} fontWeight={500} as={"span"}>
|
||||
{subTitle}
|
||||
</Text>
|
||||
</VStack>
|
||||
</HStack>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default MiniHeader
|
||||
export default MiniHeader;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -321,8 +321,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
height={"100vh"}>
|
||||
<Box height={"100vh"}>
|
||||
<HeaderMain
|
||||
isDrawerOpen={isDrawerOpen}
|
||||
logOutHandler={logOutHandler}
|
||||
@@ -331,8 +330,8 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
title={getTitle()}
|
||||
/>
|
||||
<Box
|
||||
h={{ base: "92%", lg: "96%" }}
|
||||
style={{
|
||||
height: "92%",
|
||||
width: "100%",
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
@@ -390,9 +389,13 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
({ title, type, Icon, submenu, path, colorCode }, index) => {
|
||||
if (type === "accordion") {
|
||||
return (
|
||||
<AccordionItem key={index} border={"none"} style={{borderRadius:"2px", marginBottom:"8px"}}>
|
||||
<AccordionItem
|
||||
key={index}
|
||||
border={"none"}
|
||||
style={{ borderRadius: "2px", marginBottom: "8px" }}
|
||||
>
|
||||
<AccordionButton
|
||||
style={{ height: "auto", borderRadius:"2px" }}
|
||||
style={{ height: "auto", borderRadius: "2px" }}
|
||||
_hover={{ bg: "#ced8e6a2" }}
|
||||
className={`${
|
||||
true
|
||||
@@ -400,7 +403,9 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
: "p-2 ps-1 web-text-xlarge justify-content-center"
|
||||
} link d-flex align-items-center gap-2 w-100 mb-1`}
|
||||
>
|
||||
<NavLink to="/home" as="span"
|
||||
<NavLink
|
||||
to="/home"
|
||||
as="span"
|
||||
className="d-flex align-items-centre gap-2 w-50 py-1"
|
||||
>
|
||||
{/* {Icon && title === "Admin" ? <Image w={15} src={shield} /> : <Icon className={`web-text-large`} />} */}
|
||||
@@ -451,7 +456,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
} d-flex align-items-center p-0`}
|
||||
>
|
||||
<NavLink
|
||||
style={{borderRadius:"2px"}}
|
||||
style={{ borderRadius: "2px" }}
|
||||
className={`${
|
||||
true
|
||||
? "p-2 ps-1 ms-2 web-text-medium "
|
||||
@@ -495,7 +500,11 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
return (
|
||||
<NavLink
|
||||
key={index}
|
||||
style={{ height: "auto", position: "relative", borderRadius:"2px" }}
|
||||
style={{
|
||||
height: "auto",
|
||||
position: "relative",
|
||||
borderRadius: "2px",
|
||||
}}
|
||||
className={`${
|
||||
true
|
||||
? "p-2 web-text-medium"
|
||||
@@ -523,15 +532,17 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<main
|
||||
className={` d-flex flex-column gap-0 `}
|
||||
<Box
|
||||
style={{
|
||||
width: `calc(100% - ${isDrawerOpen ? 230 : 0}px)`,
|
||||
transition: "width 0.3s ease-in-out",
|
||||
backgroundColor:"#F3F3F9"
|
||||
backgroundColor: "#F3F3F9",
|
||||
display:'flex',
|
||||
flexDirection:'column',
|
||||
gap:0
|
||||
}}
|
||||
>
|
||||
{/* <HeaderMain
|
||||
{/* <HeaderBox
|
||||
slideDirecttion={slideFromRight}
|
||||
logOutHandler={logOutHandler}
|
||||
icon
|
||||
@@ -541,7 +552,7 @@ const DashboardLayout = ({ isOnline }) => {
|
||||
{/* <CustomBreadcrumb /> */}
|
||||
|
||||
<AppContent />
|
||||
</main>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1,14 +1,184 @@
|
||||
import { Box } from "@chakra-ui/react";
|
||||
import React from "react";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Divider,
|
||||
HStack,
|
||||
Icon,
|
||||
Tag,
|
||||
TagLabel,
|
||||
Text,
|
||||
VStack,
|
||||
} from "@chakra-ui/react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import MiniHeader from "../../Components/MiniHeader";
|
||||
import GlobalStateContext from "../../Contexts/GlobalStateContext";
|
||||
import NormalTable from "../../Components/DataTable/NormalTable";
|
||||
import { CalendarIcon, EmailIcon, ViewIcon } from "@chakra-ui/icons";
|
||||
import { OPACITY_ON_LOAD } from "../../Layout/animations";
|
||||
import { MdNotificationsNone, MdOutlineHeadsetMic } from "react-icons/md";
|
||||
import { RiDeleteBin5Line, RiWallet3Line } from "react-icons/ri";
|
||||
import { AiOutlineEdit } from "react-icons/ai";
|
||||
import { FaRegEye } from "react-icons/fa";
|
||||
import { PiReceipt } from "react-icons/pi";
|
||||
|
||||
const Report = () => {
|
||||
const { reportsHistory } = useContext(GlobalStateContext);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Set isLoading to true
|
||||
setIsLoading(true);
|
||||
|
||||
// Simulate a 3-second delay
|
||||
const timer = setTimeout(() => {
|
||||
setIsLoading(false); // Set isLoading to false after 3 seconds
|
||||
}, 500);
|
||||
|
||||
// Cleanup the timer when the component unmounts or when the useEffect re-runs
|
||||
return () => clearTimeout(timer);
|
||||
}, []); // Empty dependency array means this effect runs once after the component mounts
|
||||
|
||||
// ===============================[ Table Header ]
|
||||
const tableHeadRow = [
|
||||
"Name",
|
||||
"Last Update",
|
||||
"Report type",
|
||||
"Total Expense",
|
||||
"Status",
|
||||
"Actions",
|
||||
];
|
||||
|
||||
// const extractedArray = reportsHistory.map((item)=>({ }))
|
||||
|
||||
const extractedArray = reportsHistory.map((item, index) => ({
|
||||
Name: <Text as={'span'} display={'flex'} gap={2} alignItems={'center'}>
|
||||
<Icon as={PiReceipt} boxSize={8} p={1.5} bg={index % 2 === 0 ? "#6311cb14" : "#fff"} rounded={'full'} />{item?.name}</Text>,
|
||||
"Last Update":
|
||||
item?.lastUpdated,
|
||||
"Report type": item?.reportType,
|
||||
"Total Expense": item?.totalExpense,
|
||||
Status: (
|
||||
<Tag
|
||||
my={1}
|
||||
size={"sm"}
|
||||
borderRadius="full"
|
||||
colorScheme={
|
||||
item?.status === "Approved"
|
||||
? "green"
|
||||
: item?.status === "Fully Reimbursed"
|
||||
? "purple"
|
||||
: item?.status === "Disapproved"
|
||||
? "red"
|
||||
: item?.status === "Saved"
|
||||
? "yellow"
|
||||
: item?.status === "Partially Reimbursed"
|
||||
? "orange"
|
||||
: "gray" // default color scheme if status doesn't match any condition
|
||||
}
|
||||
border={`1px solid ${
|
||||
item?.status === "Approved"
|
||||
? "green"
|
||||
: item?.status === "Fully Reimbursed"
|
||||
? "purple"
|
||||
: item?.status === "Disapproved"
|
||||
? "red"
|
||||
: item?.status === "Saved"
|
||||
? "orange"
|
||||
: item?.status === "Partially Reimbursed"
|
||||
? "orange"
|
||||
: "gray" // default border color if status doesn't match any condition
|
||||
}`}
|
||||
p={1}
|
||||
px={3}
|
||||
>
|
||||
<TagLabel>{item?.status}</TagLabel>
|
||||
</Tag>
|
||||
),
|
||||
Actions: (
|
||||
<Box
|
||||
display={"flex"}
|
||||
gap={1}
|
||||
alignItems={"center"}
|
||||
justifyContent={"center"}
|
||||
>
|
||||
<Button _hover={{ color:"gray.800", bg:"gray.100"}} transition={'0.5s'} size={"sm"} bg={"none"} p={0} color="gray.600">
|
||||
<FaRegEye fontSize={"18px"} />
|
||||
</Button>
|
||||
<Button _hover={{ color:"gray.800", bg:"gray.100"}} transition={'0.5s'} size={"sm"} bg={"none"} p={0} color="gray.600">
|
||||
<AiOutlineEdit fontSize={"19px"} />
|
||||
</Button>
|
||||
<Button _hover={{ color:"gray.800", bg:"gray.100"}} transition={'0.5s'} size={"sm"} bg={"none"} p={0} color="gray.600">
|
||||
<RiDeleteBin5Line fontSize={"18px"} />
|
||||
</Button>
|
||||
</Box>
|
||||
),
|
||||
}));
|
||||
|
||||
return (
|
||||
<Box h={"100%"} p={6}>
|
||||
<Box {...OPACITY_ON_LOAD} p={4} overflowX={"scroll"}>
|
||||
<MiniHeader
|
||||
title={"Reports History"}
|
||||
subTitle={"Lorem ipsum dolor sit amet, consectetur adipiscing elit."}
|
||||
backButton={true}
|
||||
/>
|
||||
|
||||
<Box
|
||||
rounded={"xl"}
|
||||
py={3}
|
||||
// pb={0}
|
||||
display={"flex"}
|
||||
flexDirection={"column"}
|
||||
bg={"#fff"}
|
||||
shadow={"md"}
|
||||
minH={"100%"}
|
||||
>
|
||||
<VStack mb={0} px={3} alignItems={"start"} gap={0}>
|
||||
<Text fontSize={"lg"} fontWeight={600}>
|
||||
Reports
|
||||
</Text>
|
||||
<HStack w={"100%"} justifyContent={"space-between"}>
|
||||
<Button
|
||||
fontWeight={500}
|
||||
size={"sm"}
|
||||
leftIcon={<CalendarIcon color={"purple.800"} />}
|
||||
colorScheme="gray"
|
||||
color={"gray.700"}
|
||||
variant="outline"
|
||||
fontSize={"xs"}
|
||||
>
|
||||
Select Date Range
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
_hover={{
|
||||
// bgGradient: "linear(to-r, #5E0FCD, #3725EA)",
|
||||
opacity: 0.8,
|
||||
}}
|
||||
bgGradient="linear(to-r, #3725EA, #5E0FCD)"
|
||||
fontSize={"xs"}
|
||||
px={8}
|
||||
fontWeight={500}
|
||||
size={"sm"}
|
||||
color={"#fff"}
|
||||
variant="outline"
|
||||
transition={"0.5s all"}
|
||||
_active={{
|
||||
// bgGradient: "linear(to-r, #5E0FCD, #3725EA)",
|
||||
opacity: 1,
|
||||
}}
|
||||
>
|
||||
Add to Report
|
||||
</Button>
|
||||
</HStack>
|
||||
</VStack>
|
||||
<Divider />
|
||||
<NormalTable
|
||||
emptyMessage={`We don't have any Sponers `}
|
||||
tableHeadRow={tableHeadRow}
|
||||
data={extractedArray}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ const Requests = () => {
|
||||
<MiniHeader
|
||||
title={"My Requests"}
|
||||
subTitle={"Lorem ipsum dolor sit amet, consectetur adipiscing elit."}
|
||||
backButton={true}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user