From 722b9f7937a991cc72e1b2e413596be50ef5b1e0 Mon Sep 17 00:00:00 2001 From: Elia Bieri Date: Tue, 20 Sep 2022 11:12:05 +0000 Subject: [PATCH] Merged in feature/vbv-148-human-readable-duration (pull request #8) Implement human readable durations * Implement duration formatting for humans * Add UTs * Rework rounding and formatting * Rename function --- .../components/circle/LearningSequence.vue | 5 ++-- .../utils/__tests__/humanizeDuration.spec.ts | 13 +++++++++ client/src/utils/humanizeDuration.ts | 29 +++++++++++++++++++ client/src/views/CircleView.vue | 3 +- 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 client/src/utils/__tests__/humanizeDuration.spec.ts create mode 100644 client/src/utils/humanizeDuration.ts diff --git a/client/src/components/circle/LearningSequence.vue b/client/src/components/circle/LearningSequence.vue index a809023e..c9f0f43d 100644 --- a/client/src/components/circle/LearningSequence.vue +++ b/client/src/components/circle/LearningSequence.vue @@ -4,6 +4,7 @@ import type { LearningContent, LearningSequence } from '@/types' import { useCircleStore } from '@/stores/circle' import { computed } from 'vue' import _ from 'lodash' +import { humanizeDuration } from '@/utils/humanizeDuration' const props = defineProps<{ learningSequence: LearningSequence @@ -73,14 +74,14 @@ const learningSequenceBorderClass = computed(() => {

{{ learningSequence.title }}

-
{{ learningSequence.minutes }} Minuten
+
{{ humanizeDuration(learningSequence.minutes) }}
{{ learningUnit.title }}
-
{{ learningUnit.minutes }} Minuten
+
{{ humanizeDuration(learningUnit.minutes) }}
{ + expect(humanizeDuration(1)).toBe('1 Minute') + expect(humanizeDuration(15)).toBe('15 Minuten') + expect(humanizeDuration(42)).toBe('45 Minuten') + expect(humanizeDuration(60)).toBe('1 Stunde') + expect(humanizeDuration(122)).toBe('2 Stunden') + expect(humanizeDuration(120)).toBe('2 Stunden') + expect(humanizeDuration(132)).toBe('2 Stunden 15 Minuten') + expect(humanizeDuration(632)).toBe('10 Stunden') +}) diff --git a/client/src/utils/humanizeDuration.ts b/client/src/utils/humanizeDuration.ts new file mode 100644 index 00000000..2a022e2c --- /dev/null +++ b/client/src/utils/humanizeDuration.ts @@ -0,0 +1,29 @@ +function pluralize(text: string, count: number) { + if (count === 1) { + return text; + } + return text + 'n'; +} + + +export function humanizeDuration(minutes: number) { + const hours = Math.floor(minutes / 60) + const remainingMinutes = minutes % 60 + + if (hours === 0 && minutes < 16) { + return pluralize(`${remainingMinutes} Minute`, remainingMinutes) + } + + // Remaining minutes are rounded to 15 mins + const roundToMinutes = 15 + const roundedMinutes = Math.round((minutes % 60) / roundToMinutes) * roundToMinutes + + const hoursString = hours > 0 ? pluralize(`${hours} Stunde`, hours) : '' + + const showMinutesUpToHours = 10 + const minutesString = roundedMinutes > 0 && hours < showMinutesUpToHours + ? pluralize(`${roundedMinutes} Minute`, roundedMinutes) : '' + + const delimiter = hoursString && minutesString ? ' ' : '' + return `${hoursString}${delimiter}${minutesString}` +} \ No newline at end of file diff --git a/client/src/views/CircleView.vue b/client/src/views/CircleView.vue index bd00eaae..88aed09e 100644 --- a/client/src/views/CircleView.vue +++ b/client/src/views/CircleView.vue @@ -10,6 +10,7 @@ import { useCircleStore } from '@/stores/circle' import { useAppStore } from '@/stores/app' import { useRoute } from 'vue-router' import _ from 'lodash' +import { humanizeDuration } from '@/utils/humanizeDuration' const route = useRoute() @@ -28,7 +29,7 @@ const circleStore = useCircleStore() const duration = computed(() => { if (circleStore.circle) { const minutes = _.sumBy(circleStore.circle.learningSequences, 'minutes') - return `${minutes} Minuten` + return humanizeDuration(minutes) } return ''