@@ -131,7 +131,7 @@ export function CrudDialog<TClient extends CrudDialogClient>({
|
||||
Add {title}
|
||||
</Button>
|
||||
</div>
|
||||
<DataTable
|
||||
<DataTable
|
||||
columns={allColumns}
|
||||
data={crud.items}
|
||||
pagination={crud.pagination}
|
||||
|
||||
@@ -21,6 +21,42 @@ export type UseCrudDialogOptions<TClient extends CrudDialogClient> = {
|
||||
resourceLabel?: string
|
||||
}
|
||||
|
||||
type CrudListShape = {
|
||||
data?: unknown
|
||||
meta?: {
|
||||
last_page?: number
|
||||
total?: number
|
||||
}
|
||||
pagination?: {
|
||||
last_page?: number
|
||||
total?: number
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeCrudListResponse(response: unknown): {
|
||||
items: any[]
|
||||
meta?: { last_page?: number; total?: number }
|
||||
} {
|
||||
const root = (response ?? {}) as CrudListShape
|
||||
const directData = root.data
|
||||
|
||||
if (Array.isArray(directData)) {
|
||||
return { items: directData, meta: root.meta ?? root.pagination }
|
||||
}
|
||||
|
||||
if (directData && typeof directData === "object") {
|
||||
const nested = directData as CrudListShape
|
||||
if (Array.isArray(nested.data)) {
|
||||
return {
|
||||
items: nested.data,
|
||||
meta: nested.meta ?? nested.pagination ?? root.meta ?? root.pagination,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { items: [], meta: root.meta ?? root.pagination }
|
||||
}
|
||||
|
||||
// ── Hook ──
|
||||
|
||||
export function useCrudDialog<TClient extends CrudDialogClient>({
|
||||
@@ -46,17 +82,23 @@ export function useCrudDialog<TClient extends CrudDialogClient>({
|
||||
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: fullQueryKey,
|
||||
queryFn: () => {
|
||||
queryFn: async () => {
|
||||
const params: Record<string, unknown> = { page, per_page: pageSize }
|
||||
if (sortBy) params.sort_by = sortBy
|
||||
if (sortOrder) params.sort_order = sortOrder
|
||||
return client.list(params)
|
||||
|
||||
try {
|
||||
return await client.list(params)
|
||||
} catch {
|
||||
// Some endpoints ignore/reject pagination params; retry without params.
|
||||
return client.list()
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const responseData = (data as any)?.data ?? []
|
||||
const items = Array.isArray(responseData) ? responseData : []
|
||||
const meta = (data as any)?.meta
|
||||
const normalized = normalizeCrudListResponse(data)
|
||||
const items = normalized.items
|
||||
const meta = normalized.meta
|
||||
|
||||
const pagination: DataViewPaginationState = {
|
||||
page,
|
||||
|
||||
@@ -5,6 +5,7 @@ export type TextInputFieldProps = BaseFieldControlProps<string> & {
|
||||
placeholder?: string
|
||||
type?: React.HTMLInputTypeAttribute
|
||||
step?: React.InputHTMLAttributes<HTMLInputElement>["step"]
|
||||
formatter?: (value: string) => string
|
||||
}
|
||||
|
||||
export function TextInputField({
|
||||
@@ -17,11 +18,12 @@ export function TextInputField({
|
||||
placeholder,
|
||||
type = "text",
|
||||
step,
|
||||
formatter,
|
||||
}: TextInputFieldProps) {
|
||||
return (
|
||||
<Input
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
onChange={(e) => onChange(formatter ? formatter(e.target.value) : e.target.value)}
|
||||
onBlur={onBlur}
|
||||
name={name}
|
||||
disabled={disabled}
|
||||
|
||||
@@ -38,7 +38,7 @@ export function TimePickerField({
|
||||
disabled,
|
||||
invalid,
|
||||
placeholder = "Pick a time",
|
||||
withSeconds = true,
|
||||
withSeconds = false,
|
||||
}: TimePickerFieldProps) {
|
||||
const { hours, minutes, seconds } = parseTime(value ?? "")
|
||||
const hasValue = !!value
|
||||
|
||||
@@ -20,5 +20,5 @@ export function RhfTimeField<
|
||||
TValues extends FieldValues,
|
||||
TName extends FieldPath<TValues>,
|
||||
>(props: RhfTimeFieldProps<TValues, TName>) {
|
||||
return <RhfField {...props} component={TimePickerField} />
|
||||
return <RhfField {...props} component={TimePickerField} />
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user