@sneat/extension-eventus-shared 0.0.1

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.
Files changed (20) hide show
  1. package/fesm2022/sneat-extension-eventus-shared-bring-along-page.component-DHi-E8P1.mjs +153 -0
  2. package/fesm2022/sneat-extension-eventus-shared-bring-along-page.component-DHi-E8P1.mjs.map +1 -0
  3. package/fesm2022/sneat-extension-eventus-shared-create-event-page.component-Da39fu36.mjs +90 -0
  4. package/fesm2022/sneat-extension-eventus-shared-create-event-page.component-Da39fu36.mjs.map +1 -0
  5. package/fesm2022/sneat-extension-eventus-shared-edit-event-page.component-lhOpcqld.mjs +103 -0
  6. package/fesm2022/sneat-extension-eventus-shared-edit-event-page.component-lhOpcqld.mjs.map +1 -0
  7. package/fesm2022/sneat-extension-eventus-shared-event-page.component-CuOA0EU9.mjs +143 -0
  8. package/fesm2022/sneat-extension-eventus-shared-event-page.component-CuOA0EU9.mjs.map +1 -0
  9. package/fesm2022/sneat-extension-eventus-shared-events-list-page.component-DELSoZ2W.mjs +72 -0
  10. package/fesm2022/sneat-extension-eventus-shared-events-list-page.component-DELSoZ2W.mjs.map +1 -0
  11. package/fesm2022/sneat-extension-eventus-shared-invitees-page.component-DGG1LDd7.mjs +94 -0
  12. package/fesm2022/sneat-extension-eventus-shared-invitees-page.component-DGG1LDd7.mjs.map +1 -0
  13. package/fesm2022/sneat-extension-eventus-shared-responses-page.component-L9ayYgBN.mjs +78 -0
  14. package/fesm2022/sneat-extension-eventus-shared-responses-page.component-L9ayYgBN.mjs.map +1 -0
  15. package/fesm2022/sneat-extension-eventus-shared-share-links-page.component-BzZ6tFBc.mjs +92 -0
  16. package/fesm2022/sneat-extension-eventus-shared-share-links-page.component-BzZ6tFBc.mjs.map +1 -0
  17. package/fesm2022/sneat-extension-eventus-shared.mjs +270 -0
  18. package/fesm2022/sneat-extension-eventus-shared.mjs.map +1 -0
  19. package/package.json +43 -0
  20. package/types/sneat-extension-eventus-shared.d.ts +60 -0
