This commit is contained in:
1 parent
e85e4d74ea
commit
2e4ed76121
378 files changed
+22404
-20686
No files matched your search
@@ -1,14 +1,14 @@
|
||||
'use client'
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export function useDebounce<T>(value: T, delay: number = 300): T {
|
||||
const [debouncedValue, setDebouncedValue] = useState<T>(value)
|
||||
const [debouncedValue, setDebouncedValue] = useState<T>(value);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setDebouncedValue(value), delay)
|
||||
return () => clearTimeout(timer)
|
||||
}, [value, delay])
|
||||
const timer = setTimeout(() => setDebouncedValue(value), delay);
|
||||
return () => clearTimeout(timer);
|
||||
}, [value, delay]);
|
||||
|
||||
return debouncedValue
|
||||
return debouncedValue;
|
||||
}
|
||||
@@ -1,22 +1,22 @@
|
||||
'use client'
|
||||
"use client";
|
||||
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useTransition } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import type { ActionResult } from '@/lib/safe-action-shared'
|
||||
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
|
||||
redirectOnSuccess?: string;
|
||||
}
|
||||
|
||||
interface RunOptions {
|
||||
successMessage?: string
|
||||
errorMessage?: string
|
||||
successMessage?: string;
|
||||
errorMessage?: string;
|
||||
/** Override redirect path for this specific call */
|
||||
redirectTo?: string
|
||||
redirectTo?: string;
|
||||
/** Called on success with the result data. Overrides default router.refresh(). */
|
||||
onSuccess?: (data: Record<string, unknown>) => void
|
||||
onSuccess?: (data: Record<string, unknown>) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,39 +33,39 @@ interface RunOptions {
|
||||
* run(() => deleteNews(id), { redirectTo: '/admin/news' })
|
||||
*/
|
||||
export function useServerAction(options: UseServerActionOptions = {}) {
|
||||
const [isPending, startTransition] = useTransition()
|
||||
const router = useRouter()
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const router = useRouter();
|
||||
|
||||
function run(action: () => Promise<ActionResult | void>, opts: RunOptions = {}) {
|
||||
const {
|
||||
successMessage = 'Saved successfully.',
|
||||
errorMessage = 'An error occurred.',
|
||||
successMessage = "Saved successfully.",
|
||||
errorMessage = "An error occurred.",
|
||||
redirectTo,
|
||||
onSuccess,
|
||||
} = opts
|
||||
} = opts;
|
||||
|
||||
startTransition(async () => {
|
||||
try {
|
||||
const result = await action()
|
||||
const result = await action();
|
||||
|
||||
if (!result || result.ok) {
|
||||
toast.success(successMessage)
|
||||
toast.success(successMessage);
|
||||
if (onSuccess) {
|
||||
onSuccess((result?.data ?? {}) as Record<string, unknown>)
|
||||
onSuccess((result?.data ?? {}) as Record<string, unknown>);
|
||||
} else {
|
||||
const target = redirectTo || options.redirectOnSuccess
|
||||
if (target) router.push(target)
|
||||
else router.refresh()
|
||||
const target = redirectTo || options.redirectOnSuccess;
|
||||
if (target) router.push(target);
|
||||
else router.refresh();
|
||||
}
|
||||
} else {
|
||||
toast.error(result.error || errorMessage)
|
||||
toast.error(result.error || errorMessage);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[useServerAction] Unexpected error:', err)
|
||||
toast.error(errorMessage)
|
||||
console.error("[useServerAction] Unexpected error:", err);
|
||||
toast.error(errorMessage);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return { run, isPending }
|
||||
return { run, isPending };
|
||||
}
|
||||
Reference in new issue
Block a user