2424
2525import React , { useEffect , useState , useCallback , useMemo } from 'react' ;
2626import type { ObjectGridSchema , DataSource , ViewData , CalendarConfig } from '@object-ui/types' ;
27+ import { CalendarView , type CalendarEvent } from './CalendarView' ;
2728
2829export interface CalendarSchema {
2930 type : 'calendar' ;
@@ -34,6 +35,8 @@ export interface CalendarSchema {
3435 colorField ?: string ;
3536 filter ?: any ;
3637 sort ?: any ;
38+ /** Initial view mode */
39+ defaultView ?: 'month' | 'week' | 'day' ;
3740}
3841
3942export interface ObjectCalendarProps {
@@ -44,6 +47,8 @@ export interface ObjectCalendarProps {
4447 onDateClick ?: ( date : Date ) => void ;
4548 onEdit ?: ( record : any ) => void ;
4649 onDelete ?: ( record : any ) => void ;
50+ onNavigate ?: ( date : Date ) => void ;
51+ onViewChange ?: ( view : 'month' | 'week' | 'day' ) => void ;
4752}
4853
4954/**
@@ -131,6 +136,8 @@ export const ObjectCalendar: React.FC<ObjectCalendarProps> = ({
131136 className,
132137 onEventClick,
133138 onDateClick,
139+ onNavigate,
140+ onViewChange,
134141} ) => {
135142 const [ data , setData ] = useState < any [ ] > ( [ ] ) ;
136143 const [ loading , setLoading ] = useState ( true ) ;
@@ -265,57 +272,13 @@ export const ObjectCalendar: React.FC<ObjectCalendarProps> = ({
265272 } ) . filter ( event => ! isNaN ( event . start . getTime ( ) ) ) ; // Filter out invalid dates
266273 } , [ data , calendarConfig ] ) ;
267274
268- // Get days in current month view
269- const calendarDays = useMemo ( ( ) => {
270- const year = currentDate . getFullYear ( ) ;
271- const month = currentDate . getMonth ( ) ;
272-
273- const firstDay = new Date ( year , month , 1 ) ;
274- const lastDay = new Date ( year , month + 1 , 0 ) ;
275- const startDay = new Date ( firstDay ) ;
276- startDay . setDate ( startDay . getDate ( ) - startDay . getDay ( ) ) ; // Start from Sunday
277-
278- const days : Date [ ] = [ ] ;
279- const current = new Date ( startDay ) ;
280-
281- // Get 6 weeks worth of days
282- for ( let i = 0 ; i < 42 ; i ++ ) {
283- days . push ( new Date ( current ) ) ;
284- current . setDate ( current . getDate ( ) + 1 ) ;
285- }
286-
287- return days ;
288- } , [ currentDate ] ) ;
289-
290- // Get events for a specific day
291- const getEventsForDay = useCallback ( ( day : Date ) => {
292- return events . filter ( event => {
293- const eventStart = new Date ( event . start ) ;
294- eventStart . setHours ( 0 , 0 , 0 , 0 ) ;
295-
296- let eventEnd : Date ;
297- if ( event . end ) {
298- eventEnd = new Date ( event . end ) ;
299- } else {
300- eventEnd = new Date ( eventStart ) ;
301- }
302-
303- eventEnd . setHours ( 23 , 59 , 59 , 999 ) ;
304-
305- const checkDay = new Date ( day ) ;
306- checkDay . setHours ( 0 , 0 , 0 , 0 ) ;
307-
308- return checkDay >= eventStart && checkDay <= eventEnd ;
309- } ) ;
310- } , [ events ] ) ;
311-
312- const navigateMonth = useCallback ( ( direction : 'prev' | 'next' ) => {
313- setCurrentDate ( prev => {
314- const newDate = new Date ( prev ) ;
315- newDate . setMonth ( newDate . getMonth ( ) + ( direction === 'next' ? 1 : - 1 ) ) ;
316- return newDate ;
317- } ) ;
318- } , [ ] ) ;
275+ // Get days in current month view - REMOVED (Handled by CalendarView)
276+
277+ const handleCreate = useCallback ( ( ) => {
278+ // Standard "Create" action trigger
279+ const today = new Date ( ) ;
280+ onDateClick ?.( today ) ;
281+ } , [ onDateClick ] ) ;
319282
320283 if ( loading ) {
321284 return (
@@ -349,98 +312,25 @@ export const ObjectCalendar: React.FC<ObjectCalendarProps> = ({
349312 ) ;
350313 }
351314
352- const monthNames = [ 'January' , 'February' , 'March' , 'April' , 'May' , 'June' ,
353- 'July' , 'August' , 'September' , 'October' , 'November' , 'December' ] ;
354- const dayNames = [ 'Sun' , 'Mon' , 'Tue' , 'Wed' , 'Thu' , 'Fri' , 'Sat' ] ;
355-
356315 return (
357316 < div className = { className } >
358- < div className = "border rounded-lg bg-background" >
359- { /* Calendar Header */ }
360- < div className = "flex items-center justify-between p-4 border-b" >
361- < h2 className = "text-xl font-semibold" >
362- { monthNames [ currentDate . getMonth ( ) ] } { currentDate . getFullYear ( ) }
363- </ h2 >
364- < div className = "flex gap-2" >
365- < button
366- onClick = { ( ) => navigateMonth ( 'prev' ) }
367- className = "px-3 py-1 border rounded hover:bg-muted"
368- >
369- Previous
370- </ button >
371- < button
372- onClick = { ( ) => setCurrentDate ( new Date ( ) ) }
373- className = "px-3 py-1 border rounded hover:bg-muted"
374- >
375- Today
376- </ button >
377- < button
378- onClick = { ( ) => navigateMonth ( 'next' ) }
379- className = "px-3 py-1 border rounded hover:bg-muted"
380- >
381- Next
382- </ button >
383- </ div >
384- </ div >
385-
386- { /* Calendar Grid */ }
387- < div className = "p-4" >
388- { /* Day Headers */ }
389- < div className = "grid grid-cols-7 gap-px mb-px" >
390- { dayNames . map ( day => (
391- < div
392- key = { day }
393- className = "text-center text-sm font-medium text-muted-foreground py-2"
394- >
395- { day }
396- </ div >
397- ) ) }
398- </ div >
399-
400- { /* Calendar Days */ }
401- < div className = "grid grid-cols-7 gap-px bg-border" >
402- { calendarDays . map ( ( day , index ) => {
403- const dayEvents = getEventsForDay ( day ) ;
404- const isCurrentMonth = day . getMonth ( ) === currentDate . getMonth ( ) ;
405- const isToday =
406- day . getDate ( ) === new Date ( ) . getDate ( ) &&
407- day . getMonth ( ) === new Date ( ) . getMonth ( ) &&
408- day . getFullYear ( ) === new Date ( ) . getFullYear ( ) ;
409-
410- return (
411- < div
412- key = { index }
413- className = { `min-h-24 bg-background p-2 ${
414- ! isCurrentMonth ? 'text-muted-foreground bg-muted/30' : ''
415- } ${ isToday ? 'ring-2 ring-primary' : '' } `}
416- onClick = { ( ) => onDateClick ?.( day ) }
417- >
418- < div className = "text-sm font-medium mb-1" > { day . getDate ( ) } </ div >
419- < div className = "space-y-1" >
420- { dayEvents . slice ( 0 , 3 ) . map ( event => (
421- < div
422- key = { event . id }
423- className = "text-xs px-1 py-0.5 rounded bg-primary/10 hover:bg-primary/20 cursor-pointer truncate"
424- onClick = { ( e ) => {
425- e . stopPropagation ( ) ;
426- onEventClick ?.( event . data ) ;
427- } }
428- style = { event . color ? { borderLeft : `3px solid ${ event . color } ` } : undefined }
429- >
430- { event . title }
431- </ div >
432- ) ) }
433- { dayEvents . length > 3 && (
434- < div className = "text-xs text-muted-foreground" >
435- +{ dayEvents . length - 3 } more
436- </ div >
437- ) }
438- </ div >
439- </ div >
440- ) ;
441- } ) }
442- </ div >
443- </ div >
317+ < div className = "border rounded-lg bg-background h-[calc(100vh-200px)] min-h-[600px]" >
318+ < CalendarView
319+ events = { events }
320+ currentDate = { currentDate }
321+ view = { ( schema as any ) . defaultView || 'month' }
322+ onEventClick = { ( event ) => onEventClick ?.( event . data ) }
323+ onDateClick = { onDateClick }
324+ onNavigate = { ( date ) => {
325+ setCurrentDate ( date ) ;
326+ onNavigate ?.( date ) ;
327+ } }
328+ onViewChange = { ( v ) => {
329+ setView ( v ) ;
330+ onViewChange ?.( v ) ;
331+ } }
332+ onAddClick = { handleCreate }
333+ />
444334 </ div >
445335 </ div >
446336 ) ;
0 commit comments