blog2video-test / frontend /src /components /DesignerTemplateRequestModal.tsx
Muhammad-Mehdi's picture
custom template flow modified
482dcd8
Raw
History Blame Contribute Delete
6.16 kB
import { useState } from "react";
import ReactDOM from "react-dom";
import { sendCustomTemplateRequest } from "../api/enterprise";
interface Props {
open: boolean;
onClose: () => void;
}
export default function DesignerTemplateRequestModal({ open, onClose }: Props) {
const [description, setDescription] = useState("");
const [altContact, setAltContact] = useState("");
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleClose = () => {
if (loading) return;
onClose();
setTimeout(() => {
setDescription("");
setAltContact("");
setSuccess(false);
setError(null);
}, 200);
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!description.trim()) return;
setLoading(true);
setError(null);
try {
await sendCustomTemplateRequest({
description: description.trim(),
alternate_contact: altContact.trim() || undefined,
});
setSuccess(true);
setTimeout(() => {
handleClose();
}, 3000);
} catch {
setError("Failed to send request. Please try again.");
} finally {
setLoading(false);
}
};
if (!open) return null;
return ReactDOM.createPortal(
<div className="fixed inset-0 z-[130] flex items-center justify-center p-4">
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" onClick={handleClose} aria-hidden />
<div className="relative bg-white rounded-2xl shadow-2xl w-full max-w-lg p-6">
{success ? (
<div className="flex flex-col items-center py-8 text-center gap-4">
<div className="w-14 h-14 bg-green-100 rounded-full flex items-center justify-center">
<svg className="w-7 h-7 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<h3 className="text-lg font-semibold text-gray-900">Request Successfully Sent</h3>
<p className="text-sm text-gray-500 max-w-sm">
Thank you! Our design team will review your request and reach out with next steps shortly.
You'll hear back from us within 1–2 business days.
</p>
</div>
) : (
<>
<div className="flex items-start justify-between mb-5">
<div>
<h3 className="text-lg font-semibold text-gray-900">Request a Designer Template</h3>
<p className="text-sm text-gray-500 mt-1">
Tell us what you need and our design team will create a custom Designer Template tailored to your brand.
</p>
</div>
<button onClick={handleClose} className="ml-4 shrink-0 text-gray-400 hover:text-gray-600 transition">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<form onSubmit={handleSubmit} className="space-y-5">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Template Description <span className="text-red-400">*</span>
</label>
<textarea
required
rows={5}
maxLength={3000}
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="Describe your ideal template or give links to references."
className="w-full px-3 py-2 border border-gray-200 rounded-xl text-sm text-gray-900 placeholder-gray-400 resize-none focus:outline-none focus:ring-2 focus:ring-purple-300"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Alternate Contact <span className="text-gray-400 font-normal">(optional)</span>
</label>
<input
type="text"
maxLength={300}
value={altContact}
onChange={(e) => setAltContact(e.target.value)}
placeholder="Alternate email, phone, etc."
className="w-full px-3 py-2 border border-gray-200 rounded-xl text-sm text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-300"
/>
</div>
{error && <p className="text-sm text-red-500">{error}</p>}
<div className="flex gap-3 pt-2">
<button
type="button"
onClick={handleClose}
className="flex-1 px-4 py-2.5 text-sm font-medium text-gray-600 border border-gray-200 rounded-xl hover:bg-gray-50 transition-colors"
>
Cancel
</button>
<button
type="submit"
disabled={loading || !description.trim()}
className="flex-1 px-4 py-2.5 text-sm font-medium text-white bg-purple-600 hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed rounded-xl transition-colors flex items-center justify-center gap-2"
>
{loading && (
<svg className="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z" />
</svg>
)}
{loading ? "Submitting…" : "Submit Request"}
</button>
</div>
</form>
</>
)}
</div>
</div>,
document.body
);
}