diff --git a/public/assets/vendor/css/core.css b/public/assets/vendor/css/core.css index a0771547..e65d3662 100644 --- a/public/assets/vendor/css/core.css +++ b/public/assets/vendor/css/core.css @@ -5069,6 +5069,9 @@ fieldset:disabled .btn { .card-group > .card { margin-bottom: var(--bs-card-group-margin); } +.card-minHeight{ + min-height: 430px; +} @media (min-width: 576px) { .card-group { display: flex; diff --git a/src/Context/FabContext.jsx b/src/Context/FabContext.jsx new file mode 100644 index 00000000..7151e6d7 --- /dev/null +++ b/src/Context/FabContext.jsx @@ -0,0 +1,15 @@ +import React, { createContext, useContext, useState } from "react"; + +const FabContext = createContext(); + +export const FabProvider = ({ children }) => { + const [actions, setActions] = useState([]); + + return ( + + {children} + + ); +}; + +export const useFab = () => useContext(FabContext); \ No newline at end of file diff --git a/src/components/Directory/CardViewDirectory.jsx b/src/components/Directory/CardViewDirectory.jsx index a7fe7d32..1dc16cec 100644 --- a/src/components/Directory/CardViewDirectory.jsx +++ b/src/components/Directory/CardViewDirectory.jsx @@ -30,7 +30,7 @@ const CardViewDirectory = ({ (contact?.name || "").trim().split(" ")[1]?.charAt(0) || "" } />{" "} -

{contact.name}

+ {contact.name}
@@ -55,20 +55,19 @@ const CardViewDirectory = ({ setSelectedContact(contact); setIsOpenModal(true); }} - > - - - Modify + + + Modify
  • IsDeleted(contact.id)} > - - Delete + + Delete
  • @@ -80,7 +79,7 @@ const CardViewDirectory = ({
  • -
  • +
  • {contact.organization}
  • @@ -96,52 +95,54 @@ const CardViewDirectory = ({ >
    {contact.contactEmails[0] && ( -
    ); diff --git a/src/components/Directory/DirectorySchema.js b/src/components/Directory/DirectorySchema.js index 3d30292f..915cf10a 100644 --- a/src/components/Directory/DirectorySchema.js +++ b/src/components/Directory/DirectorySchema.js @@ -6,7 +6,7 @@ export const ContactSchema = z contactCategoryId: z.string().nullable().optional(), address: z.string().optional(), description: z.string().min(1, { message: "Description is required" }), - projectIds: z.array(z.string()).min(1, "Project is required"), + projectIds: z.array(z.string()), // min(1, "Project is required") contactEmails: z .array( z.object({ @@ -39,7 +39,7 @@ export const ContactSchema = z }) ) .min(1, { message: "At least one tag is required" }), - bucketIds: z.array(z.string()).optional(), + bucketIds: z.array(z.string()).min(1,{message:"At least one Label required"}), }) // .refine((data) => { diff --git a/src/components/Directory/EmployeeList.jsx b/src/components/Directory/EmployeeList.jsx new file mode 100644 index 00000000..1cb1f9a9 --- /dev/null +++ b/src/components/Directory/EmployeeList.jsx @@ -0,0 +1,147 @@ +import React, { useState } from "react"; +import { useSortableData } from "../../hooks/useSortableData"; + +const EmployeeList = ({ employees }) => { + const [selectedIds, setSelectedIds] = useState([]); + const [searchTerm, setSearchTerm] = useState(""); + + const handleCheckboxChange = (id) => { + setSelectedIds((prev) => + prev.includes(id) ? prev?.filter((empId) => empId !== id) : [...prev, id] + ); + }; + + const getSelectedEmployees = () => { + console.log("Selected Employee IDs:", selectedIds); + }; + + const { + items: sortedEmployees, + requestSort, + sortConfig, + } = useSortableData(employees, { + key: (e) => `${e?.firstName} ${e?.lastName}`, + direction: "asc", + }); + + const getSortIcon = () => { + if (!sortConfig) return null; + return sortConfig.direction === "asc" ? ( + + ) : ( + + ); + }; + + const filteredEmployees = sortedEmployees?.filter((employee) => { + const fullName = + `${employee?.firstName} ${employee?.lastName}`?.toLowerCase(); + // const email = employee.email.toLowerCase(); + // const role = employee.jobRole.toLowerCase(); + const term = searchTerm?.toLowerCase(); + + return fullName.includes(term); + // email.includes(term) || + // role.includes(term) + }); + + return ( + <> +
    +

    Add Employee

    +
    + setSearchTerm(e.target.value)} + /> +
    +
    + +
    + + + + + + + + + + + + {employees.length === 0 ? ( + + + + ) : filteredEmployees.length === 0 ? ( + + + + ) : ( + filteredEmployees?.map((employee) => ( + + + + + + + )) + )} + +
    + requestSort((e) => `${e.firstName} ${e.lastName}`) + } + className="text-start cursor-pointer" + > + Name {getSortIcon()} + RoleStatusBucket
    +
    + No Employee Available +
    +
    +
    + No Matchinng Employee Found. +
    +
    +
    + handleCheckboxChange(employee.id)} + /> +
    +

    + {`${employee.firstName} ${employee.lastName}`} +

    + {employee.email} +
    +
    +
    + {employee.jobRole} + + + {employee.isActive ? "Active" : "Inactive"} + + + + {" "} + {employee.jobRole} + +
    +
    + + ); +}; + +export default EmployeeList; diff --git a/src/components/Directory/ManageBucket.jsx b/src/components/Directory/ManageBucket.jsx index d3a5d5c3..60f59e5b 100644 --- a/src/components/Directory/ManageBucket.jsx +++ b/src/components/Directory/ManageBucket.jsx @@ -8,15 +8,36 @@ import Directory from "../../pages/Directory/Directory"; import { DirectoryRepository } from "../../repositories/DirectoryRepository"; import { cacheData, getCachedData } from "../../slices/apiDataManager"; import { useBuckets } from "../../hooks/useDirectory"; +import EmployeeList from "./EmployeeList"; +import { useAllEmployees, useEmployees } from "../../hooks/useEmployees"; +import { useSortableData } from "../../hooks/useSortableData"; +import ConfirmModal from "../common/ConfirmModal"; -const ManageBucket = () => -{ +const ManageBucket = () => { const [bucketList, setBucketList] = useState([]); - - const { buckets } = useBuckets(); + const { employeesList } = useAllEmployees(false); + const { buckets, loading,refetch } = useBuckets(); const [action_bucket, setAction_bucket] = useState(false); const [isSubmitting, setSubmitting] = useState(false); const [selected_bucket, select_bucket] = useState(null); + const [deleteBucket, setDeleteBucket] = useState(null); + const [searchTerm, setSearchTerm] = useState(""); + const { + items: sortedBuckteList, + requestSort, + sortConfig, + } = useSortableData(bucketList, { + key: (e) => `${e.name}`, + direction: "asc", + }); + const getSortIcon = () => { + if (!sortConfig) return null; + return sortConfig.direction === "asc" ? ( + + ) : ( + + ); + }; const { register, @@ -29,197 +50,290 @@ const ManageBucket = () => name: "", description: "", }, - } ); - - const onSubmit = async (data) => { - setSubmitting(true); - try { - let response; + }); - if ( selected_bucket ) - { - let payload ={...data, id:selected_bucket.id} - response = await DirectoryRepository.UpdateBuckets(selected_bucket.id, payload); - const cache_buckets = getCachedData("buckets") || []; - const updatedBuckets = cache_buckets.map((bucket) => - bucket.id === selected_bucket.id ? response?.data : bucket - ); - cacheData( "buckets", updatedBuckets ); - setBucketList(updatedBuckets); - showToast("Bucket Updated Successfully", "success"); - } else { - response = await DirectoryRepository.CreateBuckets(data); - const cache_buckets = getCachedData("buckets") || []; - const updatedBuckets = [...cache_buckets, response?.data]; - cacheData( "buckets", updatedBuckets ); - setBucketList(updatedBuckets); - showToast("Bucket Created Successfully", "success"); + const onSubmit = async (data) => { + setSubmitting(true); + try { + let response; + + if (selected_bucket) { + let payload = { ...data, id: selected_bucket.id }; + response = await DirectoryRepository.UpdateBuckets( + selected_bucket.id, + payload + ); + const cache_buckets = getCachedData("buckets") || []; + const updatedBuckets = cache_buckets.map((bucket) => + bucket.id === selected_bucket.id ? response?.data : bucket + ); + cacheData("buckets", updatedBuckets); + setBucketList(updatedBuckets); + showToast("Bucket Updated Successfully", "success"); + } else { + response = await DirectoryRepository.CreateBuckets(data); + const cache_buckets = getCachedData("buckets") || []; + const updatedBuckets = [...cache_buckets, response?.data]; + cacheData("buckets", updatedBuckets); + setBucketList(updatedBuckets); + showToast("Bucket Created Successfully", "success"); + } + + handleBack(); + } catch (error) { + const message = + error?.response?.data?.message || + error?.message || + "Error occurred during API call"; + showToast(message, "error"); } + }; - handleBack(); - } catch (error) { - const message = - error?.response?.data?.message || - error?.message || - "Error occurred during API call"; - showToast(message, "error"); - } -}; - + const handleDeleteContact = async () => { + try { + const resp = await DirectoryRepository.DeleteBucket( deleteBucket ); + const cache_buckets = getCachedData("buckets") || []; + const updatedBuckets = cache_buckets.filter((bucket) => + bucket.id != deleteBucket + ); + cacheData("buckets", updatedBuckets); + setBucketList(updatedBuckets); + showToast("Bucket deleted successfully", "success"); + setDeleteBucket(null); + } catch (error) { + const message = + error?.response?.data?.message || + error?.message || + "Error occurred during API call."; + showToast(message, "error"); + } + }; useEffect(() => { reset({ name: selected_bucket?.name || "", description: selected_bucket?.description || "", }); - }, [ selected_bucket ] ); + }, [selected_bucket]); + + useEffect(() => { + setBucketList(buckets); + }, [buckets]); - useEffect( () => - { - setBucketList( buckets ) - }, [ buckets ] ) - const handleBack = () => { select_bucket(null); setAction_bucket(false); setSubmitting(false); }; + const sortedBucktesList = sortedBuckteList?.filter((bucket) => { + const term = searchTerm?.toLowerCase(); + const name = bucket.name?.toLowerCase(); + return name?.includes(term); + }); return ( -
    -
    -

    Manage Buckets

    -
    -
    - - -
    -
    - {!action_bucket ? ( -
    - - - - - - - - + setDeleteBucket(null)} + // loading={IsDeleting} + /> + + )} - - {bucketList.map((bucket) => ( - - - - - - ))} - -
    -
    - - Name -
    -
    -
    - - Description -
    -
    -
    - - Action -
    -
    - {bucket.name} - - {bucket.description} - -
    - { - select_bucket(bucket); - setAction_bucket(true); - }} - > - - - -
    -
    -
    - ) : ( -
    -
    - +
    +
    +

    Manage Buckets

    +
    +
    + {action_bucket ? ( + + ) : ( +
    - {errors.name && ( - {errors.name.message} - )} + placeholder="Search Bucket ..." + value={searchTerm} + onChange={(e) => setSearchTerm(e.target.value)} + /> + rrefetch()} + />
    -
    - -