fix(demo): graceful UX when YouTube actions are unavailable
The shared demo account no longer hits YouTube affordances: the onboarding wizard never opens (or renders) for it, the empty-feed prompt nudges into the shared library instead of the connect wizard, and the browser-facing /auth/upgrade redirects the demo home instead of returning a raw 403 JSON.
This commit is contained in:
parent
cc43488781
commit
cac0ff7489
6 changed files with 50 additions and 18 deletions
|
|
@ -68,12 +68,14 @@ export default function Feed({
|
|||
setFilters,
|
||||
view,
|
||||
canRead,
|
||||
isDemo = false,
|
||||
onOpenWizard,
|
||||
}: {
|
||||
filters: FeedFilters;
|
||||
setFilters: (f: FeedFilters) => void;
|
||||
view: "grid" | "list";
|
||||
canRead: boolean;
|
||||
isDemo?: boolean;
|
||||
onOpenWizard: () => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
|
@ -204,26 +206,42 @@ export default function Feed({
|
|||
|
||||
if (query.isLoading) return <div className="p-8 text-muted">{t("feed.loading")}</div>;
|
||||
if (query.isError) return <div className="p-8 text-muted">{t("feed.loadError")}</div>;
|
||||
// Onboarding empty state (no YouTube + own subscriptions): a dedicated full-page prompt,
|
||||
// with no toolbar (content-type/sort would be meaningless here).
|
||||
// Empty "my" feed with no YouTube access. The shared demo account can never connect
|
||||
// YouTube, so it gets a gentle nudge into the shared library instead of the connect
|
||||
// wizard; real users get the onboarding prompt. No toolbar (sort/type are meaningless).
|
||||
if (items.length === 0 && !canRead && filters.scope === "my")
|
||||
return (
|
||||
<div className="p-8 grid place-items-center text-center">
|
||||
<div className="max-w-sm">
|
||||
<h2 className="text-lg font-semibold">{t("feed.emptyTitle")}</h2>
|
||||
<p className="text-sm text-muted mt-2 mb-4">{t("feed.emptyBody")}</p>
|
||||
<button
|
||||
onClick={onOpenWizard}
|
||||
className="inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold bg-accent text-accent-fg hover:opacity-90 transition"
|
||||
>
|
||||
{t("feed.setUp")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilters({ ...filters, scope: "all" })}
|
||||
className="block mx-auto mt-3 text-sm text-muted hover:text-accent transition"
|
||||
>
|
||||
{t("feed.browseShared")}
|
||||
</button>
|
||||
<h2 className="text-lg font-semibold">
|
||||
{isDemo ? t("feed.demoEmptyTitle") : t("feed.emptyTitle")}
|
||||
</h2>
|
||||
<p className="text-sm text-muted mt-2 mb-4">
|
||||
{isDemo ? t("feed.demoEmptyBody") : t("feed.emptyBody")}
|
||||
</p>
|
||||
{isDemo ? (
|
||||
<button
|
||||
onClick={() => setFilters({ ...filters, scope: "all" })}
|
||||
className="inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold bg-accent text-accent-fg hover:opacity-90 transition"
|
||||
>
|
||||
{t("feed.browseLibrary")}
|
||||
</button>
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
onClick={onOpenWizard}
|
||||
className="inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-semibold bg-accent text-accent-fg hover:opacity-90 transition"
|
||||
>
|
||||
{t("feed.setUp")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setFilters({ ...filters, scope: "all" })}
|
||||
className="block mx-auto mt-3 text-sm text-muted hover:text-accent transition"
|
||||
>
|
||||
{t("feed.browseShared")}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue