Added online status
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { getColor } from "@/lib/colors"
|
||||
import { formatRelativeTime } from "@/lib/formatters"
|
||||
import { Player } from "@/lib/schema/player"
|
||||
import { Wifi, WifiOff } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"
|
||||
|
||||
type NewPackageRank = Player["player"]["newPackageRank"]
|
||||
type MonthlyPackageRank = Player["player"]["monthlyPackageRank"]
|
||||
@@ -162,4 +164,44 @@ function GuildTag({ tag, tagColor, ign }: { tag?: string, tagColor?: string, ign
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
function OnlineStatus({ lastLogin, lastLogout }: { lastLogin: number | undefined, lastLogout: number | undefined }) {
|
||||
const size = 36
|
||||
|
||||
if (!lastLogout || !lastLogin) {
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<WifiOff className="text-mc-gray" size={size} />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
Offline. Player is most likely in status offline or a staff with api off.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
if (lastLogout > lastLogin) {
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<WifiOff className="text-mc-gray" size={size} />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{`Offline. Last seen online ${formatRelativeTime(lastLogout, "past")}`}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<Wifi className="text-mc-green" size={size} />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{`Online. Online for ${formatRelativeTime(lastLogout, "future")}`}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
61
src/components/ui/tooltip.tsx
Normal file
61
src/components/ui/tooltip.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
"use client"
|
||||
|
||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function TooltipProvider({
|
||||
delayDuration = 0,
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
||||
return (
|
||||
<TooltipPrimitive.Provider
|
||||
data-slot="tooltip-provider"
|
||||
delayDuration={delayDuration}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function Tooltip({
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
||||
</TooltipProvider>
|
||||
)
|
||||
}
|
||||
|
||||
function TooltipTrigger({
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
||||
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
||||
}
|
||||
|
||||
function TooltipContent({
|
||||
className,
|
||||
sideOffset = 0,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
||||
return (
|
||||
<TooltipPrimitive.Portal>
|
||||
<TooltipPrimitive.Content
|
||||
data-slot="tooltip-content"
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
|
||||
</TooltipPrimitive.Content>
|
||||
</TooltipPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
|
||||
@@ -18,3 +18,26 @@ export function formatNumber(num: number): string {
|
||||
export function formatDate(timestamp: number): string {
|
||||
return dateFormatter.format(new Date(timestamp))
|
||||
}
|
||||
|
||||
export function formatRelativeTime(timestamp: number, type: "past" | "future") {
|
||||
const now = Date.now()
|
||||
let diffMs = timestamp - now
|
||||
const past = diffMs < 0
|
||||
diffMs = Math.abs(diffMs)
|
||||
const suffixString = type === "past" ? " ago" : ""
|
||||
|
||||
const seconds = Math.floor(diffMs / 1000)
|
||||
const days = Math.floor(seconds / 86400)
|
||||
const hours = Math.floor((seconds % 86400) / 3600)
|
||||
const minutes = Math.floor((seconds % 3600) / 60)
|
||||
const secs = seconds % 60
|
||||
|
||||
const parts: string[] = []
|
||||
if (days) parts.push(days + " days,")
|
||||
if (hours) parts.push(hours + " hours,")
|
||||
if (minutes) parts.push(minutes + " minutes and")
|
||||
if (!parts.length || secs) parts.push(secs + " seconds")
|
||||
|
||||
const str = parts.slice(0, 4).join(" ")
|
||||
return past ? str + suffixString : "in " + str
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user