fix: ui fixes
This commit is contained in:
@@ -0,0 +1,77 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /u/[handle]/collections/[id] — single public-collection view for another
|
||||||
|
* user's profile. Mirrors the auth user's /u/me/collections/[id] exactly —
|
||||||
|
* the CollectionScrollCard carousel (cover + posts) — but read-only: no Edit
|
||||||
|
* affordance, since the viewer doesn't own it. Private collections (or a bad
|
||||||
|
* id) 403/404 from the BFF, which we treat as "not found".
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { use, useEffect, useState } from "react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { notFound } from "next/navigation";
|
||||||
|
import { ArrowLeft } from "lucide-react";
|
||||||
|
import {
|
||||||
|
collections,
|
||||||
|
SocialError,
|
||||||
|
type Collection,
|
||||||
|
type Post,
|
||||||
|
} from "@/lib/social";
|
||||||
|
import { CollectionScrollCard } from "@/components/social/collection/collection-scroll-card";
|
||||||
|
|
||||||
|
export default function PublicCollectionDetailPage(props: {
|
||||||
|
params: Promise<{ handle: string; id: string }>;
|
||||||
|
}) {
|
||||||
|
const { handle, id } = use(props.params);
|
||||||
|
|
||||||
|
const [c, setC] = useState<Collection | null>(null);
|
||||||
|
const [posts, setPosts] = useState<Post[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [missing, setMissing] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let cancelled = false;
|
||||||
|
collections
|
||||||
|
.get(id)
|
||||||
|
.then(({ collection, posts }) => {
|
||||||
|
if (cancelled) return;
|
||||||
|
setC(collection);
|
||||||
|
setPosts(posts ?? []);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (cancelled) return;
|
||||||
|
if (
|
||||||
|
err instanceof SocialError &&
|
||||||
|
(err.status === 404 || err.status === 403)
|
||||||
|
) {
|
||||||
|
setMissing(true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => !cancelled && setLoading(false));
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
if (missing) notFound();
|
||||||
|
if (loading) return <p className="text-sm text-muted-foreground">Loading…</p>;
|
||||||
|
if (!c) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Link
|
||||||
|
href={`/u/${handle}/collections`}
|
||||||
|
className="inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground"
|
||||||
|
>
|
||||||
|
<ArrowLeft className="size-4" /> All collections
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<CollectionScrollCard
|
||||||
|
collection={c}
|
||||||
|
href={`/u/${handle}/collections/${c.id}`}
|
||||||
|
initialPosts={posts}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -6,6 +6,9 @@
|
|||||||
* The list comes from the layout's profile fetch (`public_collections`),
|
* The list comes from the layout's profile fetch (`public_collections`),
|
||||||
* so this page only has to decide between the empty state and the grid.
|
* so this page only has to decide between the empty state and the grid.
|
||||||
* Layout owns the ProfileHeader + tabs + container.
|
* Layout owns the ProfileHeader + tabs + container.
|
||||||
|
*
|
||||||
|
* Cards link into /u/[handle]/collections/[id] — the same grid → carousel
|
||||||
|
* detail structure the auth user gets at /u/me/collections.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { CollectionViews } from "@/components/social/collection/collection-views";
|
import { CollectionViews } from "@/components/social/collection/collection-views";
|
||||||
@@ -23,5 +26,10 @@ export default function PublicProfileCollectionsPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <CollectionViews collections={list} hrefFor={(c) => `/c/${c.id}`} />;
|
return (
|
||||||
|
<CollectionViews
|
||||||
|
collections={list}
|
||||||
|
hrefFor={(c) => `/u/${data.handle}/collections/${c.id}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user