added pagination and partially added filter

This commit is contained in:
pramod mahajan 2025-08-09 10:30:06 +05:30
parent fb3b55c694
commit 4bff065153
9 changed files with 304 additions and 177 deletions

View File

@ -0,0 +1,40 @@
import { zodResolver } from '@hookform/resolvers/zod'
import React from 'react'
import { FormProvider, useForm, useFormContext } from 'react-hook-form'
import { defaultFilterValues, filterSchema } from './TenantSchema'
import Label from '../common/Label'
import SelectMultiple from '../common/SelectMultiple'
import { useIndustries } from '../../hooks/useTenant'
const TenantFilterPanel = () => {
const method = useForm({
resolver:zodResolver(filterSchema),
defaultValues:defaultFilterValues
})
const {control, register, handleSubmit, reset, watch} = method;
const {data,isError,isLoading} = useIndustries()
console.log(data)
const onSubmit =()=>{
}
if(isLoading) return <div className='text-center'>Loading...</div>
return (
<FormProvider {...method}>
<form onsubmit={(handleSubmit(onSubmit))} >
<div className='text-start mb-1'>
<SelectMultiple
name="industryIds"
label="Industries :"
options={data}
labelKey="name"
valueKey="id"
/>
</div>
</form>
</FormProvider>
)
}
export default TenantFilterPanel

View File

