Availability and booking info text format fixes (#4000)

* Recurring info format

* More mismatch visual bugs when booking

* More tweaks

* Prettier

* Prettier cont

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Leo Giovanetti 2022-08-29 13:01:45 -03:00 committed by GitHub
parent 00c00a9aee
commit e4e4ec5ffc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 113 additions and 102 deletions

View File

@ -1,9 +1,10 @@
import { getEventLocationType, locationKeyToString } from "@calcom/app-store/locations";
import { classNames } from "@calcom/lib";
import { Props } from "./pages/AvailabilityPage";
export function AvailableEventLocations({ locations }: { locations: Props["eventType"]["locations"] }) {
return (
return locations.length ? (
<div>
<div className="flex-warp mr-6 flex break-words text-sm text-gray-600 dark:text-white">
<p className="w-full">
@ -14,10 +15,13 @@ export function AvailableEventLocations({ locations }: { locations: Props["event
return null;
}
return (
<span key={location.type} className="flex flex-row items-center pt-1">
<span key={location.type} className="flex flex-row items-center text-sm font-medium">
<img
src={eventLocationType.iconUrl}
className="mr-[10px] ml-[2px] h-4 w-4"
className={classNames(
"mr-[10px] ml-[2px] h-4 w-4 opacity-70 dark:opacity-100",
!eventLocationType.iconUrl?.includes("api") ? "dark:invert" : ""
)}
alt={`${eventLocationType.label} icon`}
/>
<span key={location.type}>{locationKeyToString(location)} </span>
@ -27,5 +31,7 @@ export function AvailableEventLocations({ locations }: { locations: Props["event
</p>
</div>
</div>
) : (
<></>
);
}

View File

@ -239,15 +239,15 @@ function TimezoneDropdown({
};
return (
<Collapsible.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen}>
<Collapsible.Trigger className="min-w-32 dark:text-darkgray-600 mb-1 -ml-2 px-2 py-1 text-left text-gray-600">
<p className="py-1 text-sm font-medium ">
<Icon.FiGlobe className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
<Collapsible.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen} className="flex">
<Collapsible.Trigger className="min-w-32 mb-2 -ml-2 px-2 text-left text-gray-600 dark:text-white">
<p className="text-sm font-medium">
<Icon.FiGlobe className="mr-[10px] ml-[2px] -mt-[2px] inline-block h-4 w-4" />
{timeZone}
{isTimeOptionsOpen ? (
<Icon.FiChevronUp className="ml-1 -mt-1 inline-block h-4 w-4 " />
<Icon.FiChevronUp className="ml-1 inline-block h-4 w-4 " />
) : (
<Icon.FiChevronDown className="ml-1 -mt-1 inline-block h-4 w-4 " />
<Icon.FiChevronDown className="ml-1 inline-block h-4 w-4 " />
)}
</p>
</Collapsible.Trigger>
@ -379,10 +379,7 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
shouldAlignCentrally ? "mx-auto" : "",
isEmbed
? classNames(maxWidth)
: classNames(
"transition-max-width dark:bg- mx-auto my-0 duration-500 ease-in-out md:my-24",
maxWidth
)
: classNames("transition-max-width mx-auto my-0 duration-500 ease-in-out md:my-24", maxWidth)
)}>
<div
style={availabilityDatePickerEmbedStyles}
@ -411,27 +408,27 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
</h1>
<div className="flex flex-col space-y-2">
{eventType?.description && (
<div className="dark:text-darkgray-600 flex py-1 text-sm font-medium text-gray-600">
<div className="flex py-1 text-sm font-medium text-gray-600 dark:text-white">
<div>
<Icon.FiInfo className="dark:text-darkgray-600 mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-400" />
<Icon.FiInfo className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
</div>
<EventTypeDescriptionSafeHTML eventType={eventType} />
</div>
)}
{eventType?.requiresConfirmation && (
<p className="dark:text-darkgray-600 text-gray-600">
<Icon.FiCheckSquare className="dark:text-darkgray-600 mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
<p className="dark:text-darkgray-600 text-gray-600 dark:text-white">
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
{t("requires_confirmation")}
</p>
)}
<AvailableEventLocations locations={eventType.locations} />
<p className="text-gray-600 dark:text-white">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4 text-gray-500" />
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
{eventType.length} {t("minutes")}
</p>
{eventType.price > 0 && (
<div className="dark:text-darkgray-600 text-gray-600">
<Icon.FiCreditCard className="dark:text-darkgray-600 mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<div className="text-gray-600 dark:text-white">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<IntlProvider locale="en">
<FormattedNumber
value={eventType.price / 100.0}
@ -511,15 +508,15 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
</h1>
<div className="flex flex-col space-y-2">
{eventType?.description && (
<div className="dark:text-darkgray-600 flex py-1 text-sm font-medium text-gray-600">
<div className="flex text-sm font-medium text-gray-600 dark:text-white">
<div>
<Icon.FiInfo className="dark:text-darkgray-600 mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
<Icon.FiInfo className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
</div>
<EventTypeDescriptionSafeHTML eventType={eventType} />
</div>
)}
{eventType?.requiresConfirmation && (
<div className="dark:text-darkgray-600 flex items-center text-sm font-medium text-gray-600">
<div className="flex items-center text-sm font-medium text-gray-600 dark:text-white">
<div>
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
</div>
@ -527,13 +524,13 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
</div>
)}
<AvailableEventLocations locations={eventType.locations} />
<p className="py-1 text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4 text-gray-500" />
<p className="text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
{eventType.length} {t("minutes")}
</p>
{!rescheduleUid && eventType.recurringEvent && (
<div className="dark:text-darkgray-600 flex items-center text-gray-600">
<Icon.FiRefreshCcw className="float-left mr-[10px] mt-1 ml-[2px] inline-block h-4 w-4 " />
<div className="flex items-start text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiRefreshCcw className="float-left mr-[10px] mt-[7px] ml-[2px] inline-block h-4 w-4 " />
<div>
<p className="mb-1 -ml-2 inline px-2 py-1">
{getRecurringFreq({ t, recurringEvent: eventType.recurringEvent })}
@ -542,13 +539,13 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
type="number"
min="1"
max={eventType.recurringEvent.count}
className="w-15 dark:text-darkgray-600 h-7 rounded-sm border-gray-300 bg-white text-sm text-gray-600 [appearance:textfield] ltr:mr-2 rtl:ml-2 dark:border-gray-500 dark:bg-gray-600"
className="w-15 dark:bg-darkgray-200 h-7 rounded-sm border-gray-300 bg-white text-sm font-medium [appearance:textfield] ltr:mr-2 rtl:ml-2 dark:border-gray-500"
defaultValue={eventType.recurringEvent.count}
onChange={(event) => {
setRecurringEventCount(parseInt(event?.target.value));
}}
/>
<p className="dark:text-darkgray-600 inline text-gray-600">
<p className="inline">
{t("occurrence", {
count: recurringEventCount,
})}
@ -557,7 +554,7 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
</div>
)}
{eventType.price > 0 && (
<p className="dark:text-darkgray-600 -ml-2 px-2 py-1 text-gray-600">
<p className="-ml-2 px-2 text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<IntlProvider locale="en">
<FormattedNumber

View File

@ -50,6 +50,7 @@ import { parseDate, parseRecurringDates } from "@lib/parseDate";
import slugify from "@lib/slugify";
import { UserAvatars } from "@components/booking/UserAvatars";
import EventTypeDescriptionSafeHTML from "@components/eventtype/EventTypeDescriptionSafeHTML";
import { BookPageProps } from "../../../pages/[user]/book";
import { HashLinkPageProps } from "../../../pages/d/[link]/book";
@ -472,12 +473,13 @@ const BookingPage = ({
profile={profile}
users={eventType.users}
showMembers={eventType.schedulingType !== SchedulingType.ROUND_ROBIN}
size={14}
size={10}
truncateAfter={3}
/>
<h2 className="font-cal text-bookinglight mt-2 font-medium dark:text-gray-300">
<h2 className="mt-2 break-words text-sm font-medium text-gray-500 dark:text-gray-300">
{profile.name}
</h2>
<h1 className="text-bookingdark mb-4 text-xl font-semibold dark:text-white">
<h1 className="font-cal dark:text-darkgray-900 mb-6 break-words text-2xl text-gray-900 ">
{eventType.title}
</h1>
{!!eventType.seatsPerTimeSlot && (
@ -496,83 +498,89 @@ const BookingPage = ({
</p>
)}
{eventType?.description && (
<p className="text-bookinglight mb-2 text-sm ">
<Icon.FiInfo className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
{eventType.description}
</p>
<div className="dark:text-darkgray-600 flex py-1 text-sm font-medium text-gray-600">
<div>
<Icon.FiInfo className="dark:text-darkgray-600 mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
</div>
<EventTypeDescriptionSafeHTML eventType={eventType} />
</div>
)}
{eventType?.requiresConfirmation && (
<p className="text-bookinglight mb-2 text-sm ">
<Icon.FiClipboard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<div className="dark:text-darkgray-600 flex items-center text-sm font-medium text-gray-600">
<div>
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
</div>
{t("requires_confirmation")}
</p>
</div>
)}
<p className="text-bookinglight mb-2 text-sm ">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
{eventType.length} {t("minutes")}
</p>
{eventType.price > 0 && (
<p className="text-bookinglight mb-1 -ml-2 px-2 py-1 text-sm ">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<IntlProvider locale="en">
<FormattedNumber
value={eventType.price / 100.0}
style="currency"
currency={eventType.currency.toUpperCase()}
/>
</IntlProvider>
<div className="flex flex-col space-y-2">
<p className="text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
{eventType.length} {t("minutes")}
</p>
)}
{!rescheduleUid && eventType.recurringEvent?.freq && recurringEventCount && (
<div className="mb-3 text-sm text-gray-600 ">
<Icon.FiRefreshCw className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
<p className="mb-1 -ml-2 inline px-2 py-1">
{getEveryFreqFor({
t,
recurringEvent: eventType.recurringEvent,
recurringCount: recurringEventCount,
})}
{eventType.price > 0 && (
<p className="text-bookinglight -ml-2 px-2 text-sm ">
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
<IntlProvider locale="en">
<FormattedNumber
value={eventType.price / 100.0}
style="currency"
currency={eventType.currency.toUpperCase()}
/>
</IntlProvider>
</p>
)}
{!rescheduleUid && eventType.recurringEvent?.freq && recurringEventCount && (
<div className="items-start text-sm font-medium text-gray-600 dark:text-white">
<Icon.FiRefreshCw className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
<p className="-ml-2 inline-block items-center px-2">
{getEveryFreqFor({
t,
recurringEvent: eventType.recurringEvent,
recurringCount: recurringEventCount,
})}
</p>
</div>
)}
<div className="text-bookinghighlight flex items-start text-sm">
<Icon.FiCalendar className="mr-[10px] ml-[2px] mt-[2px] inline-block h-4 w-4" />
<div className="text-sm font-medium">
{(rescheduleUid || !eventType.recurringEvent?.freq) &&
parseDate(dayjs(date).tz(timeZone()), i18n)}
{!rescheduleUid &&
eventType.recurringEvent?.freq &&
recurringStrings.slice(0, 5).map((aDate, key) => <p key={key}>{aDate}</p>)}
{!rescheduleUid && eventType.recurringEvent?.freq && recurringStrings.length > 5 && (
<div className="flex">
<Tooltip
content={recurringStrings.slice(5).map((aDate, key) => (
<p key={key}>{aDate}</p>
))}>
<p className="dark:text-darkgray-600 text-sm">
{t("plus_more", { count: recurringStrings.length - 5 })}
</p>
</Tooltip>
</div>
)}
</div>
</div>
)}
<div className="text-bookinghighlight mb-4 flex items-center text-sm">
<Icon.FiCalendar className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
<div>
{(rescheduleUid || !eventType.recurringEvent?.freq) &&
parseDate(dayjs(date).tz(timeZone()), i18n)}
{!rescheduleUid &&
eventType.recurringEvent?.freq &&
recurringStrings.slice(0, 5).map((aDate, key) => <p key={key}>{aDate}</p>)}
{!rescheduleUid && eventType.recurringEvent?.freq && recurringStrings.length > 5 && (
<div className="flex">
<Tooltip
content={recurringStrings.slice(5).map((aDate, key) => (
<p key={key}>{aDate}</p>
))}>
<p className="dark:text-darkgray-600 text-sm">
{t("plus_more", { count: recurringStrings.length - 5 })}
</p>
</Tooltip>
</div>
)}
</div>
{eventTypeDetail.isWeb3Active && eventType.metadata.smartContractAddress && (
<p className="text-bookinglight mb-1 -ml-2 px-2">
{t("requires_ownership_of_a_token") + " " + eventType.metadata.smartContractAddress}
</p>
)}
{booking?.startTime && rescheduleUid && (
<div>
<p className="mt-8 mb-2 text-sm " data-testid="former_time_p">
{t("former_time")}
</p>
<p className="line-through ">
<Icon.FiCalendar className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
{typeof booking.startTime === "string" && parseDate(dayjs(booking.startTime), i18n)}
</p>
</div>
)}
</div>
{eventTypeDetail.isWeb3Active && eventType.metadata.smartContractAddress && (
<p className="text-bookinglight mb-1 -ml-2 px-2 py-1">
{t("requires_ownership_of_a_token") + " " + eventType.metadata.smartContractAddress}
</p>
)}
{booking?.startTime && rescheduleUid && (
<div>
<p className="mt-8 mb-2 text-sm " data-testid="former_time_p">
{t("former_time")}
</p>
<p className="line-through ">
<Icon.FiCalendar className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
{typeof booking.startTime === "string" && parseDate(dayjs(booking.startTime), i18n)}
</p>
</div>
)}
</div>
<div className="p-6 sm:w-1/2">
<Form form={bookingForm} handleSubmit={bookEvent}>