## What does this PR do? - Adds a welcome modal for new Cal.com users - Implements timezone display in the weekly calendar view - Creates a hook for fetching onboarding calendar events ## Visual Demo (For contributors especially) #### Image Demo:   ## Mandatory Tasks - [x] I have self-reviewed the code - [x] I have updated the developer docs in /docs - [x] I confirm automated tests are in place that prove my fix is effective or that my feature works. ## How should this be tested? 1. **Welcome Modal:** - Create a new user account - Verify the welcome modal appears with correct content - Test the "Continue" button closes the modal - Check that the modal can be triggered via URL parameter `?welcomeToCalcomModal=true` 2. **Timezone Display:** - Go to the weekly calendar view - Verify the timezone is displayed correctly when `showTimezone` is enabled - Test with different timezones to ensure proper formatting 3. **Onboarding Calendar Events:** - Test the hook by connecting a calendar during onboarding - Verify events are fetched and displayed correctly - Check that events refresh when new calendars are connected ## Checklist - I have read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md) - My code follows the style guidelines of this project - I have commented my code, particularly in hard-to-understand areas - I have checked if my changes generate no new warnings
80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
import { useSession } from "next-auth/react";
|
|
import { useMemo, useEffect } from "react";
|
|
|
|
import dayjs from "@calcom/dayjs";
|
|
import type { GetUserAvailabilityResult } from "@calcom/features/availability/lib/getUserAvailability";
|
|
import type { CalendarEvent } from "@calcom/features/calendars/weeklyview/types/events";
|
|
import { BookingStatus } from "@calcom/prisma/enums";
|
|
import { trpc } from "@calcom/trpc/react";
|
|
|
|
type UseOnboardingCalendarEventsProps = {
|
|
startDate: Date;
|
|
endDate: Date;
|
|
};
|
|
|
|
const emptyAvailabilityData = {
|
|
busy: [],
|
|
timeZone: "",
|
|
dateRanges: [],
|
|
oooExcludedDateRanges: [],
|
|
workingHours: [],
|
|
dateOverrides: [],
|
|
currentSeats: null,
|
|
datesOutOfOffice: {},
|
|
} as GetUserAvailabilityResult;
|
|
|
|
export const useOnboardingCalendarEvents = ({ startDate, endDate }: UseOnboardingCalendarEventsProps) => {
|
|
const { data: session } = useSession();
|
|
const utils = trpc.useUtils();
|
|
|
|
// Watch for calendar installations to refetch events
|
|
const { data: connectedCalendars } = trpc.viewer.calendars.connectedCalendars.useQuery(undefined, {
|
|
refetchInterval: 5000, // Poll every 5 seconds to detect new calendar installations
|
|
});
|
|
|
|
const { data: busyEvents } = trpc.viewer.availability.user.useQuery(
|
|
{
|
|
username: session?.user?.username || "",
|
|
dateFrom: dayjs(startDate).startOf("day").utc().format(),
|
|
dateTo: dayjs(endDate).endOf("day").utc().format(),
|
|
withSource: true,
|
|
},
|
|
{
|
|
enabled: !!session?.user?.username,
|
|
// Don't show loading state - return empty array immediately
|
|
placeholderData: emptyAvailabilityData,
|
|
}
|
|
);
|
|
|
|
// Refetch availability when calendars change
|
|
useEffect(() => {
|
|
if (connectedCalendars?.connectedCalendars) {
|
|
utils.viewer.availability.user.invalidate();
|
|
}
|
|
}, [connectedCalendars?.connectedCalendars?.length, utils.viewer.availability.user]);
|
|
|
|
// Format events similar to Troubleshooter
|
|
// Always return an array, never undefined
|
|
const events = useMemo((): CalendarEvent[] => {
|
|
if (!busyEvents?.busy) return [];
|
|
|
|
return busyEvents.busy.map((event, idx) => {
|
|
return {
|
|
id: idx,
|
|
title: event.title ?? `Busy`,
|
|
start: new Date(event.start),
|
|
end: new Date(event.end),
|
|
options: {
|
|
color: event.source ? undefined : undefined,
|
|
status: BookingStatus.ACCEPTED,
|
|
},
|
|
};
|
|
});
|
|
}, [busyEvents]);
|
|
|
|
return {
|
|
events,
|
|
isLoading: false, // Never show loading state
|
|
};
|
|
};
|