Files
rubix-admin-panel/src/Pages/Community/Community.jsx
2024-05-07 12:47:06 +05:30

511 lines
15 KiB
JavaScript

import React, { useRef, useState } from "react";
import {
Avatar,
Box,
Link,
Tag,
Text,
WrapItem,
Tooltip,
Divider,
Stack,
HStack,
Input,
Button,
Select,
Image,
Menu,
MenuButton,
MenuList,
MenuItem,
Switch,
Portal,
useDisclosure,
AlertDialog,
AlertDialogOverlay,
AlertDialogContent,
AlertDialogHeader,
AlertDialogCloseButton,
AlertDialogBody,
AlertDialogFooter,
useToast,
Skeleton,
VStack,
} from "@chakra-ui/react";
import { GrAdd } from "react-icons/gr";
import { AddIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, HamburgerIcon } from "@chakra-ui/icons";
import DataTable from "../../Components/DataTable/DataTable";
import CommunityBanner from "../../Components/CommunityBanner";
import { OPACITY_ON_LOAD } from "../../Layout/animations";
import { v4 as uuidv4 } from "uuid";
import { Link as RouterLink } from "react-router-dom";
import {
useDeleteCommunityMutation,
useGetCommunityBannerQuery,
useGetCommunityByIdQuery,
useGetCommunityQuery,
useUpdateCommunityStatusMutation,
} from "../../Services/api.service";
import { HiDotsVertical } from "react-icons/hi";
import TimeCalculator from "../../Components/Functions/TimeCalculator";
import { formatDate } from "../../Components/Functions/UTCConvertor";
import CustomAlertDialog from "../../Components/CustomAlertDialog";
import WebButton from "../../Components/WebButton";
import CommunityCardDisplay from "./CommunityCardDisplay";
import CommunityBannerCard from "./CommunityBannerCard";
import Header from "../../Components/Header";
import { TABLE_PAGINATION } from "../../Constants/Paginations";
const Community = () => {
// ====================================================[Hooks]===================================================================
const cancelRef = useRef();
const toast = useToast();
const { isOpen, onOpen, onClose } = useDisclosure();
const [deleteAlert, setDeleteAlert] = useState(false);
const [actionId, setActionId] = useState(null);
const [deleteIsLoading, setDeleteIsLoading] = useState(false);
const [searchTerm, setSearchTerm] = useState("");
const [statusFilter, setStatusFilter] = useState("all");
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
const [currentPage, setCurrentPage] = useState(1);
const [displayRange, setDisplayRange] = useState({ start: TABLE_PAGINATION?.page, end: pageSize });
const community = useGetCommunityQuery({ page: currentPage, size: pageSize });
const [deleteCommunity] = useDeleteCommunityMutation();
const [updateCommunityStatus] = useUpdateCommunityStatusMutation();
// ====================================================[Functions]===================================================================
const handleDelete = async (communityId) => {
try {
// Trigger the mutation
setDeleteIsLoading(true);
await deleteCommunity(communityId)
.then((response) => {
// Handle the response here
console.log("Mutation response:", response?.data?.statusCode);
console.log("Mutation response:", response?.data?.message);
if (response?.data?.statusCode === 201) {
setDeleteIsLoading(false);
setDeleteAlert(false);
}
})
.catch((error) => {
console.error("Error creating community:", error);
setDeleteIsLoading(false);
setDeleteAlert(false);
});
} catch (error) {
// Handle errors
console.error("Error deleting community:", error);
}
};
const handleUpdateStatus = async (id) => {
try {
// Trigger the mutation
await updateCommunityStatus({ id })
.then((response) => {
console.log(response?.data);
if (response?.data?.statusCode === 201) {
console.log("toasted");
toast({
title: response?.data?.message,
status: "success",
isClosable: true,
});
}
})
.catch((error) => {
console.log(error);
});
} catch (error) {
// Handle errors
console.error("Error updating community status:", error);
}
};
// ====================================================[Table Filter]================================================================
const filteredData = community?.data?.data?.rows?.filter((item) => {
// Filter by name (case insensitive)
const name = item.member_name;
const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower);
// Filter by status
const status = item.status;
const statusLower = status ? "active" : "inactive";
const statusMatches =
statusFilter === "all" ||
(statusFilter === "active" && status === true) ||
(statusFilter === "inactive" && status === false);
return nameMatches && statusMatches;
});
// ====================================================[Table Setup]================================================================
const tableHeadRow = [
"Name",
"Discription",
"Linked In",
"Active",
"Created At",
];
const extractedArray = filteredData?.map((item, index) => {
return {
Name: (
<RouterLink
to={`view/${item.id}`}
className="d-flex align-items-center gap-2 pointer"
>
<Avatar
size="sm"
name="KC Reddy"
src={`https://rubix.betadelivery.com/${item.profile_image}`}
/>
<span className="d-flex flex-column">
<Text
as={"span"}
color={"teal.700"}
className="d-flex fw-bold align-items-center web-text-small"
>
{item?.member_name}
</Text>
<span className="d-flex align-items-center web-text-xsmall text-secondary">
{item?.designation}
</span>
</span>
</RouterLink>
),
Discription: (
<Text as={"span"} color={"teal.900"}>
{item?.description}
</Text>
),
"Linked In": (
<Link href={item?.linkedin} isExternal>
<Tooltip
className="rounded-2 web-text-xsmall"
width={"fit-content"}
placement="top"
hasArrow
label={item?.linkedin}
bg="blue.200"
>
<Tag
variant="solid"
size={"sm"}
borderRadius={2}
colorScheme="linkedin"
>
Linked In
</Tag>
</Tooltip>
</Link>
),
Active: (
<Switch
size={"sm"}
colorScheme="teal"
onChange={() => handleUpdateStatus(item.id)}
isChecked={item.status}
/>
),
"Created At": (
<span className="d-flex justify-content-between align-items-center">
<Text as={"span"} color={"teal.600"} className=" fw-bold">
{formatDate(item?.createdAt)}
</Text>
<Menu>
<MenuButton className="link p-1 rounded-1">
<HiDotsVertical className="rubix-text-dark fs-6" />
</MenuButton>
<Portal>
<MenuList minWidth="80px">
<RouterLink to={`edit/${item.id}`}>
<MenuItem className="web-text-medium">Edit</MenuItem>
</RouterLink>
<RouterLink to={`view/${item.id}`}>
<MenuItem className="web-text-medium">View</MenuItem>
</RouterLink>
<MenuItem
onClick={() => {
setActionId(item.id);
setDeleteAlert(true);
}}
className="web-text-medium"
>
Delete
</MenuItem>
</MenuList>
</Portal>
</Menu>
</span>
),
};
});
// ====================================================[Pagination Setup]================================================================
const paginationPrev = () => {
if (currentPage > 1) {
setCurrentPage(currentPage - 1);
updateDisplayRange(currentPage - 1);
}
};
const paginationNext = () => {
const totalPages = Math.ceil(community?.data?.data?.totalItems / pageSize);
if (currentPage < totalPages) {
setCurrentPage(currentPage + 1);
updateDisplayRange(currentPage + 1);
}
};
const updateDisplayRange = (page) => {
const start = (page - 1) * pageSize + 1;
const end = Math.min(start + pageSize - 1, community?.data?.data?.totalItems);
setDisplayRange({ start, end });
};
return (
<Box
{...OPACITY_ON_LOAD}
overflowY={"scroll"}
paddingBottom={50}
height={"100vh"}
>
<Header
title={"Community"}
btnTitle={"Create member"}
link={"/community/add-comunity"}
/>
<Box pt={4}>
{/* <HStack
display={"flex"}
justifyContent={"space-between"}
alignItems={"center"}
pe={1}
> */}
{/* <Text
as={"span"}
color={"teal.800"}
className="web-text-large fw-bold"
>
Community banner
</Text>
<RouterLink to="/community/add-banner">
<Button
leftIcon={<AddIcon />}
backgroundColor={"purple.700"}
_hover={{
backgroundColor: "purple.800",
}}
color={"whitesmoke"}
size="sm"
>
Create banner
</Button>
</RouterLink>
</HStack> */}
{/* <Box
display={"flex"}
// bg={"red.500"}
alignItems={"start"}
flexWrap={"wrap"}
justifyContent={"start"}
gap={3}
w={"100%"}
h={"auto"}
spacing="24px"
p={3}
> */}
{/* {communityBanner?.isLoading ? <Skeleton
h={"100%"}
w={"100%"}
borderRadius={6}/> :
<Box
bgImage={`https://rubix.betadelivery.com/${banner?.banner_image}`}
bgSize="cover"
bgPosition="center"
cursor={'pointer'}
h={"100%"}
w={"100%"}
borderRadius={6}
display={"flex"}
p={10}
justifyContent={"center"}
alignItems={"start"}
flexDirection={"column"}
position={'relative'}
>
<Text
mt={10}
w={400}
color={"white"}
className="fw-bolder"
as={"h1"}
>
{banner?.Heading}
</Text>
<Text
w={600}
color={"white"}
as={"p"}
className="fw-bolder web-text-large"
>
{banner?.sub_heading}
</Text>
<WebButton title={banner?.CTO_button_title} />
<Text opacity={0.3} position={'absolute'} bottom={0} right={4} className="web-text-small text-white">Last update: {formatDate(banner?.createdAt)}</Text>
</Box>} */}
{/* {communityBanner?.isLoading
? Array.from({ length: 3 }).map((_, index) => (
<Skeleton rounded={"md"} w={352} height={150} />
))
: banner?.map(
({
id,
CTO_button_title,
banner_image,
Heading,
createdAt,
sub_heading,
}) => (
<CommunityBannerCard
key={id}
bgImage={banner_image}
subHeading={sub_heading}
heading={Heading}
createdAt={createdAt}
ctoBtnTitle={CTO_button_title}
/>
)
)}
</Box>*/}
</Box>
{/* ====================================================[ Top bar ]================================================================ */}
{/* <Divider /> */}
<Box
bg="white.500"
>
{/* <HStack>
<Text color={"teal.800"} className="web-text-large fw-bold">
Community cards
</Text>
</HStack> */}
<HStack
display={"flex"}
justifyContent={"space-between"}
ps={1}
pe={1}
pb={4}
spacing="24px"
>
<Input
type="search"
width={300}
placeholder="Search..."
size="sm"
rounded="sm"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<HStack>
<Select
className="pointer web-text-small"
width={"90px"}
rounded="sm"
size="sm"
value={statusFilter}
onChange={(e) => setStatusFilter(e.target.value)}
>
<option value="all">All</option>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</Select>
<Select
className="pointer web-text-small"
width={"90px"}
rounded="sm"
size="sm"
value={pageSize}
onChange={(e) => setPageSize(e.target.value)}
>
<option value={pageSize}>{pageSize}</option>
{/* <option value={20}>20 rows</option>
<option value={30}>30 rows</option> */}
</Select>
<HStack>
<ChevronLeftIcon
onClick={paginationPrev}
className=" link rounded-3 pointer"
/>
<Text className="web-text-medium" as={"span"}>
{displayRange.start} - {displayRange.end} of{" "}
{community?.data?.data?.totalItems}
</Text>
<ChevronRightIcon
onClick={paginationNext}
className=" link rounded-3 pointer"
/>
</HStack>
</HStack>
</HStack>
</Box>
{/* ====================================================[ Table ]================================================================ */}
<DataTable
emptyMessage={"We don't have any blog for this author"}
tableHeadRow={tableHeadRow}
data={extractedArray}
isLoading={community?.isLoading}
/>
{/* <Divider /> */}
{/* <HStack>
<Text color={"teal.800"} className="web-text-large fw-bold">
Community cards
</Text>
</HStack>
<RouterLink to="/community-table-view">
<CommunityCardDisplay />
</RouterLink> */}
{/* ====================================================[ Alert ]================================================================ */}
<CustomAlertDialog
onClose={() => setDeleteAlert(false)}
isOpen={deleteAlert}
alertHandler={() => handleDelete(actionId)}
message={"Are you sure you want to delete member?"}
isLoading={deleteIsLoading}
/>
</Box>
);
};
export default Community;