diff --git a/src/components/master/CreateActivity.jsx b/src/components/master/CreateActivity.jsx index 62cca207..d64bf361 100644 --- a/src/components/master/CreateActivity.jsx +++ b/src/components/master/CreateActivity.jsx @@ -10,11 +10,19 @@ import showToast from "../../services/toastService"; const schema = z.object({ activityName: z.string().min(1, { message: "Activity Name is required" }), - unitOfMeasurement: z.string().min(1, { message: "Unit of Measurement is required" }), + unitOfMeasurement: z + .string() + .min(1, { message: "Unit of Measurement is required" }), + serviceId: z.string().min(1, { message: "A service selection is required." }), + actitvityGroupId: z + .string() + .min(1, { message: "A activity group selection is required." }), checkList: z .array( z.object({ - description: z.string().min(1, { message: "descriptionlist item cannot be empty" }), + description: z + .string() + .min(1, { message: "description list item cannot be empty" }), isMandatory: z.boolean().default(false), id: z.any().default(null), }) @@ -24,6 +32,12 @@ const schema = z.object({ const CreateActivity = ({ onClose }) => { const [isLoading, setIsLoading] = useState(false); + const [services, setServices] = useState(getCachedData("Services")); + const [selectedService, setSelectedService] = useState(null); + const [activityGroups, setActivityGroups] = useState( + getCachedData("Activity Group") + ); + const [activityGroupList, setActivityGroupList] = useState(null); const { register, @@ -41,10 +55,11 @@ const CreateActivity = ({ onClose }) => { activityName: "", unitOfMeasurement: "", checkList: [], + serviceId: "", + actitvityGroupId: "", }, }); - const { fields: checkListItems, append, @@ -59,15 +74,21 @@ const CreateActivity = ({ onClose }) => { setIsLoading(true); MasterRespository.createActivity(data) - .then( ( resp ) => - { - + .then((resp) => { const cachedData = getCachedData("Activity"); - const updatedData = [ ...cachedData, resp?.data ]; + const updatedData = [...cachedData, resp?.data]; cacheData("Activity", updatedData); showToast("Activity Successfully Added.", "success"); setIsLoading(false); - handleClose() + reset({ + activityName: "", + unitOfMeasurement: "", + checkList: [], + serviceId: "", + actitvityGroupId: "", + }); + setSelectedService(null) + // handleClose(); }) .catch((error) => { showToast(error.message, "error"); @@ -75,7 +96,6 @@ const CreateActivity = ({ onClose }) => { }); }; - const addChecklistItem = () => { const values = getValues("checkList"); const lastIndex = checkListItems.length - 1; @@ -97,11 +117,33 @@ const CreateActivity = ({ onClose }) => { }); }; + const handleServicesChange = (e) => { + const { value } = e.target; + const service = services.find((b) => b.id === String(value)); + const selectedActivityGroups = activityGroups.filter( + (ag) => ag.serviceId == service.id + ); + setSelectedService(service.id); + setActivityGroupList(selectedActivityGroups); + reset((prev) => ({ + ...prev, + serviceId: String(value), + })); + }; + + const handleActivityGroupsChange = (e) => { + const { value } = e.target; + const service = services.find((b) => b.id === String(value)); + reset((prev) => ({ + ...prev, + actitvityGroupId: String(value), + })); + }; + const removeChecklistItem = (index) => { remove(index); }; - const handleChecklistChange = (index, value) => { setValue(`checkList.${index}`, value); }; @@ -111,132 +153,230 @@ const CreateActivity = ({ onClose }) => { onClose(); }; - - // for tooltip useEffect(() => { - const tooltipTriggerList = Array.from(document.querySelectorAll('[data-bs-toggle="tooltip"]')); + if (!services) { + MasterRespository.getServices().then((res) => { + setServices(res?.data); + cacheData("Services", res?.data); + }); + } + if (!activityGroups) { + MasterRespository.getActivityGroups().then((res) => { + setActivityGroups(res?.data); + cacheData("Activity Group", res?.data); + }); + } + const tooltipTriggerList = Array.from( + document.querySelectorAll('[data-bs-toggle="tooltip"]') + ); tooltipTriggerList.forEach((el) => new bootstrap.Tooltip(el)); }, []); return (
); diff --git a/src/components/master/CreateActivityGroup.jsx b/src/components/master/CreateActivityGroup.jsx new file mode 100644 index 00000000..4f254e87 --- /dev/null +++ b/src/components/master/CreateActivityGroup.jsx @@ -0,0 +1,174 @@ +import React, { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { MasterRespository } from "../../repositories/MastersRepository"; +import { clearApiCacheKey } from "../../slices/apiCacheSlice"; +import { getCachedData, cacheData } from "../../slices/apiDataManager"; +import showToast from "../../services/toastService"; + +const schema = z.object({ + name: z.string().min(1, { message: "Service Name is required" }), + description: z + .string() + .min(1, { message: "Description is required" }) + .max(255, { message: "Description cannot exceed 255 characters" }), + serviceId: z.string().min(1, { message: "A service selection is required." }), +}); + +const CreateActivityGroup = ({ onClose }) => { + const [isLoading, setIsLoading] = useState(false); + const [services, setServices] = useState(getCachedData("Services")); + + + const { + register, + handleSubmit, + formState: { errors }, + reset, + } = useForm({ + resolver: zodResolver(schema), + defaultValues: { + name: "", + description: "", + serviceId: "", + }, + }); + + const handleServicesChange = (e) => { + const { value } = e.target; + const service = services.find((b) => b.id === String(value)); + reset((prev) => ({ + ...prev, + serviceId: String(value), + })); + }; + + const onSubmit = (data) => { + setIsLoading(true); + const result = { + name: data.name, + description: data.description, + serviceId: data.serviceId, + }; + + MasterRespository.createActivityGroup(result) + .then((resp) => { + setIsLoading(false); + resetForm(); + const cachedData = getCachedData("Activity Group"); + const updatedData = [...cachedData, resp?.data]; + cacheData("Activity Group", updatedData); + showToast("Activity Group Added successfully.", "success"); + + onClose(); + }) + .catch((error) => { + showToast(error.message, "error"); + setIsLoading(false); + }); + }; + const resetForm = () => { + reset({ + name: "", + description: "", + serviceId: "", + }); + setDescriptionLength(0); + }; + + useEffect(() => { + if (!services) { + MasterRespository.getServices().then((res) => { + setServices(res?.data); + cacheData("Services", res?.data); + }); + } + return () => resetForm(); + }, []); + const [descriptionLength, setDescriptionLength] = useState(0); + const maxDescriptionLength = 255; + return ( + <> + + > + ); +}; + +export default CreateActivityGroup; diff --git a/src/components/master/CreateServices.jsx b/src/components/master/CreateServices.jsx new file mode 100644 index 00000000..673d77f1 --- /dev/null +++ b/src/components/master/CreateServices.jsx @@ -0,0 +1,123 @@ +import React, { useEffect,useState } from 'react' +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { MasterRespository } from '../../repositories/MastersRepository'; +import { clearApiCacheKey } from '../../slices/apiCacheSlice'; +import { getCachedData,cacheData } from '../../slices/apiDataManager'; +import showToast from '../../services/toastService'; + + +const schema = z.object({ + name: z.string().min(1, { message: "Service Name is required" }), + description: z.string().min(1, { message: "Description is required" }) + .max(255, { message: "Description cannot exceed 255 characters" }), +}); + +const CreateServices = ({onClose}) => { + + const[isLoading,setIsLoading] = useState(false) + const { + register, + handleSubmit, + formState: { errors },reset + + } = useForm({ + resolver: zodResolver(schema), + defaultValues: { + name: "", + description: "", + + }, + }); + + const onSubmit = (data) => { + setIsLoading(true) + const result = { + name: data.name, + description: data.description, + }; + + MasterRespository.createService(result).then((resp)=>{ + setIsLoading(false) + resetForm() + const cachedData = getCachedData("Services"); + const updatedData = [...cachedData, resp?.data]; + cacheData("Services", updatedData); + showToast("Service Added successfully.", "success"); + + onClose() + }).catch((error)=>{ + showToast(error.message, "error"); + setIsLoading(false) + }) + + + }; + const resetForm = () => { + reset({ + name: "", + description: "" + }); + setDescriptionLength(0); + } + + useEffect(()=>{ + return ()=>resetForm() + },[]) + + const [descriptionLength, setDescriptionLength] = useState(0); + const maxDescriptionLength = 255; + return (<> + + + > + ) +} + +export default CreateServices; \ No newline at end of file diff --git a/src/components/master/EditActivity.jsx b/src/components/master/EditActivity.jsx index 503bf8c0..a601bf07 100644 --- a/src/components/master/EditActivity.jsx +++ b/src/components/master/EditActivity.jsx @@ -2,28 +2,38 @@ import React, { useEffect, useState } from "react"; import { useForm, useFieldArray } from "react-hook-form"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; -import {MasterRespository} from "../../repositories/MastersRepository"; +import { MasterRespository } from "../../repositories/MastersRepository"; import showToast from "../../services/toastService"; -import {getCachedData,cacheData} from "../../slices/apiDataManager"; - +import { getCachedData, cacheData } from "../../slices/apiDataManager"; const schema = z.object({ activityName: z.string().min(1, { message: "Activity name is required" }), unitOfMeasurement: z.string().min(1, { message: "Measurement is required" }), + serviceId: z.string().min(1, { message: "A service selection is required." }), + actitvityGroupId: z + .string() + .min(1, { message: "A activity group selection is required." }), checkList: z .array( z.object({ id: z.any().default(null), - description: z.string().min(1, { message: "Checklist item cannot be empty" }), + description: z + .string() + .min(1, { message: "Checklist item cannot be empty" }), isMandatory: z.boolean().default(false), }) ) .optional(), }); - const UpdateActivity = ({ activityData, onClose }) => { const [isLoading, setIsLoading] = useState(false); + const [services, setServices] = useState(getCachedData("Services")); + const [selectedService, setSelectedService] = useState(null); + const [activityGroups, setActivityGroups] = useState( + getCachedData("Activity Group") + ); + const [activityGroupList, setActivityGroupList] = useState(null); const { register, @@ -35,26 +45,80 @@ const UpdateActivity = ({ activityData, onClose }) => { clearErrors, getValues, formState: { errors }, + watch, } = useForm({ resolver: zodResolver(schema), defaultValues: { - id:activityData.id, - activityName: activityData.activityName, - unitOfMeasurement: activityData.unitOfMeasurement, - checkLists: activityData.checkLists || [], + id: activityData.id, + serviceId: activityData.serviceId || "", + actitvityGroupId: activityData.actitvityGroupId || "", + activityName: activityData.activityName, + unitOfMeasurement: activityData.unitOfMeasurement, + checkLists: activityData.checkLists || [], }, }); - const { fields: checkListItems, append, remove } = useFieldArray({ + const selectedServiceId = watch("serviceId"); + const [selectedActitvityGroupId, setSelectedActitvityGroupId] = useState( + watch("actitvityGroupId") + ); + + const { + fields: checkListItems, + append, + remove, + } = useFieldArray({ control, name: "checkList", }); // Load initial data useEffect(() => { + if (!services) { + MasterRespository.getServices().then((res) => { + setServices(res?.data); + cacheData("Services", res?.data); + }); + } + if (!activityGroups) { + MasterRespository.getActivityGroups().then((res) => { + setActivityGroups(res?.data); + const selectedActivityGroups = res?.data.filter( + (item) => item.serviceId == selectedServiceId + ); + setActivityGroupList(selectedActivityGroups); + cacheData("Activity Group", res?.data); + const isExist = selectedActivityGroups.some( + (item) => item.id === String(watch("actitvityGroupId")) + ); + + if (!isExist) { + reset((prev) => ({ + ...prev, + actitvityGroupId: "", + })); + } + }); + } else { + const selectedActivityGroups = activityGroups.filter( + (item) => item.serviceId == selectedServiceId + ); + setActivityGroupList(selectedActivityGroups); + const isExist = selectedActivityGroups.some( + (item) => item.id === String(watch("actitvityGroupId")) + ); + if (!isExist) { + reset((prev) => ({ + ...prev, + actitvityGroupId: "", + })); + } + } if (activityData) { - reset( { - id:activityData.id, + reset({ + id: activityData.id, + serviceId: activityData.serviceId || "", + actitvityGroupId: activityData.actitvityGroupId || "", activityName: activityData.activityName, unitOfMeasurement: activityData.unitOfMeasurement, checkList: activityData.checkLists || [], @@ -62,42 +126,66 @@ const UpdateActivity = ({ activityData, onClose }) => { } }, [activityData]); - + const handleServicesChange = (e) => { + const { value } = e.target; + const service = services.find((b) => b.id === String(value)); + const selectedActivityGroups = activityGroups.filter( + (ag) => ag.serviceId == service.id + ); + setSelectedService(service.id); + setActivityGroupList(selectedActivityGroups); + reset((prev) => ({ + ...prev, + serviceId: String(value), + })); + }; + + const handleActivityGroupsChange = (e) => { + const { value } = e.target; + setValue("actitvityGroupId", String(value)); + // reset((prev) => ({ + // ...prev, + // actitvityGroupId: String(value), + // })); + setSelectedActitvityGroupId(String(value)); + }; + const handleChecklistChange = (index, value) => { setValue(`checkList.${index}`, value); }; // Submit handler - const onSubmit = async(data) => { + const onSubmit = async (data) => { setIsLoading(true); - - const Activity = {...data, id:activityData.id} - try - { - const response = await MasterRespository.updateActivity( activityData?.id, Activity ); + + const Activity = { ...data, id: activityData.id }; + try { + const response = await MasterRespository.updateActivity( + activityData?.id, + Activity + ); const updatedActivity = response.data; - const cachedData = getCachedData("Activity") - + const cachedData = getCachedData("Activity"); + if (cachedData) { const updatedActivities = cachedData.map((activity) => - activity.id === updatedActivity.id ? { ...activity, ...updatedActivity } : activity + activity.id === updatedActivity.id + ? { ...activity, ...updatedActivity } + : activity ); - - cacheData( "Activity", updatedActivities ); - onClose() + + cacheData("Activity", updatedActivities); + onClose(); } - setIsLoading( false ) + setIsLoading(false); showToast("Activity Successfully Updated", "success"); - } catch ( err ) - { - setIsLoading( false ) + } catch (err) { + setIsLoading(false); showToast("error.message", "error"); } }; - - // Add new checklist item const addChecklistItem = () => { const values = getValues("checkList"); @@ -122,12 +210,13 @@ const UpdateActivity = ({ activityData, onClose }) => { remove(index); }; - - // for tooltip - useEffect(() => { - const tooltipTriggerList = Array.from(document.querySelectorAll('[data-bs-toggle="tooltip"]')); - tooltipTriggerList.forEach((el) => new bootstrap.Tooltip(el)); - }, []); + // for tooltip + useEffect(() => { + const tooltipTriggerList = Array.from( + document.querySelectorAll('[data-bs-toggle="tooltip"]') + ); + tooltipTriggerList.forEach((el) => new bootstrap.Tooltip(el)); + }, []); return (