feat: atoms enhancements (#27224)
This commit is contained in:
1 parent
0171b5a08c
commit
9a927206bd
12 files changed
+186
-170
No files matched your search
@@ -36,6 +36,8 @@ interface AppListProps {
|
||||
data: RouterOutputs["viewer"]["apps"]["integrations"];
|
||||
handleDisconnect: HandleDisconnect;
|
||||
listClassName?: string;
|
||||
appCardClassName?: string;
|
||||
appCardMenuClassName?: string;
|
||||
defaultConferencingApp: RouterOutputs["viewer"]["apps"]["getUsersDefaultConferencingApp"];
|
||||
handleUpdateUserDefaultConferencingApp: (params: UpdateUsersDefaultConferencingAppParams) => void;
|
||||
handleBulkUpdateDefaultLocation: (params: BulkUpdatParams) => void;
|
||||
@@ -51,6 +53,8 @@ export const AppList = ({
|
||||
handleDisconnect,
|
||||
variant,
|
||||
listClassName,
|
||||
appCardClassName,
|
||||
appCardMenuClassName,
|
||||
defaultConferencingApp,
|
||||
handleUpdateUserDefaultConferencingApp,
|
||||
handleBulkUpdateDefaultLocation,
|
||||
@@ -85,6 +89,7 @@ export const AppList = ({
|
||||
slug={item.slug}
|
||||
invalidCredential={item?.invalidCredentialIds ? item.invalidCredentialIds.length > 0 : false}
|
||||
credentialOwner={item?.credentialOwner}
|
||||
className={appCardClassName}
|
||||
actions={
|
||||
!item.credentialOwner?.readOnly ? (
|
||||
<div className="flex justify-end">
|
||||
@@ -92,7 +97,7 @@ export const AppList = ({
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button StartIcon="ellipsis" variant="icon" color="secondary" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuContent className={appCardMenuClassName}>
|
||||
{!appIsDefault && variant === "conferencing" && (
|
||||
<DropdownMenuItem>
|
||||
<DropdownItem
|
||||
|
||||
@@ -91,6 +91,7 @@ const BookerComponent = ({
|
||||
timeZones,
|
||||
eventMetaChildren,
|
||||
roundRobinHideOrgAndTeam,
|
||||
hideOrgTeamAvatar,
|
||||
showNoAvailabilityDialog,
|
||||
}: BookerProps & WrappedBookerProps) => {
|
||||
const searchParams = useCompatSearchParams();
|
||||
@@ -470,6 +471,7 @@ const BookerComponent = ({
|
||||
locale={userLocale}
|
||||
timeZones={timeZones}
|
||||
roundRobinHideOrgAndTeam={roundRobinHideOrgAndTeam}
|
||||
hideOrgTeamAvatar={hideOrgTeamAvatar}
|
||||
hideEventTypeDetails={hideEventTypeDetails}>
|
||||
{eventMetaChildren}
|
||||
</EventMeta>
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
import { m } from "framer-motion";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { shallow } from "zustand/shallow";
|
||||
|
||||
import { Timezone as PlatformTimezoneSelect } from "@calcom/atoms/timezone";
|
||||
import { EventDetails, EventMembers, EventMetaSkeleton, EventTitle } from "./event-meta";
|
||||
import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider";
|
||||
import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime";
|
||||
import { fadeInUp } from "@calcom/features/bookings/Booker/config";
|
||||
import type { Timezone } from "@calcom/features/bookings/Booker/types";
|
||||
import { SeatsAvailabilityText } from "@calcom/web/modules/bookings/components/SeatsAvailabilityText";
|
||||
import { EventMetaBlock } from "@calcom/web/modules/bookings/components/event-meta/Details";
|
||||
import { FromToTime } from "@calcom/features/bookings/Booker/utils/dates";
|
||||
import { useTimePreferences } from "@calcom/features/bookings/lib";
|
||||
import type { BookerEvent } from "@calcom/features/bookings/types";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
@@ -16,12 +11,15 @@ import { markdownToSafeHTMLClient } from "@calcom/lib/markdownToSafeHTMLClient";
|
||||
import { CURRENT_TIMEZONE } from "@calcom/lib/timezoneConstants";
|
||||
import type { EventTypeTranslation } from "@calcom/prisma/client";
|
||||
import { EventTypeAutoTranslatedField } from "@calcom/prisma/enums";
|
||||
|
||||
import { EventMetaBlock } from "@calcom/web/modules/bookings/components/event-meta/Details";
|
||||
import { SeatsAvailabilityText } from "@calcom/web/modules/bookings/components/SeatsAvailabilityText";
|
||||
import { m } from "framer-motion";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { shallow } from "zustand/shallow";
|
||||
import i18nConfigration from "../../../../../i18n.json";
|
||||
import { fadeInUp } from "@calcom/features/bookings/Booker/config";
|
||||
import { FromToTime } from "@calcom/features/bookings/Booker/utils/dates";
|
||||
import { EventDetails, EventMembers, EventMetaSkeleton, EventTitle } from "./event-meta";
|
||||
import { ScrollableWithGradients } from "./ScrollableWithGradients";
|
||||
import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime";
|
||||
|
||||
const WebTimezoneSelect = dynamic(
|
||||
() => import("@calcom/web/modules/timezone/components/TimezoneSelect").then((mod) => mod.TimezoneSelect),
|
||||
@@ -56,6 +54,7 @@ export const EventMeta = ({
|
||||
children,
|
||||
selectedTimeslot,
|
||||
roundRobinHideOrgAndTeam,
|
||||
hideOrgTeamAvatar,
|
||||
hideEventTypeDetails = false,
|
||||
}: {
|
||||
event?: Pick<
|
||||
@@ -96,6 +95,7 @@ export const EventMeta = ({
|
||||
children?: React.ReactNode;
|
||||
selectedTimeslot: string | null;
|
||||
roundRobinHideOrgAndTeam?: boolean;
|
||||
hideOrgTeamAvatar?: boolean;
|
||||
hideEventTypeDetails?: boolean;
|
||||
}) => {
|
||||
const { timeFormat, timezone } = useBookerTime();
|
||||
@@ -141,8 +141,8 @@ export const EventMeta = ({
|
||||
const colorClass = isNearlyFull
|
||||
? "text-rose-600"
|
||||
: isHalfFull
|
||||
? "text-yellow-500"
|
||||
: "text-bookinghighlight";
|
||||
? "text-yellow-500"
|
||||
: "text-bookinghighlight";
|
||||
const userLocale = locale ?? navigator.language;
|
||||
const translatedDescription = getTranslatedField(
|
||||
event?.fieldTranslations ?? [],
|
||||
@@ -171,6 +171,7 @@ export const EventMeta = ({
|
||||
entity={event.entity}
|
||||
isPrivateLink={isPrivateLink}
|
||||
roundRobinHideOrgAndTeam={roundRobinHideOrgAndTeam}
|
||||
hideOrgTeamAvatar={hideOrgTeamAvatar}
|
||||
/>
|
||||
<EventTitle className={`${classNames?.eventMetaTitle} my-2`}>
|
||||
{translatedTitle ?? event?.title}
|
||||
|
||||
@@ -19,6 +19,7 @@ export interface EventMembersProps {
|
||||
entity: BookerEvent["entity"];
|
||||
isPrivateLink: boolean;
|
||||
roundRobinHideOrgAndTeam?: boolean;
|
||||
hideOrgTeamAvatar?: boolean;
|
||||
}
|
||||
|
||||
export const EventMembers = ({
|
||||
@@ -28,6 +29,7 @@ export const EventMembers = ({
|
||||
entity,
|
||||
isPrivateLink,
|
||||
roundRobinHideOrgAndTeam,
|
||||
hideOrgTeamAvatar,
|
||||
}: EventMembersProps) => {
|
||||
const username = useBookerStore((state) => state.username);
|
||||
const isDynamic = !!(username && username.indexOf("+") > -1);
|
||||
@@ -46,8 +48,12 @@ export const EventMembers = ({
|
||||
return <div className="h-6" />;
|
||||
}
|
||||
|
||||
if (schedulingType === SchedulingType.ROUND_ROBIN && hideOrgTeamAvatar) {
|
||||
return <p className="text-subtle pt-6 text-sm font-semibold">{profile.name}</p>;
|
||||
}
|
||||
|
||||
const orgOrTeamAvatarItem =
|
||||
isDynamic || (!profile.image && !entity.logoUrl) || !entity.teamSlug
|
||||
hideOrgTeamAvatar || isDynamic || (!profile.image && !entity.logoUrl) || !entity.teamSlug
|
||||
? []
|
||||
: [
|
||||
{
|
||||
@@ -56,8 +62,8 @@ export const EventMembers = ({
|
||||
isEmbed || isPlatform || isPrivateLink || entity.hideProfileLink
|
||||
? null
|
||||
: entity.teamSlug
|
||||
? getTeamUrlSync({ orgSlug: entity.orgSlug, teamSlug: entity.teamSlug })
|
||||
: getBookerBaseUrlSync(entity.orgSlug),
|
||||
? getTeamUrlSync({ orgSlug: entity.orgSlug, teamSlug: entity.teamSlug })
|
||||
: getBookerBaseUrlSync(entity.orgSlug),
|
||||
image: entity.logoUrl ?? profile.image ?? "",
|
||||
alt: entity.name ?? profile.name ?? "",
|
||||
title: entity.name ?? profile.name ?? "",
|
||||
|
||||
+25
-18
@@ -52,6 +52,7 @@ export type EventTeamAssignmentTabBaseProps = Pick<
|
||||
customClassNames?: EventTeamAssignmentTabCustomClassNames;
|
||||
orgId: number | null;
|
||||
isSegmentApplicable: boolean;
|
||||
hideFixedHostsForCollective?: boolean;
|
||||
};
|
||||
|
||||
export const mapMemberToChildrenOption = (
|
||||
@@ -615,6 +616,7 @@ const Hosts = ({
|
||||
setAssignAllTeamMembers,
|
||||
customClassNames,
|
||||
isSegmentApplicable,
|
||||
hideFixedHostsForCollective = false,
|
||||
}: {
|
||||
orgId: number | null;
|
||||
teamId: number;
|
||||
@@ -623,6 +625,7 @@ const Hosts = ({
|
||||
setAssignAllTeamMembers: Dispatch<SetStateAction<boolean>>;
|
||||
customClassNames?: HostsCustomClassNames;
|
||||
isSegmentApplicable: boolean;
|
||||
hideFixedHostsForCollective?: boolean;
|
||||
}) => {
|
||||
const {
|
||||
control,
|
||||
@@ -662,10 +665,10 @@ const Hosts = ({
|
||||
|
||||
return existingHost
|
||||
? {
|
||||
...newValue,
|
||||
scheduleId: existingHost.scheduleId,
|
||||
groupId: existingHost.groupId,
|
||||
}
|
||||
...newValue,
|
||||
scheduleId: existingHost.scheduleId,
|
||||
groupId: existingHost.groupId,
|
||||
}
|
||||
: newValue;
|
||||
});
|
||||
};
|
||||
@@ -675,7 +678,9 @@ const Hosts = ({
|
||||
name="hosts"
|
||||
render={({ field: { onChange, value } }) => {
|
||||
const schedulingTypeRender = {
|
||||
COLLECTIVE: (
|
||||
COLLECTIVE: hideFixedHostsForCollective ? (
|
||||
<></>
|
||||
) : (
|
||||
<FixedHosts
|
||||
teamId={teamId}
|
||||
teamMembers={teamMembers}
|
||||
@@ -733,6 +738,7 @@ export const EventTeamAssignmentTab = ({
|
||||
customClassNames,
|
||||
orgId,
|
||||
isSegmentApplicable,
|
||||
hideFixedHostsForCollective = false,
|
||||
}: EventTeamAssignmentTabBaseProps) => {
|
||||
const { t } = useLocale();
|
||||
|
||||
@@ -741,17 +747,17 @@ export const EventTeamAssignmentTab = ({
|
||||
label: string;
|
||||
// description: string;
|
||||
}[] = [
|
||||
{
|
||||
value: "COLLECTIVE",
|
||||
label: t("collective"),
|
||||
// description: t("collective_description"),
|
||||
},
|
||||
{
|
||||
value: "ROUND_ROBIN",
|
||||
label: t("round_robin"),
|
||||
// description: t("round_robin_description"),
|
||||
},
|
||||
];
|
||||
{
|
||||
value: "COLLECTIVE",
|
||||
label: t("collective"),
|
||||
// description: t("collective_description"),
|
||||
},
|
||||
{
|
||||
value: "ROUND_ROBIN",
|
||||
label: t("round_robin"),
|
||||
// description: t("round_robin_description"),
|
||||
},
|
||||
];
|
||||
const pendingMembers = (member: (typeof teamMembers)[number]) =>
|
||||
!!eventType.team?.parentId || !!member.username;
|
||||
const teamMembersOptions = teamMembers
|
||||
@@ -883,11 +889,11 @@ export const EventTeamAssignmentTab = ({
|
||||
</RadioArea.Item>
|
||||
{(eventType.team?.rrTimestampBasis &&
|
||||
eventType.team?.rrTimestampBasis !== RRTimestampBasis.CREATED_AT) ||
|
||||
hostGroups?.length > 1 ? (
|
||||
hostGroups?.length > 1 ? (
|
||||
<Tooltip
|
||||
content={
|
||||
eventType.team?.rrTimestampBasis &&
|
||||
eventType.team?.rrTimestampBasis !== RRTimestampBasis.CREATED_AT
|
||||
eventType.team?.rrTimestampBasis !== RRTimestampBasis.CREATED_AT
|
||||
? t("rr_load_balancing_disabled")
|
||||
: t("rr_load_balancing_disabled_with_groups")
|
||||
}>
|
||||
@@ -942,6 +948,7 @@ export const EventTeamAssignmentTab = ({
|
||||
setAssignAllTeamMembers={setAssignAllTeamMembers}
|
||||
teamMembers={teamMembersOptions}
|
||||
customClassNames={customClassNames?.hosts}
|
||||
hideFixedHostsForCollective={hideFixedHostsForCollective}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import type React from "react";
|
||||
|
||||
import type { UseBookerLayoutType } from "@calcom/features/bookings/Booker/components/hooks/useBookerLayout";
|
||||
import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/components/hooks/useBookingForm";
|
||||
import type { UseBookingsReturnType } from "@calcom/features/bookings/Booker/components/hooks/useBookings";
|
||||
@@ -10,7 +8,7 @@ import type { UseVerifyEmailReturnType } from "@calcom/features/bookings/Booker/
|
||||
import type { useScheduleForEventReturnType } from "@calcom/features/bookings/Booker/utils/event";
|
||||
import type { BookerEventQuery } from "@calcom/features/bookings/types";
|
||||
import type { IntlSupportedTimeZones } from "@calcom/lib/timeZones";
|
||||
|
||||
import type React from "react";
|
||||
import type { GetBookingType } from "../lib/get-booking";
|
||||
|
||||
export type Timezone = (typeof IntlSupportedTimeZones)[number];
|
||||
@@ -141,12 +139,14 @@ export type WrappedBookerPropsForPlatform = WrappedBookerPropsMain & {
|
||||
customClassNames?: CustomClassNames;
|
||||
timeZones?: Timezone[];
|
||||
roundRobinHideOrgAndTeam?: boolean;
|
||||
hideOrgTeamAvatar?: boolean;
|
||||
};
|
||||
export type WrappedBookerPropsForWeb = WrappedBookerPropsMain & {
|
||||
isPlatform: false;
|
||||
verifyCode: UseVerifyCodeReturnType;
|
||||
timeZones?: Timezone[];
|
||||
roundRobinHideOrgAndTeam?: boolean;
|
||||
hideOrgTeamAvatar?: boolean;
|
||||
};
|
||||
|
||||
export type WrappedBookerProps = WrappedBookerPropsForPlatform | WrappedBookerPropsForWeb;
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import debounce from "lodash/debounce";
|
||||
import {
|
||||
useMemo,
|
||||
useEffect,
|
||||
useCallback,
|
||||
useState,
|
||||
useRef,
|
||||
useContext,
|
||||
} from "react";
|
||||
import { shallow } from "zustand/shallow";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { Booker as BookerComponent } from "@calcom/web/modules/bookings/components/Booker";
|
||||
import {
|
||||
BookerStoreProvider,
|
||||
useInitializeBookerStoreContext,
|
||||
useBookerStoreContext,
|
||||
BookerStoreContext,
|
||||
BookerStoreProvider,
|
||||
useBookerStoreContext,
|
||||
useInitializeBookerStoreContext,
|
||||
} from "@calcom/features/bookings/Booker/BookerStoreProvider";
|
||||
import { useBookerLayout } from "@calcom/features/bookings/Booker/components/hooks/useBookerLayout";
|
||||
import { useBookingForm } from "@calcom/features/bookings/Booker/components/hooks/useBookingForm";
|
||||
@@ -30,13 +18,17 @@ import { useTimesForSchedule } from "@calcom/features/schedules/lib/use-schedule
|
||||
import { getRoutedTeamMemberIdsFromSearchParams } from "@calcom/lib/bookings/getRoutedTeamMemberIdsFromSearchParams";
|
||||
import { localStorage } from "@calcom/lib/webstorage";
|
||||
import { BookerLayouts } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import { Booker as BookerComponent } from "@calcom/web/modules/bookings/components/Booker";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import debounce from "lodash/debounce";
|
||||
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { shallow } from "zustand/shallow";
|
||||
import { useCreateBooking } from "../hooks/bookings/useCreateBooking";
|
||||
import { useCreateInstantBooking } from "../hooks/bookings/useCreateInstantBooking";
|
||||
import { useCreateRecurringBooking } from "../hooks/bookings/useCreateRecurringBooking";
|
||||
import {
|
||||
useGetBookingForReschedule,
|
||||
QUERY_KEY as BOOKING_RESCHEDULE_KEY,
|
||||
useGetBookingForReschedule,
|
||||
} from "../hooks/bookings/useGetBookingForReschedule";
|
||||
import { useHandleBookEvent } from "../hooks/bookings/useHandleBookEvent";
|
||||
import { useAtomGetPublicEvent } from "../hooks/event-types/public/useAtomGetPublicEvent";
|
||||
@@ -56,9 +48,7 @@ import type {
|
||||
} from "./types";
|
||||
|
||||
const BookerPlatformWrapperComponent = (
|
||||
props:
|
||||
| BookerPlatformWrapperAtomPropsForIndividual
|
||||
| BookerPlatformWrapperAtomPropsForTeam
|
||||
props: BookerPlatformWrapperAtomPropsForIndividual | BookerPlatformWrapperAtomPropsForTeam
|
||||
) => {
|
||||
const {
|
||||
view = "MONTH_VIEW",
|
||||
@@ -80,33 +70,24 @@ const BookerPlatformWrapperComponent = (
|
||||
hideEventMetadata = false,
|
||||
defaultPhoneCountry,
|
||||
rrHostSubsetIds,
|
||||
hideOrgTeamAvatar = false,
|
||||
} = props;
|
||||
const layout = BookerLayouts[view];
|
||||
|
||||
const { clientId } = useAtomsContext();
|
||||
const teamId: number | undefined = props.isTeamEvent
|
||||
? props.teamId
|
||||
: undefined;
|
||||
const teamId: number | undefined = props.isTeamEvent ? props.teamId : undefined;
|
||||
const [_bookerState, setBookerState] = useBookerStoreContext(
|
||||
(state) => [state.state, state.setState],
|
||||
shallow
|
||||
);
|
||||
const setSelectedDate = useBookerStoreContext(
|
||||
(state) => state.setSelectedDate
|
||||
);
|
||||
const setSelectedDuration = useBookerStoreContext(
|
||||
(state) => state.setSelectedDuration
|
||||
);
|
||||
const setSelectedDate = useBookerStoreContext((state) => state.setSelectedDate);
|
||||
const setSelectedDuration = useBookerStoreContext((state) => state.setSelectedDuration);
|
||||
const setBookingData = useBookerStoreContext((state) => state.setBookingData);
|
||||
const setOrg = useBookerStoreContext((state) => state.setOrg);
|
||||
const bookingData = useBookerStoreContext((state) => state.bookingData);
|
||||
const setSelectedTimeslot = useBookerStoreContext(
|
||||
(state) => state.setSelectedTimeslot
|
||||
);
|
||||
const setSelectedTimeslot = useBookerStoreContext((state) => state.setSelectedTimeslot);
|
||||
const setSelectedMonth = useBookerStoreContext((state) => state.setMonth);
|
||||
const selectedDuration = useBookerStoreContext(
|
||||
(state) => state.selectedDuration
|
||||
);
|
||||
const selectedDuration = useBookerStoreContext((state) => state.selectedDuration);
|
||||
|
||||
const [isOverlayCalendarEnabled, setIsOverlayCalendarEnabled] = useState(
|
||||
Boolean(localStorage?.getItem?.("overlayCalendarSwitchDefault"))
|
||||
@@ -121,14 +102,9 @@ const BookerPlatformWrapperComponent = (
|
||||
}, []);
|
||||
const debouncedStateChange = useMemo(() => {
|
||||
return debounce(
|
||||
(
|
||||
currentStateValues: BookerStoreValues,
|
||||
callback: (values: BookerStoreValues) => void
|
||||
) => {
|
||||
(currentStateValues: BookerStoreValues, callback: (values: BookerStoreValues) => void) => {
|
||||
const prevState = prevStateRef.current;
|
||||
const stateChanged =
|
||||
!prevState ||
|
||||
JSON.stringify(prevState) !== JSON.stringify(currentStateValues);
|
||||
const stateChanged = !prevState || JSON.stringify(prevState) !== JSON.stringify(currentStateValues);
|
||||
|
||||
if (stateChanged) {
|
||||
callback(currentStateValues);
|
||||
@@ -156,12 +132,7 @@ const BookerPlatformWrapperComponent = (
|
||||
unsubscribe();
|
||||
debouncedStateChange.cancel();
|
||||
};
|
||||
}, [
|
||||
onBookerStateChange,
|
||||
getStateValues,
|
||||
debouncedStateChange,
|
||||
bookerStoreContext,
|
||||
]);
|
||||
}, [onBookerStateChange, getStateValues, debouncedStateChange, bookerStoreContext]);
|
||||
|
||||
useGetBookingForReschedule({
|
||||
uid: props.rescheduleUid ?? props.bookingUid ?? "",
|
||||
@@ -240,10 +211,7 @@ const BookerPlatformWrapperComponent = (
|
||||
allowUpdatingUrlParams,
|
||||
defaultPhoneCountry,
|
||||
});
|
||||
const [dayCount] = useBookerStoreContext(
|
||||
(state) => [state.dayCount, state.setDayCount],
|
||||
shallow
|
||||
);
|
||||
const [dayCount] = useBookerStoreContext((state) => [state.dayCount, state.setDayCount], shallow);
|
||||
const selectedDate = useBookerStoreContext((state) => state.selectedDate);
|
||||
|
||||
const month = useBookerStoreContext((state) => state.month);
|
||||
@@ -251,11 +219,7 @@ const BookerPlatformWrapperComponent = (
|
||||
|
||||
const { data: session } = useMe();
|
||||
const hasSession = !!session;
|
||||
const {
|
||||
name: defaultName,
|
||||
guests: defaultGuests,
|
||||
...restFormValues
|
||||
} = props.defaultFormValues ?? {};
|
||||
const { name: defaultName, guests: defaultGuests, ...restFormValues } = props.defaultFormValues ?? {};
|
||||
|
||||
const prefillFormParamName = useMemo(() => {
|
||||
if (defaultName) {
|
||||
@@ -289,8 +253,7 @@ const BookerPlatformWrapperComponent = (
|
||||
});
|
||||
|
||||
const startTime =
|
||||
customStartTime &&
|
||||
dayjs(customStartTime).isAfter(dayjs(calculatedStartTime))
|
||||
customStartTime && dayjs(customStartTime).isAfter(dayjs(calculatedStartTime))
|
||||
? dayjs(customStartTime).toISOString()
|
||||
: calculatedStartTime;
|
||||
const endTime = calculatedEndTime;
|
||||
@@ -306,10 +269,8 @@ const BookerPlatformWrapperComponent = (
|
||||
? new URLSearchParams(routingFormSearchParams)
|
||||
: new URLSearchParams(window.location.search);
|
||||
|
||||
const routedTeamMemberIds =
|
||||
getRoutedTeamMemberIdsFromSearchParams(searchParams);
|
||||
const skipContactOwner =
|
||||
searchParams.get("cal.skipContactOwner") === "true";
|
||||
const routedTeamMemberIds = getRoutedTeamMemberIdsFromSearchParams(searchParams);
|
||||
const skipContactOwner = searchParams.get("cal.skipContactOwner") === "true";
|
||||
|
||||
const isBookingDryRun =
|
||||
searchParams?.get("cal.isBookingDryRun")?.toLowerCase() === "true" ||
|
||||
@@ -349,12 +310,7 @@ const BookerPlatformWrapperComponent = (
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
schedule.data &&
|
||||
!schedule.isPending &&
|
||||
!schedule.error &&
|
||||
onTimeslotsLoaded
|
||||
) {
|
||||
if (schedule.data && !schedule.isPending && !schedule.error && onTimeslotsLoaded) {
|
||||
onTimeslotsLoaded(schedule.data.slots);
|
||||
}
|
||||
}, [schedule.data, schedule.isPending, schedule.error, onTimeslotsLoaded]);
|
||||
@@ -429,17 +385,14 @@ const BookerPlatformWrapperComponent = (
|
||||
onReserveSlotError: props.onReserveSlotError,
|
||||
onDeleteSlotSuccess: props.onDeleteSlotSuccess,
|
||||
onDeleteSlotError: props.onDeleteSlotError,
|
||||
isBookingDryRun: props.isBookingDryRun
|
||||
? props.isBookingDryRun
|
||||
: routingParams?.isBookingDryRun,
|
||||
isBookingDryRun: props.isBookingDryRun ? props.isBookingDryRun : routingParams?.isBookingDryRun,
|
||||
handleSlotReservation,
|
||||
});
|
||||
|
||||
const verifyEmail = useVerifyEmail({
|
||||
email: bookerForm.formEmail,
|
||||
name: bookerForm.formName,
|
||||
requiresBookerEmailVerification:
|
||||
event?.data?.requiresBookerEmailVerification,
|
||||
requiresBookerEmailVerification: event?.data?.requiresBookerEmailVerification,
|
||||
onVerifyEmail: bookerForm.beforeVerifyEmail,
|
||||
});
|
||||
|
||||
@@ -453,10 +406,9 @@ const BookerPlatformWrapperComponent = (
|
||||
},
|
||||
});
|
||||
|
||||
const { data: connectedCalendars, isPending: fetchingConnectedCalendars } =
|
||||
useConnectedCalendars({
|
||||
enabled: hasSession,
|
||||
});
|
||||
const { data: connectedCalendars, isPending: fetchingConnectedCalendars } = useConnectedCalendars({
|
||||
enabled: hasSession,
|
||||
});
|
||||
const calendars = connectedCalendars as ConnectedDestinationCalendars;
|
||||
|
||||
const { set, clearSet } = useLocalSet<{
|
||||
@@ -477,11 +429,7 @@ const BookerPlatformWrapperComponent = (
|
||||
onError: () => {
|
||||
clearSet();
|
||||
},
|
||||
enabled: Boolean(
|
||||
hasSession &&
|
||||
isOverlayCalendarEnabled &&
|
||||
latestCalendarsToLoad?.length > 0
|
||||
),
|
||||
enabled: Boolean(hasSession && isOverlayCalendarEnabled && latestCalendarsToLoad?.length > 0),
|
||||
});
|
||||
|
||||
const handleBookEvent = useHandleBookEvent({
|
||||
@@ -548,9 +496,7 @@ const BookerPlatformWrapperComponent = (
|
||||
if (isOverlayCalendarEnabled && view === "MONTH_VIEW") {
|
||||
localStorage?.removeItem("overlayCalendarSwitchDefault");
|
||||
}
|
||||
setIsOverlayCalendarEnabled(
|
||||
Boolean(localStorage?.getItem?.("overlayCalendarSwitchDefault"))
|
||||
);
|
||||
setIsOverlayCalendarEnabled(Boolean(localStorage?.getItem?.("overlayCalendarSwitchDefault")));
|
||||
}, [view, isOverlayCalendarEnabled]);
|
||||
|
||||
return (
|
||||
@@ -579,16 +525,16 @@ const BookerPlatformWrapperComponent = (
|
||||
confirmButtonDisabled={confirmButtonDisabled}
|
||||
fromUserNameRedirected=""
|
||||
hasSession={hasSession}
|
||||
onGoBackInstantMeeting={function (): void {
|
||||
onGoBackInstantMeeting={(): void => {
|
||||
throw new Error("Function not implemented.");
|
||||
}}
|
||||
onConnectNowInstantMeeting={function (): void {
|
||||
onConnectNowInstantMeeting={(): void => {
|
||||
throw new Error("Function not implemented.");
|
||||
}}
|
||||
onOverlayClickNoCalendar={function (): void {
|
||||
onOverlayClickNoCalendar={(): void => {
|
||||
throw new Error("Function not implemented.");
|
||||
}}
|
||||
onClickOverlayContinue={function (): void {
|
||||
onClickOverlayContinue={(): void => {
|
||||
throw new Error("Function not implemented.");
|
||||
}}
|
||||
onOverlaySwitchStateChange={onOverlaySwitchStateChange}
|
||||
@@ -602,14 +548,8 @@ const BookerPlatformWrapperComponent = (
|
||||
bookingForm: bookerForm.bookingForm,
|
||||
bookerFormErrorRef: bookerForm.bookerFormErrorRef,
|
||||
errors: {
|
||||
hasDataErrors:
|
||||
isCreateBookingError ||
|
||||
isCreateRecBookingError ||
|
||||
isCreateInstantBookingError,
|
||||
dataErrors:
|
||||
createBookingError ||
|
||||
createRecBookingError ||
|
||||
createInstantBookingError,
|
||||
hasDataErrors: isCreateBookingError || isCreateRecBookingError || isCreateInstantBookingError,
|
||||
dataErrors: createBookingError || createRecBookingError || createInstantBookingError,
|
||||
},
|
||||
loadingStates: {
|
||||
creatingBooking: creatingBooking,
|
||||
@@ -645,15 +585,14 @@ const BookerPlatformWrapperComponent = (
|
||||
isBookingDryRun={isBookingDryRun ?? routingParams?.isBookingDryRun}
|
||||
eventMetaChildren={props.eventMetaChildren}
|
||||
roundRobinHideOrgAndTeam={props.roundRobinHideOrgAndTeam}
|
||||
hideOrgTeamAvatar={hideOrgTeamAvatar}
|
||||
/>
|
||||
</AtomsWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const BookerPlatformWrapper = (
|
||||
props:
|
||||
| BookerPlatformWrapperAtomPropsForIndividual
|
||||
| BookerPlatformWrapperAtomPropsForTeam
|
||||
props: BookerPlatformWrapperAtomPropsForIndividual | BookerPlatformWrapperAtomPropsForTeam
|
||||
) => {
|
||||
return (
|
||||
<BookerStoreProvider>
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import type React from "react";
|
||||
|
||||
import type { BookerProps } from "@calcom/features/bookings/Booker";
|
||||
import type { BookerStore, CountryCode } from "@calcom/features/bookings/Booker/store";
|
||||
import type { Timezone, VIEW_TYPE } from "@calcom/features/bookings/Booker/types";
|
||||
import type { BookingCreateBody } from "@calcom/features/bookings/lib/bookingCreateBodySchema";
|
||||
import type { BookingResponse } from "@calcom/platform-libraries";
|
||||
import type {
|
||||
ApiSuccessResponse,
|
||||
ApiErrorResponse,
|
||||
ApiSuccessResponse,
|
||||
ApiSuccessResponseWithoutData,
|
||||
RoutingFormSearchParams,
|
||||
} from "@calcom/platform-types";
|
||||
|
||||
import type React from "react";
|
||||
import type { UseCreateBookingInput } from "../hooks/bookings/useCreateBooking";
|
||||
|
||||
export type Slot = {
|
||||
@@ -96,6 +94,7 @@ export type BookerPlatformWrapperAtomProps = Omit<
|
||||
silentlyHandleCalendarFailures?: boolean;
|
||||
hideEventMetadata?: boolean;
|
||||
defaultPhoneCountry?: CountryCode;
|
||||
hideOrgTeamAvatar?: boolean;
|
||||
};
|
||||
|
||||
export type BookerPlatformWrapperAtomPropsForIndividual = BookerPlatformWrapperAtomProps & {
|
||||
|
||||
+65
-20
@@ -1,11 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useReducer, useState } from "react";
|
||||
|
||||
import AccountDialog from "@calcom/app-store/office365video/components/AccountDialog";
|
||||
import { AppList } from "@calcom/web/modules/apps/components/AppList";
|
||||
import DisconnectIntegrationModal from "@calcom/web/modules/apps/components/DisconnectIntegrationModal";
|
||||
import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { GOOGLE_MEET, OFFICE_365_VIDEO, ZOOM } from "@calcom/platform-constants";
|
||||
@@ -14,16 +9,20 @@ import type { App } from "@calcom/types/App";
|
||||
import { Button } from "@calcom/ui/components/button";
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownMenuTrigger,
|
||||
DropdownItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@calcom/ui/components/dropdown";
|
||||
import { EmptyScreen } from "@calcom/ui/components/empty-screen";
|
||||
import { SkeletonContainer, SkeletonText } from "@calcom/ui/components/skeleton";
|
||||
|
||||
import { AppList } from "@calcom/web/modules/apps/components/AppList";
|
||||
import DisconnectIntegrationModal from "@calcom/web/modules/apps/components/DisconnectIntegrationModal";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useReducer, useState } from "react";
|
||||
import { AtomsWrapper } from "../../src/components/atoms-wrapper";
|
||||
import { useToast } from "../../src/components/ui/use-toast";
|
||||
import { cn } from "../../src/lib/utils";
|
||||
import type {
|
||||
BulkUpdatParams,
|
||||
UpdateUsersDefaultConferencingAppParams,
|
||||
@@ -31,19 +30,35 @@ import type {
|
||||
import { useAtomBulkUpdateEventTypesToDefaultLocation } from "./hooks/useAtomBulkUpdateEventTypesToDefaultLocation";
|
||||
import { useAtomGetEventTypes } from "./hooks/useAtomGetEventTypes";
|
||||
import {
|
||||
useAtomsGetInstalledConferencingApps,
|
||||
QUERY_KEY as atomsConferencingAppsQueryKey,
|
||||
useAtomsGetInstalledConferencingApps,
|
||||
} from "./hooks/useAtomsGetInstalledConferencingApps";
|
||||
import { useConnect } from "./hooks/useConnect";
|
||||
import { useDeleteCredential } from "./hooks/useDeleteCredential";
|
||||
import {
|
||||
useGetDefaultConferencingApp,
|
||||
QUERY_KEY as defaultConferencingAppQueryKey,
|
||||
useGetDefaultConferencingApp,
|
||||
} from "./hooks/useGetDefaultConferencingApp";
|
||||
import { useUpdateUserDefaultConferencingApp } from "./hooks/useUpdateUserDefaultConferencingApp";
|
||||
|
||||
type ConferencingAppSlug = typeof GOOGLE_MEET | typeof ZOOM | typeof OFFICE_365_VIDEO;
|
||||
|
||||
export type ConferencingAppsCustomClassNames = {
|
||||
containerClassName?: string;
|
||||
headerClassName?: string;
|
||||
headerTitleClassName?: string;
|
||||
headerDescriptionClassName?: string;
|
||||
addButtonClassName?: string;
|
||||
addDropdownClassName?: string;
|
||||
appListClassName?: string;
|
||||
appCardClassName?: string;
|
||||
appCardMenuClassName?: string;
|
||||
emptyScreenClassName?: string;
|
||||
emptyScreenIconWrapperClassName?: string;
|
||||
emptyScreenIconClassName?: string;
|
||||
skeletonClassName?: string;
|
||||
};
|
||||
|
||||
type ConferencingAppsViewPlatformWrapperProps = {
|
||||
disableToasts?: boolean;
|
||||
returnTo?: string;
|
||||
@@ -51,13 +66,14 @@ type ConferencingAppsViewPlatformWrapperProps = {
|
||||
teamId?: number;
|
||||
apps?: ConferencingAppSlug[];
|
||||
disableBulkUpdateEventTypes?: boolean;
|
||||
customClassNames?: ConferencingAppsCustomClassNames;
|
||||
};
|
||||
|
||||
type RemoveAppParams = { callback: () => void; app?: App["slug"] };
|
||||
|
||||
const SkeletonLoader = () => {
|
||||
const SkeletonLoader = ({ className }: { className?: string }) => {
|
||||
return (
|
||||
<SkeletonContainer>
|
||||
<SkeletonContainer className={className}>
|
||||
<div className="divide-subtle border-subtle stack-y-6 rounded-b-lg border border-t-0 px-6 py-4">
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
<SkeletonText className="h-8 w-full" />
|
||||
@@ -79,6 +95,7 @@ export const ConferencingAppsViewPlatformWrapper = ({
|
||||
teamId,
|
||||
apps,
|
||||
disableBulkUpdateEventTypes = false,
|
||||
customClassNames,
|
||||
}: ConferencingAppsViewPlatformWrapperProps) => {
|
||||
const { t } = useLocale();
|
||||
const queryClient = useQueryClient();
|
||||
@@ -200,15 +217,23 @@ export const ConferencingAppsViewPlatformWrapper = ({
|
||||
teamId,
|
||||
});
|
||||
|
||||
const AddConferencingButtonPlatform = ({ installedApps }: { installedApps?: Array<{ slug: string }> }) => {
|
||||
const AddConferencingButtonPlatform = ({
|
||||
installedApps,
|
||||
buttonClassName,
|
||||
dropdownClassName,
|
||||
}: {
|
||||
installedApps?: Array<{ slug: string }>;
|
||||
buttonClassName?: string;
|
||||
dropdownClassName?: string;
|
||||
}) => {
|
||||
return (
|
||||
<Dropdown>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button color="secondary" StartIcon="plus">
|
||||
<Button color="secondary" StartIcon="plus" className={buttonClassName}>
|
||||
{t("add")}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuContent className={dropdownClassName}>
|
||||
{/* Show Google Meet if it's not installed and either no apps filter is provided or it's in the apps filter */}
|
||||
{installedApps &&
|
||||
!installedApps.find((app) => app.slug === GOOGLE_MEET) &&
|
||||
@@ -247,17 +272,23 @@ export const ConferencingAppsViewPlatformWrapper = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<AtomsWrapper>
|
||||
<AtomsWrapper customClassName={customClassNames?.containerClassName}>
|
||||
<SettingsHeader
|
||||
title={t("conferencing")}
|
||||
description={t("conferencing_description")}
|
||||
CTA={<AddConferencingButtonPlatform installedApps={installedIntegrationsQuery.data?.items} />}
|
||||
CTA={
|
||||
<AddConferencingButtonPlatform
|
||||
installedApps={installedIntegrationsQuery.data?.items}
|
||||
buttonClassName={customClassNames?.addButtonClassName}
|
||||
dropdownClassName={customClassNames?.addDropdownClassName}
|
||||
/>
|
||||
}
|
||||
borderInShellHeader={true}>
|
||||
<>
|
||||
<div className="bg-default w-full sm:mx-0 xl:mt-0">
|
||||
<QueryCell
|
||||
query={installedIntegrationsQuery}
|
||||
customLoader={<SkeletonLoader />}
|
||||
customLoader={<SkeletonLoader className={customClassNames?.skeletonClassName} />}
|
||||
success={({ data }) => {
|
||||
if (!data.items.length) {
|
||||
return (
|
||||
@@ -267,13 +298,27 @@ export const ConferencingAppsViewPlatformWrapper = ({
|
||||
category: t("conferencing").toLowerCase(),
|
||||
})}
|
||||
description={t("no_category_apps_description_conferencing")}
|
||||
buttonRaw={<AddConferencingButtonPlatform installedApps={data?.items} />}
|
||||
buttonRaw={
|
||||
<AddConferencingButtonPlatform
|
||||
installedApps={data?.items}
|
||||
buttonClassName={customClassNames?.addButtonClassName}
|
||||
dropdownClassName={customClassNames?.addDropdownClassName}
|
||||
/>
|
||||
}
|
||||
className={customClassNames?.emptyScreenClassName}
|
||||
iconWrapperClassName={customClassNames?.emptyScreenIconWrapperClassName}
|
||||
iconClassName={customClassNames?.emptyScreenIconClassName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<AppList
|
||||
listClassName="rounded-lg rounded-t-none border-t-0 max-w-full"
|
||||
listClassName={cn(
|
||||
"rounded-lg rounded-t-none border-t-0 max-w-full",
|
||||
customClassNames?.appListClassName
|
||||
)}
|
||||
appCardClassName={customClassNames?.appCardClassName}
|
||||
appCardMenuClassName={customClassNames?.appCardMenuClassName}
|
||||
handleDisconnect={handleDisconnect}
|
||||
data={data}
|
||||
variant="conferencing"
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ import {
|
||||
} from "@calcom/web/modules/event-types/components/tabs/assignment/EventTeamAssignmentTab";
|
||||
|
||||
const EventTeamAssignmentTabPlatformWrapper = (
|
||||
props: Omit<EventTeamAssignmentTabBaseProps, "isSegmentApplicable">
|
||||
props: Omit<EventTeamAssignmentTabBaseProps, "isSegmentApplicable" | "hideFixedHostsForCollective">
|
||||
) => {
|
||||
// todo: implement attributes for platform orgs for segment
|
||||
return <EventTeamAssignmentTab {...props} isSegmentApplicable={false} />;
|
||||
return <EventTeamAssignmentTab {...props} isSegmentApplicable={false} hideFixedHostsForCollective={true} />;
|
||||
};
|
||||
|
||||
export default EventTeamAssignmentTabPlatformWrapper;
|
||||
@@ -32,6 +32,7 @@ export { EventTypePlatformWrapper as EventTypeSettings } from "./event-types/wra
|
||||
export type { EventSettingsFromRef } from "./event-types/wrappers/types";
|
||||
export type { AvailabilitySettingsFormRef } from "./availability/types";
|
||||
export { ConferencingAppsViewPlatformWrapper as ConferencingAppsSettings } from "./connect/conferencing-apps/ConferencingAppsViewPlatformWrapper";
|
||||
export type { ConferencingAppsCustomClassNames } from "./connect/conferencing-apps/ConferencingAppsViewPlatformWrapper";
|
||||
export { StripeConnect } from "./connect/stripe/StripeConnect";
|
||||
export { CreateEventTypePlatformWrapper as CreateEventType } from "./event-types/wrappers/CreateEventTypePlatformWrapper";
|
||||
export { PaymentForm } from "./event-types/payments/PaymentForm";
|
||||
|
||||
@@ -1,21 +1,32 @@
|
||||
import { Navbar } from "@/components/Navbar";
|
||||
import { type ConferencingAppsCustomClassNames, ConferencingAppsSettings } from "@calcom/atoms";
|
||||
import { Inter } from "next/font/google";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
import { ConferencingAppsSettings } from "@calcom/atoms";
|
||||
import { Navbar } from "@/components/Navbar";
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
|
||||
export default function ConferencingApps(props: { calUsername: string; calEmail: string }) {
|
||||
const pathname = usePathname();
|
||||
const callbackUri = `${window.location.origin}${pathname}`;
|
||||
const customClassNames: ConferencingAppsCustomClassNames = {
|
||||
containerClassName: "bg-red-50 p-4 rounded-lg",
|
||||
addButtonClassName: "bg-blue-600 hover:bg-blue-700 text-white",
|
||||
addDropdownClassName: "bg-indigo-50 border-2 border-indigo-300",
|
||||
appListClassName: "border-2 border-green-500",
|
||||
appCardClassName: "bg-blue-50 border-b-2 border-blue-300",
|
||||
appCardMenuClassName: "bg-pink-50 border-2 border-pink-300",
|
||||
emptyScreenClassName: "bg-yellow-50 border-yellow-300",
|
||||
emptyScreenIconWrapperClassName: "bg-purple-100",
|
||||
emptyScreenIconClassName: "text-purple-600",
|
||||
skeletonClassName: "bg-gray-300",
|
||||
};
|
||||
|
||||
return (
|
||||
<main
|
||||
className={`flex min-h-screen flex-col ${inter.className} main text-default flex min-h-full w-full flex-col items-center overflow-visible`}>
|
||||
<Navbar username={props.calUsername} />
|
||||
<div className="my-8">
|
||||
<ConferencingAppsSettings returnTo={callbackUri} onErrorReturnTo={callbackUri} />
|
||||
<ConferencingAppsSettings returnTo={callbackUri} onErrorReturnTo={callbackUri} customClassNames={customClassNames}/>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user