From 143b09e754433f5194600873459613524befcd1a Mon Sep 17 00:00:00 2001 From: Neraste Date: Sun, 9 Aug 2026 19:44:39 +0200 Subject: [PATCH 1/4] Improve time representation Fixes #291. --- src/components/generics/Timing.jsx | 67 +++++++++++ src/components/karaoke/player/Carousel.jsx | 49 +++++++-- src/components/library/status/InPlaylist.jsx | 11 +- src/components/library/widgets/Song.jsx | 5 +- src/components/playlist/played/Entry.jsx | 6 +- .../playlist/playerErrors/Entry.jsx | 4 +- src/components/playlist/queuing/Entry.jsx | 6 +- .../playlist/widgets/PlaylistEntry.jsx | 8 +- src/style/components/generics/_index.scss | 1 + src/style/components/generics/_timing.scss | 5 + .../library/status/_in_playlist.scss | 2 +- src/utils/index.js | 44 +++++--- src/utils/index.test.js | 104 +++++++++++++----- 13 files changed, 235 insertions(+), 77 deletions(-) create mode 100644 src/components/generics/Timing.jsx create mode 100644 src/style/components/generics/_timing.scss diff --git a/src/components/generics/Timing.jsx b/src/components/generics/Timing.jsx new file mode 100644 index 00000000..3cc5c198 --- /dev/null +++ b/src/components/generics/Timing.jsx @@ -0,0 +1,67 @@ +import PropTypes from 'prop-types' + +import { + formatDuration, + formatTime, + formatDateTime, + formatTimeRelative, +} from 'utils' + +export function Duration({ duration }) { + const [iso, hhmm, ss] = formatDuration(duration) + + return ( + + ) +} + +Duration.propTypes = { + duration: PropTypes.string.isRequired, +} + +export function Time({ iso }) { + const date = formatTime(iso) + + return ( + + ) +} + +Time.propTypes = { + iso: PropTypes.string.isRequired, +} + +export function DateTime({ iso, showSeconds = false }) { + const [date, ss] = formatDateTime(iso, showSeconds) + + return ( + + ) +} + +DateTime.propTypes = { + iso: PropTypes.string.isRequired, + showSeconds: PropTypes.bool, +} + +export function TimeRelative({ iso }) { + const date = formatTimeRelative(iso) + + return ( + + ) +} + +TimeRelative.propTypes = { + iso: PropTypes.string.isRequired, +} diff --git a/src/components/karaoke/player/Carousel.jsx b/src/components/karaoke/player/Carousel.jsx index ab45711e..750523c2 100644 --- a/src/components/karaoke/player/Carousel.jsx +++ b/src/components/karaoke/player/Carousel.jsx @@ -1,13 +1,15 @@ import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' +import duration from 'dayjs/plugin/duration' import queryString from 'query-string' import { useSelector } from 'react-redux' import { Link } from 'react-router' import { CarouselEntry } from 'components/generics/Carousel' +import { Duration, Time } from 'components/generics/Timing' import PlaylistEntryWidget from 'components/playlist/widgets/PlaylistEntry' -import { formatDate, formatDuration } from 'utils' +dayjs.extend(duration) dayjs.extend(relativeTime) export function CarouselEntryCurrentSong() { @@ -40,8 +42,12 @@ export function CarouselEntryCurrentSong() { />
-
{formatDuration(timing)}
-
{formatDuration(entry.song.duration)}
+
+ +
+
+ +
) @@ -147,7 +153,10 @@ export function CarouselEntryStats() { if (playlistEndDate && !karaokeEndDate) { end = (
  • - Playlist ends at {formatDate(playlistEndDate)} + Playlist ends at{' '} + +
  • ) // only karaoke date end @@ -156,10 +165,20 @@ export function CarouselEntryStats() { end = ( <>
  • - Karaoke ends at {formatDate(karaokeEndDate)} + Karaoke ends at{' '} + +
  • - {dayjs().to(karaokeEndDate, true)} remaining + + + {' '} + remaining
  • ) @@ -173,10 +192,20 @@ export function CarouselEntryStats() { end = ( <>
  • - Karaoke ends at {formatDate(karaokeEndDate)} + Karaoke ends at{' '} + +
  • - {dayjs().to(karaokeEndDate, true)} remaining + + + {' '} + remaining
  • ) @@ -186,7 +215,9 @@ export function CarouselEntryStats() { <>
  • Playlist should end after karaoke at{' '} - {formatDate(playlistEndDate)} + +
  • Playlist exceeds karaoke scheduled end!
  • diff --git a/src/components/library/status/InPlaylist.jsx b/src/components/library/status/InPlaylist.jsx index 3a8718af..9fbb39e5 100644 --- a/src/components/library/status/InPlaylist.jsx +++ b/src/components/library/status/InPlaylist.jsx @@ -6,7 +6,8 @@ import { Link } from 'react-router' import UserWidget from 'components/user/widgets/User' import { playlistEntryPropType } from 'serverPropTypes/playlist' -import { formatDate, formatDateRelative, getMostPertinentEntry } from 'utils' +import { getMostPertinentEntry } from 'utils' +import { Time, TimeRelative } from 'components/generics/Timing' function Playing({ entry }) { const playerStatus = useSelector((state) => state.playlist.playerStatus.data) @@ -35,7 +36,7 @@ function Queuing({ entry }) { - +