- Settings → Workspace: agency name, logo, brand colour, support email, website - Logo replaces Quorla's in the app (with 'Powered by Quorla'), sign-in page, client approval page and PDF reports; brand colour drives buttons, links and highlights; emails and reports use the agency name - Getting started checklist on the Clients page for admins, checked against the real state (workspace, Meta, first client, team, platforms, email, library, first post, approval link); dismissible Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
40 lines
2.3 KiB
JavaScript
40 lines
2.3 KiB
JavaScript
import { useEffect, useState } from "react";
|
|
import { Link } from "react-router-dom";
|
|
import { CircleCheck, Circle, X } from "lucide-react";
|
|
import { api } from "./api.js";
|
|
import { useAuth } from "./App.jsx";
|
|
import { cx } from "./ui.jsx";
|
|
|
|
/** Admin checklist on the Clients page until every step is done or it's dismissed. */
|
|
export default function GettingStarted() {
|
|
const { isAdmin } = useAuth();
|
|
const [d, setD] = useState(null);
|
|
useEffect(() => { if (isAdmin) api("/api/onboarding").then(setD).catch(() => {}); }, [isAdmin]);
|
|
if (!d || d.dismissed || d.done === d.total) return null;
|
|
const next = d.items.find((s) => !s.done);
|
|
return (
|
|
<section className="panel p-4" aria-labelledby="gs-title">
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div>
|
|
<h2 id="gs-title" className="text-[15px] font-bold">Getting started</h2>
|
|
<p className="text-[12.5px] text-muted">{d.done} of {d.total} done. Next: <b className="text-ink-2">{next.title}</b>.</p>
|
|
</div>
|
|
<button type="button" onClick={() => api("/api/onboarding/dismiss", { method: "POST", body: { dismissed: true } }).then(setD)} className="p-1.5 rounded hover:bg-canvas text-muted" aria-label="Hide the getting started list"><X className="size-4" /></button>
|
|
</div>
|
|
<div className="h-1.5 rounded-full bg-canvas mt-3 overflow-hidden" aria-hidden="true"><div className="h-full bg-accent" style={{ width: `${(d.done / d.total) * 100}%` }} /></div>
|
|
<ol className="mt-3 grid sm:grid-cols-2 lg:grid-cols-3 gap-x-5 gap-y-2.5">
|
|
{d.items.map((s) => (
|
|
<li key={s.id} className="flex gap-2.5 items-start">
|
|
{s.done ? <CircleCheck className="size-[18px] text-ok shrink-0 mt-0.5" aria-label="Done" /> : <Circle className="size-[18px] text-faint shrink-0 mt-0.5" aria-label="To do" />}
|
|
<div className="min-w-0">
|
|
{s.done ? <span className="text-[13px] text-muted line-through">{s.title}</span>
|
|
: <Link to={s.link} className={cx("text-[13px] font-medium hover:underline", s.id === next.id ? "text-brand-deep" : "text-ink")}>{s.title}</Link>}
|
|
{!s.done && <p className="text-[12px] text-muted leading-snug">{s.text}</p>}
|
|
</div>
|
|
</li>
|
|
))}
|
|
</ol>
|
|
</section>
|
|
);
|
|
}
|