@@ -0,0 +1,153 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, input, signal, computed, Component } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { FormsModule } from '@angular/forms';
5
+ import { IonHeader, IonToolbar, IonTitle, IonButtons, IonBackButton, IonButton, IonContent, IonList, IonListHeader, IonItem, IonLabel, IonInput, IonNote, IonText, IonSpinner } from '@ionic/angular/standalone';
6
+ import { BRING_ALONG_SERVICE, EVENTUS_CURRENT_CLAIMANT, extractErrorMessage } from '@sneat/extension-eventus-contract';
7
+
8
+ // Bring-along screen for an event: the host defines slots (label + optional
9
+ // note); each slot shows as OPEN (with Claim) or CLAIMED ("{label} — {claimant}",
10
+ // with Release when the current claimant owns it). A 409 on claim shows a
11
+ // friendly message and refreshes the list.
12
+ // (AC: host-defines-slots, claim-prevents-duplicates)
13
+ class BringAlongPageComponent {
14
+ bringAlongService = inject(BRING_ALONG_SERVICE);
15
+ claimant = inject(EVENTUS_CURRENT_CLAIMANT);
16
+ spaceID = input.required(...(ngDevMode ? [{ debugName: "spaceID" }] : /* istanbul ignore next */ []));
17
+ eventID = input.required(...(ngDevMode ? [{ debugName: "eventID" }] : /* istanbul ignore next */ []));
18
+ slots = signal([], ...(ngDevMode ? [{ debugName: "slots" }] : /* istanbul ignore next */ []));
19
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
20
+ submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
21
+ error = signal(undefined, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
22
+ newLabel = '';
23
+ newNote = '';
24
+ /** The identity used for claim/release, shown in the header for clarity. */
25
+ claimantLabel = computed(() => this.claimant.label, ...(ngDevMode ? [{ debugName: "claimantLabel" }] : /* istanbul ignore next */ []));
26
+ ngOnInit() {
27
+ this.loadSlots();
28
+ }
29
+ loadSlots() {
30
+ this.loading.set(true);
31
+ this.bringAlongService.listSlots(this.spaceID(), this.eventID()).subscribe({
32
+ next: (slots) => {
33
+ this.slots.set(slots);
34
+ this.loading.set(false);
35
+ },
36
+ error: (err) => {
37
+ this.loading.set(false);
38
+ this.error.set(extractErrorMessage(err, 'Failed to load slots.'));
39
+ },
40
+ });
41
+ }
42
+ /** Whether the current claimant owns this slot (so they may release it). */
43
+ claimedByMe(slot) {
44
+ return slot.claimedBy?.ref === this.claimant.ref;
45
+ }
46
+ /** Host defines a new slot. (AC: host-defines-slots) */
47
+ addSlot() {
48
+ const label = this.newLabel.trim();
49
+ if (!label || this.submitting()) {
50
+ return;
51
+ }
52
+ const note = this.newNote.trim();
53
+ this.submitting.set(true);
54
+ this.error.set(undefined);
55
+ this.bringAlongService
56
+ .defineSlot(this.spaceID(), this.eventID(), {
57
+ label,
58
+ ...(note ? { note } : {}),
59
+ })
60
+ .subscribe({
61
+ next: (slot) => {
62
+ this.slots.update((list) => [...list, slot]);
63
+ this.newLabel = '';
64
+ this.newNote = '';
65
+ this.submitting.set(false);
66
+ },
67
+ error: (err) => {
68
+ this.submitting.set(false);
69
+ this.error.set(extractErrorMessage(err, 'Failed to add slot.'));
70
+ },
71
+ });
72
+ }
73
+ /** Claim an open slot. On 409 show a friendly message and refresh. */
74
+ claim(slot) {
75
+ if (this.submitting()) {
76
+ return;
77
+ }
78
+ this.submitting.set(true);
79
+ this.error.set(undefined);
80
+ this.bringAlongService
81
+ .claimSlot(this.spaceID(), this.eventID(), slot.id, {
82
+ ref: this.claimant.ref,
83
+ label: this.claimant.label,
84
+ })
85
+ .subscribe({
86
+ next: (updated) => {
87
+ this.replaceSlot(updated);
88
+ this.submitting.set(false);
89
+ },
90
+ error: (err) => {
91
+ this.submitting.set(false);
92
+ if (err?.status === 409) {
93
+ this.error.set('Already claimed by someone else.');
94
+ this.loadSlots();
95
+ }
96
+ else {
97
+ this.error.set(extractErrorMessage(err, 'Failed to claim slot.'));
98
+ }
99
+ },
100
+ });
101
+ }
102
+ /** Release a slot the current claimant owns, returning it to open. */
103
+ release(slot) {
104
+ if (this.submitting()) {
105
+ return;
106
+ }
107
+ this.submitting.set(true);
108
+ this.error.set(undefined);
109
+ this.bringAlongService
110
+ .releaseSlot(this.spaceID(), this.eventID(), slot.id, {
111
+ ref: this.claimant.ref,
112
+ })
113
+ .subscribe({
114
+ next: (updated) => {
115
+ this.replaceSlot(updated);
116
+ this.submitting.set(false);
117
+ },
118
+ error: (err) => {
119
+ this.submitting.set(false);
120
+ this.error.set(extractErrorMessage(err, 'Failed to release slot.'));
121
+ },
122
+ });
123
+ }
124
+ replaceSlot(updated) {
125
+ this.slots.update((list) => list.map((s) => (s.id === updated.id ? updated : s)));
126
+ }
127
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BringAlongPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
128
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: BringAlongPageComponent, isStandalone: true, selector: "eventus-bring-along-page", inputs: { spaceID: { classPropertyName: "spaceID", publicName: "spaceID", isSignal: true, isRequired: true, transformFunction: null }, eventID: { classPropertyName: "eventID", publicName: "eventID", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-back-button defaultHref=\"/\"></ion-back-button>\n </ion-buttons>\n <ion-title>Bring along</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n @if (error()) {\n <ion-text color=\"danger\">{{ error() }}</ion-text>\n }\n\n <ion-list>\n <ion-list-header>Add a slot</ion-list-header>\n <ion-item>\n <ion-input\n label=\"What's needed\"\n labelPlacement=\"floating\"\n placeholder=\"e.g. Drinks\"\n [(ngModel)]=\"newLabel\"\n ></ion-input>\n </ion-item>\n <ion-item>\n <ion-input\n label=\"Note (optional)\"\n labelPlacement=\"floating\"\n placeholder=\"e.g. 2 bottles\"\n [(ngModel)]=\"newNote\"\n ></ion-input>\n </ion-item>\n <ion-button\n expand=\"block\"\n class=\"ion-margin-top\"\n [disabled]=\"submitting() || !newLabel.trim()\"\n (click)=\"addSlot()\"\n >\n Add slot\n </ion-button>\n </ion-list>\n\n <ion-list>\n <ion-list-header>Slots</ion-list-header>\n @if (loading()) {\n <ion-item>\n <ion-spinner aria-label=\"Loading slots\"></ion-spinner>\n </ion-item>\n } @else {\n @for (slot of slots(); track slot.id) {\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n @if (slot.claimedBy; as claimant) {\n <h3>{{ slot.label }} \u2014 {{ claimant.label }}</h3>\n } @else {\n <h3>{{ slot.label }}</h3>\n <ion-note color=\"success\">Open</ion-note>\n }\n @if (slot.note) {\n <p>{{ slot.note }}</p>\n }\n </ion-label>\n @if (!slot.claimedBy) {\n <ion-button\n slot=\"end\"\n [disabled]=\"submitting()\"\n (click)=\"claim(slot)\"\n >\n Claim\n </ion-button>\n } @else if (claimedByMe(slot)) {\n <ion-button\n slot=\"end\"\n fill=\"outline\"\n [disabled]=\"submitting()\"\n (click)=\"release(slot)\"\n >\n Release\n </ion-button>\n }\n </ion-item>\n } @empty {\n <ion-item>\n <ion-note>No slots yet.</ion-note>\n </ion-item>\n }\n }\n </ion-list>\n</ion-content>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonBackButton, selector: "ion-back-button" }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }] });
129
+ }
130
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BringAlongPageComponent, decorators: [{
131
+ type: Component,
132
+ args: [{ selector: 'eventus-bring-along-page', imports: [
133
+ FormsModule,
134
+ IonHeader,
135
+ IonToolbar,
136
+ IonTitle,
137
+ IonButtons,
138
+ IonBackButton,
139
+ IonButton,
140
+ IonContent,
141
+ IonList,
142
+ IonListHeader,
143
+ IonItem,
144
+ IonLabel,
145
+ IonInput,
146
+ IonNote,
147
+ IonText,
148
+ IonSpinner,
149
+ ], template: "<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-back-button defaultHref=\"/\"></ion-back-button>\n </ion-buttons>\n <ion-title>Bring along</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n @if (error()) {\n <ion-text color=\"danger\">{{ error() }}</ion-text>\n }\n\n <ion-list>\n <ion-list-header>Add a slot</ion-list-header>\n <ion-item>\n <ion-input\n label=\"What's needed\"\n labelPlacement=\"floating\"\n placeholder=\"e.g. Drinks\"\n [(ngModel)]=\"newLabel\"\n ></ion-input>\n </ion-item>\n <ion-item>\n <ion-input\n label=\"Note (optional)\"\n labelPlacement=\"floating\"\n placeholder=\"e.g. 2 bottles\"\n [(ngModel)]=\"newNote\"\n ></ion-input>\n </ion-item>\n <ion-button\n expand=\"block\"\n class=\"ion-margin-top\"\n [disabled]=\"submitting() || !newLabel.trim()\"\n (click)=\"addSlot()\"\n >\n Add slot\n </ion-button>\n </ion-list>\n\n <ion-list>\n <ion-list-header>Slots</ion-list-header>\n @if (loading()) {\n <ion-item>\n <ion-spinner aria-label=\"Loading slots\"></ion-spinner>\n </ion-item>\n } @else {\n @for (slot of slots(); track slot.id) {\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n @if (slot.claimedBy; as claimant) {\n <h3>{{ slot.label }} \u2014 {{ claimant.label }}</h3>\n } @else {\n <h3>{{ slot.label }}</h3>\n <ion-note color=\"success\">Open</ion-note>\n }\n @if (slot.note) {\n <p>{{ slot.note }}</p>\n }\n </ion-label>\n @if (!slot.claimedBy) {\n <ion-button\n slot=\"end\"\n [disabled]=\"submitting()\"\n (click)=\"claim(slot)\"\n >\n Claim\n </ion-button>\n } @else if (claimedByMe(slot)) {\n <ion-button\n slot=\"end\"\n fill=\"outline\"\n [disabled]=\"submitting()\"\n (click)=\"release(slot)\"\n >\n Release\n </ion-button>\n }\n </ion-item>\n } @empty {\n <ion-item>\n <ion-note>No slots yet.</ion-note>\n </ion-item>\n }\n }\n </ion-list>\n</ion-content>\n" }]
150
+ }], propDecorators: { spaceID: [{ type: i0.Input, args: [{ isSignal: true, alias: "spaceID", required: true }] }], eventID: [{ type: i0.Input, args: [{ isSignal: true, alias: "eventID", required: true }] }] } });
151
+
152
+ export { BringAlongPageComponent };
153
+ //# sourceMappingURL=sneat-extension-eventus-shared-bring-along-page.component-DHi-E8P1.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sneat-extension-eventus-shared-bring-along-page.component-DHi-E8P1.mjs","sources":["../../../../../../libs/extensions/eventus/shared/src/lib/pages/bring-along/bring-along-page.component.ts","../../../../../../libs/extensions/eventus/shared/src/lib/pages/bring-along/bring-along-page.component.html"],"sourcesContent":["import { Component, OnInit, computed, inject, input, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n IonBackButton,\n IonButton,\n IonButtons,\n IonContent,\n IonHeader,\n IonInput,\n IonItem,\n IonLabel,\n IonList,\n IonListHeader,\n IonNote,\n IonSpinner,\n IonText,\n IonTitle,\n IonToolbar,\n} from '@ionic/angular/standalone';\nimport {\n BRING_ALONG_SERVICE,\n EVENTUS_CURRENT_CLAIMANT,\n extractErrorMessage,\n IBringAlongSlot,\n} from '@sneat/extension-eventus-contract';\n\n// Bring-along screen for an event: the host defines slots (label + optional\n// note); each slot shows as OPEN (with Claim) or CLAIMED (\"{label} — {claimant}\",\n// with Release when the current claimant owns it). A 409 on claim shows a\n// friendly message and refreshes the list.\n// (AC: host-defines-slots, claim-prevents-duplicates)\n@Component({\n selector: 'eventus-bring-along-page',\n templateUrl: './bring-along-page.component.html',\n imports: [\n FormsModule,\n IonHeader,\n IonToolbar,\n IonTitle,\n IonButtons,\n IonBackButton,\n IonButton,\n IonContent,\n IonList,\n IonListHeader,\n IonItem,\n IonLabel,\n IonInput,\n IonNote,\n IonText,\n IonSpinner,\n ],\n})\nexport class BringAlongPageComponent implements OnInit {\n private readonly bringAlongService = inject(BRING_ALONG_SERVICE);\n private readonly claimant = inject(EVENTUS_CURRENT_CLAIMANT);\n\n readonly spaceID = input.required<string>();\n readonly eventID = input.required<string>();\n\n protected readonly slots = signal<IBringAlongSlot[]>([]);\n protected readonly loading = signal(true);\n protected readonly submitting = signal(false);\n protected readonly error = signal<string | undefined>(undefined);\n\n protected newLabel = '';\n protected newNote = '';\n\n /** The identity used for claim/release, shown in the header for clarity. */\n protected readonly claimantLabel = computed(() => this.claimant.label);\n\n ngOnInit(): void {\n this.loadSlots();\n }\n\n private loadSlots(): void {\n this.loading.set(true);\n this.bringAlongService.listSlots(this.spaceID(), this.eventID()).subscribe({\n next: (slots) => {\n this.slots.set(slots);\n this.loading.set(false);\n },\n error: (err: unknown) => {\n this.loading.set(false);\n this.error.set(extractErrorMessage(err, 'Failed to load slots.'));\n },\n });\n }\n\n /** Whether the current claimant owns this slot (so they may release it). */\n protected claimedByMe(slot: IBringAlongSlot): boolean {\n return slot.claimedBy?.ref === this.claimant.ref;\n }\n\n /** Host defines a new slot. (AC: host-defines-slots) */\n protected addSlot(): void {\n const label = this.newLabel.trim();\n if (!label || this.submitting()) {\n return;\n }\n const note = this.newNote.trim();\n this.submitting.set(true);\n this.error.set(undefined);\n this.bringAlongService\n .defineSlot(this.spaceID(), this.eventID(), {\n label,\n ...(note ? { note } : {}),\n })\n .subscribe({\n next: (slot) => {\n this.slots.update((list) => [...list, slot]);\n this.newLabel = '';\n this.newNote = '';\n this.submitting.set(false);\n },\n error: (err: unknown) => {\n this.submitting.set(false);\n this.error.set(extractErrorMessage(err, 'Failed to add slot.'));\n },\n });\n }\n\n /** Claim an open slot. On 409 show a friendly message and refresh. */\n protected claim(slot: IBringAlongSlot): void {\n if (this.submitting()) {\n return;\n }\n this.submitting.set(true);\n this.error.set(undefined);\n this.bringAlongService\n .claimSlot(this.spaceID(), this.eventID(), slot.id, {\n ref: this.claimant.ref,\n label: this.claimant.label,\n })\n .subscribe({\n next: (updated) => {\n this.replaceSlot(updated);\n this.submitting.set(false);\n },\n error: (err: { status?: number }) => {\n this.submitting.set(false);\n if (err?.status === 409) {\n this.error.set('Already claimed by someone else.');\n this.loadSlots();\n } else {\n this.error.set(extractErrorMessage(err, 'Failed to claim slot.'));\n }\n },\n });\n }\n\n /** Release a slot the current claimant owns, returning it to open. */\n protected release(slot: IBringAlongSlot): void {\n if (this.submitting()) {\n return;\n }\n this.submitting.set(true);\n this.error.set(undefined);\n this.bringAlongService\n .releaseSlot(this.spaceID(), this.eventID(), slot.id, {\n ref: this.claimant.ref,\n })\n .subscribe({\n next: (updated) => {\n this.replaceSlot(updated);\n this.submitting.set(false);\n },\n error: (err: unknown) => {\n this.submitting.set(false);\n this.error.set(extractErrorMessage(err, 'Failed to release slot.'));\n },\n });\n }\n\n private replaceSlot(updated: IBringAlongSlot): void {\n this.slots.update((list) =>\n list.map((s) => (s.id === updated.id ? updated : s)),\n );\n }\n}\n","<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-back-button defaultHref=\"/\"></ion-back-button>\n </ion-buttons>\n <ion-title>Bring along</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n @if (error()) {\n <ion-text color=\"danger\">{{ error() }}</ion-text>\n }\n\n <ion-list>\n <ion-list-header>Add a slot</ion-list-header>\n <ion-item>\n <ion-input\n label=\"What's needed\"\n labelPlacement=\"floating\"\n placeholder=\"e.g. Drinks\"\n [(ngModel)]=\"newLabel\"\n ></ion-input>\n </ion-item>\n <ion-item>\n <ion-input\n label=\"Note (optional)\"\n labelPlacement=\"floating\"\n placeholder=\"e.g. 2 bottles\"\n [(ngModel)]=\"newNote\"\n ></ion-input>\n </ion-item>\n <ion-button\n expand=\"block\"\n class=\"ion-margin-top\"\n [disabled]=\"submitting() || !newLabel.trim()\"\n (click)=\"addSlot()\"\n >\n Add slot\n </ion-button>\n </ion-list>\n\n <ion-list>\n <ion-list-header>Slots</ion-list-header>\n @if (loading()) {\n <ion-item>\n <ion-spinner aria-label=\"Loading slots\"></ion-spinner>\n </ion-item>\n } @else {\n @for (slot of slots(); track slot.id) {\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n @if (slot.claimedBy; as claimant) {\n <h3>{{ slot.label }} — {{ claimant.label }}</h3>\n } @else {\n <h3>{{ slot.label }}</h3>\n <ion-note color=\"success\">Open</ion-note>\n }\n @if (slot.note) {\n <p>{{ slot.note }}</p>\n }\n </ion-label>\n @if (!slot.claimedBy) {\n <ion-button\n slot=\"end\"\n [disabled]=\"submitting()\"\n (click)=\"claim(slot)\"\n >\n Claim\n </ion-button>\n } @else if (claimedByMe(slot)) {\n <ion-button\n slot=\"end\"\n fill=\"outline\"\n [disabled]=\"submitting()\"\n (click)=\"release(slot)\"\n >\n Release\n </ion-button>\n }\n </ion-item>\n } @empty {\n <ion-item>\n <ion-note>No slots yet.</ion-note>\n </ion-item>\n }\n }\n </ion-list>\n</ion-content>\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, input, signal, Component } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { FormsModule } from '@angular/forms';
5
+ import { Router } from '@angular/router';
6
+ import { IonHeader, IonToolbar, IonTitle, IonButtons, IonBackButton, IonContent, IonList, IonItem, IonInput, IonDatetime, IonTextarea, IonNote, IonButton } from '@ionic/angular/standalone';
7
+ import { EVENTUS_EVENT_SERVICE, extractErrorMessage } from '@sneat/extension-eventus-contract';
8
+
9
+ // Host screen to create an event (title, date/time, location, description).
10
+ // On success it navigates to the created event's view page.
11
+ // (AC: host-creates-event)
12
+ class CreateEventPageComponent {
13
+ eventService = inject(EVENTUS_EVENT_SERVICE);
14
+ router = inject(Router);
15
+ /** Host space the event is created in (from the route). */
16
+ spaceType = input.required(...(ngDevMode ? [{ debugName: "spaceType" }] : /* istanbul ignore next */ []));
17
+ spaceID = input.required(...(ngDevMode ? [{ debugName: "spaceID" }] : /* istanbul ignore next */ []));
18
+ title = '';
19
+ start = '';
20
+ location = '';
21
+ description = '';
22
+ /** Event length in minutes (default 60); reuses Calendarius's duration model. */
23
+ durationMinutes = 60;
24
+ submitting = signal(false, ...(ngDevMode ? [{ debugName: "submitting" }] : /* istanbul ignore next */ []));
25
+ error = signal(undefined, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
26
+ get canSubmit() {
27
+ return (!this.submitting() &&
28
+ this.title.trim().length > 0 &&
29
+ this.start.trim().length > 0 &&
30
+ this.location.trim().length > 0);
31
+ }
32
+ submit() {
33
+ if (!this.canSubmit) {
34
+ return;
35
+ }
36
+ const request = {
37
+ title: this.title.trim(),
38
+ start: this.start,
39
+ location: this.location.trim(),
40
+ };
41
+ const description = this.description.trim();
42
+ if (description) {
43
+ request.description = description;
44
+ }
45
+ if (this.durationMinutes > 0) {
46
+ request.durationMinutes = this.durationMinutes;
47
+ }
48
+ this.submitting.set(true);
49
+ this.error.set(undefined);
50
+ this.eventService.createEvent(this.spaceID(), request).subscribe({
51
+ next: (created) => {
52
+ void this.router.navigate([
53
+ '/space',
54
+ this.spaceType(),
55
+ this.spaceID(),
56
+ 'events',
57
+ created.id,
58
+ ]);
59
+ },
60
+ error: (err) => {
61
+ this.submitting.set(false);
62
+ this.error.set(extractErrorMessage(err, 'Failed to create event.'));
63
+ },
64
+ });
65
+ }
66
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CreateEventPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
67
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CreateEventPageComponent, isStandalone: true, selector: "eventus-create-event-page", inputs: { spaceType: { classPropertyName: "spaceType", publicName: "spaceType", isSignal: true, isRequired: true, transformFunction: null }, spaceID: { classPropertyName: "spaceID", publicName: "spaceID", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-back-button defaultHref=\"/\"></ion-back-button>\n </ion-buttons>\n <ion-title>New event</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n <ion-list>\n <ion-item>\n <ion-input\n label=\"Title\"\n labelPlacement=\"stacked\"\n placeholder=\"Sophie's 10th Birthday\"\n [(ngModel)]=\"title\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-input\n label=\"Location\"\n labelPlacement=\"stacked\"\n placeholder=\"123 Main St\"\n [(ngModel)]=\"location\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-textarea\n label=\"Description\"\n labelPlacement=\"stacked\"\n placeholder=\"Optional details\"\n [(ngModel)]=\"description\"\n [autoGrow]=\"true\"\n ></ion-textarea>\n </ion-item>\n </ion-list>\n\n <ion-list>\n <ion-item lines=\"none\">\n <ion-note>Date &amp; time</ion-note>\n </ion-item>\n <ion-datetime\n aria-label=\"Event date and time\"\n [(ngModel)]=\"start\"\n presentation=\"date-time\"\n ></ion-datetime>\n <ion-item>\n <ion-input\n label=\"Duration (minutes)\"\n labelPlacement=\"stacked\"\n type=\"number\"\n min=\"1\"\n [(ngModel)]=\"durationMinutes\"\n ></ion-input>\n </ion-item>\n </ion-list>\n\n @if (error()) {\n <ion-note color=\"danger\" class=\"ion-padding-start\">{{ error() }}</ion-note>\n }\n\n <ion-button\n expand=\"block\"\n class=\"ion-margin-top\"\n [disabled]=\"!canSubmit\"\n (click)=\"submit()\"\n >\n Create event\n </ion-button>\n</ion-content>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonBackButton, selector: "ion-back-button" }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonDatetime, selector: "ion-datetime", inputs: ["cancelText", "clearText", "color", "dayValues", "disabled", "doneText", "firstDayOfWeek", "formatOptions", "highlightedDates", "hourCycle", "hourValues", "isDateEnabled", "locale", "max", "min", "minuteValues", "mode", "monthValues", "multiple", "name", "preferWheel", "presentation", "readonly", "showAdjacentDays", "showClearButton", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "titleSelectedDatesFormatter", "value", "yearValues"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }] });
68
+ }
69
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CreateEventPageComponent, decorators: [{
70
+ type: Component,
71
+ args: [{ selector: 'eventus-create-event-page', imports: [
72
+ FormsModule,
73
+ IonHeader,
74
+ IonToolbar,
75
+ IonTitle,
76
+ IonButtons,
77
+ IonBackButton,
78
+ IonContent,
79
+ IonList,
80
+ IonItem,
81
+ IonInput,
82
+ IonDatetime,
83
+ IonTextarea,
84
+ IonNote,
85
+ IonButton,
86
+ ], template: "<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-back-button defaultHref=\"/\"></ion-back-button>\n </ion-buttons>\n <ion-title>New event</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n <ion-list>\n <ion-item>\n <ion-input\n label=\"Title\"\n labelPlacement=\"stacked\"\n placeholder=\"Sophie's 10th Birthday\"\n [(ngModel)]=\"title\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-input\n label=\"Location\"\n labelPlacement=\"stacked\"\n placeholder=\"123 Main St\"\n [(ngModel)]=\"location\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-textarea\n label=\"Description\"\n labelPlacement=\"stacked\"\n placeholder=\"Optional details\"\n [(ngModel)]=\"description\"\n [autoGrow]=\"true\"\n ></ion-textarea>\n </ion-item>\n </ion-list>\n\n <ion-list>\n <ion-item lines=\"none\">\n <ion-note>Date &amp; time</ion-note>\n </ion-item>\n <ion-datetime\n aria-label=\"Event date and time\"\n [(ngModel)]=\"start\"\n presentation=\"date-time\"\n ></ion-datetime>\n <ion-item>\n <ion-input\n label=\"Duration (minutes)\"\n labelPlacement=\"stacked\"\n type=\"number\"\n min=\"1\"\n [(ngModel)]=\"durationMinutes\"\n ></ion-input>\n </ion-item>\n </ion-list>\n\n @if (error()) {\n <ion-note color=\"danger\" class=\"ion-padding-start\">{{ error() }}</ion-note>\n }\n\n <ion-button\n expand=\"block\"\n class=\"ion-margin-top\"\n [disabled]=\"!canSubmit\"\n (click)=\"submit()\"\n >\n Create event\n </ion-button>\n</ion-content>\n" }]
87
+ }], propDecorators: { spaceType: [{ type: i0.Input, args: [{ isSignal: true, alias: "spaceType", required: true }] }], spaceID: [{ type: i0.Input, args: [{ isSignal: true, alias: "spaceID", required: true }] }] } });
88
+
89
+ export { CreateEventPageComponent };
90
+ //# sourceMappingURL=sneat-extension-eventus-shared-create-event-page.component-Da39fu36.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sneat-extension-eventus-shared-create-event-page.component-Da39fu36.mjs","sources":["../../../../../../libs/extensions/eventus/shared/src/lib/pages/create-event/create-event-page.component.ts","../../../../../../libs/extensions/eventus/shared/src/lib/pages/create-event/create-event-page.component.html"],"sourcesContent":["import { Component, inject, input, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { Router } from '@angular/router';\nimport {\n IonButton,\n IonButtons,\n IonBackButton,\n IonContent,\n IonHeader,\n IonInput,\n IonItem,\n IonList,\n IonDatetime,\n IonNote,\n IonTextarea,\n IonTitle,\n IonToolbar,\n} from '@ionic/angular/standalone';\nimport {\n EVENTUS_EVENT_SERVICE,\n extractErrorMessage,\n ICreateEventRequest,\n} from '@sneat/extension-eventus-contract';\n\n// Host screen to create an event (title, date/time, location, description).\n// On success it navigates to the created event's view page.\n// (AC: host-creates-event)\n@Component({\n selector: 'eventus-create-event-page',\n templateUrl: './create-event-page.component.html',\n imports: [\n FormsModule,\n IonHeader,\n IonToolbar,\n IonTitle,\n IonButtons,\n IonBackButton,\n IonContent,\n IonList,\n IonItem,\n IonInput,\n IonDatetime,\n IonTextarea,\n IonNote,\n IonButton,\n ],\n})\nexport class CreateEventPageComponent {\n private readonly eventService = inject(EVENTUS_EVENT_SERVICE);\n private readonly router = inject(Router);\n\n /** Host space the event is created in (from the route). */\n readonly spaceType = input.required<string>();\n readonly spaceID = input.required<string>();\n\n protected title = '';\n protected start = '';\n protected location = '';\n protected description = '';\n /** Event length in minutes (default 60); reuses Calendarius's duration model. */\n protected durationMinutes = 60;\n\n protected readonly submitting = signal(false);\n protected readonly error = signal<string | undefined>(undefined);\n\n protected get canSubmit(): boolean {\n return (\n !this.submitting() &&\n this.title.trim().length > 0 &&\n this.start.trim().length > 0 &&\n this.location.trim().length > 0\n );\n }\n\n protected submit(): void {\n if (!this.canSubmit) {\n return;\n }\n const request: ICreateEventRequest = {\n title: this.title.trim(),\n start: this.start,\n location: this.location.trim(),\n };\n const description = this.description.trim();\n if (description) {\n request.description = description;\n }\n if (this.durationMinutes > 0) {\n request.durationMinutes = this.durationMinutes;\n }\n\n this.submitting.set(true);\n this.error.set(undefined);\n this.eventService.createEvent(this.spaceID(), request).subscribe({\n next: (created) => {\n void this.router.navigate([\n '/space',\n this.spaceType(),\n this.spaceID(),\n 'events',\n created.id,\n ]);\n },\n error: (err: unknown) => {\n this.submitting.set(false);\n this.error.set(extractErrorMessage(err, 'Failed to create event.'));\n },\n });\n }\n}\n","<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-back-button defaultHref=\"/\"></ion-back-button>\n </ion-buttons>\n <ion-title>New event</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n <ion-list>\n <ion-item>\n <ion-input\n label=\"Title\"\n labelPlacement=\"stacked\"\n placeholder=\"Sophie's 10th Birthday\"\n [(ngModel)]=\"title\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-input\n label=\"Location\"\n labelPlacement=\"stacked\"\n placeholder=\"123 Main St\"\n [(ngModel)]=\"location\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-textarea\n label=\"Description\"\n labelPlacement=\"stacked\"\n placeholder=\"Optional details\"\n [(ngModel)]=\"description\"\n [autoGrow]=\"true\"\n ></ion-textarea>\n </ion-item>\n </ion-list>\n\n <ion-list>\n <ion-item lines=\"none\">\n <ion-note>Date &amp; time</ion-note>\n </ion-item>\n <ion-datetime\n aria-label=\"Event date and time\"\n [(ngModel)]=\"start\"\n presentation=\"date-time\"\n ></ion-datetime>\n <ion-item>\n <ion-input\n label=\"Duration (minutes)\"\n labelPlacement=\"stacked\"\n type=\"number\"\n min=\"1\"\n [(ngModel)]=\"durationMinutes\"\n ></ion-input>\n </ion-item>\n </ion-list>\n\n @if (error()) {\n <ion-note color=\"danger\" class=\"ion-padding-start\">{{ error() }}</ion-note>\n }\n\n <ion-button\n expand=\"block\"\n class=\"ion-margin-top\"\n [disabled]=\"!canSubmit\"\n (click)=\"submit()\"\n >\n Create event\n </ion-button>\n</ion-content>\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, input, signal, Component } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { FormsModule } from '@angular/forms';
5
+ import { Router } from '@angular/router';
6
+ import { IonHeader, IonToolbar, IonTitle, IonButtons, IonBackButton, IonContent, IonList, IonItem, IonInput, IonDatetime, IonTextarea, IonNote, IonText, IonSpinner, IonButton } from '@ionic/angular/standalone';
7
+ import { EVENT_SERVICE, extractErrorMessage } from '@sneat/extension-eventus-contract';
8
+
9
+ // Host screen to edit an event's title/date-time/location/description (PUT).
10
+ // Loads the current event to prefill the form. (AC: only-host-edits)
11
+ class EditEventPageComponent {
12
+ eventService = inject(EVENT_SERVICE);
13
+ router = inject(Router);
14
+ spaceType = input.required(...(ngDevMode ? [{ debugName: "spaceType" }] : /* istanbul ignore next */ []));
15
+ spaceID = input.required(...(ngDevMode ? [{ debugName: "spaceID" }] : /* istanbul ignore next */ []));
16
+ eventID = input.required(...(ngDevMode ? [{ debugName: "eventID" }] : /* istanbul ignore next */ []));
17
+ title = '';
18
+ start = '';
19
+ location = '';
20
+ description = '';
21
+ loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
22
+ loadFailed = signal(false, ...(ngDevMode ? [{ debugName: "loadFailed" }] : /* istanbul ignore next */ []));
23
+ saving = signal(false, ...(ngDevMode ? [{ debugName: "saving" }] : /* istanbul ignore next */ []));
24
+ error = signal(undefined, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
25
+ ngOnInit() {
26
+ this.eventService.getEvent(this.spaceID(), this.eventID()).subscribe({
27
+ next: (event) => {
28
+ this.title = event.title;
29
+ this.start = event.start;
30
+ this.location = event.location;
31
+ this.description = event.description ?? '';
32
+ this.loading.set(false);
33
+ },
34
+ error: (err) => {
35
+ this.loading.set(false);
36
+ this.loadFailed.set(true);
37
+ this.error.set(extractErrorMessage(err, 'Failed to load event.'));
38
+ },
39
+ });
40
+ }
41
+ get canSave() {
42
+ return (!this.saving() &&
43
+ this.title.trim().length > 0 &&
44
+ this.start.trim().length > 0 &&
45
+ this.location.trim().length > 0);
46
+ }
47
+ save() {
48
+ if (!this.canSave) {
49
+ return;
50
+ }
51
+ const request = {
52
+ title: this.title.trim(),
53
+ start: this.start,
54
+ location: this.location.trim(),
55
+ description: this.description.trim(),
56
+ };
57
+ this.saving.set(true);
58
+ this.error.set(undefined);
59
+ this.eventService
60
+ .updateEvent(this.spaceID(), this.eventID(), request)
61
+ .subscribe({
62
+ next: (event) => {
63
+ void this.router.navigate([
64
+ '/space',
65
+ this.spaceType(),
66
+ this.spaceID(),
67
+ 'events',
68
+ event.id,
69
+ ]);
70
+ },
71
+ error: (err) => {
72
+ this.saving.set(false);
73
+ this.error.set(extractErrorMessage(err, 'Failed to save event.'));
74
+ },
75
+ });
76
+ }
77
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EditEventPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
78
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: EditEventPageComponent, isStandalone: true, selector: "eventus-edit-event-page", inputs: { spaceType: { classPropertyName: "spaceType", publicName: "spaceType", isSignal: true, isRequired: true, transformFunction: null }, spaceID: { classPropertyName: "spaceID", publicName: "spaceID", isSignal: true, isRequired: true, transformFunction: null }, eventID: { classPropertyName: "eventID", publicName: "eventID", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-back-button defaultHref=\"/\"></ion-back-button>\n </ion-buttons>\n <ion-title>Edit event</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n @if (loading()) {\n <ion-spinner aria-label=\"Loading event\"></ion-spinner>\n } @else if (loadFailed()) {\n <ion-text color=\"danger\">{{ error() }}</ion-text>\n } @else {\n <ion-list>\n <ion-item>\n <ion-input\n label=\"Title\"\n labelPlacement=\"stacked\"\n [(ngModel)]=\"title\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-input\n label=\"Location\"\n labelPlacement=\"stacked\"\n [(ngModel)]=\"location\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-textarea\n label=\"Description\"\n labelPlacement=\"stacked\"\n placeholder=\"Optional details\"\n [(ngModel)]=\"description\"\n [autoGrow]=\"true\"\n ></ion-textarea>\n </ion-item>\n </ion-list>\n\n <ion-list>\n <ion-item lines=\"none\">\n <ion-note>Date &amp; time</ion-note>\n </ion-item>\n <ion-datetime\n aria-label=\"Event date and time\"\n [(ngModel)]=\"start\"\n presentation=\"date-time\"\n ></ion-datetime>\n </ion-list>\n\n @if (error()) {\n <ion-text color=\"danger\">{{ error() }}</ion-text>\n }\n\n <ion-button\n expand=\"block\"\n class=\"ion-margin-top\"\n [disabled]=\"!canSave\"\n (click)=\"save()\"\n >\n Save changes\n </ion-button>\n }\n</ion-content>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonBackButton, selector: "ion-back-button" }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonDatetime, selector: "ion-datetime", inputs: ["cancelText", "clearText", "color", "dayValues", "disabled", "doneText", "firstDayOfWeek", "formatOptions", "highlightedDates", "hourCycle", "hourValues", "isDateEnabled", "locale", "max", "min", "minuteValues", "mode", "monthValues", "multiple", "name", "preferWheel", "presentation", "readonly", "showAdjacentDays", "showClearButton", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "titleSelectedDatesFormatter", "value", "yearValues"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }] });
79
+ }
80
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EditEventPageComponent, decorators: [{
81
+ type: Component,
82
+ args: [{ selector: 'eventus-edit-event-page', imports: [
83
+ FormsModule,
84
+ IonHeader,
85
+ IonToolbar,
86
+ IonTitle,
87
+ IonButtons,
88
+ IonBackButton,
89
+ IonContent,
90
+ IonList,
91
+ IonItem,
92
+ IonInput,
93
+ IonDatetime,
94
+ IonTextarea,
95
+ IonNote,
96
+ IonText,
97
+ IonSpinner,
98
+ IonButton,
99
+ ], template: "<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-back-button defaultHref=\"/\"></ion-back-button>\n </ion-buttons>\n <ion-title>Edit event</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n @if (loading()) {\n <ion-spinner aria-label=\"Loading event\"></ion-spinner>\n } @else if (loadFailed()) {\n <ion-text color=\"danger\">{{ error() }}</ion-text>\n } @else {\n <ion-list>\n <ion-item>\n <ion-input\n label=\"Title\"\n labelPlacement=\"stacked\"\n [(ngModel)]=\"title\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-input\n label=\"Location\"\n labelPlacement=\"stacked\"\n [(ngModel)]=\"location\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-textarea\n label=\"Description\"\n labelPlacement=\"stacked\"\n placeholder=\"Optional details\"\n [(ngModel)]=\"description\"\n [autoGrow]=\"true\"\n ></ion-textarea>\n </ion-item>\n </ion-list>\n\n <ion-list>\n <ion-item lines=\"none\">\n <ion-note>Date &amp; time</ion-note>\n </ion-item>\n <ion-datetime\n aria-label=\"Event date and time\"\n [(ngModel)]=\"start\"\n presentation=\"date-time\"\n ></ion-datetime>\n </ion-list>\n\n @if (error()) {\n <ion-text color=\"danger\">{{ error() }}</ion-text>\n }\n\n <ion-button\n expand=\"block\"\n class=\"ion-margin-top\"\n [disabled]=\"!canSave\"\n (click)=\"save()\"\n >\n Save changes\n </ion-button>\n }\n</ion-content>\n" }]
100
+ }], propDecorators: { spaceType: [{ type: i0.Input, args: [{ isSignal: true, alias: "spaceType", required: true }] }], spaceID: [{ type: i0.Input, args: [{ isSignal: true, alias: "spaceID", required: true }] }], eventID: [{ type: i0.Input, args: [{ isSignal: true, alias: "eventID", required: true }] }] } });
101
+
102
+ export { EditEventPageComponent };
103
+ //# sourceMappingURL=sneat-extension-eventus-shared-edit-event-page.component-lhOpcqld.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sneat-extension-eventus-shared-edit-event-page.component-lhOpcqld.mjs","sources":["../../../../../../libs/extensions/eventus/shared/src/lib/pages/edit-event/edit-event-page.component.ts","../../../../../../libs/extensions/eventus/shared/src/lib/pages/edit-event/edit-event-page.component.html"],"sourcesContent":["import { Component, OnInit, inject, input, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { Router } from '@angular/router';\nimport {\n IonBackButton,\n IonButton,\n IonButtons,\n IonContent,\n IonDatetime,\n IonHeader,\n IonInput,\n IonItem,\n IonList,\n IonNote,\n IonSpinner,\n IonTextarea,\n IonText,\n IonTitle,\n IonToolbar,\n} from '@ionic/angular/standalone';\nimport {\n EVENT_SERVICE,\n extractErrorMessage,\n IUpdateEventRequest,\n} from '@sneat/extension-eventus-contract';\n\n// Host screen to edit an event's title/date-time/location/description (PUT).\n// Loads the current event to prefill the form. (AC: only-host-edits)\n@Component({\n selector: 'eventus-edit-event-page',\n templateUrl: './edit-event-page.component.html',\n imports: [\n FormsModule,\n IonHeader,\n IonToolbar,\n IonTitle,\n IonButtons,\n IonBackButton,\n IonContent,\n IonList,\n IonItem,\n IonInput,\n IonDatetime,\n IonTextarea,\n IonNote,\n IonText,\n IonSpinner,\n IonButton,\n ],\n})\nexport class EditEventPageComponent implements OnInit {\n private readonly eventService = inject(EVENT_SERVICE);\n private readonly router = inject(Router);\n\n readonly spaceType = input.required<string>();\n readonly spaceID = input.required<string>();\n readonly eventID = input.required<string>();\n\n protected title = '';\n protected start = '';\n protected location = '';\n protected description = '';\n\n protected readonly loading = signal(true);\n protected readonly loadFailed = signal(false);\n protected readonly saving = signal(false);\n protected readonly error = signal<string | undefined>(undefined);\n\n ngOnInit(): void {\n this.eventService.getEvent(this.spaceID(), this.eventID()).subscribe({\n next: (event) => {\n this.title = event.title;\n this.start = event.start;\n this.location = event.location;\n this.description = event.description ?? '';\n this.loading.set(false);\n },\n error: (err: unknown) => {\n this.loading.set(false);\n this.loadFailed.set(true);\n this.error.set(extractErrorMessage(err, 'Failed to load event.'));\n },\n });\n }\n\n protected get canSave(): boolean {\n return (\n !this.saving() &&\n this.title.trim().length > 0 &&\n this.start.trim().length > 0 &&\n this.location.trim().length > 0\n );\n }\n\n protected save(): void {\n if (!this.canSave) {\n return;\n }\n const request: IUpdateEventRequest = {\n title: this.title.trim(),\n start: this.start,\n location: this.location.trim(),\n description: this.description.trim(),\n };\n\n this.saving.set(true);\n this.error.set(undefined);\n this.eventService\n .updateEvent(this.spaceID(), this.eventID(), request)\n .subscribe({\n next: (event) => {\n void this.router.navigate([\n '/space',\n this.spaceType(),\n this.spaceID(),\n 'events',\n event.id,\n ]);\n },\n error: (err: unknown) => {\n this.saving.set(false);\n this.error.set(extractErrorMessage(err, 'Failed to save event.'));\n },\n });\n }\n}\n","<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-back-button defaultHref=\"/\"></ion-back-button>\n </ion-buttons>\n <ion-title>Edit event</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\">\n @if (loading()) {\n <ion-spinner aria-label=\"Loading event\"></ion-spinner>\n } @else if (loadFailed()) {\n <ion-text color=\"danger\">{{ error() }}</ion-text>\n } @else {\n <ion-list>\n <ion-item>\n <ion-input\n label=\"Title\"\n labelPlacement=\"stacked\"\n [(ngModel)]=\"title\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-input\n label=\"Location\"\n labelPlacement=\"stacked\"\n [(ngModel)]=\"location\"\n required\n ></ion-input>\n </ion-item>\n\n <ion-item>\n <ion-textarea\n label=\"Description\"\n labelPlacement=\"stacked\"\n placeholder=\"Optional details\"\n [(ngModel)]=\"description\"\n [autoGrow]=\"true\"\n ></ion-textarea>\n </ion-item>\n </ion-list>\n\n <ion-list>\n <ion-item lines=\"none\">\n <ion-note>Date &amp; time</ion-note>\n </ion-item>\n <ion-datetime\n aria-label=\"Event date and time\"\n [(ngModel)]=\"start\"\n presentation=\"date-time\"\n ></ion-datetime>\n </ion-list>\n\n @if (error()) {\n <ion-text color=\"danger\">{{ error() }}</ion-text>\n }\n\n <ion-button\n expand=\"block\"\n class=\"ion-margin-top\"\n [disabled]=\"!canSave\"\n (click)=\"save()\"\n >\n Save changes\n </ion-button>\n }\n</ion-content>\n"],"names":[],"mappings":"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"}