Adds the complete Next.js website including i18n routing, house and apartment pages, Beds24 v2 integration for live availability/pricing, Stripe checkout, contact forms, Docker setup and deployment docs. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
126 lines
4.6 KiB
TypeScript
126 lines
4.6 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { Mail, Send, CheckCircle2 } from "lucide-react";
|
|
|
|
interface NoAvailabilityContactProps {
|
|
locale: string;
|
|
/** e.g. the searched arrival/departure dates, sent along for context. */
|
|
context?: string;
|
|
}
|
|
|
|
export function NoAvailabilityContact({ locale, context }: NoAvailabilityContactProps) {
|
|
const [email, setEmail] = useState("");
|
|
const [message, setMessage] = useState("");
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState("");
|
|
const [sent, setSent] = useState(false);
|
|
|
|
const isDe = locale === "de";
|
|
|
|
async function handleSubmit(e: React.FormEvent) {
|
|
e.preventDefault();
|
|
if (!email || !message) return;
|
|
setLoading(true);
|
|
setError("");
|
|
|
|
try {
|
|
const res = await fetch("/api/contact", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ email, message, context }),
|
|
});
|
|
|
|
if (!res.ok) {
|
|
throw new Error("Failed to send message");
|
|
}
|
|
|
|
setSent(true);
|
|
} catch {
|
|
setError(
|
|
isDe
|
|
? "Ihre Nachricht konnte nicht gesendet werden. Bitte versuchen Sie es erneut oder schreiben Sie uns direkt an info@bb-apartment.de."
|
|
: "Your message could not be sent. Please try again or email us directly at info@bb-apartment.de."
|
|
);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
if (sent) {
|
|
return (
|
|
<div className="bg-brand-green/10 border-2 border-brand-green/30 rounded-2xl p-8 text-center max-w-xl mx-auto">
|
|
<CheckCircle2 className="w-10 h-10 text-brand-green mx-auto mb-3" />
|
|
<h3 className="text-xl font-bold text-brand-grey-dark mb-2">
|
|
{isDe ? "Nachricht gesendet!" : "Message sent!"}
|
|
</h3>
|
|
<p className="text-brand-grey">
|
|
{isDe
|
|
? "Danke für Ihre Anfrage. Wir melden uns so schnell wie möglich bei Ihnen."
|
|
: "Thank you for reaching out. We'll get back to you as soon as possible."}
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="bg-white border-2 border-brand-grey-soft rounded-2xl p-8 max-w-xl mx-auto">
|
|
<div className="flex items-center gap-3 mb-2">
|
|
<Mail className="w-6 h-6 text-brand-green" />
|
|
<h3 className="text-xl font-bold text-brand-grey-dark">
|
|
{isDe ? "Kein passendes Apartment gefunden?" : "Can't find what you're looking for?"}
|
|
</h3>
|
|
</div>
|
|
<p className="text-brand-grey mb-6">
|
|
{isDe
|
|
? "Schreiben Sie uns kurz Ihre Wunschtermine und Anforderungen — wir melden uns persönlich bei Ihnen, auch für individuelle Anfragen oder Wartelisten."
|
|
: "Tell us your preferred dates and requirements — we'll get back to you personally, including for custom requests or waitlists."}
|
|
</p>
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
<div>
|
|
<label className="block text-sm font-medium text-brand-grey-dark mb-1">
|
|
{isDe ? "E-Mail" : "Email"}
|
|
</label>
|
|
<input
|
|
type="email"
|
|
required
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
className="w-full px-4 py-3 rounded-xl border border-brand-grey-soft focus:border-brand-green focus:ring-1 focus:ring-brand-green outline-none"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block text-sm font-medium text-brand-grey-dark mb-1">
|
|
{isDe ? "Ihre Nachricht" : "Your message"}
|
|
</label>
|
|
<textarea
|
|
required
|
|
rows={5}
|
|
value={message}
|
|
onChange={(e) => setMessage(e.target.value)}
|
|
placeholder={
|
|
isDe
|
|
? "z.B. gewünschter Zeitraum, Anzahl Personen, besondere Wünsche..."
|
|
: "e.g. preferred dates, number of guests, special requests..."
|
|
}
|
|
className="w-full px-4 py-3 rounded-xl border border-brand-grey-soft focus:border-brand-green focus:ring-1 focus:ring-brand-green outline-none"
|
|
/>
|
|
</div>
|
|
|
|
{error && (
|
|
<div className="bg-red-50 text-red-600 rounded-lg p-3 text-sm">{error}</div>
|
|
)}
|
|
|
|
<button
|
|
type="submit"
|
|
disabled={loading}
|
|
className="inline-flex items-center justify-center gap-2 w-full bg-brand-green text-white font-semibold px-8 py-4 rounded-full hover:bg-brand-green-dark transition-colors disabled:opacity-50"
|
|
>
|
|
{loading ? (isDe ? "Wird gesendet..." : "Sending...") : isDe ? "Nachricht senden" : "Send message"}
|
|
<Send className="w-4 h-4" />
|
|
</button>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|