chore: i18n/extract strings (#934)

This commit is contained in:
Mihai C 2021-10-13 13:49:15 +03:00 committed by GitHub
parent bee41b242b
commit 9e2f8de313
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 139 additions and 72 deletions

View file

@ -4,6 +4,7 @@ import { useRouter } from "next/router";
import { useEffect } from "react"; import { useEffect } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { useLocale } from "@lib/hooks/useLocale";
import { useToggleQuery } from "@lib/hooks/useToggleQuery"; import { useToggleQuery } from "@lib/hooks/useToggleQuery";
import showToast from "@lib/notification"; import showToast from "@lib/notification";
import { trpc } from "@lib/trpc"; import { trpc } from "@lib/trpc";
@ -22,6 +23,7 @@ function convertMinsToHrsMins(mins: number) {
return `${hours}:${minutes}`; return `${hours}:${minutes}`;
} }
export default function Availability() { export default function Availability() {
const { t } = useLocale();
const queryMe = trpc.useQuery(["viewer.me"]); const queryMe = trpc.useQuery(["viewer.me"]);
const formModal = useToggleQuery("edit"); const formModal = useToggleQuery("edit");
@ -57,27 +59,25 @@ export default function Availability() {
return <Loader />; return <Loader />;
} }
if (queryMe.status !== "success") { if (queryMe.status !== "success") {
return <Alert severity="error" title="Something went wrong" />; return <Alert severity="error" title={t("something_went_wrong")} />;
} }
const user = queryMe.data; const user = queryMe.data;
return ( return (
<div> <div>
<Shell heading="Availability" subtitle="Configure times when you are available for bookings."> <Shell heading={t("availability")} subtitle={t("configure_availability")}>
<div className="flex"> <div className="flex">
<div className="w-1/2 mr-2 bg-white border border-gray-200 rounded-sm"> <div className="w-1/2 mr-2 bg-white border border-gray-200 rounded-sm">
<div className="px-4 py-5 sm:p-6"> <div className="px-4 py-5 sm:p-6">
<h3 className="text-lg leading-6 font-medium text-gray-900"> <h3 className="text-lg leading-6 font-medium text-gray-900">{t("change_start_end")}</h3>
Change the start and end times of your day
</h3>
<div className="mt-2 max-w-xl text-sm text-gray-500"> <div className="mt-2 max-w-xl text-sm text-gray-500">
<p> <p>
Currently, your day is set to start at {convertMinsToHrsMins(user.startTime)} and end at{" "} {t("current_start_date")} {convertMinsToHrsMins(user.startTime)} {t("and_end_at")}{" "}
{convertMinsToHrsMins(user.endTime)}. {convertMinsToHrsMins(user.endTime)}.
</p> </p>
</div> </div>
<div className="mt-5"> <div className="mt-5">
<Button href={formModal.hrefOn}>Change available times</Button> <Button href={formModal.hrefOn}>{t("change_available_times")}</Button>
</div> </div>
</div> </div>
</div> </div>
@ -85,14 +85,14 @@ export default function Availability() {
<div className="w-1/2 ml-2 border border-gray-200 rounded-sm"> <div className="w-1/2 ml-2 border border-gray-200 rounded-sm">
<div className="px-4 py-5 sm:p-6"> <div className="px-4 py-5 sm:p-6">
<h3 className="text-lg leading-6 font-medium text-gray-900"> <h3 className="text-lg leading-6 font-medium text-gray-900">
Something doesn&apos;t look right? {t("something_doesnt_look_right")}
</h3> </h3>
<div className="mt-2 max-w-xl text-sm text-gray-500"> <div className="mt-2 max-w-xl text-sm text-gray-500">
<p>Troubleshoot your availability to explore why your times are showing as they are.</p> <p>{t("troubleshoot_availability")}</p>
</div> </div>
<div className="mt-5"> <div className="mt-5">
<Link href="/availability/troubleshoot"> <Link href="/availability/troubleshoot">
<a className="btn btn-white">Launch troubleshooter</a> <a className="btn btn-white">{t("launch_troubleshooter")}</a>
</Link> </Link>
</div> </div>
</div> </div>
@ -111,12 +111,10 @@ export default function Availability() {
</div> </div>
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> <div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 className="text-lg leading-6 font-medium text-gray-900" id="modal-title"> <h3 className="text-lg leading-6 font-medium text-gray-900" id="modal-title">
Change your available times {t("change_your_available_times")}
</h3> </h3>
<div> <div>
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">{t("change_start_end_buffer")}</p>
Set the start and end time of your day and a minimum buffer between your meetings.
</p>
</div> </div>
</div> </div>
</div> </div>
@ -136,19 +134,21 @@ export default function Availability() {
}, },
}); });
if (!response.ok) { if (!response.ok) {
showToast("Something went wrong", "error"); showToast(t("something_went_wrong"), "error");
return; return;
} }
await queryMe.refetch(); await queryMe.refetch();
router.push(formModal.hrefOff); router.push(formModal.hrefOff);
showToast("The start and end times for your day have been changed successfully.", "success"); showToast(t("start_end_changed_successfully"), "success");
})}> })}>
<div className="flex mb-4"> <div className="flex mb-4">
<label className="w-1/4 pt-2 block text-sm font-medium text-gray-700">Start time</label> <label className="w-1/4 pt-2 block text-sm font-medium text-gray-700">
{t("start_time")}
</label>
<div> <div>
<label htmlFor="startHours" className="sr-only"> <label htmlFor="startHours" className="sr-only">
Hours {t("hours")}
</label> </label>
<input <input
{...formMethods.register("startHours")} {...formMethods.register("startHours")}
@ -162,7 +162,7 @@ export default function Availability() {
<span className="mx-2 pt-1">:</span> <span className="mx-2 pt-1">:</span>
<div> <div>
<label htmlFor="startMins" className="sr-only"> <label htmlFor="startMins" className="sr-only">
Minutes {t("minutes")}
</label> </label>
<input <input
{...formMethods.register("startMins")} {...formMethods.register("startMins")}
@ -174,10 +174,10 @@ export default function Availability() {
</div> </div>
</div> </div>
<div className="flex mb-4"> <div className="flex mb-4">
<label className="w-1/4 pt-2 block text-sm font-medium text-gray-700">End time</label> <label className="w-1/4 pt-2 block text-sm font-medium text-gray-700">{t("end_time")}</label>
<div> <div>
<label htmlFor="endHours" className="sr-only"> <label htmlFor="endHours" className="sr-only">
Hours {t("hours")}
</label> </label>
<input <input
{...formMethods.register("endHours")} {...formMethods.register("endHours")}
@ -190,7 +190,7 @@ export default function Availability() {
<span className="mx-2 pt-1">:</span> <span className="mx-2 pt-1">:</span>
<div> <div>
<label htmlFor="endMins" className="sr-only"> <label htmlFor="endMins" className="sr-only">
Minutes {t("minutes")}
</label> </label>
<input <input
{...formMethods.register("endMins")} {...formMethods.register("endMins")}
@ -202,10 +202,10 @@ export default function Availability() {
</div> </div>
</div> </div>
<div className="flex mb-4"> <div className="flex mb-4">
<label className="w-1/4 pt-2 block text-sm font-medium text-gray-700">Buffer</label> <label className="w-1/4 pt-2 block text-sm font-medium text-gray-700">{t("buffer")}</label>
<div> <div>
<label htmlFor="bufferHours" className="sr-only"> <label htmlFor="bufferHours" className="sr-only">
Hours {t("hours")}
</label> </label>
<input <input
{...formMethods.register("bufferHours")} {...formMethods.register("bufferHours")}
@ -218,7 +218,7 @@ export default function Availability() {
<span className="mx-2 pt-1">:</span> <span className="mx-2 pt-1">:</span>
<div> <div>
<label htmlFor="bufferMins" className="sr-only"> <label htmlFor="bufferMins" className="sr-only">
Minutes {t("minutes")}
</label> </label>
<input <input
{...formMethods.register("bufferMins")} {...formMethods.register("bufferMins")}
@ -231,10 +231,10 @@ export default function Availability() {
</div> </div>
<div className="mt-5 sm:mt-4 sm:flex space-x-2"> <div className="mt-5 sm:mt-4 sm:flex space-x-2">
<Button href={formModal.hrefOff} color="secondary" tabIndex={-1}> <Button href={formModal.hrefOff} color="secondary" tabIndex={-1}>
Cancel {t("cancel")}
</Button> </Button>
<Button type="submit" loading={formMethods.formState.isSubmitting}> <Button type="submit" loading={formMethods.formState.isSubmitting}>
Update {t("update")}
</Button> </Button>
</div> </div>
</form> </form>

View file

@ -1,9 +1,12 @@
import dayjs from "dayjs"; import dayjs from "dayjs";
import utc from "dayjs/plugin/utc"; import utc from "dayjs/plugin/utc";
import { GetServerSidePropsContext } from "next"; import { GetServerSidePropsContext } from "next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { getSession } from "@lib/auth"; import { getSession } from "@lib/auth";
import { getOrSetUserLocaleFromHeaders } from "@lib/core/i18n/i18n.utils";
import { useLocale } from "@lib/hooks/useLocale";
import prisma from "@lib/prisma"; import prisma from "@lib/prisma";
import { inferSSRProps } from "@lib/types/inferSSRProps"; import { inferSSRProps } from "@lib/types/inferSSRProps";
@ -13,6 +16,7 @@ import Shell from "@components/Shell";
dayjs.extend(utc); dayjs.extend(utc);
export default function Troubleshoot({ user }: inferSSRProps<typeof getServerSideProps>) { export default function Troubleshoot({ user }: inferSSRProps<typeof getServerSideProps>) {
const { t } = useLocale();
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [availability, setAvailability] = useState([]); const [availability, setAvailability] = useState([]);
const [selectedDate, setSelectedDate] = useState(dayjs()); const [selectedDate, setSelectedDate] = useState(dayjs());
@ -52,12 +56,10 @@ export default function Troubleshoot({ user }: inferSSRProps<typeof getServerSid
return ( return (
<div> <div>
<Shell <Shell heading={t("troubleshoot")} subtitle={t("troubleshoot_description")}>
heading="Troubleshoot"
subtitle="Understand why certain times are available and others are blocked.">
<div className="bg-white max-w-xl overflow-hidden shadow rounded-sm"> <div className="bg-white max-w-xl overflow-hidden shadow rounded-sm">
<div className="px-4 py-5 sm:p-6"> <div className="px-4 py-5 sm:p-6">
Here is an overview of your day on{" "} {t("overview_of_day")}{" "}
<input <input
type="date" type="date"
className="inline border-none h-8 p-0" className="inline border-none h-8 p-0"
@ -66,34 +68,33 @@ export default function Troubleshoot({ user }: inferSSRProps<typeof getServerSid
setSelectedDate(dayjs(e.target.value)); setSelectedDate(dayjs(e.target.value));
}} }}
/> />
<small className="block text-neutral-400"> <small className="block text-neutral-400">{t("hover_over_bold_times_tip")}</small>
Tip: Hover over the bold times for a full timestamp
</small>
<div className="mt-4 space-y-4"> <div className="mt-4 space-y-4">
<div className="bg-black overflow-hidden rounded-sm"> <div className="bg-black overflow-hidden rounded-sm">
<div className="px-4 sm:px-6 py-2 text-white"> <div className="px-4 sm:px-6 py-2 text-white">
Your day starts at {convertMinsToHrsMins(user.startTime)} {t("your_day_starts_at")} {convertMinsToHrsMins(user.startTime)}
</div> </div>
</div> </div>
{availability.map((slot) => ( {availability.map((slot) => (
<div key={slot.start} className="bg-neutral-100 overflow-hidden rounded-sm"> <div key={slot.start} className="bg-neutral-100 overflow-hidden rounded-sm">
<div className="px-4 py-5 sm:p-6 text-black"> <div className="px-4 py-5 sm:p-6 text-black">
Your calendar shows you as busy between{" "} {t("calendar_shows_busy_between")}{" "}
<span className="font-medium text-neutral-800" title={slot.start}> <span className="font-medium text-neutral-800" title={slot.start}>
{dayjs(slot.start).format("HH:mm")} {dayjs(slot.start).format("HH:mm")}
</span>{" "} </span>{" "}
and{" "} {t("and")}{" "}
<span className="font-medium text-neutral-800" title={slot.end}> <span className="font-medium text-neutral-800" title={slot.end}>
{dayjs(slot.end).format("HH:mm")} {dayjs(slot.end).format("HH:mm")}
</span>{" "} </span>{" "}
on {dayjs(slot.start).format("D MMMM YYYY")} {t("on")} {dayjs(slot.start).format("D")}{" "}
{t(dayjs(slot.start).format("MMMM").toLowerCase())} {dayjs(slot.start).format("YYYY")}
</div> </div>
</div> </div>
))} ))}
{availability.length === 0 && <Loader />} {availability.length === 0 && <Loader />}
<div className="bg-black overflow-hidden rounded-sm"> <div className="bg-black overflow-hidden rounded-sm">
<div className="px-4 sm:px-6 py-2 text-white"> <div className="px-4 sm:px-6 py-2 text-white">
Your day ends at {convertMinsToHrsMins(user.endTime)} {t("your_day_ends_at")} {convertMinsToHrsMins(user.endTime)}
</div> </div>
</div> </div>
</div> </div>
@ -106,6 +107,8 @@ export default function Troubleshoot({ user }: inferSSRProps<typeof getServerSid
export const getServerSideProps = async (context: GetServerSidePropsContext) => { export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const session = await getSession(context); const session = await getSession(context);
const locale = await getOrSetUserLocaleFromHeaders(context.req);
if (!session?.user?.id) { if (!session?.user?.id) {
return { redirect: { permanent: false, destination: "/auth/login" } }; return { redirect: { permanent: false, destination: "/auth/login" } };
} }
@ -124,6 +127,10 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
if (!user) return { redirect: { permanent: false, destination: "/auth/login" } }; if (!user) return { redirect: { permanent: false, destination: "/auth/login" } };
return { return {
props: { session, user }, props: {
session,
user,
...(await serverSideTranslations(locale, ["common"])),
},
}; };
}; };

View file

@ -2,6 +2,7 @@ import { CalendarIcon } from "@heroicons/react/outline";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { QueryCell } from "@lib/QueryCell"; import { QueryCell } from "@lib/QueryCell";
import { useLocale } from "@lib/hooks/useLocale";
import { inferQueryInput, trpc } from "@lib/trpc"; import { inferQueryInput, trpc } from "@lib/trpc";
import BookingsShell from "@components/BookingsShell"; import BookingsShell from "@components/BookingsShell";
@ -11,19 +12,21 @@ import BookingListItem from "@components/booking/BookingListItem";
type BookingListingStatus = inferQueryInput<"viewer.bookings">["status"]; type BookingListingStatus = inferQueryInput<"viewer.bookings">["status"];
export default function Bookings() {
const { t } = useLocale();
const descriptionByStatus: Record<BookingListingStatus, string> = { const descriptionByStatus: Record<BookingListingStatus, string> = {
upcoming: "As soon as someone books a time with you it will show up here.", upcoming: t("upcoming_bookings"),
past: "Your past bookings will show up here.", past: t("past_bookings"),
cancelled: "Your cancelled bookings will show up here.", cancelled: t("cancelled_bookings"),
}; };
export default function Bookings() {
const router = useRouter(); const router = useRouter();
const status = router.query?.status as BookingListingStatus; const status = router.query?.status as BookingListingStatus;
const query = trpc.useQuery(["viewer.bookings", { status }]); const query = trpc.useQuery(["viewer.bookings", { status }]);
return ( return (
<Shell heading="Bookings" subtitle="See upcoming and past events booked through your event type links."> <Shell heading={t("bookings")} subtitle={t("bookings_description")}>
<BookingsShell> <BookingsShell>
<div className="-mx-4 sm:mx-auto flex flex-col"> <div className="-mx-4 sm:mx-auto flex flex-col">
<div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8"> <div className="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
@ -44,8 +47,11 @@ export default function Bookings() {
empty={() => ( empty={() => (
<EmptyScreen <EmptyScreen
Icon={CalendarIcon} Icon={CalendarIcon}
headline={`No ${status} bookings, yet`} headline={t("no_status_bookings_yet", { status: status })}
description={`You have no ${status} bookings. ${descriptionByStatus[status]}`} description={t("no_status_bookings_yet_description", {
status: status,
description: descriptionByStatus[status],
})}
/> />
)} )}
/> />

View file

@ -1,13 +1,17 @@
import { XIcon } from "@heroicons/react/outline"; import { XIcon } from "@heroicons/react/outline";
import { ArrowRightIcon } from "@heroicons/react/solid"; import { ArrowRightIcon } from "@heroicons/react/solid";
import { useLocale } from "@lib/hooks/useLocale";
import { HeadSeo } from "@components/seo/head-seo"; import { HeadSeo } from "@components/seo/head-seo";
import Button from "@components/ui/Button"; import Button from "@components/ui/Button";
export default function NoMeetingFound() { export default function NoMeetingFound() {
const { t } = useLocale();
return ( return (
<div> <div>
<HeadSeo title={`No meeting found`} description={`No Meeting found`} /> <HeadSeo title={t("no_meeting_found")} description={t("no_meeting_found")} />
<main className="max-w-3xl mx-auto my-24"> <main className="max-w-3xl mx-auto my-24">
<div className="fixed inset-0 z-50 overflow-y-auto"> <div className="fixed inset-0 z-50 overflow-y-auto">
<div className="flex items-end justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0"> <div className="flex items-end justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0">
@ -26,19 +30,17 @@ export default function NoMeetingFound() {
</div> </div>
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline"> <h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline">
No Meeting Found {t("no_meeting_found")}
</h3> </h3>
</div> </div>
<div className="mt-2"> <div className="mt-2">
<p className="text-sm text-center text-gray-500"> <p className="text-sm text-center text-gray-500">{t("no_meeting_found_description")}</p>
This meeting does not exist. Contact the meeting owner for an updated link.
</p>
</div> </div>
</div> </div>
<div className="mt-5 text-center sm:mt-6"> <div className="mt-5 text-center sm:mt-6">
<div className="mt-5"> <div className="mt-5">
<Button data-testid="return-home" href="/event-types" EndIcon={ArrowRightIcon}> <Button data-testid="return-home" href="/event-types" EndIcon={ArrowRightIcon}>
Go back home {t("go_back_home")}
</Button> </Button>
</div> </div>
</div> </div>

View file

@ -2,9 +2,12 @@ import { CalendarIcon, XIcon } from "@heroicons/react/solid";
import dayjs from "dayjs"; import dayjs from "dayjs";
import utc from "dayjs/plugin/utc"; import utc from "dayjs/plugin/utc";
import { getSession } from "next-auth/client"; import { getSession } from "next-auth/client";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useState } from "react"; import { useState } from "react";
import { getOrSetUserLocaleFromHeaders } from "@lib/core/i18n/i18n.utils";
import { useLocale } from "@lib/hooks/useLocale";
import prisma from "@lib/prisma"; import prisma from "@lib/prisma";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@lib/telemetry";
@ -14,6 +17,7 @@ import { Button } from "@components/ui/Button";
dayjs.extend(utc); dayjs.extend(utc);
export default function Type(props) { export default function Type(props) {
const { t } = useLocale();
// Get router variables // Get router variables
const router = useRouter(); const router = useRouter();
const { uid } = router.query; const { uid } = router.query;
@ -21,7 +25,7 @@ export default function Type(props) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const [is24h, setIs24h] = useState(false); const [is24h, setIs24h] = useState(false);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(props.booking ? null : "This booking was already cancelled"); const [error, setError] = useState(props.booking ? null : t("booking_already_cancelled"));
const telemetry = useTelemetry(); const telemetry = useTelemetry();
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
@ -52,15 +56,15 @@ export default function Type(props) {
); );
} else { } else {
setLoading(false); setLoading(false);
setError("An error with status code " + res.status + " occurred. Please try again later."); setError(`${t("error_with_status_code_occured", { status: res.status })} ${t("please_try_again")}`);
} }
}; };
return ( return (
<div> <div>
<HeadSeo <HeadSeo
title={`Cancel ${props.booking && props.booking.title} | ${props.profile.name}`} title={`${t("cancel")} ${props.booking && props.booking.title} | ${props.profile.name}`}
description={`Cancel ${props.booking && props.booking.title} | ${props.profile.name}`} description={`${t("cancel")} ${props.booking && props.booking.title} | ${props.profile.name}`}
/> />
<main className="max-w-3xl mx-auto my-24"> <main className="max-w-3xl mx-auto my-24">
<div className="fixed inset-0 z-50 overflow-y-auto"> <div className="fixed inset-0 z-50 overflow-y-auto">
@ -95,14 +99,12 @@ export default function Type(props) {
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline"> <h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-headline">
{props.cancellationAllowed {props.cancellationAllowed
? "Really cancel your booking?" ? t("really_cancel_booking")
: "You cannot cancel this booking"} : t("cannot_cancel_booking")}
</h3> </h3>
<div className="mt-2"> <div className="mt-2">
<p className="text-sm text-gray-500"> <p className="text-sm text-gray-500">
{props.cancellationAllowed {props.cancellationAllowed ? t("reschedule_instead") : t("event_is_in_the_past")}
? "Instead, you could also reschedule it."
: "The event is in the past"}
</p> </p>
</div> </div>
<div className="py-4 mt-4 border-t border-b"> <div className="py-4 mt-4 border-t border-b">
@ -125,9 +127,9 @@ export default function Type(props) {
data-testid="cancel" data-testid="cancel"
onClick={cancellationHandler} onClick={cancellationHandler}
loading={loading}> loading={loading}>
Cancel {t("cancel")}
</Button> </Button>
<Button onClick={() => router.push("/reschedule/" + uid)}>Reschedule</Button> <Button onClick={() => router.push("/reschedule/" + uid)}>{t("reschedule")}</Button>
</div> </div>
)} )}
</> </>
@ -143,6 +145,7 @@ export default function Type(props) {
export async function getServerSideProps(context) { export async function getServerSideProps(context) {
const session = await getSession(context); const session = await getSession(context);
const locale = await getOrSetUserLocaleFromHeaders(context.req);
const booking = await prisma.booking.findUnique({ const booking = await prisma.booking.findUnique({
where: { where: {
uid: context.query.uid, uid: context.query.uid,
@ -199,6 +202,7 @@ export async function getServerSideProps(context) {
booking: bookingObj, booking: bookingObj,
cancellationAllowed: cancellationAllowed:
(!!session?.user && session.user.id == booking.user?.id) || booking.startTime >= new Date(), (!!session?.user && session.user.id == booking.user?.id) || booking.startTime >= new Date(),
...(await serverSideTranslations(locale, ["common"])),
}, },
}; };
} }

View file

@ -3,17 +3,23 @@ import { ArrowRightIcon } from "@heroicons/react/solid";
import { useSession } from "next-auth/client"; import { useSession } from "next-auth/client";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useLocale } from "@lib/hooks/useLocale";
import { HeadSeo } from "@components/seo/head-seo"; import { HeadSeo } from "@components/seo/head-seo";
import Button from "@components/ui/Button"; import Button from "@components/ui/Button";
export default function CancelSuccess() { export default function CancelSuccess() {
const { t } = useLocale();
// Get router variables // Get router variables
const router = useRouter(); const router = useRouter();
const { title, name, eventPage } = router.query; const { title, name, eventPage } = router.query;
const [session, loading] = useSession(); const [session, loading] = useSession();
return ( return (
<div> <div>
<HeadSeo title={`Cancelled ${title} | ${name}`} description={`Cancelled ${title} | ${name}`} /> <HeadSeo
title={`${t("cancelled")} ${title} | ${name}`}
description={`${t("cancelled")} ${title} | ${name}`}
/>
<main className="max-w-3xl mx-auto my-24"> <main className="max-w-3xl mx-auto my-24">
<div className="fixed z-50 inset-0 overflow-y-auto"> <div className="fixed z-50 inset-0 overflow-y-auto">
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> <div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
@ -32,11 +38,11 @@ export default function CancelSuccess() {
</div> </div>
<div className="mt-3 text-center sm:mt-5"> <div className="mt-3 text-center sm:mt-5">
<h3 className="text-lg leading-6 font-medium text-gray-900" id="modal-headline"> <h3 className="text-lg leading-6 font-medium text-gray-900" id="modal-headline">
Cancellation successful {t("cancellation_successful")}
</h3> </h3>
{!loading && !session.user && ( {!loading && !session.user && (
<div className="mt-2"> <div className="mt-2">
<p className="text-sm text-gray-500">Feel free to pick another event anytime.</p> <p className="text-sm text-gray-500">{t("free_to_pick_another_event_type")}</p>
</div> </div>
)} )}
</div> </div>
@ -46,7 +52,7 @@ export default function CancelSuccess() {
{!loading && !session.user && <Button href={eventPage}>Pick another</Button>} {!loading && !session.user && <Button href={eventPage}>Pick another</Button>}
{!loading && session.user && ( {!loading && session.user && (
<Button data-testid="back-to-bookings" href="/bookings" EndIcon={ArrowRightIcon}> <Button data-testid="back-to-bookings" href="/bookings" EndIcon={ArrowRightIcon}>
Back to bookings {t("back_to_bookings")}
</Button> </Button>
)} )}
</div> </div>

View file

@ -1,4 +1,45 @@
{ {
"back_to_bookings": "Back to bookings",
"free_to_pick_another_event_type": "Feel free to pick another event anytime.",
"cancelled": "Cancelled",
"cancellation_successful": "Cancellation successful",
"really_cancel_booking": "Really cancel your booking?",
"cannot_cancel_booking": "You cannot cancel this booking",
"reschedule_instead": "Instead, you could also reschedule it.",
"event_is_in_the_past": "The event is in the past",
"error_with_status_code_occured": "An error with status code {{status}} occurred.",
"booking_already_cancelled": "This booking was already cancelled",
"go_back_home": "Go back home",
"no_meeting_found": "No Meeting Found",
"no_meeting_found_description": "This meeting does not exist. Contact the meeting owner for an updated link.",
"no_status_bookings_yet": "No {{status}} bookings, yet",
"no_status_bookings_yet_description": "You have no {{status}} bookings. {{description}}",
"bookings": "Bookings",
"bookings_description": "See upcoming and past events booked through your event type links.",
"upcoming_bookings": "As soon as someone books a time with you it will show up here.",
"past_bookings": "Your past bookings will show up here.",
"cancelled_bookings": "Your cancelled bookings will show up here.",
"on": "on",
"and": "and",
"calendar_shows_busy_between": "Your calendar shows you as busy between",
"troubleshoot": "Troubleshoot",
"troubleshoot_description": "Understand why certain times are available and others are blocked.",
"overview_of_day": "Here is an overview of your day on",
"hover_over_bold_times_tip": "Tip: Hover over the bold times for a full timestamp",
"start_time": "Start time",
"end_time": "End time",
"buffer": "Buffer",
"your_day_starts_at": "Your day starts at",
"your_day_ends_at": "Your day ends at",
"launch_troubleshooter": "Launch troubleshooter",
"troubleshoot_availability": "Troubleshoot your availability to explore why your times are showing as they are.",
"change_available_times": "Change available times",
"change_your_available_times": "Change your available times",
"change_start_end": "Change the start and end times of your day",
"change_start_end_buffer": "Set the start and end time of your day and a minimum buffer between your meetings.",
"current_start_date": "Currently, your day is set to start at",
"start_end_changed_successfully": "The start and end times for your day have been changed successfully.",
"and_end_at": "and end at",
"light": "Light", "light": "Light",
"dark": "Dark", "dark": "Dark",
"automatically_adjust_theme": "Automatically adjust theme based on invitee preferences", "automatically_adjust_theme": "Automatically adjust theme based on invitee preferences",
@ -50,6 +91,7 @@
"password_has_been_changed": "Your password has been successfully changed.", "password_has_been_changed": "Your password has been successfully changed.",
"error_changing_password": "Error changing password", "error_changing_password": "Error changing password",
"something_went_wrong": "Something went wrong", "something_went_wrong": "Something went wrong",
"something_doesnt_look_right": "Something doesn't look right?",
"please_try_again": "Please try again", "please_try_again": "Please try again",
"super_secure_new_password": "Your super secure new password", "super_secure_new_password": "Your super secure new password",
"new_password": "New Password", "new_password": "New Password",
@ -158,7 +200,7 @@
"collective": "Collective", "collective": "Collective",
"collective_description": "Schedule meetings when all selected team members are available.", "collective_description": "Schedule meetings when all selected team members are available.",
"duration": "Duration", "duration": "Duration",
"minutes": "minutes", "minutes": "Minutes",
"round_robin": "Round Robin", "round_robin": "Round Robin",
"round_robin_description": "Cycle meetings between multiple team members.", "round_robin_description": "Cycle meetings between multiple team members.",
"url": "URL", "url": "URL",
@ -210,7 +252,7 @@
"billing": "Billing", "billing": "Billing",
"manage_your_billing_info": "Manage your billing information and cancel your subscription.", "manage_your_billing_info": "Manage your billing information and cancel your subscription.",
"availability": "Availability", "availability": "Availability",
"configure_times_available_bookings": "Configure times when you are available for bookings.", "configure_availability": "Configure times when you are available for bookings.",
"change_weekly_schedule": "Change your weekly schedule", "change_weekly_schedule": "Change your weekly schedule",
"logo": "Logo", "logo": "Logo",
"error": "Error", "error": "Error",