feat: Added feature of embeding availability to emails (#10183)

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
This commit is contained in:
Pradumn Kumar
2023-07-24 10:09:03 +00:00
committed by GitHub
co-authored by Peer Richelsen Hariom Balhara
parent a9cc3649e0
commit 8de75aebf0
7 changed files with 806 additions and 257 deletions
File diff suppressed because it is too large Load Diff
@@ -318,6 +318,7 @@ function EventTypeSingleLayout({
color="secondary"
variant="icon"
tooltip={t("embed")}
eventId={eventType.id}
/>
</>
)}
+2 -1
View File
@@ -513,7 +513,8 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
type="button"
StartIcon={Code}
className="w-full rounded-none"
embedUrl={encodeURIComponent(embedLink)}>
embedUrl={encodeURIComponent(embedLink)}
eventId={type.id}>
{t("embed")}
</EmbedButton>
</DropdownMenuItem>
@@ -1949,6 +1949,11 @@
"insights_subtitle": "View booking insights across your events",
"location_options": "{{locationCount}} location options",
"custom_plan": "Custom Plan",
"email_embed": "Email Embed",
"add_times_to_your_email": "Add times to your Email",
"select_time": "Select Time",
"select_date": "Select Date",
"see_all_available_times": "See all available times",
"org_team_names_example": "e.g. Marketing Team",
"org_team_names_example_1": "e.g. Marketing Team",
"org_team_names_example_2": "e.g. Sales Team",
@@ -65,6 +65,11 @@ export type BookerStore = {
selectedDate: string | null;
setSelectedDate: (date: string | null) => void;
addToSelectedDate: (days: number) => void;
/**
* Multiple Selected Dates and Times
*/
selectedDatesAndTimes: { [key: string]: { [key: string]: string[] } } | null;
setSelectedDatesAndTimes: (selectedDatesAndTimes: { [key: string]: { [key: string]: string[] } }) => void;
/**
* Selected event duration in minutes.
*/
@@ -144,6 +149,10 @@ export const useBookerStore = create<BookerStore>((set, get) => ({
updateQueryParam("month", newSelection.format("YYYY-MM"));
}
},
selectedDatesAndTimes: null,
setSelectedDatesAndTimes: (selectedDatesAndTimes) => {
set({ selectedDatesAndTimes });
},
addToSelectedDate: (days: number) => {
const currentSelection = dayjs(get().selectedDate);
const newSelection = currentSelection.add(days, "day");
@@ -26,6 +26,7 @@ type AvailableTimesProps = {
seatsPerTimeSlot?: number | null;
showTimeFormatToggle?: boolean;
className?: string;
selectedSlots?: string[];
};
export const AvailableTimes = ({
@@ -35,6 +36,7 @@ export const AvailableTimes = ({
seatsPerTimeSlot,
showTimeFormatToggle = true,
className,
selectedSlots,
}: AvailableTimesProps) => {
const { t, i18n } = useLocale();
const [timeFormat, timezone] = useTimePreferences((state) => [state.timeFormat, state.timezone]);
@@ -97,7 +99,10 @@ export const AvailableTimes = ({
data-disabled={bookingFull}
data-time={slot.time}
onClick={() => onTimeSelect(slot.time, slot?.attendees || 0, seatsPerTimeSlot, slot.bookingUid)}
className="min-h-9 hover:border-brand-default mb-2 flex h-auto w-full flex-col justify-center py-2"
className={classNames(
"min-h-9 hover:border-brand-default mb-2 flex h-auto w-full flex-col justify-center py-2",
selectedSlots?.includes(slot.time) && "border-brand-default"
)}
color="secondary">
{dayjs.utc(slot.time).tz(timezone).format(timeFormat)}
{bookingFull && <p className="text-sm">{t("booking_full")}</p>}
+29 -1
View File
@@ -1,6 +1,9 @@
import { shallow } from "zustand/shallow";
import type { Dayjs } from "@calcom/dayjs";
import dayjs from "@calcom/dayjs";
import { useEmbedStyles } from "@calcom/embed-core/embed-iframe";
import { useBookerStore } from "@calcom/features/bookings/Booker/store";
import classNames from "@calcom/lib/classNames";
import { daysInMonth, yyyymmdd } from "@calcom/lib/date-fns";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -32,6 +35,8 @@ export type DatePickerProps = {
className?: string;
/** Shows a small loading spinner next to the month name */
isLoading?: boolean;
/** used to query the multiple selected dates */
eventSlug?: string;
};
export const Day = ({
@@ -100,6 +105,7 @@ const Days = ({
selected,
month,
nextMonthButton,
eventSlug,
...props
}: Omit<DatePickerProps, "locale" | "className" | "weekStart"> & {
DayComponent?: React.FC<React.ComponentProps<typeof Day>>;
@@ -138,6 +144,28 @@ const Days = ({
days.push(date);
}
const [selectedDatesAndTimes] = useBookerStore((state) => [state.selectedDatesAndTimes], shallow);
const isActive = (day: dayjs.Dayjs) => {
if (selected && yyyymmdd(selected) === yyyymmdd(day)) {
return true;
}
// for multiple dates select
if (
eventSlug &&
selectedDatesAndTimes &&
selectedDatesAndTimes[eventSlug as string] &&
Object.keys(selectedDatesAndTimes[eventSlug as string]).length > 0
) {
return Object.keys(selectedDatesAndTimes[eventSlug as string]).some((date) => {
return yyyymmdd(dayjs(date)) === yyyymmdd(day);
});
}
return false;
};
return (
<>
{days.map((day, idx) => (
@@ -161,7 +189,7 @@ const Days = ({
(includedDates && !includedDates.includes(yyyymmdd(day))) ||
excludedDates.includes(yyyymmdd(day))
}
active={selected ? yyyymmdd(selected) === yyyymmdd(day) : false}
active={isActive(day)}
/>
)}
</div>