feat: add logo field to settings schema and update settings client to handle file uploads

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
This commit is contained in:
2026-05-19 17:56:39 +04:00
parent 2d6e3c5734
commit 4f0a2f790f
56 changed files with 1220 additions and 92 deletions
@@ -0,0 +1,12 @@
"use client"
import { createContext, useContext } from "react"
// Closes the nearest dialog/sheet wrapper. `null` means the form is not
// inside a dialog that should auto-close (or a parent has explicitly
// shadowed the context, e.g. CrudDialog).
export const DialogCloseContext = createContext<(() => void) | null>(null)
export function useDialogClose(): (() => void) | null {
return useContext(DialogCloseContext)
}
@@ -3,14 +3,25 @@
import { useMutation, type UseMutationOptions } from "@tanstack/react-query"
import type { FieldValues, UseFormReturn } from "react-hook-form"
import { ApiError } from "@garage/api"
import { useDialogClose } from "./use-dialog-close"
export function useFormMutation<TValues extends FieldValues, TResponse = unknown>(
form: UseFormReturn<TValues>,
options: UseMutationOptions<TResponse, Error, TValues>,
) {
const closeDialog = useDialogClose()
return useMutation<TResponse, Error, TValues>({
...options,
onError: (err, vars,values, ctx) => {
onSuccess: async (data, vars, onMutateResult, ctx) => {
await options.onSuccess?.(data, vars, onMutateResult, ctx)
// If this form is rendered inside a dialog wrapper that registers
// a close handler (e.g. FormDialog), dismiss the dialog after a
// successful submit. Plain pages render the form without the
// provider, so this is a no-op there.
closeDialog?.()
},
onError: (err, vars, values, ctx) => {
if (err instanceof ApiError && err.validationErrors) {
Object.entries(err.validationErrors).forEach(([field, msgs]) => {
form.setError(field as any, { message: msgs[0] })