fix: restore complete admin feature dependencies

This commit is contained in:
Simo committed 2026-07-11 21:15:54 +02:00
1 parent 5b4228261a
commit 0cd753c735
115 files changed
+18565 -4930

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
'use client'
import { useEffect, useState } from 'react'
export function useDebounce<T>(value: T, delay: number = 300): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay)
return () => clearTimeout(timer)
}, [value, delay])
return debouncedValue
}
+71
View File
@@ -0,0 +1,71 @@
'use client'
import { useRouter } from 'next/navigation'
import { useTransition } from 'react'
import { toast } from 'sonner'
import type { ActionResult } from '@/lib/safe-action-shared'
interface UseServerActionOptions {
/** Where to redirect after a successful action (optional) */
redirectOnSuccess?: string
}
interface RunOptions {
successMessage?: string
errorMessage?: string
/** Override redirect path for this specific call */
redirectTo?: string
/** Called on success with the result data. Overrides default router.refresh(). */
onSuccess?: (data: Record<string, unknown>) => void
}
/**
* Hook that wraps a server action with loading state, toast notifications,
* and optional redirect/refresh. Drop-in replacement for useAdminForm.
*
* @example
* const { run, isPending } = useServerAction()
*
* // Submit
* run(() => updateNews({ id, ...data }), { successMessage: 'Saved!' })
*
* // Delete with redirect
* run(() => deleteNews(id), { redirectTo: '/admin/news' })
*/
export function useServerAction(options: UseServerActionOptions = {}) {
const [isPending, startTransition] = useTransition()
const router = useRouter()
function run(action: () => Promise<ActionResult | void>, opts: RunOptions = {}) {
const {
successMessage = 'Saved successfully.',
errorMessage = 'An error occurred.',
redirectTo,
onSuccess,
} = opts
startTransition(async () => {
try {
const result = await action()
if (!result || result.ok) {
toast.success(successMessage)
if (onSuccess) {
onSuccess((result?.data ?? {}) as Record<string, unknown>)
} else {
const target = redirectTo || options.redirectOnSuccess
if (target) router.push(target)
else router.refresh()
}
} else {
toast.error(result.error || errorMessage)
}
} catch (err) {
console.error('[useServerAction] Unexpected error:', err)
toast.error(errorMessage)
}
})
}
return { run, isPending }
}