Initial commit with 🏗️ create-eth @ 2.0.4
This commit is contained in:
55
packages/nextjs/components/oracle/TimeAgo.tsx
Normal file
55
packages/nextjs/components/oracle/TimeAgo.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useChallengeState } from "~~/services/store/challengeStore";
|
||||
|
||||
type TimeAgoProps = {
|
||||
timestamp?: bigint;
|
||||
staleWindow?: bigint;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const formatTimeAgo = (tsSec: number | undefined, nowSec: number): string => {
|
||||
if (tsSec === undefined) return "—";
|
||||
if (tsSec === 0) return "never";
|
||||
// Clamp to avoid negative display in rare race conditions
|
||||
const diffSec = Math.max(0, nowSec - tsSec);
|
||||
if (diffSec < 60) return `${diffSec}s ago`;
|
||||
const diffMin = Math.floor(diffSec / 60);
|
||||
if (diffMin < 60) return `${diffMin}m ago`;
|
||||
const diffHr = Math.floor(diffMin / 60);
|
||||
return `${diffHr}h ago`;
|
||||
};
|
||||
|
||||
export const TimeAgo = ({ timestamp, staleWindow, className = "" }: TimeAgoProps) => {
|
||||
const { timestamp: networkTimestamp } = useChallengeState();
|
||||
const [currentTime, setCurrentTime] = useState<number>(() =>
|
||||
networkTimestamp ? Number(networkTimestamp) : Math.floor(Date.now() / 1000),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setCurrentTime(prev => prev + 1);
|
||||
}, 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const tsSec = typeof timestamp === "bigint" ? Number(timestamp) : timestamp;
|
||||
const displayNow = currentTime;
|
||||
const text = formatTimeAgo(tsSec, displayNow);
|
||||
|
||||
// Determine staleness coloring
|
||||
let colorClass = "";
|
||||
if (tsSec === undefined) {
|
||||
colorClass = "";
|
||||
} else if (tsSec === 0) {
|
||||
colorClass = "text-error";
|
||||
} else if (typeof staleWindow === "bigint") {
|
||||
const isStale = tsSec === undefined ? false : displayNow - tsSec > Number(staleWindow);
|
||||
colorClass = isStale ? "text-error" : "text-success";
|
||||
}
|
||||
|
||||
return <span className={`whitespace-nowrap ${colorClass} ${className}`}>{text}</span>;
|
||||
};
|
||||
|
||||
export default TimeAgo;
|
||||
Reference in New Issue
Block a user