added updation for fllter

This commit is contained in:
pramod.mahajan 2025-09-29 11:52:11 +05:30
parent 22514b1fa0
commit 72424eee53
14 changed files with 178 additions and 148 deletions

View File

@ -1,36 +1,66 @@
import React, { useState } from 'react' import React, { useState } from "react";
import { useCurrentService, useProjectInfra } from '../../hooks/useProjects' import { useCurrentService, useProjectInfra } from "../../hooks/useProjects";
import { useSelectedProject } from '../../slices/apiDataManager'; import { useSelectedProject } from "../../slices/apiDataManager";
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from "react-hook-form";
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from "@hookform/resolvers/zod";
import { TaskReportDefaultValue, TaskReportFilterSchema } from './TaskRportScheam'; import {
import { DateRangePicker1 } from '../common/DateRangePicker'; TaskReportDefaultValue,
import SelectMultiple from '../common/SelectMultiple'; TaskReportFilterSchema,
} from "./TaskRportScheam";
import { DateRangePicker1 } from "../common/DateRangePicker";
import SelectMultiple from "../common/SelectMultiple";
import { localToUtc } from "../../utils/appUtils";
const TaskReportFilterPanel = () => { const TaskReportFilterPanel = ({ handleFilter }) => {
const [resetKey, setResetKey] = useState(0); const [resetKey, setResetKey] = useState(0);
const selectedProjec = useSelectedProject() const selectedProjec = useSelectedProject();
const selectedService = useCurrentService(); const selectedService = useCurrentService();
const {projectInfra, isLoading, error, isFetched } = useProjectInfra(selectedProjec,selectedService); const { projectInfra, isLoading, error, isFetched } = useProjectInfra(
const methods = useForm({resolver:zodResolver(TaskReportFilterSchema),defaultValues:TaskReportDefaultValue}) selectedProjec,
const {register,reset,handleSubmit, formState:{errors}} = methods; selectedService
const onSubmit =(formData)=>{} );
return ( const methods = useForm({
<FormProvider {...methods}> resolver: zodResolver(TaskReportFilterSchema),
<form onSubmit={handleSubmit(onSubmit)} className="p-2 text-start"> defaultValues: TaskReportDefaultValue,
<div className="mb-3 w-100"> });
<label className="fw-semibold">Choose Date Range:</label>
<DateRangePicker1
placeholder="DD-MM-YYYY To DD-MM-YYYY"
startField="startDate"
endField="endDate"
resetSignal={resetKey}
defaultRange={false}
/>
</div>
<div className="row g-2"> const {
register,
reset,
handleSubmit,
formState: { errors },
} = methods;
const onSubmit = (formData) => {
console.log(formData)
const filterPayload = {
startDate:localToUtc(formData.startDate),
endDate:localToUtc(formData.endDate)
}
handleFilter(filterPayload);
};
const onClear =()=>{
setResetKey((prev) => prev + 1);
reset(TaskReportDefaultValue)
}
return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit)} className="p-2 text-start">
<div className="mb-3 w-100">
<label className="fw-semibold">Choose Date Range:</label>
<DateRangePicker1
placeholder="DD-MM-YYYY To DD-MM-YYYY"
startField="startDate"
endField="endDate"
resetSignal={resetKey}
defaultRange={true}
/>
</div>
{/* <div className="row g-2">
<SelectMultiple <SelectMultiple
name="buildingIds" name="buildingIds"
label="Projects" label="Projects"
@ -47,23 +77,19 @@ const TaskReportFilterPanel = () => {
labelKey="floorName" labelKey="floorName"
valueKey="id" valueKey="id"
/> />
</div> </div> */}
<div className="d-flex justify-content-end py-3 gap-2"> <div className="d-flex justify-content-end py-3 gap-2">
<button <button type="button" className="btn btn-label-secondary btn-sm">
type="button" Clear
className="btn btn-label-secondary btn-xs" </button>
> <button type="submit" className="btn btn-primary btn-sm">
Clear Apply
</button> </button>
<button type="submit" className="btn btn-primary btn-xs"> </div>
Apply </form>
</button> </FormProvider>
</div> );
</form> };
</FormProvider>
)
}
export default TaskReportFilterPanel export default TaskReportFilterPanel;

