accomadesc 0.4.8 → 0.4.9
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/dist/basic/Icon.svelte +3 -1
- package/package.json +1 -1
- package/dist/occusplan-link/OccuPlanAvailableInfo.svelte +0 -43
- package/dist/occusplan-link/OccuPlanGrid.svelte +0 -383
- package/dist/occusplan-link/OccuPlanPicker.svelte +0 -584
- package/dist/occusplan-link/OccuPlanRows.svelte +0 -376
- package/dist/occusplan-link/OccuPlanWrapper.svelte +0 -120
- package/dist/occusplan-link/defaultTranslations.js +0 -157
- package/dist/occusplan-link/state.svelte.d.ts +0 -94
- package/dist/occusplan-link/state.svelte.js +0 -413
package/dist/basic/Icon.svelte
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
height?: string;
|
|
14
14
|
filter?: string;
|
|
15
15
|
} = $props();
|
|
16
|
+
|
|
17
|
+
const icon = $derived(getIcon(iconName, color));
|
|
16
18
|
</script>
|
|
17
19
|
|
|
18
20
|
<div
|
|
@@ -23,5 +25,5 @@
|
|
|
23
25
|
{filter ? `filter: ${filter};` : ''}
|
|
24
26
|
"
|
|
25
27
|
>
|
|
26
|
-
{@html
|
|
28
|
+
{@html icon}
|
|
27
29
|
</div>
|
package/package.json
CHANGED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { DateTime } from 'luxon';
|
|
3
|
-
import { normalizeDate } from '../helpers/normalizeDate.js';
|
|
4
|
-
import { getContext, onMount, untrack, setContext, type Snippet } from 'svelte';
|
|
5
|
-
import { OccupationState, contextKey, type AvailableSpans } from '../occuplan/state.svelte.js';
|
|
6
|
-
import Spinner from '../basic/Spinner.svelte';
|
|
7
|
-
|
|
8
|
-
let {
|
|
9
|
-
url,
|
|
10
|
-
debug = false,
|
|
11
|
-
search = [3, 7, 14],
|
|
12
|
-
maxFutureDate = normalizeDate(DateTime.utc().plus({ years: 1 })),
|
|
13
|
-
children,
|
|
14
|
-
}: {
|
|
15
|
-
url: string;
|
|
16
|
-
debug?: boolean | undefined;
|
|
17
|
-
search?: number[];
|
|
18
|
-
maxFutureDate?: DateTime;
|
|
19
|
-
children: Snippet<[AvailableSpans]>;
|
|
20
|
-
} = $props();
|
|
21
|
-
|
|
22
|
-
const stateID = contextKey(untrack(() => url));
|
|
23
|
-
let ss: OccupationState = getContext(stateID);
|
|
24
|
-
if (!ss) {
|
|
25
|
-
ss = new OccupationState(() => {
|
|
26
|
-
return { iCalURL: url, debug };
|
|
27
|
-
});
|
|
28
|
-
setContext(stateID, ss);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let occupationState: OccupationState = $derived(ss);
|
|
32
|
-
let av = $derived(occupationState ? occupationState.calcAvailability(search, maxFutureDate) : {});
|
|
33
|
-
|
|
34
|
-
onMount(() => {
|
|
35
|
-
occupationState.loadOccupations();
|
|
36
|
-
});
|
|
37
|
-
</script>
|
|
38
|
-
|
|
39
|
-
{#if !occupationState || occupationState.loading}
|
|
40
|
-
<Spinner />
|
|
41
|
-
{/if}
|
|
42
|
-
|
|
43
|
-
{@render children(av)}
|
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { DateTime, type MonthNumbers } from 'luxon';
|
|
3
|
-
import {
|
|
4
|
-
contextKey,
|
|
5
|
-
defaultMonthHeaderFormat,
|
|
6
|
-
defaultMonthLabels,
|
|
7
|
-
defaultWeekdayLabels,
|
|
8
|
-
OccupationState,
|
|
9
|
-
occupationTypeFormatting,
|
|
10
|
-
realFirstMonth,
|
|
11
|
-
type FirstMonth,
|
|
12
|
-
type OccupationType,
|
|
13
|
-
type OccuplanTranslations,
|
|
14
|
-
} from './state.svelte.js';
|
|
15
|
-
import Button from '../basic/Button.svelte';
|
|
16
|
-
import Spinner from '../basic/Spinner.svelte';
|
|
17
|
-
import { randomID } from '../names/gen.js';
|
|
18
|
-
import { getContext, onMount, setContext, untrack } from 'svelte';
|
|
19
|
-
|
|
20
|
-
let {
|
|
21
|
-
url,
|
|
22
|
-
debug = false,
|
|
23
|
-
header = '',
|
|
24
|
-
footer = '',
|
|
25
|
-
nextPage = '>',
|
|
26
|
-
prevPage = '<',
|
|
27
|
-
weekdayLabels = defaultWeekdayLabels,
|
|
28
|
-
monthLabels = defaultMonthLabels,
|
|
29
|
-
monthHeaderFormat = defaultMonthHeaderFormat,
|
|
30
|
-
numberOfMonth = 12,
|
|
31
|
-
maxWidth = '1200px',
|
|
32
|
-
firstMonth = DateTime.utc().month,
|
|
33
|
-
maxDate = DateTime.utc().plus({ years: 2 }),
|
|
34
|
-
minDate = DateTime.utc(),
|
|
35
|
-
typeLabels = {
|
|
36
|
-
one: 'BOOKING',
|
|
37
|
-
two: 'RESERVATION',
|
|
38
|
-
three: 'PERSONAL',
|
|
39
|
-
},
|
|
40
|
-
}: OccuplanTranslations & {
|
|
41
|
-
url: string;
|
|
42
|
-
debug?: boolean;
|
|
43
|
-
numberOfMonth?: number;
|
|
44
|
-
firstMonth?: FirstMonth;
|
|
45
|
-
minDate?: DateTime;
|
|
46
|
-
maxDate?: DateTime;
|
|
47
|
-
maxWidth?: string;
|
|
48
|
-
} = $props();
|
|
49
|
-
|
|
50
|
-
const id = randomID();
|
|
51
|
-
|
|
52
|
-
const stateID = contextKey(untrack(() => url));
|
|
53
|
-
let ss: OccupationState = getContext(stateID);
|
|
54
|
-
if (!ss) {
|
|
55
|
-
ss = new OccupationState(() => {
|
|
56
|
-
return { iCalURL: url, debug };
|
|
57
|
-
});
|
|
58
|
-
setContext(stateID, ss);
|
|
59
|
-
}
|
|
60
|
-
let occupationState: OccupationState = $derived(ss);
|
|
61
|
-
|
|
62
|
-
//let formatFun = $derived(Sqrl.compile(monthHeaderFormat, { useWith: true }));
|
|
63
|
-
const monthHeader = (monthNum: MonthNumbers, year: number): string => {
|
|
64
|
-
const monthLabel = monthLabels[monthNum];
|
|
65
|
-
|
|
66
|
-
let formatted = monthHeaderFormat.replace('{{month}}', monthLabel);
|
|
67
|
-
formatted = formatted.replace('{{year}}', `${year}`);
|
|
68
|
-
|
|
69
|
-
return formatted;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
let page: number = $state(0);
|
|
73
|
-
let rfMonth: DateTime = $derived(
|
|
74
|
-
realFirstMonth(firstMonth, DateTime.utc().get('year'), numberOfMonth, page),
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
let currentMaxDate = $derived(rfMonth.plus({ month: numberOfMonth }));
|
|
78
|
-
|
|
79
|
-
let months: DateTime[] = $derived.by(() => {
|
|
80
|
-
const result = [];
|
|
81
|
-
|
|
82
|
-
let fMonth: DateTime = DateTime.utc(rfMonth.year, rfMonth.month, 1);
|
|
83
|
-
|
|
84
|
-
result.push(fMonth);
|
|
85
|
-
|
|
86
|
-
let nMonth = fMonth.plus({ months: 1 });
|
|
87
|
-
for (let c = 1; c < numberOfMonth; c++) {
|
|
88
|
-
result.push(nMonth);
|
|
89
|
-
nMonth = nMonth.plus({ months: 1 });
|
|
90
|
-
}
|
|
91
|
-
return result;
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
const nextClicked = () => {
|
|
95
|
-
page += 1;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const prevClicked = () => {
|
|
99
|
-
page -= 1;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
let monthGridTemplateColumns = `[rowLegend] 1fr [d1] 1fr [d2] 1fr [d3] 1fr [d4] 1fr [d5] 1fr [d6] 1fr [d7] 1fr`;
|
|
103
|
-
|
|
104
|
-
let monthGridTemplateRows = (m: DateTime): string => {
|
|
105
|
-
let res = `[columnLegend] 1fr [w${m.weekNumber}] 1fr`;
|
|
106
|
-
let n = m.plus({ weeks: 1 });
|
|
107
|
-
for (let w = 1; w <= 5; w++) {
|
|
108
|
-
res += ` [w${n.weekNumber}] 1fr`;
|
|
109
|
-
n = n.plus({ weeks: 1 });
|
|
110
|
-
}
|
|
111
|
-
return res;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const weeks = (m: DateTime): DateTime[] => {
|
|
115
|
-
let n = m.plus({ weeks: 1 });
|
|
116
|
-
let res: DateTime[] = [m, n];
|
|
117
|
-
for (let i = 1; i <= 4; i++) {
|
|
118
|
-
n = n.plus({ weeks: 1 });
|
|
119
|
-
res.push(n);
|
|
120
|
-
}
|
|
121
|
-
return res;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const days = (m: DateTime): DateTime[] => {
|
|
125
|
-
//find first
|
|
126
|
-
let firstDay = m.startOf('week');
|
|
127
|
-
|
|
128
|
-
//find last
|
|
129
|
-
let lastDayOfMonth = m.endOf('month');
|
|
130
|
-
let lastDay = lastDayOfMonth.endOf('week');
|
|
131
|
-
|
|
132
|
-
let n = firstDay.plus({ days: 1 });
|
|
133
|
-
let res: DateTime[] = [firstDay];
|
|
134
|
-
|
|
135
|
-
while (n <= lastDay) {
|
|
136
|
-
res.push(n);
|
|
137
|
-
n = n.plus({ days: 1 });
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return res;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const hiddenWeekNum = (m: DateTime, w: DateTime): boolean => {
|
|
144
|
-
let lastDayOfMonth = m.endOf('month');
|
|
145
|
-
let firstDayOfWeek = w.startOf('week');
|
|
146
|
-
return lastDayOfMonth < firstDayOfWeek;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
let foundOccupationTypes: OccupationType[] = $derived(
|
|
150
|
-
occupationState?.occupations.reduce((res, occupation) => {
|
|
151
|
-
if (!res.includes(occupation.type)) {
|
|
152
|
-
res.push(occupation.type);
|
|
153
|
-
}
|
|
154
|
-
return res;
|
|
155
|
-
}, [] as OccupationType[]),
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
onMount(() => {
|
|
159
|
-
occupationState.loadOccupations();
|
|
160
|
-
});
|
|
161
|
-
</script>
|
|
162
|
-
|
|
163
|
-
{#if !occupationState || occupationState.loading}
|
|
164
|
-
<Spinner />
|
|
165
|
-
{/if}
|
|
166
|
-
|
|
167
|
-
<section class="occuplan-wrapper" style="max-width: {maxWidth};">
|
|
168
|
-
<header class="occupation-plan-header">
|
|
169
|
-
<div class="header-controls">
|
|
170
|
-
{#if rfMonth >= minDate}
|
|
171
|
-
<Button text={`${prevPage}`} clicked={prevClicked} />
|
|
172
|
-
{/if}
|
|
173
|
-
</div>
|
|
174
|
-
<div class="header-label"><h3>{@html header}</h3></div>
|
|
175
|
-
<div class="header-controls">
|
|
176
|
-
{#if currentMaxDate <= maxDate}
|
|
177
|
-
<Button text={`${nextPage}`} clicked={nextClicked} />
|
|
178
|
-
{/if}
|
|
179
|
-
</div>
|
|
180
|
-
</header>
|
|
181
|
-
<main>
|
|
182
|
-
{#each months as m (`${m.year}-${m.month}`)}
|
|
183
|
-
<div class="month">
|
|
184
|
-
<header class="month-header">{monthHeader(m.month as MonthNumbers, m.year)}</header>
|
|
185
|
-
<div
|
|
186
|
-
id={`${m.year}-${m.month}-${id}`}
|
|
187
|
-
style="
|
|
188
|
-
grid-template-columns: {monthGridTemplateColumns};
|
|
189
|
-
grid-template-rows: {monthGridTemplateRows(m)};
|
|
190
|
-
"
|
|
191
|
-
class="days"
|
|
192
|
-
>
|
|
193
|
-
<div class="weekday-header" style="grid-area: columnLegend / d1 / columnLegend / d1;">
|
|
194
|
-
{weekdayLabels[1]}
|
|
195
|
-
</div>
|
|
196
|
-
<div class="weekday-header" style="grid-area: columnLegend / d2 / columnLegend / d2;">
|
|
197
|
-
{weekdayLabels[2]}
|
|
198
|
-
</div>
|
|
199
|
-
<div class="weekday-header" style="grid-area: columnLegend / d3 / columnLegend / d3;">
|
|
200
|
-
{weekdayLabels[3]}
|
|
201
|
-
</div>
|
|
202
|
-
<div class="weekday-header" style="grid-area: columnLegend / d4 / columnLegend / d4;">
|
|
203
|
-
{weekdayLabels[4]}
|
|
204
|
-
</div>
|
|
205
|
-
<div class="weekday-header" style="grid-area: columnLegend / d5 / columnLegend / d5;">
|
|
206
|
-
{weekdayLabels[5]}
|
|
207
|
-
</div>
|
|
208
|
-
<div class="weekday-header" style="grid-area: columnLegend / d6 / columnLegend / d6;">
|
|
209
|
-
{weekdayLabels[6]}
|
|
210
|
-
</div>
|
|
211
|
-
<div class="weekday-header" style="grid-area: columnLegend / d7 / columnLegend / d7;">
|
|
212
|
-
{weekdayLabels[7]}
|
|
213
|
-
</div>
|
|
214
|
-
|
|
215
|
-
{#each days(m) as d (`${d.year}-${d.month}-${d.day}`)}
|
|
216
|
-
<div
|
|
217
|
-
id={`${m.year}-${m.month}-${m.day}-${id}`}
|
|
218
|
-
class:weekend={[6, 7].includes(d.weekday)}
|
|
219
|
-
class:other-month={m.month !== d.month}
|
|
220
|
-
class="day"
|
|
221
|
-
style="
|
|
222
|
-
grid-area: w{d.weekNumber} / d{d.weekday} / w{d.weekNumber} / d{d.weekday};
|
|
223
|
-
{occupationState?.occupationStyle(
|
|
224
|
-
{ day: d.day, month: d.month as MonthNumbers, year: d.year },
|
|
225
|
-
false,
|
|
226
|
-
maxDate,
|
|
227
|
-
)}
|
|
228
|
-
"
|
|
229
|
-
>
|
|
230
|
-
{d.day}
|
|
231
|
-
</div>
|
|
232
|
-
{/each}
|
|
233
|
-
|
|
234
|
-
{#each weeks(m) as w (`${w.year}-${w.month}-${w.weekNumber}`)}
|
|
235
|
-
<div
|
|
236
|
-
id={`${w.year}-${w.month}-${w.weekNumber}-${id}`}
|
|
237
|
-
class:hidden={hiddenWeekNum(m, w)}
|
|
238
|
-
class="week-number"
|
|
239
|
-
style="grid-area: w{w.weekNumber} / rowLegend / w{w.weekNumber} / rowLegend;"
|
|
240
|
-
>
|
|
241
|
-
{w.weekNumber}
|
|
242
|
-
</div>
|
|
243
|
-
{/each}
|
|
244
|
-
</div>
|
|
245
|
-
</div>
|
|
246
|
-
{/each}
|
|
247
|
-
</main>
|
|
248
|
-
<footer>
|
|
249
|
-
<div class="legend">
|
|
250
|
-
{#each foundOccupationTypes as t}
|
|
251
|
-
{@const format = occupationTypeFormatting(t)}
|
|
252
|
-
<span>{typeLabels[t]}</span>
|
|
253
|
-
<div
|
|
254
|
-
id="occupation-type-{t}-legend"
|
|
255
|
-
class="legend-entry-marker"
|
|
256
|
-
style="background-color: {format.bgColor};"
|
|
257
|
-
>
|
|
258
|
-
|
|
259
|
-
</div>
|
|
260
|
-
{/each}
|
|
261
|
-
</div>
|
|
262
|
-
<div class="footer-content">
|
|
263
|
-
{@html footer}
|
|
264
|
-
</div>
|
|
265
|
-
</footer>
|
|
266
|
-
</section>
|
|
267
|
-
|
|
268
|
-
<style>
|
|
269
|
-
.footer-content {
|
|
270
|
-
display: flex;
|
|
271
|
-
flex-direction: column;
|
|
272
|
-
justify-content: flex-end;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.legend-entry-marker {
|
|
276
|
-
outline: var(--occuplan-grid-border);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.month-header {
|
|
280
|
-
text-align: center;
|
|
281
|
-
color: var(--occuplan-main-font-color);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
.hidden {
|
|
285
|
-
display: none;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
.occupation-plan-header {
|
|
289
|
-
display: flex;
|
|
290
|
-
flex-direction: row;
|
|
291
|
-
width: 100%;
|
|
292
|
-
justify-content: space-between;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.header-label {
|
|
296
|
-
text-transform: capitalize;
|
|
297
|
-
font-weight: bold;
|
|
298
|
-
font-variant: small-caps;
|
|
299
|
-
|
|
300
|
-
h3 {
|
|
301
|
-
color: var(--occuplan-main-font-color);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
.week-number {
|
|
306
|
-
text-align: left;
|
|
307
|
-
font-style: italic;
|
|
308
|
-
font-weight: lighter;
|
|
309
|
-
background-color: var(--occuplan-weeknum-bg-color);
|
|
310
|
-
color: var(--occuplan-weeknum-font-color);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
.weekday-header {
|
|
314
|
-
text-align: center;
|
|
315
|
-
background-color: var(--occuplan-days-header-bg-color);
|
|
316
|
-
color: var(--occuplan-days-header-font-color);
|
|
317
|
-
grid-area: columnLegend / d1 / columnLegend / d1;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
.day {
|
|
321
|
-
text-align: center;
|
|
322
|
-
color: var(--occuplan-main-font-color);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
.weekend {
|
|
326
|
-
font-weight: bold;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
.occuplan-wrapper {
|
|
330
|
-
height: 100%;
|
|
331
|
-
width: calc(100% - 0.5rem);
|
|
332
|
-
padding: 0.5rem;
|
|
333
|
-
margin: 0;
|
|
334
|
-
display: flex;
|
|
335
|
-
flex-direction: column;
|
|
336
|
-
flex-wrap: nowrap;
|
|
337
|
-
align-items: center;
|
|
338
|
-
|
|
339
|
-
border: var(--occuplan-main-border);
|
|
340
|
-
color: var(--occuplan-main-font-color);
|
|
341
|
-
background-color: var(--occuplan-main-bg-color);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
main {
|
|
345
|
-
display: grid;
|
|
346
|
-
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
|
|
347
|
-
gap: 1rem;
|
|
348
|
-
width: 100%;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.month {
|
|
352
|
-
display: flex;
|
|
353
|
-
flex-direction: column;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
.days {
|
|
357
|
-
display: grid;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
footer {
|
|
361
|
-
display: flex;
|
|
362
|
-
flex-direction: row;
|
|
363
|
-
align-items: stretch;
|
|
364
|
-
justify-content: space-between;
|
|
365
|
-
width: 100%;
|
|
366
|
-
margin-top: 1rem;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
.legend {
|
|
370
|
-
display: grid;
|
|
371
|
-
grid-template-columns: [label] 1fr [marker] 1rem;
|
|
372
|
-
column-gap: 1rem;
|
|
373
|
-
text-transform: capitalize;
|
|
374
|
-
font-variant: small-caps;
|
|
375
|
-
|
|
376
|
-
span {
|
|
377
|
-
color: var(--occuplan-main-font-color);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
.header-controls {
|
|
381
|
-
width: 2rem;
|
|
382
|
-
}
|
|
383
|
-
</style>
|