Files
tanami-admin-panel/src/Pages/Admin/Notification.jsx

405 lines
11 KiB
React
Raw Normal View History

2024-09-20 18:04:22 +05:30
import React, { useContext, useEffect, useState } from "react";
import {
2024-10-02 18:41:38 +05:30
Badge,
2024-09-20 18:04:22 +05:30
Box,
2024-10-02 18:41:38 +05:30
Button,
2025-01-08 17:04:07 +05:30
HStack,
Input,
Select,
2024-10-02 18:41:38 +05:30
Text,
Tooltip,
2024-09-20 18:04:22 +05:30
useToast,
} from "@chakra-ui/react";
2025-01-08 17:04:07 +05:30
import { useForm } from "react-hook-form";
2024-09-20 18:04:22 +05:30
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import { useNavigate } from "react-router-dom";
import { OPACITY_ON_LOAD } from "../../Layout/animations";
import FormInputMain from "../../Components/FormInputMain";
import {
useGetContactQuery,
2024-10-05 20:14:59 +05:30
useSendNotificationMutation,
2024-09-20 18:04:22 +05:30
useUpdateContactMutation,
} from "../../Services/contact.service";
import FullscreenLoaders from "../../Components/Loaders/FullscreenLoaders";
import ToastBox from "../../Components/ToastBox";
2024-10-02 18:41:38 +05:30
import NormalTable from "../../Components/DataTable/NormalTable";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import { useGetInvestorsQuery } from "../../Services/investor.details.service";
import {
INVESTOR_TABLE_PAGINATION,
TABLE_PAGINATION,
} from "../../Constants/Paginations";
2024-10-05 20:14:59 +05:30
import { formatDate, generateSerialNumber } from "../../Constants/Constants";
2024-10-02 18:41:38 +05:30
import { ViewIcon } from "@chakra-ui/icons";
2024-10-05 20:14:59 +05:30
import { useGetUnbanInvestorQuery } from "../../Services/ban.investor.service";
2024-09-20 18:04:22 +05:30
export const notification = yup.object().shape({
2025-01-08 20:08:57 +05:30
title: yup.string().required("Notification Header is required"),
2024-09-20 18:04:22 +05:30
ManualDate: yup
.date()
.required("Manual Date is required")
.typeError("Invalid date format"),
ManualTime: yup
.string()
.required("Manual Time is required")
.matches(
/^([01]\d|2[0-3]):?([0-5]\d)$/,
"Invalid time format, must be in HH:mm"
),
2025-01-08 17:04:07 +05:30
expectedReturn: yup.string().required("Expected Return is required"),
2024-09-20 18:04:22 +05:30
});
2024-10-17 13:39:39 +05:30
export const notificationNew = yup.object().shape({
2025-01-08 20:08:57 +05:30
title: yup.string().required("Notification Header is required"),
message: yup.string().notRequired(),
2024-10-17 13:39:39 +05:30
});
2024-06-24 20:02:01 +05:30
const Notification = () => {
2024-09-20 18:04:22 +05:30
const toast = useToast();
const navigate = useNavigate();
const [form, setForm] = useState({});
const [isLoading, setIsLoading] = useState(false);
2025-01-08 17:04:07 +05:30
const [selectedRadio, setSelectedRadio] = useState([]);
2025-01-04 21:05:49 +05:30
const [pageSize, setPageSize] = useState(INVESTOR_TABLE_PAGINATION?.size);
const [currentPage, setCurrentPage] = useState(
INVESTOR_TABLE_PAGINATION?.page
);
2024-10-17 19:58:27 +05:30
const [searchTerm, setSearchTerm] = useState("");
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
2025-01-08 17:04:07 +05:30
const [country, setCountry] = useState("");
const [kyc, setKyc] = useState("");
2024-09-20 18:04:22 +05:30
const {
control,
reset,
2024-10-17 20:28:21 +05:30
watch,
2024-09-20 18:04:22 +05:30
handleSubmit,
formState: { errors },
} = useForm({
2024-10-17 13:39:39 +05:30
resolver: yupResolver(notificationNew),
2024-10-17 15:58:21 +05:30
2025-01-08 17:04:07 +05:30
defaultValues: {
title: "",
message: "",
},
2024-09-20 18:04:22 +05:30
});
console.log(errors);
2025-01-08 17:04:07 +05:30
2024-09-20 18:04:22 +05:30
const {
data: contact,
isLoading: contactLoading,
error,
} = useGetContactQuery();
2024-10-02 18:41:38 +05:30
2024-10-07 17:22:51 +05:30
const formatDate = (date) => {
return new Date(date).toLocaleDateString("en-GB", {
day: "2-digit",
month: "2-digit",
year: "numeric",
});
};
2024-10-05 20:14:59 +05:30
// const {
// data: investorDetails,
// isLoading: investorDetailsLoading,
// // error,
// } = useGetInvestorsQuery({ page: currentPage, size: pageSize });
2025-01-08 17:04:07 +05:30
useEffect(() => {
const handler = setTimeout(() => {
2025-01-08 19:51:35 +05:30
setDebouncedSearchTerm(searchTerm.trim()); // Trim to remove leading/trailing spaces
}, 300);
2025-01-08 17:04:07 +05:30
return () => clearTimeout(handler);
}, [searchTerm]);
2024-10-05 20:14:59 +05:30
const {
data: investorDetails,
isLoading: investorDetailsLoading,
refetch,
} = useGetUnbanInvestorQuery(
2025-01-08 17:04:07 +05:30
{
2025-01-08 19:51:35 +05:30
page: 1, // Omit pagination for search
2025-01-08 17:04:07 +05:30
size: 10000, // Omit pagination for search
2025-01-08 19:51:35 +05:30
// page: debouncedSearchTerm ? undefined : currentPage, // Disable pagination for search
// size: debouncedSearchTerm ? undefined : 10000 || pageSize || 500, // Disable pagination for search
search: debouncedSearchTerm, // Pass search term
2025-01-08 17:04:07 +05:30
country_xid: country,
KYCStatus: kyc,
},
{
2025-01-08 19:51:35 +05:30
skip: searchTerm !== "" && debouncedSearchTerm === "", // Skip if search not debounced yet
2025-01-08 17:04:07 +05:30
}
);
2024-10-17 19:58:27 +05:30
2025-01-08 19:51:35 +05:30
// useEffect(() => {
// console.log("Search Term:", searchTerm);
// console.log("Debounced Search Term:", debouncedSearchTerm);
// console.log("Investor Details:", investorDetails);
// }, [searchTerm, debouncedSearchTerm, investorDetails]);
2024-10-02 18:41:38 +05:30
2024-10-05 20:14:59 +05:30
const [sendNotification] = useSendNotificationMutation();
2024-09-20 18:04:22 +05:30
if (contactLoading) {
return <FullscreenLoaders />;
}
const formFields = [
{
2024-10-17 19:58:27 +05:30
label: "Notification Header",
2024-09-20 18:04:22 +05:30
placeHolder: " ",
2024-10-17 13:39:39 +05:30
name: "title",
2024-09-20 18:04:22 +05:30
type: "text",
2025-01-08 17:04:07 +05:30
width: "100%",
maxLength: 100,
helperText: `Maximum length should be 100 characters. You have entered ${
watch()?.title?.length || 0
} characters.`,
2024-09-20 18:04:22 +05:30
isRequired: true,
2024-10-17 19:58:27 +05:30
section: "Send Custom Push Notification",
2024-09-20 18:04:22 +05:30
// value: contact?.phoneNumber || "",
},
{
2024-10-17 19:58:27 +05:30
label: "Notification Message",
2024-09-20 18:04:22 +05:30
placeHolder: " ",
2024-10-17 13:39:39 +05:30
name: "message",
2025-01-08 17:04:07 +05:30
width: "100%",
2024-10-17 13:39:39 +05:30
type: "textarea",
2024-09-20 18:04:22 +05:30
isRequired: true,
2025-01-08 17:04:07 +05:30
maxLength: 200,
helperText: `Maximum length should be 200 characters. You have entered ${
watch()?.message?.length || 0
} characters.`,
2024-10-17 19:58:27 +05:30
section: "Send Custom Push Notification",
2024-10-17 13:39:39 +05:30
// value: contact?.phoneNumber || "",
2024-09-20 18:04:22 +05:30
},
];
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
groups[section] = [];
}
groups[section].push(field);
return groups;
}, {});
const onSubmit = async (data) => {
2024-10-02 18:41:38 +05:30
const dataToPass = {
...data,
2025-01-08 17:04:07 +05:30
principal_xid: selectedRadio,
};
2024-09-20 18:04:22 +05:30
setIsLoading(true);
try {
2024-10-05 20:14:59 +05:30
const res = await sendNotification(dataToPass);
2025-01-08 17:04:07 +05:30
2024-10-05 20:14:59 +05:30
if (res?.error) {
toast({
render: () => (
<ToastBox status={"error"} message={res?.error?.data?.message} />
),
});
2025-01-08 17:04:07 +05:30
setIsLoading(false);
} else if (res?.data) {
2024-10-05 20:14:59 +05:30
toast({
2025-01-08 17:04:07 +05:30
render: () => <ToastBox message={res?.data?.message} />,
2024-10-05 20:14:59 +05:30
});
2025-01-08 17:04:07 +05:30
setIsLoading(false);
setSelectedRadio([]);
2024-10-17 15:58:21 +05:30
reset({
2025-01-08 17:04:07 +05:30
title: "", // Resetting specific fields
message: "",
2024-10-17 15:58:21 +05:30
}); // Clears the form fields
2025-01-08 17:04:07 +05:30
} else {
2024-09-20 18:04:22 +05:30
toast({
2024-10-05 20:14:59 +05:30
render: () => (
2025-01-08 17:04:07 +05:30
<ToastBox status={"error"} message={"Something went wrong"} />
2024-10-05 20:14:59 +05:30
),
2024-09-20 18:04:22 +05:30
});
2025-01-08 17:04:07 +05:30
setIsLoading(false);
2024-09-20 18:04:22 +05:30
}
} catch (error) {
console.log(error);
setIsLoading(false);
}
2024-10-05 20:14:59 +05:30
};
2024-10-02 18:41:38 +05:30
// ====================================================[Table Setup]================================================================
const tableHeadRow = [
2024-10-05 20:14:59 +05:30
"Sr N/O",
"Date",
2024-10-02 18:41:38 +05:30
"Client ID",
"First Name",
"Last Name",
2024-10-05 20:14:59 +05:30
"Country",
2024-10-02 18:41:38 +05:30
"Phone Number",
"E-mail ID",
"KYC Status",
];
const extractedArray = investorDetails?.data?.rows?.map((item, idx) => ({
2024-10-05 20:14:59 +05:30
id: item?.principal_xid,
"Sr N/O": (
2024-10-02 18:41:38 +05:30
<Text
justifyContent={"left"}
as={"span"}
color={"gray.600"}
className="d-flex align-items-center fw-bold web-text-small"
>
2025-01-08 17:04:07 +05:30
{generateSerialNumber(idx, currentPage, pageSize)}
2024-10-02 18:41:38 +05:30
</Text>
),
2024-10-05 20:14:59 +05:30
Date: (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
{formatDate(item?.date)}
</Text>
</Box>
),
2024-10-02 18:41:38 +05:30
"Client ID": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
2024-10-05 20:14:59 +05:30
{item?.clientReference_id}
2024-10-02 18:41:38 +05:30
</Text>
2024-10-05 20:14:59 +05:30
</Box>
2024-10-02 18:41:38 +05:30
),
"First Name": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
2024-10-05 20:14:59 +05:30
{item?.firstName}
2024-10-02 18:41:38 +05:30
</Text>
</Box>
),
"Last Name": (
2024-10-05 20:14:59 +05:30
<Box w={"auto"} isTruncated={true}>
2024-10-02 18:41:38 +05:30
<Text as={"span"} color={"teal.900"}>
2024-10-05 20:14:59 +05:30
{item?.lastName}
2024-10-02 18:41:38 +05:30
</Text>
</Box>
),
Country: (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
2024-10-05 20:14:59 +05:30
{item?.country}
2024-10-02 18:41:38 +05:30
</Text>
</Box>
),
"Phone Number": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
2024-10-05 20:14:59 +05:30
{item?.phoneNumber}
2024-10-02 18:41:38 +05:30
</Text>
</Box>
),
"E-mail ID": (
<Box w={"auto"} isTruncated={true}>
<Text as={"span"} color={"teal.900"}>
2024-10-05 20:14:59 +05:30
{item?.emailAddress}
2024-10-02 18:41:38 +05:30
</Text>
</Box>
),
"KYC Status": (
2024-10-05 20:14:59 +05:30
<Box w={"auto"} isTruncated={true}>
<Badge
fontWeight={"500"}
2024-10-02 18:41:38 +05:30
textTransform={"none"}
2024-10-05 20:14:59 +05:30
color={item?.KYCStatus === false ? "red" : "blue"}
2024-10-02 18:41:38 +05:30
px={2}
py={0.5}
2025-01-08 17:04:07 +05:30
variant={"ghost"}
2024-10-02 18:41:38 +05:30
>
2025-01-08 17:04:07 +05:30
{item?.KYCStatus === true ? "Completed" : "Not Completed"}
2024-10-05 20:14:59 +05:30
</Badge>
2024-10-02 18:41:38 +05:30
</Box>
),
}));
2024-06-24 20:02:01 +05:30
return (
2024-09-20 18:04:22 +05:30
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
<FormInputMain
groupedFields={groupedFields}
control={control}
errors={errors}
onSubmit={handleSubmit(onSubmit)}
btnLoading={isLoading}
2024-10-02 18:41:38 +05:30
>
2025-01-08 17:04:07 +05:30
<HStack
display={"flex"}
justifyContent={"space-between"}
ps={1}
pe={1}
pb={4}
pt={4}
spacing="24px"
>
<Input
mt={1}
type="search"
width={300}
placeholder="Search..."
size="sm"
rounded="sm"
focusBorderColor="green.500"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<HStack className="col" justifyContent={"end"}>
<Select
w={250}
focusBorderColor="green.500"
size={"sm"}
fontSize={"xs"}
cursor={"pointer"}
onChange={(e) => setCountry(e.target.value)}
value={country}
>
<option value="" defaultValue={""} disabled hidden>
Country
</option>
<option value="">All</option>
<option value="1">Bahrain</option>
<option value="2">Kuwait</option>
<option value="3">Oman</option>
<option value="4">Qatar</option>
<option value="5">Saudi arabia</option>
<option value="6">United arab emirates</option>
</Select>
<Select
w={250}
focusBorderColor="green.500"
size={"sm"}
fontSize={"xs"}
cursor={"pointer"}
onChange={(e) => setKyc(e.target.value)}
value={kyc}
>
<option value="" defaultValue={""} disabled hidden>
KYC Status
</option>
<option value="">KYC Status</option>
<option value="0">Not Completed</option>
<option value="1">Completed</option>
</Select>
</HStack>
</HStack>
<Box overflow={"scroll"} h={"58vh"}>
<NormalTable
centered={true}
emptyMessage={`We don't have any Sponers `}
tableHeadRow={tableHeadRow}
data={extractedArray}
isLoading={investorDetailsLoading}
setSelectedRadio={setSelectedRadio}
selectedRadio={selectedRadio}
showRadioButton={true}
/>
</Box>
2024-10-02 18:41:38 +05:30
</FormInputMain>
2024-06-24 20:02:01 +05:30
</Box>
2024-09-20 18:04:22 +05:30
);
};
2024-06-24 20:02:01 +05:30
2024-09-20 18:04:22 +05:30
export default Notification;