Single liverun type

This commit is contained in:
2026-02-07 00:55:23 +01:00
parent 9cf69fde7d
commit 75042007b7
6 changed files with 54 additions and 68 deletions
+2 -15
View File
@@ -1,4 +1,5 @@
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import formatTime from "@/lib/time-format";
import { LiveRun } from "@/modules/live-run/types"; import { LiveRun } from "@/modules/live-run/types";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@@ -7,21 +8,7 @@ export default function RunTimer({ runInfo }: { runInfo: LiveRun }) {
useEffect(() => { useEffect(() => {
// Update function calculates elapsed time // Update function calculates elapsed time
const updateTime = () => { const updateTime = () => setTime(formatTime(Date.now() - runInfo.start));
const elapsedMs = Date.now() - runInfo.start;
const totalSeconds = elapsedMs / 1000;
const hours = String(Math.floor(totalSeconds / 3600)).padStart(2, "0");
const minutes = String(Math.floor((totalSeconds % 3600) / 60)).padStart(
2,
"0",
);
const seconds = (totalSeconds % 60).toFixed(2);
setTime(
`${totalSeconds / 3600 >= 1 ? hours + ":" : ""}${minutes}:${seconds}`,
);
};
// Update immediately and then every second // Update immediately and then every second
updateTime(); updateTime();
+15 -15
View File
@@ -5,18 +5,18 @@ import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { TableRow, TableCell } from "@/components/ui/table"; import { TableRow, TableCell } from "@/components/ui/table";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { LiveRun } from "@/modules/live-run/types";
import formatTime from "@/lib/time-format";
export default function LiveRunRow({ export default function LiveRunRow({
index, index,
username, run,
problem, }: {
category, index: number;
time, run: LiveRun;
pace, }) {
status, const now = new Date().getTime() + 1000;
}: any) { const isTop = false;
const pacePositive = pace.startsWith("+");
const isTop = status === "pb";
return ( return (
<TableRow <TableRow
@@ -30,14 +30,14 @@ export default function LiveRunRow({
}} }}
> >
<TableCell className="font-medium pl-5"> <TableCell className="font-medium pl-5">
{isTop ? `🔥 ${username}` : username} {isTop ? `🔥 ${run.username}` : run.username}
</TableCell> </TableCell>
<TableCell> <TableCell>
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">
<span>{problem}</span> <span>{run.problem}</span>
<Badge variant="outline" className="w-fit text-xs"> <Badge variant="outline" className="w-fit text-xs">
{category} {run.category}
</Badge> </Badge>
</div> </div>
</TableCell> </TableCell>
@@ -45,18 +45,18 @@ export default function LiveRunRow({
<TableCell <TableCell
className={`font-mono ${isTop ? "text-primary font-bold" : ""}`} className={`font-mono ${isTop ? "text-primary font-bold" : ""}`}
> >
{time} {formatTime(now - run.start, false)}
</TableCell> </TableCell>
<TableCell> <TableCell>
<Badge <Badge
className={ className={
pacePositive false
? "bg-red-500/10 text-red-400" ? "bg-red-500/10 text-red-400"
: "bg-green-500/10 text-green-400" : "bg-green-500/10 text-green-400"
} }
> >
{pace} 0
</Badge> </Badge>
</TableCell> </TableCell>
+2 -6
View File
@@ -24,11 +24,7 @@ export default function LiveRuns() {
const [liveRuns, liveRunsLoaded, liveRunsError] = useAction(getLiveRuns); const [liveRuns, liveRunsLoaded, liveRunsError] = useAction(getLiveRuns);
// Sort top runners (status === 'pb') to the top // Sort top runners (status === 'pb') to the top
const sortedRuns = [...(liveRuns || [])].sort((a, b) => { const sortedRuns = [...(liveRuns || [])];
if (a.status === "pb" && b.status !== "pb") return -1;
if (a.status !== "pb" && b.status === "pb") return 1;
return 0;
});
return ( return (
<div className="min-h-screen pt-24 pb-16"> <div className="min-h-screen pt-24 pb-16">
@@ -82,7 +78,7 @@ export default function LiveRuns() {
<TableBody> <TableBody>
{sortedRuns.map((run, index) => ( {sortedRuns.map((run, index) => (
<LiveRunRow key={run.id} {...run} index={index} /> <LiveRunRow key={run.id} index={index} run={run} />
))} ))}
</TableBody> </TableBody>
</Table> </Table>
+15
View File
@@ -0,0 +1,15 @@
export default function formatTime(elapsedMs: number, formatMs = true) {
const totalSeconds = formatMs
? elapsedMs / 1000
: Math.floor(elapsedMs / 1000);
const hours = String(Math.floor(totalSeconds / 3600)).padStart(2, "0");
const minutes = String(Math.floor((totalSeconds % 3600) / 60)).padStart(
2,
"0",
);
const seconds = formatMs
? (totalSeconds % 60).toFixed(2).padStart(2, "0")
: (totalSeconds % 60).toString().padStart(2, "0");
return `${totalSeconds / 3600 >= 1 ? hours + ":" : ""}${minutes}:${seconds}`;
}
+19 -22
View File
@@ -3,55 +3,52 @@
import { createClient } from "@/lib/supabase/server"; import { createClient } from "@/lib/supabase/server";
import { getSession, getSessionRedirect } from "../account/core"; import { getSession, getSessionRedirect } from "../account/core";
import * as Core from "./core"; import * as Core from "./core";
import { LiveRun, Run } from "./types"; import { LiveRun } from "./types";
export async function getLiveRuns(): Promise<Run[]> { export async function getLiveRuns(): Promise<LiveRun[]> {
const supabase = await createClient(); const supabase = await createClient();
const _ = await getSession(supabase); const _ = await getSession(supabase);
return [ return [
{ {
id: 1, id: "1",
username: "speedmaster_x", username: "speedmaster_x",
problem: "Two Sum Dash", problem: "Two Sum Dash",
category: "Any%", category: "any%",
time: "1:52.34", runsCount: 1,
pace: "-0:03", start: new Date().getTime(),
status: "pb",
}, },
{ {
id: 2, id: "2",
username: "algo_ninja", username: "algo_ninja",
problem: "Binary Sprint", problem: "Binary Sprint",
category: "Any%", category: "any%",
time: "2:04.11", runsCount: 1,
pace: "+0:05", start: new Date().getTime(),
status: "normal",
}, },
{ {
id: 3, id: "3",
username: "stackattack", username: "stackattack",
problem: "String Scramble", problem: "String Scramble",
category: "Easy", category: "any%",
time: "0:48.92", runsCount: 1,
pace: "-0:01", start: new Date().getTime(),
status: "pb",
}, },
{ {
id: 4, id: "4",
username: "reset_king", username: "reset_king",
problem: "Linked List Rush", problem: "Linked List Rush",
category: "Any%", category: "any%",
time: "1:31.77", runsCount: 1,
pace: "+0:12", start: new Date().getTime(),
status: "danger",
}, },
]; ];
} }
export async function getLiveRun(): Promise<LiveRun> { export async function getLiveRun(): Promise<LiveRun> {
return { return {
id: "0",
username: "selimaj", username: "selimaj",
start: new Date().getTime(), start: new Date().getTime(),
problem: "solve", problem: "solve",
+1 -10
View File
@@ -1,17 +1,8 @@
export interface LiveRun { export interface LiveRun {
id: string;
username: string; username: string;
start: number; start: number;
runsCount: number; runsCount: number;
problem: string; problem: string;
category: "any%" | "100%"; category: "any%" | "100%";
} }
export interface Run {
id: number;
username: string;
problem: string;
category: string;
time: string;
pace: string;
status: string;
}