import { useCallback, useEffect, useState } from "react"; import { Link } from "react-router-dom"; import { Check, Copy, ExternalLink, Link2, RefreshCw, Unlink } from "lucide-react"; import { api } from "../api.js"; import { useAuth } from "../App.jsx"; import { Button, Empty, ErrorNote, Field, Panel, Spinner, timeAgo } from "../ui.jsx"; /** Client page tab: the client's private approval link and who to notify. */ export default function ClientPortal({ slug, clientName }) { const { isAdmin } = useAuth(); const [link, setLink] = useState(null); const [error, setError] = useState(null); const [busy, setBusy] = useState(null); const [copied, setCopied] = useState(false); const [contact, setContact] = useState({ contactName: "", contactEmail: "" }); const load = useCallback(() => api(`/api/portal/${slug}`).then((l) => { setLink(l); setContact({ contactName: l.contactName || "", contactEmail: l.contactEmail || "" }); }).catch(setError), [slug]); useEffect(() => { load(); }, [load]); const run = async (what, fn) => { setBusy(what); setError(null); try { const l = await fn(); if (l) { setLink(l); } } catch (e) { setError(e); } setBusy(null); }; if (!link) return error ? : ; const url = link.enabled ? `${location.origin}/p/${link.token}` : null; const copy = () => navigator.clipboard?.writeText(url).then(() => { setCopied(true); setTimeout(() => setCopied(false), 1500); }); return (
{!link.enabled ? ( run("issue", () => api(`/api/portal/${slug}`, { method: "POST", body: {} }))}>Create approval link : An admin creates the link.}> Give {clientName} a private link where they see the posts you send them, approve them or ask for changes. No login needed. Your team still gives the final approval before anything is posted. ) : ( <>
{url}

To send a post for review: Publishing → a draft → Send to client. Their answer shows on the draft.

{isAdmin && (
)}
{ e.preventDefault(); run("contact", () => api(`/api/portal/${slug}`, { method: "PATCH", body: contact })); }}> setContact({ ...contact, contactName: e.target.value })} /> setContact({ ...contact, contactEmail: e.target.value })} /> {isAdmin && }
)}
); }