UNPKG

@wandelbots/wandelbots-js-react-components

Version:

React UI toolkit for building applications on top of the Wandelbots platform

123 lines (106 loc) 3.59 kB
/** * Formats time in seconds to D:HH:MM:SS, H:MM:SS or MM:SS format * Used for the default (large) timer variant * Automatically includes days and hours as needed for clarity */ export const formatTime = (seconds: number): string => { const days = Math.floor(seconds / 86400) const hours = Math.floor((seconds % 86400) / 3600) const minutes = Math.floor((seconds % 3600) / 60) const remainingSeconds = seconds % 60 // Build time parts array const parts: string[] = [] if (days > 0) { parts.push(days.toString()) parts.push(hours.toString().padStart(2, "0")) parts.push(minutes.toString().padStart(2, "0")) parts.push(remainingSeconds.toString().padStart(2, "0")) } else if (hours > 0) { parts.push(hours.toString()) parts.push(minutes.toString().padStart(2, "0")) parts.push(remainingSeconds.toString().padStart(2, "0")) } else { parts.push(minutes.toString()) parts.push(remainingSeconds.toString().padStart(2, "0")) } return parts.join(":") } /** * Formats time in seconds to a localized human-readable format * Used for the small timer variant * Examples: "2h 30m 15s", "45m 30s", "30s" * Falls back to English units if Intl.DurationFormat is not available */ export const formatTimeLocalized = ( seconds: number, locale?: string, ): string => { const days = Math.floor(seconds / 86400) const hours = Math.floor((seconds % 86400) / 3600) const minutes = Math.floor((seconds % 3600) / 60) const remainingSeconds = seconds % 60 // Try using Intl.DurationFormat if available (newer browsers) if (typeof Intl !== "undefined" && "DurationFormat" in Intl) { try { const duration: Record<string, number> = {} if (days > 0) duration.days = days if (hours > 0) duration.hours = hours if (minutes > 0) duration.minutes = minutes if (remainingSeconds > 0 || Object.keys(duration).length === 0) { duration.seconds = remainingSeconds } // @ts-expect-error - DurationFormat is not yet in TypeScript types const formatter = new Intl.DurationFormat(locale, { style: "narrow" }) return formatter.format(duration) } catch { // Fall through to manual formatting } } // Manual formatting with compact units const parts: string[] = [] if (days > 0) parts.push(`${days}d`) if (hours > 0) parts.push(`${hours}h`) if (minutes > 0) parts.push(`${minutes}m`) if (remainingSeconds > 0 || parts.length === 0) { parts.push(`${remainingSeconds}s`) } return parts.join(" ") } /** * Calculates progress percentage for different timer states */ export const calculateProgress = ( currentState: string, remainingTime: number, maxTime: number | null, ): number => { if (currentState === "idle") { return 0 } if (currentState === "countdown" && maxTime !== null) { // Count-down mode: progress based on elapsed time const elapsed = maxTime - remainingTime return Math.min(100, (elapsed / maxTime) * 100) } if (currentState === "measuring") { // Measuring mode: progress based on minute steps (0-100% per minute) return ((remainingTime / 60) % 1) * 100 } return 0 } /** * Calculates exact progress position based on elapsed time */ export const calculateExactProgress = ( currentState: string, totalElapsed: number, maxTime: number | null, ): number => { if (currentState === "countdown" && maxTime !== null) { return Math.min(100, (totalElapsed / maxTime) * 100) } if (currentState === "measuring") { return ((totalElapsed / 60) % 1) * 100 } return 0 }