complete installation device pagination
This commit is contained in:
Generated
+39
-1
@@ -36,7 +36,8 @@
|
|||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
"yup": "^1.4.0"
|
"yup": "^1.4.0",
|
||||||
|
"zustand": "^4.5.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tanstack/eslint-plugin-query": "^5.51.15",
|
"@tanstack/eslint-plugin-query": "^5.51.15",
|
||||||
@@ -19162,6 +19163,15 @@
|
|||||||
"requires-port": "^1.0.0"
|
"requires-port": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/use-sync-external-store": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
@@ -20275,6 +20285,34 @@
|
|||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zustand": {
|
||||||
|
"version": "4.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz",
|
||||||
|
"integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"use-sync-external-store": "1.2.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.7.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": ">=16.8",
|
||||||
|
"immer": ">=9.0.6",
|
||||||
|
"react": ">=16.8"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"immer": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -31,7 +31,8 @@
|
|||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
"yup": "^1.4.0"
|
"yup": "^1.4.0",
|
||||||
|
"zustand": "^4.5.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|||||||
@@ -2,15 +2,18 @@ import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOption
|
|||||||
import { ArrowDown2 } from 'iconsax-react'
|
import { ArrowDown2 } from 'iconsax-react'
|
||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import { ComboBoxItems } from '../../types'
|
import { ComboBoxItems } from '../../types'
|
||||||
|
import { useParamsStore } from '../../store/params'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
field?: any
|
field?: any
|
||||||
placeholder?: string
|
placeholder?: string
|
||||||
className?: string,
|
className?: string,
|
||||||
data?: ComboBoxItems[] | []
|
data?: ComboBoxItems[] | []
|
||||||
|
mode?: "table" | "default"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ComboBox: FC<Props> = ({ field, placeholder, className, data = [] }) => {
|
export const ComboBox: FC<Props> = ({ field, placeholder, className, data = [], mode = "default" }) => {
|
||||||
|
const { updateParams } = useParamsStore()
|
||||||
const [query, setQuery] = useState('')
|
const [query, setQuery] = useState('')
|
||||||
|
|
||||||
const filteredValue =
|
const filteredValue =
|
||||||
@@ -21,7 +24,12 @@ export const ComboBox: FC<Props> = ({ field, placeholder, className, data = [] }
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Combobox value={field && field.value} onChange={field && field.onChange} onClose={() => setQuery('')} disabled={data?.length <= 0}>
|
<Combobox value={field && field.value} onChange={mode === "default" ? field && field.onChange : (e: ComboBoxItems) => {
|
||||||
|
console.log(e)
|
||||||
|
updateParams({
|
||||||
|
rows: e?.id
|
||||||
|
})
|
||||||
|
}} onClose={() => setQuery('')} disabled={data?.length <= 0}>
|
||||||
<div className="relative w-full">
|
<div className="relative w-full">
|
||||||
<ComboboxInput
|
<ComboboxInput
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ type Props = {
|
|||||||
icon?: React.ReactNode,
|
icon?: React.ReactNode,
|
||||||
field?: any,
|
field?: any,
|
||||||
ref?: any,
|
ref?: any,
|
||||||
className?: string
|
className?: string,
|
||||||
|
value?: string,
|
||||||
|
onChange?: (value: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Input: FC<Props> = ({ placeholder, type = "text", icon, field, ref, className }) => {
|
export const Input: FC<Props> = ({ placeholder, type = "text", icon, field, ref, className, value, onChange }) => {
|
||||||
const [hidden, setHidden] = useState<boolean>(false)
|
const [hidden, setHidden] = useState<boolean>(false)
|
||||||
const handleHidden = () => setHidden(prev => !prev)
|
const handleHidden = () => setHidden(prev => !prev)
|
||||||
return (
|
return (
|
||||||
@@ -26,7 +28,7 @@ export const Input: FC<Props> = ({ placeholder, type = "text", icon, field, ref,
|
|||||||
: icon}
|
: icon}
|
||||||
{placeholder === "شماره کارت" && field.value && findBankByPAN(field.value).icon}
|
{placeholder === "شماره کارت" && field.value && findBankByPAN(field.value).icon}
|
||||||
</div>
|
</div>
|
||||||
<InputComponent ref={ref} {...field} type={type === "password" && hidden ? "text" : type} placeholder={placeholder} className={`input-style min-w-full ${className}`} />
|
<InputComponent ref={ref} {...field} value={value} onChange={onChange} type={type === "password" && hidden ? "text" : type} placeholder={placeholder} className={`input-style min-w-full ${className}`} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,25 @@
|
|||||||
import { flexRender, getCoreRowModel, getPaginationRowModel, SortingState, useReactTable } from "@tanstack/react-table"
|
import { flexRender, getCoreRowModel, getPaginationRowModel, SortingState, useReactTable } from "@tanstack/react-table"
|
||||||
import { ArrowDown2, ArrowLeft2, ArrowRight2, ArrowUp2, SearchNormal1 } from "iconsax-react"
|
import { ArrowDown2, ArrowLeft2, ArrowRight2, ArrowUp2, SearchNormal1 } from "iconsax-react"
|
||||||
import { FC } from "react"
|
import { FC, useEffect } from "react"
|
||||||
import { Input } from "./input"
|
import { Input } from "./input"
|
||||||
import { ComboBox } from "./combo-box"
|
import { ComboBox } from "./combo-box"
|
||||||
import { Loading } from "./loading"
|
import { Loading } from "./loading"
|
||||||
|
import { useParamsStore } from "../../store/params"
|
||||||
|
import { tableRows } from "../../utility/table-rows"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
columns: any
|
columns: any
|
||||||
data: any
|
data: any
|
||||||
sorting: SortingState,
|
sorting?: SortingState,
|
||||||
setSorting: React.Dispatch<React.SetStateAction<SortingState>>,
|
setSorting?: React.Dispatch<React.SetStateAction<SortingState>>,
|
||||||
tableStatus?: string | number,
|
tableStatus?: string | number,
|
||||||
isLoading?: boolean
|
isLoading?: boolean,
|
||||||
|
totalData?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Table: FC<Props> = ({ columns, data, setSorting, sorting, tableStatus, isLoading = false }) => {
|
export const Table: FC<Props> = ({ columns, data, setSorting, sorting, tableStatus, isLoading = false, totalData = 0 }) => {
|
||||||
|
const { updateParams, params } = useParamsStore()
|
||||||
|
const totalPages = Math.ceil(totalData / params?.rows)
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data: data ? data : [],
|
data: data ? data : [],
|
||||||
columns: columns ? columns : [],
|
columns: columns ? columns : [],
|
||||||
@@ -32,14 +36,28 @@ export const Table: FC<Props> = ({ columns, data, setSorting, sorting, tableStat
|
|||||||
getPaginationRowModel: getPaginationRowModel()
|
getPaginationRowModel: getPaginationRowModel()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handleInputValue = (value: string) => {
|
||||||
|
updateParams({
|
||||||
|
search: value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateParams({
|
||||||
|
page: 1,
|
||||||
|
rows: 10,
|
||||||
|
search: ""
|
||||||
|
})
|
||||||
|
}, [updateParams])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-10">
|
<div className="flex flex-col gap-10">
|
||||||
<div className="flex flex-col sm:flex-row justify-between items-center gap-2.5 md:gap-10">
|
<div className="flex flex-col sm:flex-row justify-between items-center gap-2.5 md:gap-10">
|
||||||
<div className="sm:max-w-[300px] xl:max-w-[450px] w-full">
|
<div className="sm:max-w-[300px] xl:max-w-[450px] w-full">
|
||||||
<Input placeholder="جستجو" className="bg-auth-form placeholder:text-[#777577]" icon={<SearchNormal1 color="#777577" />} />
|
<Input placeholder="جستجو" value={params?.search} onChange={(e: any) => handleInputValue(e?.target?.value)} className="bg-auth-form placeholder:text-[#777577]" icon={<SearchNormal1 color="#777577" />} />
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full sm:max-w-[100px]">
|
<div className="w-full sm:max-w-[100px]">
|
||||||
<ComboBox placeholder="100" className="bg-auth-form" />
|
<ComboBox placeholder={params?.rows.toString()} className="bg-auth-form" data={tableRows} mode="table" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{tableStatus && <div className="w-full flex justify-end items-end text-sm lg:text-lg text-primary-text-color font-normal -mb-7 pl-2">امتیاز من: {tableStatus}</div>}
|
{tableStatus && <div className="w-full flex justify-end items-end text-sm lg:text-lg text-primary-text-color font-normal -mb-7 pl-2">امتیاز من: {tableStatus}</div>}
|
||||||
@@ -73,9 +91,13 @@ export const Table: FC<Props> = ({ columns, data, setSorting, sorting, tableStat
|
|||||||
</table>
|
</table>
|
||||||
{isLoading ? <Loading /> :
|
{isLoading ? <Loading /> :
|
||||||
<div className="flex flex-row justify-center items-center border-t p-4 gap-x-3 mt-3">
|
<div className="flex flex-row justify-center items-center border-t p-4 gap-x-3 mt-3">
|
||||||
<ArrowRight2 color="#11212D" size={19} className="cursor-pointer" onClick={() => table.getCanNextPage() && table.nextPage()} />
|
<ArrowRight2 color="#11212D" size={19} className="cursor-pointer" onClick={() => params?.page < totalPages && updateParams({
|
||||||
<p className="text-base font-normal text-primary-text-color">1-{table.getPageCount()}</p>
|
page: params?.page + 1
|
||||||
<ArrowLeft2 color="#11212D" size={19} className="cursor-pointer" onClick={() => table.getCanPreviousPage() && table.previousPage()} />
|
})} />
|
||||||
|
<p className="text-base font-normal text-primary-text-color">{params?.page}-{totalPages}</p>
|
||||||
|
<ArrowLeft2 color="#11212D" size={19} className="cursor-pointer" onClick={() => params?.page > 1 && updateParams({
|
||||||
|
page: params?.page - 1
|
||||||
|
})} />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,18 +1,34 @@
|
|||||||
import { installationReportsCol } from "../../utility/reports"
|
import { installationReportsCol } from "../../utility/reports"
|
||||||
import { Table } from "../common/table"
|
import { Table } from "../common/table"
|
||||||
import { useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import { SortingState } from "@tanstack/react-table"
|
import { useMutation } from "@tanstack/react-query"
|
||||||
import { useQuery } from "@tanstack/react-query"
|
|
||||||
import { getRegisterDeviceList } from "../../services/api/register-device"
|
import { getRegisterDeviceList } from "../../services/api/register-device"
|
||||||
|
import { RegisterDeviceResponse } from "../../types"
|
||||||
|
import { useParamsStore } from "../../store/params"
|
||||||
|
|
||||||
export const InstallationReports = () => {
|
export const InstallationReports = () => {
|
||||||
const [sorting, setSorting] = useState<SortingState>([])
|
const { params } = useParamsStore()
|
||||||
const { data, isLoading } = useQuery({
|
const [data, setData] = useState<RegisterDeviceResponse>({
|
||||||
queryKey: ["register-device"],
|
data: [],
|
||||||
queryFn: getRegisterDeviceList
|
total: 0
|
||||||
})
|
})
|
||||||
|
const { mutate, isPending } = useMutation({
|
||||||
|
mutationFn: getRegisterDeviceList
|
||||||
|
})
|
||||||
|
useEffect(() => {
|
||||||
|
mutate({
|
||||||
|
...params
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onSuccess: (res: any) => {
|
||||||
|
setData({
|
||||||
|
data: res?.data?.data,
|
||||||
|
total: res?.data?.total
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [mutate, params])
|
||||||
return (
|
return (
|
||||||
<Table columns={installationReportsCol} data={data?.data?.data} sorting={sorting} setSorting={setSorting} isLoading={isLoading} />
|
<Table columns={installationReportsCol} data={data?.data} totalData={data?.total} isLoading={isPending} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
import axiosInstance from "../axios";
|
import axiosInstance from "../axios";
|
||||||
|
|
||||||
export const loginMutation = (payload: any) => axiosInstance.post<any>("/auth/gps/login", payload)
|
export const loginMutation = (payload: any) => axiosInstance.post<any>("/auth/gps/login/pass", payload)
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
import { RegisterDeviceResponse } from "../../types";
|
import { RegisterDeviceResponse, TableParams } from "../../types";
|
||||||
import axiosInstance from "../axios";
|
import axiosInstance from "../axios";
|
||||||
|
|
||||||
export const getRegisterDeviceList = () => axiosInstance.get<RegisterDeviceResponse[] | RegisterDeviceResponse | [], any>("/gps/register-device")
|
export const getRegisterDeviceList = (params: TableParams) => axiosInstance.get<RegisterDeviceResponse[] | RegisterDeviceResponse | [], any>("/gps/register-device", {
|
||||||
|
params: params
|
||||||
|
})
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { TableParams } from '../types';
|
||||||
|
|
||||||
|
type ZustandState = {
|
||||||
|
params: TableParams;
|
||||||
|
updateParams: (newParams: Partial<TableParams>) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useParamsStore = create<ZustandState>((set) => ({
|
||||||
|
params: {
|
||||||
|
page: 1,
|
||||||
|
rows: 10,
|
||||||
|
search: "",
|
||||||
|
},
|
||||||
|
updateParams: (newParams: Partial<TableParams>) =>
|
||||||
|
set((state) => ({
|
||||||
|
...state,
|
||||||
|
params: {
|
||||||
|
...state.params,
|
||||||
|
...newParams,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
}));
|
||||||
+10
-11
@@ -168,21 +168,14 @@ export interface DeviceId {
|
|||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
export interface RegisterDeviceResponse {
|
export interface RegisterDeviceResponse {
|
||||||
status: number,
|
data: RegisterDeviceData[] | [],
|
||||||
_id: string,
|
total: number
|
||||||
deviceId: DeviceId
|
|
||||||
registerDate: string,
|
|
||||||
userId: string,
|
|
||||||
created_at: string,
|
|
||||||
updated_at: string,
|
|
||||||
__v: number,
|
|
||||||
id: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RegisterDeviceData {
|
export interface RegisterDeviceData {
|
||||||
status: number,
|
status: number,
|
||||||
_id: string,
|
_id: string,
|
||||||
deviceId: RegisterDeviceData[] | [],
|
deviceId: DeviceId[] | [],
|
||||||
registerDate: string,
|
registerDate: string,
|
||||||
userId: string,
|
userId: string,
|
||||||
created_at: string,
|
created_at: string,
|
||||||
@@ -279,5 +272,11 @@ export interface ScoreResponse {
|
|||||||
|
|
||||||
export interface ComboBoxItems {
|
export interface ComboBoxItems {
|
||||||
name: string,
|
name: string,
|
||||||
id: string | number
|
id: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableParams {
|
||||||
|
page: number,
|
||||||
|
rows: number,
|
||||||
|
search: string
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { ComboBoxItems } from "../types";
|
||||||
|
|
||||||
|
export const tableRows: ComboBoxItems[] | [] | undefined = [
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
name: "10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 20,
|
||||||
|
name: "20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 50,
|
||||||
|
name: "50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 100,
|
||||||
|
name: "100"
|
||||||
|
},
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user