@sneat/extensions-schedulus-shared 0.3.0
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/esm2022/index.js +2 -0
- package/esm2022/index.js.map +1 -0
- package/esm2022/lib/components/calendar/calendar-base.component.js +83 -0
- package/esm2022/lib/components/calendar/calendar-base.component.js.map +1 -0
- package/esm2022/lib/components/calendar/calendar-brief.component.js +57 -0
- package/esm2022/lib/components/calendar/calendar-brief.component.js.map +1 -0
- package/esm2022/lib/components/calendar/calendar-component-types.js +2 -0
- package/esm2022/lib/components/calendar/calendar-component-types.js.map +1 -0
- package/esm2022/lib/components/calendar/calendar-state.service.js +90 -0
- package/esm2022/lib/components/calendar/calendar-state.service.js.map +1 -0
- package/esm2022/lib/components/calendar/calendar.component.js +284 -0
- package/esm2022/lib/components/calendar/calendar.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-add-buttons/calendar-add-buttons.component.js +45 -0
- package/esm2022/lib/components/calendar/components/calendar-add-buttons/calendar-add-buttons.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day-base.component.js +26 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day-base.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day-card.component.js +67 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day-card.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day-tab.component.js +74 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day-tab.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day-title.component.js +27 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day-title.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day.component.js +129 -0
- package/esm2022/lib/components/calendar/components/calendar-day/calendar-day.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-filter/calendar-filter.component.js +162 -0
- package/esm2022/lib/components/calendar/components/calendar-filter/calendar-filter.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-filter/calendar-filter.js +17 -0
- package/esm2022/lib/components/calendar/components/calendar-filter/calendar-filter.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-filter/contacts-filter.component.js +95 -0
- package/esm2022/lib/components/calendar/components/calendar-filter/contacts-filter.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-week/calendar-week-card.component.js +50 -0
- package/esm2022/lib/components/calendar/components/calendar-week/calendar-week-card.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-week/calendar-week-tab.component.js +18 -0
- package/esm2022/lib/components/calendar/components/calendar-week/calendar-week-tab.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-week/calendar-week-title.component.js +15 -0
- package/esm2022/lib/components/calendar/components/calendar-week/calendar-week-title.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-week/calendar-week.component.js +78 -0
- package/esm2022/lib/components/calendar/components/calendar-week/calendar-week.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/calendar-weekday/calendar-weekday.component.js +66 -0
- package/esm2022/lib/components/calendar/components/calendar-weekday/calendar-weekday.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/day-slot-item/day-slot-item.component.js +93 -0
- package/esm2022/lib/components/calendar/components/day-slot-item/day-slot-item.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/day-slot-item/slot-context-menu.component.js +324 -0
- package/esm2022/lib/components/calendar/components/day-slot-item/slot-context-menu.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/recurrings-tab/recurrings-tab.component.js +36 -0
- package/esm2022/lib/components/calendar/components/recurrings-tab/recurrings-tab.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/singles-tab/single-happenings-list.component.js +65 -0
- package/esm2022/lib/components/calendar/components/singles-tab/single-happenings-list.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/singles-tab/singles-tab.component.js +106 -0
- package/esm2022/lib/components/calendar/components/singles-tab/singles-tab.component.js.map +1 -0
- package/esm2022/lib/components/calendar/components/timing-badge/timing-badge.component.js +25 -0
- package/esm2022/lib/components/calendar/components/timing-badge/timing-badge.component.js.map +1 -0
- package/esm2022/lib/components/calendar/weekday.js +2 -0
- package/esm2022/lib/components/calendar/weekday.js.map +1 -0
- package/esm2022/lib/components/calendar-core.js +64 -0
- package/esm2022/lib/components/calendar-core.js.map +1 -0
- package/esm2022/lib/components/calendar-filter.service.js +28 -0
- package/esm2022/lib/components/calendar-filter.service.js.map +1 -0
- package/esm2022/lib/components/calendar-slots.js +30 -0
- package/esm2022/lib/components/calendar-slots.js.map +1 -0
- package/esm2022/lib/components/happening-base.component.js +188 -0
- package/esm2022/lib/components/happening-base.component.js.map +1 -0
- package/esm2022/lib/components/happening-card/happening-card.component.js +69 -0
- package/esm2022/lib/components/happening-card/happening-card.component.js.map +1 -0
- package/esm2022/lib/components/happening-component-base-params.js +37 -0
- package/esm2022/lib/components/happening-component-base-params.js.map +1 -0
- package/esm2022/lib/components/happening-form/happening-form.component.js +348 -0
- package/esm2022/lib/components/happening-form/happening-form.component.js.map +1 -0
- package/esm2022/lib/components/happening-form/happening-price-form/happening-price-modal.component.js +161 -0
- package/esm2022/lib/components/happening-form/happening-price-form/happening-price-modal.component.js.map +1 -0
- package/esm2022/lib/components/happening-form/happening-prices/happening-prices.component.js +142 -0
- package/esm2022/lib/components/happening-form/happening-prices/happening-prices.component.js.map +1 -0
- package/esm2022/lib/components/happening-participants/happening-participants.component.js +195 -0
- package/esm2022/lib/components/happening-participants/happening-participants.component.js.map +1 -0
- package/esm2022/lib/components/happening-slot-form/happening-slot-form.component.js +505 -0
- package/esm2022/lib/components/happening-slot-form/happening-slot-form.component.js.map +1 -0
- package/esm2022/lib/components/happening-slot-form/happening-slot-modal.component.js +140 -0
- package/esm2022/lib/components/happening-slot-form/happening-slot-modal.component.js.map +1 -0
- package/esm2022/lib/components/happening-slot-form/happening-slot-modal.service.js +47 -0
- package/esm2022/lib/components/happening-slot-form/happening-slot-modal.service.js.map +1 -0
- package/esm2022/lib/components/happening-slot-participants/happening-slot-participants.component.js +74 -0
- package/esm2022/lib/components/happening-slot-participants/happening-slot-participants.component.js.map +1 -0
- package/esm2022/lib/components/happening-slots/happening-slots.component.js +130 -0
- package/esm2022/lib/components/happening-slots/happening-slots.component.js.map +1 -0
- package/esm2022/lib/components/index.js +20 -0
- package/esm2022/lib/components/index.js.map +1 -0
- package/esm2022/lib/components/start-end-dates-range-form/start-end-dates-range-form.component.js +68 -0
- package/esm2022/lib/components/start-end-dates-range-form/start-end-dates-range-form.component.js.map +1 -0
- package/esm2022/lib/components/start-end-datetime-form/start-end-datetime-form.component.js +377 -0
- package/esm2022/lib/components/start-end-datetime-form/start-end-datetime-form.component.js.map +1 -0
- package/esm2022/lib/components/start-end-datetime-form/time-selector.component.js +92 -0
- package/esm2022/lib/components/start-end-datetime-form/time-selector.component.js.map +1 -0
- package/esm2022/lib/components/swipeable-base.component.js +112 -0
- package/esm2022/lib/components/swipeable-base.component.js.map +1 -0
- package/esm2022/lib/components/swipeable-ui.js +64 -0
- package/esm2022/lib/components/swipeable-ui.js.map +1 -0
- package/esm2022/lib/components/week.js +2 -0
- package/esm2022/lib/components/week.js.map +1 -0
- package/esm2022/lib/components/weekday-functions.js +13 -0
- package/esm2022/lib/components/weekday-functions.js.map +1 -0
- package/esm2022/lib/components/weekdays/weekdays-form-base.js +72 -0
- package/esm2022/lib/components/weekdays/weekdays-form-base.js.map +1 -0
- package/esm2022/lib/index.js +3 -0
- package/esm2022/lib/index.js.map +1 -0
- package/esm2022/lib/modals/happening-title-modal/happening-title-modal.component.js +87 -0
- package/esm2022/lib/modals/happening-title-modal/happening-title-modal.component.js.map +1 -0
- package/esm2022/lib/services/calendar-data-provider.js +271 -0
- package/esm2022/lib/services/calendar-data-provider.js.map +1 -0
- package/esm2022/lib/services/calendar-day.js +179 -0
- package/esm2022/lib/services/calendar-day.js.map +1 -0
- package/esm2022/lib/services/calendar-day.service.js +37 -0
- package/esm2022/lib/services/calendar-day.service.js.map +1 -0
- package/esm2022/lib/services/calendar-nav.service.js +36 -0
- package/esm2022/lib/services/calendar-nav.service.js.map +1 -0
- package/esm2022/lib/services/calendar-space.js +152 -0
- package/esm2022/lib/services/calendar-space.js.map +1 -0
- package/esm2022/lib/services/calendar-types.js +52 -0
- package/esm2022/lib/services/calendar-types.js.map +1 -0
- package/esm2022/lib/services/calendarium-services.module.js +16 -0
- package/esm2022/lib/services/calendarium-services.module.js.map +1 -0
- package/esm2022/lib/services/calendarium-space.service.js +16 -0
- package/esm2022/lib/services/calendarium-space.service.js.map +1 -0
- package/esm2022/lib/services/happening.service.js +225 -0
- package/esm2022/lib/services/happening.service.js.map +1 -0
- package/esm2022/lib/services/index.js +6 -0
- package/esm2022/lib/services/index.js.map +1 -0
- package/esm2022/sneat-extensions-schedulus-shared.js +5 -0
- package/esm2022/sneat-extensions-schedulus-shared.js.map +1 -0
- package/index.d.ts +1 -0
- package/lib/components/calendar/calendar-base.component.d.ts +23 -0
- package/lib/components/calendar/calendar-brief.component.d.ts +11 -0
- package/lib/components/calendar/calendar-component-types.d.ts +1 -0
- package/lib/components/calendar/calendar-state.service.d.ts +15 -0
- package/lib/components/calendar/calendar.component.d.ts +32 -0
- package/lib/components/calendar/components/calendar-add-buttons/calendar-add-buttons.component.d.ts +13 -0
- package/lib/components/calendar/components/calendar-day/calendar-day-base.component.d.ts +10 -0
- package/lib/components/calendar/components/calendar-day/calendar-day-card.component.d.ts +17 -0
- package/lib/components/calendar/components/calendar-day/calendar-day-tab.component.d.ts +19 -0
- package/lib/components/calendar/components/calendar-day/calendar-day-title.component.d.ts +10 -0
- package/lib/components/calendar/components/calendar-day/calendar-day.component.d.ts +30 -0
- package/lib/components/calendar/components/calendar-filter/calendar-filter.component.d.ts +39 -0
- package/lib/components/calendar/components/calendar-filter/calendar-filter.d.ts +10 -0
- package/lib/components/calendar/components/calendar-filter/contacts-filter.component.d.ts +20 -0
- package/lib/components/calendar/components/calendar-week/calendar-week-card.component.d.ts +15 -0
- package/lib/components/calendar/components/calendar-week/calendar-week-tab.component.d.ts +9 -0
- package/lib/components/calendar/components/calendar-week/calendar-week-title.component.d.ts +7 -0
- package/lib/components/calendar/components/calendar-week/calendar-week.component.d.ts +20 -0
- package/lib/components/calendar/components/calendar-weekday/calendar-weekday.component.d.ts +23 -0
- package/lib/components/calendar/components/day-slot-item/day-slot-item.component.d.ts +19 -0
- package/lib/components/calendar/components/day-slot-item/slot-context-menu.component.d.ts +40 -0
- package/lib/components/calendar/components/recurrings-tab/recurrings-tab.component.d.ts +15 -0
- package/lib/components/calendar/components/singles-tab/single-happenings-list.component.d.ts +22 -0
- package/lib/components/calendar/components/singles-tab/singles-tab.component.d.ts +29 -0
- package/lib/components/calendar/components/timing-badge/timing-badge.component.d.ts +17 -0
- package/lib/components/calendar/weekday.d.ts +7 -0
- package/lib/components/calendar-core.d.ts +10 -0
- package/lib/components/calendar-filter.service.d.ts +8 -0
- package/lib/components/calendar-slots.d.ts +5 -0
- package/lib/components/happening-base.component.d.ts +46 -0
- package/lib/components/happening-card/happening-card.component.d.ts +11 -0
- package/lib/components/happening-component-base-params.d.ts +16 -0
- package/lib/components/happening-form/happening-form.component.d.ts +52 -0
- package/lib/components/happening-form/happening-price-form/happening-price-modal.component.d.ts +29 -0
- package/lib/components/happening-form/happening-prices/happening-prices.component.d.ts +16 -0
- package/lib/components/happening-participants/happening-participants.component.d.ts +24 -0
- package/lib/components/happening-slot-form/happening-slot-form.component.d.ts +76 -0
- package/lib/components/happening-slot-form/happening-slot-modal.component.d.ts +26 -0
- package/lib/components/happening-slot-form/happening-slot-modal.service.d.ts +18 -0
- package/lib/components/happening-slot-participants/happening-slot-participants.component.d.ts +19 -0
- package/lib/components/happening-slots/happening-slots.component.d.ts +28 -0
- package/lib/components/index.d.ts +5 -0
- package/lib/components/start-end-dates-range-form/start-end-dates-range-form.component.d.ts +16 -0
- package/lib/components/start-end-datetime-form/start-end-datetime-form.component.d.ts +53 -0
- package/lib/components/start-end-datetime-form/time-selector.component.d.ts +15 -0
- package/lib/components/swipeable-base.component.d.ts +25 -0
- package/lib/components/swipeable-ui.d.ts +24 -0
- package/lib/components/week.d.ts +4 -0
- package/lib/components/weekday-functions.d.ts +3 -0
- package/lib/components/weekdays/weekdays-form-base.d.ts +31 -0
- package/lib/index.d.ts +2 -0
- package/lib/modals/happening-title-modal/happening-title-modal.component.d.ts +24 -0
- package/lib/services/calendar-data-provider.d.ts +33 -0
- package/lib/services/calendar-day.d.ts +45 -0
- package/lib/services/calendar-day.service.d.ts +18 -0
- package/lib/services/calendar-nav.service.d.ts +14 -0
- package/lib/services/calendar-space.d.ts +23 -0
- package/lib/services/calendar-types.d.ts +10 -0
- package/lib/services/calendarium-services.module.d.ts +6 -0
- package/lib/services/calendarium-space.service.d.ts +8 -0
- package/lib/services/happening.service.d.ts +99 -0
- package/lib/services/index.d.ts +5 -0
- package/package.json +26 -0
- package/sneat-extensions-schedulus-shared.d.ts +5 -0
- package/tsconfig.lib.prod.tsbuildinfo +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"happening-form.component.js","sourceRoot":"","sources":["../../../../../../../../../libs/extensions/schedulus/shared/src/lib/components/happening-form/happening-form.component.ts","../../../../../../../../../libs/extensions/schedulus/shared/src/lib/components/happening-form/happening-form.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n AfterViewInit,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n computed,\n effect,\n EventEmitter,\n inject,\n input,\n Input,\n Output,\n signal,\n ViewChild,\n} from '@angular/core';\nimport {\n FormControl,\n FormGroup,\n ReactiveFormsModule,\n Validators,\n} from '@angular/forms';\nimport {\n ModalController,\n NavController,\n IonButton,\n IonCard,\n IonCardContent,\n IonCardHeader,\n IonIcon,\n IonInput,\n IonItem,\n IonItemGroup,\n IonLabel,\n IonSegment,\n IonSegmentButton,\n IonSpinner,\n IonCardSubtitle,\n IonButtons,\n IonTextarea,\n IonGrid,\n IonRow,\n IonCol,\n} from '@ionic/angular/standalone';\nimport { RoutingState } from '@sneat/core';\nimport {\n HappeningType,\n IHappeningContext,\n IHappeningDbo,\n IHappeningSlotWithID,\n mergeValuesWithIDs,\n WeekdayCode2,\n} from '@sneat/mod-schedulus-core';\nimport { SpaceComponentBaseParams } from '@sneat/space-components';\nimport { takeUntil } from 'rxjs';\nimport { HappeningTitleModalComponent } from '../../modals/happening-title-modal/happening-title-modal.component';\nimport { HappeningParticipantsComponent } from '../happening-participants/happening-participants.component';\nimport { HappeningSlotFormComponent } from '../happening-slot-form/happening-slot-form.component';\nimport { HappeningSlotsComponent } from '../happening-slots/happening-slots.component';\nimport { HappeningPricesComponent } from './happening-prices/happening-prices.component';\nimport {\n HappeningService,\n HappeningServiceModule,\n ICancelHappeningRequest,\n} from '../../services/happening.service';\nimport { WithSpaceInput } from '@sneat/space-services';\n\n@Component({\n imports: [\n ReactiveFormsModule,\n HappeningServiceModule,\n HappeningParticipantsComponent,\n HappeningPricesComponent,\n HappeningSlotFormComponent,\n HappeningSlotsComponent,\n IonSegment,\n IonSegmentButton,\n IonCard,\n IonItem,\n IonLabel,\n IonInput,\n IonItemGroup,\n IonButton,\n IonCardHeader,\n IonCardContent,\n IonIcon,\n IonSpinner,\n IonCardSubtitle,\n IonButtons,\n IonTextarea,\n IonGrid,\n IonRow,\n IonCol,\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'sneat-happening-form',\n templateUrl: 'happening-form.component.html',\n})\nexport class HappeningFormComponent\n extends WithSpaceInput\n implements AfterViewInit\n{\n private readonly changeDetectorRef = inject(ChangeDetectorRef);\n private readonly happeningService = inject(HappeningService);\n private readonly params = inject(SpaceComponentBaseParams);\n\n public readonly $happening = input.required<IHappeningContext>();\n protected readonly $happeningID = computed(() => this.$happening().id);\n protected readonly $mode = computed<'edit' | 'create'>(() =>\n this.$happeningID() ? 'edit' : 'create',\n );\n protected readonly $hasDescription = computed(\n () => this.$happening().dbo?.description,\n );\n @Input() public wd?: WeekdayCode2;\n @Input() public date?: string;\n @Output() readonly happeningChange = new EventEmitter<IHappeningContext>();\n\n private readonly navController = inject(NavController);\n\n // @Input({ required: true }) public space?: ISpaceContext;\n\n @ViewChild('titleInput', { static: true }) titleInput?: IonInput;\n @ViewChild('happeningSlotsComponent', { static: false })\n happeningSlotsComponent?: HappeningSlotsComponent;\n\n protected readonly $isCreating = signal(false);\n protected readonly $isCancelling = signal(false);\n protected readonly $isDeleting = signal(false);\n\n protected readonly $slots = computed<IHappeningSlotWithID[] | undefined>(\n () => {\n const happening = this.$happening();\n return happening.brief\n ? mergeValuesWithIDs(happening.brief.slots)\n : undefined;\n },\n );\n\n protected readonly happeningTitle = new FormControl<string>(\n '',\n Validators.required,\n );\n\n // protected onTitleChange(event: Event): void {\n // \tconsole.log('onTitleChange()', event);\n // }\n\n private readonly modalController = inject(ModalController);\n\n protected async editTitle(event: Event) {\n event.preventDefault();\n event.stopPropagation();\n const modal = await this.modalController.create({\n component: HappeningTitleModalComponent,\n componentProps: {\n happening: this.$happening(),\n },\n });\n await modal.present();\n // const title = (event as CustomEvent).detail.value;\n // this.happeningTitle.setValue(title);\n // const happening = this.$happening();\n // if (happening.brief) {\n // \tthis.happeningChange.emit({\n // \t\t...happening,\n // \t\tbrief: { ...happening.brief, title },\n // \t});\n // }\n }\n\n protected readonly happeningType = new FormControl<HappeningType>(\n 'recurring',\n Validators.required,\n );\n\n protected readonly happeningForm = new FormGroup({\n title: this.happeningTitle,\n });\n\n private readonly hasNavHistory: boolean;\n\n protected isToDo = false;\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private readonly onHappeningTitleChanged = (): void => {};\n\n constructor() {\n super();\n const routingState = inject(RoutingState);\n this.happeningTitle.registerOnChange(this.onHappeningTitleChanged);\n this.hasNavHistory = routingState.hasHistory();\n effect(() => {\n const happening = this.$happening();\n const happeningType = happening?.brief?.type;\n if (happeningType) {\n this.happeningType.setValue(happeningType);\n }\n if (happening.brief?.title && this.happeningTitle.untouched) {\n this.happeningTitle.setValue(happening?.brief?.title);\n // this.changeDetectorRef.markForCheck();\n // this.slots = this?.happening?.brief?.slots || [];\n }\n // this.changeDetectorRef.markForCheck();\n });\n }\n\n ngAfterViewInit(): void /* Intentionally not ngOnInit*/ {\n // console.log('HappeningFormComponent.ngAfterViewInit()');\n this.setFocusToInput(this.titleInput);\n }\n\n protected onHappeningTypeChanged(event: Event): void {\n const happeningType = (event as CustomEvent).detail.value as HappeningType;\n let happening = this.$happening();\n happening = {\n ...happening,\n brief: {\n ...(happening.brief || {\n type: happeningType,\n status: 'draft',\n kind: 'activity',\n title: '',\n }),\n type: happeningType,\n },\n };\n this.happeningChange.emit(happening);\n\n // const setSlots = (slots?: IHappeningSlot[]) => {\n // if (slots && this.happening?.brief) {\n // this.happening = {\n // ...this.happening,\n // brief: {\n // ...this.happening.brief,\n // slots,\n // },\n // };\n // }\n // };\n //\n // switch (happeningType) {\n // case 'single':\n // setSlots(this.happening?.brief?.slots);\n // break;\n // case 'recurring':\n // setSlots(this.happening?.brief?.slots);\n // break;\n // }\n }\n\n protected onTitleEnter(_event?: Event): void {\n this.changeDetectorRef.markForCheck();\n }\n\n protected onTitleChanged(event: CustomEvent): void {\n\n if (event.detail.value === this.titleInput?.value) {\n this.happeningTitle.reset();\n }\n }\n\n ionViewDidEnter(): void {\n if (!this.titleInput) {\n this.errorLogger.logError(new Error('titleInput is not initialized'));\n return;\n }\n this.titleInput\n .setFocus()\n .catch(\n this.errorLogger.logErrorHandler('failed to set focus to title input'),\n );\n }\n\n // onAddSlotModalDismissed(): void {\n // \tconsole.log('NewHappeningPage.onAddSlotModalDismissed()');\n // \tif (!this.titleInput?.value) {\n // \t\tif (this.titleInput) {\n // \t\t\tsetTimeout(() => {\n // \t\t\t\tthis.titleInput?.setFocus().catch(this.logErrorHandler('failed to set focus to title input'));\n // \t\t\t}, 50);\n // \t\t} else {\n // \t\t\tconsole.warn('View child #titleInput is not initialized');\n // \t\t}\n // \t}\n // }\n\n protected onSlotAdded(_slot?: unknown): void {\n this.happeningForm.markAllAsTouched();\n }\n\n protected onHappeningChanged(happening: IHappeningContext): void {\n // this.happening = happening;\n this.happeningForm.markAllAsTouched(); // TODO: Document why we need it and if we can remove it\n this.happeningChange.emit(happening);\n }\n\n protected formIsValid(): boolean {\n if (!this.happeningForm.valid) {\n return false;\n }\n return !!this.$slots()?.length;\n }\n\n private makeHappeningDto(): IHappeningDbo {\n const space = this.$space();\n if (!space) {\n throw new Error('!this.team');\n }\n const happening = this.$happening();\n if (!happening) {\n throw new Error('!this.happening');\n }\n if (!happening.brief) {\n throw new Error('!this.happening.brief');\n }\n const activityFormValue = this.happeningForm.value;\n const dto: IHappeningDbo = {\n ...happening.dbo,\n ...happening.brief,\n spaceIDs: [space.id], // TODO: should be already in this.happening.brief\n title: activityFormValue.title || '', // TODO: should be already in this.happening.brief\n };\n // switch (dto.type) {\n // \tcase 'recurring':\n // \t\t// dto.slots = this.slots.map(slot => ({ ...slot, repeats: 'weekly', id: slot.id || newRandomId({ len: 5 }) }));\n // \t\tbreak;\n // \tcase 'single':\n // \t\tif (!this.singleSlot) {\n // \t\t\tthrow new Error('timing is not set');\n // \t\t}\n // \t\tdto.slots = [{\n // \t\t\t...this.singleSlot,\n // \t\t\tid: 'once',\n // \t\t\trepeats: 'once',\n // \t\t}];\n // \t\tbreak;\n // \tdefault:\n // \t\tthrow new Error('unknown happening type: ' + dto.type);\n // }\n\n return dto;\n }\n\n protected submit(): void {\n if (this.$happening()?.id) {\n alert('editing existing happening is not implemented yet');\n } else {\n //Create happening\n this.createHappening();\n }\n }\n\n private createHappening(): void {\n const space = this.$space();\n if (!space) {\n this.errorLogger.logError(new Error('!space context'));\n return;\n }\n try {\n // this.happeningForm.markAsTouched();\n // if (!this.happeningForm.valid) {\n // \talert('title is a required field');\n // \t// if (!this.happeningForm.controls['title'].valid) {\n // \t// \tthis.titleInput?.setFocus()\n // \t// \t\t.catch(this.logErrorHandler('failed to set focus to title input after happening found to be not valid'));\n // \t// }\n // \treturn;\n // }\n\n this.$isCreating.set(true);\n\n let happening = this.makeHappeningDto();\n\n switch (happening.type) {\n case 'single':\n happening = {\n ...happening,\n slots: Object.fromEntries(\n Object.entries(happening.slots || {}).map(([id, data]) => [\n id,\n { ...data, repeats: 'once' },\n ]),\n ),\n };\n break;\n }\n\n this.happeningService\n .createHappening({ spaceID: space.id, happening })\n .pipe(takeUntil(this.destroyed$))\n .subscribe({\n next: () => {\n if (this.hasNavHistory) {\n this.navController\n .pop()\n .catch(\n this.errorLogger.logErrorHandler(\n 'failed to pop back after creating a happening',\n ),\n );\n } else {\n this.params.spaceNavService\n .navigateBackToSpacePage(space, 'calendar')\n .catch(\n this.errorLogger.logErrorHandler(\n 'failed to navigate to space calendar after creating a happening',\n ),\n );\n }\n },\n error: (err: unknown) => {\n this.$isCreating.set(false);\n this.errorLogger.logError(\n err,\n 'API request failed to create new happening',\n );\n },\n complete: () => {\n this.$isCreating.set(false);\n },\n });\n } catch (e) {\n this.$isCreating.set(false);\n this.errorLogger.logError(e, 'failed to create new happening');\n }\n }\n\n protected cancel(): void {\n const space = this.$space();\n const happening = this.$happening();\n const request: ICancelHappeningRequest = {\n spaceID: space.id || '',\n happeningID: happening.id || '',\n };\n this.$isCancelling.set(true);\n this.happeningService.cancelHappening(request).subscribe({\n next: () => this.$isCancelling.set(false),\n error: (err) => {\n this.errorLogger.logError(err, 'failed to cancel happening');\n this.$isCancelling.set(false);\n },\n // complete: () => this.isCancelling.set(false), -- TODO(help-wanted): Why is not working?\n });\n }\n\n protected delete(): void {\n this.$isDeleting.set(true);\n this.happeningService.deleteHappening(this.$happening()).subscribe({\n next: () => this.$isDeleting.set(false),\n error: (err) => {\n this.errorLogger.logError(err, 'failed to delete happening');\n this.$isDeleting.set(false);\n },\n });\n }\n}\n","<form [formGroup]=\"happeningForm\" (ngSubmit)=\"submit()\">\n @if ($mode() === \"create\") {\n <ion-segment\n class=\"ion-padding-horizontal\"\n [formControl]=\"happeningType\"\n (ionChange)=\"onHappeningTypeChanged($event)\"\n >\n <ion-segment-button value=\"recurring\" [disabled]=\"!!$happening().id\">\n Recurring\n </ion-segment-button>\n <ion-segment-button value=\"single\" [disabled]=\"!!$happening().id\">\n One-timer\n </ion-segment-button>\n </ion-segment>\n }\n\n <ion-card>\n <ion-item\n class=\"sneat-tiny-end-padding\"\n [lines]=\"happeningTitle.value ? 'none' : undefined\"\n >\n @switch ($mode()) {\n @case (\"edit\") {\n @if ($happening().dbo) {\n <ion-label (click)=\"editTitle($event)\" style=\"font-weight: bold\">\n {{ $happening().dbo?.title }}\n </ion-label>\n } @else {\n <ion-spinner\n color=\"medium\"\n name=\"lines-small\"\n slot=\"start\"\n title=\"Loading...\"\n />\n <ion-label>Loading...</ion-label>\n }\n <ion-buttons slot=\"end\">\n <ion-button\n color=\"medium\"\n (click)=\"editTitle($event)\"\n [disabled]=\"!$happeningID()\"\n >\n <ion-icon name=\"create-outline\" slot=\"start\" />\n <ion-label>Edit</ion-label>\n </ion-button>\n </ion-buttons>\n }\n @case (\"create\") {\n <ion-input\n placeholder=\"Title\"\n style=\"font-weight: bold\"\n #titleInput\n [formControl]=\"happeningTitle\"\n (keyup.enter)=\"onTitleEnter($event)\"\n (ionChange)=\"onTitleChanged($event)\"\n type=\"text\"\n />\n }\n }\n </ion-item>\n @if (!happeningTitle.value) {\n <ion-item>\n <ion-label color=\"medium\">\n Enter above the name of the event.\n </ion-label>\n </ion-item>\n }\n @if ($mode() === \"edit\") {\n <ion-grid class=\"ion-grid-layout\">\n <ion-row>\n <ion-col [size]=\"$hasDescription() ? 12 : 6\">\n <ion-item>\n <ion-textarea\n label=\"Summary\"\n labelPlacement=\"stacked\"\n placeholder=\"none\"\n auto-grow=\"true\"\n readonly=\"true\"\n [value]=\"$happening().dbo?.summary\"\n />\n </ion-item>\n </ion-col>\n <ion-col [size]=\"$hasDescription() ? 12 : 6\">\n <ion-item lines=\"none\">\n {{ $happening().dbo?.description }}\n </ion-item>\n </ion-col>\n </ion-row>\n </ion-grid>\n }\n </ion-card>\n\n @if (happeningTitle.value) {\n <ion-card>\n <ion-item-group>\n @if (!$slots()?.length) {\n <sneat-happening-slot-form\n mode=\"in-form\"\n [wd]=\"wd\"\n [date]=\"date\"\n [$happening]=\"$happening()\"\n (happeningChange)=\"onHappeningChanged($event)\"\n (slotAdded)=\"onSlotAdded($event)\"\n />\n }\n @if ($happening().id || $slots()?.length) {\n <sneat-happening-slots\n #happeningSlotsComponent\n [happening]=\"$happening()\"\n [wd]=\"wd\"\n />\n }\n <!--\t\t\t<sneat-single-slot-form-->\n <!--\t\t\t\t[happening]=\"happening\"-->\n <!--\t\t\t\t[style.display]=\"happeningType === 'single' ? 'block' : 'none'\"-->\n <!--\t\t\t\t(happeningSlotChange)=\"onSingleSlotChanged($event)\"-->\n <!--\t\t\t>-->\n <!--\t\t\t\t<!– hide with [style.display] to preserve input values if tab switched back and forth –>-->\n <!--\t\t\t</sneat-single-slot-form>-->\n </ion-item-group>\n </ion-card>\n\n @if ($happening().id || $happening().brief?.slots) {\n <ng-container>\n <sneat-happening-pricing\n [happening]=\"$happening()\"\n (happeningChange)=\"onHappeningChanged($event)\"\n />\n\n <sneat-happening-participants\n [$space]=\"$space()\"\n [$happening]=\"$happening()\"\n (happeningChange)=\"onHappeningChanged($event)\"\n />\n\n <ion-card>\n @if (!formIsValid()) {\n <ion-item>\n <ion-label color=\"danger\">\n <ul>\n @if (\n happeningForm.touched &&\n happeningForm.controls[\"title\"].errors\n ) {\n <li>\n @if (isToDo) {\n Task title is required.\n } @else {\n Please enter a required \"Title\" field at top of the\n page.\n }\n </li>\n }\n @if (\n happeningType.value === \"recurring\" && !$slots()?.length\n ) {\n <li>\n <p>\n At least 1 slot should be specified for a recurring\n happening.\n </p>\n <ion-button>Add slot</ion-button>\n </li>\n }\n </ul>\n </ion-label>\n </ion-item>\n }\n <!--\t\t\t\t@if (weekdaysForm.touched && weekdaysForm.errors && weekdaysForm.errors['required']) {-->\n <!--\t\t\t\t\t<ion-item color=\"danger\" *ngIf=\"\">-->\n <!--\t\t\t\t\t\t{{ weekdaysForm.errors['required'] }}-->\n <!--\t\t\t\t\t</ion-item>-->\n <!--\t\t\t\t}-->\n\n @if (!$happening().id) {\n <div class=\"ion-padding\">\n <ion-button\n [disabled]=\"$isCreating()\"\n [color]=\"formIsValid() ? 'primary' : 'medium'\"\n size=\"large\"\n (click)=\"submit()\"\n >\n @if (isToDo) {\n <ion-label>Add task</ion-label>\n } @else {\n @switch (happeningType.value) {\n @case (\"recurring\") {\n <ion-label>Create recurring happening</ion-label>\n }\n @case (\"single\") {\n <ion-label>Create one-timer happening</ion-label>\n }\n }\n }\n @if ($isCreating()) {\n <ion-spinner slot=\"end\" class=\"ion-margin-horizontal\" />\n }\n </ion-button>\n </div>\n }\n </ion-card>\n </ng-container>\n }\n }\n</form>\n\n@if ($happening().id) {\n <ion-card>\n <ion-card-header>\n <!--\t\t<ion-card-title>Danger zone</ion-card-title>-->\n <ion-card-subtitle>Actions in red are irrevocable</ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n @if ($happening().brief?.status !== \"canceled\") {\n <ion-button\n color=\"warning\"\n [disabled]=\"$isCancelling()\"\n (click)=\"cancel()\"\n >\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Cancel & Archive</ion-label>\n <ion-icon name=\"archive-outline\" slot=\"end\" />\n </ion-button>\n }\n <ion-button color=\"danger\" (click)=\"delete()\" [disabled]=\"$isDeleting()\">\n @if ($isDeleting()) {\n <ion-spinner name=\"lines-small\" slot=\"start\" />\n } @else {\n <ion-icon name=\"close-circle-outline\" slot=\"start\" />\n }\n <ion-label>Delete</ion-label>\n </ion-button>\n </ion-card-content>\n </ion-card>\n}\n"]}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, inject, } from '@angular/core';
|
|
2
|
+
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
3
|
+
import { IonButton, IonButtons, IonContent, IonFooter, IonHeader, IonIcon, IonInput, IonItem, IonLabel, IonList, IonSelect, IonSelectOption, IonTitle, IonToolbar, } from '@ionic/angular/standalone';
|
|
4
|
+
import { ClassName, SneatBaseModalComponent } from '@sneat/ui';
|
|
5
|
+
import { HappeningService, } from '../../../services/happening.service';
|
|
6
|
+
import { RadioGroupToSelectComponent } from '@sneat/wizard';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
import * as i1 from "@angular/forms";
|
|
9
|
+
export class HappeningPriceModalComponent extends SneatBaseModalComponent {
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
13
|
+
this.happeningService = inject(HappeningService);
|
|
14
|
+
this.happeningChange = new EventEmitter();
|
|
15
|
+
// @ViewChild('termLengthSelect', { static: false })
|
|
16
|
+
// termLengthSelect?: IonSelect;
|
|
17
|
+
this.canceled = new EventEmitter();
|
|
18
|
+
this.isSubmitting = false;
|
|
19
|
+
this.priceValue = new FormControl(undefined);
|
|
20
|
+
this.priceCurrency = new FormControl('EUR');
|
|
21
|
+
this.termLength = new FormControl(1);
|
|
22
|
+
this.termPeriods = [];
|
|
23
|
+
this.setTermLengths();
|
|
24
|
+
}
|
|
25
|
+
onTermLengthChange() {
|
|
26
|
+
// console.log('onTermLengthChange', event);
|
|
27
|
+
this.setTermLengths();
|
|
28
|
+
this.forceSelectOptionsRefresh();
|
|
29
|
+
}
|
|
30
|
+
forceSelectOptionsRefresh() {
|
|
31
|
+
// For some reason, the select options are not refreshed when the ion-select-option changes.
|
|
32
|
+
// this.termLengthSelect?.
|
|
33
|
+
const temUnit = this.termUnit;
|
|
34
|
+
this.termUnit = undefined;
|
|
35
|
+
this.changeDetectorRef.detectChanges();
|
|
36
|
+
this.termUnit = temUnit;
|
|
37
|
+
this.changeDetectorRef.detectChanges();
|
|
38
|
+
}
|
|
39
|
+
setTermLengths() {
|
|
40
|
+
const isPlural = (this.termLength.value || 0) > 1;
|
|
41
|
+
this.termPeriods = [
|
|
42
|
+
{ value: 'single', title: 'Single event' },
|
|
43
|
+
{ value: 'hour', title: isPlural ? 'Hours' : 'Hour' },
|
|
44
|
+
{ value: 'day', title: isPlural ? 'Days' : 'Day' },
|
|
45
|
+
{ value: 'week', title: 'Week' },
|
|
46
|
+
{ value: 'month', title: 'Month' },
|
|
47
|
+
{ value: 'year', title: 'Year' },
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
addPrice(event) {
|
|
51
|
+
event.stopPropagation();
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
const termLength = this.termLength.value || 0;
|
|
54
|
+
if (!termLength) {
|
|
55
|
+
this.errorLogger.logError('!termLength');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const amountValue = (this.priceValue.value || 0) * 100;
|
|
59
|
+
const currency = this.priceCurrency.value || '';
|
|
60
|
+
if (!this.termUnit) {
|
|
61
|
+
this.errorLogger.logError('!termUnit');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const price = {
|
|
65
|
+
id: '',
|
|
66
|
+
term: {
|
|
67
|
+
unit: this.termUnit,
|
|
68
|
+
length: termLength,
|
|
69
|
+
},
|
|
70
|
+
amount: {
|
|
71
|
+
value: amountValue,
|
|
72
|
+
currency,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
if (this.happening?.id && this.happening?.space?.id) {
|
|
76
|
+
this.submitPrice(price);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.addPriceToNewHappening(price);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
addPriceToNewHappening(price) {
|
|
83
|
+
price = { ...price, id: `${price.term.unit}${price.term.length}` };
|
|
84
|
+
const pushPrice = (h) => {
|
|
85
|
+
return { ...h, prices: [...(h.prices || []), price] };
|
|
86
|
+
};
|
|
87
|
+
if (this.happening?.brief) {
|
|
88
|
+
this.happening = {
|
|
89
|
+
...this.happening,
|
|
90
|
+
brief: pushPrice(this.happening.brief),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (this.happening?.dbo) {
|
|
94
|
+
this.happening = {
|
|
95
|
+
...this.happening,
|
|
96
|
+
dbo: pushPrice(this.happening.dbo),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
this.happeningChange.emit(this.happening);
|
|
100
|
+
this.dismissModal(this.happening);
|
|
101
|
+
}
|
|
102
|
+
submitPrice(price) {
|
|
103
|
+
const happeningID = this.happening?.id || '';
|
|
104
|
+
const spaceID = this.happening?.space?.id || '';
|
|
105
|
+
if (!happeningID) {
|
|
106
|
+
this.errorLogger.logError('!happeningID');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!spaceID) {
|
|
110
|
+
this.errorLogger.logError('!spaceID');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const request = {
|
|
114
|
+
spaceID: spaceID,
|
|
115
|
+
happeningID,
|
|
116
|
+
prices: [price],
|
|
117
|
+
};
|
|
118
|
+
this.isSubmitting = true;
|
|
119
|
+
this.happeningService.setHappeningPrices(request).subscribe({
|
|
120
|
+
error: this.errorLogger.logErrorHandler('failed to add price to a happening'),
|
|
121
|
+
complete: () => {
|
|
122
|
+
this.isSubmitting = false;
|
|
123
|
+
},
|
|
124
|
+
next: () => {
|
|
125
|
+
this.dismissModal();
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: HappeningPriceModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
130
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: HappeningPriceModalComponent, isStandalone: true, selector: "sneat-happening-price-form", inputs: { happening: "happening" }, outputs: { happeningChange: "happeningChange", canceled: "canceled" }, providers: [{ provide: ClassName, useValue: 'HappeningPriceFormComponent' }], usesInheritance: true, ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"primary\">\n <ion-title>New price</ion-title>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-list lines=\"full\" class=\"ion-no-padding\">\n <ion-item>\n <ion-label color=\"medium\">\n <i>Choose term period and enter the price</i>\n </ion-label>\n </ion-item>\n @if (termUnit) {\n <ion-item>\n @if (termUnit !== \"single\") {\n <ion-input\n label=\"Per\"\n type=\"number\"\n style=\"text-align: right\"\n [formControl]=\"termLength\"\n (ionChange)=\"onTermLengthChange()\"\n />\n }\n <ion-select\n [label]=\"termUnit === 'single' ? 'Per' : undefined\"\n [(ngModel)]=\"termUnit\"\n interface=\"popover\"\n >\n @for (o of termPeriods; track o.value) {\n <ion-select-option [value]=\"o.value\"\n >{{ o.title }}\n </ion-select-option>\n }\n </ion-select>\n </ion-item>\n } @else {\n <sneat-radio-group-to-select\n label=\"Per\"\n [(ngModel)]=\"termUnit\"\n [selectOptions]=\"termPeriods\"\n />\n }\n <ion-item>\n <ion-input\n type=\"number\"\n [formControl]=\"priceValue\"\n label=\"Price\"\n style=\"text-align: right\"\n />\n <ion-select [formControl]=\"priceCurrency\">\n <ion-select-option value=\"EUR\">EUR</ion-select-option>\n <ion-select-option value=\"USD\">USD</ion-select-option>\n <ion-select-option value=\"RUB\">RUB</ion-select-option>\n </ion-select>\n </ion-item>\n </ion-list>\n</ion-content>\n<ion-footer>\n <ion-toolbar>\n @if (termUnit) {\n <ion-item lines=\"none\">\n @if (!priceValue.value) {\n <ion-label color=\"danger\"><i>Price amount is required</i></ion-label>\n }\n @if (!termLength.value && priceValue.value) {\n <ion-label color=\"danger\"><i>Term length is required</i></ion-label>\n }\n </ion-item>\n }\n <ion-buttons slot=\"end\">\n <ion-button\n slot=\"end\"\n fill=\"solid\"\n color=\"primary\"\n [disabled]=\"!priceValue.value || !termLength.value\"\n (click)=\"addPrice($event)\"\n >\n <ion-icon name=\"add-outline\" slot=\"start\" />\n <ion-label>Add price</ion-label>\n </ion-button>\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Cancel</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-footer>\n", dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { 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: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { 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: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: RadioGroupToSelectComponent, selector: "sneat-radio-group-to-select", inputs: ["label", "selectLabel", "radioGroupLabel", "slot", "selectOptions", "disabled"] }, { kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
131
|
+
}
|
|
132
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: HappeningPriceModalComponent, decorators: [{
|
|
133
|
+
type: Component,
|
|
134
|
+
args: [{ imports: [
|
|
135
|
+
ReactiveFormsModule,
|
|
136
|
+
FormsModule,
|
|
137
|
+
IonContent,
|
|
138
|
+
IonList,
|
|
139
|
+
IonLabel,
|
|
140
|
+
IonButtons,
|
|
141
|
+
IonButton,
|
|
142
|
+
IonIcon,
|
|
143
|
+
IonItem,
|
|
144
|
+
IonInput,
|
|
145
|
+
IonSelect,
|
|
146
|
+
IonSelectOption,
|
|
147
|
+
RadioGroupToSelectComponent,
|
|
148
|
+
IonHeader,
|
|
149
|
+
IonTitle,
|
|
150
|
+
IonToolbar,
|
|
151
|
+
IonFooter,
|
|
152
|
+
], providers: [{ provide: ClassName, useValue: 'HappeningPriceFormComponent' }], selector: 'sneat-happening-price-form', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar color=\"primary\">\n <ion-title>New price</ion-title>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-list lines=\"full\" class=\"ion-no-padding\">\n <ion-item>\n <ion-label color=\"medium\">\n <i>Choose term period and enter the price</i>\n </ion-label>\n </ion-item>\n @if (termUnit) {\n <ion-item>\n @if (termUnit !== \"single\") {\n <ion-input\n label=\"Per\"\n type=\"number\"\n style=\"text-align: right\"\n [formControl]=\"termLength\"\n (ionChange)=\"onTermLengthChange()\"\n />\n }\n <ion-select\n [label]=\"termUnit === 'single' ? 'Per' : undefined\"\n [(ngModel)]=\"termUnit\"\n interface=\"popover\"\n >\n @for (o of termPeriods; track o.value) {\n <ion-select-option [value]=\"o.value\"\n >{{ o.title }}\n </ion-select-option>\n }\n </ion-select>\n </ion-item>\n } @else {\n <sneat-radio-group-to-select\n label=\"Per\"\n [(ngModel)]=\"termUnit\"\n [selectOptions]=\"termPeriods\"\n />\n }\n <ion-item>\n <ion-input\n type=\"number\"\n [formControl]=\"priceValue\"\n label=\"Price\"\n style=\"text-align: right\"\n />\n <ion-select [formControl]=\"priceCurrency\">\n <ion-select-option value=\"EUR\">EUR</ion-select-option>\n <ion-select-option value=\"USD\">USD</ion-select-option>\n <ion-select-option value=\"RUB\">RUB</ion-select-option>\n </ion-select>\n </ion-item>\n </ion-list>\n</ion-content>\n<ion-footer>\n <ion-toolbar>\n @if (termUnit) {\n <ion-item lines=\"none\">\n @if (!priceValue.value) {\n <ion-label color=\"danger\"><i>Price amount is required</i></ion-label>\n }\n @if (!termLength.value && priceValue.value) {\n <ion-label color=\"danger\"><i>Term length is required</i></ion-label>\n }\n </ion-item>\n }\n <ion-buttons slot=\"end\">\n <ion-button\n slot=\"end\"\n fill=\"solid\"\n color=\"primary\"\n [disabled]=\"!priceValue.value || !termLength.value\"\n (click)=\"addPrice($event)\"\n >\n <ion-icon name=\"add-outline\" slot=\"start\" />\n <ion-label>Add price</ion-label>\n </ion-button>\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Cancel</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-footer>\n" }]
|
|
153
|
+
}], ctorParameters: () => [], propDecorators: { happening: [{
|
|
154
|
+
type: Input,
|
|
155
|
+
args: [{ required: true }]
|
|
156
|
+
}], happeningChange: [{
|
|
157
|
+
type: Output
|
|
158
|
+
}], canceled: [{
|
|
159
|
+
type: Output
|
|
160
|
+
}] } });
|
|
161
|
+
//# sourceMappingURL=happening-price-modal.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"happening-price-modal.component.js","sourceRoot":"","sources":["../../../../../../../../../../libs/extensions/schedulus/shared/src/lib/components/happening-form/happening-price-form/happening-price-modal.component.ts","../../../../../../../../../../libs/extensions/schedulus/shared/src/lib/components/happening-form/happening-price-form/happening-price-modal.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n EventEmitter,\n Input,\n Output,\n inject,\n} from '@angular/core';\nimport { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport {\n IonButton,\n IonButtons,\n IonContent,\n IonFooter,\n IonHeader,\n IonIcon,\n IonInput,\n IonItem,\n IonLabel,\n IonList,\n IonSelect,\n IonSelectOption,\n IonTitle,\n IonToolbar,\n} from '@ionic/angular/standalone';\nimport {\n CurrencyCode,\n IHappeningBrief,\n IHappeningContext,\n IHappeningPrice,\n TermUnit,\n} from '@sneat/mod-schedulus-core';\nimport { ClassName, SneatBaseModalComponent } from '@sneat/ui';\nimport {\n HappeningService,\n IHappeningPricesRequest,\n} from '../../../services/happening.service';\nimport { RadioGroupToSelectComponent, SelectOption } from '@sneat/wizard';\n\n@Component({\n imports: [\n ReactiveFormsModule,\n FormsModule,\n IonContent,\n IonList,\n IonLabel,\n IonButtons,\n IonButton,\n IonIcon,\n IonItem,\n IonInput,\n IonSelect,\n IonSelectOption,\n RadioGroupToSelectComponent,\n IonHeader,\n IonTitle,\n IonToolbar,\n IonFooter,\n ],\n providers: [{ provide: ClassName, useValue: 'HappeningPriceFormComponent' }],\n selector: 'sneat-happening-price-form',\n templateUrl: 'happening-price-modal.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class HappeningPriceModalComponent extends SneatBaseModalComponent {\n protected readonly changeDetectorRef = inject(ChangeDetectorRef);\n protected readonly happeningService = inject(HappeningService);\n\n @Input({ required: true }) happening?: IHappeningContext;\n\n @Output() happeningChange = new EventEmitter<IHappeningContext>();\n\n // @ViewChild('termLengthSelect', { static: false })\n // termLengthSelect?: IonSelect;\n\n @Output() readonly canceled = new EventEmitter<void>();\n\n protected isSubmitting = false;\n\n public constructor() {\n super();\n this.setTermLengths();\n }\n\n protected readonly priceValue = new FormControl<number | undefined>(\n undefined,\n );\n\n protected readonly priceCurrency = new FormControl<CurrencyCode | undefined>(\n 'EUR',\n );\n\n protected readonly termLength = new FormControl<number | undefined>(1);\n protected termUnit?: TermUnit;\n\n protected termPeriods: SelectOption[] = [];\n\n protected onTermLengthChange(): void {\n // console.log('onTermLengthChange', event);\n this.setTermLengths();\n this.forceSelectOptionsRefresh();\n }\n\n private forceSelectOptionsRefresh(): void {\n // For some reason, the select options are not refreshed when the ion-select-option changes.\n // this.termLengthSelect?.\n const temUnit = this.termUnit;\n this.termUnit = undefined;\n this.changeDetectorRef.detectChanges();\n this.termUnit = temUnit;\n this.changeDetectorRef.detectChanges();\n }\n\n private setTermLengths(): void {\n const isPlural = (this.termLength.value || 0) > 1;\n this.termPeriods = [\n { value: 'single', title: 'Single event' },\n { value: 'hour', title: isPlural ? 'Hours' : 'Hour' },\n { value: 'day', title: isPlural ? 'Days' : 'Day' },\n { value: 'week', title: 'Week' },\n { value: 'month', title: 'Month' },\n { value: 'year', title: 'Year' },\n ];\n }\n\n protected addPrice(event: Event): void {\n event.stopPropagation();\n event.preventDefault();\n\n const termLength: number = this.termLength.value || 0;\n if (!termLength) {\n this.errorLogger.logError('!termLength');\n return;\n }\n\n const amountValue = (this.priceValue.value || 0) * 100;\n const currency = this.priceCurrency.value || '';\n\n if (!this.termUnit) {\n this.errorLogger.logError('!termUnit');\n return;\n }\n\n const price: IHappeningPrice = {\n id: '',\n term: {\n unit: this.termUnit,\n length: termLength,\n },\n amount: {\n value: amountValue,\n currency,\n },\n };\n\n if (this.happening?.id && this.happening?.space?.id) {\n this.submitPrice(price);\n } else {\n this.addPriceToNewHappening(price);\n }\n }\n\n private addPriceToNewHappening(price: IHappeningPrice): void {\n price = { ...price, id: `${price.term.unit}${price.term.length}` };\n\n const pushPrice = <T extends IHappeningBrief>(h: T): T => {\n return { ...h, prices: [...(h.prices || []), price] };\n };\n if (this.happening?.brief) {\n this.happening = {\n ...this.happening,\n brief: pushPrice(this.happening.brief),\n };\n }\n if (this.happening?.dbo) {\n this.happening = {\n ...this.happening,\n dbo: pushPrice(this.happening.dbo),\n };\n }\n this.happeningChange.emit(this.happening);\n this.dismissModal(this.happening);\n }\n\n private submitPrice(price: IHappeningPrice): void {\n const happeningID = this.happening?.id || '';\n const spaceID = this.happening?.space?.id || '';\n if (!happeningID) {\n this.errorLogger.logError('!happeningID');\n return;\n }\n if (!spaceID) {\n this.errorLogger.logError('!spaceID');\n return;\n }\n\n const request: IHappeningPricesRequest = {\n spaceID: spaceID,\n happeningID,\n prices: [price],\n };\n\n this.isSubmitting = true;\n this.happeningService.setHappeningPrices(request).subscribe({\n error: this.errorLogger.logErrorHandler(\n 'failed to add price to a happening',\n ),\n complete: () => {\n this.isSubmitting = false;\n },\n next: () => {\n this.dismissModal();\n },\n });\n }\n}\n","<ion-header>\n <ion-toolbar color=\"primary\">\n <ion-title>New price</ion-title>\n <ion-buttons slot=\"end\">\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n<ion-content>\n <ion-list lines=\"full\" class=\"ion-no-padding\">\n <ion-item>\n <ion-label color=\"medium\">\n <i>Choose term period and enter the price</i>\n </ion-label>\n </ion-item>\n @if (termUnit) {\n <ion-item>\n @if (termUnit !== \"single\") {\n <ion-input\n label=\"Per\"\n type=\"number\"\n style=\"text-align: right\"\n [formControl]=\"termLength\"\n (ionChange)=\"onTermLengthChange()\"\n />\n }\n <ion-select\n [label]=\"termUnit === 'single' ? 'Per' : undefined\"\n [(ngModel)]=\"termUnit\"\n interface=\"popover\"\n >\n @for (o of termPeriods; track o.value) {\n <ion-select-option [value]=\"o.value\"\n >{{ o.title }}\n </ion-select-option>\n }\n </ion-select>\n </ion-item>\n } @else {\n <sneat-radio-group-to-select\n label=\"Per\"\n [(ngModel)]=\"termUnit\"\n [selectOptions]=\"termPeriods\"\n />\n }\n <ion-item>\n <ion-input\n type=\"number\"\n [formControl]=\"priceValue\"\n label=\"Price\"\n style=\"text-align: right\"\n />\n <ion-select [formControl]=\"priceCurrency\">\n <ion-select-option value=\"EUR\">EUR</ion-select-option>\n <ion-select-option value=\"USD\">USD</ion-select-option>\n <ion-select-option value=\"RUB\">RUB</ion-select-option>\n </ion-select>\n </ion-item>\n </ion-list>\n</ion-content>\n<ion-footer>\n <ion-toolbar>\n @if (termUnit) {\n <ion-item lines=\"none\">\n @if (!priceValue.value) {\n <ion-label color=\"danger\"><i>Price amount is required</i></ion-label>\n }\n @if (!termLength.value && priceValue.value) {\n <ion-label color=\"danger\"><i>Term length is required</i></ion-label>\n }\n </ion-item>\n }\n <ion-buttons slot=\"end\">\n <ion-button\n slot=\"end\"\n fill=\"solid\"\n color=\"primary\"\n [disabled]=\"!priceValue.value || !termLength.value\"\n (click)=\"addPrice($event)\"\n >\n <ion-icon name=\"add-outline\" slot=\"start\" />\n <ion-label>Add price</ion-label>\n </ion-button>\n <ion-button (click)=\"close()\">\n <ion-icon name=\"close-outline\" slot=\"start\" />\n <ion-label>Cancel</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-footer>\n"]}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { CurrencyPipe } from '@angular/common';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, signal, inject, } from '@angular/core';
|
|
3
|
+
import { IonButton, IonButtons, IonCard, IonCheckbox, IonIcon, IonItem, IonItemDivider, IonLabel, IonSpinner, ModalController, } from '@ionic/angular/standalone';
|
|
4
|
+
import { Decimal64p2Pipe } from '@sneat/components';
|
|
5
|
+
import { ErrorLogger } from '@sneat/core';
|
|
6
|
+
import { HappeningService, } from '../../../services/happening.service';
|
|
7
|
+
import { HappeningPriceModalComponent } from '../happening-price-form/happening-price-modal.component';
|
|
8
|
+
import * as i0 from "@angular/core";
|
|
9
|
+
export class HappeningPricesComponent {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.errorLogger = inject(ErrorLogger);
|
|
12
|
+
this.modalCtrl = inject(ModalController);
|
|
13
|
+
this.happeningService = inject(HappeningService);
|
|
14
|
+
this.happeningChange = new EventEmitter();
|
|
15
|
+
this.updatingPriceIDs = signal([], ...(ngDevMode ? [{ debugName: "updatingPriceIDs" }] : []));
|
|
16
|
+
}
|
|
17
|
+
openNewPriceForm() {
|
|
18
|
+
this.modalCtrl
|
|
19
|
+
.create({
|
|
20
|
+
component: HappeningPriceModalComponent,
|
|
21
|
+
componentProps: {
|
|
22
|
+
happening: this.happening,
|
|
23
|
+
happeningChange: new EventEmitter(),
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
.then((modal) => {
|
|
27
|
+
modal
|
|
28
|
+
.present()
|
|
29
|
+
.then(() => {
|
|
30
|
+
const modalHappeningChange = modal?.componentProps?.['happeningChange'];
|
|
31
|
+
modalHappeningChange.subscribe({
|
|
32
|
+
next: (happening) => {
|
|
33
|
+
this.happeningChange.emit(happening);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
})
|
|
37
|
+
.catch(this.errorLogger.logErrorHandler('Failed to present modal of new price form'));
|
|
38
|
+
})
|
|
39
|
+
.catch(this.errorLogger.logErrorHandler('Failed to create modal of new price form'));
|
|
40
|
+
}
|
|
41
|
+
deletePrice(price) {
|
|
42
|
+
if (!confirm('Are you sure you want delete this price?')) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const happeningID = this.happening?.id, spaceID = this.happening?.space?.id;
|
|
46
|
+
if (!happeningID) {
|
|
47
|
+
const removePrice = (h) => ({
|
|
48
|
+
...h,
|
|
49
|
+
prices: h.prices?.filter((p) => p.id !== price.id),
|
|
50
|
+
});
|
|
51
|
+
let happening = this.happening;
|
|
52
|
+
if (happening?.brief) {
|
|
53
|
+
happening = { ...happening, brief: removePrice(happening.brief) };
|
|
54
|
+
}
|
|
55
|
+
if (happening?.dbo) {
|
|
56
|
+
happening = { ...happening, dbo: removePrice(happening.dbo) };
|
|
57
|
+
}
|
|
58
|
+
this.happeningChange.emit(happening);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (!spaceID) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.updatingPriceIDs.set([...this.updatingPriceIDs(), price.id]);
|
|
65
|
+
this.happeningService
|
|
66
|
+
.deleteHappeningPrices({
|
|
67
|
+
spaceID: spaceID,
|
|
68
|
+
happeningID,
|
|
69
|
+
priceIDs: [price.id],
|
|
70
|
+
})
|
|
71
|
+
.subscribe({
|
|
72
|
+
error: this.errorLogger.logErrorHandler(`Failed to delete happening price with ID=${price.id}`),
|
|
73
|
+
complete: () => {
|
|
74
|
+
this.updatingPriceIDs.set(this.updatingPriceIDs().filter((id) => id !== price.id));
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
priceChecked(price, event) {
|
|
79
|
+
event.stopPropagation();
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
if (!this.happening) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const isChecked = !!event.detail.checked;
|
|
85
|
+
const expenseQuantity = isChecked ? 1 : 0;
|
|
86
|
+
if (!this.happening?.id) {
|
|
87
|
+
const setPrices = (h) => ({
|
|
88
|
+
...h,
|
|
89
|
+
prices: h.prices?.map((p) => p.id === price.id ? { ...p, expenseQuantity } : p),
|
|
90
|
+
});
|
|
91
|
+
if (this.happening?.brief) {
|
|
92
|
+
this.happening = {
|
|
93
|
+
...this.happening,
|
|
94
|
+
brief: setPrices(this.happening.brief),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (this.happening?.dbo) {
|
|
98
|
+
this.happening = {
|
|
99
|
+
...this.happening,
|
|
100
|
+
dbo: setPrices(this.happening.dbo),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
this.happeningChange.emit(this.happening);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.updatingPriceIDs.set([...this.updatingPriceIDs(), price.id]);
|
|
107
|
+
const request = {
|
|
108
|
+
spaceID: this.happening?.space?.id || '',
|
|
109
|
+
happeningID: this.happening?.id || '',
|
|
110
|
+
prices: [{ ...price, expenseQuantity }],
|
|
111
|
+
};
|
|
112
|
+
this.happeningService.setHappeningPrices(request).subscribe({
|
|
113
|
+
complete: () => {
|
|
114
|
+
this.updatingPriceIDs.set(this.updatingPriceIDs().filter((id) => id !== price.id));
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: HappeningPricesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
119
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: HappeningPricesComponent, isStandalone: true, selector: "sneat-happening-pricing", inputs: { happening: "happening" }, outputs: { happeningChange: "happeningChange" }, ngImport: i0, template: "<ion-card>\n <ion-item-divider color=\"light\" class=\"sneat-tiny-end-padding\">\n <ion-label>Pricing</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"primary\" (click)=\"openNewPriceForm()\">\n <ion-icon name=\"add\" slot=\"start\" />\n <ion-label>Add price</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n @if (!happening?.dbo) {\n <ion-item>\n <ion-spinner slot=\"start\" name=\"lines-small\" />\n <ion-label>Loading...</ion-label>\n </ion-item>\n } @else {\n @for (\n price of happening?.dbo?.prices || happening?.brief?.prices || [];\n track price.id\n ) {\n <ion-item class=\"sneat-no-end-padding-margin\">\n <ion-checkbox\n justify=\"start\"\n labelPlacement=\"end\"\n [value]=\"price.id\"\n [checked]=\"!!price.expenseQuantity\"\n [disabled]=\"updatingPriceIDs().includes(price.id)\"\n (ionChange)=\"priceChecked(price, $event)\"\n >\n <b>{{\n price.amount.value | decimal64p2 | currency: price.amount.currency\n }}</b>\n for {{ price.term.length }} {{ price.term.unit }}\n </ion-checkbox>\n @if (!updatingPriceIDs().includes(price.id)) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\" (click)=\"deletePrice(price)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n } @empty {\n <ion-item>\n <ion-label color=\"medium\"\n ><i>No pricing information available</i></ion-label\n >\n </ion-item>\n }\n }\n <ion-item>\n <ion-label color=\"medium\"\n ><i\n >Check price above to add it as expense to budget calculation.</i\n ></ion-label\n >\n </ion-item>\n</ion-card>\n", dependencies: [{ kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonItemDivider, selector: "ion-item-divider", inputs: ["color", "mode", "sticky"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { 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: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { 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: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "pipe", type: Decimal64p2Pipe, name: "decimal64p2" }, { kind: "pipe", type: CurrencyPipe, name: "currency" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
120
|
+
}
|
|
121
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: HappeningPricesComponent, decorators: [{
|
|
122
|
+
type: Component,
|
|
123
|
+
args: [{ selector: 'sneat-happening-pricing', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
124
|
+
Decimal64p2Pipe,
|
|
125
|
+
IonCard,
|
|
126
|
+
IonItemDivider,
|
|
127
|
+
IonLabel,
|
|
128
|
+
IonButtons,
|
|
129
|
+
IonButton,
|
|
130
|
+
IonIcon,
|
|
131
|
+
IonItem,
|
|
132
|
+
IonSpinner,
|
|
133
|
+
IonCheckbox,
|
|
134
|
+
CurrencyPipe,
|
|
135
|
+
], template: "<ion-card>\n <ion-item-divider color=\"light\" class=\"sneat-tiny-end-padding\">\n <ion-label>Pricing</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"primary\" (click)=\"openNewPriceForm()\">\n <ion-icon name=\"add\" slot=\"start\" />\n <ion-label>Add price</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n @if (!happening?.dbo) {\n <ion-item>\n <ion-spinner slot=\"start\" name=\"lines-small\" />\n <ion-label>Loading...</ion-label>\n </ion-item>\n } @else {\n @for (\n price of happening?.dbo?.prices || happening?.brief?.prices || [];\n track price.id\n ) {\n <ion-item class=\"sneat-no-end-padding-margin\">\n <ion-checkbox\n justify=\"start\"\n labelPlacement=\"end\"\n [value]=\"price.id\"\n [checked]=\"!!price.expenseQuantity\"\n [disabled]=\"updatingPriceIDs().includes(price.id)\"\n (ionChange)=\"priceChecked(price, $event)\"\n >\n <b>{{\n price.amount.value | decimal64p2 | currency: price.amount.currency\n }}</b>\n for {{ price.term.length }} {{ price.term.unit }}\n </ion-checkbox>\n @if (!updatingPriceIDs().includes(price.id)) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\" (click)=\"deletePrice(price)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n } @empty {\n <ion-item>\n <ion-label color=\"medium\"\n ><i>No pricing information available</i></ion-label\n >\n </ion-item>\n }\n }\n <ion-item>\n <ion-label color=\"medium\"\n ><i\n >Check price above to add it as expense to budget calculation.</i\n ></ion-label\n >\n </ion-item>\n</ion-card>\n" }]
|
|
136
|
+
}], propDecorators: { happening: [{
|
|
137
|
+
type: Input,
|
|
138
|
+
args: [{ required: true }]
|
|
139
|
+
}], happeningChange: [{
|
|
140
|
+
type: Output
|
|
141
|
+
}] } });
|
|
142
|
+
//# sourceMappingURL=happening-prices.component.js.map
|
package/esm2022/lib/components/happening-form/happening-prices/happening-prices.component.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"happening-prices.component.js","sourceRoot":"","sources":["../../../../../../../../../../libs/extensions/schedulus/shared/src/lib/components/happening-form/happening-prices/happening-prices.component.ts","../../../../../../../../../../libs/extensions/schedulus/shared/src/lib/components/happening-form/happening-prices/happening-prices.component.html"],"names":[],"mappings":"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","sourcesContent":["import { CurrencyPipe } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n EventEmitter,\n Input,\n Output,\n signal,\n inject,\n} from '@angular/core';\nimport {\n IonButton,\n IonButtons,\n IonCard,\n IonCheckbox,\n IonIcon,\n IonItem,\n IonItemDivider,\n IonLabel,\n IonSpinner,\n ModalController,\n} from '@ionic/angular/standalone';\nimport { Decimal64p2Pipe } from '@sneat/components';\nimport { ErrorLogger, IErrorLogger } from '@sneat/core';\nimport {\n IHappeningBrief,\n IHappeningContext,\n IHappeningPrice,\n} from '@sneat/mod-schedulus-core';\nimport {\n HappeningService,\n IHappeningPricesRequest,\n} from '../../../services/happening.service';\nimport { HappeningPriceModalComponent } from '../happening-price-form/happening-price-modal.component';\n\n@Component({\n selector: 'sneat-happening-pricing',\n templateUrl: 'happening-prices.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n Decimal64p2Pipe,\n IonCard,\n IonItemDivider,\n IonLabel,\n IonButtons,\n IonButton,\n IonIcon,\n IonItem,\n IonSpinner,\n IonCheckbox,\n CurrencyPipe,\n ],\n})\nexport class HappeningPricesComponent {\n private readonly errorLogger = inject<IErrorLogger>(ErrorLogger);\n private readonly modalCtrl = inject(ModalController);\n private readonly happeningService = inject(HappeningService);\n\n @Input({ required: true }) happening?: IHappeningContext;\n @Output() readonly happeningChange = new EventEmitter<IHappeningContext>();\n\n protected openNewPriceForm(): void {\n this.modalCtrl\n .create({\n component: HappeningPriceModalComponent,\n componentProps: {\n happening: this.happening,\n happeningChange: new EventEmitter<IHappeningContext>(),\n },\n })\n .then((modal) => {\n modal\n .present()\n .then(() => {\n const modalHappeningChange = modal?.componentProps?.[\n 'happeningChange'\n ] as EventEmitter<IHappeningContext>;\n modalHappeningChange.subscribe({\n next: (happening: IHappeningContext) => {\n this.happeningChange.emit(happening);\n },\n });\n })\n .catch(\n this.errorLogger.logErrorHandler(\n 'Failed to present modal of new price form',\n ),\n );\n })\n .catch(\n this.errorLogger.logErrorHandler(\n 'Failed to create modal of new price form',\n ),\n );\n }\n\n protected deletePrice(price: IHappeningPrice): void {\n if (!confirm('Are you sure you want delete this price?')) {\n return;\n }\n\n const happeningID = this.happening?.id,\n spaceID = this.happening?.space?.id;\n\n if (!happeningID) {\n const removePrice = <T extends IHappeningBrief>(h: T) => ({\n ...h,\n prices: h.prices?.filter((p) => p.id !== price.id),\n });\n let happening = this.happening;\n if (happening?.brief) {\n happening = { ...happening, brief: removePrice(happening.brief) };\n }\n if (happening?.dbo) {\n happening = { ...happening, dbo: removePrice(happening.dbo) };\n }\n this.happeningChange.emit(happening);\n return;\n }\n\n if (!spaceID) {\n return;\n }\n\n this.updatingPriceIDs.set([...this.updatingPriceIDs(), price.id]);\n\n this.happeningService\n .deleteHappeningPrices({\n spaceID: spaceID,\n happeningID,\n priceIDs: [price.id],\n })\n .subscribe({\n error: this.errorLogger.logErrorHandler(\n `Failed to delete happening price with ID=${price.id}`,\n ),\n complete: () => {\n this.updatingPriceIDs.set(\n this.updatingPriceIDs().filter((id) => id !== price.id),\n );\n },\n });\n }\n\n protected updatingPriceIDs = signal<readonly string[]>([]);\n\n protected priceChecked(price: IHappeningPrice, event: Event): void {\n event.stopPropagation();\n event.preventDefault();\n\n if (!this.happening) {\n return;\n }\n\n const isChecked = !!(event as CustomEvent).detail.checked;\n const expenseQuantity = isChecked ? 1 : 0;\n\n if (!this.happening?.id) {\n const setPrices = <T extends IHappeningBrief>(h: T): T => ({\n ...h,\n prices: h.prices?.map((p) =>\n p.id === price.id ? { ...p, expenseQuantity } : p,\n ),\n });\n\n if (this.happening?.brief) {\n this.happening = {\n ...this.happening,\n brief: setPrices(this.happening.brief),\n };\n }\n if (this.happening?.dbo) {\n this.happening = {\n ...this.happening,\n dbo: setPrices(this.happening.dbo),\n };\n }\n this.happeningChange.emit(this.happening);\n return;\n }\n\n this.updatingPriceIDs.set([...this.updatingPriceIDs(), price.id]);\n\n const request: IHappeningPricesRequest = {\n spaceID: this.happening?.space?.id || '',\n happeningID: this.happening?.id || '',\n prices: [{ ...price, expenseQuantity }],\n };\n this.happeningService.setHappeningPrices(request).subscribe({\n complete: () => {\n this.updatingPriceIDs.set(\n this.updatingPriceIDs().filter((id) => id !== price.id),\n );\n },\n });\n }\n}\n","<ion-card>\n <ion-item-divider color=\"light\" class=\"sneat-tiny-end-padding\">\n <ion-label>Pricing</ion-label>\n <ion-buttons slot=\"end\">\n <ion-button color=\"primary\" (click)=\"openNewPriceForm()\">\n <ion-icon name=\"add\" slot=\"start\" />\n <ion-label>Add price</ion-label>\n </ion-button>\n </ion-buttons>\n </ion-item-divider>\n @if (!happening?.dbo) {\n <ion-item>\n <ion-spinner slot=\"start\" name=\"lines-small\" />\n <ion-label>Loading...</ion-label>\n </ion-item>\n } @else {\n @for (\n price of happening?.dbo?.prices || happening?.brief?.prices || [];\n track price.id\n ) {\n <ion-item class=\"sneat-no-end-padding-margin\">\n <ion-checkbox\n justify=\"start\"\n labelPlacement=\"end\"\n [value]=\"price.id\"\n [checked]=\"!!price.expenseQuantity\"\n [disabled]=\"updatingPriceIDs().includes(price.id)\"\n (ionChange)=\"priceChecked(price, $event)\"\n >\n <b>{{\n price.amount.value | decimal64p2 | currency: price.amount.currency\n }}</b>\n for {{ price.term.length }} {{ price.term.unit }}\n </ion-checkbox>\n @if (!updatingPriceIDs().includes(price.id)) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"medium\" (click)=\"deletePrice(price)\">\n <ion-icon name=\"close-outline\" />\n </ion-button>\n </ion-buttons>\n }\n </ion-item>\n } @empty {\n <ion-item>\n <ion-label color=\"medium\"\n ><i>No pricing information available</i></ion-label\n >\n </ion-item>\n }\n }\n <ion-item>\n <ion-label color=\"medium\"\n ><i\n >Check price above to add it as expense to budget calculation.</i\n ></ion-label\n >\n </ion-item>\n</ion-card>\n"]}
|