11<script lang =" ts" >
22 import type { EventInitFormData } from ' @axium/calendar/client' ;
3- import { getCalPermissionsInfo , weekDaysFor , type EventInit } from ' @axium/calendar/common' ;
3+ import { getCalPermissionsInfo , weekDaysFor , type Event , type EventInit } from ' @axium/calendar/common' ;
44 import * as Calendar from ' @axium/calendar/components' ;
55 import { contextMenu , dynamicRows } from ' @axium/client/attachments' ;
6- import { AccessControlDialog , FormDialog , Icon , Popover , ZodInput , ZodForm } from ' @axium/client/components' ;
6+ import { AccessControlDialog , FormDialog , Icon , Popover } from ' @axium/client/components' ;
7+ import UserDiscovery from ' @axium/client/components/UserDiscovery' ;
78 import { fetchAPI } from ' @axium/client/requests' ;
89 import { SvelteDate } from ' svelte/reactivity' ;
9- import { _throw } from ' utilium' ;
10- import * as z from ' zod' ;
10+ import { _throw , type WithRequired } from ' utilium' ;
11+ import z from ' zod' ;
1112 const { data } = $props ();
1213
1314 const { user } = data .session ;
2728
2829 let dialogs = $state <Record <string , HTMLDialogElement >>({});
2930
30- let eventInit = $state <EventInit >({ } as EventInit );
31+ let eventInit = $state <WithRequired < EventInit , ' attendees ' >>({ attendees: [] } as any );
3132 </script >
3233
3334<svelte:head >
146147 </div>
147148</div>
148149
149- <!--
150- export const EventInit = z.object({
151- calId: z .uuid (),
152- summary: z .string (),
153- location: z .string ().nullish (),
154- start: z .coerce .date (),
155- end: z .coerce .date (),
156- description: z .string ().nullish (),
157- attendees: AttendeeInit .array ().optional ().default ([]),
158- // note: recurrences are not support yet
159- recurrence: z .string ().nullish (),
160- recurrenceExcludes: z .array (z .string ()).nullish (),
161- recurrenceId: z .uuid ().nullish (),
162- });
163- -- >
164-
165150<FormDialog
166151 id="new-event"
167152 submitText="Create"
168- submit = {(data: EventInitFormData ) => fetchAPI (' PUT' , ' calendars/:id/events' , { ... data , ... eventInit , attendees: [] }, data .calId )}
153+ submit={async (data: EventInitFormData ) => {
154+ const calendar = calendars .find (cal => cal .id == data .calId );
155+ if (! calendar ) throw ' Invalid calendar' ;
156+ const event: Event = await fetchAPI (
157+ ' PUT' ,
158+ ' calendars/:id/events' ,
159+ { ... data , ... eventInit , recurrenceExcludes: [], recurrenceId: null },
160+ data .calId
161+ );
162+ event .calendar = calendar ;
163+ calendar .events ?.push (event );
164+ }}
169165>
170166 < input name = " summary" type = " text" required placeholder = " Add title" / >
171167 < div class = " event-times-container" >
@@ -174,13 +170,15 @@ export const EventInit = z.object({
174170 < input type = " datetime-local" name = " start" id = " eventInit.start" required / >
175171 < input type = " datetime-local" name = " end" id = " eventInit.end" required / >
176172 < div class = " event-time-options" >
177- < input bind :checked = {eventInit.isAllDay } id = " eventInit.isAllDay:checkbox" type = " checkbox" required / >
173+ < input bind :checked = {eventInit.isAllDay } id = " eventInit.isAllDay:checkbox" type = " checkbox" / >
178174 < label for = " eventInit.isAllDay:checkbox" class = " checkbox" >
179175 {#if eventInit .isAllDay }< Icon i = " check" -- size = " 1.3em" / > {/if }
180176 < / label >
181177 < label for = " eventInit.isAllDay:checkbox" > All day < / label >
182178 < div class = " spacing" > </div >
183- < select class = " recurrence" > </select >
179+ < select class = " recurrence" >
180+ < ! -- @todo -- >
181+ < / select >
184182 < / div >
185183 < / div >
186184 < / div >
@@ -194,6 +192,27 @@ export const EventInit = z.object({
194192 < / select >
195193 < / div >
196194
195+ < div class = " attendees-container" >
196+ < label for = " eventInit.attendee" > <Icon i =" user-group" /></label >
197+ < div class = " attendees" >
198+ < UserDiscovery
199+ noRoles
200+ allowExact
201+ onSelect = {target => {
202+ const { data : userId } = z .uuid ().safeParse (target );
203+ const { data : email } = z .email ().safeParse (target );
204+ if (! userId && ! email ) throw ' Can not determine attendee: ' + target ;
205+ if (! email ) throw ' Specifying attendees without an email is not supported yet' ;
206+ // @todo supports roles and also contacts
207+ eventInit .attendees .push ({ userId , email });
208+ }}
209+ / >
210+ {#each eventInit .attendees as attendee (attendee .email )}
211+ < div class = " attendee" > {attendee.email }< / div >
212+ {/ each }
213+ < / div >
214+ < / div >
215+
197216 <div >
198217 < label for = " eventInit.location" > <Icon i =" location-dot" /></label >
199218 < input name = " location" id = " eventInit.location" placeholder = " Add location" / >
@@ -244,13 +263,15 @@ export const EventInit = z.object({
244263 div :has (label ~ input ),
245264 div :has (label ~ textarea ),
246265 div :has (label ~ select ),
247- .event - times - container {
266+ .event - times - container ,
267+ .attendees - container {
248268 display : flex ;
249269 flex - direction : row ;
250270 gap : 0.5em ;
251271 }
252272
253- div .event - times {
273+ div .event - times ,
274+ div .attendees {
254275 display : flex ;
255276 flex - direction : column ;
256277 gap : 0.5em ;
0 commit comments