From 9ff76b5ee403a95ecc15c6399dc1501112fc36f7 Mon Sep 17 00:00:00 2001 From: fierillo Date: Wed, 27 May 2026 11:10:20 -0300 Subject: [PATCH] show scored soldier positions --- app/soldados/SoldiersTable.tsx | 132 +++++++++++++++++---------------- app/soldados/[slug]/page.tsx | 2 +- 2 files changed, 68 insertions(+), 66 deletions(-) diff --git a/app/soldados/SoldiersTable.tsx b/app/soldados/SoldiersTable.tsx index 5b809df..2eb9709 100644 --- a/app/soldados/SoldiersTable.tsx +++ b/app/soldados/SoldiersTable.tsx @@ -3,6 +3,7 @@ import Link from "next/link"; import { Trophy, Zap } from "lucide-react"; import { GithubIcon } from "@/components/BrandIcons"; import { cn } from "@/lib/cn"; +import { HACKATHON_LABELS } from "@/lib/projects"; import type { Soldier } from "@/lib/soldiers"; // Mirrors the scoring constants in lib/soldiers.ts. Kept local to render @@ -61,21 +62,47 @@ function medal(position: number | null): string { return ""; } -function medalCounts(s: Soldier): { - gold: number; - silver: number; - bronze: number; - total: number; -} { - let gold = 0; - let silver = 0; - let bronze = 0; - for (const p of s.projects) { - if (p.position === 1) gold++; - else if (p.position === 2) silver++; - else if (p.position === 3) bronze++; +type ScoredPositionEntry = { + position: number; + hackathonId: string | null; + hackathonLabel: string; + projectId: string; + points: number; +}; + +function scoredPositionEntries(projects: Soldier["projects"]): ScoredPositionEntry[] { + return projects + .filter((p) => p.positionPoints > 0 && p.position != null) + .map((p) => ({ + position: p.position!, + hackathonId: p.hackathonId, + hackathonLabel: p.hackathonId ? hackathonLabel(p.hackathonId) : "Sin hackatón", + projectId: p.projectId, + points: p.positionPoints, + })) + .sort((a, b) => { + if (a.position !== b.position) return a.position - b.position; + return a.hackathonLabel.localeCompare(b.hackathonLabel, undefined, { + sensitivity: "base", + }); + }); +} + +function positionLabel(position: number): string { + if (position === 1) return "1er puesto 🥇"; + if (position === 2) return "2do puesto 🥈"; + if (position === 3) return "3er puesto 🥉"; + if (position === 4) return "4to puesto"; + if (position === 5) return "5to puesto"; + if (position === 6) return "6to puesto"; + return `${position}° puesto`; +} + +function hackathonLabel(id: string): string { + if (id in HACKATHON_LABELS) { + return HACKATHON_LABELS[id as keyof typeof HACKATHON_LABELS]; } - return { gold, silver, bronze, total: gold + silver + bronze }; + return id; } export default function SoldiersTable({ soldiers }: { soldiers: Soldier[] }) { @@ -95,7 +122,7 @@ export default function SoldiersTable({ soldiers }: { soldiers: Soldier[] }) { Builder Hackatones Proyectos - Medallas + Puestos Mejor Score @@ -217,63 +244,38 @@ export default function SoldiersTable({ soldiers }: { soldiers: Soldier[] }) { {(() => { - const m = medalCounts(s); - if (m.total === 0) + const entries = scoredPositionEntries(s.projects); + if (entries.length === 0) return ( ); - const goldPts = m.gold * POSITION_POINTS[1]!; - const silverPts = m.silver * POSITION_POINTS[2]!; - const bronzePts = m.bronze * POSITION_POINTS[3]!; - const medalsTotal = goldPts + silverPts + bronzePts; - const rows: TooltipRow[] = []; - if (m.gold > 0) - rows.push({ - left: `🥇 ${m.gold} × ${POSITION_POINTS[1]}`, - }); - if (m.silver > 0) - rows.push({ - left: `🥈 ${m.silver} × ${POSITION_POINTS[2]}`, - }); - if (m.bronze > 0) - rows.push({ - left: `🥉 ${m.bronze} × ${POSITION_POINTS[3]}`, - }); + const rows = entries.map(({ position, hackathonLabel }) => ({ + left: `${positionLabel(position)} · ${hackathonLabel} · ${POSITION_POINTS[position]} pts`, + })); + const positionsTotal = entries.reduce( + (sum, entry) => sum + entry.points, + 0, + ); return ( - - - {m.gold > 0 && ( - - 🥇 - - {m.gold} - - - )} - {m.silver > 0 && ( - - 🥈 - - {m.silver} - - - )} - {m.bronze > 0 && ( - - 🥉 - - {m.bronze} - + + + {entries.map(({ position, hackathonLabel, projectId }) => ( + + {positionLabel(position)} - )} + ))} ); @@ -422,8 +424,8 @@ function StatTooltip({ role="tooltip" className={cn( "pointer-events-none absolute right-0 top-full mt-2 z-30", - "min-w-[13rem] max-w-xs rounded-xl border border-border bg-background-card/95 backdrop-blur-md shadow-2xl", - "px-3.5 py-2.5 text-left whitespace-nowrap", + "min-w-[18rem] max-w-md rounded-xl border border-border bg-background-card/95 backdrop-blur-md shadow-2xl", + "px-3.5 py-2.5 text-left whitespace-normal", "opacity-0 translate-y-1", hoverClass, "transition-all duration-150", @@ -497,7 +499,7 @@ function ScoreBreakdownTooltip({ soldier }: { soldier: Soldier }) {
  • - Posiciones + Puestos +{b.positions}{" "} puntos diff --git a/app/soldados/[slug]/page.tsx b/app/soldados/[slug]/page.tsx index 67899d7..efdd12d 100644 --- a/app/soldados/[slug]/page.tsx +++ b/app/soldados/[slug]/page.tsx @@ -211,7 +211,7 @@ export default async function SoldierProfilePage({