69 lines · 2.9 KB
import { Link } from "@tanstack/react-router";
import { useState } from "react";
import { listFollows, setFollow } from "~/fns/profile";
import { useOptimisticMutation } from "~/hooks/use-optimistic-mutation";
import { Button } from "~/ui/Button";
import { Avatar } from "~/ui/Avatar";

type Person = { name: string; display_name: string | null; avatar_key: string | null };
type Props = { name: string; followers: number; following: number; isFollowing: boolean; canFollow: boolean };

export function FollowPanel({ name, followers, following, isFollowing, canFollow }: Props) {
  const follow = useOptimisticMutation(
    { isFollowing, followers },
    (state, next: boolean) => ({ isFollowing: next, followers: Math.max(0, state.followers + (next ? 1 : -1)) }),
    (next: boolean) => setFollow({ data: { name, follow: next } }),
  );
  const [list, setList] = useState<{ direction: "followers" | "following"; people: Person[] } | null>(null);

  async function show(direction: "followers" | "following") {
    if (list?.direction === direction) return setList(null);
    setList({ direction, people: await listFollows({ data: { name, direction } }) });
  }

  return (
    <div className="space-y-3 text-sm">
      {canFollow && (
        <Button
          className="w-full"
          variant={follow.state.isFollowing ? "secondary" : "primary"}
          aria-pressed={follow.state.isFollowing}
          onClick={() => follow.run(!follow.state.isFollowing)}
        >
          {follow.state.isFollowing ? "Unfollow" : "Follow"}
        </Button>
      )}
      <div className="flex gap-3 text-kumo-subtle">
        <button type="button" className="hover:text-accent-400" onClick={() => show("followers")}>
          <span className="font-medium text-kumo-strong tabular-nums">{follow.state.followers}</span> followers
        </button>
        <button type="button" className="hover:text-accent-400" onClick={() => show("following")}>