View File

@ -29,7 +29,7 @@ const TaskReportList = () => {
const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK); const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK);
const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK); const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK);
const { service, openModal, closeModal } = useDailyProgrssContext(); const { service, openModal, closeModal,filter } = useDailyProgrssContext();
const selectedProject = useSelectedProject(); const selectedProject = useSelectedProject();
const { projectNames } = useProjectName(); const { projectNames } = useProjectName();
@ -37,7 +37,7 @@ const TaskReportList = () => {
selectedProject, selectedProject,
ITEMS_PER_PAGE, ITEMS_PER_PAGE,
currentPage, currentPage,
service service,filter
); );
const ProgrssReportColumn = [ const ProgrssReportColumn = [

View File

@ -1,15 +1,15 @@
import { z } from "zod"; import { z } from "zod";
export const TaskReportFilterSchema = z.object({ export const TaskReportFilterSchema = z.object({
buildingIds: z.array(z.string()).optional(), // buildingIds: z.array(z.string()).optional(),
floorIds: z.array(z.string()).optional(), // floorIds: z.array(z.string()).optional(),
startDate: z.string().optional(), startDate: z.string().optional(),
endDate: z.string().optional(), endDate: z.string().optional(),
}); });
export const TaskReportDefaultValue = { export const TaskReportDefaultValue = {
buildingIds:[], // buildingIds:[],
floorIds:[], // floorIds:[],
startDate:null, startDate:null,
endDate:null endDate:null
} }

View File

@ -200,12 +200,12 @@ const ExpenseFilterPanel = ({ onApply, handleGroupBy }) => {
<div className="d-flex justify-content-end py-3 gap-2"> <div className="d-flex justify-content-end py-3 gap-2">
<button <button
type="button" type="button"
className="btn btn-label-secondary btn-xs" className="btn btn-label-secondary btn-sm"
onClick={onClear} onClick={onClear}
> >
Clear Clear
</button> </button>
<button type="submit" className="btn btn-primary btn-xs"> <button type="submit" className="btn btn-primary btn-sm">
Apply Apply
</button> </button>
</div> </div>

View File

@ -19,7 +19,12 @@ const ManagOrg = () => {
const { data: service, isLoading } = useGlobalServices(); const { data: service, isLoading } = useGlobalServices();
const { flowType, orgData, startStep, onOpen, onClose, prevStep } = const { flowType, orgData, startStep, onOpen, onClose, prevStep } =
useOrganizationModal(); useOrganizationModal();
const {data:organization,isLoading:organizationLoading,isError,error} = useOrganization(orgData?.id); const {
data: organization,
isLoading: organizationLoading,
isError,
error,
} = useOrganization(orgData?.id);
const method = useForm({ const method = useForm({
resolver: zodResolver(organizationSchema), resolver: zodResolver(organizationSchema),
@ -47,25 +52,27 @@ const ManagOrg = () => {
onOpen({ startStep: 1 }); onOpen({ startStep: 1 });
onClose(); onClose();
}); });
console.log(organization)
// Prefill form if editing // Prefill form if editing
useEffect(() => { useEffect(() => {
if (orgData) { if (organization) {
console.log(orgData);
reset({ reset({
name: orgData.name || "", name: organization.name || "",
contactPerson: orgData.contactPerson || "", contactPerson: organization.contactPerson || "",
contactNumber: orgData.contactNumber || "", contactNumber: organization.contactNumber || "",
email: orgData.email || "", email: organization.email || "",
serviceIds: orgData.services?.map((s) => s.id) || [], serviceIds: organization.services?.map((s) => s.id) || [],
address: orgData.address || "", address: organization.address || "",
}); });
} }
}, [orgData, reset]); }, [organization, reset, service?.data]);
const onSubmit = (payload) => { const onSubmit = (formData) => {
if (orgData?.id) { let payload = { ...formData };
updateOrganization({ id: orgData.id, ...payload }); if (organization?.id) {
updateOrganization({
orgId: organization.id,
payload: { ...payload, id: organization.id },
});
} else { } else {
createOrganization(payload); createOrganization(payload);
} }
@ -144,11 +151,11 @@ console.log(organization)
<div className="mb-1 text-start"> <div className="mb-1 text-start">
<SelectMultiple <SelectMultiple
name="serviceIds" name="serviceIds"
label="Services" label="Select Service"
required options={service?.data}
labelKey="name"
valueKey="id" valueKey="id"
options={service?.data || []} IsLoading={isLoading}
required = {true}
/> />
{errors.serviceIds && ( {errors.serviceIds && (
<span className="danger-text">{errors.serviceIds.message}</span> <span className="danger-text">{errors.serviceIds.message}</span>

View File

@ -19,7 +19,7 @@ export const organizationSchema = z.object({
.email("Invalid email address"), .email("Invalid email address"),
serviceIds: z serviceIds: z
.array(z.string()) .array(z.string())
.min(1, { message: "Please insert service id" }), .min(1, { message: "Service isrequired" }),
}); });
export const defaultOrganizationValues = { export const defaultOrganizationValues = {

View File

@ -106,13 +106,13 @@ const TenantFilterPanel = ({ onApply }) => {
<div className="d-flex justify-content-end py-3 gap-2"> <div className="d-flex justify-content-end py-3 gap-2">
<button <button
type="button" type="button"
className="btn btn-label-secondary btn-xs" className="btn btn-label-secondary btn-sm"
onClick={onClear} onClick={onClear}
> >
Clear Clear
</button> </button>
<button type="submit" className="btn btn-primary btn-xs" > <button type="submit" className="btn btn-primary btn-sm" >
Apply Apply
</button> </button>
</div> </div>

View File

@ -8,25 +8,24 @@ const SelectMultiple = ({
name, name,
options = [], options = [],
label = "Select options", label = "Select options",
labelKey = "name", labelKey = "name",
valueKey = "id", valueKey = "id",
placeholder = "Please select...", placeholder = "Please select...",
IsLoading = false, IsLoading = false,required = false
required = false
}) => { }) => {
const { setValue, watch } = useFormContext(); const { setValue, watch,register } = useFormContext();
const selectedValues = watch(name) || []; useEffect(() => {
register(name, { value: [] });
}, [register, name]);
const selectedValues = watch(name) || [];
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [searchText, setSearchText] = useState(""); const [searchText, setSearchText] = useState("");
const containerRef = useRef(null); const containerRef = useRef(null);
const dropdownRef = useRef(null); const dropdownRef = useRef(null);
const [dropdownStyles, setDropdownStyles] = useState({ const [dropdownStyles, setDropdownStyles] = useState({ top: 0, left: 0, width: 0 });
top: 0,
left: 0,
width: 0,
});
useEffect(() => { useEffect(() => {
const handleClickOutside = (e) => { const handleClickOutside = (e) => {
@ -65,10 +64,14 @@ const SelectMultiple = ({
setValue(name, updated, { shouldValidate: true }); setValue(name, updated, { shouldValidate: true });
}; };
const filteredOptions = options.filter((item) => { const filteredOptions = (options || []).filter((item) => {
const label = getLabel(item); const label = getLabel(item);
return label?.toLowerCase().includes(searchText.toLowerCase()); return (
}); typeof label === "string" &&
label.toLowerCase().includes(searchText.toLowerCase())
);
});
const dropdownElement = ( const dropdownElement = (
<div <div
@ -106,14 +109,8 @@ const SelectMultiple = ({
return ( return (
<div <div
key={valueVal} key={valueVal}
className={`multi-select-dropdown-option ${ className={`multi-select-dropdown-option ${isChecked ? "selected" : ""}`}
isChecked ? "selected" : "" style={{ display: "flex", alignItems: "center", padding: "4px 8px" }}
}`}
style={{
display: "flex",
alignItems: "center",
padding: "4px 8px",
}}
> >
<input <input
type="checkbox" type="checkbox"
@ -142,13 +139,9 @@ const SelectMultiple = ({
return ( return (
<> <>
<div <div ref={containerRef} className="multi-select-dropdown-container" style={{ position: "relative" }}>
ref={containerRef} <label className="form-label mb-1">{label}</label>
className="multi-select-dropdown-container" <Label className={name} required={required}></Label>
style={{ position: "relative" }}
>
<Label required={required}>{label}</Label>
<div <div
className="multi-select-dropdown-header" className="multi-select-dropdown-header"
@ -157,9 +150,7 @@ const SelectMultiple = ({
> >
<span <span
className={ className={
selectedValues.length > 0 selectedValues.length > 0 ? "placeholder-style-selected" : "placeholder-style"
? "placeholder-style-selected"
: "placeholder-style"
} }
> >
<div className="selected-badges-container"> <div className="selected-badges-container">
@ -168,10 +159,7 @@ const SelectMultiple = ({
const found = options.find((opt) => opt[valueKey] === val); const found = options.find((opt) => opt[valueKey] === val);
const label = found ? getLabel(found) : ""; const label = found ? getLabel(found) : "";
return ( return (
<span <span key={val} className="badge badge-selected-item mx-1 mb-1">
key={val}
className="badge badge-selected-item mx-1 mb-1"
>
{label} {label}
</span> </span>
); );

View File

@ -40,7 +40,10 @@ export const useOrganizationModal = () => {
export const useOrganization=(id)=>{ export const useOrganization=(id)=>{
return useQuery({ return useQuery({
queryKey:["organization",id], queryKey:["organization",id],
queryFn:async()=> await OrganizationRepository.getOrganizaion(id), queryFn:async()=> {
const resp = await await OrganizationRepository.getOrganizaion(id);
return resp.data
},
enabled:!!id enabled:!!id
}) })
} }
@ -171,7 +174,7 @@ export const useAssignOrgToTenant = (onSuccessCallback) => {
}, },
}); });
}; };
export const useUpdateOrganization = () => { export const useUpdateOrganization = (onSuccessCallback) => {
const useClient = useQueryClient(); const useClient = useQueryClient();
return useMutation({ return useMutation({
mutationFn: async ({orgId,payload}) => mutationFn: async ({orgId,payload}) =>

View File

@ -21,7 +21,7 @@ export const useDailyProgrssContext = () => {
const DailyProgrssReport = () => { const DailyProgrssReport = () => {
const [service, setService] = useState(""); const [service, setService] = useState("");
const [filter,setFilter] = useState('')
const { setOffcanvasContent, setShowTrigger } = useFab(); const { setOffcanvasContent, setShowTrigger } = useFab();
const { data, isLoading, isError, error } = useServices(); const { data, isLoading, isError, error } = useServices();
@ -30,15 +30,20 @@ const DailyProgrssReport = () => {
const openModal = (type, data = null) => setModal({ type, data }); const openModal = (type, data = null) => setModal({ type, data });
const closeModal = () => setModal({ type: null, data: null }); const closeModal = () => setModal({ type: null, data: null });
const contextObj = { const contextDispatcher = {
service, service,
openModal, openModal,
closeModal, closeModal,
filter,
}; };
const handleFilter = (filterObj)=>{
setFilter(filterObj)
}
useEffect(() => { useEffect(() => {
setShowTrigger(true); setShowTrigger(true);
setOffcanvasContent("Report Filter", <TaskReportFilterPanel />); setOffcanvasContent("Report Filter", <TaskReportFilterPanel handleFilter={handleFilter} />);
return () => { return () => {
setShowTrigger(false); setShowTrigger(false);
@ -47,7 +52,7 @@ const DailyProgrssReport = () => {
}, []); }, []);
return ( return (
<div className="container-fluid"> <div className="container-fluid">
<DailyProgrssContext.Provider value={contextObj}> <DailyProgrssContext.Provider value={contextDispatcher}>
{modal.type === "report" && ( {modal.type === "report" && (
<GlobalModel isOpen size="md" closeModal={closeModal}> <GlobalModel isOpen size="md" closeModal={closeModal}>
<ReportTask report={modal.data} closeModal={closeModal} /> <ReportTask report={modal.data} closeModal={closeModal} />

View File

@ -2,7 +2,7 @@ import { api } from "../utils/axiosClient";
const OrganizationRepository = { const OrganizationRepository = {
createOrganization: (data) => api.post("/api/Organization/create", data), createOrganization: (data) => api.post("/api/Organization/create", data),
updateOrganizaion:(id,data)=>api.put(`/api/Organization/edit/${id}`), updateOrganizaion:(id,data)=>api.put(`/api/Organization/edit/${id}`,data),
getOrganizaion:(id)=>api.get(`/api/Organization/details/${id}`), getOrganizaion:(id)=>api.get(`/api/Organization/details/${id}`),
getOrganizationList: (pageSize, pageNumber, active, sprid, searchString) => { getOrganizationList: (pageSize, pageNumber, active, sprid, searchString) => {
return api.get( return api.get(

View File

@ -12,6 +12,7 @@ export const TasksRepository = {
const payloadJsonString = encodeURIComponent(JSON.stringify(filter)); const payloadJsonString = encodeURIComponent(JSON.stringify(filter));
url += `&filter=${payloadJsonString}`; url += `&filter=${payloadJsonString}`;
} }
debugger
return api.get(url); return api.get(url);
}, },

View File

@ -1,31 +1,31 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { format, parseISO } from "date-fns"; import { format, parseISO } from "date-fns";
export const formatFileSize=(bytes)=> { export const formatFileSize = (bytes) => {
if (bytes < 1024) return bytes + " B"; if (bytes < 1024) return bytes + " B";
else if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + " KB"; else if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + " KB";
else return (bytes / (1024 * 1024)).toFixed(2) + " MB"; else return (bytes / (1024 * 1024)).toFixed(2) + " MB";
} };
export const AppColorconfig = { export const AppColorconfig = {
colors: { colors: {
primary: '#696cff', primary: "#696cff",
secondary: '#8592a3', secondary: "#8592a3",
success: '#71dd37', success: "#71dd37",
info: '#03c3ec', info: "#03c3ec",
warning: '#ffab00', warning: "#ffab00",
danger: '#ff3e1d', danger: "#ff3e1d",
dark: '#233446', dark: "#233446",
black: '#000', black: "#000",
white: '#fff', white: "#fff",
cardColor: '#fff', cardColor: "#fff",
bodyBg: '#f5f5f9', bodyBg: "#f5f5f9",
bodyColor: '#697a8d', bodyColor: "#697a8d",
headingColor: '#566a7f', headingColor: "#566a7f",
textMuted: '#a1acb8', textMuted: "#a1acb8",
borderColor: '#eceef1' borderColor: "#eceef1",
} },
}; };
export const getColorNameFromHex = (hex) => { export const getColorNameFromHex = (hex) => {
const normalizedHex = hex?.replace(/'/g, '').toLowerCase(); const normalizedHex = hex?.replace(/'/g, "").toLowerCase();
const colors = AppColorconfig.colors; const colors = AppColorconfig.colors;
for (const [name, value] of Object.entries(colors)) { for (const [name, value] of Object.entries(colors)) {
@ -62,18 +62,19 @@ export const getIconByFileType = (type = "") => {
return "bx bx-file"; return "bx bx-file";
}; };
export const normalizeAllowedContentTypes = (allowedContentType) => { export const normalizeAllowedContentTypes = (allowedContentType) => {
if (!allowedContentType) return []; if (!allowedContentType) return [];
if (Array.isArray(allowedContentType)) return allowedContentType; if (Array.isArray(allowedContentType)) return allowedContentType;
if (typeof allowedContentType === "string") return allowedContentType.split(","); if (typeof allowedContentType === "string")
return allowedContentType.split(",");
return []; return [];
}; };
export function localToUtc(localDateString) { export function localToUtc(localDateString) {
if (!localDateString || localDateString.trim() === "") return null; // return null instead of undefined if (!localDateString || localDateString.trim() === "") return null;
const date = new Date(localDateString);
if (isNaN(date.getTime())) return null; // invalid date check const [day, month, year] = localDateString.split("-");
return date.toISOString(); const date = new Date(`${year}-${month}-${day}T00:00:00`);
}
return isNaN(date.getTime()) ? null : date.toISOString();
}

View File

@ -16,7 +16,6 @@ export const axiosClient = axios.create({
// Auto retry failed requests (e.g., network issues) // Auto retry failed requests (e.g., network issues)
axiosRetry(axiosClient, { retries: 3 }); axiosRetry(axiosClient, { retries: 3 });
debugger
// Request Interceptor Add Bearer token if required // Request Interceptor Add Bearer token if required
axiosClient.interceptors.request.use( axiosClient.interceptors.request.use(
async (config) => { async (config) => {