1
1
import FullCalendar from "@fullcalendar/react" ;
2
2
import interactionPlugin from "@fullcalendar/interaction" ;
3
3
import timeGridPlugin from "@fullcalendar/timegrid" ;
4
- import { EventChangeArg , EventInput } from "@fullcalendar/core" ;
4
+ import { DateSelectArg , EventChangeArg , EventInput } from "@fullcalendar/core" ;
5
5
import { formatDate , getDateFromTimeAndWeekday , getTime , isSame , Modal , useDisclosure , useMantineTheme } from "@quassel/ui" ;
6
6
import { QuestionnaireEntry } from "./QuestionnaireEntry" ;
7
7
import { components } from "../../../api.gen" ;
8
8
import { EntityForm , EntryFormValues } from "./EntryForm" ;
9
9
import { useEffect , useState } from "react" ;
10
10
import { i18n } from "../../../stores/i18n" ;
11
11
import { useStore } from "@nanostores/react" ;
12
+ import { GapsPerDay } from "../../../utils/entry" ;
13
+ import { EventImpl } from "@fullcalendar/core/internal" ;
12
14
13
15
const calendarBaseConfig : FullCalendar [ "props" ] = {
14
16
allDaySlot : false ,
@@ -27,10 +29,13 @@ const calendarBaseConfig: FullCalendar["props"] = {
27
29
eventLongPressDelay : 400 ,
28
30
} ;
29
31
30
- export type ExtendedEvent = EventInput & { extendedProps : { entryLanguages : components [ "schemas" ] [ "EntryLanguageResponseDto" ] [ ] } } ;
32
+ export type ExtendedEvent = EventInput & {
33
+ extendedProps ?: { entryLanguages : components [ "schemas" ] [ "EntryLanguageResponseDto" ] [ ] ; weeklyRecurring ?: number } ;
34
+ } ;
31
35
32
36
export type EntryCalendarProps = {
33
37
entries : components [ "schemas" ] [ "QuestionnaireEntryDto" ] [ ] ;
38
+ gaps ?: GapsPerDay ;
34
39
onAddEntry : ( entry : EntryFormValues , weekday : number ) => Promise < unknown > ;
35
40
onUpdateEntry : ( id : number , entry : Partial < EntryFormValues > , weekday : number ) => Promise < unknown > ;
36
41
onDeleteEntry : ( id : number ) => Promise < unknown > ;
@@ -47,6 +52,7 @@ const messages = i18n("entryCalendar", {
47
52
48
53
export function EntryCalendar ( {
49
54
entries,
55
+ gaps,
50
56
onAddEntry,
51
57
onUpdateEntry,
52
58
onDeleteEntry,
@@ -69,19 +75,48 @@ export function EntryCalendar({
69
75
70
76
useEffect ( ( ) => {
71
77
if ( entries ) {
72
- setEvents (
73
- entries . map ( ( { startedAt, endedAt, weekday, carer, entryLanguages, id } ) => ( {
78
+ setEvents ( [
79
+ ... entries . map ( ( { startedAt, endedAt, weekday, carer, weeklyRecurring , entryLanguages, id } ) => ( {
74
80
id : id . toString ( ) ,
75
81
start : getDateFromTimeAndWeekday ( startedAt , weekday ) ,
76
82
end : getDateFromTimeAndWeekday ( endedAt , weekday ) ,
77
83
title : carer . name ,
78
- extendedProps : { entryLanguages } ,
84
+ extendedProps : { entryLanguages, weeklyRecurring } ,
79
85
backgroundColor : carer . color ?? theme . colors [ theme . primaryColor ] [ 4 ] ,
80
86
borderColor : carer . color ?? theme . colors [ theme . primaryColor ] [ 4 ] ,
81
- } ) ) ?? [ ]
82
- ) ;
87
+ } ) ) ,
88
+ ...( gaps ?? [ ] ) . flatMap ( ( dailyGaps , index ) =>
89
+ dailyGaps . map ( ( gap ) => ( {
90
+ start : getDateFromTimeAndWeekday ( gap [ 0 ] , index ) ,
91
+ end : getDateFromTimeAndWeekday ( gap [ 1 ] , index ) ,
92
+ backgroundColor : theme . colors . uzhBerry [ 4 ] ,
93
+ display : "background" ,
94
+ } ) )
95
+ ) ,
96
+ ] ) ;
83
97
}
84
- } , [ entries ] ) ;
98
+ } , [ entries , gaps ] ) ;
99
+
100
+ const setupEntryUpdate = ( event : EventImpl ) => {
101
+ const { carer, entryLanguages, id, weekday, ...rest } = entries ?. find ( ( entry ) => entry . id . toString ( ) === event . id ) ?? { } ;
102
+
103
+ setEntryDraft ( {
104
+ carer : carer ?. id ,
105
+ entryLanguages : entryLanguages ?. map ( ( { language, ...rest } ) => ( { ...rest , language : language . id } ) ) ,
106
+ ...rest ,
107
+ startedAt : getTime ( event . start ! ) ,
108
+ endedAt : getTime ( event . end ! ) ,
109
+ } ) ;
110
+ setSelectedWeekday ( weekday ) ;
111
+ setEntryUpdadingId ( id ) ;
112
+ open ( ) ;
113
+ } ;
114
+
115
+ const setupEntryCreate = ( { start, end } : DateSelectArg | EventImpl ) => {
116
+ setEntryDraft ( { startedAt : getTime ( start ! ) , endedAt : getTime ( end ! ) } ) ;
117
+ setSelectedWeekday ( start ! . getDay ( ) ) ;
118
+ open ( ) ;
119
+ } ;
85
120
86
121
const handleEventChange = ( { event } : EventChangeArg ) => {
87
122
const { id, start, end } = event ;
@@ -119,24 +154,13 @@ export function EntryCalendar({
119
154
{ ...calendarBaseConfig }
120
155
plugins = { [ timeGridPlugin , interactionPlugin ] }
121
156
events = { events }
122
- select = { ( { start, end } ) => {
123
- setEntryDraft ( { startedAt : getTime ( start ) , endedAt : getTime ( end ) } ) ;
124
- setSelectedWeekday ( start . getDay ( ) ) ;
125
- open ( ) ;
126
- } }
157
+ select = { setupEntryCreate }
127
158
eventClick = { ( { event } ) => {
128
- const { carer, entryLanguages, id, weekday, ...rest } = entries ?. find ( ( entry ) => entry . id . toString ( ) === event . id ) ?? { } ;
129
-
130
- setEntryDraft ( {
131
- carer : carer ?. id ,
132
- entryLanguages : entryLanguages ?. map ( ( { language, ...rest } ) => ( { ...rest , language : language . id } ) ) ,
133
- ...rest ,
134
- startedAt : getTime ( event . start ! ) ,
135
- endedAt : getTime ( event . end ! ) ,
136
- } ) ;
137
- setSelectedWeekday ( weekday ) ;
138
- setEntryUpdadingId ( id ) ;
139
- open ( ) ;
159
+ if ( event . display === "background" ) {
160
+ setupEntryCreate ( event ) ;
161
+ } else {
162
+ setupEntryUpdate ( event ) ;
163
+ }
140
164
} }
141
165
eventChange = { handleEventChange }
142
166
eventContent = { ( { event } ) => < QuestionnaireEntry event = { event } /> }
0 commit comments