@ -64,6 +64,24 @@ export const subscriptionDefaultValues = {
autoRenew: false,
};
export const filterSchema = z.object({
industryIds: z.array(z.string()).optional(),
createdByIds: z.array(z.string()).optional(),
tenantStatusIds: z.array(z.string()).optional(),
references: z.array(z.string()).optional(),
startDate: z.string().optional(),
endDate: z.string().optional(),
});
export const defaultFilterValues = {
industryIds: [],
createdByIds: [],
tenantStatusIds: [],
references: [],
startDate: "YYYY-MM-DDTHH:mm:ssZ",
endDate: "YYYY-MM-DDTHH:mm:ssZ",
};
export const getStepFields = (stepIndex) => {
const stepFieldMap = {
0: [

View File

@ -3,12 +3,14 @@ import { useTenants } from "../../hooks/useTenant";
import { ITEMS_PER_PAGE } from "../../utils/constants";
import { getTenantStatus } from "../../utils/dateUtils";
import IconButton from "../common/IconButton";
import Pagination from "../common/Pagination";
const TenantsList = ({searchText}) => {
const [currentPage, setCurrentPage] = useState(1);
const { data, isLoading, isError, isInitialLoading, error } = useTenants(
ITEMS_PER_PAGE,
currentPage
currentPage,
{},
searchText,
);
const paginate = (page) => {
@ -131,6 +133,13 @@ const TenantsList = ({searchText}) => {
)}
</tbody>
</table>
{data?.data?.length > 0 && (
<Pagination
currentPage={currentPage}
totalPages={data.totalPages}
onPageChange={paginate}
/>
)}
</div>
</div>
</>

View File

@ -1,118 +1,124 @@
[
{
"header": "",
"items": [
{
"text": "Dashboard",
"icon": "bx bx-home",
"available": true,
"link": "/dashboard"
},
{
"text": "Projects",
"icon": "bx bx-building-house",
"available": true,
"link": "/projects"
},
{
"text": "Employees",
"icon": "bx bx-user",
"available": true,
"link": "/employees"
},
{
"text": "Activities",
"icon": "bx bx-list-ul",
"available": true,
"link": "",
"submenu": [
{
"text": "Attendance",
"available": true,
"link": "/activities/Attendance"
},
{
"text": "Daily Task Planning",
"available": true,
"link": "/activities/task"
},
{
"text": "Daily Progress Report",
"available": true,
"link": "/activities/records"
},
{
"text": "Project Report",
"available": true,
"link": "/activities/reports"
},
{
"text": "Daily Expenses",
"available": true,
"link": "/activities/reports"
}
]
},
{
"text": "Directory",
"icon": "bx bx-group",
"available": true,
"link": "/directory"
},
{
"text": "Image Gallary",
"icon": "bx bx-images",
"available": true,
"link": "/gallary"
},
{
"text": "Administration",
"icon": "bx bx-box",
"available": true,
"link": "",
"submenu": [
{
"text": "Users",
"available": true,
"link": "/employees/"
},
{
"text": "Masters",
"available": true,
"link": "/masters"
}
]
},
{
"text": "Inventory",
"icon": "bx bx-store",
"available": true,
"link": "/inventory"
}
{
"header": "",
"items": [
{
"text": "Dashboard",
"icon": "bx bx-home",
"available": true,
"link": "/dashboard"
},
{
"text": "Projects",
"icon": "bx bx-building-house",
"available": true,
"link": "/projects"
},
{
"text": "Employees",
"icon": "bx bx-user",
"available": true,
"link": "/employees"
},
{
"text": "Activities",
"icon": "bx bx-list-ul",
"available": true,
"link": "",
"submenu": [
{
"text": "Attendance",
"available": true,
"link": "/activities/Attendance"
},
{
"text": "Daily Task Planning",
"available": true,
"link": "/activities/task"
},
{
"text": "Daily Progress Report",
"available": true,
"link": "/activities/records"
},
{
"text": "Project Report",
"available": true,
"link": "/activities/reports"
},
{
"text": "Daily Expenses",
"available": true,
"link": "/activities/reports"
}
]
},
{
"header": "",
"items": [
{
"text": "Support",
"icon": "bx bx-copy",
"available": true,
"link": "/help/support"
},
{
"text": "Documentation",
"available": true,
"icon": "bx bx-book-reader",
"link": "/help/docs"
},
{
"text": "Help Desk",
"available": true,
"link": "/help/connect",
"icon": "bx bx-question-mark"
}
},
{
"text": "Directory",
"icon": "bx bx-group",
"available": true,
"link": "/directory"
},
{
"text": "Expense",
"icon": "bx bx-receipt",
"available": true,
"link": "/expenses"
},
{
"text": "Image Gallary",
"icon": "bx bx-images",
"available": true,
"link": "/gallary"
},
{
"text": "Administration",
"icon": "bx bx-box",
"available": true,
"link": "",
"submenu": [
{
"text": "Tenant",
"available": true,
"link": "/tenants/"
},
{
"text": "Masters",
"available": true,
"link": "/masters"
}
]
}
},
{
"text": "Inventory",
"icon": "bx bx-store",
"available": true,
"link": "/inventory"
}
]
},
{
"header": "",
"items": [
{
"text": "Support",
"icon": "bx bx-copy",
"available": true,
"link": "/help/support"
},
{
"text": "Documentation",
"available": true,
"icon": "bx bx-book-reader",
"link": "/help/docs"
},
{
"text": "Help Desk",
"available": true,
"link": "/help/connect",
"icon": "bx bx-question-mark"
}
]
}
]

View File

@ -4,23 +4,22 @@ import { MarketRepository } from "../repositories/MarketRepository";
import showToast from "../services/toastService";
import { useDispatch } from "react-redux";
import { setCurrentTenant } from "../slices/globalVariablesSlice";
import { ITEMS_PER_PAGE } from "../utils/constants";
export const useTenants = (
pageSize,
pageNumber,
filter,
searchString = ""
) => {
export const useTenants = (pageNumber, filter = {}, searchString = "") => {
return useQuery({
queryKey: ["Tenants", pageNumber, pageSize],
queryKey: ["Tenants", pageNumber, JSON.stringify(filter), searchString],
queryFn: async () => {
const response = await TenantRepository.getTenantList(
pageSize,
ITEMS_PER_PAGE,
pageNumber,
filter,
searchString
);
return response.data;
},
keepPreviousData: true,
staleTime: 60_000
});
};

View File

@ -48,11 +48,13 @@ const DailyTask = () => {
dateRange?.endDate || null
);
useEffect(() => {
if(selectedProject == null){
dispatch(setProjectId(projectNames[0]?.id));
}
},[])
useEffect(() => {
if (!selectedProject?.id && projectNames.length > 0) {
dispatch(setProjectId(projectNames[0].id));
}
}, [selectedProject, projectNames, dispatch]);
const [TaskLists, setTaskLists] = useState([]);
const [dates, setDates] = useState([]);
const popoverRefs = useRef([]);

View File

@ -1,9 +1,19 @@
import React, { useState,createContext } from "react";
import React, { useState, createContext, useEffect } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
// ------Components-------
import Breadcrumb from "../../components/common/Breadcrumb";
import TenantsList from "../../components/Tenanat/TenantsList";
import { useNavigate } from "react-router-dom";
import { useDebounce } from "../../utils/appUtils";
import { useFab } from "../../Context/FabContext";
//---------- Schema and defaultValues----
import { defaultFilterValues, filterSchema } from "../../components/Tenanat/TenantSchema";
import TenantFilterPanel from "../../components/Tenanat/TenantFilterPanel";
// This is context that wrapping all components tenant releated , but must pass inside 'TenantContext.Provider'
export const TenantContext = createContext();
export const useTenantContext = () => {
const context = useContext(TenantContext);
@ -12,52 +22,72 @@ export const useTenantContext = () => {
}
return context;
};
const TenantPage = () => {
const [searchText, setSearchText] = useState("");
const debouncedSearch = useDebounce(searchText, 500);
const contextValue = {};
const navigate = useNavigate();
const contextValue = {
};
return (
<TenantContext.Provider value={contextValue}>
<div className="container-fluid">
<Breadcrumb
data={[
{ label: "Home", link: "/dashboard" },
{ label: "Tenant", link: null },
]}
/>
<div className="card d-flex p-3">
<div className="row align-items-center">
<div className="col-6 col-md-6 col-lg-3 mb-md-0">
<input
type="search"
className="form-control form-control-sm"
placeholder="Search..."
/>
</div>
const { setOffcanvasContent, setShowTrigger } = useFab();
<div className="col-6 col-md-6 col-lg-9 text-end">
<button
type="button"
data-bs-toggle="tooltip"
data-bs-offset="0,8"
data-bs-placement="top"
data-bs-custom-class="tooltip"
title="Add New Tenant"
className="p-1 bg-primary rounded-circle"
onClick={() => navigate("/tenants/new-tenant")}
>
<i className="bx bx-plus fs-4 text-white"></i>
</button>
// This Hook allow us to right-side bar for filter Tenants
useEffect(() => {
setShowTrigger(true);
setOffcanvasContent(
"Expense Filters",
<TenantFilterPanel/>
);
return () => {
setShowTrigger(false);
setOffcanvasContent("", null);
};
}, []);
return (
<TenantContext.Provider value={contextValue}>
<div className="container-fluid">
<Breadcrumb
data={[
{ label: "Home", link: "/dashboard" },
{ label: "Tenant", link: null },
]}
/>
<div className="card d-flex p-2">
<div className="row align-items-center">
<div className="col-6 col-md-6 col-lg-3 mb-md-0">
<input
type="search"
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
className="form-control form-control-sm"
placeholder="Search..."
/>
</div>
<div className="col-6 col-md-6 col-lg-9 text-end">
<button
type="button"
data-bs-toggle="tooltip"
data-bs-offset="0,8"
data-bs-placement="top"
data-bs-custom-class="tooltip"
title="Add New Tenant"
className="p-1 bg-primary rounded-circle"
onClick={() => navigate("/tenants/new-tenant")}
>
<i className="bx bx-plus fs-4 text-white"></i>
</button>
</div>
</div>
</div>
</div>
<TenantsList searchText ={searchText} />
</div>
<TenantsList searchText={debouncedSearch} />
</div>
</TenantContext.Provider>
);
};

View File

@ -40,6 +40,7 @@ import Directory from "../pages/Directory/Directory";
import LoginWithOtp from "../pages/authentication/LoginWithOtp";
import TenantPage from "../pages/Tenant/TenantPage";
import CreateTenant from "../pages/Tenant/CreateTenant";
import ExpensePage from "../pages/Expense/ExpensePage";
const router = createBrowserRouter(
[

View File

@ -1,6 +1,6 @@
export const THRESH_HOLD = 48; // hours
export const DURATION_TIME = 10; // minutes
export const ITEMS_PER_PAGE = 20;
export const DURATION_TIME = 20; // minutes
export const ITEMS_PER_PAGE = 10;
export const OTP_EXPIRY_SECONDS = 600 // OTP time
export const MANAGE_MASTER = "588a8824-f924-4955-82d8-fc51956cf323";
@ -41,14 +41,36 @@ export const DIRECTORY_MANAGER = "62668630-13ce-4f52-a0f0-db38af2230c5"
export const DIRECTORY_USER = "0f919170-92d4-4337-abd3-49b66fc871bb"
export const BASIC_PLAN = "08ddd43e-ca62-4cf4-8d7b-569a364307f4"
export const VIEW_SELF_EXPENSE = "385be49f-8fde-440e-bdbc-3dffeb8dd116"
export const VIEW_ALL_EXPNESE = "01e06444-9ca7-4df4-b900-8c3fa051b92f";
export const CREATE_EXEPENSE = "0f57885d-bcb2-4711-ac95-d841ace6d5a7";
export const REVIEW_EXPENSE = "1f4bda08-1873-449a-bb66-3e8222bd871b";
export const APPROVE_EXPENSE = "eaafdd76-8aac-45f9-a530-315589c6deca";
export const PROCESS_EXPENSE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"
export const EXPENSE_MANAGE = "ea5a1529-4ee8-4828-80ea-0e23c9d4dd11"
export const EXPENSE_REJECTEDBY = ["d1ee5eec-24b6-4364-8673-a8f859c60729","965eda62-7907-4963-b4a1-657fb0b2724b"]
export const EXPENSE_DRAFT = "297e0d8f-f668-41b5-bfea-e03b354251c8"
export const ActiveTenant = "297e0d8f-f668-41b5-bfea-e03b354251c8"
// -------------------Application Role------------------------------
// 1 - Expense Manage
export const EXPENSE_MANAGEMENT = "a4e25142-449b-4334-a6e5-22f70e4732d7"
export const CONSTANT_TEXT = {
}
export const BASE_URL = process.env.VITE_BASE_URL;
export const ActiveTenant = "62b05792-5115-4f99-8ff5-e8374859b191"
// export const BASE_URL = "https://api.marcoaiot.com";
export const CONSTANT_TEXT = {
RenewsubscriptionLabel : " This option; if checked, will renew your productive subscription, if the current plan expires."
}