95 lines
3.3 KiB
TypeScript
95 lines
3.3 KiB
TypeScript
import type { ComponentType, SVGProps } from "react";
|
|
import { Button } from "@/components/ui/button";
|
|
import Link from "next/link";
|
|
import { Trophy } from "lucide-react";
|
|
import type { LinkConfig, IconName } from "@/lib/config";
|
|
import {
|
|
getCountForLink,
|
|
formatCount,
|
|
type FollowerCounts,
|
|
} from "@/lib/followers/utils";
|
|
import { RobloxIcon, DiscordIcon, TiktokIcon, YoutubeIcon, FormIcon, DonateIcon } from "@/lib/icons";
|
|
import { LinkCarousel } from "@/components/link-carousel";
|
|
|
|
const iconMap: Record<IconName, ComponentType<SVGProps<SVGSVGElement>>> = {
|
|
roblox: RobloxIcon,
|
|
discord: DiscordIcon,
|
|
tiktok: TiktokIcon,
|
|
youtube: YoutubeIcon,
|
|
form: FormIcon,
|
|
donate: DonateIcon,
|
|
leaderboard: Trophy,
|
|
};
|
|
|
|
function LinkList({
|
|
counts,
|
|
label,
|
|
links,
|
|
}: {
|
|
counts: FollowerCounts;
|
|
label: string;
|
|
links: readonly LinkConfig[];
|
|
}) {
|
|
return (
|
|
<nav aria-label={label} className="flex flex-col gap-3">
|
|
{links.map((item) => {
|
|
const IconComponent = iconMap[item.icon];
|
|
const count = getCountForLink(item.name, counts);
|
|
const external = !item.link.startsWith("/");
|
|
|
|
return (
|
|
<Button
|
|
key={item.link}
|
|
variant="outline"
|
|
className="group h-12 w-full bg-black/60 p-4 transition-colors hover:border-primary/50 hover:bg-accent/80 md:bg-muted"
|
|
asChild
|
|
>
|
|
<Link
|
|
href={item.link}
|
|
target={external ? "_blank" : undefined}
|
|
rel={external ? "noopener noreferrer" : undefined}
|
|
>
|
|
<span className="flex w-full items-center justify-between gap-3">
|
|
<span className="flex min-w-0 items-center gap-3">
|
|
<span className="flex size-8 shrink-0 items-center justify-center">
|
|
<IconComponent className="size-6 text-muted-foreground transition-colors group-hover:text-foreground" />
|
|
</span>
|
|
<span className="flex min-w-0 flex-col items-start text-left">
|
|
<span className="truncate font-medium text-foreground">
|
|
{item.name}
|
|
</span>
|
|
{item.desc && (
|
|
<span className="truncate text-xs text-muted-foreground">
|
|
{item.desc}
|
|
</span>
|
|
)}
|
|
</span>
|
|
</span>
|
|
{item.icon === "donate" ? (
|
|
<span className="shrink-0 text-xs font-medium text-muted-foreground">
|
|
ขึ้นจอ 10 บาท+
|
|
</span>
|
|
) : count !== null ? (
|
|
<span className="shrink-0 text-xs font-medium">
|
|
{formatCount(count.count)}{" "}
|
|
<span className="text-muted-foreground">{count.label}</span>
|
|
</span>
|
|
) : null}
|
|
</span>
|
|
</Link>
|
|
</Button>
|
|
);
|
|
})}
|
|
</nav>
|
|
);
|
|
}
|
|
|
|
export function LinkCard({ counts, links1, links2 }: { counts: FollowerCounts; links1: readonly LinkConfig[]; links2: readonly LinkConfig[] }) {
|
|
return (
|
|
<LinkCarousel
|
|
primary={<LinkList counts={counts} label="ลิงก์หลัก" links={links1} />}
|
|
secondary={<LinkList counts={counts} label="ลิงก์เพิ่มเติม" links={links2} />}
|
|
/>
|
|
);
|
|
}
|