From b0530d59af0370819fdae2da17033adf7bcdc5e8 Mon Sep 17 00:00:00 2001
From: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Date: Wed, 19 Apr 2023 17:38:06 -0400
Subject: [PATCH] Remove Intl.Provider (#8208)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Add payment option to schema
* Add payment option to Stripe zod
* Set payment option on event type
* Create manual payment intent in Stripe
* Set payment option from Stripe app
* Add payment option to DB
* Pass React.ReactNode to checkbox
* Create uncaptured payment intent
* WIP
* Capture card in setup intent
* Show charge card option
* Charge card from booking page
* Bug fixes
* Clean up
* Clean up app card
* Add no-show fee messaging on booking page
* Send payment email on payment & add price
* Fix messaging
* Create no show fee charged email
* Send charge fee collected email
* Disable submit on card failure
* Clean up
* Serverside prevent charging card again if already charged
* Only confirm booking if paid for
* Type fixes
* More type fixes
* More type fixes
* Type fix
* Type fixes
* UI changes
* Payment component rework
* Update apps/web/public/static/locales/en/common.json
Co-authored-by: Alex van Andel
* Update apps/web/public/static/locales/en/common.json
Co-authored-by: Alex van Andel
* Update apps/web/components/dialog/ChargeCardDialog.tsx
Co-authored-by: Alex van Andel
* Update packages/trpc/server/routers/viewer/payments.tsx
Co-authored-by: Alex van Andel
* Revert GTM config
* Adjust payment option dropdown
* Show alert when seats are set
* Small bug fixes
* Create collect card method
* clean up
* Prevent seats & charge no-show fee to be enabled together
* Do not charge no-show fee on unconfirmed bookings
* Add check to collect card method
* Webhook send request emails
* Fix some dark mode colours
* Change awaiting payment language
* Type fixes
* Set height of Select and TextField both to 38px to fix alignment
* Fix message seats & payment error message
* Type fix
* Remove Intl.Provider
* Add percentFeePercentage
* WIP
* Use i18n language
* Type fix
---------
Co-authored-by: Alex van Andel
Co-authored-by: Omar López
---
apps/web/components/apps/App.tsx | 4 +--
.../booking/BookingDescriptionPayment.tsx | 29 +++++++++--------
.../booking/pages/AvailabilityPage.tsx | 27 +++++-----------
.../components/booking/pages/BookingPage.tsx | 2 +-
.../components/dialog/ChargeCardDialog.tsx | 32 ++++---------------
apps/web/public/static/locales/en/common.json | 4 +++
.../components/EventTypeAppCardInterface.tsx | 11 +++----
.../ee/payments/components/PaymentPage.tsx | 14 +++-----
.../components/EventTypeDescription.tsx | 19 ++++-------
9 files changed, 53 insertions(+), 89 deletions(-)
diff --git a/apps/web/components/apps/App.tsx b/apps/web/components/apps/App.tsx
index bef34e0e24..dfb9fad24b 100644
--- a/apps/web/components/apps/App.tsx
+++ b/apps/web/components/apps/App.tsx
@@ -41,7 +41,7 @@ const Component = ({
isTemplate,
dependencies,
}: Parameters[0]) => {
- const { t } = useLocale();
+ const { t, i18n } = useLocale();
const hasDescriptionItems = descriptionItems && descriptionItems.length > 0;
const router = useRouter();
@@ -247,7 +247,7 @@ const Component = ({
t("free_to_use_apps")
) : (
<>
- {Intl.NumberFormat("en-US", {
+ {Intl.NumberFormat(i18n.language, {
style: "currency",
currency: "USD",
useGrouping: false,
diff --git a/apps/web/components/booking/BookingDescriptionPayment.tsx b/apps/web/components/booking/BookingDescriptionPayment.tsx
index 9fe9478c15..2f9ef06652 100644
--- a/apps/web/components/booking/BookingDescriptionPayment.tsx
+++ b/apps/web/components/booking/BookingDescriptionPayment.tsx
@@ -1,5 +1,5 @@
+import { i18n } from "next-i18next";
import type { TFunction } from "next-i18next";
-import { FormattedNumber, IntlProvider } from "react-intl";
import getPaymentAppData from "@calcom/lib/getPaymentAppData";
import { CreditCard } from "@calcom/ui/components/icon";
@@ -7,28 +7,29 @@ import { CreditCard } from "@calcom/ui/components/icon";
const BookingDescriptionPayment = (props: {
eventType: Parameters[0];
t: TFunction;
+ i18n: typeof i18n;
}) => {
const paymentAppData = getPaymentAppData(props.eventType);
if (!paymentAppData || paymentAppData.price <= 0) return null;
+ const params = {
+ amount: paymentAppData.price / 100.0,
+ formatParams: { amount: { currency: paymentAppData.currency } },
+ };
+
return (
{paymentAppData.paymentOption === "HOLD" ? (
- <>
- {props.t("no_show_fee_amount", {
- amount: paymentAppData.price / 100.0,
- formatParams: { amount: { currency: paymentAppData.currency } },
- })}
- >
+ <>{props.t("no_show_fee_amount", params)}>
) : (
-
-
-
+ <>
+ {/* If undefined this will default to the browser locale */}
+ {new Intl.NumberFormat(i18n?.language, {
+ style: "currency",
+ currency: paymentAppData.currency,
+ }).format(paymentAppData.price / 100)}
+ >
)}
);
diff --git a/apps/web/components/booking/pages/AvailabilityPage.tsx b/apps/web/components/booking/pages/AvailabilityPage.tsx
index ee973fef46..9ed76360b4 100644
--- a/apps/web/components/booking/pages/AvailabilityPage.tsx
+++ b/apps/web/components/booking/pages/AvailabilityPage.tsx
@@ -1,7 +1,6 @@
import dynamic from "next/dynamic";
import { useRouter } from "next/router";
import { useEffect, useMemo, useReducer, useState } from "react";
-import { FormattedNumber, IntlProvider } from "react-intl";
import { z } from "zod";
import BookingPageTagManager from "@calcom/app-store/BookingPageTagManager";
@@ -75,7 +74,7 @@ const AvailabilityPage = ({ profile, eventType, ...restProps }: Props) => {
brandColor: profile.brandColor,
darkBrandColor: profile.darkBrandColor,
});
- const { t } = useLocale();
+ const { t, i18n } = useLocale();
const availabilityDatePickerEmbedStyles = useEmbedStyles("availabilityDatePicker");
//TODO: Plan to remove shouldAlignCentrallyInEmbed config
const shouldAlignCentrallyInEmbed = useEmbedNonStylesConfig("align") !== "left";
@@ -124,16 +123,7 @@ const AvailabilityPage = ({ profile, eventType, ...restProps }: Props) => {
[timeZone]
);
const paymentAppData = getPaymentAppData(eventType);
- const paymentAmount = () => {
- return;
-
-
- ;
- };
+
const rainbowAppData = getEventTypeAppData(eventType, "rainbow") || {};
const rawSlug = profile.slug ? profile.slug.split("/") : [];
if (rawSlug.length > 1) rawSlug.pop(); //team events have team name as slug, but user events have [user]/[type] as slug.
@@ -257,13 +247,12 @@ const AvailabilityPage = ({ profile, eventType, ...restProps }: Props) => {
})}
>
) : (
-
-
-
+ <>
+ {new Intl.NumberFormat(i18n.language, {
+ style: "currency",
+ currency: paymentAppData.currency,
+ }).format(paymentAppData.price / 100)}
+ >
)}
)}
diff --git a/apps/web/components/booking/pages/BookingPage.tsx b/apps/web/components/booking/pages/BookingPage.tsx
index 0de010846c..ff2dd7ca07 100644
--- a/apps/web/components/booking/pages/BookingPage.tsx
+++ b/apps/web/components/booking/pages/BookingPage.tsx
@@ -554,7 +554,7 @@ const BookingPage = ({
{showEventTypeDetails && (
-
+
{!rescheduleUid && eventType.recurringEvent?.freq && recurringEventCount && (
diff --git a/apps/web/components/dialog/ChargeCardDialog.tsx b/apps/web/components/dialog/ChargeCardDialog.tsx
index e2c6a06c89..0295f4ced4 100644
--- a/apps/web/components/dialog/ChargeCardDialog.tsx
+++ b/apps/web/components/dialog/ChargeCardDialog.tsx
@@ -1,7 +1,5 @@
-import { Trans } from "next-i18next";
import { useState } from "react";
import type { Dispatch, SetStateAction } from "react";
-import { IntlProvider, FormattedNumber } from "react-intl";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
@@ -40,6 +38,11 @@ export const ChargeCardDialog = (props: IRescheduleDialog) => {
},
});
+ const currencyStringParams = {
+ amount: props.paymentAmount / 100.0,
+ formatParams: { amount: { currency: props.paymentCurrency } },
+ };
+
return (
-
-
- You are about to charge the attendee{" "}
-
-
-
- . Are you sure you want to continue?
-
-
+
{t("charge_card_dialog_body", currencyStringParams)}
{chargeError && (
@@ -80,16 +71,7 @@ export const ChargeCardDialog = (props: IRescheduleDialog) => {
bookingId,
})
}>
-
- Charge attendee{" "}
-
-
-
-
+ {t("charge_attendee", currencyStringParams)}
diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json
index 124e675857..204a9fb4aa 100644
--- a/apps/web/public/static/locales/en/common.json
+++ b/apps/web/public/static/locales/en/common.json
@@ -1784,6 +1784,10 @@
"seats_and_no_show_fee_error": "Currently cannot enable seats and charge a no-show fee",
"complete_your_booking": "Complete your booking",
"complete_your_booking_subject": "Complete your booking: {{title}} on {{date}}",
+ "currency_string": "{{amount, currency}}",
+ "charge_card_dialog_body": "You are about to charge the attendee {{amount, currency}}. Are you sure you want to continue?",
+ "charge_attendee": "Charge attendee {{amount, currency}}",
+ "payment_app_commission": "Require payment ({{paymentFeePercentage}}% + {{fee, currency}} commission per transaction)",
"email_invite_team": "{{email}} has been invited",
"image_size_limit_exceed": "Uploaded image shouldn't exceed 5mb size limit"
}
diff --git a/packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx b/packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx
index 494f3ce196..f17473c7cc 100644
--- a/packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx
+++ b/packages/app-store/stripepayment/components/EventTypeAppCardInterface.tsx
@@ -1,6 +1,5 @@
import { useRouter } from "next/router";
import { useState } from "react";
-import { FormattedNumber, IntlProvider } from "react-intl";
import { useAppContextWithSchema } from "@calcom/app-store/EventTypeAppContext";
import AppCard from "@calcom/app-store/_components/AppCard";
@@ -47,11 +46,11 @@ const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({
description={
<>
- {t("require_payment")} (0.5% +{" "}
-
-
- {" "}
- {t("commission_per_transaction")})
+ {t("payment_app_commission", {
+ paymentFeePercentage: 0.5,
+ fee: 0.1,
+ formatParams: { fee: { currency } },
+ })}
>
}>
diff --git a/packages/features/ee/payments/components/PaymentPage.tsx b/packages/features/ee/payments/components/PaymentPage.tsx
index d551d16b56..62c73cddd2 100644
--- a/packages/features/ee/payments/components/PaymentPage.tsx
+++ b/packages/features/ee/payments/components/PaymentPage.tsx
@@ -2,7 +2,6 @@ import classNames from "classnames";
import Head from "next/head";
import type { FC } from "react";
import { useEffect, useState } from "react";
-import { FormattedNumber, IntlProvider } from "react-intl";
import { getSuccessPageLocationMessage } from "@calcom/app-store/locations";
import dayjs from "@calcom/dayjs";
@@ -19,7 +18,7 @@ import type { PaymentPageProps } from "../pages/payment";
import PaymentComponent from "./Payment";
const PaymentPage: FC
= (props) => {
- const { t } = useLocale();
+ const { t, i18n } = useLocale();
const [is24h, setIs24h] = useState(isBrowserLocale24h());
const [date, setDate] = useState(dayjs.utc(props.booking.startTime));
const [timezone, setTimezone] = useState(null);
@@ -107,13 +106,10 @@ const PaymentPage: FC = (props) => {
{props.payment.paymentOption === "HOLD" ? t("no_show_fee") : t("price")}
-
-
-
+ {new Intl.NumberFormat(i18n.language, {
+ style: "currency",
+ currency: paymentAppData.currency,
+ }).format(paymentAppData.price / 100.0)}
diff --git a/packages/features/eventtypes/components/EventTypeDescription.tsx b/packages/features/eventtypes/components/EventTypeDescription.tsx
index 5f4dfb5e00..26e6688b35 100644
--- a/packages/features/eventtypes/components/EventTypeDescription.tsx
+++ b/packages/features/eventtypes/components/EventTypeDescription.tsx
@@ -1,11 +1,9 @@
import type { Prisma } from "@prisma/client";
import { SchedulingType } from "@prisma/client";
import { useMemo } from "react";
-import { FormattedNumber, IntlProvider } from "react-intl";
import type { z } from "zod";
import { classNames, parseRecurringEvent } from "@calcom/lib";
-import getPaymentAppData from "@calcom/lib/getPaymentAppData";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { baseEventTypeSelect } from "@calcom/prisma";
import type { EventTypeModel } from "@calcom/prisma/zod";
@@ -32,15 +30,13 @@ export const EventTypeDescription = ({
shortenDescription,
isPublic,
}: EventTypeDescriptionProps) => {
- const { t } = useLocale();
+ const { t, i18n } = useLocale();
const recurringEvent = useMemo(
() => parseRecurringEvent(eventType.recurringEvent),
[eventType.recurringEvent]
);
- const stripeAppData = getPaymentAppData(eventType);
-
return (
<>
@@ -93,16 +89,13 @@ export const EventTypeDescription = ({
)}
- {stripeAppData.price > 0 && (
+ {eventType.price > 0 && (
-
-
-
+ {new Intl.NumberFormat(i18n.language, {
+ style: "currency",
+ currency: eventType.currency,
+ }).format(eventType.price / 100)}
)}