sms-extension/client/src/pages/Brand.jsx

179 lines
7.4 KiB
JavaScript

import { useState } from 'react';
import { Link } from 'react-router-dom';
import { useBrand } from '../context/BrandContext';
import BusinessReviewModal from '../components/BusinessReviewModal';
import RegisterBusinessModal from '../components/RegisterBusinessModal';
import apiClient from '../api/client';
const NAV_CARDS = [
{ to: '/events', label: 'Events', icon: '⚡', desc: 'Manage order events and generate templates' },
{ to: '/templates', label: 'Templates', icon: '📄', desc: 'Review and configure approved templates' },
{ to: '/providers', label: 'Providers', icon: '🏢', desc: 'Save your SMS provider DLT details' },
];
function DeleteConfirmModal({ brandName, onCancel, onConfirm, deleting }) {
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-gray-900/50 backdrop-blur-sm">
<div className="bg-white border border-gray-200 rounded-lg p-5 w-full max-w-md ">
<div className="w-12 h-12 rounded-full bg-white flex items-center justify-center mx-auto mb-4">
<span className="text-xl">🗑</span>
</div>
<h3 className="text-lg font-semibold text-gray-800 text-center mb-2">Delete Brand?</h3>
<p className="text-sm text-gray-500 text-center mb-6">
This will permanently delete <span className="text-gray-800 font-medium">{brandName}</span> and all associated events, templates, and images. This cannot be undone.
</p>
<div className="flex gap-3">
<button
onClick={onCancel}
disabled={deleting}
className="flex-1 py-2 rounded-lg border border-gray-300 text-gray-700 hover:bg-gray-50 text-sm font-medium transition disabled:opacity-50"
>
Cancel
</button>
<button
onClick={onConfirm}
disabled={deleting}
className="flex-1 py-2 rounded-lg bg-red-600 hover:bg-red-700 text-white text-sm font-medium transition disabled:opacity-50 flex items-center justify-center gap-2"
>
{deleting ? <><span className="w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin" /> Deleting</> : 'Yes, Delete'}
</button>
</div>
</div>
</div>
);
}
export default function Brand() {
const { brand, loading, refetch } = useBrand();
const [showModal, setShowModal] = useState(false);
const [showReviewModal, setShowReviewModal] = useState(false);
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
const [deleting, setDeleting] = useState(false);
const [deleteError, setDeleteError] = useState('');
async function handleDelete() {
setDeleting(true);
setDeleteError('');
try {
await apiClient.delete('/api/brand');
setShowDeleteConfirm(false);
await refetch();
} catch (err) {
setDeleteError(err.response?.data?.error || 'Failed to delete brand');
setDeleting(false);
}
}
if (loading) {
return (
<div className="min-h-screen flex items-center justify-center bg-white">
<div className="w-8 h-8 border-2 border-gray-200 border-t-indigo-600 rounded-full animate-spin" />
</div>
);
}
// — WELCOME SCREEN —
if (!brand) {
return (
<div className="min-h-screen flex items-center justify-center bg-white">
<div className="text-center max-w-lg px-8">
<div className="w-16 h-16 rounded-lg bg-primary-blue flex items-center justify-center mx-auto mb-6 text-2xl font-bold text-white ">
S
</div>
<h1 className="text-3xl font-bold text-gray-800 mb-3 tracking-tight">SMS Template Extension</h1>
<p className="text-gray-500 text-base mb-8 leading-relaxed">
Generate TRAI-compliant SMS templates for your Fynd store. We'll scrape your website and use AI to extract your brand context automatically.
</p>
<button
onClick={() => setShowModal(true)}
className="px-8 py-2 rounded-lg bg-primary-blue hover:bg-primary-dark text-white font-medium transition-all focus:ring-2 focus:ring-offset-2 focus:ring-primary-blue"
>
Register Your Business
</button>
</div>
{showModal && <RegisterBusinessModal onClose={() => { setShowModal(false); refetch(); }} />}
</div>
);
}
// — BRAND DETAIL PAGE —
return (
<div className="min-h-screen bg-white p-5">
<div className="max-w-4xl mx-auto">
{/* Brand header card */}
<div className="rounded-lg bg-white border border-gray-200 p-5 mb-6">
<div className="flex items-start justify-between gap-4">
<div className="flex-1 min-w-0">
<h1 className="text-3xl font-bold text-gray-800 tracking-tight truncate">{brand.brandName}</h1>
<p className="text-gray-500 mt-1 text-sm font-medium">{brand.domain}</p>
<div className="flex items-center gap-2 mt-4 flex-wrap">
<span className="text-xs px-2.5 py-1 rounded-md bg-white border border-gray-200 text-primary-dark font-medium capitalize">
{brand.tone}
</span>
<span className="text-xs text-gray-400 font-medium tracking-wide">
Registered {new Date(brand.scrapedAt).toLocaleDateString('en-IN', { day: 'numeric', month: 'short', year: 'numeric' })}
</span>
</div>
</div>
<button
onClick={() => setShowDeleteConfirm(true)}
className="shrink-0 rounded-lg border border-gray-200 px-3 py-2 text-xs font-medium text-red-600 transition hover:border-red-200 hover:bg-red-50 hover:text-red-700"
>
Delete Brand
</button>
</div>
</div>
{/* Navigation cards */}
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
{NAV_CARDS.map(card => (
<Link
key={card.to}
to={card.to}
className="group rounded-lg bg-white border border-gray-200 p-5 transition-all hover:border-primary-blue hover:shadow-sm"
>
<div className="text-2xl mb-3 grayscale group-hover:grayscale-0 opacity-80 group-hover:opacity-100 transition-all">{card.icon}</div>
<p className="font-semibold text-gray-800 mb-1">{card.label}</p>
<p className="text-sm text-gray-500 leading-relaxed">{card.desc}</p>
</Link>
))}
</div>
{deleteError && (
<p className="mt-4 text-sm font-medium text-red-600 text-center">{deleteError}</p>
)}
</div>
<button
onClick={() => setShowReviewModal(true)}
className="fixed bottom-6 right-6 z-30 rounded-full bg-primary-blue px-5 py-3 text-sm font-semibold text-white shadow-lg transition hover:bg-primary-dark"
>
View Brand Review
</button>
{showDeleteConfirm && (
<DeleteConfirmModal
brandName={brand.brandName}
onCancel={() => setShowDeleteConfirm(false)}
onConfirm={handleDelete}
deleting={deleting}
/>
)}
{showReviewModal && (
<BusinessReviewModal
business={brand}
eyebrow="Business review"
helperText={brand?.domain
? `Review the captured brand context for ${brand.domain}.`
: 'Review the captured brand context for this business.'}
closeLabel="Close"
onClose={() => setShowReviewModal(false)}
/>
)}
</div>
);
}