"use client" import { Card, CardContent } from "@/components/ui/card" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { getColor } from "@/lib/colors" import { formatDate, formatNumber } from "@/lib/formatters" import { head } from "@/lib/hypixel/general" import { Guild } from "@/lib/schema/guild" import { playerForGuildSchema } from "@/lib/schema/player" import z from "zod" type PlayerForGuild = z.infer import Image from "next/image" import Link from "next/link" import { useEffect, useState } from "react" import { toast } from "sonner" type MemberWithPlayer = Guild["guild"]["members"][number] & { player?: PlayerForGuild["player"] loading?: boolean error?: boolean } export function GuildMembers({ members: mem, ranks }: { members: Guild["guild"]["members"], ranks: Guild["guild"]["ranks"] }) { const [members, setMembers] = useState( mem.map(member => ({ ...member, loading: false, error: false })) ) const [currentIndex, setCurrentIndex] = useState(0) const [isLoading, setIsLoading] = useState(false) const fetchMemberData = async (uuid: string, index: number) => { setMembers(prev => prev.map((member, i) => i === index ? { ...member, loading: true } : member)) try { const response = await fetch(`/api/guildmembers?uuid=${uuid}`) const data = await response.json() if (data.error) { setMembers(prev => prev.map((member, i) => i === index ? { ...member, loading: false, error: true } : member)) } else { setMembers(prev => prev.map((member, i) => i === index ? { ...member, loading: false, player: data.player } : member)) } } catch { setMembers(prev => prev.map((member, i) => i === index ? { ...member, loading: false, error: true } : member)) } } useEffect(() => { if (currentIndex < members.length && !isLoading) { const timer = setTimeout(() => { setIsLoading(true) fetchMemberData(members[currentIndex].uuid, currentIndex).then(() => { setCurrentIndex(prev => prev + 1) setIsLoading(false) }) }, 100) return () => clearTimeout(timer) } }, [currentIndex, members, isLoading]) toast.info(`Loaded ${members.filter(member => member.player).length} out of ${members.length} guild members`, { id: "guild.members.loader", duration: 1000 }) return ( Name Rank Weekly GEXP Joined Since {members.filter(member => member.player).sort((a, b) => { if (a.rank === "Guild Master" && b.rank !== "Guild Master") return -1 if (b.rank === "Guild Master" && a.rank !== "Guild Master") return 1 const aRank = ranks?.find(rank => rank.name === a.rank) const bRank = ranks?.find(rank => rank.name === b.rank) const aPriority = aRank?.priority ?? Number.MIN_SAFE_INTEGER const bPriority = bRank?.priority ?? Number.MIN_SAFE_INTEGER if (aPriority !== bPriority) { return bPriority - aPriority } return a.uuid.localeCompare(b.uuid) }).map((member, i) => )}
) } function MemberCard({ member: m }: { member: MemberWithPlayer }) { return ( {`${m.player?.displayname}'s {" "} {m.rank} {formatNumber(Object.values(m.expHistory).reduce((a, b) => a + b))} {formatDate(m.joined)} ) } function PlayerIGN( { ign, rank, monthly, rankColor, specialRank, prefix }: { ign: string rank: string | undefined monthly: string | undefined rankColor: string | undefined specialRank: string | undefined prefix: string | undefined } ) { if (prefix === "[PIG+++]") { return {ign} } if (specialRank) { if (specialRank === "YOUTUBER") { return {ign} } if (specialRank === "STAFF") { return {ign} } } if (monthly === "SUPERSTAR") { if (rankColor === "GOLD") { return {ign} } else { return {ign} } } switch (rank) { case "VIP": return {ign} case "VIP_PLUS": return {ign} case "MVP": return {ign} case "MVP_PLUS": return {ign} default: return {ign} } } function PlayerRank( { rank, monthly, plusColor, rankColor, specialRank, prefix }: { rank: string | undefined monthly: string | undefined plusColor?: string rankColor: string | undefined specialRank: string | undefined prefix: string | undefined } ) { if (prefix === "[PIG+++]") { return ( <> [PIG +++ ] ) } if (specialRank) { if (specialRank === "YOUTUBER") { return ( <> [ YOUTUBE ] ) } if (specialRank === "STAFF") { return ( <> [ ] ) } } if (monthly === "SUPERSTAR") { if (rankColor === "GOLD") { return ( <> [MVP ++ ] ) } else { return ( <> [MVP ++ ] ) } } switch (rank) { case "VIP": return [VIP] case "VIP_PLUS": return ( <> [VIP + ] ) case "MVP": return [MVP] case "MVP_PLUS": return ( <> [MVP + ] ) default: return null } }