diff --git a/packages/ui/src/makerkit/marketing/index.tsx b/packages/ui/src/makerkit/marketing/index.tsx index 7a648f031..476d4abcb 100644 --- a/packages/ui/src/makerkit/marketing/index.tsx +++ b/packages/ui/src/makerkit/marketing/index.tsx @@ -10,3 +10,5 @@ export * from './footer'; export * from './feature-showcase'; export * from './feature-grid'; export * from './feature-card'; +export * from './newsletter-signup'; +export * from './newsletter-signup-container'; \ No newline at end of file diff --git a/packages/ui/src/makerkit/marketing/newsletter-signup-container.tsx b/packages/ui/src/makerkit/marketing/newsletter-signup-container.tsx new file mode 100644 index 000000000..5bb565c4a --- /dev/null +++ b/packages/ui/src/makerkit/marketing/newsletter-signup-container.tsx @@ -0,0 +1,86 @@ +'use client'; + +import { useCallback, useState } from 'react'; + +import { Alert, AlertDescription, AlertTitle } from '../../shadcn/alert'; +import { Heading } from '../../shadcn/heading'; +import { cn } from '../../utils'; +import { Spinner } from '../spinner'; +import { NewsletterSignup } from './newsletter-signup'; + +interface NewsletterSignupContainerProps + extends React.HTMLAttributes { + onSignup: (email: string) => Promise; + heading?: string; + description?: string; + successMessage?: string; + errorMessage?: string; +} + +export function NewsletterSignupContainer({ + onSignup, + heading = 'Subscribe to our newsletter', + description = 'Get the latest updates and offers directly to your inbox.', + successMessage = 'Thank you for subscribing!', + errorMessage = 'An error occurred. Please try again.', + className, + ...props +}: NewsletterSignupContainerProps) { + const [status, setStatus] = useState< + 'idle' | 'loading' | 'success' | 'error' + >('idle'); + + const handleSubmit = useCallback( + async (data: { email: string }) => { + setStatus('loading'); + + try { + await onSignup(data.email); + + setStatus('success'); + } catch (error) { + console.error('Newsletter signup error:', error); + setStatus('error'); + } + }, + [onSignup], + ); + + return ( +
+
+ {heading} +

{description}

+
+ + {status === 'idle' && } + + {status === 'loading' && ( +
+ +
+ )} + + {status === 'success' && ( +
+ + Success! + {successMessage} + +
+ )} + + {status === 'error' && ( +
+ + Error + {errorMessage} + +
+ )} +
+ ); +} diff --git a/packages/ui/src/makerkit/marketing/newsletter-signup.tsx b/packages/ui/src/makerkit/marketing/newsletter-signup.tsx new file mode 100644 index 000000000..9791eb8a1 --- /dev/null +++ b/packages/ui/src/makerkit/marketing/newsletter-signup.tsx @@ -0,0 +1,71 @@ +'use client'; + +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; + +import { Button } from '../../shadcn/button'; +import { + Form, + FormControl, + FormField, + FormItem, + FormMessage, +} from '../../shadcn/form'; +import { Input } from '../../shadcn/input'; +import { cn } from '../../utils'; + +const NewsletterFormSchema = z.object({ + email: z.string().email('Please enter a valid email address'), +}); + +type NewsletterFormValues = z.infer; + +interface NewsletterSignupProps extends React.HTMLAttributes { + onSignup: (data: NewsletterFormValues) => void; + buttonText?: string; + placeholder?: string; +} + +export function NewsletterSignup({ + onSignup, + buttonText = 'Subscribe', + placeholder = 'Enter your email', + className, + ...props +}: NewsletterSignupProps) { + const form = useForm({ + resolver: zodResolver(NewsletterFormSchema), + defaultValues: { + email: '', + }, + }); + + return ( +
+
+ + ( + + + + + + + )} + /> + + + + +
+ ); +}