diff --git a/src/components/availability/availability-actions.tsx b/src/components/availability/availability-actions.tsx
index b00c0f94a..704a08dc3 100644
--- a/src/components/availability/availability-actions.tsx
+++ b/src/components/availability/availability-actions.tsx
@@ -202,7 +202,7 @@ export function AvailabilityActions({
: handleScheduleCancel
}
>
- Cancel
+ Cancel
) : (
{isScheduled && (
-
}
- onClick={async () => {
- if (isGeneratingLink) return;
- setIsGeneratingLink(true);
- try {
- const { success, link } =
- await getGoogleCalendarPrefilledLink({
- meetingId: meetingData.id,
- meetingTitle: meetingData.title,
- meetingDescription: meetingData.description,
- meetingLocation: meetingData.location,
- timezone: meetingData.timezone,
- });
+
+ }
+ onClick={async () => {
+ if (isGeneratingLink) return;
+ setIsGeneratingLink(true);
+ try {
+ const { success, link } =
+ await getGoogleCalendarPrefilledLink({
+ meetingId: meetingData.id,
+ meetingTitle: meetingData.title,
+ meetingDescription: meetingData.description,
+ meetingLocation: meetingData.location,
+ timezone: meetingData.timezone,
+ });
- if (!success || !link) {
- showError("Failed to generate Google Calendar link.");
- return;
- }
+ if (!success || !link) {
+ showError("Failed to generate Google Calendar link.");
+ return;
+ }
- window.open(link, "_blank", "noopener,noreferrer");
- showSuccess(
- "Google Calendar link opened! Confirm the event in your calendar.",
- );
- } catch (error) {
- console.error(
- "Error generating Google Calendar link:",
- error,
- );
- showError(
- "An error occurred while generating the Google Calendar link.",
- );
- } finally {
- setIsGeneratingLink(false);
+ window.open(link, "_blank", "noopener,noreferrer");
+ showSuccess(
+ "Google Calendar link opened! Confirm the event in your calendar.",
+ );
+ } catch (error) {
+ console.error(
+ "Error generating Google Calendar link:",
+ error,
+ );
+ showError(
+ "An error occurred while generating the Google Calendar link.",
+ );
+ } finally {
+ setIsGeneratingLink(false);
+ }
+ }}
+ >
+ Add to Calendar
+
+
+ )}
+
+ }
+ className="w-full max-w-full normal-case"
+ sx={{ py: 0.75 }}
+ onClick={() => {
+ if (!user) {
+ setIsAuthModalOpen(true);
+ router.push("/auth/login/google");
+ return;
}
+ setChangeableTimezone(false);
+ setTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone);
+ setAvailabilityView("personal");
}}
>
- Add to Calendar
+
+ {hasAvailability ? "Edit Availability" : "Add Availability"}
+
- )}
-
- }
- className="w-full max-w-full normal-case"
- sx={{ py: 0.75 }}
- onClick={() => {
- if (!user) {
- setIsAuthModalOpen(true);
- router.push("/auth/login/google");
- return;
- }
- setChangeableTimezone(false);
- setTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone);
- setAvailabilityView("personal");
- }}
- >
-
- {hasAvailability ? "Edit Availability" : "Add Availability"}
-
-
+
{isOwner && (
- <>
+
}
@@ -301,7 +304,7 @@ export function AvailabilityActions({
>
Invite Members
- >
+
)}
)}
diff --git a/src/components/availability/availability.tsx b/src/components/availability/availability.tsx
index 5321b79ae..b3e3c3f5c 100644
--- a/src/components/availability/availability.tsx
+++ b/src/components/availability/availability.tsx
@@ -1,6 +1,7 @@
"use client";
import { Paper } from "@mui/material";
+import { useRouter } from "next/navigation";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useShallow } from "zustand/shallow";
import { AvailabilityActions } from "@/components/availability/availability-actions";
@@ -27,7 +28,9 @@ import {
import type { MemberMeetingAvailability } from "@/lib/types/availability";
import type { HourMinuteString } from "@/lib/types/chrono";
import { useAvailabilityStore } from "@/store/useAvailabilityStore";
+import { MobilePersonalAvailabilitySidebar } from "../nav/mobile-personal-availability";
import { PersonalAvailabilitySidebar } from "../nav/personal-availability-sidebar";
+import { MobileGroupResponses } from "./mobile-group-responses";
export function Availability({
meetingData,
@@ -48,10 +51,11 @@ export function Availability({
// View + paint mode live in the store (paint mode is reset atomically in
// `setAvailabilityView`, so it cannot drift across view switches).
- const { availabilityView, paintMode } = useAvailabilityStore(
+ const { availabilityView, paintMode, setPaintMode } = useAvailabilityStore(
useShallow((state) => ({
availabilityView: state.availabilityView,
paintMode: state.paintMode,
+ setPaintMode: state.setPaintMode,
})),
);
@@ -84,6 +88,15 @@ export function Availability({
})),
);
+ const { setAvailabilityView, setIsMobileDrawerOpen } = useAvailabilityStore(
+ useShallow((state) => ({
+ setAvailabilityView: state.setAvailabilityView,
+ setIsMobileDrawerOpen: state.setIsMobileDrawerOpen,
+ })),
+ );
+
+ const router = useRouter();
+
const isMobile = useIsMobile();
useEffect(() => {
setItemsPerPage(isMobile ? 2 : 5);
@@ -254,6 +267,51 @@ export function Availability({
onOpenInviteDialog: handleOpenInviteDialog,
} as const;
+ const isMeetingOwner = Boolean(user && meetingData.hostId === user.memberId);
+
+ const groupResponsesProps = useMemo(
+ () => ({
+ availabilityDates,
+ fromTime: fromTimeMinutes,
+ members,
+ pendingMembers,
+ timezone: userTimezone,
+ anchorNormalizedDate,
+ currentPageAvailability,
+ availabilityTimeBlocks,
+ doesntNeedDay,
+ }),
+ [
+ availabilityDates,
+ fromTimeMinutes,
+ members,
+ pendingMembers,
+ userTimezone,
+ anchorNormalizedDate,
+ currentPageAvailability,
+ availabilityTimeBlocks,
+ doesntNeedDay,
+ ],
+ );
+
+ const handleMobileAddAvailability = useCallback(() => {
+ if (!user) {
+ router.push("/auth/login/google");
+ return;
+ }
+ setChangeableTimezone(false);
+ setUserTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone);
+ setAvailabilityView("personal");
+ }, [router, setAvailabilityView, user]);
+
+ const handleMobileOpenAttendees = useCallback(() => {
+ setIsMobileDrawerOpen(true);
+ }, [setIsMobileDrawerOpen]);
+
+ const handleMobileSchedule = useCallback(() => {
+ setAvailabilityView("schedule");
+ }, [setAvailabilityView]);
+
return (