From 410d96a8b859bc37d85bcdb1f6d06150f914153e Mon Sep 17 00:00:00 2001 From: Markus Thielker Date: Sun, 17 Mar 2024 17:19:05 +0100 Subject: [PATCH] N-FIN-47: introduce reusable server action trigger component --- src/components/form/serverActionTrigger.tsx | 53 +++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 src/components/form/serverActionTrigger.tsx diff --git a/src/components/form/serverActionTrigger.tsx b/src/components/form/serverActionTrigger.tsx new file mode 100644 index 0000000..ce5b431 --- /dev/null +++ b/src/components/form/serverActionTrigger.tsx @@ -0,0 +1,53 @@ +'use client'; + +import { buttonVariants } from '@/components/ui/button'; +import React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { cn } from '@/lib/utils'; +import { useRouter } from 'next/navigation'; +import { toast } from 'sonner'; +import { sonnerContent } from '@/components/ui/sonner'; +import type { VariantProps } from 'class-variance-authority'; +import { ActionResponse } from '@/lib/types/actionResponse'; + +export interface ButtonWithActionProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; + action: () => Promise>; + callback?: (data: T) => void; +} + +const ServerActionTrigger = React.forwardRef( + ({className, variant, size, asChild = false, ...props}, ref) => { + + const router = useRouter(); + + const Comp = asChild ? Slot : 'button'; + + const handleSubmit = async () => { + const response = await props.action(); + toast(sonnerContent(response)); + if (props.callback) { + props.callback(response); + } + if (response.redirect) { + router.push(response.redirect); + } + }; + + // TODO: add optional confirmation dialog + + return ( + + ); + }, +); +ServerActionTrigger.displayName = 'ServerActionTrigger'; + +export { ServerActionTrigger };