diff --git a/src/Components/FormInputMain.jsx b/src/Components/FormInputMain.jsx
index 411c737..ad1bd11 100644
--- a/src/Components/FormInputMain.jsx
+++ b/src/Components/FormInputMain.jsx
@@ -15,7 +15,8 @@ const FormInputMain = ({
submitTitle,
p,
w,
- btnLoading
+ btnLoading,
+ btnhidden,
}) => {
return (
@@ -91,7 +92,7 @@ const FormInputMain = ({
{children}
-
+
{onCancle && (
+ {btnhidden ? (
+ ""
+ ) : (
+ }
+ type="submit"
+ colorScheme={"forestGreen"}
+ >
+ {submitTitle ? submitTitle : "Submit"}
+
+ )}
diff --git a/src/Constants/Constants.js b/src/Constants/Constants.js
index 16ac5bf..931a3a2 100644
--- a/src/Constants/Constants.js
+++ b/src/Constants/Constants.js
@@ -1,4 +1,12 @@
export const getFileNameFromPath = (filePath) => {
- const parts = filePath.split('/');
- return parts[parts.length - 1];
- };
\ No newline at end of file
+ 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);
+ };
+}
diff --git a/src/Pages/IO_Management/KeyMeritsAdd.jsx b/src/Pages/IO_Management/KeyMeritsAdd.jsx
index 53d48d7..3bf0b2c 100644
--- a/src/Pages/IO_Management/KeyMeritsAdd.jsx
+++ b/src/Pages/IO_Management/KeyMeritsAdd.jsx
@@ -116,7 +116,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id }) => {
@@ -197,7 +197,7 @@ const KeyMeritsAdd = ({ isOpen, onClose, firstField, id }) => {
setAlert(true)}
diff --git a/src/Pages/Master/InvestmentType/AddInvestmentType.jsx b/src/Pages/Master/InvestmentType/AddInvestmentType.jsx
index 4bbe497..b0b47d5 100644
--- a/src/Pages/Master/InvestmentType/AddInvestmentType.jsx
+++ b/src/Pages/Master/InvestmentType/AddInvestmentType.jsx
@@ -1,25 +1,30 @@
-import React, { useContext, useState } from "react";
+import React, { useContext, useEffect, useState } from "react";
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
-import { Box } 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 } from "react-router-dom";
-import FormField from "../../../Components/FormField";
-import { v4 as uuidv4 } from "uuid";
+import { useNavigate, useParams } from "react-router-dom";
import FormInputMain from "../../../Components/FormInputMain";
import SwitchButton from "../../../Components/SwitchButton";
+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({
- investmentName: yup.string().required("Investment name is required"),
- description: yup.string().required("Description is required"),
- investmentNameArabic: yup.string().required("Investment name is required"),
- descriptionArabic: yup.string().required("Description is required"),
+ investmentTypeName: yup.string().required("Investment name is required"),
+ note: yup.string().required("Description 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) {
@@ -29,109 +34,221 @@ export function debounce(func, delay) {
}
const AddInvestmentType = () => {
- const navigate = useNavigate();
- const [bannerImageData, setBannerImageData] = useState(null);
- const { investmentType, setInvestmentType } = useContext(GlobalStateContext);
- const [selectedBannerImageData, setSelectedBannerImageData] = useState(null);
- const [isSwitchOn, setIsSwitchOn] = useState(false);
+
+
+
+
+ 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 [alert, setAlert] = useState(false);
+ const [form, setForm] = useState();
+
+
+
+ const [createInvestmentType] = useCreateInvestmentTypeMutation();
+ const [updateInvestmentType] = useUpdateInvestmentTypeMutation();
+
+ // ======================== [validators] ===========================
- const [otherImageData, setOtherImageData] = useState(null);
- const [selectedOtherImageData, setSelectedOtherImageData] = useState(null);
const {
control,
handleSubmit,
formState: { errors },
+ reset,
} = useForm({
resolver: yupResolver(addInvestmentType),
});
- const handleBannerImageChange = (e) => {
- const file = e.target.files[0];
- setBannerImageData(file);
- if (file) {
- const reader = new FileReader();
- reader.onloadend = () => {
- setSelectedBannerImageData(reader.result);
- };
- reader.readAsDataURL(file);
+ const {data: investmentTypeByIdData,error,isLoading,} = useGetInvestmentTypeByIdQuery(id, { skip: !id });
+
+ // ========================== [useEffect] ================================
+
+ useEffect(() => {
+ if (investmentTypeByIdData?.data) {
+ reset({
+ investmentTypeName: investmentTypeByIdData?.data?.investmentTypeName,
+ investmentTypeNameArabic:
+ investmentTypeByIdData?.data?.investmentTypeNameArabic,
+ note: investmentTypeByIdData?.data?.note,
+ noteArabic: investmentTypeByIdData?.data?.noteArabic,
+ });
+ }
+ }, [investmentTypeByIdData, reset]);
+
+ if (false) {
+ return ;
+ }
+
+ // ============================ [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: () => ,
+ });
+
+ setIsLoadingBtn(false);
+ setAlert(false);
+ navigate("/investment-type");
+ } else {
+ toast({
+ render: () => (
+
+ ),
+ });
+
+ 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: () => ,
+ });
+
+ setIsLoadingBtn(false);
+ navigate("/investment-type");
+ } else {
+ toast({
+ render: () => (
+
+ ),
+ });
+
+ setIsLoadingBtn(false);
+ navigate("/investment-type");
+ }
+ });
+ } catch (error) {
+ console.log(error);
+
+ setIsLoadingBtn(false);
+ navigate("/investment-type");
+ }
}
};
- // Handler for file input
- const handleOtherImageChange = (e) => {
- const files = Array.from(e.target.files);
- const newImageData = [...(otherImageData || []), ...files]; // Ensure otherImageData is an array
-
- setOtherImageData(newImageData);
-
- const readers = files.map((file) => {
- return new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.onloadend = () => {
- resolve(reader.result);
- };
- reader.onerror = reject;
- reader.readAsDataURL(file);
- });
- });
-
- Promise.all(readers)
- .then((results) => {
- setSelectedOtherImageData([
- ...(selectedOtherImageData || []),
- ...results,
- ]); // Ensure selectedOtherImageData is an array
- })
- .catch((error) => {
- console.error("Error reading files:", error);
- });
- };
-
- // Function to remove a specific image
- const removeOtherImage = (index) => {
- const newImageData = otherImageData.filter((_, i) => i !== index);
- const newSelectedImageData = selectedOtherImageData.filter(
- (_, i) => i !== index
- );
-
- setOtherImageData(newImageData);
- setSelectedOtherImageData(newSelectedImageData);
- };
-
+ // ====================== [Update Form Object] =========================
const formFields = [
{
- label: "Investment name",
- name: "investmentName",
+ label: "Investment Type (English)",
+ placeHolder: " ",
+ name: "investmentTypeName",
type: "text",
isRequired: true,
section: "Add Details",
},
{
- label: "Investment Name (Arabic)",
- name: "investmentNameArabic",
+ label: "Investment Type (Arabic) ",
+ name: "investmentTypeNameArabic",
+ placeHolder: " ",
type: "text",
isRequired: true,
- arabic: true,
section: "Add Details",
+ isArabic: true,
},
{
- label: "Description Name",
- name: "description",
+ label: "Description (English)",
+ placeHolder: " ",
+ name: "note",
type: "text",
isRequired: true,
section: "Add Details",
},
{
- label: "Description Name (Arabic)",
- name: "descriptionArabic",
+ label: "Description (Arabic)",
+ placeHolder: " ",
+ name: "noteArabic",
type: "text",
isRequired: true,
- arabic: true,
+ isArabic: true,
section: "Add Details",
},
];
+ // ==================== [Create Form Object] =======================
+
+ const formEditFields = [
+ {
+ label: "Investment Type (English) *",
+ placeHolder: " ",
+ name: "investmentTypeName",
+ type: "text",
+ isRequired: true,
+ section: "Add Details",
+ },
+ {
+ label: "Investment Type (Arabic) *",
+ name: "investmentTypeNameArabic",
+ placeHolder: " ",
+ type: "text",
+ isRequired: true,
+ section: "Add Details",
+ isArabic: true,
+ },
+ {
+ label: "Description (English)",
+ placeHolder: " ",
+ name: "note",
+ type: "text",
+ isRequired: true,
+ section: "Add Details",
+ },
+ {
+ label: "Description (Arabic)",
+ placeHolder: " ",
+ name: "noteArabic",
+ type: "text",
+ isRequired: true,
+ isArabic: true,
+ section: "Add Details",
+ },
+ ];
+
+ // ====================== [Group Create Fields] =========================
+
+ const groupedEditFields = formEditFields.reduce((groups, field) => {
+ const { section } = field;
+ if (!groups[section]) {
+ groups[section] = [];
+ }
+ groups[section].push(field);
+ return groups;
+ }, {});
+
+ // ====================== [Group Update Fields] =======================
+
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
@@ -141,31 +258,48 @@ const AddInvestmentType = () => {
return groups;
}, {});
- const onSubmit = (data) => {
- setInvestmentType([
- {
- ...data,
- status: true,
- id: uuidv4(),
- createdAt: new Date().toISOString(),
- },
- ...investmentType,
- ]);
- navigate("/investment-type");
+
+ // ==================== [On Submit] ========================
+ const onSubmit = async (data) => {
+ // setIsLoadingBtn(true);
+ if (Object.keys(errors).length === 0) {
+ setForm(data);
+ setAlert(true);
+ }
};
return (
-
+
+ {/* ===================== [Switch Button] ======================== */}
+
+
+
+ {/* ====================== [Form Input] ====================== */}
+
+
+
+ {/* ======================= [Modal] =========================== */}
+
+ setAlert(false)}
+ alertHandler={handleConfirm}
+ message={"Are you sure you want to add this?"}
+ isLoading={isLoadingBtn}
/>
+
);
};
diff --git a/src/Pages/Master/InvestmentType/InvestmentType.jsx b/src/Pages/Master/InvestmentType/InvestmentType.jsx
index 963d343..cde187e 100644
--- a/src/Pages/Master/InvestmentType/InvestmentType.jsx
+++ b/src/Pages/Master/InvestmentType/InvestmentType.jsx
@@ -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: () => ,
+ // });
+ // }, 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: () => ,
- });
- }, 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,127 +59,143 @@ const InvestmentType = () => {
return nameMatches;
});
+
+ // ==================================================== [Table Setup] ================================================================
+
+ const tableHeadRow = [
+ "Sr.no",
+ "Investment Type",
+ "Description",
+ "Status",
+ "Action",
+ ];
+
const extractedArray = filteredData?.map((item, index) => ({
- // id: item?.id,
- "Sr.no": (
-
- {index + 1}
+ "Sr.no": (
+
+ {index + 1}
+
+ ),
+ "Investment Type": (
+
+ {item.investmentTypeName}
+
+ ),
+ Description: (
+
+
+ {item.note}
- ),
- "Investment Type": (
-
- {item.investmentTypeName}
+
+ ),
+ Status: (
+
+
+
+ {item?.isActive ? "Active" : "Inactive"}
+
- ),
- Description: (
-
-
- {item.note}
-
-
- ),
- Status: (
-
-
- {item.isActive}
-
-
- ),
- Action: (
-
-
+ ),
+ Action: (
+
+
+ {
+ navigate(`view-investment/${item.id}`);
+ }}
+ color="green.300"
rounded={"sm"}
- fontSize={"xs"}
- label="View"
- bg="#fff"
- color={"green.500"}
- placement="top"
+ size={"xs"}
>
- {
- navigate(`view-investment/${item.id}`);
- }}
- color="green.300"
- rounded={"sm"}
- size={"xs"}
- >
-
-
-
+
+
+
-
+
+ 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"}
>
- {
- navigate(`edit-investment/${item.id}`);
- }}
- _hover={{ color: "blue.500" }}
- // transition={"0.5s all"}
- color="blue.400"
- rounded={"sm"}
- size={"xs"}
- >
-
-
-
+
+
+
-
+ {
+ 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"}
>
- {
- setActionId(item?.id);
- setDeleteAlert(true);
- }}
- _hover={{ color: "red.500" }}
- // transition={"0.5s all"}
- color="red.300"
- rounded={"sm"}
- size={"xs"}
- >
-
-
-
-
- ),
- }))
+
+
+
+
+ ),
+ }));
- const handleDelete = () => {
- const IOtype = investmentType.filter(
- (investmentType) => investmentType.id !== actionId
- );
+ // ==================== [Delete Function] =======================
- 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 (
@@ -241,6 +210,9 @@ const InvestmentType = () => {
pt={4}
spacing="24px"
>
+
+ {/* ======================= [Search Input] ======================== */}
+
{
/>
+
+ {/* ==================== [Pagination] ===================== */}
+
+ {/* ===================== [Add Button] ===================== */}
+
}
@@ -269,20 +246,21 @@ const InvestmentType = () => {
+ {/* ======================== [Data Table] ======================= */}
+
+ {/* ======================== [Modal] ======================== */}
+
setDeleteAlert(false)}
isOpen={deleteAlert}
diff --git a/src/Pages/Master/InvestmentType/ViewInvestmentType.jsx b/src/Pages/Master/InvestmentType/ViewInvestmentType.jsx
index d7cd6f0..9203382 100644
--- a/src/Pages/Master/InvestmentType/ViewInvestmentType.jsx
+++ b/src/Pages/Master/InvestmentType/ViewInvestmentType.jsx
@@ -6,55 +6,49 @@ import FormInputView from "../../../Components/FormInputView";
import { useForm } from "react-hook-form"; // assuming react-hook-form is used
import { OPACITY_ON_LOAD } from "../../../Layout/animations";
import { ArrowBackIcon } from "@chakra-ui/icons";
+import { useGetInvestmentTypeByIdQuery } from "../../../Services/investment.type.service";
+import FullscreenLoaders from "../../../Components/Loaders/FullscreenLoaders";
const ViewInvestmentType = () => {
const navigate = useNavigate();
const params = useParams();
const { investmentType } = useContext(GlobalStateContext);
const { reset } = useForm(); // assuming react-hook-form
+ const { data, error, isLoading } = useGetInvestmentTypeByIdQuery(params?.id);
const id = params?.id;
- const foundObject = investmentType.find(
- (item) => item?.id.toString() === id.toString()
- );
- if (!foundObject) {
- return Loading...;
+ if (!data?.data) {
+ return ;
}
+ // ========================== [Input Setup] ===========================
+
const formFields = [
{
- label: "Investment name",
- value: foundObject.investmentName,
- type: "text",
- isRequired: true,
- section: "Personal Details",
+ label: "Investment Type (English)",
+ value: data?.data?.investmentTypeName,
+ section: "",
},
{
- label: "Investment Name (Arabic)",
- value: foundObject.investmentNameArabic,
- type: "text",
- isRequired: true,
- arabic: true,
- section: "Personal Details",
+ label: "Investment Type (Arabic)",
+ value: data?.data?.investmentTypeNameArabic,
+ section: "",
},
{
- label: "Description",
- value: foundObject.description,
- type: "text",
- isRequired: true,
- arabic: true,
- section: "Personal Details",
+ label: "Description (English)",
+ value: data?.data?.note,
+ section: "",
},
{
- label: "Description Arabic",
- value: foundObject.descriptionArabic,
- type: "text",
- isRequired: true,
- section: "Personal Details",
+ label: "Description (Arabic)",
+ value: data?.data?.noteArabic,
+ section: "",
},
];
+ // ====================== [Group Fields] =========================
+
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
@@ -65,14 +59,12 @@ const ViewInvestmentType = () => {
}, {});
return (
-
- navigate(-1)}
- style={{ fontSize: "15px", cursor: "pointer" }}
- >
- Back
-
+
+
+ {/* ======================= [Input Form View] ====================== */}
+
+
);
};
diff --git a/src/Pages/Master/Sponser/AddSponser.jsx b/src/Pages/Master/Sponser/AddSponser.jsx
index 9d8231c..97af839 100644
--- a/src/Pages/Master/Sponser/AddSponser.jsx
+++ b/src/Pages/Master/Sponser/AddSponser.jsx
@@ -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({
@@ -87,6 +76,78 @@ const AddSponser = () => {
return ;
}
+ // ============================ [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: () => ,
+ });
+
+ setIsLoadingBtn(false);
+ setAlert(false);
+ navigate("/sponser");
+ } else {
+ toast({
+ render: () => (
+
+ ),
+ });
+
+ 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: () => ,
+ });
+
+ setIsLoadingBtn(false);
+ navigate("/sponser");
+ } else {
+ toast({
+ render: () => (
+
+ ),
+ });
+
+ setIsLoadingBtn(false);
+ navigate("/sponser");
+ }
+ });
+ } catch (error) {
+ console.log(error);
+
+ setIsLoadingBtn(false);
+ navigate("/sponser");
+ }
+ }
+ };
+
+ // ====================== [Update Form Object] =========================
+
const formFields = [
{
label: "Sponser name (English)",
@@ -104,6 +165,7 @@ const AddSponser = () => {
isRequired: true,
section: "Add Details",
isArabic: true,
+ right: true,
},
{
label: "Email address",
@@ -115,6 +177,8 @@ const AddSponser = () => {
},
];
+ // ==================== [Create Form Object] =======================
+
const formEditFields = [
{
label: "Sponser name",
@@ -143,6 +207,8 @@ const AddSponser = () => {
},
];
+ // ====================== [Group Create Fields] =========================
+
const groupedEditFields = formEditFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
@@ -152,6 +218,8 @@ const AddSponser = () => {
return groups;
}, {});
+ // ====================== [Group Update Fields] =======================
+
const groupedFields = formFields.reduce((groups, field) => {
const { section } = field;
if (!groups[section]) {
@@ -161,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: () => ,
- });
-
- setIsLoadingBtn(false);
- navigate("/sponser");
- } else {
- toast({
- render: () => (
-
- ),
- });
-
- 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: () => ,
- });
-
- setIsLoadingBtn(false);
- navigate("/sponser");
- } else {
- toast({
- render: () => (
-
- ),
- });
-
- 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 ;
- }
-
-
return (
+
+ {/* ====================== [Form Input] ====================== */}
+
+
+ {/* ======================= [Modal] =========================== */}
+
+ setAlert(false)}
+ alertHandler={handleConfirm}
+ message={"Are you sure you want to add this?"}
+ isLoading={isLoadingBtn}
/>
);
diff --git a/src/Pages/Master/Sponser/Sponsers.jsx b/src/Pages/Master/Sponser/Sponsers.jsx
index 2be5964..8b20350 100644
--- a/src/Pages/Master/Sponser/Sponsers.jsx
+++ b/src/Pages/Master/Sponser/Sponsers.jsx
@@ -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,119 +11,54 @@ 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) => {
- const d = new Date(date);
- const day = String(d.getDate()).padStart(2, '0');
- const month = String(d.getMonth() + 1).padStart(2, '0'); // Months are zero-based
- const year = d.getFullYear();
- return `${day}-${month}-${year}`;
-};
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(() => {
- // setSponser(sponsors)
- // }, [])
+ const {data: sponsors,error,isLoading: isSponserLoading,} = useGetSponserMasterQuery({ page: 1, size: 20 });
- useEffect(() => {
- // Simulate loading
- const timer = setTimeout(() => {
- setIsLoading(false);
- }, 1500);
+ // ========================= [Toggle ToastBox] ==========================
- // Cleanup the timer on component unmount
- return () => clearTimeout(timer);
- }, []);
+ // const handleUpdateStatus = debounce(async (id) => {
+ // try {
+ // await toggleStatus({ id }).then((response) => {
+ // console.log(response);
+ // if (response?.data?.statusCode) {
+ // toast({
+ // render: () => ,
+ // });
+ // } else {
+ // toast({
+ // render: () => (
+ //
+ // ),
+ // });
+ // }
+ // });
+ // } catch (error) {}
+ // }, 300);
- // ====================================================[Table Setup]================================================================
- const tableHeadRow = [
- "Sponsor name",
- // "Sponsor name (Arabic)",
- "Email address",
- "Status",
- "Created At",
- "Action",
- ];
-
- const handleUpdateStatus = debounce(async (id) => {
- // setSponser((prevSponser) =>
- // prevSponser.map((sponsor) =>
- // sponsor.id === id ? { ...sponsor, status: !sponsor.status } : sponsor
- // )
- // );
-
- try {
- await toggleStatus({ id }).then((response) => {
- console.log(response);
- if (response?.data?.statusCode) {
- toast({
- render: () => ,
- });
- } else {
- toast({
- render: () => (
-
- ),
- });
- }
- });
- } catch (error) {}
- }, 300);
-
- // // ====================================================[Table Filter]================================================================
- // const filteredData = sponsors?.data?.rows?.filter((item) => {
- // // Filter by name (case insensitive)
- // const name = item.sponserName;
- // 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;
- // });
+ // ==============================[Table Filter]========================
const filteredData = sponsors?.data?.rows?.filter((item) => {
- // Filter by name (case insensitive)
const name = item.sponsorName;
const searchLower = searchTerm?.toLowerCase();
const nameMatches = name?.toLowerCase().includes(searchLower);
@@ -151,9 +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": (
{
),
- // "Sponsor name (Arabic)":(
- // {item.sponsorNameArabic}
- // ),
"Email address": (
@@ -184,60 +97,19 @@ const Sponser = () => {
),
Status: (
- {/* handleUpdateStatus(item.id)}
- isChecked={item.isActive}
- /> */}
-
- {item.isActive ? "Active":"Inactive"}
+
+ {item.isActive ? "Active" : "Inactive"}
),
-
- // item?.status ? (
- //
- // Passed
- //
- // ) : (
- //
- // Not passes
- //
- // ),
-
- "Created At": (
-
-
- {formatDate(item.createdAt)}
-
-
- ),
Action: (
- {/*
- navigate(`/view-sponser/${item.id}`) }
- onClick={() => {
- navigate(`/sponser/view-sponser/${item.id}`);
- }}
- _hover={{ color: "green.500" }}
- // transition={"0.5s all"}
- color="green.300"
- rounded={"sm"}
- size={"xs"}
- >
-
-
- */}
-
{
navigate(`/sponser/add-sponser/${item.id}`)}
_hover={{ color: "blue.500" }}
- // transition={"0.5s all"}
color="blue.400"
rounded={"sm"}
size={"xs"}
@@ -272,7 +143,6 @@ const Sponser = () => {
setDeleteAlert(true);
}}
_hover={{ color: "red.500" }}
- // transition={"0.5s all"}
color="red.300"
rounded={"sm"}
size={"xs"}
@@ -284,6 +154,8 @@ const Sponser = () => {
),
}));
+ // =========================== [Delete Function] =================================
+
const handleDelete = async () => {
console.log(actionId);
setIsLoading(true);
@@ -307,6 +179,9 @@ const Sponser = () => {
pt={4}
spacing="24px"
>
+
+ {/* =======================[Search Input]======================== */}
+
{
/>
+
+ {/* ====================[Pagination]===================== */}
+
+ {/* =====================[Add Button]===================== */}
+
}
@@ -336,6 +216,8 @@ const Sponser = () => {
+ {/* =================== [Data Table] ===================== */}
+
{
isLoading={isSponserLoading}
viewActionId={actionId}
setViewActionId={setActionId}
- // totalPages={10}
-
setMouseEnteredId={setMouseEnteredId}
setMouseEntered={setMouseEntered}
/>
+ {/* ======================== [Modal] ======================== */}
+
setDeleteAlert(false)}
isOpen={deleteAlert}
diff --git a/src/Pages/Master/Sponser/ViewSponser.jsx b/src/Pages/Master/Sponser/ViewSponser.jsx
index 350ccfa..b53cd9a 100644
--- a/src/Pages/Master/Sponser/ViewSponser.jsx
+++ b/src/Pages/Master/Sponser/ViewSponser.jsx
@@ -16,10 +16,12 @@ const ViewSponser = () => {
console.log(data?.data);
- if (!data) {
+ if (!data) {
return Loading...;
}
+ // ========================== [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 (
+
+ {/* ======================= [Input Form View] =================== */}
+
+
);
};
diff --git a/src/Routes/Routes.js b/src/Routes/Routes.js
index 15b02b9..133ad99 100644
--- a/src/Routes/Routes.js
+++ b/src/Routes/Routes.js
@@ -40,6 +40,7 @@ import InvestmentType from "../Pages/Master/InvestmentType/InvestmentType";
export const RouteLink = [
// =============[ Tanami ]================
// ===============[ Management]===============
+
{ path: "/", Component: Sponser },
{ path: "/sponser", Component: Sponser },
{ path: "/sponser/add-sponser/:id", Component: AddSponser },
@@ -52,13 +53,8 @@ export const RouteLink = [
{ path: "/exchange-rate", Component: ExchangeRate },
{ path: "/investment-type", Component: InvestmentType },
+ { path: "/investment-type/add-investment/:id", Component: AddInvestmentType },
{ path: "/investment-type/add-investment", Component: AddInvestmentType },
-
-
-
-
-
-
{ path: "/investment-type/view-investment/:id", Component: ViewInvestmentType },
{ path: "/investment-type/edit-investment/:id", Component: EditInvestmentType },
diff --git a/src/Services/investment.type.service.js b/src/Services/investment.type.service.js
index dcd3db9..11638f1 100644
--- a/src/Services/investment.type.service.js
+++ b/src/Services/investment.type.service.js
@@ -8,16 +8,64 @@ const baseUrl = api?.defaults.baseURL;
export const investmentType = createApi({
reducerPath: "investmentType",
baseQuery: fetchBaseQuery({ baseUrl }),
- tagTypes: [],
+ tagTypes: ["getInvestmentType"],
endpoints: (builder) => ({
+
+ // ========[Get All]=========
+
getInvestmentTypes: builder.query({
- query: ({ page, size }) => `/investmentType/admin?page=${page}&size=${size}`,
+ 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/`,
+ method: "POST",
+ body: data,
+ }),
+ invalidatesTags: ["getInvestmentType"],
+ }),
+
+ // ========[Update Investment]=======
+
+ updateInvestmentType: builder.mutation({
+ query: ({ data, id }) => ({
+ url: `/investmentType/admin/${id}`,
+ method: "PATCH",
+ body: data,
+ }),
+ invalidatesTags: ["getInvestmentType"],
+ }),
+
+ // ========[Delete Investment]=======
+
+ deleteInvestmentType: builder.mutation({
+ query: (id) => ({
+ url: `/investmentType/admin/delete/${id}`,
+ method: "DELETE",
+ }),
+ invalidatesTags: ["getSponser"],
+ }),
+
}),
});
// Export hooks for usage in functional components
-export const { useGetInvestmentTypesQuery, useGetInvestmentTypeByIdQuery } = investmentType;
+export const {
+ useGetInvestmentTypesQuery,
+ useGetInvestmentTypeByIdQuery,
+ useCreateInvestmentTypeMutation,
+ useUpdateInvestmentTypeMutation,
+ useDeleteInvestmentTypeMutation,
+} = investmentType;
diff --git a/src/Services/sponser.service.js b/src/Services/sponser.service.js
index d8d7b7e..ccbb971 100644
--- a/src/Services/sponser.service.js
+++ b/src/Services/sponser.service.js
@@ -15,45 +15,35 @@ 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"],
}),
-
-
-
getSponserMasterActive: builder.query({
query: () => "/sponsor/admin/active",
- })
+ }),
-
- ,
-
+ // ======[Get ID]=====
getSponserById: builder.query({
query: (id) => `/sponsor/admin/${id}`,
providesTags: ["getSponser"],
}),
-
-
-
-
-
-
-
-
-
-
-
-
+ // ========[Toggle Status]========
toggleStatus: builder.mutation({
query: ({ id }) => ({
@@ -63,6 +53,8 @@ export const sponserMaster = createApi({
invalidatesTags: ["getSponser"],
}),
+ // ========[Create Sponser]========
+
createSponser: builder.mutation({
query: (data) => ({
url: `/sponsor/admin`,
@@ -72,6 +64,8 @@ export const sponserMaster = createApi({
invalidatesTags: ["getSponser"],
}),
+ // ========[Update Sponser]========
+
updateSponser: builder.mutation({
query: ({ data, id }) => ({
url: `/sponsor/admin/${id}`,
@@ -81,6 +75,8 @@ export const sponserMaster = createApi({
invalidatesTags: ["getSponser"],
}),
+ // ========[Delete Sponser]========
+
deleteSponser: builder.mutation({
query: (id) => ({
url: `/sponsor/admin/delete/${id}`,