InvestType sponsers Api

This commit is contained in:
YasinShaikh123
2024-07-24 19:57:31 +05:30
parent 83e3bb2679
commit fe03ce3944
12 changed files with 619 additions and 586 deletions

View File

@@ -33,7 +33,7 @@ const CustomAlertDialog = ({ isOpen, onOpen, onClose, alertHandler, isLoading, m
onClick={alertHandler}
size={"sm"}
rounded={'sm'}
colorScheme="green"
colorScheme="forestGreen"
ml={3}
>
Yes

View File

@@ -15,7 +15,8 @@ const FormInputMain = ({
submitTitle,
p,
w,
btnLoading
btnLoading,
btnhidden,
}) => {
return (
<Box mt={0} as="form" onSubmit={onSubmit}>
@@ -25,67 +26,67 @@ const FormInputMain = ({
{/* <ArrowBackIcon fontSize={'lg'} /> */}
{section}
</Heading>
<Box
as="span"
width={"100%"}
p={p ? p : 5}
display={"flex"}
flexWrap={"wrap"}
gap={4}
>
{fields.map(
(
{
label,
name,
id,
arabic,
type,
isRequired,
selectedImageData,
setSelectedImageData,
imageData,
handleImageChange,
removeImage,
placeHolder,
options,
helperText,
multiple,
width,
},
key
) => (
<FormField
id={id}
key={key}
label={label}
type={type}
name={name}
helperText={helperText ? helperText : undefined}
options={options ? options : undefined}
placeHolder={placeHolder ? placeHolder : undefined}
control={control}
errors={errors}
multiple={multiple}
isRequired={isRequired}
arabic={arabic}
selectedImageData={selectedImageData}
setSelectedImageData={setSelectedImageData}
imageData={imageData}
handleImageChange={handleImageChange}
removeImage={removeImage}
width={width}
/>
)
)}
</Box>
<Box
as="span"
width={"100%"}
p={p ? p : 5}
display={"flex"}
flexWrap={"wrap"}
gap={4}
>
{fields.map(
(
{
label,
name,
id,
arabic,
type,
isRequired,
selectedImageData,
setSelectedImageData,
imageData,
handleImageChange,
removeImage,
placeHolder,
options,
helperText,
multiple,
width,
},
key
) => (
<FormField
id={id}
key={key}
label={label}
type={type}
name={name}
helperText={helperText ? helperText : undefined}
options={options ? options : undefined}
placeHolder={placeHolder ? placeHolder : undefined}
control={control}
errors={errors}
multiple={multiple}
isRequired={isRequired}
arabic={arabic}
selectedImageData={selectedImageData}
setSelectedImageData={setSelectedImageData}
imageData={imageData}
handleImageChange={handleImageChange}
removeImage={removeImage}
width={width}
/>
)
)}
</Box>
{index < Object.entries(groupedFields).length - 1 && <Divider />}
</Box>
))}
{children}
<Box display={"flex"} justifyContent={"end"} mt={2} >
<Box display={"flex"} justifyContent={"end"} mt={2}>
<Box display={"flex"} justifyContent={"end"} p={2} w={"49%"} gap={4}>
{onCancle && (
<Button
@@ -99,17 +100,21 @@ const FormInputMain = ({
Cancel
</Button>
)}
<Button
isLoading={btnLoading}
size={"sm"}
width={w ? w : "44.5%"}
rounded={"sm"}
spinner={<Spinner size='sm' color='white' />}
type="submit"
colorScheme={"forestGreen"}
>
{submitTitle ? submitTitle : "Submit"}
</Button>
{btnhidden ? (
""
) : (
<Button
isLoading={btnLoading}
size={"sm"}
width={w ? w : "44.5%"}
rounded={"sm"}
spinner={<Spinner size="sm" color="white" />}
type="submit"
colorScheme={"forestGreen"}
>
{submitTitle ? submitTitle : "Submit"}
</Button>
)}
</Box>
</Box>
</Box>

View File

@@ -1,4 +1,12 @@
export const getFileNameFromPath = (filePath) => {
const parts = filePath.split('/');
return parts[parts.length - 1];
};
const parts = filePath.split("/");
return parts[parts.length - 1];
};
export function debounce(func, delay) {
let debounceTimer;
return function (...args) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => func.apply(this, args), delay);
};
}

View File

@@ -102,7 +102,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id }) => {
<Drawer
isOpen={isOpen}
placement="right"
initialFocusRef={firstField}
initialFocusRef={firstField}
onClose={onClose}
>
<DrawerOverlay />
@@ -180,7 +180,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id }) => {
</Button>
<Button
colorScheme={"green"}
colorScheme={"forestGreen"}
rounded={"sm"}
size={"sm"}
onClick={() => setAlert(true)}

View File

@@ -1,28 +1,30 @@
import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import { Box, useToast } from "@chakra-ui/react";
import { Box, Button, useToast } from "@chakra-ui/react";
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import { useNavigate, useParams } from "react-router-dom";
import FormInputMain from "../../../Components/FormInputMain";
import SwitchButton from "../../../Components/SwitchButton";
import {
useCreateInvestmentTypeMutation,
import {useCreateInvestmentTypeMutation,
useGetInvestmentTypeByIdQuery,
useUpdateInvestmentTypeMutation,
} from "../../../Services/investment.type.service";
import ToastBox from "../../../Components/ToastBox";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
// ======================= [validation] =========================
export const addInvestmentType = yup.object().shape({
investmentTypeName: yup.string().required("Investment name is required"),
note: yup.string().required("Description is required"),
investmentTypeNameArabic: yup
.string()
.required("Investment name is required"),
investmentTypeNameArabic: yup.string().required("Investment name is required"),
noteArabic: yup.string().required("Description is required"),
});
// ==================== [debounce] ========================
export function debounce(func, delay) {
let debounceTimer;
return function (...args) {
@@ -32,59 +34,132 @@ export function debounce(func, delay) {
}
const AddInvestmentType = () => {
const navigate = useNavigate();
const toast = useToast();
const params = useParams();
const id = params?.id;
console.log('hit');
// =====================[useState]=======================
const [isSwitchOn, setIsSwitchOn] = useState(false);
const [isLoadingBtn, setIsLoadingBtn] = useState(false);
const [otherImageData, setOtherImageData] = useState(null);
const [selectedOtherImageData, setSelectedOtherImageData] = useState(null);
const [alert, setAlert] = useState(false);
const [form, setForm] = useState();
const [createInvestmentType] = useCreateInvestmentTypeMutation();
const [updateInvestmentType] = useUpdateInvestmentTypeMutation();
// ======================== [validators] ===========================
const {
control,
handleSubmit,
formState: { errors },
reset,
} = useForm({
resolver: yupResolver(addInvestmentType),
});
const id = params?.id;
const {data: investmentTypeByIdData,error,isLoading,} = useGetInvestmentTypeByIdQuery(id, { skip: !id });
const {
data: investmentTypeByIdData,
error,
isLoading,
} = useGetInvestmentTypeByIdQuery(id, {
skip: !id,
});
console.log(investmentTypeByIdData);
console.log(id);
// ========================== [useEffect] ================================
useEffect(() => {
if (investmentTypeByIdData?.data) {
reset({
investmentTypeName: investmentTypeByIdData?.data?.investmentTypeName,
investmentTypeNameArabic: investmentTypeByIdData?.data?.investmentTypeNameArabic,
investmentTypeNameArabic:
investmentTypeByIdData?.data?.investmentTypeNameArabic,
note: investmentTypeByIdData?.data?.note,
noteArabic: investmentTypeByIdData?.data?.noteArabic,
// email: investmentTypeByIdData?.data?.email,
});
}
}, [investmentTypeByIdData, reset]);
if (false) {
return <FullscreenLoaders />;
}
// ============================ [API]===============================
const handleConfirm = async () => {
setIsLoadingBtn(true);
const id = params?.id;
if (id) {
try {
const formData = {
...form,
isActive: isSwitchOn,
};
await updateInvestmentType({ data: formData, id }).then((response) => {
if (response?.data?.statusCode === 200) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
setIsLoadingBtn(false);
setAlert(false);
navigate("/investment-type");
} else {
toast({
render: () => (
<ToastBox message={"Something Went Wrong"} status={"error"} />
),
});
setIsLoadingBtn(false);
navigate("/investment-type");
}
});
} catch (error) {
console.log(error);
setIsLoadingBtn(false);
navigate("/investment-type");
}
} else {
try {
const formData = {
...form,
isActive: isSwitchOn,
};
await createInvestmentType(formData).then((response) => {
if (response?.data?.statusCode === 201) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
setIsLoadingBtn(false);
navigate("/investment-type");
} else {
toast({
render: () => (
<ToastBox message={"Something Went Wrong"} status={"error"} />
),
});
setIsLoadingBtn(false);
navigate("/investment-type");
}
});
} catch (error) {
console.log(error);
setIsLoadingBtn(false);
navigate("/investment-type");
}
}
};
// ====================== [Update Form Object] =========================
console.log("hit");
const formFields = [
{
label: "Investment Type (English)",
@@ -122,6 +197,8 @@ const AddInvestmentType = () => {
},
];
// ==================== [Create Form Object] =======================
const formEditFields = [
{
label: "Investment Type (English) *",
@@ -159,6 +236,8 @@ const AddInvestmentType = () => {
},
];
// ====================== [Group Create Fields] =========================
const groupedEditFields = formEditFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
@@ -168,6 +247,8 @@ const AddInvestmentType = () => {
return groups;
}, {});
// ====================== [Group Update Fields] =======================
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
@@ -177,79 +258,48 @@ const AddInvestmentType = () => {
return groups;
}, {});
// ==================== [On Submit] ========================
const onSubmit = async (data) => {
setIsLoadingBtn(true);
console.log(data);
const id = params?.id;
if (id) {
try {
await updateInvestmentType({ data, id }).then((response) => {
if (response?.data?.statusCode === 200) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
setIsLoadingBtn(false);
navigate("/investment-type");
} else {
toast({
render: () => (
<ToastBox message={"Something Went Wrong"} status={"error"} />
),
});
setIsLoadingBtn(false);
navigate("/investment-type");
}
});
} catch (error) {
console.log(error);
setIsLoadingBtn(false);
navigate("/investment-type");
}
} else {
try {
await createInvestmentType(data).then((response) => {
if (response?.data?.statusCode === 201) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
setIsLoadingBtn(false);
navigate("/investment-type");
} else {
toast({
render: () => (
<ToastBox message={"Something Went Wrong"} status={"error"} />
),
});
setIsLoadingBtn(false);
navigate("/investment-type");
}
});
} catch (error) {
console.log(error);
setIsLoadingBtn(false);
navigate("/investment-type");
}
}
// setIsLoadingBtn(true);
if (Object.keys(errors).length === 0) {
setForm(data);
setAlert(true);
}
};
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
{/* ===================== [Switch Button] ======================== */}
<Box mt={5} display={"flex"} justifyContent={"right"} mr={5}>
<SwitchButton isSwitchOn={isSwitchOn} setIsSwitchOn={setIsSwitchOn} />
</Box>
{/* ====================== [Form Input] ====================== */}
<FormInputMain
groupedFields={params?.id ? groupedEditFields : groupedFields}
control={control}
errors={errors}
onSubmit={handleSubmit(onSubmit)}
submitTitle={params?.id ? "Update" : "Submit"}
btnLoading={isLoadingBtn}
// btnLoading={isLoadingBtn}
>
</FormInputMain>
{/* ======================= [Modal] =========================== */}
<CustomAlertDialog
isOpen={alert}
onClose={() => setAlert(false)}
alertHandler={handleConfirm}
message={"Are you sure you want to add this?"}
isLoading={isLoadingBtn}
/>
</Box>
);
};

