This commit is contained in:
Manchik
2026-05-19 18:28:43 +03:00
parent 48c16b8d3a
commit 68433b74c0
183 changed files with 18415 additions and 192 deletions
@@ -1,3 +1,20 @@
import { useState, useRef } from "react";
export function CountryBadge({ country }: { country: string | null }) {
if (!country) return <span className="text-gray-600 text-xs"></span>;
const isCode = country.length === 2;
return (
<span className="inline-flex items-center gap-1.5 text-xs text-gray-300 whitespace-nowrap">
{isCode && (
<span
className={`fi fi-${country.toLowerCase()}`}
style={{ width: "1.33em", height: "1em", borderRadius: "2px" }}
/>
)}
<span>{country}</span>
</span>
);
}
import { createPortal } from "react-dom";
import { IconLock, IconUnlock } from "@/components/shared/Icons";
import { t } from "@/lib/i18n";
@@ -35,3 +52,58 @@ export function MafileBadge({ hasMafile }: { hasMafile: boolean }) {
? <span className="badge badge-ok"></span>
: <span className="badge badge-unknown"></span>;
}
export function VacBadge({ status, games }: { status: string | null; games?: string | null }) {
const [pos, setPos] = useState<{ top: number; left: number } | null>(null);
const ref = useRef<HTMLSpanElement>(null);
const gameList: string[] = (() => {
if (!games) return [];
try { return JSON.parse(games) as string[]; } catch { return []; }
})();
const handleEnter = () => {
if (!ref.current || gameList.length === 0) return;
const r = ref.current.getBoundingClientRect();
setPos({ top: r.top, left: r.right + 6 });
};
const handleLeave = () => setPos(null);
if (status === "VAC") return <span className="badge badge-error">Vac</span>;
if (status === "GAME BAN") {
return (
<>
<span
ref={ref}
className="badge badge-error cursor-default"
onMouseEnter={handleEnter}
onMouseLeave={handleLeave}
>
Vac{gameList.length > 0 && <span className="ml-0.5 opacity-70">({gameList.length})</span>}
</span>
{pos && gameList.length > 0 && createPortal(
<div
style={{ position: "fixed", top: pos.top, left: pos.left, zIndex: 9999 }}
className="bg-dark-700 border border-dark-600 rounded-lg shadow-xl px-2.5 py-2 min-w-[140px] max-w-[220px] pointer-events-none"
>
<div className="text-[10px] text-gray-400 mb-1 font-semibold uppercase tracking-wide">Game Bans</div>
{gameList.map((g, i) => (
<div key={i} className="text-xs text-gray-200 py-0.5 border-b border-dark-600 last:border-0">{g}</div>
))}
</div>,
document.body,
)}
</>
);
}
if (status === "CLEAN") return <span className="badge badge-ok">NoVac</span>;
return <span className="badge badge-unknown"></span>;
}
export function LimitBadge({ status }: { status: string | null }) {
if (status === "Lim") return <span className="badge badge-running">Lim</span>;
if (status === "NoLim") return <span className="badge badge-ok">NoLim</span>;
return <span className="badge badge-unknown"></span>;
}