refactor: streamline DashboardCrudPage by integrating useDashboardPagedList and removing redundant state management
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import type { ReactNode } from "react"
|
import type { ReactNode } from "react"
|
||||||
import { useCallback, useEffect, useState } from "react"
|
import { useState } from "react"
|
||||||
import {
|
import {
|
||||||
closestCenter,
|
closestCenter,
|
||||||
DndContext,
|
DndContext,
|
||||||
@@ -38,6 +38,7 @@ import {
|
|||||||
} from "@/components/dashboard-page"
|
} from "@/components/dashboard-page"
|
||||||
import { ListPagination } from "@/components/list-pagination"
|
import { ListPagination } from "@/components/list-pagination"
|
||||||
import { OptionCombobox } from "@/components/option-combobox"
|
import { OptionCombobox } from "@/components/option-combobox"
|
||||||
|
import { useDashboardPagedList } from "@/components/dashboard/list"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { ButtonGroup } from "@/components/ui/button-group"
|
import { ButtonGroup } from "@/components/ui/button-group"
|
||||||
import {
|
import {
|
||||||
@@ -56,10 +57,8 @@ import {
|
|||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table"
|
} from "@/components/ui/table"
|
||||||
import {
|
import {
|
||||||
buildDashboardCrudQuery,
|
|
||||||
isDashboardCrudActionDisabled,
|
isDashboardCrudActionDisabled,
|
||||||
isDashboardCrudActionVisible,
|
isDashboardCrudActionVisible,
|
||||||
normalizeDashboardCrudPageResult,
|
|
||||||
type DashboardCrudActionRule,
|
type DashboardCrudActionRule,
|
||||||
type DashboardCrudFormField,
|
type DashboardCrudFormField,
|
||||||
type DashboardCrudPageResult,
|
type DashboardCrudPageResult,
|
||||||
@@ -67,7 +66,6 @@ import {
|
|||||||
type DashboardCrudQueryValue,
|
type DashboardCrudQueryValue,
|
||||||
} from "./dashboard-crud-utils"
|
} from "./dashboard-crud-utils"
|
||||||
import { DashboardCrudFormDialog } from "./dashboard-crud-form-dialog"
|
import { DashboardCrudFormDialog } from "./dashboard-crud-form-dialog"
|
||||||
import { useDashboardCrudFilters } from "./use-dashboard-crud-filters"
|
|
||||||
|
|
||||||
export type DashboardCrudFilter<TValue extends string | number = string> =
|
export type DashboardCrudFilter<TValue extends string | number = string> =
|
||||||
DashboardCrudQueryFilter & {
|
DashboardCrudQueryFilter & {
|
||||||
@@ -207,53 +205,24 @@ export function DashboardCrudPage<TItem, TPayload>({
|
|||||||
coordinateGetter: sortableKeyboardCoordinates,
|
coordinateGetter: sortableKeyboardCoordinates,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
const { draftFilters, appliedFilters, setDraftFilter, applyFilters } =
|
const list = useDashboardPagedList<TItem>({
|
||||||
useDashboardCrudFilters(filters)
|
filters,
|
||||||
const filtersKey = filters
|
fetchList,
|
||||||
.map(
|
pageSize,
|
||||||
(filter) =>
|
loadFailed: labels.loadFailed,
|
||||||
`${filter.name}:${String(filter.defaultValue)}:${String(filter.allValue)}:${filter.trim ? "1" : "0"}:${filter.valueType ?? ""}`
|
})
|
||||||
)
|
const draftFilters = list.draftFilters
|
||||||
.join("|")
|
const setDraftFilter = list.setDraftFilter
|
||||||
const [page, setPage] = useState(1)
|
const loading = list.loading
|
||||||
const [limit, setLimit] = useState(pageSize)
|
const result = list.result
|
||||||
const [loading, setLoading] = useState(true)
|
const loadData = list.loadData
|
||||||
const [saving, setSaving] = useState(false)
|
const [saving, setSaving] = useState(false)
|
||||||
const [actionLoadingId, setActionLoadingId] = useState<number | null>(null)
|
const [actionLoadingId, setActionLoadingId] = useState<number | null>(null)
|
||||||
const [dialogOpen, setDialogOpen] = useState(false)
|
const [dialogOpen, setDialogOpen] = useState(false)
|
||||||
const [editingItem, setEditingItem] = useState<TItem | null>(null)
|
const [editingItem, setEditingItem] = useState<TItem | null>(null)
|
||||||
const [result, setResult] = useState<DashboardCrudPageResult<TItem>>({
|
|
||||||
results: [],
|
|
||||||
page: { page: 1, limit: pageSize, total: 0 },
|
|
||||||
})
|
|
||||||
|
|
||||||
const loadData = useCallback(async () => {
|
|
||||||
setLoading(true)
|
|
||||||
try {
|
|
||||||
const data = await fetchList(
|
|
||||||
buildDashboardCrudQuery({
|
|
||||||
values: appliedFilters,
|
|
||||||
filters,
|
|
||||||
page,
|
|
||||||
limit,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
setResult(normalizeDashboardCrudPageResult(data, page, limit))
|
|
||||||
} catch (error) {
|
|
||||||
toast.error(error instanceof Error ? error.message : labels.loadFailed)
|
|
||||||
} finally {
|
|
||||||
setLoading(false)
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [appliedFilters, fetchList, filtersKey, labels.loadFailed, limit, page])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
void loadData()
|
|
||||||
}, [loadData])
|
|
||||||
|
|
||||||
function handleApplyFilters() {
|
function handleApplyFilters() {
|
||||||
applyFilters()
|
list.applyFilters()
|
||||||
setPage(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFilterKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
|
function handleFilterKeyDown(event: React.KeyboardEvent<HTMLInputElement>) {
|
||||||
@@ -366,7 +335,7 @@ export function DashboardCrudPage<TItem, TPayload>({
|
|||||||
|
|
||||||
const previousResults = result.results
|
const previousResults = result.results
|
||||||
const nextResults = arrayMove(result.results, oldIndex, newIndex)
|
const nextResults = arrayMove(result.results, oldIndex, newIndex)
|
||||||
setResult((current) => ({ ...current, results: nextResults }))
|
list.setResult((current) => ({ ...current, results: nextResults }))
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sort.onReorder(nextResults)
|
await sort.onReorder(nextResults)
|
||||||
@@ -374,7 +343,7 @@ export function DashboardCrudPage<TItem, TPayload>({
|
|||||||
toast.success(sort.successMessage)
|
toast.success(sort.successMessage)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setResult((current) => ({ ...current, results: previousResults }))
|
list.setResult((current) => ({ ...current, results: previousResults }))
|
||||||
toast.error(error instanceof Error ? error.message : sort.errorMessage)
|
toast.error(error instanceof Error ? error.message : sort.errorMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -556,16 +525,10 @@ export function DashboardCrudPage<TItem, TPayload>({
|
|||||||
<ListPagination
|
<ListPagination
|
||||||
page={result.page.page}
|
page={result.page.page}
|
||||||
total={result.page.total}
|
total={result.page.total}
|
||||||
limit={limit}
|
limit={list.limit}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
onPageChange={(nextPage) => {
|
onPageChange={list.handlePageChange}
|
||||||
if (nextPage < 1 || nextPage === page) return
|
onLimitChange={list.handleLimitChange}
|
||||||
setPage(nextPage)
|
|
||||||
}}
|
|
||||||
onLimitChange={(nextLimit) => {
|
|
||||||
setLimit(nextLimit)
|
|
||||||
setPage(1)
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import {
|
|||||||
type DashboardCrudFilterStateConfig,
|
type DashboardCrudFilterStateConfig,
|
||||||
type DashboardCrudQueryFilter,
|
type DashboardCrudQueryFilter,
|
||||||
type DashboardCrudQueryValue,
|
type DashboardCrudQueryValue,
|
||||||
} from "@/components/dashboard/crud"
|
} from "@/components/dashboard/crud/dashboard-crud-utils"
|
||||||
import { useDashboardCrudFilters } from "@/components/dashboard/crud"
|
import { useDashboardCrudFilters } from "@/components/dashboard/crud/use-dashboard-crud-filters"
|
||||||
|
|
||||||
export type DashboardPagedListFilter = DashboardCrudQueryFilter &
|
export type DashboardPagedListFilter = DashboardCrudQueryFilter &
|
||||||
DashboardCrudFilterStateConfig
|
DashboardCrudFilterStateConfig
|
||||||
|
|||||||
Reference in New Issue
Block a user