Compare commits

...

12 Commits

Author SHA1 Message Date
Pramod Mahajan
30a9908499 changed Task Report UI 2025-04-15 02:58:01 +05:30
Pramod Mahajan
d1c36dfd97 Changed 'Role' to 'Application Role' 2025-04-15 01:08:59 +05:30
Pramod Mahajan
57272eb894 chanaged activityName validation msg 2025-04-15 01:02:15 +05:30
Pramod Mahajan
5f094aa2e6 added CreateActivity and EditActivity components. 2025-04-15 00:36:20 +05:30
Pramod Mahajan
6df20de749 it will take default range date, initially whenever component mount 2025-04-14 22:53:38 +05:30
Pramod Mahajan
ee2762fb4a removed console 2025-04-14 22:51:58 +05:30
Pramod Mahajan
97606dfef0 added 'checkLists' array inside hiddenColumn 2025-04-14 20:15:39 +05:30
Pramod Mahajan
23223661f0 removed console 2025-04-14 20:14:25 +05:30
Pramod Mahajan
2d57ab23da removed console and unnecessary hook 2025-04-14 20:10:30 +05:30
Pramod Mahajan
409c80471a removed href-# 2025-04-14 20:07:59 +05:30
Pramod Mahajan
a100194508 Merge branch 'Feature_Task_Management' of https://git.marcoaiot.com/admin/marco.pms.web into Feature_Task_Management 2025-04-14 20:05:40 +05:30
Pramod Mahajan
d421355451 added to tooltip in projectCard view more button 2025-04-14 20:05:16 +05:30
16 changed files with 465 additions and 357 deletions

View File