View File

@@ -1,104 +1,57 @@
import {
Avatar,
Badge,
Box,
Button,
HStack,
Input,
Menu,
MenuButton,
MenuItem,
MenuList,
Portal,
Select,
Switch,
Tag,
Text,
Tooltip,
useToast,
} from "@chakra-ui/react";
import {Badge,Box,Button,HStack,Input,Text,Tooltip,useToast,} from "@chakra-ui/react";
import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import { HiDotsVertical } from "react-icons/hi";
import { Link, Link as RouterLink, useNavigate } from "react-router-dom";
import {
AddIcon,
CheckIcon,
CloseIcon,
DeleteIcon,
EditIcon,
EmailIcon,
ViewIcon,
} from "@chakra-ui/icons";
import {AddIcon,DeleteIcon,EditIcon,ViewIcon,} from "@chakra-ui/icons";
import Pagination from "../../../Components/Pagination";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
import ToastBox from "../../../Components/ToastBox";
import { debounce } from "./AddInvestmentType";
import DataTable from "../../../Components/DataTable/DataTable";
import SwitchButton from "../../../Components/SwitchButton";
import { useGetInvestmentTypesQuery } from "../../../Services/investment.type.service";
import {useDeleteInvestmentTypeMutation,useGetInvestmentTypesQuery,} from "../../../Services/investment.type.service";
const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
const InvestmentType = () => {
const navigate = useNavigate();
const toast = useToast();
const { investmentType, setInvestmentType, slideFromRight } =
useContext(GlobalStateContext);
// ======================== [Use State] =========================
const [searchTerm, setSearchTerm] = useState("");
const [isLoading, setIsLoading] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [deleteAlert, setDeleteAlert] = useState(false);
const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
const [isSwitchOn, setIsSwitchOn] = useState(false);
const { investmentType, setInvestmentType, slideFromRight } =
useContext(GlobalStateContext);
const {
data: investmentTypes,
isLoading: investmentTypesLoading,
error,
} = useGetInvestmentTypesQuery({ page: 1, size: 10 })
const [deleteInvestmentType] = useDeleteInvestmentTypeMutation();
const {data: investmentTypes,isLoading: investmentTypesLoading,error,} = useGetInvestmentTypesQuery({ page: 1, size: 10 });
console.log(investmentTypes?.data?.rows);
// ========= [Toggle ToastBox] =======
// const handleUpdateStatus = debounce((id) => {
// setInvestmentType((prevInvestmentType) =>
// prevInvestmentType.map((investmentType) =>
// investmentType.id === id
// ? { ...investmentType, status: !investmentType.status }
// : investmentType
// )
// );
// toast({
// render: () => <ToastBox message={"Status changed succesfully.!"} />,
// });
// }, 300);
useEffect(() => {
// Simulate loading
const timer = setTimeout(() => {
setIsLoading(false);
}, 1500);
// ===========================[Table Filter]=============================
// Cleanup the timer on component unmount
return () => clearTimeout(timer);
}, []);
// ====================================================[Table Setup]================================================================
const tableHeadRow = [
"Sr.no",
"Investment Type",
"Description",
"Action",
];
const handleUpdateStatus = debounce((id) => {
setInvestmentType((prevInvestmentType) =>
prevInvestmentType.map((investmentType) =>
investmentType.id === id
? { ...investmentType, status: !investmentType.status }
: investmentType
)
);
toast({
render: () => <ToastBox message={"Status changed succesfully.!"} />,
});
}, 300);
// ====================================================[Table Filter]================================================================
const filteredData = investmentTypes?.data?.rows?.filter((item) => {
// Filter by name (case insensitive)
const name = item.investmentTypeName;
const searchLower = searchTerm.toLowerCase();
const nameMatches = name.toLowerCase().includes(searchLower);
@@ -106,131 +59,143 @@ const InvestmentType = () => {
return nameMatches;
});
// ==================================================== [Table Setup] ================================================================
const extractedArray=filteredData?.map((item, index) => ({
// id: item?.id,
"Sr.no": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{index + 1}
const tableHeadRow = [
"Sr.no",
"Investment Type",
"Description",
"Status",
"Action",
];
const extractedArray = filteredData?.map((item, index) => ({
"Sr.no": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{index + 1}
</Text>
),
"Investment Type": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{item.investmentTypeName}
</Text>
),
Description: (
<Box w={'250px'} isTruncated={true}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
{item.note}
</Text>
),
"Investment Type": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
as={"span"}
color={"teal.900"}
fontWeight={"500"}
className="d-flex align-items-center web-text-small"
>
{item.investmentTypeName}
</Box>
),
Status: (
<Box isTruncated={true}>
<Text as={"span"} fontWeight={"500"}>
<Badge
fontWeight={"500"}
textTransform={"none"}
color={item.isActive ? "green" : "red"}
px={2}
py={0.5}
>
{item?.isActive ? "Active" : "Inactive"}
</Badge>
</Text>
),
Description: (
<Box w={"200px"} isTruncated={true}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
{item.note}
</Text>
</Box>
),
Status: (
<Box w={"200px"} isTruncated={true}>
<Text as={"span"} color={"teal.900"} fontWeight={"500"}>
{item.isActive}
</Text>
</Box>
),
Action: (
<Box display={"flex"} justifyContent={"center"} gap={2}>
<Tooltip
</Box>
),
Action: (
<Box display={"flex"} justifyContent={"center"} gap={2}>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="View"
bg="#fff"
color={"green.500"}
placement="top"
>
<Button
_hover={{ color: "green.500" }}
transition={"0.5s all"}
onClick={() => {
navigate(`view-investment/${item.id}`);
}}
color="green.300"
rounded={"sm"}
fontSize={"xs"}
label="View"
bg="#fff"
color={"green.500"}
placement="top"
size={"xs"}
>
<Button
_hover={{ color: "green.500" }}
transition={"0.5s all"}
onClick={() => {
navigate(`view-investment/${item.id}`);
}}
color="green.300"
rounded={"sm"}
size={"xs"}
>
<ViewIcon />
</Button>
</Tooltip>
<ViewIcon />
</Button>
</Tooltip>
<Tooltip
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="Edit"
bg="#fff"
color={"blue.500"}
placement="top"
>
<Button
onClick={() =>
navigate(`/investment-type/add-investment/${item.id}`)
}
_hover={{ color: "blue.500" }}
color="blue.400"
rounded={"sm"}
fontSize={"xs"}
label="Edit"
bg="#fff"
color={"blue.500"}
placement="top"
size={"xs"}
>
<Button
// onClick={() => {
// navigate(`edit-investment/${item.id}`);
// }}
onClick={() => navigate(`/investment-type/add-investment/${item.id}`)}
_hover={{ color: "blue.500" }}
// transition={"0.5s all"}
color="blue.400"
rounded={"sm"}
size={"xs"}
>
<EditIcon />
</Button>
</Tooltip>
<EditIcon />
</Button>
</Tooltip>
<Tooltip
<Tooltip
rounded={"sm"}
fontSize={"xs"}
label="Delete"
bg="#fff"
color={"red.500"}
placement="top"
>
<Button
onClick={() => {
setActionId(item?.id);
setDeleteAlert(true);
}}
_hover={{ color: "red.500" }}
color="red.300"
rounded={"sm"}
fontSize={"xs"}
label="Delete"
bg="#fff"
color={"red.500"}
placement="top"
size={"xs"}
>
<Button
onClick={() => {
setActionId(item?.id);
setDeleteAlert(true);
}}
_hover={{ color: "red.500" }}
// transition={"0.5s all"}
color="red.300"
rounded={"sm"}
size={"xs"}
>
<DeleteIcon />
</Button>
</Tooltip>
</Box>
),
}))
<DeleteIcon />
</Button>
</Tooltip>
</Box>
),
}));
console.log(extractedArray);
// ==================== [Delete Function] =======================
const handleDelete = () => {
const IOtype = investmentType.filter(
(investmentType) => investmentType.id !== actionId
);
setTimeout(() => {
setInvestmentType(IOtype);
setDeleteAlert(false);
setIsLoading(false);
}, 100);
const handleDelete = async () => {
console.log(actionId);
setIsLoading(true);
try {
const response = await deleteInvestmentType(actionId);
console.log(response);
setIsLoading(false);
setDeleteAlert(false);
} catch (error) {}
};
return (
@@ -245,6 +210,9 @@ const InvestmentType = () => {
pt={4}
spacing="24px"
>
{/* ======================= [Search Input] ======================== */}
<Input
type="search"
width={300}
@@ -257,8 +225,13 @@ const InvestmentType = () => {
/>
<HStack display={"flex"} alignItems={"center"}>
{/* ==================== [Pagination] ===================== */}
<Pagination totalItems={10} />
{/* ===================== [Add Button] ===================== */}
<Link to={"/investment-type/add-investment"}>
<Button
leftIcon={<AddIcon />}
@@ -273,20 +246,21 @@ const InvestmentType = () => {
</HStack>
</Box>
{/* ======================== [Data Table] ======================= */}
<DataTable
emptyMessage={`We don't have any Investment type `}
tableHeadRow={tableHeadRow}
// setData={setExtractedArray}
data={extractedArray}
isLoading={isLoading}
isLoading={investmentTypesLoading}
viewActionId={actionId}
setViewActionId={setActionId}
// totalPages={10}
setMouseEnteredId={setMouseEnteredId}
setMouseEntered={setMouseEntered}
/>
{/* ======================== [Modal] ======================== */}
<CustomAlertDialog
onClose={() => setDeleteAlert(false)}
isOpen={deleteAlert}

View File

@@ -17,70 +17,38 @@ const ViewInvestmentType = () => {
const { data, error, isLoading } = useGetInvestmentTypeByIdQuery(params?.id);
const id = params?.id;
// const foundObject = investmentType.find(
// (item) => item?.id.toString() === id.toString()
// );
if (!data?.data) {
return <FullscreenLoaders />;
}
// const formFields = [
// {
// label: "Investment name",
// value: foundObject.investmentName,
// type: "text",
// isRequired: true,
// section: "Personal Details",
// },
// {
// label: "Investment Name (Arabic)",
// value: foundObject.investmentNameArabic,
// type: "text",
// isRequired: true,
// arabic: true,
// section: "Personal Details",
// },
// {
// label: "Description",
// value: foundObject.description,
// type: "text",
// isRequired: true,
// arabic: true,
// section: "Personal Details",
// },
// {
// label: "Description Arabic",
// value: foundObject.descriptionArabic,
// type: "text",
// isRequired: true,
// section: "Personal Details",
// },
// ];
// ========================== [Input Setup] ===========================
const formFields = [
{
label: "Investment Type (English)",
value:data?.data?.investmentTypeName,
value: data?.data?.investmentTypeName,
section: "",
},
{
label: "Investment Type (Arabic)",
value:data?.data?.investmentTypeNameArabic,
value: data?.data?.investmentTypeNameArabic,
section: "",
},
{
label: "Description (English)",
value:data?.data?.note,
value: data?.data?.note,
section: "",
},
{
label: "Description (Arabic)",
value:data?.data?.noteArabic,
value: data?.data?.noteArabic,
section: "",
},
];
// ====================== [Group Fields] =========================
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
@@ -91,9 +59,13 @@ const ViewInvestmentType = () => {
}, {});
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
<FormInputView groupedFields={groupedFields} />
</Box>
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14} pt={5}>
{/* ======================= [Input Form View] ====================== */}
<FormInputView groupedFields={groupedFields} />
</Box>
);
};

View File

@@ -1,33 +1,27 @@
import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import { Box, useToast } from "@chakra-ui/react";
import { Box, Button, useToast } from "@chakra-ui/react";
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import { WarningTwoIcon } from "@chakra-ui/icons";
import { TiWarning } from "react-icons/ti";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import { useNavigate, useParams } from "react-router-dom";
import { v4 as uuidv4 } from "uuid";
import FormInputMain from "../../../Components/FormInputMain";
import {
useCreateSponserMutation,
// useEditSponserMutation,
useGetSponserByIdQuery,
useUpdateSponserMutation,
} from "../../../Services/sponser.service";
import {useCreateSponserMutation,useGetSponserByIdQuery,useUpdateSponserMutation,} from "../../../Services/sponser.service";
import ToastBox from "../../../Components/ToastBox";
import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
// ======================= [validation] =========================
export const addSponser = yup.object().shape({
sponsorName: yup.string().required("Sponser name is required"),
sponsorNameArabic: yup.string().required("Sponser name is required"),
email: yup
.string()
.email("Must be a valid email")
.required("Email is required"),
email: yup.string().email("Must be a valid email").required("Email is required"),
});
// ==================== [debounce] ========================
export function debounce(func, delay) {
let debounceTimer;
return function (...args) {
@@ -37,32 +31,25 @@ export function debounce(func, delay) {
}
const AddSponser = () => {
const toast = useToast();
const params = useParams();
const navigate = useNavigate();
const [isLoadingBtn, setIsLoadingBtn] = useState(false);
const [bannerImageData, setBannerImageData] = useState(null);
const [selectedBannerImageData, setSelectedBannerImageData] = useState(null);
const id = params?.id;
// =====================[useState]=======================
const [isLoadingBtn, setIsLoadingBtn] = useState(false);
const [alert, setAlert] = useState(false);
const [form, setForm] = useState();
const [otherImageData, setOtherImageData] = useState(null);
const [selectedOtherImageData, setSelectedOtherImageData] = useState(null);
const { sponser, setSponser } = useContext(GlobalStateContext);
const [createSponser] = useCreateSponserMutation();
const [updateSponser] = useUpdateSponserMutation();
const id = params?.id;
console.log(id);
// Fetch sponsor data only if id exists
const {
data: sponserByIdData,
error,
isLoading,
} = useGetSponserByIdQuery(id, {
skip: !id,
});
const {data: sponserByIdData,error,isLoading,} = useGetSponserByIdQuery(id, {skip: !id,});
console.log(sponserByIdData?.data);
// ======================== [validators] ===========================
const {
control,
@@ -73,6 +60,8 @@ const AddSponser = () => {
resolver: yupResolver(addSponser),
});
// ========================== [useEffect] ================================
useEffect(() => {
if (sponserByIdData?.data) {
reset({
@@ -83,10 +72,82 @@ const AddSponser = () => {
}
}, [sponserByIdData, reset]);
if (false) {
if (false) {
return <FullscreenLoaders />;
}
// ============================ [API]===============================
const handleConfirm = async () => {
setIsLoadingBtn(true);
const id = params?.id;
if (id) {
try {
const formData = {
...form,
// isActive: isSwitchOn,
};
await updateSponser({ data: formData, id }).then((response) => {
if (response?.data?.statusCode) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
setIsLoadingBtn(false);
setAlert(false);
navigate("/sponser");
} else {
toast({
render: () => (
<ToastBox message={"Something Went Wrong"} status={"error"} />
),
});
setIsLoadingBtn(false);
navigate("/sponser");
}
});
} catch (error) {
console.log(error);
setIsLoadingBtn(false);
navigate("/sponser");
}
} else {
try {
const formData = {
...form,
// isActive: isSwitchOn,
};
await createSponser(formData).then((response) => {
if (response?.data?.statusCode) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
setIsLoadingBtn(false);
navigate("/sponser");
} else {
toast({
render: () => (
<ToastBox message={"Something Went Wrong"} status={"error"} />
),
});
setIsLoadingBtn(false);
navigate("/sponser");
}
});
} catch (error) {
console.log(error);
setIsLoadingBtn(false);
navigate("/sponser");
}
}
};
// ====================== [Update Form Object] =========================
const formFields = [
{
label: "Sponser name (English)",
@@ -104,7 +165,7 @@ const AddSponser = () => {
isRequired: true,
section: "Add Details",
isArabic: true,
right:true
right: true,
},
{
label: "Email address",
@@ -116,11 +177,13 @@ const AddSponser = () => {
},
];
// ==================== [Create Form Object] =======================
const formEditFields = [
{
label: "Sponser name",
placeHolder: " ",
name: "sponsorName",
name: "sponsorName",
type: "text",
isRequired: true,
section: "Add Details",
@@ -144,6 +207,8 @@ const AddSponser = () => {
},
];
// ====================== [Group Create Fields] =========================
const groupedEditFields = formEditFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
@@ -153,6 +218,8 @@ const AddSponser = () => {
return groups;
}, {});
// ====================== [Group Update Fields] =======================
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
@@ -162,80 +229,36 @@ const AddSponser = () => {
return groups;
}, {});
// ==================== [On Submit] ========================
const onSubmit = async (data) => {
setIsLoadingBtn(true);
console.log(data);
const id = params?.id;
if (id) {
try {
await updateSponser({ data, id }).then((response) => {
if (response?.data?.statusCode) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
setIsLoadingBtn(false);
navigate("/sponser");
} else {
toast({
render: () => (
<ToastBox message={"Something Went Wrong"} status={"error"} />
),
});
setIsLoadingBtn(false);
navigate("/sponser");
}
});
} catch (error) {
console.log(error);
setIsLoadingBtn(false);
navigate("/sponser");
}
} else {
try {
await createSponser(data).then((response) => {
if (response?.data?.statusCode) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
setIsLoadingBtn(false);
navigate("/sponser");
} else {
toast({
render: () => (
<ToastBox message={"Something Went Wrong"} status={"error"} />
),
});
setIsLoadingBtn(false);
navigate("/sponser");
}
});
} catch (error) {
console.log(error);
setIsLoadingBtn(false);
navigate("/sponser");
}
if (Object.keys(errors).length === 0) {
setForm(data);
setAlert(true);
}
};
if (isLoading) {
return <FullscreenLoaders />;
}
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
{/* ====================== [Form Input] ====================== */}
<FormInputMain
groupedFields={params?.id ? groupedEditFields : groupedFields}
control={control}
errors={errors}
onSubmit={handleSubmit(onSubmit)}
submitTitle={params?.id ? "Update" : "Submit"}
btnLoading={isLoadingBtn}
></FormInputMain>
{/* ======================= [Modal] =========================== */}
<CustomAlertDialog
isOpen={alert}
onClose={() => setAlert(false)}
alertHandler={handleConfirm}
message={"Are you sure you want to add this?"}
isLoading={isLoadingBtn}
/>
</Box>
);

View File

@@ -1,29 +1,9 @@
import {
Badge,
Box,
Button,
HStack,
Input,
Switch,
Tag,
Text,
Tooltip,
useToast,
} from "@chakra-ui/react";
import {Badge, Box,Button,HStack,Input,Text,Tooltip,useToast,} from "@chakra-ui/react";
import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import DataTable from "../../../Components/DataTable/DataTable";
import { HiDotsVertical } from "react-icons/hi";
import { Link, Link as RouterLink } from "react-router-dom";
import {
AddIcon,
CheckIcon,
CloseIcon,
DeleteIcon,
EditIcon,
EmailIcon,
ViewIcon,
} from "@chakra-ui/icons";
import {AddIcon,DeleteIcon,EditIcon,} from "@chakra-ui/icons";
import Pagination from "../../../Components/Pagination";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import CustomAlertDialog from "../../../Components/CustomAlertDialog";
@@ -31,80 +11,52 @@ import { useNavigate } from "react-router-dom";
import ToastBox from "../../../Components/ToastBox";
import { debounce } from "./AddSponser";
import { TABLE_PAGINATION } from "../../../Constants/Paginations";
import {
useDeleteSponserMutation,
useGetSponserMasterQuery,
useToggleStatusMutation,
} from "../../../Services/sponser.service";
import {useDeleteSponserMutation,useGetSponserMasterQuery,useToggleStatusMutation,} from "../../../Services/sponser.service";
export const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
export const formatDate = (date) => new Date(date).toLocaleDateString(); // Simple date formatter
const Sponser = () => {
const navigate = useNavigate();
const toast = useToast();
// =========================== [Use State] =============================
const [pageSize, setPageSize] = useState(TABLE_PAGINATION?.size);
const [currentPage, setCurrentPage] = useState(1);
const {
data: sponsors,
error,
isLoading: isSponserLoading,
} = useGetSponserMasterQuery({ page: 1, size: 20 });
const [displayRange, setDisplayRange] = useState({
start: TABLE_PAGINATION?.page,
end: pageSize,
});
const { sponser, setSponser, slideFromRight } =
useContext(GlobalStateContext);
const [searchTerm, setSearchTerm] = useState("");
const [isLoading, setIsLoading] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [deleteAlert, setDeleteAlert] = useState(false);
const [actionId, setActionId] = useState(false);
const [mouseEntered, setMouseEntered] = useState(false);
const [mouseEnteredId, setMouseEnteredId] = useState("");
const [toggleStatus] = useToggleStatusMutation();
const [deleteSponser] = useDeleteSponserMutation();
const [deleteSponser] = useDeleteSponserMutation();
const { sponser, setSponser, slideFromRight } = useContext(GlobalStateContext);
useEffect(() => {
// Simulate loading
const timer = setTimeout(() => {
setIsLoading(false);
}, 1500);
return () => clearTimeout(timer);
}, []);
const {data: sponsors,error,isLoading: isSponserLoading,} = useGetSponserMasterQuery({ page: 1, size: 20 });
// ====================================================[Table Setup]================================================================
const tableHeadRow = [
"Sponsor name",
"Email address",
"Status",
// "Created At",
"Action",
];
// ========================= [Toggle ToastBox] ==========================
const handleUpdateStatus = debounce(async (id) => {
// const handleUpdateStatus = debounce(async (id) => {
// try {
// await toggleStatus({ id }).then((response) => {
// console.log(response);
// if (response?.data?.statusCode) {
// toast({
// render: () => <ToastBox message={response?.data?.message} />,
// });
// } else {
// toast({
// render: () => (
// <ToastBox message={"Something Went Wrong"} status={"error"} />
// ),
// });
// }
// });
// } catch (error) {}
// }, 300);
try {
await toggleStatus({ id }).then((response) => {
console.log(response);
if (response?.data?.statusCode) {
toast({
render: () => <ToastBox message={response?.data?.message} />,
});
} else {
toast({
render: () => (
<ToastBox message={"Something Went Wrong"} status={"error"} />
),
});
}
});
} catch (error) {}
}, 300);
// ==============================[Table Filter]========================
const filteredData = sponsors?.data?.rows?.filter((item) => {
const name = item.sponsorName;
@@ -114,8 +66,16 @@ const Sponser = () => {
return nameMatches;
});
// ====================================================[Table Setup]================================================================
const tableHeadRow = [
"Sponsor name",
"Email address",
"Status",
"Action",
];
const extractedArray = filteredData?.map((item) => ({
// id: item?.id,
"Sponsor name": (
<Text
justifyContent={slideFromRight ? "right" : "left"}
@@ -137,28 +97,19 @@ const Sponser = () => {
),
Status: (
<Box minW={24} isTruncated={true}>
{/* <Switch
size={"sm"}
colorScheme="green"
onChange={() => handleUpdateStatus(item.id)}
isChecked={item.isActive}
/> */}
<Badge fontWeight={'500'} textTransform={'none'} color={item.isActive ? "green" : "red"} px={2} py={0.5}>
{item.isActive ? "Active":"Inactive"}
<Badge
fontWeight={"500"}
textTransform={"none"}
color={item.isActive ? "green" : "red"}
px={2}
py={0.5}
>
{item.isActive ? "Active" : "Inactive"}
</Badge>
</Box>
),
// "Created At": (
// <Box className="d-flex justify-content-between align-items-center">
// <Text as={"span"} color={"gray.600"} fontWeight={"500"}>
// {formatDate(item.createdAt)}
// </Text>
// </Box>
// ),
Action: (
<Box display={"flex"} justifyContent={"center"} gap={2}>
<Tooltip
rounded={"sm"}
fontSize={"xs"}
@@ -170,7 +121,6 @@ const Sponser = () => {
<Button
onClick={() => navigate(`/sponser/add-sponser/${item.id}`)}
_hover={{ color: "blue.500" }}
// transition={"0.5s all"}
color="blue.400"
rounded={"sm"}
size={"xs"}
@@ -193,7 +143,6 @@ const Sponser = () => {
setDeleteAlert(true);
}}
_hover={{ color: "red.500" }}
// transition={"0.5s all"}
color="red.300"
rounded={"sm"}
size={"xs"}
@@ -205,6 +154,8 @@ const Sponser = () => {
),
}));
// =========================== [Delete Function] =================================
const handleDelete = async () => {
console.log(actionId);
setIsLoading(true);
@@ -228,6 +179,9 @@ const Sponser = () => {
pt={4}
spacing="24px"
>
{/* =======================[Search Input]======================== */}
<Input
type="search"
width={300}
@@ -240,12 +194,17 @@ const Sponser = () => {
/>
<HStack display={"flex"} alignItems={"center"}>
{/* ====================[Pagination]===================== */}
<Pagination totalItems={10} />
{/* =====================[Add Button]===================== */}
<Link to={"/sponser/add-sponser"}>
<Button
leftIcon={<AddIcon />}
colorScheme={"green"}
colorScheme={"forestGreen"}
rounded={"sm"}
size={"sm"}
>
@@ -256,6 +215,8 @@ const Sponser = () => {
</HStack>
</Box>
{/* =================== [Data Table] ===================== */}
<DataTable
emptyMessage={`We don't have any Sponers `}
tableHeadRow={tableHeadRow}
@@ -263,12 +224,12 @@ const Sponser = () => {
isLoading={isSponserLoading}
viewActionId={actionId}
setViewActionId={setActionId}
// totalPages={10}
setMouseEnteredId={setMouseEnteredId}
setMouseEntered={setMouseEntered}
/>
{/* ======================== [Modal] ======================== */}
<CustomAlertDialog
onClose={() => setDeleteAlert(false)}
isOpen={deleteAlert}

View File

@@ -20,6 +20,8 @@ const ViewSponser = () => {
return <Box>Loading...</Box>;
}
// ========================== [Input Setup] ===========================
const formFields = [
{
label: "Sponser name",
@@ -38,6 +40,7 @@ const ViewSponser = () => {
},
];
// ====================== [Group Fields] =========================
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
@@ -50,7 +53,11 @@ const ViewSponser = () => {
return (
<Box {...OPACITY_ON_LOAD} overflowY={"scroll"} height={"100vh"} pb={14}>
{/* ======================= [Input Form View] =================== */}
<FormInputView groupedFields={groupedFields} />
</Box>
);
};

View File

@@ -10,17 +10,24 @@ export const investmentType = createApi({
baseQuery: fetchBaseQuery({ baseUrl }),
tagTypes: ["getInvestmentType"],
endpoints: (builder) => ({
// ========[Get All]=========
getInvestmentTypes: builder.query({
query: ({ page, size }) =>
`/investmentType/admin?page=${page}&size=${size}`,
providesTags: ["getInvestmentType"],
}),
// ========[Get ID]=========
getInvestmentTypeById: builder.query({
query: (id) => `/investmentType/admin/${id}`,
providesTags: ["getInvestmentType"],
}),
// ========[Create Investment]========
createInvestmentType: builder.mutation({
query: (data) => ({
url: `/investmentType/admin/`,
@@ -30,6 +37,7 @@ export const investmentType = createApi({
invalidatesTags: ["getInvestmentType"],
}),
// ========[Update Investment]=======
updateInvestmentType: builder.mutation({
query: ({ data, id }) => ({
@@ -40,6 +48,16 @@ export const investmentType = createApi({
invalidatesTags: ["getInvestmentType"],
}),
// ========[Delete Investment]=======
deleteInvestmentType: builder.mutation({
query: (id) => ({
url: `/investmentType/admin/delete/${id}`,
method: "DELETE",
}),
invalidatesTags: ["getSponser"],
}),
}),
});
@@ -49,4 +67,5 @@ export const {
useGetInvestmentTypeByIdQuery,
useCreateInvestmentTypeMutation,
useUpdateInvestmentTypeMutation,
useDeleteInvestmentTypeMutation,
} = investmentType;

View File

@@ -15,11 +15,17 @@ export const sponserMaster = createApi({
endpoints: (builder) => ({
// ======[Get All]=====
getSponserMaster: builder.query({
query: ({ page, size }) => `/sponsor/admin?page=${page}&size=${size}`,
providesTags: ["getSponser"],
}),
// ========[Get Active]========
getActiveSponserMaster: builder.query({
query: () => `/sponsor/admin/active`,
providesTags: ["getSponser"],
@@ -29,13 +35,15 @@ export const sponserMaster = createApi({
query: () => "/sponsor/admin/active",
}),
// ======[Get ID]=====
getSponserById: builder.query({
query: (id) => `/sponsor/admin/${id}`,
providesTags: ["getSponser"],
}),
// ========[Toggle Status]========
toggleStatus: builder.mutation({
query: ({ id }) => ({
@@ -45,6 +53,8 @@ export const sponserMaster = createApi({
invalidatesTags: ["getSponser"],
}),
// ========[Create Sponser]========
createSponser: builder.mutation({
query: (data) => ({
url: `/sponsor/admin`,
@@ -54,6 +64,8 @@ export const sponserMaster = createApi({
invalidatesTags: ["getSponser"],
}),
// ========[Update Sponser]========
updateSponser: builder.mutation({
query: ({ data, id }) => ({
url: `/sponsor/admin/${id}`,
@@ -63,6 +75,8 @@ export const sponserMaster = createApi({
invalidatesTags: ["getSponser"],
}),
// ========[Delete Sponser]========
deleteSponser: builder.mutation({
query: (id) => ({
url: `/sponsor/admin/delete/${id}`,