added updation for fllter
This commit is contained in:
parent
22514b1fa0
commit
72424eee53
@ -1,36 +1,66 @@
|
||||
import React, { useState } from 'react'
|
||||
import { useCurrentService, useProjectInfra } from '../../hooks/useProjects'
|
||||
import { useSelectedProject } from '../../slices/apiDataManager';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { TaskReportDefaultValue, TaskReportFilterSchema } from './TaskRportScheam';
|
||||
import { DateRangePicker1 } from '../common/DateRangePicker';
|
||||
import SelectMultiple from '../common/SelectMultiple';
|
||||
import React, { useState } from "react";
|
||||
import { useCurrentService, useProjectInfra } from "../../hooks/useProjects";
|
||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import {
|
||||
TaskReportDefaultValue,
|
||||
TaskReportFilterSchema,
|
||||
} from "./TaskRportScheam";
|
||||
import { DateRangePicker1 } from "../common/DateRangePicker";
|
||||
import SelectMultiple from "../common/SelectMultiple";
|
||||
import { localToUtc } from "../../utils/appUtils";
|
||||
|
||||
const TaskReportFilterPanel = () => {
|
||||
const [resetKey, setResetKey] = useState(0);
|
||||
const selectedProjec = useSelectedProject()
|
||||
const TaskReportFilterPanel = ({ handleFilter }) => {
|
||||
const [resetKey, setResetKey] = useState(0);
|
||||
const selectedProjec = useSelectedProject();
|
||||
const selectedService = useCurrentService();
|
||||
const {projectInfra, isLoading, error, isFetched } = useProjectInfra(selectedProjec,selectedService);
|
||||
const methods = useForm({resolver:zodResolver(TaskReportFilterSchema),defaultValues:TaskReportDefaultValue})
|
||||
const {register,reset,handleSubmit, formState:{errors}} = methods;
|
||||
const onSubmit =(formData)=>{}
|
||||
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={false}
|
||||
/>
|
||||
</div>
|
||||
const { projectInfra, isLoading, error, isFetched } = useProjectInfra(
|
||||
selectedProjec,
|
||||
selectedService
|
||||
);
|
||||
const methods = useForm({
|
||||
resolver: zodResolver(TaskReportFilterSchema),
|
||||
defaultValues: TaskReportDefaultValue,
|
||||
});
|
||||
|
||||
<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
|
||||
name="buildingIds"
|
||||
label="Projects"
|
||||
@ -47,23 +77,19 @@ const TaskReportFilterPanel = () => {
|
||||
labelKey="floorName"
|
||||
valueKey="id"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div> */}
|
||||
|
||||
<div className="d-flex justify-content-end py-3 gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-label-secondary btn-xs"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
<button type="submit" className="btn btn-primary btn-xs">
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
)
|
||||
}
|
||||
<div className="d-flex justify-content-end py-3 gap-2">
|
||||
<button type="button" className="btn btn-label-secondary btn-sm">
|
||||
Clear
|
||||
</button>
|
||||
<button type="submit" className="btn btn-primary btn-sm">
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default TaskReportFilterPanel
|
||||
export default TaskReportFilterPanel;
|
||||
|
@ -29,7 +29,7 @@ const TaskReportList = () => {
|
||||
const ApprovedTaskRights = useHasUserPermission(APPROVE_TASK);
|
||||
const ReportTaskRights = useHasUserPermission(ASSIGN_REPORT_TASK);
|
||||
|
||||
const { service, openModal, closeModal } = useDailyProgrssContext();
|
||||
const { service, openModal, closeModal,filter } = useDailyProgrssContext();
|
||||
const selectedProject = useSelectedProject();
|
||||
const { projectNames } = useProjectName();
|
||||
|
||||
@ -37,7 +37,7 @@ const TaskReportList = () => {
|
||||
selectedProject,
|
||||
ITEMS_PER_PAGE,
|
||||
currentPage,
|
||||
service
|
||||
service,filter
|
||||
);
|
||||
|
||||
const ProgrssReportColumn = [
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const TaskReportFilterSchema = z.object({
|
||||
buildingIds: z.array(z.string()).optional(),
|
||||
floorIds: z.array(z.string()).optional(),
|
||||
// buildingIds: z.array(z.string()).optional(),
|
||||
// floorIds: z.array(z.string()).optional(),
|
||||
startDate: z.string().optional(),
|
||||
endDate: z.string().optional(),
|
||||
});
|
||||
|
||||
export const TaskReportDefaultValue = {
|
||||
buildingIds:[],
|
||||
floorIds:[],
|
||||
// buildingIds:[],
|
||||
// floorIds:[],
|
||||
startDate:null,
|
||||
endDate:null
|
||||
}
|
@ -200,12 +200,12 @@ const ExpenseFilterPanel = ({ onApply, handleGroupBy }) => {
|
||||
<div className="d-flex justify-content-end py-3 gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-label-secondary btn-xs"
|
||||
className="btn btn-label-secondary btn-sm"
|
||||
onClick={onClear}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
<button type="submit" className="btn btn-primary btn-xs">
|
||||
<button type="submit" className="btn btn-primary btn-sm">
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
|
@ -19,7 +19,12 @@ const ManagOrg = () => {
|
||||
const { data: service, isLoading } = useGlobalServices();
|
||||
const { flowType, orgData, startStep, onOpen, onClose, prevStep } =
|
||||
useOrganizationModal();
|
||||
const {data:organization,isLoading:organizationLoading,isError,error} = useOrganization(orgData?.id);
|
||||
const {
|
||||
data: organization,
|
||||
isLoading: organizationLoading,
|
||||
isError,
|
||||
error,
|
||||
} = useOrganization(orgData?.id);
|
||||
|
||||
const method = useForm({
|
||||
resolver: zodResolver(organizationSchema),
|
||||
@ -47,25 +52,27 @@ const ManagOrg = () => {
|
||||
onOpen({ startStep: 1 });
|
||||
onClose();
|
||||
});
|
||||
console.log(organization)
|
||||
// Prefill form if editing
|
||||
useEffect(() => {
|
||||
if (orgData) {
|
||||
console.log(orgData);
|
||||
if (organization) {
|
||||
reset({
|
||||
name: orgData.name || "",
|
||||
contactPerson: orgData.contactPerson || "",
|
||||
contactNumber: orgData.contactNumber || "",
|
||||
email: orgData.email || "",
|
||||
serviceIds: orgData.services?.map((s) => s.id) || [],
|
||||
address: orgData.address || "",
|
||||
name: organization.name || "",
|
||||
contactPerson: organization.contactPerson || "",
|
||||
contactNumber: organization.contactNumber || "",
|
||||
email: organization.email || "",
|
||||
serviceIds: organization.services?.map((s) => s.id) || [],
|
||||
address: organization.address || "",
|
||||
});
|
||||
}
|
||||
}, [orgData, reset]);
|
||||
}, [organization, reset, service?.data]);
|
||||
|
||||
const onSubmit = (payload) => {
|
||||
if (orgData?.id) {
|
||||
updateOrganization({ id: orgData.id, ...payload });
|
||||
const onSubmit = (formData) => {
|
||||
let payload = { ...formData };
|
||||
if (organization?.id) {
|
||||
updateOrganization({
|
||||
orgId: organization.id,
|
||||
payload: { ...payload, id: organization.id },
|
||||
});
|
||||
} else {
|
||||
createOrganization(payload);
|
||||
}
|
||||
@ -144,11 +151,11 @@ console.log(organization)
|
||||
<div className="mb-1 text-start">
|
||||
<SelectMultiple
|
||||
name="serviceIds"
|
||||
label="Services"
|
||||
required
|
||||
label="Select Service"
|
||||
options={service?.data}
|
||||
labelKey="name"
|
||||
valueKey="id"
|
||||
options={service?.data || []}
|
||||
required = {true}
|
||||
IsLoading={isLoading}
|
||||
/>
|
||||
{errors.serviceIds && (
|
||||
<span className="danger-text">{errors.serviceIds.message}</span>
|
||||
|
@ -19,7 +19,7 @@ export const organizationSchema = z.object({
|
||||
.email("Invalid email address"),
|
||||
serviceIds: z
|
||||
.array(z.string())
|
||||
.min(1, { message: "Please insert service id" }),
|
||||
.min(1, { message: "Service isrequired" }),
|
||||
});
|
||||
|
||||
export const defaultOrganizationValues = {
|
||||
|
@ -106,13 +106,13 @@ const TenantFilterPanel = ({ onApply }) => {
|
||||
<div className="d-flex justify-content-end py-3 gap-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-label-secondary btn-xs"
|
||||
className="btn btn-label-secondary btn-sm"
|
||||
onClick={onClear}
|
||||
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
<button type="submit" className="btn btn-primary btn-xs" >
|
||||
<button type="submit" className="btn btn-primary btn-sm" >
|
||||
Apply
|
||||
</button>
|
||||
</div>
|
||||
|
@ -8,25 +8,24 @@ const SelectMultiple = ({
|
||||
name,
|
||||
options = [],
|
||||
label = "Select options",
|
||||
labelKey = "name",
|
||||
labelKey = "name",
|
||||
valueKey = "id",
|
||||
placeholder = "Please select...",
|
||||
IsLoading = false,
|
||||
required = false
|
||||
IsLoading = false,required = false
|
||||
}) => {
|
||||
const { setValue, watch } = useFormContext();
|
||||
const selectedValues = watch(name) || [];
|
||||
const { setValue, watch,register } = useFormContext();
|
||||
useEffect(() => {
|
||||
register(name, { value: [] });
|
||||
}, [register, name]);
|
||||
|
||||
const selectedValues = watch(name) || [];
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [searchText, setSearchText] = useState("");
|
||||
const containerRef = useRef(null);
|
||||
const dropdownRef = useRef(null);
|
||||
|
||||
const [dropdownStyles, setDropdownStyles] = useState({
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
});
|
||||
const [dropdownStyles, setDropdownStyles] = useState({ top: 0, left: 0, width: 0 });
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (e) => {
|
||||
@ -65,10 +64,14 @@ const SelectMultiple = ({
|
||||
setValue(name, updated, { shouldValidate: true });
|
||||
};
|
||||
|
||||
const filteredOptions = options.filter((item) => {
|
||||
const label = getLabel(item);
|
||||
return label?.toLowerCase().includes(searchText.toLowerCase());
|
||||
});
|
||||
const filteredOptions = (options || []).filter((item) => {
|
||||
const label = getLabel(item);
|
||||
return (
|
||||
typeof label === "string" &&
|
||||
label.toLowerCase().includes(searchText.toLowerCase())
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
const dropdownElement = (
|
||||
<div
|
||||
@ -106,14 +109,8 @@ const SelectMultiple = ({
|
||||
return (
|
||||
<div
|
||||
key={valueVal}
|
||||
className={`multi-select-dropdown-option ${
|
||||
isChecked ? "selected" : ""
|
||||
}`}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "4px 8px",
|
||||
}}
|
||||
className={`multi-select-dropdown-option ${isChecked ? "selected" : ""}`}
|
||||
style={{ display: "flex", alignItems: "center", padding: "4px 8px" }}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
@ -142,13 +139,9 @@ const SelectMultiple = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="multi-select-dropdown-container"
|
||||
style={{ position: "relative" }}
|
||||
>
|
||||
<Label required={required}>{label}</Label>
|
||||
|
||||
<div ref={containerRef} className="multi-select-dropdown-container" style={{ position: "relative" }}>
|
||||
<label className="form-label mb-1">{label}</label>
|
||||
<Label className={name} required={required}></Label>
|
||||
|
||||
<div
|
||||
className="multi-select-dropdown-header"
|
||||
@ -157,9 +150,7 @@ const SelectMultiple = ({
|
||||
>
|
||||
<span
|
||||
className={
|
||||
selectedValues.length > 0
|
||||
? "placeholder-style-selected"
|
||||
: "placeholder-style"
|
||||
selectedValues.length > 0 ? "placeholder-style-selected" : "placeholder-style"
|
||||
}
|
||||
>
|
||||
<div className="selected-badges-container">
|
||||
@ -168,10 +159,7 @@ const SelectMultiple = ({
|
||||
const found = options.find((opt) => opt[valueKey] === val);
|
||||
const label = found ? getLabel(found) : "";
|
||||
return (
|
||||
<span
|
||||
key={val}
|
||||
className="badge badge-selected-item mx-1 mb-1"
|
||||
>
|
||||
<span key={val} className="badge badge-selected-item mx-1 mb-1">
|
||||
{label}
|
||||
</span>
|
||||
);
|
||||
|
@ -40,7 +40,10 @@ export const useOrganizationModal = () => {
|
||||
export const useOrganization=(id)=>{
|
||||
return useQuery({
|
||||
queryKey:["organization",id],
|
||||
queryFn:async()=> await OrganizationRepository.getOrganizaion(id),
|
||||
queryFn:async()=> {
|
||||
const resp = await await OrganizationRepository.getOrganizaion(id);
|
||||
return resp.data
|
||||
},
|
||||
enabled:!!id
|
||||
})
|
||||
}
|
||||
@ -171,7 +174,7 @@ export const useAssignOrgToTenant = (onSuccessCallback) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
export const useUpdateOrganization = () => {
|
||||
export const useUpdateOrganization = (onSuccessCallback) => {
|
||||
const useClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({orgId,payload}) =>
|
||||
|
@ -21,7 +21,7 @@ export const useDailyProgrssContext = () => {
|
||||
|
||||
const DailyProgrssReport = () => {
|
||||
const [service, setService] = useState("");
|
||||
|
||||
const [filter,setFilter] = useState('')
|
||||
const { setOffcanvasContent, setShowTrigger } = useFab();
|
||||
const { data, isLoading, isError, error } = useServices();
|
||||
|
||||
@ -30,15 +30,20 @@ const DailyProgrssReport = () => {
|
||||
const openModal = (type, data = null) => setModal({ type, data });
|
||||
const closeModal = () => setModal({ type: null, data: null });
|
||||
|
||||
const contextObj = {
|
||||
const contextDispatcher = {
|
||||
service,
|
||||
openModal,
|
||||
closeModal,
|
||||
filter,
|
||||
};
|
||||
|
||||
const handleFilter = (filterObj)=>{
|
||||
setFilter(filterObj)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setShowTrigger(true);
|
||||
setOffcanvasContent("Report Filter", <TaskReportFilterPanel />);
|
||||
setOffcanvasContent("Report Filter", <TaskReportFilterPanel handleFilter={handleFilter} />);
|
||||
|
||||
return () => {
|
||||
setShowTrigger(false);
|
||||
@ -47,7 +52,7 @@ const DailyProgrssReport = () => {
|
||||
}, []);
|
||||
return (
|
||||
<div className="container-fluid">
|
||||
<DailyProgrssContext.Provider value={contextObj}>
|
||||
<DailyProgrssContext.Provider value={contextDispatcher}>
|
||||
{modal.type === "report" && (
|
||||
<GlobalModel isOpen size="md" closeModal={closeModal}>
|
||||
<ReportTask report={modal.data} closeModal={closeModal} />
|
||||
|
@ -2,7 +2,7 @@ import { api } from "../utils/axiosClient";
|
||||
|
||||
const OrganizationRepository = {
|
||||
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}`),
|
||||
getOrganizationList: (pageSize, pageNumber, active, sprid, searchString) => {
|
||||
return api.get(
|
||||
|
@ -12,6 +12,7 @@ export const TasksRepository = {
|
||||
const payloadJsonString = encodeURIComponent(JSON.stringify(filter));
|
||||
url += `&filter=${payloadJsonString}`;
|
||||
}
|
||||
debugger
|
||||
|
||||
return api.get(url);
|
||||
},
|
||||
|
@ -1,31 +1,31 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { format, parseISO } from "date-fns";
|
||||
export const formatFileSize=(bytes)=> {
|
||||
export const formatFileSize = (bytes) => {
|
||||
if (bytes < 1024) return bytes + " B";
|
||||
else if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + " KB";
|
||||
else return (bytes / (1024 * 1024)).toFixed(2) + " MB";
|
||||
}
|
||||
};
|
||||
export const AppColorconfig = {
|
||||
colors: {
|
||||
primary: '#696cff',
|
||||
secondary: '#8592a3',
|
||||
success: '#71dd37',
|
||||
info: '#03c3ec',
|
||||
warning: '#ffab00',
|
||||
danger: '#ff3e1d',
|
||||
dark: '#233446',
|
||||
black: '#000',
|
||||
white: '#fff',
|
||||
cardColor: '#fff',
|
||||
bodyBg: '#f5f5f9',
|
||||
bodyColor: '#697a8d',
|
||||
headingColor: '#566a7f',
|
||||
textMuted: '#a1acb8',
|
||||
borderColor: '#eceef1'
|
||||
}
|
||||
primary: "#696cff",
|
||||
secondary: "#8592a3",
|
||||
success: "#71dd37",
|
||||
info: "#03c3ec",
|
||||
warning: "#ffab00",
|
||||
danger: "#ff3e1d",
|
||||
dark: "#233446",
|
||||
black: "#000",
|
||||
white: "#fff",
|
||||
cardColor: "#fff",
|
||||
bodyBg: "#f5f5f9",
|
||||
bodyColor: "#697a8d",
|
||||
headingColor: "#566a7f",
|
||||
textMuted: "#a1acb8",
|
||||
borderColor: "#eceef1",
|
||||
},
|
||||
};
|
||||
export const getColorNameFromHex = (hex) => {
|
||||
const normalizedHex = hex?.replace(/'/g, '').toLowerCase();
|
||||
const normalizedHex = hex?.replace(/'/g, "").toLowerCase();
|
||||
const colors = AppColorconfig.colors;
|
||||
|
||||
for (const [name, value] of Object.entries(colors)) {
|
||||
@ -62,18 +62,19 @@ export const getIconByFileType = (type = "") => {
|
||||
return "bx bx-file";
|
||||
};
|
||||
|
||||
|
||||
export const normalizeAllowedContentTypes = (allowedContentType) => {
|
||||
if (!allowedContentType) return [];
|
||||
if (Array.isArray(allowedContentType)) return allowedContentType;
|
||||
if (typeof allowedContentType === "string") return allowedContentType.split(",");
|
||||
if (typeof allowedContentType === "string")
|
||||
return allowedContentType.split(",");
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
export function localToUtc(localDateString) {
|
||||
if (!localDateString || localDateString.trim() === "") return null; // return null instead of undefined
|
||||
const date = new Date(localDateString);
|
||||
if (isNaN(date.getTime())) return null; // invalid date check
|
||||
return date.toISOString();
|
||||
}
|
||||
if (!localDateString || localDateString.trim() === "") return null;
|
||||
|
||||
const [day, month, year] = localDateString.split("-");
|
||||
const date = new Date(`${year}-${month}-${day}T00:00:00`);
|
||||
|
||||
return isNaN(date.getTime()) ? null : date.toISOString();
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ export const axiosClient = axios.create({
|
||||
|
||||
// Auto retry failed requests (e.g., network issues)
|
||||
axiosRetry(axiosClient, { retries: 3 });
|
||||
debugger
|
||||
// Request Interceptor — Add Bearer token if required
|
||||
axiosClient.interceptors.request.use(
|
||||
async (config) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user