From 0b9cf78e9bb82d238cb79b0d512825393da30a83 Mon Sep 17 00:00:00 2001 From: Mike Zhou Date: Sat, 2 Dec 2023 13:27:11 -0500 Subject: [PATCH] feat: display long durations in hours on booking (#12631) Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> --- apps/web/public/static/locales/ar/common.json | 1 + apps/web/public/static/locales/cs/common.json | 1 + apps/web/public/static/locales/da/common.json | 1 + apps/web/public/static/locales/de/common.json | 1 + apps/web/public/static/locales/en/common.json | 1 + apps/web/public/static/locales/es/common.json | 1 + apps/web/public/static/locales/fr/common.json | 1 + apps/web/public/static/locales/he/common.json | 1 + apps/web/public/static/locales/it/common.json | 1 + apps/web/public/static/locales/ja/common.json | 1 + apps/web/public/static/locales/ko/common.json | 1 + apps/web/public/static/locales/nl/common.json | 1 + apps/web/public/static/locales/no/common.json | 1 + apps/web/public/static/locales/pl/common.json | 1 + .../public/static/locales/pt-BR/common.json | 1 + apps/web/public/static/locales/pt/common.json | 1 + apps/web/public/static/locales/ro/common.json | 1 + apps/web/public/static/locales/ru/common.json | 1 + apps/web/public/static/locales/sr/common.json | 1 + apps/web/public/static/locales/sv/common.json | 1 + apps/web/public/static/locales/tr/common.json | 1 + apps/web/public/static/locales/uk/common.json | 1 + apps/web/public/static/locales/vi/common.json | 1 + .../public/static/locales/zh-CN/common.json | 1 + .../public/static/locales/zh-TW/common.json | 1 + .../components/event-meta/Duration.tsx | 32 +++++++++++++++++-- 26 files changed, 55 insertions(+), 2 deletions(-) diff --git a/apps/web/public/static/locales/ar/common.json b/apps/web/public/static/locales/ar/common.json index 676a3e8df5..ee1d5ade9c 100644 --- a/apps/web/public/static/locales/ar/common.json +++ b/apps/web/public/static/locales/ar/common.json @@ -656,6 +656,7 @@ "default_duration": "المدة الافتراضية", "default_duration_no_options": "يرجى اختيار المدد المتاحة أولاً", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "الدقائق", "round_robin": "الترتيب الدوري", "round_robin_description": "نقل الاجتماعات بشكل دوري بين أعضاء الفريق المتعددين.", diff --git a/apps/web/public/static/locales/cs/common.json b/apps/web/public/static/locales/cs/common.json index 07d8d5c07c..b21f2b6c53 100644 --- a/apps/web/public/static/locales/cs/common.json +++ b/apps/web/public/static/locales/cs/common.json @@ -656,6 +656,7 @@ "default_duration": "Výchozí doba trvání", "default_duration_no_options": "Nejprve vyberte dostupné doby trvání", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "min", "round_robin": "Plánování Round Robin", "round_robin_description": "Schůzky v řadě mezi několika členy týmu.", diff --git a/apps/web/public/static/locales/da/common.json b/apps/web/public/static/locales/da/common.json index 5e3cdf8c5f..34deeeb5c3 100644 --- a/apps/web/public/static/locales/da/common.json +++ b/apps/web/public/static/locales/da/common.json @@ -553,6 +553,7 @@ "default_duration": "Standard varighed", "default_duration_no_options": "Vælg venligst tilgængelige varigheder først", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minutter", "round_robin": "Round Robin", "round_robin_description": "Cyklusmøder mellem flere teammedlemmer.", diff --git a/apps/web/public/static/locales/de/common.json b/apps/web/public/static/locales/de/common.json index 5efbe3a4ca..c7820bd5c7 100644 --- a/apps/web/public/static/locales/de/common.json +++ b/apps/web/public/static/locales/de/common.json @@ -656,6 +656,7 @@ "default_duration": "Standardlaufzeit", "default_duration_no_options": "Bitte wählen Sie zuerst die verfügbaren Laufzeiten aus", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minuten", "round_robin": "Round Robin", "round_robin_description": "Treffen zwischen mehreren Teammitgliedern durchwechseln.", diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index dceb80940c..a29287a20b 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -673,6 +673,7 @@ "default_duration": "Default duration", "default_duration_no_options": "Please choose available durations first", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minutes", "round_robin": "Round Robin", "round_robin_description": "Cycle meetings between multiple team members.", diff --git a/apps/web/public/static/locales/es/common.json b/apps/web/public/static/locales/es/common.json index d856a29277..525c5836fc 100644 --- a/apps/web/public/static/locales/es/common.json +++ b/apps/web/public/static/locales/es/common.json @@ -656,6 +656,7 @@ "default_duration": "Duración predeterminada", "default_duration_no_options": "Seleccione primero las duraciones disponibles", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minutos", "round_robin": "Petición Firmada por Turnos", "round_robin_description": "Ciclo de reuniones entre varios miembros del equipo.", diff --git a/apps/web/public/static/locales/fr/common.json b/apps/web/public/static/locales/fr/common.json index 8b6abb135d..149b1a0aaf 100644 --- a/apps/web/public/static/locales/fr/common.json +++ b/apps/web/public/static/locales/fr/common.json @@ -660,6 +660,7 @@ "default_duration": "Durée par défaut", "default_duration_no_options": "Veuillez d'abord choisir les durées disponibles", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "minutes", "round_robin": "Round-robin", "round_robin_description": "Alternez vos rendez-vous entre plusieurs membres d'équipe.", diff --git a/apps/web/public/static/locales/he/common.json b/apps/web/public/static/locales/he/common.json index 6bb5b7ac5e..37d795416f 100644 --- a/apps/web/public/static/locales/he/common.json +++ b/apps/web/public/static/locales/he/common.json @@ -656,6 +656,7 @@ "default_duration": "משך הזמן המוגדר כברירת מחדל", "default_duration_no_options": "ראשית, אנא בחר משך זמינות", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "דקות", "round_robin": "לפי תורות", "round_robin_description": "פגישות מחזוריות בין חברי צוות מרובים.", diff --git a/apps/web/public/static/locales/it/common.json b/apps/web/public/static/locales/it/common.json index 19afe8b917..405221a3e9 100644 --- a/apps/web/public/static/locales/it/common.json +++ b/apps/web/public/static/locales/it/common.json @@ -656,6 +656,7 @@ "default_duration": "Durata predefinita", "default_duration_no_options": "Scegliere prima delle durate disponibili", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minuti", "round_robin": "Round Robin", "round_robin_description": "Ciclo di riunioni tra più membri del team.", diff --git a/apps/web/public/static/locales/ja/common.json b/apps/web/public/static/locales/ja/common.json index a42c7074a4..e31e8c67d2 100644 --- a/apps/web/public/static/locales/ja/common.json +++ b/apps/web/public/static/locales/ja/common.json @@ -656,6 +656,7 @@ "default_duration": "デフォルトの時間", "default_duration_no_options": "最初に空いている時間を選択してください", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "分", "round_robin": "ラウンドロビン", "round_robin_description": "複数のチームメンバー間のミーティングを定期化する。", diff --git a/apps/web/public/static/locales/ko/common.json b/apps/web/public/static/locales/ko/common.json index a8b1a62d1e..152dd4f6dd 100644 --- a/apps/web/public/static/locales/ko/common.json +++ b/apps/web/public/static/locales/ko/common.json @@ -656,6 +656,7 @@ "default_duration": "기본 기간", "default_duration_no_options": "사용 가능한 기간을 먼저 선택하세요", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "분", "round_robin": "라운드 로빈", "round_robin_description": "여러 팀 구성원 간의 주기적인 회의", diff --git a/apps/web/public/static/locales/nl/common.json b/apps/web/public/static/locales/nl/common.json index 300997f9df..7e331d48ff 100644 --- a/apps/web/public/static/locales/nl/common.json +++ b/apps/web/public/static/locales/nl/common.json @@ -656,6 +656,7 @@ "default_duration": "Standaardduur", "default_duration_no_options": "Kies eerst de beschikbare duur", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minuten", "round_robin": "Round Robin", "round_robin_description": "Afspraken wisselen tussen meerdere teamleden.", diff --git a/apps/web/public/static/locales/no/common.json b/apps/web/public/static/locales/no/common.json index 8e080f4035..a1499e20f4 100644 --- a/apps/web/public/static/locales/no/common.json +++ b/apps/web/public/static/locales/no/common.json @@ -544,6 +544,7 @@ "default_duration": "Standard varighet", "default_duration_no_options": "Vennligst velg tilgjengelige varigheter først", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minutter", "round_robin": "Round Robin", "round_robin_description": "Varier møter mellom flere teammedlemmer.", diff --git a/apps/web/public/static/locales/pl/common.json b/apps/web/public/static/locales/pl/common.json index 4943227283..710bac31b6 100644 --- a/apps/web/public/static/locales/pl/common.json +++ b/apps/web/public/static/locales/pl/common.json @@ -656,6 +656,7 @@ "default_duration": "Domyślny czas trwania", "default_duration_no_options": "Proszę najpierw wybrać dostępne czasy trwania", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minuty", "round_robin": "Round Robin", "round_robin_description": "Cykl spotkań między wieloma członkami zespołu.", diff --git a/apps/web/public/static/locales/pt-BR/common.json b/apps/web/public/static/locales/pt-BR/common.json index 4b4de9ecf2..45174f83bf 100644 --- a/apps/web/public/static/locales/pt-BR/common.json +++ b/apps/web/public/static/locales/pt-BR/common.json @@ -656,6 +656,7 @@ "default_duration": "Duração padrão", "default_duration_no_options": "Escolha as durações disponíveis primeiro", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minutos", "round_robin": "Round Robin", "round_robin_description": "Reuniões recorrentes entre vários membros da equipe.", diff --git a/apps/web/public/static/locales/pt/common.json b/apps/web/public/static/locales/pt/common.json index 8efce907b3..e8c0928ba2 100644 --- a/apps/web/public/static/locales/pt/common.json +++ b/apps/web/public/static/locales/pt/common.json @@ -656,6 +656,7 @@ "default_duration": "Duração predefinida", "default_duration_no_options": "Por favor, selecione primeiro as durações disponíveis", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minutos", "round_robin": "Round Robin", "round_robin_description": "Reuniões de ciclo entre vários membros da equipa.", diff --git a/apps/web/public/static/locales/ro/common.json b/apps/web/public/static/locales/ro/common.json index ca48e6c368..6ffe3116db 100644 --- a/apps/web/public/static/locales/ro/common.json +++ b/apps/web/public/static/locales/ro/common.json @@ -656,6 +656,7 @@ "default_duration": "Durată implicită", "default_duration_no_options": "Alege mai întâi duratele disponibile", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minute", "round_robin": "Round Robin", "round_robin_description": "Întâlniri ciclice între mai mulţi membri ai echipei.", diff --git a/apps/web/public/static/locales/ru/common.json b/apps/web/public/static/locales/ru/common.json index 2da6be2e14..296fcf2017 100644 --- a/apps/web/public/static/locales/ru/common.json +++ b/apps/web/public/static/locales/ru/common.json @@ -656,6 +656,7 @@ "default_duration": "Продолжительность по умолчанию", "default_duration_no_options": "Пожалуйста, выберите сначала доступную продолжительность", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "мин.", "round_robin": "По кругу", "round_robin_description": "Цикл встреч между несколькими членами команды.", diff --git a/apps/web/public/static/locales/sr/common.json b/apps/web/public/static/locales/sr/common.json index 543ddaeaf7..e7e48d3949 100644 --- a/apps/web/public/static/locales/sr/common.json +++ b/apps/web/public/static/locales/sr/common.json @@ -656,6 +656,7 @@ "default_duration": "Podrazumevano trajanje", "default_duration_no_options": "Najpre izaberite dostupna trajanja", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minuti", "round_robin": "Round Robin", "round_robin_description": "Ciklusirajte sastanke između više članova tima.", diff --git a/apps/web/public/static/locales/sv/common.json b/apps/web/public/static/locales/sv/common.json index fcc2acaab1..fee90e3cbb 100644 --- a/apps/web/public/static/locales/sv/common.json +++ b/apps/web/public/static/locales/sv/common.json @@ -656,6 +656,7 @@ "default_duration": "Standardvaraktighet", "default_duration_no_options": "Välj först tillgänglig varaktighet", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Minuter", "round_robin": "Tur och ordning", "round_robin_description": "Variera möten mellan olika teammedlemmar.", diff --git a/apps/web/public/static/locales/tr/common.json b/apps/web/public/static/locales/tr/common.json index f82f854d07..0073e6fa8c 100644 --- a/apps/web/public/static/locales/tr/common.json +++ b/apps/web/public/static/locales/tr/common.json @@ -656,6 +656,7 @@ "default_duration": "Varsayılan süre", "default_duration_no_options": "Lütfen önce uygun süreleri seçin", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Dakika", "round_robin": "Round Robin", "round_robin_description": "Toplantıları birden fazla ekip üyesi arasında döndürün.", diff --git a/apps/web/public/static/locales/uk/common.json b/apps/web/public/static/locales/uk/common.json index 13e68e93ed..113127c4f7 100644 --- a/apps/web/public/static/locales/uk/common.json +++ b/apps/web/public/static/locales/uk/common.json @@ -656,6 +656,7 @@ "default_duration": "Тривалість за замовчуванням", "default_duration_no_options": "Спочатку виберіть доступні варіанти тривалості", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Хвилини", "round_robin": "Ротація", "round_robin_description": "Кілька учасників команди призначаються для нарад циклічно й по черзі.", diff --git a/apps/web/public/static/locales/vi/common.json b/apps/web/public/static/locales/vi/common.json index b4497764c7..d1d1417fa2 100644 --- a/apps/web/public/static/locales/vi/common.json +++ b/apps/web/public/static/locales/vi/common.json @@ -656,6 +656,7 @@ "default_duration": "Khoảng thời gian mặc định", "default_duration_no_options": "Vui lòng chọn trước tiên những khoảng thời gian khả dụng", "multiple_duration_mins": "{{count}}$t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "Phút", "round_robin": "Round Robin", "round_robin_description": "Luân phiên những cuộc họp giữa các thành viên trong nhóm.", diff --git a/apps/web/public/static/locales/zh-CN/common.json b/apps/web/public/static/locales/zh-CN/common.json index 2744709507..56569d5df6 100644 --- a/apps/web/public/static/locales/zh-CN/common.json +++ b/apps/web/public/static/locales/zh-CN/common.json @@ -656,6 +656,7 @@ "default_duration": "默认时长", "default_duration_no_options": "请先选择可用时长", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "分钟", "round_robin": "轮流模式", "round_robin_description": "和多个团队成员之间轮流举行会议。", diff --git a/apps/web/public/static/locales/zh-TW/common.json b/apps/web/public/static/locales/zh-TW/common.json index d128313c17..d088dd7217 100644 --- a/apps/web/public/static/locales/zh-TW/common.json +++ b/apps/web/public/static/locales/zh-TW/common.json @@ -656,6 +656,7 @@ "default_duration": "預設時間長度", "default_duration_no_options": "請先選擇可預約的時間長度", "multiple_duration_mins": "{{count}} $t(minute_timeUnit)", + "multiple_duration_timeUnit": "{{count}} $t({{unit}}_timeUnit)", "minutes": "分鐘", "round_robin": "循環制", "round_robin_description": "與多位團隊成員進行週期會議。", diff --git a/packages/features/bookings/components/event-meta/Duration.tsx b/packages/features/bookings/components/event-meta/Duration.tsx index eda63e6e95..8d22ccaa1d 100644 --- a/packages/features/bookings/components/event-meta/Duration.tsx +++ b/packages/features/bookings/components/event-meta/Duration.tsx @@ -1,3 +1,4 @@ +import type { TFunction } from "next-i18next"; import { useEffect } from "react"; import { useBookerStore } from "@calcom/features/bookings/Booker/store"; @@ -7,6 +8,31 @@ import { Badge } from "@calcom/ui"; import type { PublicEvent } from "../../types"; +/** Render X mins as X hours or X hours Y mins instead of in minutes once >= 60 minutes */ +const getDurationFormatted = (mins: number, t: TFunction) => { + const hours = Math.floor(mins / 60); + mins %= 60; + // format minutes string + let minStr = ""; + if (mins > 0) { + minStr = + mins === 1 + ? t("minute_one", { count: 1 }) + : t("multiple_duration_timeUnit", { count: mins, unit: "minute" }); + } + // format hours string + let hourStr = ""; + if (hours > 0) { + hourStr = + hours === 1 + ? t("hour_one", { count: 1 }) + : t("multiple_duration_timeUnit", { count: hours, unit: "hour" }); + } + + if (hourStr && minStr) return `${hourStr} ${minStr}`; + return hourStr || minStr; +}; + export const EventDuration = ({ event }: { event: PublicEvent }) => { const { t } = useLocale(); const [selectedDuration, setSelectedDuration, state] = useBookerStore((state) => [ @@ -25,7 +51,7 @@ export const EventDuration = ({ event }: { event: PublicEvent }) => { }, [selectedDuration, setSelectedDuration, event.metadata?.multipleDuration, event.length, isDynamicEvent]); if (!event?.metadata?.multipleDuration && !isDynamicEvent) - return <>{t("multiple_duration_mins", { count: event.length })}; + return <>{getDurationFormatted(event.length, t)}; const durations = event?.metadata?.multipleDuration || [15, 30, 60]; @@ -39,7 +65,9 @@ export const EventDuration = ({ event }: { event: PublicEvent }) => { className={classNames(selectedDuration === duration && "bg-brand-default text-brand")} size="md" key={duration} - onClick={() => setSelectedDuration(duration)}>{`${duration} ${t("minute_timeUnit")}`} + onClick={() => setSelectedDuration(duration)}> + {getDurationFormatted(duration, t)} + ))} );