-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Open
Description
import React, { useState } from "react";
// Simple one‑page local lead‑gen site
// Brand: Federal Way Mobile Pet Grooming
// Notes:
// - Replace WEBHOOK_URL with your form endpoint (Zapier, Make, Airtable, Google Apps Script)
// - Replace PHONE_NUMBER with your tracking number (CallRail/Twilio)
// - Replace FEATURED_GROOMER_* with your partner’s details/images
export default function App() {
const [status, setStatus] = useState("idle");
const [form, setForm] = useState({
name: "",
phone: "",
email: "",
petType: "Dog",
zip: "",
message: "",
});
async function submitLead(e) {
e.preventDefault();
setStatus("loading");
try {
// 🔁 Replace with your webhook (Zapier Catch Hook, Make Webhook, etc.)
const WEBHOOK_URL = "https://example.com/webhook"; // TODO: set real endpoint
const payload = {
source: "federalway-pet-grooming",
timestamp: new Date().toISOString(),
...form,
};
// Demo: don’t actually POST if placeholder URL
if (WEBHOOK_URL.includes("example.com")) {
await new Promise((r) => setTimeout(r, 800));
setStatus("success");
setForm({ name: "", phone: "", email: "", petType: "Dog", zip: "", message: "" });
return;
}
const res = await fetch(WEBHOOK_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error("Network error");
setStatus("success");
setForm({ name: "", phone: "", email: "", petType: "Dog", zip: "", message: "" });
} catch (err) {
console.error(err);
setStatus("error");
}
}
return (
{/* Header */}
{/* Hero */}
<section className="bg-gradient-to-br from-emerald-50 to-white border-b">
<div className="max-w-6xl mx-auto px-4 py-14 grid md:grid-cols-2 gap-10 items-center">
<div>
<h2 className="text-3xl sm:text-4xl font-extrabold leading-tight">
Grooming that comes to you—stress‑free for pets, easy for you.
</h2>
<p className="mt-3 text-gray-600">
Book a trusted mobile groomer in Federal Way, Kent, Auburn, and nearby. One simple form → we connect you fast.
</p>
<div className="mt-6 flex flex-wrap gap-3">
<a href="#quote" className="inline-flex items-center px-5 py-3 rounded-xl bg-emerald-600 text-white hover:bg-emerald-700 shadow">
Get a free quote
</a>
<a href="tel:+1PHONE_NUMBER" className="inline-flex items-center px-5 py-3 rounded-xl ring-1 ring-gray-300 hover:bg-gray-50">
Call now
</a>
</div>
<ul className="mt-6 grid grid-cols-2 gap-2 text-sm text-gray-700">
<li>• Nail trim & grind</li>
<li>• Deshedding & bathing</li>
<li>• Breed‑specific cuts</li>
<li>• Senior & anxious pets</li>
</ul>
</div>
{/* Lead form card */}
<div id="quote" className="bg-white rounded-2xl p-6 shadow">
<h3 className="text-xl font-semibold">Request a quote</h3>
<p className="text-sm text-gray-600 mb-4">Fast response. No spam. Local pros only.</p>
<form onSubmit={submitLead} className="grid grid-cols-1 gap-3">
<input className="px-3 py-2 rounded-xl ring-1 ring-gray-300 focus:outline-none focus:ring-2 focus:ring-emerald-600" placeholder="Your name" value={form.name} onChange={(e)=>setForm({...form, name:e.target.value})} required/>
<input className="px-3 py-2 rounded-xl ring-1 ring-gray-300 focus:outline-none focus:ring-2 focus:ring-emerald-600" placeholder="Phone" value={form.phone} onChange={(e)=>setForm({...form, phone:e.target.value})} required/>
<input className="px-3 py-2 rounded-xl ring-1 ring-gray-300 focus:outline-none focus:ring-2 focus:ring-emerald-600" placeholder="Email (optional)" value={form.email} onChange={(e)=>setForm({...form, email:e.target.value})}/>
<div className="grid grid-cols-2 gap-3">
<select className="px-3 py-2 rounded-xl ring-1 ring-gray-300 focus:outline-none focus:ring-2 focus:ring-emerald-600" value={form.petType} onChange={(e)=>setForm({...form, petType:e.target.value})}>
<option>Dog</option>
<option>Cat</option>
<option>Other</option>
</select>
<input className="px-3 py-2 rounded-xl ring-1 ring-gray-300 focus:outline-none focus:ring-2 focus:ring-emerald-600" placeholder="ZIP code" value={form.zip} onChange={(e)=>setForm({...form, zip:e.target.value})} required/>
</div>
<textarea className="px-3 py-2 rounded-xl ring-1 ring-gray-300 focus:outline-none focus:ring-2 focus:ring-emerald-600" rows={3} placeholder="Tell us about your pet / preferred time" value={form.message} onChange={(e)=>setForm({...form, message:e.target.value})}></textarea>
<button disabled={status==="loading"} className="mt-1 px-5 py-3 rounded-xl bg-emerald-600 text-white hover:bg-emerald-700 disabled:opacity-60">
{status === "loading" ? "Sending..." : "Send request"}
</button>
{status === "success" && (
<p className="text-emerald-700 text-sm">Thanks! A local groomer will reach out shortly.</p>
)}
{status === "error" && (
<p className="text-red-600 text-sm">Something went wrong. Please try again or call us.</p>
)}
</form>
<p className="mt-3 text-xs text-gray-500">By submitting, you agree to be contacted about your request. We never sell your info.</p>
</div>
</div>
</section>
{/* Featured partner */}
<section className="border-b" id="partner">
<div className="max-w-6xl mx-auto px-4 py-10">
<h3 className="text-2xl font-bold">⭐ Featured Mobile Groomer</h3>
<div className="mt-4 grid md:grid-cols-3 gap-6 items-start">
<div className="md:col-span-2 bg-white rounded-2xl p-6 ring-1 ring-gray-200">
<h4 className="text-xl font-semibold">FEATURED_GROOMER_NAME</h4>
<p className="text-gray-600 text-sm">FEATURED_GROOMER_TAGLINE – serving Federal Way, Kent, Auburn, Des Moines.</p>
<ul className="mt-3 text-sm grid grid-cols-2 gap-2">
<li>• 100% mobile service</li>
<li>• Cat & dog grooming</li>
<li>• Nail trim & teeth brush</li>
<li>• Senior & anxious pets</li>
</ul>
<div className="mt-4 flex gap-3">
<a href="#quote" className="px-4 py-2 rounded-lg bg-emerald-600 text-white hover:bg-emerald-700">Request a quote</a>
<a href="tel:+1PHONE_NUMBER" className="px-4 py-2 rounded-lg ring-1 ring-gray-300 hover:bg-gray-50">Call {"(555) 000‑0000"}</a>
</div>
</div>
<div className="aspect-video bg-gray-100 rounded-2xl flex items-center justify-center text-gray-500">
{/* Replace with groomer photo */}
<span>Photo / Logo</span>
</div>
</div>
</div>
</section>
{/* How it works */}
<section id="how" className="bg-white">
<div className="max-w-6xl mx-auto px-4 py-12">
<h3 className="text-2xl font-bold">How it works</h3>
<div className="mt-6 grid sm:grid-cols-3 gap-6">
{[
{ t: "Tell us about your pet", d: "Send a quick request with your ZIP and pet details." },
{ t: "We match you fast", d: "A vetted local groomer reaches out to confirm a time." },
{ t: "Grooming at your door", d: "No cages, no driving—stress‑free for your pet." },
].map((i, idx) => (
<div key={idx} className="p-5 rounded-2xl ring-1 ring-gray-200">
<div className="text-3xl">{idx + 1}</div>
<h4 className="mt-2 font-semibold">{i.t}</h4>
<p className="text-sm text-gray-600">{i.d}</p>
</div>
))}
</div>
</div>
</section>
{/* Pricing */}
<section id="costs" className="bg-emerald-50">
<div className="max-w-6xl mx-auto px-4 py-12">
<h3 className="text-2xl font-bold">Typical pricing (local ranges)</h3>
<div className="mt-6 grid md:grid-cols-3 gap-6 text-sm">
<div className="p-6 bg-white rounded-2xl ring-1 ring-gray-200">
<h4 className="font-semibold">Small dogs</h4>
<p className="text-gray-600">$60–$90 • bath, brush, nails</p>
</div>
<div className="p-6 bg-white rounded-2xl ring-1 ring-gray-200">
<h4 className="font-semibold">Medium/Large dogs</h4>
<p className="text-gray-600">$90–$140 • full groom</p>
</div>
<div className="p-6 bg-white rounded-2xl ring-1 ring-gray-200">
<h4 className="font-semibold">Cats</h4>
<p className="text-gray-600">$80–$130 • bath optional, de‑shed</p>
</div>
</div>
<p className="mt-4 text-xs text-gray-500">Prices vary by breed, coat, and travel distance. Final quote provided by your groomer.</p>
</div>
</section>
{/* Service areas */}
<section id="areas" className="bg-white">
<div className="max-w-6xl mx-auto px-4 py-12">
<h3 className="text-2xl font-bold">Service areas</h3>
<p className="text-gray-600">Federal Way • Kent • Auburn • Des Moines • Northeast Tacoma • Milton • Edgewood</p>
</div>
</section>
{/* FAQ */}
<section id="faq" className="bg-white border-t">
<div className="max-w-6xl mx-auto px-4 py-12">
<h3 className="text-2xl font-bold">FAQ</h3>
<div className="mt-6 grid md:grid-cols-2 gap-6 text-sm">
{[
{ q: "Do you handle anxious or senior pets?", a: "Yes—mobile grooming is calmer than salons. Let us know any concerns in your request." },
{ q: "Do groomers trim nails and brush teeth?", a: "Common add‑ons—ask in the form and we’ll match you appropriately." },
{ q: "How soon can I book?", a: "Same‑week slots are common outside major holidays. We’ll confirm by text." },
{ q: "What areas do you serve?", a: "Federal Way and surrounding South King County. See Service areas above." },
].map((f, i) => (
<div key={i} className="p-5 rounded-2xl ring-1 ring-gray-200">
<h4 className="font-semibold">{f.q}</h4>
<p className="text-gray-600">{f.a}</p>
</div>
))}
</div>
</div>
</section>
{/* Footer */}
<footer className="bg-gray-50 border-t">
<div className="max-w-6xl mx-auto px-4 py-10 text-sm text-gray-600">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<p>© {new Date().getFullYear()} Federal Way Mobile Pet Grooming</p>
<div className="flex gap-5">
<a href="#quote" className="hover:text-emerald-700">Get a quote</a>
<a href="#" className="hover:text-emerald-700">Privacy</a>
<a href="#" className="hover:text-emerald-700">Contact</a>
</div>
</div>
<p className="mt-3 text-xs">We connect pet owners with independent local groomers. We may receive a fee from partner businesses. Prices and availability vary.</p>
</div>
</footer>
</div>
);
}
Metadata
Metadata
Assignees
Labels
No labels