feat: add followers/following list
This commit is contained in:
@@ -34,6 +34,10 @@ import { Settings, X } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { RelationshipResult, RelationshipState } from "@/lib/social";
|
||||
import { ProfileActions } from "@/components/profile/profile-actions";
|
||||
import {
|
||||
FollowListDrawer,
|
||||
type FollowMode,
|
||||
} from "@/components/profile/follow-list-drawer";
|
||||
|
||||
export function ProfileHeader({
|
||||
avatarURL,
|
||||
@@ -85,6 +89,9 @@ export function ProfileHeader({
|
||||
const [following, setFollowing] = useState(followingCount ?? 0);
|
||||
const [rel, setRel] = useState<RelationshipState | null>(relationship ?? null);
|
||||
|
||||
// Which follow list (if any) is open in the drawer.
|
||||
const [followList, setFollowList] = useState<FollowMode | null>(null);
|
||||
|
||||
const handleResult = (r: RelationshipResult) => {
|
||||
setRel(r.relationship);
|
||||
setFollowers(r.follower_count);
|
||||
@@ -116,8 +123,16 @@ export function ProfileHeader({
|
||||
) : null}
|
||||
{showCounts ? (
|
||||
<>
|
||||
<Stat n={followers} label="followers" />
|
||||
<Stat n={following} label="following" />
|
||||
<Stat
|
||||
n={followers}
|
||||
label="followers"
|
||||
onClick={() => setFollowList("followers")}
|
||||
/>
|
||||
<Stat
|
||||
n={following}
|
||||
label="following"
|
||||
onClick={() => setFollowList("following")}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -164,17 +179,51 @@ export function ProfileHeader({
|
||||
onClose={() => setZoomOpen(false)}
|
||||
/>
|
||||
) : null}
|
||||
{showCounts ? (
|
||||
<FollowListDrawer
|
||||
open={followList !== null}
|
||||
mode={followList ?? "followers"}
|
||||
handle={handle}
|
||||
onClose={() => setFollowList(null)}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/** One inline profile stat — bold count over a muted label. */
|
||||
function Stat({ n, label }: { n: number; label: string }) {
|
||||
return (
|
||||
<div className="flex flex-col items-center leading-tight">
|
||||
<span className="font-semibold text-lg text-foreground tabular-nums">{n}</span>
|
||||
/** One inline profile stat — bold count over a muted label. Renders as a
|
||||
* button (opening the follow list) when `onClick` is provided, else a plain
|
||||
* div (e.g. the posts count). */
|
||||
function Stat({
|
||||
n,
|
||||
label,
|
||||
onClick,
|
||||
}: {
|
||||
n: number;
|
||||
label: string;
|
||||
onClick?: () => void;
|
||||
}) {
|
||||
const inner = (
|
||||
<>
|
||||
<span className="font-semibold text-lg text-foreground tabular-nums">
|
||||
{n}
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground">{label}</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
if (!onClick) {
|
||||
return (
|
||||
<div className="flex flex-col items-center leading-tight">{inner}</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className="flex flex-col items-center leading-tight rounded-md px-2 -mx-1 py-0.5 transition-colors hover:bg-muted/60 outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
||||
>
|
||||
{inner}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user