@ -13,7 +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")
.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,78 +63,65 @@ export const ReportTask = ({ report, closeModal, refetch }) => {
></button> ></button>
<div className="container m-0"> <div className="container m-0">
<div className="d-flex justify-content-between"> <div class="mb-1 row text-start">
<figure className="text-start p-0 m-0"> <label for="html5-text-input" class="col-md-4 col-form-label">
<blockquote className="blockquote"> Assigned Date :{" "}
<small> </label>
{" "} <div class="col-md-8 text-start">
Assigned Date : {formatDate(report?.assignmentDate)} <label class="col-md-2 col-form-label">
</small> {formatDate(report?.assignmentDate)}
</blockquote> </label>
</figure> </div>
<figure className="text-end p-0 m-0"> </div>
<blockquote className="blockquote"> <div class="mb-1 row text-start">
<small>Assigned By</small> <label for="html5-search-input" class="col-md-4 col-form-label">
</blockquote> Assigned By :{" "}
<figcaption className="blockquote-footer mb-0"> </label>
{/* <div className="d-flex avatar avatar-xs"> <div class="col-md-8 text-start">
<span className="avatar-initial rounded-circle bg-label-primary"> <label class=" col-form-label">{` ${report?.assignedBy.firstName} ${report?.assignedBy.lastName}`}</label>
{report?.assignedBy?.firstName.slice(0, 1)} </div>
</span> */} </div>
<cite title="Source Title m-0">{` ${report?.assignedBy.firstName} ${report?.assignedBy.lastName}`}</cite> <div class="mb-1 row text-start">
{/* </div> */} <label for="html5-email-input" class="col-md-4 col-form-label">
</figcaption> Wrok Area :
</figure> </label>
</div> <div class="col-md-8 text-start text-wrap">
<label class=" col-form-label">
<div className="d-flex p-0 m-0"> {" "}
<div className="flex-shrink-0 mt-1 mx-sm-0 px-2 mx-auto"> {report?.workItem?.workArea?.floor?.building?.name}{" "}
<i className="bx bx-buildings"></i> <i class="bx bx-chevron-right"></i>{" "}
{report?.workItem?.workArea?.floor?.floorName}{" "}
<i class="bx bx-chevron-right"> </i>
{report?.workItem?.workArea?.areaName}
</label>
</div>
</div>
<div class="mb-1 row text-start">
<label for="html5-email-input" class="col-md-4 col-form-label">
Activity :
</label>
<div class="col-md-8 text-start text-wrap">
<label class=" col-form-label">
{report?.workItem?.activityMaster.activityName}
</label>
</div>
</div>
<div class="mb-1 row text-start">
<label for="html5-email-input" class="col-md-4 col-form-label">
Team Size :
</label>
<div class="col-md-8 text-start text-wrap">
<label class=" col-form-label">
{report?.teamMembers?.length}
</label>
</div> </div>
<p className="lead">
{report?.workItem?.workArea?.floor?.building?.name}
</p>
<p className="lead ms-12">
{report?.workItem?.workArea?.floor?.floorName}
</p>
</div> </div>
<dl className="row text-start ms-3">
<dt className="col-sm-6">
Work Area : {report?.workItem?.workArea?.areaName}
</dt>
<dd className="col-sm-6">
<small> {report?.workItem?.activityMaster.activityName}</small>
</dd>
</dl>
<dl className="row text-start ms-3">
<dt className="col-sm-4">Team</dt>
<dd className="col-sm-4 d-flex align-items-center avatar-group justify-content-start">
{report?.teamMembers.map((member) => (
<>
<div
data-bs-toggle="tooltip"
data-bs-html="true"
data-popup="tooltip-custom"
data-bs-placement="top"
title={`${member.firstName} ${member.lastName}`}
className="avatar avatar-xs"
>
{/* <img src="..." alt="Avatar" className="rounded-circle pull-up" /> */}
<span className="avatar-initial rounded-circle bg-label-primary">
{member?.firstName.slice(0, 1)}
</span>
</div>
</>
))}
</dd>
<dt className="col-sm-4 text-start">
Planned : {report?.plannedTask}
</dt>
</dl>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div className="row p-0"> <div class="mb-1 row text-start">
<div className="col-4"> <label for="html5-email-input" class="col-md-4 col-form-label">
Completed Work
</label>
<div class="col-md-8 text-start text-wrap">
<input <input
{...register("completedTask", { valueAsNumber: true })} {...register("completedTask", { valueAsNumber: true })}
id="smallInput" id="smallInput"
@ -148,7 +135,12 @@ export const ReportTask = ({ report, closeModal, refetch }) => {
</div> </div>
)} )}
</div> </div>
<div className="col-8"> </div>
<div class="mb-1 row text-start">
<label for="html5-email-input" class="col-md-4 col-form-label">
Comment
</label>
<div class="col-md-8 text-start text-wrap">
<textarea <textarea
{...register("comment")} {...register("comment")}
className="form-control" className="form-control"
@ -157,11 +149,10 @@ export const ReportTask = ({ report, closeModal, refetch }) => {
placeholder="Enter comment" placeholder="Enter comment"
/> />
{errors.comment && ( {errors.comment && (
<div className="text-danger">{errors.comment.message}</div> <div className="danger-text">{errors.comment.message}</div>
)} )}
</div> </div>
</div> </div>
<div className="col-12 text-center my-2"> <div className="col-12 text-center my-2">
<button type="submit" className="btn btn-sm btn-primary me-3"> <button type="submit" className="btn btn-sm btn-primary me-3">
{loading ? "Please wait" : "Submit Report"} {loading ? "Please wait" : "Submit Report"}

View File

@ -69,7 +69,7 @@ const Header = () =>
<a <a
aria-label="toggle for sidebar" aria-label="toggle for sidebar"
className="nav-item nav-link px-0 me-xl-4" className="nav-item nav-link px-0 me-xl-4"
href="#"
> >
<i className="bx bx-menu bx-sm"></i> <i className="bx bx-menu bx-sm"></i>
</a> </a>

View File

@ -160,13 +160,14 @@ const ProjectCard = ({ projectData }) => {
data-bs-toggle="dropdown" data-bs-toggle="dropdown"
aria-expanded="false" aria-expanded="false"
> >
<i className="bx bx-dots-vertical-rounded bx-sm text-muted"></i> <i className="bx bx-dots-vertical-rounded bx-sm text-muted" data-bs-toggle="tooltip" data-bs-offset="0,8" data-bs-placement="top" data-bs-custom-class="tooltip-dark" title="More Action"></i>
</button> </button>
<ul className="dropdown-menu dropdown-menu-end"> <ul className="dropdown-menu dropdown-menu-end">
<li> <li>
<a <a
aria-label="click to View details" aria-label="click to View details"
className="dropdown-item" className="dropdown-item"
onClick={handleViewProject} onClick={handleViewProject}
> >
<i className="bx bx-detail me-2"></i> <i className="bx bx-detail me-2"></i>

View File

@ -5,16 +5,14 @@ const DateRangePicker = ({ onRangeChange }) => {
const inputRef = useRef(null); const inputRef = useRef(null);
useEffect(() => { useEffect(() => {
const today = new Date(); const today = new Date();
const fifteenDaysAgo = new Date(); const fifteenDaysAgo = new Date();
fifteenDaysAgo.setDate(today.getDate() - 15); fifteenDaysAgo.setDate(today.getDate() - 15);
const fp = flatpickr(inputRef.current, { const fp = flatpickr(inputRef.current, {
mode: "range", mode: "range",
dateFormat: "Y-m-d", dateFormat: "Y-m-d",
defaultDate: [fifteenDaysAgo, today], // set default range defaultDate: [fifteenDaysAgo, today],
static: true, static: true,
clickOpens: true, clickOpens: true,
onChange: (selectedDates, dateStr) => { onChange: (selectedDates, dateStr) => {
@ -23,6 +21,11 @@ const DateRangePicker = ({ onRangeChange }) => {
}, },
}); });
onRangeChange?.({
startDate: fifteenDaysAgo.toISOString().split("T")[0],
endDate: today.toISOString().split("T")[0],
});
return () => { return () => {
fp.destroy(); fp.destroy();
}; };

View File

@ -1,26 +1,30 @@
import React,{useState,useEffect} from 'react' import React, { useState, useEffect } from "react";
import {useFieldArray, useForm } from 'react-hook-form'; import { useFieldArray, useForm } from "react-hook-form";
import { z } from 'zod'; import { z } from "zod";
import {zodResolver} from '@hookform/resolvers/zod'; import { zodResolver } from "@hookform/resolvers/zod";
import { MasterRespository } from '../../repositories/MastersRepository'; import { MasterRespository } from "../../repositories/MastersRepository";
import { clearApiCacheKey } from '../../slices/apiCacheSlice'; import { clearApiCacheKey } from "../../slices/apiCacheSlice";
import { getCachedData,cacheData } from '../../slices/apiDataManager'; import { getCachedData, cacheData } from "../../slices/apiDataManager";
import showToast from '../../services/toastService'; import showToast from "../../services/toastService";
const schema = z.object({ const schema = z.object({
activityName: z.string().min(1, { message: "Role is required" }), activityName: z.string().min(1, { message: "Activity Name is required" }),
unitOfMeasurement: z.string().min(1, { message: "Description is required" }), unitOfMeasurement: z.string().min(1, { message: "Unit of Measurement is required" }),
checkList: z checkList: z
.array(z.string().min(1, { message: "Checklist item cannot be empty" })) .array(
.optional(), z.object({
}); check: z.string().min(1, { message: "Checklist item cannot be empty" }),
isMandatory: z.boolean().default(false),
const CreateActivity = ({onClose}) => id: z.any().default(0),
{ })
)
.optional(),
});
const CreateActivity = ({ onClose }) => {
const [isLoading, setIsLoading] = useState(false);
const [ isLoading, setIsLoading ] = useState( false )
const { const {
register, register,
handleSubmit, handleSubmit,
@ -34,147 +38,197 @@ const CreateActivity = ({onClose}) =>
} = useForm({ } = useForm({
resolver: zodResolver(schema), resolver: zodResolver(schema),
defaultValues: { defaultValues: {
activityName: '', activityName: "",
unitOfMeasurement: '', unitOfMeasurement: "",
checkList: [], checkList: [],
}, },
}); });
// Setting up field array for checkList (dynamic fields)
const { const {
fields: checkListItems, fields: checkListItems,
append, append,
remove, remove,
} = useFieldArray({ } = useFieldArray({
control, control,
name: 'checkList', name: "checkList",
}); });
// Form submission handler // Form submission handler
const onSubmit = ( data ) => const onSubmit = (data) => {
{ console.log(data);
console.log(data) setIsLoading(true);
setIsLoading(true)
MasterRespository.updateActivity(data).then((resp)=>{
setIsLoading(false)
const cachedData = getCachedData("Activity");
const updatedData = [...cachedData, resp?.data];
cacheData("Activity", updatedData);
showToast("Activity Added successfully.", "success");
onClose() MasterRespository.createActivity(data)
}).catch((error)=>{ .then( ( resp ) =>
showToast(error.message, "error"); {
setIsLoading(false)
}) const cachedData = getCachedData("Activity");
const updatedData = [ ...cachedData, resp?.data ];
cacheData("Activity", updatedData);
showToast("Activity Successfully Added.", "success");
setIsLoading(false);
handleClose()
})
.catch((error) => {
showToast(error.message, "error");
setIsLoading(false);
});
}; };
// Add a new checklist item
const addChecklistItem = () => {
const values = getValues('checkList');
const lastIndex = checkListItems.length - 1;
const addChecklistItem = () => {
if (checkListItems.length > 0 && (!values?.[lastIndex] || values[lastIndex].trim() === '')) { const values = getValues("checkList");
setError(`checkList.${lastIndex}`, { const lastIndex = checkListItems.length - 1;
type: 'manual', if (
message: 'Please fill this checklist item before adding another.', checkListItems.length > 0 &&
(!values?.[lastIndex] || values[lastIndex].check.trim() === "")
) {
setError(`checkList.${lastIndex}.check`, {
type: "manual",
message: "Please fill this checklist item before adding another.",
}); });
return; return;
} }
clearErrors(`checkList.${lastIndex}.check`);
clearErrors(`checkList.${lastIndex}`); // Clear the error if the input is filled. append({
append(''); // Add a new empty checklist input id: 0,
check: "",
isMandatory: false,
});
}; };
const removeChecklistItem = (index) => { const removeChecklistItem = (index) => {
remove(index); remove(index);
}; };
// Handle checklist item input change
const handleChecklistChange = (index, value) => { const handleChecklistChange = (index, value) => {
setValue(`checkList.${index}`, value); setValue(`checkList.${index}`, value);
}; };
const handleClose = () => const handleClose = () => {
{ reset();
reset() onClose();
onClose() };
}
return ( return (
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div className="row"> <h6>Create Activity</h6>
<div className="col-6"> <div className="row">
<label className="form-label">Activity</label> <div className="col-6">
<input <label className="form-label">Activity</label>
type="text" <input
{...register('activityName')} type="text"
className={`form-control form-control-sm ${errors.activityName ? 'is-invalid' : ''}`} {...register("activityName")}
/> className={`form-control form-control-sm ${
{errors.activityName && <p className="danger-text">{errors.activityName.message}</p>} errors.activityName ? "is-invalid" : ""
</div> }`}
/>
{errors.activityName && (
<p className="danger-text">{errors.activityName.message}</p>
)}
</div>
<div className="col-6"> <div className="col-6">
<label className="form-label">Measurement</label> <label className="form-label">Measurement</label>
<input <input
type="text" type="text"
{...register('unitOfMeasurement')} {...register("unitOfMeasurement")}
className={`form-control form-control-sm ${errors.unitOfMeasurement ? 'is-invalid' : ''}`} className={`form-control form-control-sm ${
/> errors.unitOfMeasurement ? "is-invalid" : ""
{errors.unitOfMeasurement && ( }`}
<p className="danger-text">{errors.unitOfMeasurement.message}</p> />
)} {errors.unitOfMeasurement && (
</div> <p className="danger-text">{errors.unitOfMeasurement.message}</p>
)}
</div>
<div className="col-md-6 text-start"> <div className="col-md-12 text-start mt-1">
{/* Dynamic checklist items */} <p className="py-1 my-0">{checkListItems.length > 0 ? "Check List" : "Add Check List" }</p>
{checkListItems.map((item, index) => ( {checkListItems.length > 0 && (
<div key={item.id} className=" align-items-center my-1"> <table className="table mt-1 border-0">
<div className='d-flex align-items-center gap-2'> <thead className="py-0 my-0 table-border-top-0">
<input <tr className="py-1">
{...register(`checkList.${index}`)} <th colSpan={2} className="py-1">
className="form-control form-control-sm" <small>Name</small>
placeholder={`Checklist item ${index + 1}`} </th>
onChange={(e) => handleChecklistChange(index, e.target.value)} // Handle input change <th colSpan={2} className="py-1 text-center">
/> <small>Is Mandatory</small>
<button </th>
type="button" <th className="text-center py-1">Action</th>
onClick={() => removeChecklistItem(index)} // Remove button </tr>
className="btn btn-xs btn-icon btn-text-secondary" </thead>
> <tbody className="table-border-bottom-0 ">
<span class='icon-base bx bx bx-x'></span> {checkListItems.map((item, index) => (
</button> <tr key={index} className="border-top-0">
</div> <td colSpan={2} className="border-top-0 border-0">
{errors.checkList?.[index] && ( <input
<p className="danger-text">{errors.checkList[index]?.message}</p> className="d-none"
)} {...register(`checkList.${index}.id`)}
</div> ></input>
))} <input
{/* Add new checklist item */} {...register(`checkList.${index}.check`)}
<button type="button" className="btn btn-sm btn-primary mt-2" onClick={addChecklistItem}> className="form-control form-control-sm"
+ Add Checklist Item placeholder={`Checklist item ${index + 1}`}
</button> onChange={(e) =>
</div> handleChecklistChange(index, e.target.value)
}
/>
{errors.checkList?.[index]?.check && (
<small
style={{ fontSize: "10px" }}
className="danger-text"
>
{errors.checkList[index]?.check?.message}
</small>
)}
</td>
<td colSpan={2} className="text-center border-0">
<input
className="form-check-input"
type="checkbox"
{...register(`checkList.${index}.isMandatory`)}
defaultChecked={item.isMandatory}
/>
</td>
<td className="text-center border-0">
<button
type="button"
onClick={() => removeChecklistItem(index)}
className="btn btn-xs btn-icon btn-text-secondary"
>
<i class="bx bxs-minus-circle text-danger"></i>
</button>
</td>
</tr>
))}
</tbody>
</table>
)}
<button
type="button"
className="btn btn-xs btn-primary mt-2"
onClick={addChecklistItem}
>
<i class="bx bx-plus-circle"></i>
</button>
</div>
<div className="col-12 text-center mt-3"> <div className="col-12 text-center mt-3">
<button type="submit" className="btn btn-sm btn-primary me-3"> <button type="submit" className="btn btn-sm btn-primary me-3">
{isLoading ? "Please Wait" : "Submit"} {isLoading ? "Please Wait" : "Submit"}
</button> </button>
<button <button
type="reset" type="reset"
className="btn btn-sm btn-label-secondary" className="btn btn-sm btn-label-secondary"
onClick={handleClose} onClick={handleClose}
> >
Cancel Cancel
</button> </button>
</div>
</div> </div>
</div> </form>
</form> );
) };
}
export default CreateActivity export default CreateActivity;

View File

@ -57,15 +57,12 @@ const onSubmit = (values) => {
}; };
MasterRespository.createRole(result).then((resp)=>{ MasterRespository.createRole(result).then((resp)=>{
console.log(resp)
setIsLoading(false) setIsLoading(false)
const cachedData = getCachedData( "Role" ); const cachedData = getCachedData( "Role" );
console.log(cachedData) const updatedData = [...cachedData, resp.data];
const updatedData = [...cachedData, resp];
cacheData("Role", updatedData); cacheData("Application Role", updatedData);
showToast("Role Added successfully.", "success"); showToast("Application Role Added successfully.", "success");
onClose() onClose()
} ).catch( ( err ) => } ).catch( ( err ) =>
{ {

View File

@ -10,7 +10,6 @@ const DeleteMaster = ({ master, onClose }) => {
const index = mastersdata[master?.masterType]?.findIndex( const index = mastersdata[master?.masterType]?.findIndex(
(item) => String(item?.id) === String(master?.item?.id) (item) => String(item?.id) === String(master?.item?.id)
); );
console.log(index);
if (index !== -1) { if (index !== -1) {
mastersdata[master?.masterType].splice(index, 1); mastersdata[master?.masterType].splice(index, 1);
} }

View File

@ -1,23 +1,28 @@
import React, { useState, useEffect } from 'react'; import React, { useEffect, useState } from "react";
import { useFieldArray, useForm } from 'react-hook-form'; import { useForm, useFieldArray } from "react-hook-form";
import { z } from 'zod'; import { z } from "zod";
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from "@hookform/resolvers/zod";
import {MasterRespository} from '../../repositories/MastersRepository'; import {MasterRespository} from "../../repositories/MastersRepository";
import axios from 'axios'; import showToast from "../../services/toastService";
import showToast from '../../services/toastService'; import {getCachedData,cacheData} from "../../slices/apiDataManager";
import {cacheData, getCachedData} from '../../slices/apiDataManager';
// Zod Schema for validation
const schema = z.object({ const schema = z.object({
activityName: z.string().min(1, { message: "Activity name is required" }), activityName: z.string().min(1, { message: "Activity name is required" }),
unitOfMeasurement: z.string().min(1, { message: "Measurement is required" }), unitOfMeasurement: z.string().min(1, { message: "Measurement is required" }),
checkList: z checkList: z
.array(z.string().min(1, { message: "Checklist item cannot be empty" })) .array(
z.object({
id: z.any().default(0),
check: z.string().min(1, { message: "Checklist item cannot be empty" }),
isMandatory: z.boolean().default(false),
})
)
.optional(), .optional(),
} ); });
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOlsiOGFmNjFlNDgtYzRkMy00MTYzLWI4NjAtMmEyZWNiNjQ3NDZiIiwiYjUxMzcwOWEtYmZiZS00OTM1LTlmNWMtOGVjN2IwMzFjNTFlIl0sInN1YiI6InZpa2FzQG1hcmNvYWlvdC5jb20iLCJUZW5hbnRJZCI6IjIiLCJleHAiOjE3NDQzNzQyNzAsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTI0NiIsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NTI0NiJ9.reQlePmwDpBL-_mcGOrWwADLJrxmUse5Gd7A-OgDi9s"
const EditActivity = ({activityData,onClose}) => { const UpdateActivity = ({ activityData, onClose }) => {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const { const {
@ -25,166 +30,212 @@ const EditActivity = ({activityData,onClose}) => {
handleSubmit, handleSubmit,
control, control,
setValue, setValue,
clearErrors,
setError,
getValues,
reset, reset,
setError,
clearErrors,
getValues,
formState: { errors }, formState: { errors },
} = useForm({ } = useForm({
resolver: zodResolver(schema), resolver: zodResolver(schema),
defaultValues: { defaultValues: {
activityName: '', id:activityData.id,
unitOfMeasurement: '', activityName: activityData.activityName,
checkList: [], unitOfMeasurement: activityData.unitOfMeasurement,
checkLists: activityData.checkLists || [],
}, },
}); });
// Setting up field array for checkList (dynamic fields) const { fields: checkListItems, append, remove } = useFieldArray({
const {
fields: checkListItems,
append,
remove,
} = useFieldArray({
control, control,
name: 'checkList', name: "checkList",
}); });
// Pre-populating the form with initial data when component mounts or initialData changes // Load initial data
useEffect(() => { useEffect(() => {
if (activityData) { if (activityData) {
reset({ reset( {
id:activityData.id,
activityName: activityData.activityName, activityName: activityData.activityName,
unitOfMeasurement: activityData.unitOfMeasurement, unitOfMeasurement: activityData.unitOfMeasurement,
checkList: activityData.checkList || [], checkList: activityData.checkLists || [],
}); });
} }
}, [activityData, reset]); }, [activityData]);
// Form submission handler
const onSubmit = async( data ) => const handleChecklistChange = (index, value) => {
setValue(`checkList.${index}`, value);
};
// Submit handler
const onSubmit = async(data) => {
setIsLoading(true);
const Activity = {...data, id:activityData.id}
try
{ {
console.log(data) const response = await MasterRespository.updateActivity( activityData?.id, Activity );
setIsLoading(true) const updatedActivity = response.data;
MasterRespository.updateActivity(activityData?.id,data).then((resp)=>{ const cachedData = getCachedData("Activity")
setIsLoading(false)
const cachedData = getCachedData("Activity"); if (cachedData) {
if (cachedData) { const updatedActivities = cachedData.map((activity) =>
const updatedData = cachedData.map((activity) => activity.id === updatedActivity.id ? { ...activity, ...updatedActivity } : activity
activity.id === activityData?.id );
? {
...activity, cacheData( "Activity", updatedActivities );
activityName: resp.data.activityName,
unitOfMeasurement: resp.data.unitOfMeasurement,
}
: activity
);
cacheData("Activity", updatedData);
}
showToast("Activity Added successfully.", "success");
onClose() onClose()
}).catch((error)=>{ }
showToast(error.message, "error"); setIsLoading( false )
setIsLoading(false) showToast("Activity Successfully Updated", "success");
}) } catch ( err )
{
setIsLoading( false )
};
// Add a new checklist item showToast("error.message", "error");
console.log(err)
}
};
// Add new checklist item
const addChecklistItem = () => { const addChecklistItem = () => {
const values = getValues('checkList'); const values = getValues("checkList");
const lastIndex = checkListItems.length - 1; const lastIndex = checkListItems.length - 1;
// Prevent adding new input if the last one is empty if (
if (checkListItems.length > 0 && (!values?.[lastIndex] || values[lastIndex].trim() === '')) { checkListItems.length > 0 &&
setError(`checkList.${lastIndex}`, { (!values?.[lastIndex] || values[lastIndex].check.trim() === "")
type: 'manual', ) {
message: 'Please fill this checklist item before adding another.', setError(`checkList.${lastIndex}.check`, {
type: "manual",
message: "Please fill this checklist item before adding another.",
}); });
return; return;
} }
clearErrors(`checkList.${lastIndex}`); // Clear the error if the input is filled. clearErrors(`checkList.${lastIndex}.check`);
append(''); // Add a new empty checklist input append({ id: 0, check: "", isMandatory: false });
}; };
// Remove a checklist item
const removeChecklistItem = (index) => { const removeChecklistItem = (index) => {
remove(index); // Remove the checklist item from the field array remove(index);
}; };
// 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 ( return (
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<h6>Update Activity</h6>
<div className="row"> <div className="row">
<div className="col-6"> {/* Activity Name */}
<label className="form-label">Activity</label> <div className="col-md-6">
<label className="form-label">Activity Name</label>
<input <input
type="text" type="text"
{...register('activityName')} {...register("activityName")}
className={`form-control form-control-sm ${errors.activityName ? 'is-invalid' : ''}`} className={`form-control form-control-sm ${errors.activityName ? "is-invalid" : ""}`}
/> />
{errors.activityName && <p className="danger-text">{errors.activityName.message}</p>} {errors.activityName && (
</div> <div className="text-danger">{errors.activityName.message}</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>
<div className="col-md-6 text-start"> {/* Unit of Measurement */}
{/* Dynamic checklist items */} <div className="col-md-6">
{checkListItems.map((item, index) => ( <label className="form-label">Measurement</label>
<div key={item.id} className="d-flex align-items-center gap-2 my-1"> <input
<input type="text"
{...register(`checkList.${index}`)} {...register("unitOfMeasurement")}
className="form-control form-control-sm" className={`form-control form-control-sm ${errors.unitOfMeasurement ? "is-invalid" : ""}`}
placeholder={`Checklist item ${index + 1}`} />
onChange={(e) => handleChecklistChange(index, e.target.value)} // Handle input change {errors.unitOfMeasurement && (
/> <div className="text-danger">{errors.unitOfMeasurement.message}</div>
<button )}
type="button" </div>
onClick={() => removeChecklistItem(index)} // Remove button
className="btn btn-xs btn-icon btn-text-secondary" {/* Checklist */}
> <div className="col-md-12 text-start mt-1">
<span className="icon-base bx bx-x"/> <p className="py-1 my-0">{checkListItems.length > 0 ? "Check List" : "Add Check List"}</p>
</button> {checkListItems.length > 0 && (
{errors.checkList?.[index] && ( <table className="table mt-1 border-0">
<p className="danger-text">{errors.checkList[index]?.message}</p> <thead className="py-0 my-0 table-border-top-0">
)} <tr className="py-1">
</div> <th colSpan={2} className="py-1">
))} <small>Name</small>
{/* Add new checklist item */} </th>
<button type="button" className="btn btn-sm btn-primary mt-2" onClick={addChecklistItem}> <th colSpan={2} className="py-1 text-center">
+ Add Checklist Item <small>Is Mandatory</small>
</th>
<th className="text-center py-1">Action</th>
</tr>
</thead>
<tbody>
{checkListItems.map((item, index) => (
<tr key={item.id} className="border-top-0">
<td colSpan={2} className=" border-0">
<input
className="d-none"
{...register(`checkList.${index}.id`)}
></input>
<input
{...register(`checkList.${index}.check`)}
className="form-control form-control-sm"
placeholder={`Checklist item ${index + 1}`}
onChange={(e) =>
handleChecklistChange(index, e.target.value)
}
/>
{errors.checkList?.[index]?.check && (
<small
style={{ fontSize: "10px" }}
className="danger-text"
>
{errors.checkList[index]?.check?.message}
</small>
)}
</td>
<td colSpan={2} className="text-center border-0">
<input
className="form-check-input"
type="checkbox"
{...register(`checkList.${index}.isMandatory`)}
defaultChecked={item.isMandatory}
/>
</td>
<td className="text-center border-0">
<button
type="button"
onClick={() => removeChecklistItem(index)}
className="btn btn-xs btn-icon btn-text-secondary"
>
<i class="bx bxs-minus-circle text-danger"></i>
</button>
</td>
</tr>
))}
</tbody>
</table>
)}
<button
type="button"
className="btn btn-xs btn-primary mt-2"
onClick={addChecklistItem}
>
<i class="bx bx-plus-circle"></i>
</button> </button>
</div> </div>
{/* Submit / Cancel */}
<div className="col-12 text-center mt-3"> <div className="col-12 text-center mt-3">
<button type="submit" className="btn btn-sm btn-primary me-3"> <button type="submit" className="btn btn-sm btn-primary me-3">
Submit {isLoading ? "Please Wait" : "Submit"}
</button> </button>
<button <button
type="reset" type="reset"
className="btn btn-sm btn-label-secondary" className="btn btn-sm btn-label-secondary"
onClick={handleCLose} onClick={onClose}
> >
Cancel Cancel
</button> </button>
@ -194,4 +245,4 @@ const EditActivity = ({activityData,onClose}) => {
); );
}; };
export default EditActivity; export default UpdateActivity;

View File

@ -101,7 +101,7 @@ const EditMaster=({master,onClose})=> {
setIsLoading( false ) setIsLoading( false )
const cachedData = getCachedData("Role"); const cachedData = getCachedData("Application Role");
if (cachedData) { if (cachedData) {
@ -109,9 +109,9 @@ const EditMaster=({master,onClose})=> {
role.id === resp.data?.id ? { ...role, ...resp.data } : role role.id === resp.data?.id ? { ...role, ...resp.data } : role
); );
cacheData("Role", updatedData); cacheData("Application Role", updatedData);
} }
showToast( "Role Update successfully.", "success" ); showToast( "Application Role Updated successfully.", "success" );
setIsLoading(false) setIsLoading(false)
onClose() onClose()
}).catch((Err)=>{ }).catch((Err)=>{

View File

@ -33,13 +33,13 @@ const MasterModal = ({ modaldata, closeModal }) => {
onClick={closeModal} onClick={closeModal}
></button> ></button>
<div className="text-center mb-2"></div> <div className="text-center mb-2"></div>
{modaldata?.modalType === "Role" && ( {modaldata?.modalType === "Application Role" && (
<CreateRole <CreateRole
masmodalType={modaldata.masterType} masmodalType={modaldata.masterType}
onClose={closeModal} onClose={closeModal}
/> />
)} )}
{modaldata?.modalType === "Edit-Role" && ( {modaldata?.modalType === "Edit-Application Role" && (
<EditRole master={modaldata} onClose={closeModal} /> <EditRole master={modaldata} onClose={closeModal} />
)} )}
{modaldata?.modalType === "delete" && ( {modaldata?.modalType === "delete" && (

View File

@ -1,4 +1,6 @@
export const mastersList = [{id:1, name: "Role"},{id:2, name: "Job Role"},{id:3,name:"Activity"}] // it important ------
export const mastersList = [ {id: 1, name: "Application Role"}, {id: 2, name: "Job Role"}, {id: 3, name: "Activity"} ]
// -------------------
export const dailyTask = [ export const dailyTask = [
{ {

View File

@ -35,7 +35,7 @@ const useMaster = () => {
} else { } else {
let response; let response;
switch (selectedMaster) { switch (selectedMaster) {
case "Role": case "Application Role":
response = await MasterRespository.getRoles(); response = await MasterRespository.getRoles();
response = response.data; response = response.data;
break; break;

View File

@ -15,8 +15,8 @@ import DateRangePicker from "../../components/common/DateRangePicker";
import DatePicker from "../../components/common/DatePicker"; import DatePicker from "../../components/common/DatePicker";
const DailyTask = () => { const DailyTask = () => {
const {profile: LoggedUser} = useProfile(); const { profile: LoggedUser } = useProfile();
const { const {
projects, projects,
loading: project_lodaing, loading: project_lodaing,
@ -27,13 +27,13 @@ const DailyTask = () => {
); );
const dispatch = useDispatch(selectedProject); const dispatch = useDispatch(selectedProject);
const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" }); const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" });
const { const {
TaskList, TaskList,
loading: task_loading, loading: task_loading,
error: task_error, error: task_error,
refetch, refetch,
} = useTaskList( selectedProject, dateRange.startDate, dateRange.endDate ); } = useTaskList(selectedProject, dateRange.startDate, dateRange.endDate);
const [TaskLists, setTaskLists] = useState([]); const [TaskLists, setTaskLists] = useState([]);
@ -56,7 +56,6 @@ const DailyTask = () => {
selectTask(task); selectTask(task);
openModal(); openModal();
}; };
console.log(dateRange)
return ( return (
<> <>
@ -126,7 +125,6 @@ const DailyTask = () => {
))} ))}
</select> </select>
</div> </div>
</div> </div>
<div className="table-responsive text-nowrap"> <div className="table-responsive text-nowrap">
<table className="table"> <table className="table">
@ -191,7 +189,7 @@ const DailyTask = () => {
<td>{formatDate(task.assignmentDate)}</td> <td>{formatDate(task.assignmentDate)}</td>
<td className="text-center"> <td className="text-center">
<div className="d-flex align-items-center avatar-group justify-content-center"> <div className="d-flex align-items-center avatar-group justify-content-center">
{task.teamMembers.map((member) => ( {task.teamMembers.slice(0, 3).map((member) => (
<div <div
key={member.id} key={member.id}
data-bs-toggle="tooltip" data-bs-toggle="tooltip"
@ -207,14 +205,27 @@ const DailyTask = () => {
</span> </span>
</div> </div>
))} ))}
{task.teamMembers.length > 3 && (
<div
className="avatar avatar-xs"
data-bs-toggle="tooltip"
data-bs-placement="bottom"
title={`${task.teamMembers.length - 3} more`}
>
<span className="avatar-initial rounded-circle bg-label-secondary pull-up">
+{task.teamMembers.length - 3}
</span>
</div>
)}
</div> </div>
</td> </td>
<td className="text-center"> <td className="text-center">
<div className="d-flex justify-content-center"> <div className="d-flex justify-content-center">
<button <button
type="button" type="button"
className={`btn btn-xs btn-primary ${task.completedTask > 0 ? "d-none":""}`} className={`btn btn-xs btn-primary ${
task.completedTask > 0 ? "d-none" : ""
}`}
onClick={() => { onClick={() => {
selectTask(task); selectTask(task);
openModal(); openModal();

View File

@ -36,9 +36,8 @@ const ForgotPasswordPage = () => {
const response = await AuthRepository.forgotPassword(data) const response = await AuthRepository.forgotPassword(data)
if ( response.data && response.success ) if ( response.data && response.success )
showToast( response.message, "success" ) showToast( response.message, "success" )
reset()
setLoading( false ) setLoading( false )
setEmail( "" )
console.log(response)
} catch ( err ) } catch ( err )
{ {

View File

@ -7,7 +7,7 @@ const MasterTable = ( {data, columns, loading, handleModalData} ) =>
{ {
const hasMasterPermission = useHasUserPermission(MANAGE_MASTER) const hasMasterPermission = useHasUserPermission(MANAGE_MASTER)
const selectedMaster = useSelector((store)=>store.localVariables.selectedMaster) const selectedMaster = useSelector((store)=>store.localVariables.selectedMaster)
const hiddenColumns = ["id", "featurePermission","tenant","tenantId"]; const hiddenColumns = ["id", "featurePermission","tenant","tenantId","checkLists"];
const safeData = Array.isArray(data) ? data : []; const safeData = Array.isArray(data) ? data : [];
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
@ -28,7 +28,7 @@ const MasterTable = ( {data, columns, loading, handleModalData} ) =>
.map((col) => ({ .map((col) => ({
...col, ...col,
label: label:
col.key === "role" || col.key === "Activity" || col.key === "status" ? "Name" : col.label, col.key === "role" || col.key === "activityName" || col.key === "status" ? "Name" : col.label,
})); }));
return ( return (
@ -45,7 +45,7 @@ const MasterTable = ( {data, columns, loading, handleModalData} ) =>
<thead> <thead>
<tr> <tr>
<th></th> <th></th>
<th>{ selectedMaster} Name</th> <th> Name</th>
<th>{selectedMaster} {selectedMaster === "Activity" ? "Unit":"Description" }</th> <th>{selectedMaster} {selectedMaster === "Activity" ? "Unit":"Description" }</th>
<th className={` ${!hasMasterPermission && 'd-none'}`}>Actions</th> <th className={` ${!hasMasterPermission && 'd-none'}`}>Actions</th>
</tr> </tr>

View File

@ -3,7 +3,7 @@ import { createSlice } from "@reduxjs/toolkit";
const localVariablesSlice = createSlice({ const localVariablesSlice = createSlice({
name: "localVariables", name: "localVariables",
initialState: { initialState: {
selectedMaster:"Role", selectedMaster:"Application Role",
regularizationCount:0, regularizationCount:0,
projectId:1, projectId:1,