Compare commits
6 Commits
2428f15f35
...
f4a09c7f53
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4a09c7f53 | ||
|
|
ec80121621 | ||
|
|
c2b91b9737 | ||
|
|
a7421eb6dc | ||
|
|
8608043fb2 | ||
|
|
55b9420b6c |
@ -13,10 +13,7 @@ export const ReportTask = ({ report, closeModal, refetch }) => {
|
|||||||
completedTask: z
|
completedTask: z
|
||||||
.number()
|
.number()
|
||||||
.min(1, "Completed Work must be at least 1")
|
.min(1, "Completed Work must be at least 1")
|
||||||
.max(
|
|
||||||
report?.plannedTask,
|
|
||||||
`Completed Work cannot exceed ${report?.plannedTask}`
|
|
||||||
)
|
|
||||||
.int("Completed Work must be an integer")
|
.int("Completed Work must be an integer")
|
||||||
.positive("Completed Work must be a positive number")
|
.positive("Completed Work must be a positive number")
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|||||||
@ -63,7 +63,7 @@ const ManageEmployee = () => {
|
|||||||
CurrentAddress: z
|
CurrentAddress: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Current Address is required" })
|
.min(1, { message: "Current Address is required" })
|
||||||
.max(150, { message: "Address cannot exceed 150 characters" }),
|
.max(250, { message: "Address cannot exceed 250 characters" }),
|
||||||
BirthDate: z
|
BirthDate: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Birth Date is required" })
|
.min(1, { message: "Birth Date is required" })
|
||||||
@ -112,7 +112,7 @@ const ManageEmployee = () => {
|
|||||||
PermanentAddress: z
|
PermanentAddress: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Permanent Address is required" })
|
.min(1, { message: "Permanent Address is required" })
|
||||||
.max(150, { message: "Address cannot exceed 150 characters" }),
|
.max(250, { message: "Address cannot exceed 250 characters" }),
|
||||||
PhoneNumber: z
|
PhoneNumber: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, { message: "Phone Number is required" })
|
.min(1, { message: "Phone Number is required" })
|
||||||
|
|||||||
@ -89,8 +89,7 @@ const onSubmit = async(data) => {
|
|||||||
};
|
};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// let response = await TasksRepository.assignTask( formattedData );
|
let response = await TasksRepository.assignTask( formattedData );
|
||||||
// console.log( response )
|
|
||||||
showToast( "Task Successfully Assigend", "success" )
|
showToast( "Task Successfully Assigend", "success" )
|
||||||
reset()
|
reset()
|
||||||
closeModal()
|
closeModal()
|
||||||
|
|||||||
@ -2,6 +2,9 @@ import React, { useState, useEffect } from "react";
|
|||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import {useDispatch} from "react-redux";
|
||||||
|
import {changeMaster} from "../../../slices/localVariablesSlice";
|
||||||
|
import useMaster from "../../../hooks/masterHook/useMaster";
|
||||||
|
|
||||||
// Define Zod validation schema
|
// Define Zod validation schema
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
@ -23,11 +26,12 @@ const defaultModel = {
|
|||||||
|
|
||||||
const TaskModel = ({
|
const TaskModel = ({
|
||||||
project,
|
project,
|
||||||
activities,
|
|
||||||
onSubmit,
|
onSubmit,
|
||||||
clearTrigger,
|
clearTrigger,
|
||||||
onClearComplete,onClose
|
onClearComplete,onClose
|
||||||
}) => {
|
} )=>{
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const {data:activities,loading} = useMaster()
|
||||||
const [formData, setFormData] = useState(defaultModel);
|
const [formData, setFormData] = useState(defaultModel);
|
||||||
const [selectedBuilding, setSelectedBuilding] = useState(null);
|
const [selectedBuilding, setSelectedBuilding] = useState(null);
|
||||||
const [selectedFloor, setSelectedFloor] = useState(null);
|
const [selectedFloor, setSelectedFloor] = useState(null);
|
||||||
@ -90,8 +94,6 @@ const TaskModel = ({
|
|||||||
|
|
||||||
const onSubmitForm = ( data ) =>
|
const onSubmitForm = ( data ) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
onSubmit( data );
|
onSubmit( data );
|
||||||
setSelectedActivity(null),
|
setSelectedActivity(null),
|
||||||
setSelectedWorkArea(null)
|
setSelectedWorkArea(null)
|
||||||
@ -104,6 +106,8 @@ const TaskModel = ({
|
|||||||
|
|
||||||
useEffect( () =>
|
useEffect( () =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
dispatch(changeMaster("Activity")),
|
||||||
() =>{
|
() =>{
|
||||||
resetVlaue ()
|
resetVlaue ()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,7 +82,10 @@ const ManageProjectInfo = ( {project,handleSubmitForm, onClose} ) =>
|
|||||||
handleSubmitForm( updatedProject )
|
handleSubmitForm( updatedProject )
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect( () =>
|
||||||
|
{
|
||||||
|
return ()=>setLoading(false)
|
||||||
|
},[])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -17,7 +17,6 @@ import { useProjectDetails } from "../../hooks/useProjects";
|
|||||||
|
|
||||||
const ProjectInfra = ({
|
const ProjectInfra = ({
|
||||||
data,
|
data,
|
||||||
activityMaster,
|
|
||||||
onDataChange,
|
onDataChange,
|
||||||
eachSiteEngineer,
|
eachSiteEngineer,
|
||||||
}) => {
|
}) => {
|
||||||
@ -57,130 +56,6 @@ const ProjectInfra = ({
|
|||||||
setIsBuildingModalOpen(true);
|
setIsBuildingModalOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const submitData = async (infraObject) => {
|
|
||||||
try {
|
|
||||||
let response = await ProjectRepository.manageProjectInfra(infraObject);
|
|
||||||
const entity = response.data;
|
|
||||||
|
|
||||||
const updatedProject = { ...project };
|
|
||||||
// Handle the building data
|
|
||||||
if (entity.building) {
|
|
||||||
const { id, name, description } = entity.building;
|
|
||||||
const updatedBuildings = updatedProject?.buildings?.map((building) =>
|
|
||||||
building.id === id ? { ...building, name, description } : building
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add building if it doesn't exist
|
|
||||||
if (!updatedProject.buildings.some((building) => building.id === id)) {
|
|
||||||
updatedBuildings.push({
|
|
||||||
id: id,
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
floors: [],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedProject.buildings = updatedBuildings;
|
|
||||||
|
|
||||||
// Update the cache for buildings
|
|
||||||
cacheData("projectInfo", {
|
|
||||||
projectId: updatedProject.id,
|
|
||||||
data: updatedProject,
|
|
||||||
});
|
|
||||||
setProject((prevProject) => ({
|
|
||||||
...prevProject,
|
|
||||||
buildings: updatedBuildings,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
// Handle the floor data
|
|
||||||
else if (entity.floor) {
|
|
||||||
const { buildingId, id, floorName } = entity.floor;
|
|
||||||
const updatedBuildings = updatedProject?.buildings?.map((building) =>
|
|
||||||
building.id == buildingId
|
|
||||||
? {
|
|
||||||
...building,
|
|
||||||
floors: building.floors
|
|
||||||
.map((floor) =>
|
|
||||||
floor.id === id
|
|
||||||
? {
|
|
||||||
...floor,
|
|
||||||
floorName, // Update the floor name only
|
|
||||||
// Keep other properties as they are (including workArea)
|
|
||||||
}
|
|
||||||
: floor
|
|
||||||
)
|
|
||||||
// Add the new floor if it doesn't already exist
|
|
||||||
.concat(
|
|
||||||
!building.floors.some((floor) => floor.id === id)
|
|
||||||
? [{ id: id, floorName, workAreas: [] }] // New floor added with workArea set to null
|
|
||||||
: []
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: building
|
|
||||||
);
|
|
||||||
|
|
||||||
updatedProject.buildings = updatedBuildings;
|
|
||||||
|
|
||||||
// Cache the updated project
|
|
||||||
cacheData("projectInfo", {
|
|
||||||
projectId: updatedProject.id,
|
|
||||||
data: updatedProject,
|
|
||||||
});
|
|
||||||
setProject(updatedProject);
|
|
||||||
}
|
|
||||||
// Handle the work area data
|
|
||||||
else if (entity.workArea) {
|
|
||||||
let buildingId = infraObject[0].workArea.buildingId;
|
|
||||||
|
|
||||||
const { floorId, areaName, id } = entity.workArea;
|
|
||||||
// Check if the workArea exists, otherwise create a new one
|
|
||||||
const updatedBuildings = updatedProject.buildings.map((building) =>
|
|
||||||
building.id == buildingId
|
|
||||||
? {
|
|
||||||
...building,
|
|
||||||
floors: building.floors.map((floor) =>
|
|
||||||
floor.id == floorId
|
|
||||||
? {
|
|
||||||
...floor,
|
|
||||||
workAreas: floor.workAreas.some(
|
|
||||||
(workArea) => workArea.id === id
|
|
||||||
)
|
|
||||||
? floor.workAreas.map((workArea) =>
|
|
||||||
workArea.id === id
|
|
||||||
? { ...workArea, areaName }
|
|
||||||
: workArea
|
|
||||||
)
|
|
||||||
: [
|
|
||||||
...floor.workAreas,
|
|
||||||
{ id, areaName, workItems: [] },
|
|
||||||
],
|
|
||||||
}
|
|
||||||
: floor
|
|
||||||
),
|
|
||||||
}
|
|
||||||
: building
|
|
||||||
);
|
|
||||||
|
|
||||||
updatedProject.buildings = updatedBuildings;
|
|
||||||
|
|
||||||
// Update the cache for work areas
|
|
||||||
cacheData("projectInfo", {
|
|
||||||
projectId: updatedProject.id,
|
|
||||||
data: updatedProject,
|
|
||||||
});
|
|
||||||
setProject(updatedProject);
|
|
||||||
}
|
|
||||||
// Handle the task (workItem) data
|
|
||||||
else {
|
|
||||||
console.error("Unsupported data type for submitData", entity);
|
|
||||||
}
|
|
||||||
} catch (Err) {
|
|
||||||
console.log(Err);
|
|
||||||
showToast("Somthing wrong", "error");
|
|
||||||
}
|
|
||||||
handleClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeBuildingModel = () => {
|
const closeBuildingModel = () => {
|
||||||
setIsBuildingModalOpen(false);
|
setIsBuildingModalOpen(false);
|
||||||
};
|
};
|
||||||
@ -292,6 +167,139 @@ const ProjectInfra = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const submitData = async (infraObject) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
debugger
|
||||||
|
|
||||||
|
let response = await ProjectRepository.manageProjectInfra(infraObject);
|
||||||
|
const entity = response.data;
|
||||||
|
|
||||||
|
const updatedProject = { ...project };
|
||||||
|
// Handle the building data
|
||||||
|
if (entity.building) {
|
||||||
|
const { id, name, description } = entity.building;
|
||||||
|
const updatedBuildings = updatedProject?.buildings?.map((building) =>
|
||||||
|
building.id === id ? { ...building, name, description } : building
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add building if it doesn't exist
|
||||||
|
if (!updatedProject.buildings.some((building) => building.id === id)) {
|
||||||
|
updatedBuildings.push({
|
||||||
|
id: id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
floors: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedProject.buildings = updatedBuildings;
|
||||||
|
|
||||||
|
// Update the cache for buildings
|
||||||
|
cacheData("projectInfo", {
|
||||||
|
projectId: updatedProject.id,
|
||||||
|
data: updatedProject,
|
||||||
|
});
|
||||||
|
setProject((prevProject) => ({
|
||||||
|
...prevProject,
|
||||||
|
buildings: updatedBuildings,
|
||||||
|
} ) );
|
||||||
|
closeBuildingModel()
|
||||||
|
}
|
||||||
|
// Handle the floor data
|
||||||
|
else if (entity.floor) {
|
||||||
|
const { buildingId, id, floorName } = entity.floor;
|
||||||
|
const updatedBuildings = updatedProject?.buildings?.map((building) =>
|
||||||
|
building.id == buildingId
|
||||||
|
? {
|
||||||
|
...building,
|
||||||
|
floors: building.floors
|
||||||
|
.map((floor) =>
|
||||||
|
floor.id === id
|
||||||
|
? {
|
||||||
|
...floor,
|
||||||
|
floorName, // Update the floor name only
|
||||||
|
// Keep other properties as they are (including workArea)
|
||||||
|
}
|
||||||
|
: floor
|
||||||
|
)
|
||||||
|
// Add the new floor if it doesn't already exist
|
||||||
|
.concat(
|
||||||
|
!building.floors.some((floor) => floor.id === id)
|
||||||
|
? [{ id: id, floorName, workAreas: [] }] // New floor added with workArea set to null
|
||||||
|
: []
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: building
|
||||||
|
);
|
||||||
|
|
||||||
|
updatedProject.buildings = updatedBuildings;
|
||||||
|
|
||||||
|
// Cache the updated project
|
||||||
|
cacheData("projectInfo", {
|
||||||
|
projectId: updatedProject.id,
|
||||||
|
data: updatedProject,
|
||||||
|
});
|
||||||
|
setProject( updatedProject );
|
||||||
|
closeFloorModel()
|
||||||
|
}
|
||||||
|
// Handle the work area data
|
||||||
|
else if ( entity.workArea )
|
||||||
|
{
|
||||||
|
let buildingId = infraObject[0].workArea.buildingId;
|
||||||
|
|
||||||
|
const { floorId, areaName, id } = entity.workArea;
|
||||||
|
// Check if the workArea exists, otherwise create a new one
|
||||||
|
const updatedBuildings = updatedProject.buildings.map((building) =>
|
||||||
|
building.id == buildingId
|
||||||
|
? {
|
||||||
|
...building,
|
||||||
|
floors: building.floors.map((floor) =>
|
||||||
|
floor.id == floorId
|
||||||
|
? {
|
||||||
|
...floor,
|
||||||
|
workAreas: floor.workAreas.some(
|
||||||
|
(workArea) => workArea.id === id
|
||||||
|
)
|
||||||
|
? floor.workAreas.map((workArea) =>
|
||||||
|
workArea.id === id
|
||||||
|
? { ...workArea, areaName }
|
||||||
|
: workArea
|
||||||
|
)
|
||||||
|
: [
|
||||||
|
...floor.workAreas,
|
||||||
|
{ id, areaName, workItems: [] },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: floor
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: building
|
||||||
|
);
|
||||||
|
|
||||||
|
updatedProject.buildings = updatedBuildings;
|
||||||
|
|
||||||
|
// Update the cache for work areas
|
||||||
|
cacheData("projectInfo", {
|
||||||
|
projectId: updatedProject.id,
|
||||||
|
data: updatedProject,
|
||||||
|
});
|
||||||
|
setProject( updatedProject );
|
||||||
|
closeWorkAreaModel()
|
||||||
|
}
|
||||||
|
// Handle the task (workItem) data
|
||||||
|
else {
|
||||||
|
console.error("Unsupported data type for submitData", entity);
|
||||||
|
}
|
||||||
|
} catch (Err) {
|
||||||
|
console.log(Err);
|
||||||
|
showToast("Somthing wrong", "error");
|
||||||
|
}
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const toggleBuilding = (id) => {
|
const toggleBuilding = (id) => {
|
||||||
setExpandedBuildings((prev) =>
|
setExpandedBuildings((prev) =>
|
||||||
prev.includes(id) ? prev.filter((bid) => bid !== id) : [...prev, id]
|
prev.includes(id) ? prev.filter((bid) => bid !== id) : [...prev, id]
|
||||||
@ -400,7 +408,7 @@ const ProjectInfra = ({
|
|||||||
>
|
>
|
||||||
<TaskModel
|
<TaskModel
|
||||||
project={project}
|
project={project}
|
||||||
activities={activityMaster}
|
|
||||||
onClose={closeTaskModel}
|
onClose={closeTaskModel}
|
||||||
onSubmit={handleTaskModelFormSubmit}
|
onSubmit={handleTaskModelFormSubmit}
|
||||||
clearTrigger={clearFormTrigger}
|
clearTrigger={clearFormTrigger}
|
||||||
@ -463,6 +471,7 @@ const ProjectInfra = ({
|
|||||||
<InfraTable
|
<InfraTable
|
||||||
buildings={project?.buildings}
|
buildings={project?.buildings}
|
||||||
project={project}
|
project={project}
|
||||||
|
handleFloor={submitData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
205
src/components/master/CreateActivity.jsx
Normal file
205
src/components/master/CreateActivity.jsx
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
import React,{useState,useEffect} from 'react'
|
||||||
|
import {useFieldArray, 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({
|
||||||
|
activityName: z.string().min(1, { message: "Role is required" }),
|
||||||
|
unitOfMeasurement: z.string().min(1, { message: "Description is required" }),
|
||||||
|
checkList: z
|
||||||
|
.array(z.string().min(1, { message: "Checklist item cannot be empty" }))
|
||||||
|
.optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const CreateActivity = () =>
|
||||||
|
{
|
||||||
|
|
||||||
|
const [ isLoading, setIsLoading ] = useState( false )
|
||||||
|
|
||||||
|
// const {
|
||||||
|
// register,
|
||||||
|
// handleSubmit,
|
||||||
|
// formState: { errors },reset
|
||||||
|
// } = useForm({
|
||||||
|
// resolver: zodResolver(schema),
|
||||||
|
// defaultValues: {
|
||||||
|
// activityName: "",
|
||||||
|
// unitOfMeasurement: "",
|
||||||
|
// checkList: ['']
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const onSubmit = (data) => {
|
||||||
|
// setIsLoading(true)
|
||||||
|
// const result = {
|
||||||
|
// name: data.activityName,
|
||||||
|
// description: data.unitOfMeasurement,
|
||||||
|
// };
|
||||||
|
// console.log( result )
|
||||||
|
// reset()
|
||||||
|
// MasterRespository.createJobRole(result).then((resp)=>{
|
||||||
|
// setIsLoading(false)
|
||||||
|
// resetForm()
|
||||||
|
// const cachedData = getCachedData("Job Role");
|
||||||
|
// const updatedData = [...cachedData, resp?.data];
|
||||||
|
// cacheData("Job Role", updatedData);
|
||||||
|
// showToast("JobRole Added successfully.", "success");
|
||||||
|
|
||||||
|
// onClose()
|
||||||
|
// }).catch((error)=>{
|
||||||
|
// showToast(error.message, "error");
|
||||||
|
// setIsLoading(false)
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
// };
|
||||||
|
// const resetForm =()=>{
|
||||||
|
// reset({
|
||||||
|
// activityName:"",
|
||||||
|
// unitOfMeasurement:""
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// useEffect(()=>{
|
||||||
|
// return ()=>resetForm()
|
||||||
|
// }, [] )
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
control,
|
||||||
|
setValue,
|
||||||
|
clearErrors,
|
||||||
|
setError,
|
||||||
|
getValues,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: zodResolver(schema),
|
||||||
|
defaultValues: {
|
||||||
|
activityName: '',
|
||||||
|
unitOfMeasurement: '',
|
||||||
|
checkList: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setting up field array for checkList (dynamic fields)
|
||||||
|
const {
|
||||||
|
fields: checkListItems,
|
||||||
|
append,
|
||||||
|
remove,
|
||||||
|
} = useFieldArray({
|
||||||
|
control,
|
||||||
|
name: 'checkList',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Form submission handler
|
||||||
|
const onSubmit = (data) => {
|
||||||
|
console.log('Submitted:', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a new checklist item
|
||||||
|
const addChecklistItem = () => {
|
||||||
|
const values = getValues('checkList');
|
||||||
|
const lastIndex = checkListItems.length - 1;
|
||||||
|
|
||||||
|
|
||||||
|
if (checkListItems.length > 0 && (!values?.[lastIndex] || values[lastIndex].trim() === '')) {
|
||||||
|
setError(`checkList.${lastIndex}`, {
|
||||||
|
type: 'manual',
|
||||||
|
message: 'Please fill this checklist item before adding another.',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearErrors(`checkList.${lastIndex}`); // Clear the error if the input is filled.
|
||||||
|
append(''); // Add a new empty checklist input
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const removeChecklistItem = (index) => {
|
||||||
|
remove(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle checklist item input change
|
||||||
|
const handleChecklistChange = (index, value) => {
|
||||||
|
setValue(`checkList.${index}`, value);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-6">
|
||||||
|
<label className="form-label">Activity</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
{...register('activityName')}
|
||||||
|
className={`form-control form-control-sm ${errors.activityName ? 'is-invalid' : ''}`}
|
||||||
|
/>
|
||||||
|
{errors.activityName && <p className="danger-text">{errors.activityName.message}</p>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-6">
|
||||||
|
<label className="form-label">Measurement</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
{...register('unitOfMeasurement')}
|
||||||
|
className={`form-control form-control-sm ${errors.unitOfMeasurement ? 'is-invalid' : ''}`}
|
||||||
|
/>
|
||||||
|
{errors.unitOfMeasurement && (
|
||||||
|
<p className="danger-text">{errors.unitOfMeasurement.message}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-6 text-start">
|
||||||
|
{/* Dynamic checklist items */}
|
||||||
|
{checkListItems.map((item, index) => (
|
||||||
|
<div key={item.id} className=" align-items-center my-1">
|
||||||
|
<div className='d-flex align-items-center gap-2'>
|
||||||
|
<input
|
||||||
|
{...register(`checkList.${index}`)}
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
placeholder={`Checklist item ${index + 1}`}
|
||||||
|
onChange={(e) => handleChecklistChange(index, e.target.value)} // Handle input change
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => removeChecklistItem(index)} // Remove button
|
||||||
|
className="btn btn-xs btn-icon btn-text-secondary"
|
||||||
|
>
|
||||||
|
<span class='icon-base bx bx bx-x'></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{errors.checkList?.[index] && (
|
||||||
|
<p className="danger-text">{errors.checkList[index]?.message}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{/* Add new checklist item */}
|
||||||
|
<button type="button" className="btn btn-sm btn-primary mt-2" onClick={addChecklistItem}>
|
||||||
|
+ Add Checklist Item
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 text-center mt-3">
|
||||||
|
<button type="submit" className="btn btn-sm btn-primary me-3">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
className="btn btn-sm btn-label-secondary"
|
||||||
|
onClick={() => reset()}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CreateActivity
|
||||||
175
src/components/master/EditActivity.jsx
Normal file
175
src/components/master/EditActivity.jsx
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { useFieldArray, useForm } from 'react-hook-form';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
|
||||||
|
// Zod Schema for validation
|
||||||
|
const schema = z.object({
|
||||||
|
activityName: z.string().min(1, { message: "Activity name is required" }),
|
||||||
|
unitOfMeasurement: z.string().min(1, { message: "Measurement is required" }),
|
||||||
|
checkList: z
|
||||||
|
.array(z.string().min(1, { message: "Checklist item cannot be empty" }))
|
||||||
|
.optional(),
|
||||||
|
} );
|
||||||
|
|
||||||
|
// for demo data
|
||||||
|
let initialData = {
|
||||||
|
activityName: "Item",
|
||||||
|
unitOfMeasurement: "Item-2",
|
||||||
|
checkList: [
|
||||||
|
'item 3',
|
||||||
|
'Item 4'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const EditActivity = ({onClose}) => {
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
control,
|
||||||
|
setValue,
|
||||||
|
clearErrors,
|
||||||
|
setError,
|
||||||
|
getValues,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: zodResolver(schema),
|
||||||
|
defaultValues: {
|
||||||
|
activityName: '',
|
||||||
|
unitOfMeasurement: '',
|
||||||
|
checkList: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setting up field array for checkList (dynamic fields)
|
||||||
|
const {
|
||||||
|
fields: checkListItems,
|
||||||
|
append,
|
||||||
|
remove,
|
||||||
|
} = useFieldArray({
|
||||||
|
control,
|
||||||
|
name: 'checkList',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pre-populating the form with initial data when component mounts or initialData changes
|
||||||
|
useEffect(() => {
|
||||||
|
if (initialData) {
|
||||||
|
reset({
|
||||||
|
activityName: initialData.activityName,
|
||||||
|
unitOfMeasurement: initialData.unitOfMeasurement,
|
||||||
|
checkList: initialData.checkList || [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [initialData, reset]);
|
||||||
|
|
||||||
|
// Form submission handler
|
||||||
|
const onSubmit = (data) => {
|
||||||
|
console.log('Submitted:', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a new checklist item
|
||||||
|
const addChecklistItem = () => {
|
||||||
|
const values = getValues('checkList');
|
||||||
|
const lastIndex = checkListItems.length - 1;
|
||||||
|
|
||||||
|
// Prevent adding new input if the last one is empty
|
||||||
|
if (checkListItems.length > 0 && (!values?.[lastIndex] || values[lastIndex].trim() === '')) {
|
||||||
|
setError(`checkList.${lastIndex}`, {
|
||||||
|
type: 'manual',
|
||||||
|
message: 'Please fill this checklist item before adding another.',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearErrors(`checkList.${lastIndex}`); // Clear the error if the input is filled.
|
||||||
|
append(''); // Add a new empty checklist input
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove a checklist item
|
||||||
|
const removeChecklistItem = (index) => {
|
||||||
|
remove(index); // Remove the checklist item from the field array
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle checklist item input change
|
||||||
|
const handleChecklistChange = (index, value) => {
|
||||||
|
setValue(`checkList.${index}`, value); // Update the value of the checklist item
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCLose = () =>
|
||||||
|
{
|
||||||
|
() => reset()
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-6">
|
||||||
|
<label className="form-label">Activity</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
{...register('activityName')}
|
||||||
|
className={`form-control form-control-sm ${errors.activityName ? 'is-invalid' : ''}`}
|
||||||
|
/>
|
||||||
|
{errors.activityName && <p className="danger-text">{errors.activityName.message}</p>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-6">
|
||||||
|
<label className="form-label">Measurement</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
{...register('unitOfMeasurement')}
|
||||||
|
className={`form-control form-control-sm ${errors.unitOfMeasurement ? 'is-invalid' : ''}`}
|
||||||
|
/>
|
||||||
|
{errors.unitOfMeasurement && (
|
||||||
|
<p className="danger-text">{errors.unitOfMeasurement.message}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-6 text-start">
|
||||||
|
{/* Dynamic checklist items */}
|
||||||
|
{checkListItems.map((item, index) => (
|
||||||
|
<div key={item.id} className="d-flex align-items-center gap-2 my-1">
|
||||||
|
<input
|
||||||
|
{...register(`checkList.${index}`)}
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
placeholder={`Checklist item ${index + 1}`}
|
||||||
|
onChange={(e) => handleChecklistChange(index, e.target.value)} // Handle input change
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => removeChecklistItem(index)} // Remove button
|
||||||
|
className="btn btn-xs btn-icon btn-text-secondary"
|
||||||
|
>
|
||||||
|
<span className="icon-base bx bx-x"/>
|
||||||
|
</button>
|
||||||
|
{errors.checkList?.[index] && (
|
||||||
|
<p className="danger-text">{errors.checkList[index]?.message}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{/* Add new checklist item */}
|
||||||
|
<button type="button" className="btn btn-sm btn-primary mt-2" onClick={addChecklistItem}>
|
||||||
|
+ Add Checklist Item
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 text-center mt-3">
|
||||||
|
<button type="submit" className="btn btn-sm btn-primary me-3">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
className="btn btn-sm btn-label-secondary"
|
||||||
|
onClick={handleCLose}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditActivity;
|
||||||
@ -5,53 +5,62 @@ import DeleteMaster from "./DeleteMaster";
|
|||||||
import EditRole from "./EditRole";
|
import EditRole from "./EditRole";
|
||||||
import CreateJobRole from "./CreateJobRole";
|
import CreateJobRole from "./CreateJobRole";
|
||||||
import EditJobRole from "./EditJobRole";
|
import EditJobRole from "./EditJobRole";
|
||||||
|
import CreateActivity from "./CreateActivity";
|
||||||
|
import EditActivity from "./EditActivity";
|
||||||
|
|
||||||
const MasterModal = ({ modaldata ,closeModal}) => {
|
const MasterModal = ({ modaldata, closeModal }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div
|
||||||
<div
|
className="modal fade"
|
||||||
className="modal fade"
|
id="master-modal"
|
||||||
id="master-modal"
|
tabIndex="-1"
|
||||||
tabIndex="-1"
|
aria-hidden="true"
|
||||||
aria-hidden="true"
|
role="dialog"
|
||||||
role="dialog"
|
|
||||||
aria-labelledby="modalToggleLabel"
|
aria-labelledby="modalToggleLabel"
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={`modal-dialog mx-sm-auto mx-1 ${
|
|
||||||
modaldata?.modalType === "delete" ? "modal-md" : "modal-lg"
|
|
||||||
} modal-simple ` }
|
|
||||||
>
|
>
|
||||||
<div className="modal-content">
|
<div
|
||||||
<div className="modal-body p-sm-4 p-0">
|
className={`modal-dialog mx-sm-auto mx-1 ${
|
||||||
<button
|
modaldata?.modalType === "delete" || `Ativity` ? "modal-md" : "modal-lg"
|
||||||
type="button"
|
} modal-simple `}
|
||||||
className="btn-close"
|
>
|
||||||
data-bs-dismiss="modal"
|
<div className="modal-content">
|
||||||
aria-label="Close"
|
<div className="modal-body p-sm-4 p-0">
|
||||||
onClick={closeModal}
|
<button
|
||||||
></button>
|
type="button"
|
||||||
<div className="text-center mb-2"></div>
|
className="btn-close"
|
||||||
{modaldata?.modalType === "Role" &&
|
data-bs-dismiss="modal"
|
||||||
<CreateRole masmodalType={modaldata.masterType} onClose={closeModal} />}
|
aria-label="Close"
|
||||||
{modaldata?.modalType === "Edit-Role" && (
|
onClick={closeModal}
|
||||||
<EditRole master={modaldata} onClose={closeModal} />
|
></button>
|
||||||
)}
|
<div className="text-center mb-2"></div>
|
||||||
{modaldata?.modalType === "delete" && (
|
{modaldata?.modalType === "Role" && (
|
||||||
<DeleteMaster master={modaldata} onClose={closeModal}/>
|
<CreateRole
|
||||||
)}
|
masmodalType={modaldata.masterType}
|
||||||
{modaldata?.modalType === "Job Role" && (
|
onClose={closeModal}
|
||||||
<CreateJobRole onClose={closeModal} />
|
/>
|
||||||
)}
|
)}
|
||||||
{modaldata?.modalType === "Edit-Job Role" && (
|
{modaldata?.modalType === "Edit-Role" && (
|
||||||
<EditJobRole data ={modaldata.item} onClose={closeModal} />
|
<EditRole master={modaldata} onClose={closeModal} />
|
||||||
)}
|
)}
|
||||||
|
{modaldata?.modalType === "delete" && (
|
||||||
|
<DeleteMaster master={modaldata} onClose={closeModal} />
|
||||||
|
)}
|
||||||
|
{modaldata?.modalType === "Job Role" && (
|
||||||
|
<CreateJobRole onClose={closeModal} />
|
||||||
|
)}
|
||||||
|
{modaldata?.modalType === "Edit-Job Role" && (
|
||||||
|
<EditJobRole data={modaldata.item} onClose={closeModal} />
|
||||||
|
)}
|
||||||
|
{modaldata?.modalType === "Activity" && (
|
||||||
|
<CreateActivity onClose={closeModal} /> )
|
||||||
|
}
|
||||||
|
{modaldata?.modalType === 'Edit-Activity' && (
|
||||||
|
<EditActivity onClose={closeModal} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -53,10 +53,8 @@ const MasterPage = () => {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const {data:masterData, loading,error , RecallApi} = useMaster();
|
const {data:masterData, loading,error , RecallApi} = useMaster();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleSearch = (e) => {
|
const handleSearch = (e) => {
|
||||||
const value = e.target.value.toLowerCase();
|
const value = e.target.value.toLowerCase();
|
||||||
|
|||||||
@ -27,29 +27,10 @@ const ProjectDetails = () => {
|
|||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const [project, setProject] = useState(null);
|
const [project, setProject] = useState(null);
|
||||||
const [ projectDetails, setProjectDetails ] = useState( null );
|
const [ projectDetails, setProjectDetails ] = useState( null );
|
||||||
const [activities, setActivities] = useState(null);
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [ error, setError ] = useState( "" );
|
const [ error, setError ] = useState( "" );
|
||||||
|
|
||||||
const fetchActivities = async () => {
|
|
||||||
|
|
||||||
const activities_cache = getCachedData("activitiesMaster");
|
|
||||||
|
|
||||||
if (!activities_cache) {
|
|
||||||
ActivityeRepository.getActivities()
|
|
||||||
.then((response) => {
|
|
||||||
setActivities(response.data);
|
|
||||||
cacheData("activitiesMaster", response.data);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
setError("Failed to fetch data.");
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
setActivities(activities_cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
|
||||||
@ -124,7 +105,6 @@ const ProjectDetails = () => {
|
|||||||
return (
|
return (
|
||||||
<ProjectInfra
|
<ProjectInfra
|
||||||
data={projectDetails}
|
data={projectDetails}
|
||||||
activityMaster={activities}
|
|
||||||
onDataChange={handleDataChange}
|
onDataChange={handleDataChange}
|
||||||
></ProjectInfra>
|
></ProjectInfra>
|
||||||
);
|
);
|
||||||
@ -134,7 +114,6 @@ const ProjectDetails = () => {
|
|||||||
return (
|
return (
|
||||||
<WorkPlan
|
<WorkPlan
|
||||||
data={projectDetails}
|
data={projectDetails}
|
||||||
activityMaster={activities}
|
|
||||||
onDataChange={handleDataChange}
|
onDataChange={handleDataChange}
|
||||||
></WorkPlan>
|
></WorkPlan>
|
||||||
);
|
);
|
||||||
@ -156,15 +135,12 @@ const ProjectDetails = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// fetchData();
|
|
||||||
dispatch(setProjectId(projectId))
|
dispatch(setProjectId(projectId))
|
||||||
setProject( projects_Details )
|
setProject( projects_Details )
|
||||||
setProjectDetails(projects_Details)
|
setProjectDetails(projects_Details)
|
||||||
fetchActivities();
|
|
||||||
}, [projects_Details,projectId]);
|
}, [projects_Details,projectId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<>
|
<>
|
||||||
{}
|
{}
|
||||||
<div className="container-xxl flex-grow-1 container-p-y">
|
<div className="container-xxl flex-grow-1 container-p-y">
|
||||||
|
|||||||
@ -29,7 +29,9 @@ export const MasterRespository = {
|
|||||||
getJobRole :()=>api.get("/api/roles/jobrole"),
|
getJobRole :()=>api.get("/api/roles/jobrole"),
|
||||||
updateJobRole: ( id, data ) => api.put( `/api/roles/jobrole/${ id }`, data ),
|
updateJobRole: ( id, data ) => api.put( `/api/roles/jobrole/${ id }`, data ),
|
||||||
|
|
||||||
getActivites: () => api.get( 'api/task/activities' ),
|
getActivites: () => api.get( 'api/master/activities' ),
|
||||||
|
createActivities: () => api.post( 'api/master/activity' ),
|
||||||
|
updateActivity:(id) =>api.post(`api/master/edit/${id}`),
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user