2026-04-15 04:59:05 +03:00

115 lines
4.0 KiB
TypeScript

"use client"
import { useState, useRef } from "react"
import { Button } from "@/shared/components/ui/button"
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogFooter,
} from "@/shared/components/ui/dialog"
import { CrudResource, type CrudResourceProps } from "@/shared/data-view/resource-page"
import type { ResourcePageClient, ResourceItem } from "@/shared/data-view/resource-page"
import { Card, CardContent } from "@/shared/components/ui/card"
export type ResourceSelectorDialogProps<TClient extends ResourcePageClient> = {
/** Dialog title shown in the header */
title: string
/** Opens/closes the dialog */
open: boolean
onOpenChange: (open: boolean) => void
/** Called when user confirms selection */
onConfirm: (selectedRows: ResourceItem<TClient>[]) => void
/** CrudResource config for the table (columns, routeKey, getClient, etc.) */
crudProps: Omit<CrudResourceProps<TClient>, "render" | "tableProps">
/** Optional rowKey for selection identity. Defaults to "id" */
rowKey?: keyof ResourceItem<TClient>
/**
* Selection mode.
* - "multi" (default): checkbox multi-select + Confirm button
* - "single": row click immediately fires onConfirm with the clicked row
*/
selectionMode?: "single" | "multi"
}
export function ResourceSelectorDialog<TClient extends ResourcePageClient>({
title,
open,
onOpenChange,
onConfirm,
crudProps,
rowKey,
selectionMode = "multi",
}: ResourceSelectorDialogProps<TClient>) {
type TItem = ResourceItem<TClient>
const selectedRef = useRef<TItem[]>([])
const [count, setCount] = useState(0)
const handleSelectionChange = (rows: TItem[]) => {
selectedRef.current = rows
setCount(rows.length)
}
const handleConfirm = () => {
onConfirm(selectedRef.current)
selectedRef.current = []
setCount(0)
onOpenChange(false)
}
const handleCancel = () => {
selectedRef.current = []
setCount(0)
onOpenChange(false)
}
const handleRowClick = (row: TItem) => {
onConfirm([row])
onOpenChange(false)
}
return (
<Dialog open={open} onOpenChange={(v) => { if (!v) handleCancel() }}>
<DialogContent className="min-w-4xl max-h-[90vh] flex flex-col">
<DialogHeader>
<DialogTitle className="text-2xl font-bold">{title}</DialogTitle>
</DialogHeader>
<div className="flex-1 overflow-auto">
<Card className="rounded-none border-0 shadow-none">
<CardContent className="p-0">
{selectionMode === "single" ? (
<CrudResource<TClient>
{...crudProps}
onRowClick={handleRowClick}
/>
) : (
<CrudResource<TClient>
{...crudProps}
tableProps={{
selection: {
onSelectionChange: handleSelectionChange,
...(rowKey ? { rowKey } : {}),
},
}}
/>
)}
</CardContent>
</Card>
</div>
{selectionMode === "multi" && (
<DialogFooter>
<Button variant="outline" onClick={handleCancel}>
Cancel
</Button>
<Button onClick={handleConfirm} disabled={count === 0}>
Confirm{count > 0 ? ` (${count})` : ""}
</Button>
</DialogFooter>
)}
</DialogContent>
</Dialog>
)
}