feat: implement contact form and Chatwoot widget
Add Resend API-based contact form and Chatwoot widget integration. Co-authored-by: ASOwnerYT <[email protected]>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
|
||||
export function ChatwootWidget() {
|
||||
useEffect(() => {
|
||||
const chatwootToken = process.env.NEXT_PUBLIC_CHATWOOT_ACCOUNT_TOKEN
|
||||
|
||||
if (!chatwootToken) {
|
||||
console.warn('[v0] Chatwoot account token not configured')
|
||||
return
|
||||
}
|
||||
|
||||
// Load Chatwoot widget script
|
||||
const script = document.createElement('script')
|
||||
script.src = 'https://app.chatwoot.com/packs/js/sdk.js'
|
||||
script.async = true
|
||||
|
||||
script.onload = () => {
|
||||
// Initialize Chatwoot after script loads
|
||||
if ((window as any).chatwootSDK) {
|
||||
;(window as any).chatwootSDK.run({
|
||||
websiteToken: chatwootToken,
|
||||
baseUrl: 'https://app.chatwoot.com'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
script.onerror = () => {
|
||||
console.error('[v0] Failed to load Chatwoot widget')
|
||||
}
|
||||
|
||||
document.body.appendChild(script)
|
||||
|
||||
return () => {
|
||||
// Cleanup is handled by Chatwoot itself
|
||||
// Don't remove the script as it manages its own lifecycle
|
||||
}
|
||||
}, [])
|
||||
|
||||
return null
|
||||
}
|
||||
+38
-11
@@ -3,7 +3,7 @@
|
||||
import { useState } from "react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Mail, Phone, MapPin, Send, ArrowRight } from "lucide-react"
|
||||
import { Mail, Phone, MapPin, Send, ArrowRight, AlertCircle } from "lucide-react"
|
||||
|
||||
export function Contact() {
|
||||
const [formData, setFormData] = useState({
|
||||
@@ -13,20 +13,39 @@ export function Contact() {
|
||||
})
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const [isSubmitted, setIsSubmitted] = useState(false)
|
||||
const [error, setError] = useState("")
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
setIsSubmitting(true)
|
||||
setError("")
|
||||
|
||||
// Simulate form submission
|
||||
await new Promise(resolve => setTimeout(resolve, 1500))
|
||||
|
||||
setIsSubmitting(false)
|
||||
setIsSubmitted(true)
|
||||
setFormData({ name: "", email: "", message: "" })
|
||||
|
||||
// Reset success message after 5 seconds
|
||||
setTimeout(() => setIsSubmitted(false), 5000)
|
||||
try {
|
||||
const response = await fetch('/api/send-email', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json()
|
||||
throw new Error(errorData.error || 'Failed to send message')
|
||||
}
|
||||
|
||||
setIsSubmitted(true)
|
||||
setFormData({ name: "", email: "", message: "" })
|
||||
|
||||
// Reset success message after 5 seconds
|
||||
setTimeout(() => setIsSubmitted(false), 5000)
|
||||
} catch (err) {
|
||||
const errorMessage = err instanceof Error ? err.message : 'An unexpected error occurred'
|
||||
setError(errorMessage)
|
||||
console.error('[v0] Form submission error:', err)
|
||||
} finally {
|
||||
setIsSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
const contactInfo = [
|
||||
@@ -129,7 +148,14 @@ export function Contact() {
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<>
|
||||
{error && (
|
||||
<div className="mb-6 p-4 bg-destructive/10 border border-destructive/50 rounded-lg flex items-center gap-3">
|
||||
<AlertCircle className="w-5 h-5 text-destructive flex-shrink-0" />
|
||||
<p className="text-sm text-destructive">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div className="space-y-2">
|
||||
<label htmlFor="name" className="text-sm font-medium">
|
||||
Your Name
|
||||
@@ -193,6 +219,7 @@ export function Contact() {
|
||||
)}
|
||||
</Button>
|
||||
</form>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user