feat: integrate dialog close context in vendor select field and CRUD dialog components feat: enhance vendor general info to format status using utility function feat: implement form dialog context for managing dialog close actions feat: add async select field dialog close context for better form handling fix: update form mutation hook to close dialog on successful submission feat: extend document print types to include expense and credit note feat: add settings update payload type to include logo and other fields feat: create employee attendance and work history pages with resource management feat: implement payment made and received detail pages with actions feat: add quick shortcuts component for easy navigation in the dashboard feat: create actions for payment made and received with print and delete options feat: implement dialog close context for better dialog management feat: add error parsing utility for improved error handling in API responses
100 lines
3.4 KiB
TypeScript
100 lines
3.4 KiB
TypeScript
import React from 'react'
|
|
import { useQueryStates, parseAsBoolean, parseAsString } from 'nuqs'
|
|
import { Button } from '@/shared/components/ui/button'
|
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/shared/components/ui/dialog'
|
|
import { ScrollArea } from '@/shared/components/ui/scroll-area'
|
|
import { Plus } from 'lucide-react'
|
|
import { cn } from '../lib/utils'
|
|
import { DialogCloseContext } from '@/shared/hooks/use-dialog-close'
|
|
|
|
export const formDialogParams = {
|
|
dialog: parseAsBoolean.withDefault(false),
|
|
resourceId: parseAsString,
|
|
}
|
|
|
|
export function useFormDialog(paramKey?: string) {
|
|
// Default (no paramKey) uses the standard `dialog` and `resourceId` params
|
|
const defaultState = useQueryStates(formDialogParams)
|
|
|
|
// When a paramKey is provided, use prefixed params to avoid URL collisions
|
|
const prefixedState = useQueryStates({
|
|
[`${paramKey ?? "_"}_dialog`]: parseAsBoolean.withDefault(false),
|
|
[`${paramKey ?? "_"}_resourceId`]: parseAsString,
|
|
})
|
|
|
|
if (paramKey) {
|
|
const [params, setParams] = prefixedState
|
|
const dialogKey = `${paramKey}_dialog`
|
|
const resourceIdKey = `${paramKey}_resourceId`
|
|
|
|
const open = (resourceId?: string) => {
|
|
setParams({ [dialogKey]: true, [resourceIdKey]: resourceId ?? null })
|
|
}
|
|
const close = () => {
|
|
setParams({ [dialogKey]: false, [resourceIdKey]: null })
|
|
}
|
|
|
|
return {
|
|
isOpen: (params as Record<string, unknown>)[dialogKey] as boolean,
|
|
resourceId: (params as Record<string, unknown>)[resourceIdKey] as string | null,
|
|
open,
|
|
close,
|
|
}
|
|
}
|
|
|
|
const [params, setParams] = defaultState
|
|
|
|
const open = (resourceId?: string) => {
|
|
setParams({ dialog: true, resourceId: resourceId ?? null })
|
|
}
|
|
const close = () => {
|
|
setParams({ dialog: false, resourceId: null })
|
|
}
|
|
|
|
return {
|
|
isOpen: params.dialog,
|
|
resourceId: params.resourceId,
|
|
open,
|
|
close,
|
|
}
|
|
}
|
|
|
|
export default function FormDialog(props: {
|
|
children: (resourceId: string | null,
|
|
ctx: { open: (resourceId?: string) => void, close: () => void,isOpen:boolean }
|
|
) => React.ReactNode
|
|
title: string
|
|
paramKey?: string
|
|
classNames?: {
|
|
trigger?: string
|
|
dialogContent?: string
|
|
scrollArea?: string
|
|
}
|
|
|
|
}) {
|
|
const { isOpen, resourceId, open, close } = useFormDialog(props.paramKey)
|
|
|
|
return (
|
|
<>
|
|
<Button size='sm' className={cn(props.classNames?.trigger)} onClick={() => open()}>
|
|
<Plus />
|
|
{props.title}
|
|
</Button>
|
|
<Dialog open={isOpen} onOpenChange={(v) => { if (!v) close() }}>
|
|
<DialogContent className={`min-w-xl ${cn(props.classNames?.dialogContent)}`}>
|
|
<DialogHeader>
|
|
<DialogTitle className='text-2xl font-bold'>
|
|
{props.title}
|
|
</DialogTitle>
|
|
</DialogHeader>
|
|
<ScrollArea className={`max-h-[80vh] px-4 ${cn(props.classNames?.scrollArea)}`}>
|
|
<DialogCloseContext.Provider value={close}>
|
|
{props.children(resourceId, { open, close, isOpen })}
|
|
</DialogCloseContext.Provider>
|
|
</ScrollArea>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</>
|
|
)
|
|
}
|