diff --git a/app/api/calendar-event/route.ts b/app/api/calendar-event/route.ts index 442d47e..b330fa8 100644 --- a/app/api/calendar-event/route.ts +++ b/app/api/calendar-event/route.ts @@ -4,7 +4,6 @@ import { ApiResponse } from '../types'; import { CalendarEventType, RecurrencePattern } from '@prisma/client'; import { withAuthContext, AuthResult } from '../utils/auth'; import { toUTC, formatForResponse } from '../utils/timezone'; -import { getFamilyIdFromRequest } from '../utils/family'; // Type for calendar event response interface CalendarEventResponse { @@ -46,6 +45,7 @@ interface CalendarEventResponse { address: string | null; notes: string | null; }>; + contactIds: string[]; } // Type for calendar event create/update @@ -71,6 +71,11 @@ interface CalendarEventCreate { async function handleGet(req: NextRequest, authContext: AuthResult) { try { + const { familyId: userFamilyId } = authContext; + if (!userFamilyId) { + return NextResponse.json>({ success: false, error: 'User is not associated with a family.' }, { status: 403 }); + } + const { searchParams } = new URL(req.url); const id = searchParams.get('id'); const babyId = searchParams.get('babyId'); @@ -81,19 +86,12 @@ async function handleGet(req: NextRequest, authContext: AuthResult) { const typeParam = searchParams.get('type'); const recurringParam = searchParams.get('recurring'); - // Get family ID from request - const familyId = await getFamilyIdFromRequest(req); - // Build where clause const where: any = { deletedAt: null, + familyId: userFamilyId, }; - // Add family filter if available - if (familyId) { - where.familyId = familyId; - } - // Add filters if (id) { where.id = id; @@ -140,8 +138,8 @@ async function handleGet(req: NextRequest, authContext: AuthResult) { // If ID is provided, fetch a single event if (id) { - const event = await prisma.calendarEvent.findUnique({ - where: { id }, + const event = await prisma.calendarEvent.findFirst({ + where: { id, familyId: userFamilyId }, include: { babies: { include: { @@ -177,18 +175,7 @@ async function handleGet(req: NextRequest, authContext: AuthResult) { return NextResponse.json>( { success: false, - error: 'Calendar event not found', - }, - { status: 404 } - ); - } - - // Check family access - if (familyId && event.familyId !== familyId) { - return NextResponse.json>( - { - success: false, - error: 'Calendar event not found', + error: 'Calendar event not found or access denied', }, { status: 404 } ); @@ -206,6 +193,7 @@ async function handleGet(req: NextRequest, authContext: AuthResult) { babies: event.babies.map(be => be.baby), caretakers: event.caretakers.map(ce => ce.caretaker), contacts: event.contacts.map(ce => ce.contact), + contactIds: event.contacts.map(ce => ce.contact.id), }; return NextResponse.json>({ @@ -263,6 +251,7 @@ async function handleGet(req: NextRequest, authContext: AuthResult) { babies: event.babies.map(be => be.baby), caretakers: event.caretakers.map(ce => ce.caretaker), contacts: event.contacts.map(ce => ce.contact), + contactIds: event.contacts.map(ce => ce.contact.id), })); return NextResponse.json>({ @@ -283,26 +272,59 @@ async function handleGet(req: NextRequest, authContext: AuthResult) { async function handlePost(req: NextRequest, authContext: AuthResult) { try { + const { familyId: userFamilyId, caretakerId: userCaretakerId } = authContext; + if (!userFamilyId) { + return NextResponse.json>({ success: false, error: 'User is not associated with a family.' }, { status: 403 }); + } + const body: CalendarEventCreate = await req.json(); // Validate required fields if (!body.title || !body.startTime || body.type === undefined || body.allDay === undefined) { - return NextResponse.json>( - { - success: false, - error: 'Missing required fields', - }, - { status: 400 } - ); + return NextResponse.json>({ success: false, error: 'Missing required fields' }, { status: 400 }); + } + + // Validate that all associated entities belong to the user's family + if (body.babyIds.length > 0) { + const babiesCount = await prisma.baby.count({ + where: { + id: { in: body.babyIds }, + familyId: userFamilyId, + }, + }); + if (babiesCount !== body.babyIds.length) { + return NextResponse.json>({ success: false, error: 'One or more babies not found in this family.' }, { status: 404 }); + } + } + + if (body.caretakerIds.length > 0) { + const caretakersCount = await prisma.caretaker.count({ + where: { + id: { in: body.caretakerIds }, + familyId: userFamilyId, + }, + }); + if (caretakersCount !== body.caretakerIds.length) { + return NextResponse.json>({ success: false, error: 'One or more caretakers not found in this family.' }, { status: 404 }); + } + } + + if (body.contactIds.length > 0) { + const contactsCount = await prisma.contact.count({ + where: { + id: { in: body.contactIds }, + familyId: userFamilyId, + }, + }); + if (contactsCount !== body.contactIds.length) { + return NextResponse.json>({ success: false, error: 'One or more contacts not found in this family.' }, { status: 404 }); + } } - // Get family ID from request (with fallback to body) - const familyId = await getFamilyIdFromRequest(req) || body.familyId; - // Convert dates to UTC for storage const startTimeUTC = toUTC(body.startTime); - const endTimeUTC = body.endTime ? toUTC(body.endTime) : undefined; - const recurrenceEndUTC = body.recurrenceEnd ? toUTC(body.recurrenceEnd) : undefined; + const endTimeUTC = body.endTime ? toUTC(body.endTime) : null; + const recurrenceEndUTC = body.recurrenceEnd ? toUTC(body.recurrenceEnd) : null; // Create event const event = await prisma.calendarEvent.create({ @@ -310,7 +332,7 @@ async function handlePost(req: NextRequest, authContext: AuthResult) { title: body.title, description: body.description || null, startTime: startTimeUTC, - endTime: endTimeUTC || null, + endTime: endTimeUTC, allDay: body.allDay, type: body.type, location: body.location || null, @@ -321,23 +343,17 @@ async function handlePost(req: NextRequest, authContext: AuthResult) { customRecurrence: body.customRecurrence || null, reminderTime: body.reminderTime || null, notificationSent: false, - familyId: familyId || null, + familyId: userFamilyId || null, // Create relationships babies: { - create: (body.babyIds || []).map(babyId => ({ - baby: { connect: { id: babyId } }, - })), + create: body.babyIds.map(babyId => ({ babyId })), }, caretakers: { - create: (body.caretakerIds || []).map(caretakerId => ({ - caretaker: { connect: { id: caretakerId } }, - })), + create: body.caretakerIds.map(caretakerId => ({ caretakerId })), }, contacts: { - create: (body.contactIds || []).map(contactId => ({ - contact: { connect: { id: contactId } }, - })), + create: body.contactIds.map(contactId => ({ contactId })), }, }, include: { @@ -383,6 +399,7 @@ async function handlePost(req: NextRequest, authContext: AuthResult) { babies: event.babies.map(be => be.baby), caretakers: event.caretakers.map(ce => ce.caretaker), contacts: event.contacts.map(ce => ce.contact), + contactIds: event.contacts.map(ce => ce.contact.id), }; return NextResponse.json>({ @@ -391,7 +408,7 @@ async function handlePost(req: NextRequest, authContext: AuthResult) { }, { status: 201 }); } catch (error) { console.error('Error creating calendar event:', error); - return NextResponse.json>( + return NextResponse.json>( { success: false, error: 'Failed to create calendar event', @@ -403,51 +420,57 @@ async function handlePost(req: NextRequest, authContext: AuthResult) { async function handlePut(req: NextRequest, authContext: AuthResult) { try { - const { searchParams } = new URL(req.url); - const id = searchParams.get('id'); - const body: CalendarEventCreate = await req.json(); - - if (!id) { - return NextResponse.json>( - { - success: false, - error: 'Calendar event ID is required', - }, - { status: 400 } - ); + const { familyId: userFamilyId } = authContext; + if (!userFamilyId) { + return NextResponse.json>({ success: false, error: 'User is not associated with a family.' }, { status: 403 }); } - // Get family ID from request (with fallback to body) - const familyId = await getFamilyIdFromRequest(req) || body.familyId; + const { searchParams } = new URL(req.url); + const id = searchParams.get('id'); + const body: Partial = await req.json(); - // Check if event exists and belongs to the family - const existingEvent = await prisma.calendarEvent.findUnique({ - where: { id }, + if (!id) { + return NextResponse.json>({ success: false, error: 'Calendar event ID is required' }, { status: 400 }); + } + + const existingEvent = await prisma.calendarEvent.findFirst({ + where: { id, familyId: userFamilyId }, }); if (!existingEvent || existingEvent.deletedAt) { - return NextResponse.json>( - { - success: false, - error: 'Calendar event not found', - }, - { status: 404 } - ); + return NextResponse.json>({ success: false, error: 'Calendar event not found or access denied' }, { status: 404 }); } - // Check family access - if (familyId && existingEvent.familyId !== familyId) { - return NextResponse.json>( - { - success: false, - error: 'Calendar event not found', - }, - { status: 404 } - ); + // Validate associated entities + if (body.babyIds && body.babyIds.length > 0) { + const babiesCount = await prisma.baby.count({ + where: { id: { in: body.babyIds }, familyId: userFamilyId }, + }); + if (babiesCount !== body.babyIds.length) { + return NextResponse.json>({ success: false, error: 'One or more babies not found in this family.' }, { status: 404 }); + } } - + + if (body.caretakerIds && body.caretakerIds.length > 0) { + const caretakersCount = await prisma.caretaker.count({ + where: { id: { in: body.caretakerIds }, familyId: userFamilyId }, + }); + if (caretakersCount !== body.caretakerIds.length) { + return NextResponse.json>({ success: false, error: 'One or more caretakers not found in this family.' }, { status: 404 }); + } + } + + if (body.contactIds && body.contactIds.length > 0) { + const contactsCount = await prisma.contact.count({ + where: { id: { in: body.contactIds }, familyId: userFamilyId }, + }); + if (contactsCount !== body.contactIds.length) { + return NextResponse.json>({ success: false, error: 'One or more contacts not found in this family.' }, { status: 404 }); + } + } + // Convert dates to UTC for storage - const startTimeUTC = toUTC(body.startTime); + const startTimeUTC = body.startTime ? toUTC(body.startTime) : undefined; const endTimeUTC = body.endTime ? toUTC(body.endTime) : undefined; const recurrenceEndUTC = body.recurrenceEnd ? toUTC(body.recurrenceEnd) : undefined; @@ -475,24 +498,21 @@ async function handlePut(req: NextRequest, authContext: AuthResult) { recurrenceEnd: recurrenceEndUTC || null, customRecurrence: body.customRecurrence || null, reminderTime: body.reminderTime || null, - familyId: familyId || existingEvent.familyId, // Preserve existing familyId if not provided + familyId: userFamilyId || existingEvent.familyId, // Preserve existing familyId if not provided // Create new relationships - babies: { - create: (body.babyIds || []).map(babyId => ({ - baby: { connect: { id: babyId } }, - })), - }, - caretakers: { - create: (body.caretakerIds || []).map(caretakerId => ({ - caretaker: { connect: { id: caretakerId } }, - })), - }, - contacts: { - create: (body.contactIds || []).map(contactId => ({ - contact: { connect: { id: contactId } }, - })), - }, + babies: body.babyIds ? { + deleteMany: {}, + create: body.babyIds.map(babyId => ({ babyId })), + } : undefined, + caretakers: body.caretakerIds ? { + deleteMany: {}, + create: body.caretakerIds.map(caretakerId => ({ caretakerId })), + } : undefined, + contacts: body.contactIds ? { + deleteMany: {}, + create: body.contactIds.map(contactId => ({ contactId })), + } : undefined, }, include: { babies: { @@ -540,6 +560,7 @@ async function handlePut(req: NextRequest, authContext: AuthResult) { babies: updatedEvent.babies.map(be => be.baby), caretakers: updatedEvent.caretakers.map(ce => ce.caretaker), contacts: updatedEvent.contacts.map(ce => ce.contact), + contactIds: updatedEvent.contacts.map(ce => ce.contact.id), }; return NextResponse.json>({ @@ -548,7 +569,7 @@ async function handlePut(req: NextRequest, authContext: AuthResult) { }); } catch (error) { console.error('Error updating calendar event:', error); - return NextResponse.json>( + return NextResponse.json>( { success: false, error: 'Failed to update calendar event', @@ -560,50 +581,25 @@ async function handlePut(req: NextRequest, authContext: AuthResult) { async function handleDelete(req: NextRequest, authContext: AuthResult) { try { + const { familyId: userFamilyId } = authContext; + if (!userFamilyId) { + return NextResponse.json>({ success: false, error: 'User is not associated with a family.' }, { status: 403 }); + } + const { searchParams } = new URL(req.url); const id = searchParams.get('id'); if (!id) { - return NextResponse.json>( - { - success: false, - error: 'Calendar event ID is required', - }, - { status: 400 } - ); + return NextResponse.json>({ success: false, error: 'Calendar event ID is required' }, { status: 400 }); } - // Get family ID from request - const familyId = await getFamilyIdFromRequest(req); - - // Check if event exists - const existingEvent = await prisma.calendarEvent.findUnique({ - where: { id }, + const existingEvent = await prisma.calendarEvent.findFirst({ + where: { id, familyId: userFamilyId }, }); if (!existingEvent) { - return NextResponse.json>( - { - success: false, - error: 'Calendar event not found', - }, - { status: 404 } - ); + return NextResponse.json>({ success: false, error: 'Calendar event not found or access denied' }, { status: 404 }); } - - // Check family access - if (familyId && existingEvent.familyId !== familyId) { - return NextResponse.json>( - { - success: false, - error: 'Calendar event not found', - }, - { status: 404 } - ); - } - - // Allow deleting even if it's already marked as deleted - // This prevents errors when trying to delete an event multiple times // Soft delete the event await prisma.calendarEvent.update({ @@ -613,12 +609,10 @@ async function handleDelete(req: NextRequest, authContext: AuthResult) { }, }); - return NextResponse.json>({ - success: true, - }); + return NextResponse.json>({ success: true }); } catch (error) { console.error('Error deleting calendar event:', error); - return NextResponse.json>( + return NextResponse.json>( { success: false, error: 'Failed to delete calendar event', diff --git a/documentation/Family-Documentation/adding-family-context-to-auth.md b/documentation/Family-Documentation/adding-family-context-to-auth.md index 5ba682f..14962e8 100644 --- a/documentation/Family-Documentation/adding-family-context-to-auth.md +++ b/documentation/Family-Documentation/adding-family-context-to-auth.md @@ -121,7 +121,7 @@ This checklist tracks the progress of refactoring each component and its associa - API: `app/api/sleep-log/` ### Other Components -- [ ] **Calendar** +- [x] **Calendar** - Form: `src/components/forms/CalendarEventForm/` - API: `app/api/calendar-event/` - [x] **Contacts** diff --git a/src/components/Calendar/README.md b/src/components/Calendar/README.md index 0110beb..d83f5aa 100644 --- a/src/components/Calendar/README.md +++ b/src/components/Calendar/README.md @@ -20,22 +20,11 @@ A responsive calendar component for the Baby Tracker application that displays a import { Calendar } from '@/src/components/Calendar'; function CalendarPage() { - const { selectedBaby } = useBaby(); const { userTimezone } = useTimezone(); return (
- {selectedBaby ? ( - - ) : ( -
-

No Baby Selected

-

Please select a baby from the dropdown menu above.

-
- )} +
); } @@ -51,7 +40,7 @@ Main component for displaying a monthly calendar with activity indicators. | Prop | Type | Description | Default | |------|------|-------------|---------| -| `selectedBabyId` | `string \| undefined` | The ID of the currently selected baby | Required | +| `onDateSelect` | `(date: Date) => void` | Optional callback when a date is selected | `undefined` | | `userTimezone` | `string` | The user's timezone for date calculations | Required | ## Visual Behavior @@ -63,6 +52,7 @@ Main component for displaying a monthly calendar with activity indicators. - Month and year are displayed in the header - Navigation buttons allow moving to previous/next months - "Today" button returns to the current month +- The component will handle sending this timezone to the API ## Implementation Details diff --git a/src/components/Calendar/index.tsx b/src/components/Calendar/index.tsx index 36239c2..f7363a4 100644 --- a/src/components/Calendar/index.tsx +++ b/src/components/Calendar/index.tsx @@ -101,8 +101,6 @@ export function Calendar({ selectedBabyId, userTimezone, onDateSelect }: Calenda * Fetch events for the selected month */ const fetchEvents = async () => { - if (!selectedBabyId) return; - try { // Create start date (first day of month) and end date (last day of month) const year = currentDate.getFullYear(); @@ -115,11 +113,10 @@ export function Calendar({ selectedBabyId, userTimezone, onDateSelect }: Calenda endDate.setHours(23, 59, 59, 999); console.log(`Fetching events for date range: ${startDate.toISOString()} to ${endDate.toISOString()}`); - console.log(`Baby ID: ${selectedBabyId}, Timezone: ${userTimezone}`); // Fetch calendar events const eventsResponse = await fetch( - `/api/calendar-event?babyId=${selectedBabyId}&startDate=${startDate.toISOString()}&endDate=${endDate.toISOString()}&timezone=${encodeURIComponent(userTimezone)}` + `/api/calendar-event?startDate=${startDate.toISOString()}&endDate=${endDate.toISOString()}` ); const eventsData = await eventsResponse.json(); @@ -166,7 +163,7 @@ export function Calendar({ selectedBabyId, userTimezone, onDateSelect }: Calenda */ useEffect(() => { fetchEvents(); - }, [selectedBabyId, currentDate, userTimezone]); + }, [currentDate, userTimezone]); // Removed fetchEventsForSelectedDay and its useEffect hook diff --git a/src/components/CalendarDayView/index.tsx b/src/components/CalendarDayView/index.tsx index c88510a..54df125 100644 --- a/src/components/CalendarDayView/index.tsx +++ b/src/components/CalendarDayView/index.tsx @@ -14,7 +14,6 @@ import { import CalendarEventForm from '@/src/components/forms/CalendarEventForm'; import { CalendarEventFormData } from '@/src/components/forms/CalendarEventForm/calendar-event-form.types'; import './calendar-day-view.css'; -import { useFamily } from '@/src/context/family'; /** * CalendarDayView Component @@ -41,7 +40,6 @@ export const CalendarDayView: React.FC = ({ onClose, isOpen, }) => { - const { family } = useFamily(); // State for event form const [showEventForm, setShowEventForm] = useState(false); @@ -54,22 +52,16 @@ export const CalendarDayView: React.FC = ({ React.useEffect(() => { const fetchData = async () => { try { - // Build URLs with family ID for proper data filtering - const urlParams = new URLSearchParams(); - if (family?.id) { - urlParams.append('familyId', family.id); - } - // Fetch babies - const babiesResponse = await fetch(`/api/baby?${urlParams.toString()}`); + const babiesResponse = await fetch('/api/baby'); const babiesData = await babiesResponse.json(); // Fetch caretakers - const caretakersResponse = await fetch(`/api/caretaker?${urlParams.toString()}`); + const caretakersResponse = await fetch('/api/caretaker'); const caretakersData = await caretakersResponse.json(); // Fetch contacts - const contactsResponse = await fetch(`/api/contact?${urlParams.toString()}`); + const contactsResponse = await fetch('/api/contact'); const contactsData = await contactsResponse.json(); // Update state with fetched data @@ -84,7 +76,7 @@ export const CalendarDayView: React.FC = ({ if (isOpen) { fetchData(); } - }, [isOpen, family?.id]); + }, [isOpen]); // Format date for display const formattedDate = useMemo(() => { @@ -250,26 +242,14 @@ export const CalendarDayView: React.FC = ({ // Handle event delete const handleDeleteEvent = async (eventId: string) => { - if (!eventId) return; - try { const response = await fetch(`/api/calendar-event?id=${eventId}`, { method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ familyId: family?.id }), }); - const data = await response.json(); - if (data.success) { - // Close form - setShowEventForm(false); - - // Notify parent component to refresh if (onAddEvent) { - onAddEvent(date); + onAddEvent(date); // Trigger refresh } } else { console.error('Error deleting event:', data.error); @@ -304,81 +284,83 @@ export const CalendarDayView: React.FC = ({ // Events state - grouped by time of day return ( -
- {/* Morning events */} - {groupedEvents.morning.length > 0 && ( -
-
- -

- Morning -

+
+
+ {/* Morning events */} + {groupedEvents.morning.length > 0 && ( +
+
+ +

+ Morning +

+
+ +
+ {groupedEvents.morning.map(event => ( + + ))} +
- -
- {groupedEvents.morning.map(event => ( - - ))} + )} + + {/* Afternoon events */} + {groupedEvents.afternoon.length > 0 && ( +
+
+ +

+ Afternoon +

+
+ +
+ {groupedEvents.afternoon.map(event => ( + + ))} +
-
- )} - - {/* Afternoon events */} - {groupedEvents.afternoon.length > 0 && ( -
-
- -

- Afternoon -

+ )} + + {/* Evening events */} + {groupedEvents.evening.length > 0 && ( +
+
+ +

+ Evening +

+
+ +
+ {groupedEvents.evening.map(event => ( + + ))} +
- -
- {groupedEvents.afternoon.map(event => ( - - ))} -
-
- )} - - {/* Evening events */} - {groupedEvents.evening.length > 0 && ( -
-
- -

- Evening -

-
- -
- {groupedEvents.evening.map(event => ( - - ))} -
-
- )} + )} +
); }; @@ -390,27 +372,22 @@ export const CalendarDayView: React.FC = ({ isOpen={isOpen} onClose={handleClose} title={formattedDate} - className={cn('calendar-day-view-slide-in', className)} + className={cn(styles.container, className)} > - - {renderContent()} + +
+ {renderContent()} +
- - - - {onAddEvent && ( +
- )} +
- - {/* Calendar Event Form */} = ({ babies={babies} caretakers={caretakers} contacts={contacts} - familyId={family?.id} /> ); diff --git a/src/components/forms/CalendarEventForm/README.md b/src/components/forms/CalendarEventForm/README.md index 26ccc1e..40e4f48 100644 --- a/src/components/forms/CalendarEventForm/README.md +++ b/src/components/forms/CalendarEventForm/README.md @@ -15,7 +15,6 @@ A comprehensive form component for creating and editing calendar events in the B - Responsive design for mobile and desktop - Dark mode support - Accessible UI with proper semantic structure -- Multi-family support with family ID association ## Usage @@ -90,7 +89,6 @@ Main component for creating and editing calendar events. | `caretakers` | `Caretaker[]` | Available caretakers to select | Required | | `contacts` | `Contact[]` | Available contacts to select | Required | | `isLoading` | `boolean` | Whether the form is in a loading state | `false` | -| `familyId` | `string` | The ID of the family this event belongs to (for multi-family support) | `undefined` | ### CalendarEventFormData @@ -199,34 +197,6 @@ The component follows a modular structure: - `calendar-event-form.types.ts` - TypeScript type definitions - `calendar-event-form.css` - Additional CSS for dark mode and animations -### Multi-Family Support - -The component supports multi-family functionality by: -- Accepting a `familyId` prop to associate the calendar event with a specific family -- Including the family ID in the API request payload for create, update, and delete operations -- Adding the family ID to the CalendarEventFormData interface - -When using this component in a multi-family context, you should: -1. Import and use the family context to get the current family ID -2. Pass the family ID to the CalendarEventForm component -3. The component will handle sending this ID to the API - -```tsx -import { useFamily } from '@/src/context/family'; -import { CalendarEventForm } from '@/src/components/forms/CalendarEventForm'; - -function CalendarPage() { - const { family } = useFamily(); // Get current family from context - - return ( - - ); -} -``` - ## Accessibility The component includes: diff --git a/src/components/forms/CalendarEventForm/index.tsx b/src/components/forms/CalendarEventForm/index.tsx index 8081113..4271002 100644 --- a/src/components/forms/CalendarEventForm/index.tsx +++ b/src/components/forms/CalendarEventForm/index.tsx @@ -21,7 +21,6 @@ import { DropdownMenuItem, } from '@/src/components/ui/dropdown-menu'; import './calendar-event-form.css'; -import { useFamily } from '@/src/context/family'; /** * CalendarEventForm Component @@ -39,9 +38,7 @@ const CalendarEventForm: React.FC = ({ caretakers, contacts, isLoading = false, - familyId, }) => { - const { family } = useFamily(); // Helper function to get initial form data const getInitialFormData = ( @@ -168,7 +165,7 @@ const CalendarEventForm: React.FC = ({ const handleCheckboxChange = (e: React.ChangeEvent) => { const { name, checked } = e.target; setFormData(prev => ({ ...prev, [name]: checked })); - }; // <-- Added missing closing brace + }; // Handle start date/time change with DateTimePicker const handleStartDateTimeChange = (date: Date) => { @@ -399,13 +396,8 @@ const CalendarEventForm: React.FC = ({ // Handle form submission const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - if (validateForm()) { - // Include familyId in the form data when submitting - onSave({ - ...formData, - familyId: familyId || family?.id || undefined, - }); + onSave(formData); } }; @@ -414,27 +406,20 @@ const CalendarEventForm: React.FC = ({ onClose(); }; + if (!isOpen) return null; + return ( - -
- -
+ + + +
{/* Event details section */}

Event Details

{/* Title */}
-
)}
- + {/* Event type */}
-
- + {/* Date and time - each on its own row */}
{/* Start Date/Time - Full width */}
-