@remit/web-client 0.0.231 → 0.0.232
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/calendar/CalendarComposePane.stories.tsx +101 -11
- package/src/components/calendar/CalendarComposePane.tsx +83 -23
- package/src/components/calendar/CalendarComposeSeed.tsx +35 -0
- package/src/components/calendar/CalendarEventPane.stories.tsx +30 -1
- package/src/components/calendar/CalendarEventPane.tsx +28 -5
- package/src/components/calendar/CalendarWorkspace.stories.tsx +22 -0
- package/src/components/calendar/CalendarWorkspace.tsx +31 -1
- package/src/components/calendar/OpenCalendarEvent.tsx +189 -7
- package/src/components/calendar/WriteCalendarEvent.tsx +94 -0
- package/src/components/calendar/calendar-write-flow.render.test.ts +356 -0
- package/src/hooks/calendar/calendar-reads.render.test.ts +265 -0
- package/src/hooks/calendar/calendar-writes.render.test.ts +305 -0
- package/src/hooks/calendar/draft.test.ts +241 -0
- package/src/hooks/calendar/draft.ts +168 -0
- package/src/hooks/calendar/index.ts +59 -0
- package/src/hooks/calendar/instance.ts +136 -0
- package/src/hooks/calendar/recurrence-rule.test.ts +92 -0
- package/src/hooks/calendar/recurrence-rule.ts +133 -0
- package/src/hooks/calendar/resource.test.ts +98 -0
- package/src/hooks/calendar/resource.ts +74 -0
- package/src/hooks/calendar/useCalendarEvent.ts +46 -0
- package/src/hooks/calendar/useCalendarEvents.ts +124 -0
- package/src/hooks/calendar/useCalendarWrites.ts +174 -0
- package/src/hooks/calendar/useCalendars.ts +43 -0
- package/src/hooks/calendar/window.test.ts +148 -0
- package/src/hooks/calendar/window.ts +163 -0
- package/src/hooks/useCalendarData.ts +70 -22
- package/src/lib/calendar-route.ts +7 -3
- package/src/routes/calendar/$view.$date/new.tsx +2 -2
- package/src/routes/calendar/$view.$date.tsx +43 -15
- package/src/routing/calendar.ts +19 -8
- package/src/test-support/http.ts +8 -0
- package/src/lib/calendar-fixtures.ts +0 -207
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A week of invented calendar, so the routes and the grid can be walked before
|
|
3
|
-
* the REST layer exists. Every name here is made up and every event is
|
|
4
|
-
* generated from the day being looked at, which is what keeps the grid full
|
|
5
|
-
* wherever the reader navigates instead of only in June 2026.
|
|
6
|
-
*
|
|
7
|
-
* Stage A.3 deletes this file: `hooks/useCalendarData` swaps its body for the
|
|
8
|
-
* query hooks and nothing that renders a calendar changes.
|
|
9
|
-
*/
|
|
10
|
-
import type {
|
|
11
|
-
CalendarColorId,
|
|
12
|
-
CalendarDescriptor,
|
|
13
|
-
CalendarEventData,
|
|
14
|
-
} from "@remit/ui";
|
|
15
|
-
|
|
16
|
-
export const workCalendarId = "fixture-work";
|
|
17
|
-
export const personalCalendarId = "fixture-personal";
|
|
18
|
-
export const teamCalendarId = "fixture-team";
|
|
19
|
-
|
|
20
|
-
export const fixtureCalendars: CalendarDescriptor[] = [
|
|
21
|
-
{
|
|
22
|
-
id: workCalendarId,
|
|
23
|
-
accountId: "fixture-account-work",
|
|
24
|
-
accountLabel: "Work",
|
|
25
|
-
name: "Work",
|
|
26
|
-
color: "cal-1",
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
id: teamCalendarId,
|
|
30
|
-
accountId: "fixture-account-work",
|
|
31
|
-
accountLabel: "Work",
|
|
32
|
-
name: "Team",
|
|
33
|
-
color: "cal-6",
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
id: personalCalendarId,
|
|
37
|
-
accountId: "fixture-account-personal",
|
|
38
|
-
accountLabel: "Personal",
|
|
39
|
-
name: "Personal",
|
|
40
|
-
color: "cal-4",
|
|
41
|
-
},
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
export const fixtureColorByCalendarId: Record<string, CalendarColorId> =
|
|
45
|
-
Object.fromEntries(
|
|
46
|
-
fixtureCalendars.map((calendar) => [calendar.id, calendar.color]),
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const pad = (value: number): string => String(value).padStart(2, "0");
|
|
50
|
-
|
|
51
|
-
/** The Monday of the week a day falls in; the grid starts its weeks there. */
|
|
52
|
-
function weekStart(date: string): Date {
|
|
53
|
-
const [year, month, day] = date.split("-").map(Number);
|
|
54
|
-
const instant = new Date(Date.UTC(year, month - 1, day));
|
|
55
|
-
const weekday = (instant.getUTCDay() + 6) % 7;
|
|
56
|
-
instant.setUTCDate(instant.getUTCDate() - weekday);
|
|
57
|
-
return instant;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function dayOffsetFrom(start: Date, days: number): string {
|
|
61
|
-
const instant = new Date(start);
|
|
62
|
-
instant.setUTCDate(instant.getUTCDate() + days);
|
|
63
|
-
return `${instant.getUTCFullYear()}-${pad(instant.getUTCMonth() + 1)}-${pad(
|
|
64
|
-
instant.getUTCDate(),
|
|
65
|
-
)}`;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** The zone the device is on, which is the only clock a fixture can honestly use. */
|
|
69
|
-
export const fixtureTimeZone = (): string =>
|
|
70
|
-
Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
71
|
-
|
|
72
|
-
/** An ISO instant carrying the device's own offset for that day. */
|
|
73
|
-
function at(date: string, hour: number, minute: number): string {
|
|
74
|
-
const local = new Date(`${date}T${pad(hour)}:${pad(minute)}:00`);
|
|
75
|
-
const offset = -local.getTimezoneOffset();
|
|
76
|
-
const sign = offset < 0 ? "-" : "+";
|
|
77
|
-
const size = Math.abs(offset);
|
|
78
|
-
return `${date}T${pad(hour)}:${pad(minute)}:00${sign}${pad(
|
|
79
|
-
Math.floor(size / 60),
|
|
80
|
-
)}:${pad(size % 60)}`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const template: CalendarEventData = {
|
|
84
|
-
id: "",
|
|
85
|
-
calendarId: workCalendarId,
|
|
86
|
-
title: "",
|
|
87
|
-
start: "",
|
|
88
|
-
end: "",
|
|
89
|
-
allDay: false,
|
|
90
|
-
location: "",
|
|
91
|
-
notes: "",
|
|
92
|
-
attendees: [],
|
|
93
|
-
myRsvp: "accepted",
|
|
94
|
-
threadId: "",
|
|
95
|
-
threadSubject: "",
|
|
96
|
-
timeZone: "",
|
|
97
|
-
zoneCertainty: "explicit",
|
|
98
|
-
recurrenceRule: "",
|
|
99
|
-
seriesId: "",
|
|
100
|
-
seriesException: false,
|
|
101
|
-
status: "confirmed",
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
interface FixtureSpec {
|
|
105
|
-
dayOffset: number;
|
|
106
|
-
startHour: number;
|
|
107
|
-
startMinute: number;
|
|
108
|
-
endHour: number;
|
|
109
|
-
endMinute: number;
|
|
110
|
-
title: string;
|
|
111
|
-
calendarId: string;
|
|
112
|
-
location: string;
|
|
113
|
-
recurrenceRule: string;
|
|
114
|
-
seriesId: string;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const spec = (
|
|
118
|
-
dayOffset: number,
|
|
119
|
-
title: string,
|
|
120
|
-
startHour: number,
|
|
121
|
-
endHour: number,
|
|
122
|
-
over: Partial<FixtureSpec> = {},
|
|
123
|
-
): FixtureSpec => ({
|
|
124
|
-
dayOffset,
|
|
125
|
-
startHour,
|
|
126
|
-
startMinute: 0,
|
|
127
|
-
endHour,
|
|
128
|
-
endMinute: 0,
|
|
129
|
-
title,
|
|
130
|
-
calendarId: workCalendarId,
|
|
131
|
-
location: "",
|
|
132
|
-
recurrenceRule: "",
|
|
133
|
-
seriesId: "",
|
|
134
|
-
...over,
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* One made-up week: a daily standup, a couple of long blocks, an overlap on
|
|
139
|
-
* Wednesday and something on a Saturday, so every band the grid draws has
|
|
140
|
-
* something in it.
|
|
141
|
-
*/
|
|
142
|
-
const WEEK: FixtureSpec[] = [
|
|
143
|
-
spec(0, "Standup", 9, 9, {
|
|
144
|
-
startMinute: 15,
|
|
145
|
-
endMinute: 30,
|
|
146
|
-
recurrenceRule: "Every weekday, 09:15",
|
|
147
|
-
seriesId: "fixture-standup",
|
|
148
|
-
}),
|
|
149
|
-
spec(0, "Roadmap review", 11, 12, { calendarId: teamCalendarId }),
|
|
150
|
-
spec(1, "Standup", 9, 9, {
|
|
151
|
-
startMinute: 15,
|
|
152
|
-
endMinute: 30,
|
|
153
|
-
recurrenceRule: "Every weekday, 09:15",
|
|
154
|
-
seriesId: "fixture-standup",
|
|
155
|
-
}),
|
|
156
|
-
spec(1, "Supplier call", 14, 15, {
|
|
157
|
-
calendarId: teamCalendarId,
|
|
158
|
-
location: "Meet",
|
|
159
|
-
}),
|
|
160
|
-
spec(2, "Standup", 9, 9, {
|
|
161
|
-
startMinute: 15,
|
|
162
|
-
endMinute: 30,
|
|
163
|
-
recurrenceRule: "Every weekday, 09:15",
|
|
164
|
-
seriesId: "fixture-standup",
|
|
165
|
-
}),
|
|
166
|
-
spec(2, "Design review", 10, 12, { calendarId: teamCalendarId }),
|
|
167
|
-
spec(2, "Dentist", 11, 12, {
|
|
168
|
-
calendarId: personalCalendarId,
|
|
169
|
-
location: "Kerkstraat 4",
|
|
170
|
-
}),
|
|
171
|
-
spec(3, "Standup", 9, 9, {
|
|
172
|
-
startMinute: 15,
|
|
173
|
-
endMinute: 30,
|
|
174
|
-
recurrenceRule: "Every weekday, 09:15",
|
|
175
|
-
seriesId: "fixture-standup",
|
|
176
|
-
}),
|
|
177
|
-
spec(3, "One to one", 15, 16, { location: "Room 2" }),
|
|
178
|
-
spec(4, "Standup", 9, 9, {
|
|
179
|
-
startMinute: 15,
|
|
180
|
-
endMinute: 30,
|
|
181
|
-
recurrenceRule: "Every weekday, 09:15",
|
|
182
|
-
seriesId: "fixture-standup",
|
|
183
|
-
}),
|
|
184
|
-
spec(4, "Retro", 16, 17, { calendarId: teamCalendarId }),
|
|
185
|
-
spec(5, "Climbing", 10, 12, { calendarId: personalCalendarId }),
|
|
186
|
-
];
|
|
187
|
-
|
|
188
|
-
/** The invented week around a day, in the zone the device is running on. */
|
|
189
|
-
export function fixtureEventsAround(date: string): CalendarEventData[] {
|
|
190
|
-
const start = weekStart(date);
|
|
191
|
-
const timeZone = fixtureTimeZone();
|
|
192
|
-
return WEEK.map((entry) => {
|
|
193
|
-
const day = dayOffsetFrom(start, entry.dayOffset);
|
|
194
|
-
return {
|
|
195
|
-
...template,
|
|
196
|
-
id: `fixture-${day}-${entry.title.toLowerCase().replace(/\s+/g, "-")}`,
|
|
197
|
-
calendarId: entry.calendarId,
|
|
198
|
-
title: entry.title,
|
|
199
|
-
start: at(day, entry.startHour, entry.startMinute),
|
|
200
|
-
end: at(day, entry.endHour, entry.endMinute),
|
|
201
|
-
location: entry.location,
|
|
202
|
-
timeZone,
|
|
203
|
-
recurrenceRule: entry.recurrenceRule,
|
|
204
|
-
seriesId: entry.seriesId,
|
|
205
|
-
};
|
|
206
|
-
});
|
|
207
|
-
}
|