diff --git a/app/(dashboard)/page.tsx b/app/(dashboard)/page.tsx index 07e3b487f..1c45df7c0 100644 --- a/app/(dashboard)/page.tsx +++ b/app/(dashboard)/page.tsx @@ -1,130 +1,23 @@ -import { Button } from '@/components/ui/button'; -import { ArrowRight, CreditCard, Database } from 'lucide-react'; -import { Terminal } from './terminal'; +import { ContactForm } from '@/components/contact-form'; export default function HomePage() { return ( -
-
-
-
-
-

- Build Your SaaS - Faster Than Ever -

-

- Launch your SaaS product in record time with our powerful, - ready-to-use template. Packed with modern technologies and - essential integrations. -

- -
-
- -
-
+
+
+
+

Welcome to Next.js

+
+ + {/* Contact Form Section */} + +
+ + {/* Footer will go here */} +
+
+

© 2024 Your Company. All rights reserved.

-
- -
-
-
-
-
- - - -
-
-

- Next.js and React -

-

- Leverage the power of modern web technologies for optimal - performance and developer experience. -

-
-
- -
-
- -
-
-

- Postgres and Drizzle ORM -

-

- Robust database solution with an intuitive ORM for efficient - data management and scalability. -

-
-
- -
-
- -
-
-

- Stripe Integration -

-

- Seamless payment processing and subscription management with - industry-leading Stripe integration. -

-
-
-
-
-
- -
-
-
-
-

- Ready to launch your SaaS? -

-

- Our template provides everything you need to get your SaaS up - and running quickly. Don't waste time on boilerplate - focus on - what makes your product unique. -

-
-
- - - -
-
-
-
+
); -} +} \ No newline at end of file diff --git a/app/actions/contact.ts b/app/actions/contact.ts new file mode 100644 index 000000000..57c4ba38c --- /dev/null +++ b/app/actions/contact.ts @@ -0,0 +1,60 @@ +'use server'; + +import { z } from 'zod'; + +// Define the schema for contact form validation +const contactFormSchema = z.object({ + name: z.string().min(2).max(100), + email: z.string().email(), + message: z.string().min(10).max(1000), +}); + +export type ContactFormData = z.infer; + +export async function submitContactForm(data: ContactFormData) { + try { + // Validate the data + const validatedData = contactFormSchema.parse(data); + + // Here you would typically: + // 1. Save to database + // 2. Send email notification + // 3. Integrate with CRM or support system + + // For now, we'll simulate a successful submission + console.log('Contact form submission:', validatedData); + + // Simulate API delay + await new Promise(resolve => setTimeout(resolve, 1000)); + + // In production, you might want to: + // - Send an email using a service like SendGrid, Resend, or AWS SES + // - Store in your database using Drizzle ORM + // - Send to a CRM like HubSpot or Salesforce + // - Create a ticket in a support system + + // Example database save (uncomment when ready): + // await db.insert(contactSubmissions).values({ + // name: validatedData.name, + // email: validatedData.email, + // message: validatedData.message, + // createdAt: new Date(), + // }); + + return { success: true }; + } catch (error) { + console.error('Contact form error:', error); + + if (error instanceof z.ZodError) { + return { + success: false, + error: 'Invalid form data. Please check your inputs.' + }; + } + + return { + success: false, + error: 'Failed to submit form. Please try again later.' + }; + } +} \ No newline at end of file diff --git a/components/contact-form.tsx b/components/contact-form.tsx new file mode 100644 index 000000000..83c77285e --- /dev/null +++ b/components/contact-form.tsx @@ -0,0 +1,263 @@ +'use client'; + +import { useState } from 'react'; +import { useFormStatus } from 'react-dom'; +import { z } from 'zod'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Card } from '@/components/ui/card'; +import { submitContactForm } from '@/app/actions/contact'; +import { Mail, User, MessageSquare, Send, CheckCircle, AlertCircle } from 'lucide-react'; + +const contactSchema = z.object({ + name: z.string().min(2, 'Name must be at least 2 characters'), + email: z.string().email('Please enter a valid email address'), + message: z.string().min(10, 'Message must be at least 10 characters'), +}); + +type FormData = z.infer; +type FormErrors = Partial>; + +function SubmitButton() { + const { pending } = useFormStatus(); + + return ( + + ); +} + +export function ContactForm() { + const [errors, setErrors] = useState({}); + const [status, setStatus] = useState<'idle' | 'success' | 'error'>('idle'); + const [statusMessage, setStatusMessage] = useState(''); + + async function handleSubmit(formData: FormData) { + // Reset states + setErrors({}); + setStatus('idle'); + setStatusMessage(''); + + // Validate form data + try { + const validatedData = contactSchema.parse({ + name: formData.get('name'), + email: formData.get('email'), + message: formData.get('message'), + }); + + // Submit form + const result = await submitContactForm(validatedData); + + if (result.success) { + setStatus('success'); + setStatusMessage('Thank you for your message! We\'ll get back to you soon.'); + // Reset form + const form = document.getElementById('contact-form') as HTMLFormElement; + form?.reset(); + } else { + setStatus('error'); + setStatusMessage(result.error || 'Something went wrong. Please try again.'); + } + } catch (error) { + if (error instanceof z.ZodError) { + const fieldErrors: FormErrors = {}; + error.errors.forEach((err) => { + if (err.path[0]) { + fieldErrors[err.path[0] as keyof FormData] = err.message; + } + }); + setErrors(fieldErrors); + } else { + setStatus('error'); + setStatusMessage('An unexpected error occurred. Please try again.'); + } + } + } + + return ( +
+
+
+

+ Get in Touch +

+

+ Have a question or want to work together? We'd love to hear from you. +

+
+ +
+ {/* Contact Information */} +
+ +

+ Let's Start a Conversation +

+
+
+
+
+ +
+
+
+

+ Email Us +

+

+ Send us an email and we'll respond within 24 hours +

+
+
+ +
+
+
+ +
+
+
+

+ Live Chat +

+

+ Our team is online Mon-Fri 9am-5pm EST +

+
+
+
+
+ + {/* FAQ or Additional Info */} +
+

+ Frequently Asked Questions +

+
    +
  • + + How quickly will I receive a response? +
  • +
  • + + What information should I include? +
  • +
  • + + Can I schedule a call instead? +
  • +
+
+
+ + {/* Contact Form */} + +
+
+ + + {errors.name && ( +

+ + {errors.name} +

+ )} +
+ +
+ + + {errors.email && ( +

+ + {errors.email} +

+ )} +
+ +
+ +