mirror of
https://github.com/WDI-Ideas/rubix-admin-panel.git
synced 2026-04-28 00:05:51 +00:00
511 lines
15 KiB
JavaScript
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;
|