@propbinder/mobile-design 0.2.74 → 0.2.79

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.
@@ -5,7 +5,7 @@ import { CommonModule, isPlatformBrowser } from '@angular/common';
5
5
  import * as i1$3 from '@angular/router';
6
6
  import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
7
7
  import * as i1 from '@ionic/angular/standalone';
8
- import { ModalController, IonHeader, IonToolbar, IonTitle, IonButtons, IonContent, Platform, IonRefresher, IonRefresherContent, IonPopover, AlertController, IonSpinner, IonTabBar, IonTabButton, IonLabel, IonTabs, IonTab, IonPicker, IonPickerColumn, IonPickerColumnOption, IonInfiniteScroll, IonInfiniteScrollContent } from '@ionic/angular/standalone';
8
+ import { ModalController, IonHeader, IonToolbar, IonTitle, IonButtons, IonContent, Platform, IonRefresher, IonRefresherContent, IonPopover, AlertController, IonSpinner, IonTabBar, IonTabButton, IonLabel, IonTabs, IonTab, IonPicker, IonPickerColumn, IonPickerColumnOption, IonInfiniteScroll, IonInfiniteScrollContent, NavController } from '@ionic/angular/standalone';
9
9
  import { ImpactStyle, Haptics } from '@capacitor/haptics';
10
10
  import { DsIconButtonComponent, DsIconComponent, DsButtonComponent, DsAvatarComponent, DsShapeIndicatorComponent, DsTextareaComponent, DsDatepickerComponent, DsCheckboxComponent, DsInputTimeComponent, DsLabelComponent, DsBadgeComponent } from '@propbinder/design-system';
11
11
  import { StatusBar, Style } from '@capacitor/status-bar';
@@ -12268,6 +12268,325 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
12268
12268
  type: Input
12269
12269
  }] } });
12270
12270
 
12271
+ const DEFAULT_COMMUNITY_ADMIN_LABELS = {
12272
+ pageTitle: 'Fællesskabsadministrator',
12273
+ closeButton: 'Luk',
12274
+ addButtonAriaLabel: 'Tilføj administrator',
12275
+ emptyState: 'Ingen administratorer endnu',
12276
+ emptyStateDescription: 'Tilføj beboere som administratorer, så de kan hjælpe med at administrere fællesskabet.',
12277
+ removeConfirmTitle: 'Fjern administrator?',
12278
+ removeConfirmMessage: (name) => `${name} fjernes som administrator.`,
12279
+ removeConfirmButton: 'Fjern',
12280
+ cancelButton: 'Annuller',
12281
+ addPickerTitle: 'Tilføj administrator',
12282
+ addPickerSearchPlaceholder: 'Søg efter beboer',
12283
+ addPickerSearchAriaLabel: 'Søg efter beboer',
12284
+ addPickerEmpty: 'Ingen beboere fundet',
12285
+ onboardingTitle: 'Du er nu fællesskabsadministrator',
12286
+ onboardingMessage: 'Du kan nu oprette bookbare faciliteter i fællesskabet, samt fastgøre eller slette opslag i dit ejendomsfællesskab.',
12287
+ onboardingButton: 'Forstået',
12288
+ };
12289
+ /**
12290
+ * Full-screen modal for managing community administrators.
12291
+ *
12292
+ * The main view lists current admins with a "more" menu to remove them.
12293
+ * Tapping the "+" header button opens a stacked picker modal to add new admins
12294
+ * from the available tenants list.
12295
+ */
12296
+ class DsMobileCommunityAdminsModalComponent {
12297
+ modalCtrl = inject(ModalController);
12298
+ bottomSheet = inject(DsMobileBottomSheetService);
12299
+ getAdminsSnapshot;
12300
+ availableTenants = [];
12301
+ currentUserId = '';
12302
+ onAddAdmin;
12303
+ onRemoveAdmin;
12304
+ labels;
12305
+ lbl;
12306
+ localAdmins = [];
12307
+ get showAddButton() {
12308
+ return !!this.onAddAdmin && this.availableTenants.length > 0;
12309
+ }
12310
+ ngOnInit() {
12311
+ this.lbl = { ...DEFAULT_COMMUNITY_ADMIN_LABELS, ...this.labels };
12312
+ this.syncAdmins();
12313
+ }
12314
+ syncAdmins() {
12315
+ this.localAdmins = [...(this.getAdminsSnapshot?.() ?? [])];
12316
+ }
12317
+ async confirmRemoveAdmin(admin) {
12318
+ if (!this.onRemoveAdmin || admin.id === this.currentUserId)
12319
+ return;
12320
+ const confirm = await this.bottomSheet.create({
12321
+ component: DsMobileConfirmationSheetComponent,
12322
+ componentProps: {
12323
+ title: this.lbl.removeConfirmMessage(admin.name),
12324
+ buttonText: this.lbl.removeConfirmButton,
12325
+ destructive: true,
12326
+ showIllustration: false,
12327
+ showCancelButton: true,
12328
+ },
12329
+ breakpoints: [0, 1],
12330
+ initialBreakpoint: 1,
12331
+ handle: true,
12332
+ cssClass: 'auto-height',
12333
+ });
12334
+ const result = await confirm.onWillDismiss();
12335
+ if (result.role !== 'confirm')
12336
+ return;
12337
+ await Promise.resolve(this.onRemoveAdmin(admin.id));
12338
+ this.syncAdmins();
12339
+ }
12340
+ async openAddAdminPicker() {
12341
+ if (!this.onAddAdmin)
12342
+ return;
12343
+ const currentAdminIds = new Set(this.localAdmins.map(a => a.id));
12344
+ const pickable = this.availableTenants.filter(t => !currentAdminIds.has(t.id));
12345
+ if (pickable.length === 0)
12346
+ return;
12347
+ const picker = await this.modalCtrl.create({
12348
+ component: DsMobileCommunityAdminPickerComponent,
12349
+ componentProps: {
12350
+ tenants: pickable,
12351
+ labels: this.lbl,
12352
+ },
12353
+ cssClass: 'ds-modal-base',
12354
+ mode: 'ios',
12355
+ presentingElement: document.querySelector('ion-router-outlet') || undefined,
12356
+ backdropDismiss: true,
12357
+ showBackdrop: true,
12358
+ animated: true,
12359
+ });
12360
+ await picker.present();
12361
+ const { data, role } = await picker.onWillDismiss();
12362
+ if (role === 'selected' && data?.tenantId) {
12363
+ await Promise.resolve(this.onAddAdmin(data.tenantId));
12364
+ this.syncAdmins();
12365
+ }
12366
+ }
12367
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileCommunityAdminsModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12368
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileCommunityAdminsModalComponent, isStandalone: true, selector: "ds-mobile-community-admins-modal", inputs: { getAdminsSnapshot: "getAdminsSnapshot", availableTenants: "availableTenants", currentUserId: "currentUserId", onAddAdmin: "onAddAdmin", onRemoveAdmin: "onRemoveAdmin", labels: "labels" }, ngImport: i0, template: `
12369
+ <ds-mobile-modal-base
12370
+ [headerTitle]="lbl.pageTitle"
12371
+ [closeButtonLabel]="lbl.closeButton"
12372
+ contentPadding="0"
12373
+ [hasFixedBottom]="false"
12374
+ >
12375
+ @if (showAddButton) {
12376
+ <div header-trailing>
12377
+ <ds-icon-button
12378
+ icon="remixAddLine"
12379
+ variant="secondary"
12380
+ size="md"
12381
+ (clicked)="openAddAdminPicker()"
12382
+ [attr.aria-label]="lbl.addButtonAriaLabel"
12383
+ />
12384
+ </div>
12385
+ }
12386
+
12387
+ <ds-mobile-section contentGap="0px" padding="12px 20px 20px 20px" [showBorder]="false">
12388
+ @if (localAdmins.length > 0) {
12389
+ @for (admin of localAdmins; track admin.id) {
12390
+ <ds-mobile-contact-list-item
12391
+ [name]="admin.name"
12392
+ [initials]="admin.avatarInitials || ''"
12393
+ [contactPerson]="admin.unit || ''"
12394
+ [avatarSrc]="admin.avatarSrc || ''"
12395
+ [avatarType]="admin.avatarType || 'initials'"
12396
+ [clickable]="false"
12397
+ [showChevron]="false"
12398
+ [showDeleteAction]="admin.id !== currentUserId"
12399
+ (deleteClick)="confirmRemoveAdmin(admin)"
12400
+ />
12401
+ }
12402
+ } @else {
12403
+ <p class="empty-state">{{ lbl.emptyState }}</p>
12404
+ }
12405
+ </ds-mobile-section>
12406
+ </ds-mobile-modal-base>
12407
+ `, isInline: true, styles: [".empty-state{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-tertiary);text-align:center;padding:24px 16px;margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["headerTitleInteractive", "showHeader"], outputs: ["titleClick"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileContactListItemComponent, selector: "ds-mobile-contact-list-item", inputs: ["name", "nameSuffix", "initials", "avatarSrc", "avatarType", "avatarIconName", "showBadge", "contactPerson", "phoneNumber", "clickable", "showChevron", "showMoreMenu", "moreMenuAriaLabel", "selectionMode", "selected", "showDeleteAction", "variant", "align"], outputs: ["contactClick", "selectionToggle", "moreClick", "deleteClick"] }] });
12408
+ }
12409
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileCommunityAdminsModalComponent, decorators: [{
12410
+ type: Component,
12411
+ args: [{ selector: 'ds-mobile-community-admins-modal', standalone: true, imports: [
12412
+ CommonModule,
12413
+ DsMobileModalBaseComponent,
12414
+ DsIconButtonComponent,
12415
+ DsMobileSectionComponent,
12416
+ DsMobileContactListItemComponent,
12417
+ ], template: `
12418
+ <ds-mobile-modal-base
12419
+ [headerTitle]="lbl.pageTitle"
12420
+ [closeButtonLabel]="lbl.closeButton"
12421
+ contentPadding="0"
12422
+ [hasFixedBottom]="false"
12423
+ >
12424
+ @if (showAddButton) {
12425
+ <div header-trailing>
12426
+ <ds-icon-button
12427
+ icon="remixAddLine"
12428
+ variant="secondary"
12429
+ size="md"
12430
+ (clicked)="openAddAdminPicker()"
12431
+ [attr.aria-label]="lbl.addButtonAriaLabel"
12432
+ />
12433
+ </div>
12434
+ }
12435
+
12436
+ <ds-mobile-section contentGap="0px" padding="12px 20px 20px 20px" [showBorder]="false">
12437
+ @if (localAdmins.length > 0) {
12438
+ @for (admin of localAdmins; track admin.id) {
12439
+ <ds-mobile-contact-list-item
12440
+ [name]="admin.name"
12441
+ [initials]="admin.avatarInitials || ''"
12442
+ [contactPerson]="admin.unit || ''"
12443
+ [avatarSrc]="admin.avatarSrc || ''"
12444
+ [avatarType]="admin.avatarType || 'initials'"
12445
+ [clickable]="false"
12446
+ [showChevron]="false"
12447
+ [showDeleteAction]="admin.id !== currentUserId"
12448
+ (deleteClick)="confirmRemoveAdmin(admin)"
12449
+ />
12450
+ }
12451
+ } @else {
12452
+ <p class="empty-state">{{ lbl.emptyState }}</p>
12453
+ }
12454
+ </ds-mobile-section>
12455
+ </ds-mobile-modal-base>
12456
+ `, styles: [".empty-state{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-tertiary);text-align:center;padding:24px 16px;margin:0}\n"] }]
12457
+ }], propDecorators: { getAdminsSnapshot: [{
12458
+ type: Input,
12459
+ args: [{ required: true }]
12460
+ }], availableTenants: [{
12461
+ type: Input
12462
+ }], currentUserId: [{
12463
+ type: Input
12464
+ }], onAddAdmin: [{
12465
+ type: Input
12466
+ }], onRemoveAdmin: [{
12467
+ type: Input
12468
+ }], labels: [{
12469
+ type: Input
12470
+ }] } });
12471
+ /**
12472
+ * Internal stacked picker for selecting a single tenant to promote to admin.
12473
+ */
12474
+ class DsMobileCommunityAdminPickerComponent {
12475
+ modalCtrl = inject(ModalController);
12476
+ tenants = [];
12477
+ labels;
12478
+ lbl;
12479
+ searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
12480
+ tenantsSig = signal([], ...(ngDevMode ? [{ debugName: "tenantsSig" }] : []));
12481
+ ngOnInit() {
12482
+ this.lbl = this.labels ?? DEFAULT_COMMUNITY_ADMIN_LABELS;
12483
+ this.tenantsSig.set(this.tenants ?? []);
12484
+ }
12485
+ filteredTenants = computed(() => {
12486
+ const q = this.searchQuery().toLowerCase().trim();
12487
+ const list = this.tenantsSig();
12488
+ if (!q)
12489
+ return list;
12490
+ return list.filter(t => t.name.toLowerCase().includes(q) ||
12491
+ (t.unit ?? '').toLowerCase().includes(q));
12492
+ }, ...(ngDevMode ? [{ debugName: "filteredTenants" }] : []));
12493
+ selectTenant(tenant) {
12494
+ void this.modalCtrl.dismiss({ tenantId: tenant.id }, 'selected');
12495
+ }
12496
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileCommunityAdminPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12497
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileCommunityAdminPickerComponent, isStandalone: true, selector: "ds-mobile-community-admin-picker", inputs: { tenants: "tenants", labels: "labels" }, ngImport: i0, template: `
12498
+ <ds-mobile-modal-base
12499
+ [headerTitle]="lbl.addPickerTitle"
12500
+ [closeButtonLabel]="lbl.closeButton"
12501
+ [hasFixedBottom]="false"
12502
+ [enableKeyboardHandling]="true"
12503
+ contentPadding="0"
12504
+ >
12505
+ <div header-below>
12506
+ <ds-mobile-list-search
12507
+ [placeholder]="lbl.addPickerSearchPlaceholder"
12508
+ [ariaLabel]="lbl.addPickerSearchAriaLabel"
12509
+ [showDivider]="false"
12510
+ [value]="searchQuery()"
12511
+ (valueChange)="searchQuery.set($event)"
12512
+ />
12513
+ </div>
12514
+
12515
+ <ds-mobile-section contentGap="0px" padding="12px 20px 20px 20px" [showBorder]="false">
12516
+ @if (filteredTenants().length > 0) {
12517
+ @for (t of filteredTenants(); track t.id) {
12518
+ <ds-mobile-contact-list-item
12519
+ [name]="t.name"
12520
+ [initials]="t.avatarInitials || ''"
12521
+ [contactPerson]="t.unit || ''"
12522
+ [avatarSrc]="t.avatarSrc || ''"
12523
+ [avatarType]="t.avatarType || 'initials'"
12524
+ [clickable]="true"
12525
+ [showMoreMenu]="false"
12526
+ [showChevron]="false"
12527
+ (contactClick)="selectTenant(t)"
12528
+ />
12529
+ }
12530
+ } @else {
12531
+ <p class="search-empty">{{ lbl.addPickerEmpty }}</p>
12532
+ }
12533
+ </ds-mobile-section>
12534
+ </ds-mobile-modal-base>
12535
+ `, isInline: true, styles: [".search-empty{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-tertiary);text-align:center;padding:24px 16px;margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["headerTitleInteractive", "showHeader"], outputs: ["titleClick"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileListSearchComponent, selector: "ds-mobile-list-search", inputs: ["placeholder", "ariaLabel", "value", "showDivider"], outputs: ["valueChange"] }, { kind: "component", type: DsMobileContactListItemComponent, selector: "ds-mobile-contact-list-item", inputs: ["name", "nameSuffix", "initials", "avatarSrc", "avatarType", "avatarIconName", "showBadge", "contactPerson", "phoneNumber", "clickable", "showChevron", "showMoreMenu", "moreMenuAriaLabel", "selectionMode", "selected", "showDeleteAction", "variant", "align"], outputs: ["contactClick", "selectionToggle", "moreClick", "deleteClick"] }] });
12536
+ }
12537
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileCommunityAdminPickerComponent, decorators: [{
12538
+ type: Component,
12539
+ args: [{ selector: 'ds-mobile-community-admin-picker', standalone: true, imports: [
12540
+ CommonModule,
12541
+ DsMobileModalBaseComponent,
12542
+ DsMobileSectionComponent,
12543
+ DsMobileListSearchComponent,
12544
+ DsMobileContactListItemComponent,
12545
+ ], template: `
12546
+ <ds-mobile-modal-base
12547
+ [headerTitle]="lbl.addPickerTitle"
12548
+ [closeButtonLabel]="lbl.closeButton"
12549
+ [hasFixedBottom]="false"
12550
+ [enableKeyboardHandling]="true"
12551
+ contentPadding="0"
12552
+ >
12553
+ <div header-below>
12554
+ <ds-mobile-list-search
12555
+ [placeholder]="lbl.addPickerSearchPlaceholder"
12556
+ [ariaLabel]="lbl.addPickerSearchAriaLabel"
12557
+ [showDivider]="false"
12558
+ [value]="searchQuery()"
12559
+ (valueChange)="searchQuery.set($event)"
12560
+ />
12561
+ </div>
12562
+
12563
+ <ds-mobile-section contentGap="0px" padding="12px 20px 20px 20px" [showBorder]="false">
12564
+ @if (filteredTenants().length > 0) {
12565
+ @for (t of filteredTenants(); track t.id) {
12566
+ <ds-mobile-contact-list-item
12567
+ [name]="t.name"
12568
+ [initials]="t.avatarInitials || ''"
12569
+ [contactPerson]="t.unit || ''"
12570
+ [avatarSrc]="t.avatarSrc || ''"
12571
+ [avatarType]="t.avatarType || 'initials'"
12572
+ [clickable]="true"
12573
+ [showMoreMenu]="false"
12574
+ [showChevron]="false"
12575
+ (contactClick)="selectTenant(t)"
12576
+ />
12577
+ }
12578
+ } @else {
12579
+ <p class="search-empty">{{ lbl.addPickerEmpty }}</p>
12580
+ }
12581
+ </ds-mobile-section>
12582
+ </ds-mobile-modal-base>
12583
+ `, styles: [".search-empty{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-tertiary);text-align:center;padding:24px 16px;margin:0}\n"] }]
12584
+ }], propDecorators: { tenants: [{
12585
+ type: Input
12586
+ }], labels: [{
12587
+ type: Input
12588
+ }] } });
12589
+
12271
12590
  function isPeerDirectConversation(c) {
12272
12591
  return c.kind === 'direct';
12273
12592
  }
@@ -12398,6 +12717,71 @@ function sysMsg(id, systemKind, systemMeta, ts) {
12398
12717
  };
12399
12718
  }
12400
12719
 
12720
+ const RADIUS_PX = {
12721
+ sm: 6,
12722
+ md: 8,
12723
+ lg: 12,
12724
+ xl: 16,
12725
+ };
12726
+ class DsMobileVendorAvatarComponent {
12727
+ name = input('', ...(ngDevMode ? [{ debugName: "name" }] : []));
12728
+ logo = input('', ...(ngDevMode ? [{ debugName: "logo" }] : []));
12729
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
12730
+ radiusPx = computed(() => RADIUS_PX[this.size()], ...(ngDevMode ? [{ debugName: "radiusPx" }] : []));
12731
+ sizePx = computed(() => {
12732
+ const map = { sm: 24, md: 32, lg: 48, xl: 64 };
12733
+ return map[this.size()];
12734
+ }, ...(ngDevMode ? [{ debugName: "sizePx" }] : []));
12735
+ initials = computed(() => {
12736
+ return this.name()
12737
+ .split(/\s+/)
12738
+ .filter(w => w.length > 0)
12739
+ .slice(0, 2)
12740
+ .map(w => w[0].toUpperCase())
12741
+ .join('');
12742
+ }, ...(ngDevMode ? [{ debugName: "initials" }] : []));
12743
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileVendorAvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12744
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileVendorAvatarComponent, isStandalone: true, selector: "ds-mobile-vendor-avatar", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
12745
+ @if (logo()) {
12746
+ <div
12747
+ class="vendor-avatar-logo"
12748
+ [style.width.px]="sizePx()"
12749
+ [style.height.px]="sizePx()"
12750
+ [style.border-radius.px]="radiusPx()">
12751
+ <img [src]="logo()" [alt]="name()" />
12752
+ </div>
12753
+ } @else {
12754
+ <div [style.--vendor-avatar-radius.px]="radiusPx()">
12755
+ <ds-avatar
12756
+ type="initials"
12757
+ [size]="size()"
12758
+ [initials]="initials()" />
12759
+ </div>
12760
+ }
12761
+ `, isInline: true, styles: [":host{display:inline-flex;flex-shrink:0}.vendor-avatar-logo{display:inline-flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0;background:transparent}.vendor-avatar-logo img{width:100%;height:100%;object-fit:contain;display:block}:host ::ng-deep ds-avatar .avatar{border-radius:var(--vendor-avatar-radius)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }] });
12762
+ }
12763
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileVendorAvatarComponent, decorators: [{
12764
+ type: Component,
12765
+ args: [{ selector: 'ds-mobile-vendor-avatar', standalone: true, imports: [CommonModule, DsAvatarComponent], template: `
12766
+ @if (logo()) {
12767
+ <div
12768
+ class="vendor-avatar-logo"
12769
+ [style.width.px]="sizePx()"
12770
+ [style.height.px]="sizePx()"
12771
+ [style.border-radius.px]="radiusPx()">
12772
+ <img [src]="logo()" [alt]="name()" />
12773
+ </div>
12774
+ } @else {
12775
+ <div [style.--vendor-avatar-radius.px]="radiusPx()">
12776
+ <ds-avatar
12777
+ type="initials"
12778
+ [size]="size()"
12779
+ [initials]="initials()" />
12780
+ </div>
12781
+ }
12782
+ `, styles: [":host{display:inline-flex;flex-shrink:0}.vendor-avatar-logo{display:inline-flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0;background:transparent}.vendor-avatar-logo img{width:100%;height:100%;object-fit:contain;display:block}:host ::ng-deep ds-avatar .avatar{border-radius:var(--vendor-avatar-radius)}\n"] }]
12783
+ }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], logo: [{ type: i0.Input, args: [{ isSignal: true, alias: "logo", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
12784
+
12401
12785
  /**
12402
12786
  * DsMobileCardInlineComponent
12403
12787
  *
@@ -15595,6 +15979,11 @@ class DsMobileChatModalComponent {
15595
15979
  (click)="onGroupTitleClick()"
15596
15980
  />
15597
15981
  }
15982
+ } @else if (participant().avatarShape === 'squircle') {
15983
+ <ds-mobile-vendor-avatar
15984
+ [name]="participant().name"
15985
+ [logo]="participant().avatarSrc || ''"
15986
+ size="md" />
15598
15987
  } @else {
15599
15988
  <ds-avatar-with-badge
15600
15989
  [initials]="participant().avatarInitials || ''"
@@ -15658,6 +16047,11 @@ class DsMobileChatModalComponent {
15658
16047
  style="cursor: pointer"
15659
16048
  (click)="onGroupTitleClick(); $event.stopPropagation()"
15660
16049
  />
16050
+ } @else if (participant().avatarShape === 'squircle') {
16051
+ <ds-mobile-vendor-avatar
16052
+ [name]="participant().name"
16053
+ [logo]="participant().avatarSrc || ''"
16054
+ size="xl" />
15661
16055
  } @else {
15662
16056
  <ds-avatar-with-badge
15663
16057
  [initials]="participant().avatarInitials || ''"
@@ -15809,13 +16203,14 @@ class DsMobileChatModalComponent {
15809
16203
  </ds-mobile-message-composer>
15810
16204
  </div>
15811
16205
  </ds-mobile-modal-base>
15812
- `, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important;padding:0!important}:host ::ng-deep ds-textarea.ghost-input-clean .textarea-container{padding:0!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ":host ::ng-deep .modal-content-container{padding-top:0}:host-context(.chat-modal--settings) ::ng-deep .modal-header{border-bottom:none}:host-context(.chat-modal--add-members) ::ng-deep .modal-header{border-bottom:1px solid var(--border-color-default)}.chat-messages-container{display:flex;flex-direction:column;width:100%}.chat-system-line{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;line-height:1.35;color:var(--text-color-default-tertiary, #737373);text-align:center;margin:8px 24px}.chat-avatar-section{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px 0 0;background:var(--color-background-neutral-primary, #ffffff)}.chat-avatar-info{display:flex;flex-direction:column;align-items:center;gap:4px}.chat-avatar-name{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.chat-avatar-role{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-secondary, #666666)}.chat-avatar-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:4px}.messages-list{display:flex;flex-direction:column;width:100%;padding:16px 0 0;align-items:stretch}.messages-list ds-mobile-message-bubble{width:100%;display:flex}.timestamp-header{display:flex;justify-content:center;margin:16px 0 8px}.timestamp-text{font-family:Brockmann,sans-serif;font-size:12px;font-weight:400;color:var(--color-text-secondary);padding:4px 12px}.message-file-attachments{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;padding:0 20px 0 60px;max-width:100%}.message-file-attachments.own-message{padding:0 0 0 96px;align-items:flex-end}.message-file-attachments ds-mobile-card-inline-file{max-width:280px;width:100%}.message-image-attachment{width:96px;height:96px;cursor:pointer;border-radius:12px;overflow:hidden;position:relative;transition:transform .2s ease;border:1px solid var(--border-color-default, #e5e5e5)}.message-image-attachment:active{transform:scale(.98)}.message-image-attachment .inline-image{width:100%;height:100%;display:block;-o-object-fit:cover;object-fit:cover}.group-settings-back-btn{flex-shrink:0;border-radius:50%}.group-settings-back-btn::ng-deep button{border-radius:50%!important;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsMobileMessageComposerComponent, selector: "ds-mobile-message-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "placeholder", "sendButtonLabel", "attachmentButtonLabel", "showAttachmentButton", "editIndicatorText", "replyIndicatorText", "enableMentions", "mentionUsers", "autoFocus"], outputs: ["messageSent", "editCancelled", "replyCancelled", "mentionSelected", "attachmentClicked", "attachmentsChanged"] }, { kind: "component", type: DsMobileMessageBubbleComponent, selector: "ds-mobile-message-bubble", inputs: ["content", "isOwnMessage", "senderName", "timestamp", "showTimestamp", "avatarInitials", "avatarType", "avatarSrc", "showAvatar", "clusterPosition", "attachments", "clickable", "isNewMessage", "isDeleted", "showEditedHint", "editedHintText"], outputs: ["attachmentClick", "longPress", "messageClick"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["headerTitleInteractive", "showHeader"], outputs: ["titleClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileSystemMessageBannerComponent, selector: "ds-mobile-system-message-banner", inputs: ["message", "iconName", "afterTimestamp"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileGroupAvatarStackComponent, selector: "ds-mobile-group-avatar-stack", inputs: ["members", "customAvatarUrl", "size", "layout", "currentUserId"] }, { kind: "component", type: DsMobileListSearchComponent, selector: "ds-mobile-list-search", inputs: ["placeholder", "ariaLabel", "value", "showDivider"], outputs: ["valueChange"] }, { kind: "component", type: DsMobileChatGroupPanelsComponent, selector: "ds-mobile-chat-group-panels", inputs: ["panelView", "group", "membersForStack", "participantName", "currentUserId", "isAdmin", "canEditGroupDetails", "canAddGroupMembers", "canLeaveGroup", "canRemoveMember", "canMessageMember", "allTenantsForPicker", "searchQuery", "labels"], outputs: ["navigateTo", "renameGroup", "setGroupAvatarUrl", "addMembers", "removeMember", "messageMember", "leaveGroup"] }] });
16206
+ `, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important;padding:0!important}:host ::ng-deep ds-textarea.ghost-input-clean .textarea-container{padding:0!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ":host ::ng-deep .modal-content-container{padding-top:0}:host-context(.chat-modal--settings) ::ng-deep .modal-header{border-bottom:none}:host-context(.chat-modal--add-members) ::ng-deep .modal-header{border-bottom:1px solid var(--border-color-default)}.chat-messages-container{display:flex;flex-direction:column;width:100%}.chat-system-line{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;line-height:1.35;color:var(--text-color-default-tertiary, #737373);text-align:center;margin:8px 24px}.chat-avatar-section{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px 0 0;background:var(--color-background-neutral-primary, #ffffff)}.chat-avatar-info{display:flex;flex-direction:column;align-items:center;gap:4px}.chat-avatar-name{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.chat-avatar-role{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-secondary, #666666)}.chat-avatar-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:4px}.messages-list{display:flex;flex-direction:column;width:100%;padding:16px 0 0;align-items:stretch}.messages-list ds-mobile-message-bubble{width:100%;display:flex}.timestamp-header{display:flex;justify-content:center;margin:16px 0 8px}.timestamp-text{font-family:Brockmann,sans-serif;font-size:12px;font-weight:400;color:var(--color-text-secondary);padding:4px 12px}.message-file-attachments{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;padding:0 20px 0 60px;max-width:100%}.message-file-attachments.own-message{padding:0 0 0 96px;align-items:flex-end}.message-file-attachments ds-mobile-card-inline-file{max-width:280px;width:100%}.message-image-attachment{width:96px;height:96px;cursor:pointer;border-radius:12px;overflow:hidden;position:relative;transition:transform .2s ease;border:1px solid var(--border-color-default, #e5e5e5)}.message-image-attachment:active{transform:scale(.98)}.message-image-attachment .inline-image{width:100%;height:100%;display:block;-o-object-fit:cover;object-fit:cover}.group-settings-back-btn{flex-shrink:0;border-radius:50%}.group-settings-back-btn::ng-deep button{border-radius:50%!important;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsMobileVendorAvatarComponent, selector: "ds-mobile-vendor-avatar", inputs: ["name", "logo", "size"] }, { kind: "component", type: DsMobileMessageComposerComponent, selector: "ds-mobile-message-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "placeholder", "sendButtonLabel", "attachmentButtonLabel", "showAttachmentButton", "editIndicatorText", "replyIndicatorText", "enableMentions", "mentionUsers", "autoFocus"], outputs: ["messageSent", "editCancelled", "replyCancelled", "mentionSelected", "attachmentClicked", "attachmentsChanged"] }, { kind: "component", type: DsMobileMessageBubbleComponent, selector: "ds-mobile-message-bubble", inputs: ["content", "isOwnMessage", "senderName", "timestamp", "showTimestamp", "avatarInitials", "avatarType", "avatarSrc", "showAvatar", "clusterPosition", "attachments", "clickable", "isNewMessage", "isDeleted", "showEditedHint", "editedHintText"], outputs: ["attachmentClick", "longPress", "messageClick"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["headerTitleInteractive", "showHeader"], outputs: ["titleClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileSystemMessageBannerComponent, selector: "ds-mobile-system-message-banner", inputs: ["message", "iconName", "afterTimestamp"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileGroupAvatarStackComponent, selector: "ds-mobile-group-avatar-stack", inputs: ["members", "customAvatarUrl", "size", "layout", "currentUserId"] }, { kind: "component", type: DsMobileListSearchComponent, selector: "ds-mobile-list-search", inputs: ["placeholder", "ariaLabel", "value", "showDivider"], outputs: ["valueChange"] }, { kind: "component", type: DsMobileChatGroupPanelsComponent, selector: "ds-mobile-chat-group-panels", inputs: ["panelView", "group", "membersForStack", "participantName", "currentUserId", "isAdmin", "canEditGroupDetails", "canAddGroupMembers", "canLeaveGroup", "canRemoveMember", "canMessageMember", "allTenantsForPicker", "searchQuery", "labels"], outputs: ["navigateTo", "renameGroup", "setGroupAvatarUrl", "addMembers", "removeMember", "messageMember", "leaveGroup"] }] });
15813
16207
  }
15814
16208
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileChatModalComponent, decorators: [{
15815
16209
  type: Component,
15816
16210
  args: [{ selector: 'ds-mobile-chat-modal', standalone: true, imports: [
15817
16211
  CommonModule,
15818
16212
  DsAvatarWithBadgeComponent,
16213
+ DsMobileVendorAvatarComponent,
15819
16214
  DsMobileMessageComposerComponent,
15820
16215
  DsMobileMessageBubbleComponent,
15821
16216
  DsMobileModalBaseComponent,
@@ -15866,6 +16261,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
15866
16261
  (click)="onGroupTitleClick()"
15867
16262
  />
15868
16263
  }
16264
+ } @else if (participant().avatarShape === 'squircle') {
16265
+ <ds-mobile-vendor-avatar
16266
+ [name]="participant().name"
16267
+ [logo]="participant().avatarSrc || ''"
16268
+ size="md" />
15869
16269
  } @else {
15870
16270
  <ds-avatar-with-badge
15871
16271
  [initials]="participant().avatarInitials || ''"
@@ -15929,6 +16329,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
15929
16329
  style="cursor: pointer"
15930
16330
  (click)="onGroupTitleClick(); $event.stopPropagation()"
15931
16331
  />
16332
+ } @else if (participant().avatarShape === 'squircle') {
16333
+ <ds-mobile-vendor-avatar
16334
+ [name]="participant().name"
16335
+ [logo]="participant().avatarSrc || ''"
16336
+ size="xl" />
15932
16337
  } @else {
15933
16338
  <ds-avatar-with-badge
15934
16339
  [initials]="participant().avatarInitials || ''"
@@ -16711,12 +17116,23 @@ class DsMobileTenantPickerModalComponent {
16711
17116
  modalCtrl = inject(ModalController);
16712
17117
  peerMessaging = inject(PeerMessagingService);
16713
17118
  peerChat = inject(PeerChatLauncherService);
17119
+ /**
17120
+ * When true the modal acts as a simple single-select picker:
17121
+ * tapping a tenant dismisses with `{ tenantId }` (role `'selected'`).
17122
+ * The "more" menu and group-selection footer are hidden.
17123
+ */
17124
+ pickMode = false;
17125
+ /** Optional set of tenant IDs to exclude from the list (e.g. already-selected admins). */
17126
+ excludeIds;
16714
17127
  searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
16715
17128
  selectionMode = signal(false, ...(ngDevMode ? [{ debugName: "selectionMode" }] : []));
16716
17129
  selectedIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedIds" }] : []));
16717
17130
  filteredTenants = computed(() => {
16718
17131
  const q = this.searchQuery().toLowerCase().trim();
16719
- const tenants = this.peerMessaging.tenants();
17132
+ let tenants = this.peerMessaging.tenants();
17133
+ if (this.excludeIds?.size) {
17134
+ tenants = tenants.filter(t => !this.excludeIds.has(t.id));
17135
+ }
16720
17136
  if (!q)
16721
17137
  return tenants;
16722
17138
  return tenants.filter(t => t.name.toLowerCase().includes(q) || t.unit.toLowerCase().includes(q));
@@ -16738,6 +17154,10 @@ class DsMobileTenantPickerModalComponent {
16738
17154
  async onTenantClick(tenant) {
16739
17155
  if (this.selectionMode())
16740
17156
  return;
17157
+ if (this.pickMode) {
17158
+ await this.modalCtrl.dismiss({ tenantId: tenant.id }, 'selected');
17159
+ return;
17160
+ }
16741
17161
  await this.modalCtrl.dismiss(null, 'cancel');
16742
17162
  await this.peerChat.openTenant(tenant, { autoFocus: true });
16743
17163
  }
@@ -16787,7 +17207,7 @@ class DsMobileTenantPickerModalComponent {
16787
17207
  await this.peerChat.createGroup(ids, groupName);
16788
17208
  }
16789
17209
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileTenantPickerModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
16790
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileTenantPickerModalComponent, isStandalone: true, selector: "ds-mobile-tenant-picker-modal", ngImport: i0, template: `
17210
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileTenantPickerModalComponent, isStandalone: true, selector: "ds-mobile-tenant-picker-modal", inputs: { pickMode: "pickMode", excludeIds: "excludeIds" }, ngImport: i0, template: `
16791
17211
  <ds-mobile-modal-base
16792
17212
  headerTitle="Beboere"
16793
17213
  closeButtonLabel="Luk"
@@ -16813,8 +17233,8 @@ class DsMobileTenantPickerModalComponent {
16813
17233
  [initials]="tenant.initials"
16814
17234
  [contactPerson]="tenant.unit"
16815
17235
  [clickable]="true"
16816
- [showMoreMenu]="!selectionMode()"
16817
- [selectionMode]="selectionMode()"
17236
+ [showMoreMenu]="!pickMode && !selectionMode()"
17237
+ [selectionMode]="!pickMode && selectionMode()"
16818
17238
  [selected]="selectedIds().has(tenant.id)"
16819
17239
  (selectionToggle)="toggleTenant(tenant.id)"
16820
17240
  (contactClick)="onTenantClick(tenant)"
@@ -16880,8 +17300,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
16880
17300
  [initials]="tenant.initials"
16881
17301
  [contactPerson]="tenant.unit"
16882
17302
  [clickable]="true"
16883
- [showMoreMenu]="!selectionMode()"
16884
- [selectionMode]="selectionMode()"
17303
+ [showMoreMenu]="!pickMode && !selectionMode()"
17304
+ [selectionMode]="!pickMode && selectionMode()"
16885
17305
  [selected]="selectedIds().has(tenant.id)"
16886
17306
  (selectionToggle)="toggleTenant(tenant.id)"
16887
17307
  (contactClick)="onTenantClick(tenant)"
@@ -16912,7 +17332,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
16912
17332
  }
16913
17333
  </ds-mobile-modal-base>
16914
17334
  `, styles: [".search-empty{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-tertiary);text-align:center;padding:24px 16px;margin:0}.group-footer{display:flex;gap:8px;padding:12px 16px;border-top:1px solid var(--border-color-default, #e5e5e5);background:var(--color-background-neutral-primary, #fff)}.group-footer ds-button{display:block;flex:1;min-width:0;width:100%}.group-footer ::ng-deep button{width:100%;border-radius:99px}\n"] }]
16915
- }] });
17335
+ }], propDecorators: { pickMode: [{
17336
+ type: Input
17337
+ }], excludeIds: [{
17338
+ type: Input
17339
+ }] } });
16916
17340
 
16917
17341
  var index = /*#__PURE__*/Object.freeze({
16918
17342
  __proto__: null,
@@ -17819,7 +18243,7 @@ class DsMobileInteractiveListItemBookingComponent {
17819
18243
  </div>
17820
18244
  }
17821
18245
  </ds-mobile-list-item>
17822
- `, isInline: true, styles: [":host{display:block}:host:last-child{--divider-display: none;--item-padding-bottom: 0}.booking-thumbnail{position:relative;flex-shrink:0;width:64px;height:64px;border-radius:12px;overflow:hidden;background:var(--color-surface-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center}.booking-thumbnail img{width:100%;height:100%;object-fit:cover}.booking-thumbnail-placeholder{width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:var(--text-color-default-tertiary, #737373)}.booking-content{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.booking-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.booking-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.booking-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66);display:flex;align-items:center;gap:8px;margin-top:4px}.booking-status{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:500;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66)}.booking-status.available-today{color:var(--color-accent, #5d5fef)}.booking-status.available-from{color:var(--color-warning, #f59e0b)}.booking-status.unavailable{color:var(--text-color-default-tertiary, #737373)}.booking-datetime{display:flex;align-items:center;gap:4px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66)}.booking-trailing{display:flex;align-items:center;color:var(--color-text-tertiary, #a3a3a3)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsShapeIndicatorComponent, selector: "ds-shape-indicator", inputs: ["shape", "variant", "label"] }, { kind: "component", type: DsMobileListItemComponent, selector: "ds-mobile-list-item", inputs: ["leadingSize", "variant", "align", "flushTop", "interactive", "disabled", "loading", "enableLongPress", "showDesktopMoreButton", "moreActions", "moreButtonAriaLabel", "interactiveOffset", "title", "subtitle", "showDivider", "dividerSpacing"], outputs: ["itemClick", "moreButtonClick"] }, { kind: "component", type: DsMobileLoaderOverlayComponent, selector: "ds-mobile-loader-overlay", inputs: ["spinnerSize", "borderRadius"] }] });
18246
+ `, isInline: true, styles: [":host{display:block}:host:first-child{--item-padding-top: 0}:host:last-child{--divider-display: none;--item-padding-bottom: 0}.booking-thumbnail{position:relative;flex-shrink:0;width:64px;height:64px;border-radius:12px;overflow:hidden;background:var(--color-surface-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center}.booking-thumbnail img{width:100%;height:100%;object-fit:cover}.booking-thumbnail-placeholder{width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:var(--text-color-default-tertiary, #737373)}.booking-content{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.booking-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.booking-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.booking-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66);display:flex;align-items:center;gap:8px;margin-top:4px}.booking-status{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:500;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66)}.booking-status.available-today{color:var(--color-accent, #5d5fef)}.booking-status.available-from{color:var(--color-warning, #f59e0b)}.booking-status.unavailable{color:var(--text-color-default-tertiary, #737373)}.booking-datetime{display:flex;align-items:center;gap:4px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66)}.booking-trailing{display:flex;align-items:center;color:var(--color-text-tertiary, #a3a3a3)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsShapeIndicatorComponent, selector: "ds-shape-indicator", inputs: ["shape", "variant", "label"] }, { kind: "component", type: DsMobileListItemComponent, selector: "ds-mobile-list-item", inputs: ["leadingSize", "variant", "align", "flushTop", "interactive", "disabled", "loading", "enableLongPress", "showDesktopMoreButton", "moreActions", "moreButtonAriaLabel", "interactiveOffset", "title", "subtitle", "showDivider", "dividerSpacing"], outputs: ["itemClick", "moreButtonClick"] }, { kind: "component", type: DsMobileLoaderOverlayComponent, selector: "ds-mobile-loader-overlay", inputs: ["spinnerSize", "borderRadius"] }] });
17823
18247
  }
17824
18248
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileInteractiveListItemBookingComponent, decorators: [{
17825
18249
  type: Component,
@@ -17899,7 +18323,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
17899
18323
  </div>
17900
18324
  }
17901
18325
  </ds-mobile-list-item>
17902
- `, styles: [":host{display:block}:host:last-child{--divider-display: none;--item-padding-bottom: 0}.booking-thumbnail{position:relative;flex-shrink:0;width:64px;height:64px;border-radius:12px;overflow:hidden;background:var(--color-surface-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center}.booking-thumbnail img{width:100%;height:100%;object-fit:cover}.booking-thumbnail-placeholder{width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:var(--text-color-default-tertiary, #737373)}.booking-content{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.booking-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.booking-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.booking-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66);display:flex;align-items:center;gap:8px;margin-top:4px}.booking-status{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:500;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66)}.booking-status.available-today{color:var(--color-accent, #5d5fef)}.booking-status.available-from{color:var(--color-warning, #f59e0b)}.booking-status.unavailable{color:var(--text-color-default-tertiary, #737373)}.booking-datetime{display:flex;align-items:center;gap:4px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66)}.booking-trailing{display:flex;align-items:center;color:var(--color-text-tertiary, #a3a3a3)}\n"] }]
18326
+ `, styles: [":host{display:block}:host:first-child{--item-padding-top: 0}:host:last-child{--divider-display: none;--item-padding-bottom: 0}.booking-thumbnail{position:relative;flex-shrink:0;width:64px;height:64px;border-radius:12px;overflow:hidden;background:var(--color-surface-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center}.booking-thumbnail img{width:100%;height:100%;object-fit:cover}.booking-thumbnail-placeholder{width:100%;height:100%;display:flex;align-items:center;justify-content:center;color:var(--text-color-default-tertiary, #737373)}.booking-content{display:flex;flex-direction:column;gap:4px;flex:1;min-width:0}.booking-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.booking-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.booking-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66);display:flex;align-items:center;gap:8px;margin-top:4px}.booking-status{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:500;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66)}.booking-status.available-today{color:var(--color-accent, #5d5fef)}.booking-status.available-from{color:var(--color-warning, #f59e0b)}.booking-status.unavailable{color:var(--text-color-default-tertiary, #737373)}.booking-datetime{display:flex;align-items:center;gap:4px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-secondary, #545B66)}.booking-trailing{display:flex;align-items:center;color:var(--color-text-tertiary, #a3a3a3)}\n"] }]
17903
18327
  }], ctorParameters: () => [], propDecorators: { thumbnail: [{ type: i0.Input, args: [{ isSignal: true, alias: "thumbnail", required: false }] }], facilityTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "facilityTitle", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], bookingDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookingDate", required: false }] }], bookingTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "bookingTime", required: false }] }], availabilityStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "availabilityStatus", required: false }] }], statusLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusLabel", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], showChevron: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChevron", required: false }] }], enableLongPress: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableLongPress", required: false }] }], moreActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreActions", required: false }] }], bookingClick: [{ type: i0.Output, args: ["bookingClick"] }], longPress: [{ type: i0.Output, args: ["longPress"] }] } });
17904
18328
 
17905
18329
  /**
@@ -20096,6 +20520,64 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
20096
20520
  type: Output
20097
20521
  }] } });
20098
20522
 
20523
+ /**
20524
+ * DsMobileGlassSpinnerComponent
20525
+ *
20526
+ * Reusable loader overlay with a glassmorphism (blurred) background and a spinner.
20527
+ * This is useful when you want to show a loading state without covering the entire screen
20528
+ * with a solid background, but rather blurring the content behind it.
20529
+ *
20530
+ * Features:
20531
+ * - Glassmorphism blurred background
20532
+ * - Centered animated spinner
20533
+ * - Customizable spinner size
20534
+ * - Absolute positioning to cover parent
20535
+ */
20536
+ class DsMobileGlassSpinnerComponent {
20537
+ /**
20538
+ * Size of the spinner in pixels
20539
+ * @default 24
20540
+ */
20541
+ spinnerSize = input(24, ...(ngDevMode ? [{ debugName: "spinnerSize" }] : []));
20542
+ /**
20543
+ * Border radius of the overlay in pixels (should match parent's border radius)
20544
+ * @default 0
20545
+ */
20546
+ borderRadius = input(0, ...(ngDevMode ? [{ debugName: "borderRadius" }] : []));
20547
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileGlassSpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
20548
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.16", type: DsMobileGlassSpinnerComponent, isStandalone: true, selector: "ds-mobile-glass-spinner", inputs: { spinnerSize: { classPropertyName: "spinnerSize", publicName: "spinnerSize", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
20549
+ <div
20550
+ class="glass-spinner-overlay"
20551
+ [style.border-radius.px]="borderRadius()"
20552
+ role="status"
20553
+ aria-live="polite"
20554
+ aria-label="Loading">
20555
+ <div
20556
+ class="spinner"
20557
+ [style.width.px]="spinnerSize()"
20558
+ [style.height.px]="spinnerSize()">
20559
+ </div>
20560
+ </div>
20561
+ `, isInline: true, styles: [":host{display:contents}.glass-spinner-overlay{position:absolute;inset:0;background:#fff6;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:9999;border-radius:inherit}.spinner{border:2px solid var(--color-border-neutral-secondary, #E5E5E5);border-top-color:var(--color-accent, #6B5FF5);border-radius:50%;animation:spin .6s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}@media (prefers-color-scheme: dark){.glass-spinner-overlay{background:#0000004d}.spinner{border-color:#fff3;border-top-color:var(--color-accent, #6B5FF5)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
20562
+ }
20563
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileGlassSpinnerComponent, decorators: [{
20564
+ type: Component,
20565
+ args: [{ selector: 'ds-mobile-glass-spinner', standalone: true, imports: [CommonModule], template: `
20566
+ <div
20567
+ class="glass-spinner-overlay"
20568
+ [style.border-radius.px]="borderRadius()"
20569
+ role="status"
20570
+ aria-live="polite"
20571
+ aria-label="Loading">
20572
+ <div
20573
+ class="spinner"
20574
+ [style.width.px]="spinnerSize()"
20575
+ [style.height.px]="spinnerSize()">
20576
+ </div>
20577
+ </div>
20578
+ `, styles: [":host{display:contents}.glass-spinner-overlay{position:absolute;inset:0;background:#fff6;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;z-index:9999;border-radius:inherit}.spinner{border:2px solid var(--color-border-neutral-secondary, #E5E5E5);border-top-color:var(--color-accent, #6B5FF5);border-radius:50%;animation:spin .6s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}@media (prefers-color-scheme: dark){.glass-spinner-overlay{background:#0000004d}.spinner{border-color:#fff3;border-top-color:var(--color-accent, #6B5FF5)}}\n"] }]
20579
+ }], propDecorators: { spinnerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "spinnerSize", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }] } });
20580
+
20099
20581
  /**
20100
20582
  * DsMobileAppLoadingComponent — dev app mirror.
20101
20583
  * See projects/mobile-design-lib/src/components/app-loading for the authoritative source.
@@ -21628,6 +22110,10 @@ class DsMobileNewInquiryModalComponent {
21628
22110
  * Label for the submit button
21629
22111
  */
21630
22112
  submitButtonLabel = 'Submit';
22113
+ /**
22114
+ * Pre-set category included in the emitted NewInquiryData (e.g. vendor id)
22115
+ */
22116
+ category;
21631
22117
  /**
21632
22118
  * Form title field
21633
22119
  */
@@ -21863,6 +22349,7 @@ class DsMobileNewInquiryModalComponent {
21863
22349
  title: this.title.trim(),
21864
22350
  description: this.description.trim(),
21865
22351
  attachments: this.attachments(),
22352
+ ...(this.category && { category: this.category }),
21866
22353
  };
21867
22354
  if (this.onSubmit) {
21868
22355
  await this.onSubmit(inquiryData);
@@ -21935,7 +22422,7 @@ class DsMobileNewInquiryModalComponent {
21935
22422
  return null;
21936
22423
  }
21937
22424
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileNewInquiryModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21938
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileNewInquiryModalComponent, isStandalone: true, selector: "ds-mobile-new-inquiry-modal", inputs: { loading: "loading", error: "error", onSubmit: "onSubmit", titlePlaceholder: "titlePlaceholder", descriptionPlaceholder: "descriptionPlaceholder", submitButtonLabel: "submitButtonLabel" }, viewQueries: [{ propertyName: "titleInputRef", first: true, predicate: ["titleInput"], descendants: true, read: ElementRef }, { propertyName: "descriptionInputRef", first: true, predicate: ["descriptionInput"], descendants: true, read: ElementRef }, { propertyName: "titleInput", first: true, predicate: ["titleInput"], descendants: true }, { propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: `
22425
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileNewInquiryModalComponent, isStandalone: true, selector: "ds-mobile-new-inquiry-modal", inputs: { loading: "loading", error: "error", onSubmit: "onSubmit", titlePlaceholder: "titlePlaceholder", descriptionPlaceholder: "descriptionPlaceholder", submitButtonLabel: "submitButtonLabel", category: "category" }, viewQueries: [{ propertyName: "titleInputRef", first: true, predicate: ["titleInput"], descendants: true, read: ElementRef }, { propertyName: "descriptionInputRef", first: true, predicate: ["descriptionInput"], descendants: true, read: ElementRef }, { propertyName: "titleInput", first: true, predicate: ["titleInput"], descendants: true }, { propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: `
21939
22426
  <ds-mobile-modal-base [loading]="loading" [error]="error" [showHeader]="false" [hasFixedBottom]="true" [enableKeyboardHandling]="true" [keyboardContentBehavior]="'overlay'" closeButtonLabel="Close" [onCloseRequest]="handleCloseRequest">
21940
22427
  <!-- Form Content -->
21941
22428
  <ds-mobile-section>
@@ -22143,6 +22630,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
22143
22630
  type: Input
22144
22631
  }], submitButtonLabel: [{
22145
22632
  type: Input
22633
+ }], category: [{
22634
+ type: Input
22146
22635
  }] } });
22147
22636
 
22148
22637
  /**
@@ -22197,6 +22686,7 @@ class DsMobileNewInquiryModalService extends BaseModalService {
22197
22686
  ...(options?.titlePlaceholder && { titlePlaceholder: options.titlePlaceholder }),
22198
22687
  ...(options?.descriptionPlaceholder && { descriptionPlaceholder: options.descriptionPlaceholder }),
22199
22688
  ...(options?.submitButtonLabel && { submitButtonLabel: options.submitButtonLabel }),
22689
+ ...(options?.category && { category: options.category }),
22200
22690
  }, {
22201
22691
  keyboardClose: false, // Don't close on keyboard hide for this modal
22202
22692
  });
@@ -28947,6 +29437,267 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28947
29437
  args: ['pageComponent']
28948
29438
  }] } });
28949
29439
 
29440
+ class DsMobileInteractiveListItemServiceComponent {
29441
+ title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
29442
+ description = input('', ...(ngDevMode ? [{ debugName: "description" }] : []));
29443
+ logo = input('', ...(ngDevMode ? [{ debugName: "logo" }] : []));
29444
+ showChevron = input(false, ...(ngDevMode ? [{ debugName: "showChevron" }] : []));
29445
+ serviceClick = output();
29446
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileInteractiveListItemServiceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
29447
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileInteractiveListItemServiceComponent, isStandalone: true, selector: "ds-mobile-interactive-list-item-service", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, logo: { classPropertyName: "logo", publicName: "logo", isSignal: true, isRequired: false, transformFunction: null }, showChevron: { classPropertyName: "showChevron", publicName: "showChevron", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { serviceClick: "serviceClick" }, ngImport: i0, template: `
29448
+ <ds-mobile-list-item
29449
+ [leadingSize]="'32px'"
29450
+ [align]="'top'"
29451
+ [interactive]="true"
29452
+ [enableLongPress]="false"
29453
+ (itemClick)="serviceClick.emit()">
29454
+
29455
+ <div content-leading>
29456
+ <ds-mobile-vendor-avatar
29457
+ [name]="title()"
29458
+ [logo]="logo()"
29459
+ size="md" />
29460
+ </div>
29461
+
29462
+ <div content-main>
29463
+ <div class="service-content">
29464
+ <h3 class="service-title">{{ title() }}</h3>
29465
+ @if (description()) {
29466
+ <p class="service-description">{{ description() }}</p>
29467
+ }
29468
+ </div>
29469
+ </div>
29470
+
29471
+ @if (showChevron()) {
29472
+ <div content-trailing>
29473
+ <div class="service-trailing">
29474
+ <ds-icon name="remixArrowRightSLine" size="20px" />
29475
+ </div>
29476
+ </div>
29477
+ }
29478
+ </ds-mobile-list-item>
29479
+ `, isInline: true, styles: [":host{display:block}:host:first-child{--item-padding-top: 0}:host:last-child{--divider-display: none;--item-padding-bottom: 0}.service-content{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.service-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.service-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.service-trailing{display:flex;align-items:center;color:var(--color-text-tertiary, #a3a3a3)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobileListItemComponent, selector: "ds-mobile-list-item", inputs: ["leadingSize", "variant", "align", "flushTop", "interactive", "disabled", "loading", "enableLongPress", "showDesktopMoreButton", "moreActions", "moreButtonAriaLabel", "interactiveOffset", "title", "subtitle", "showDivider", "dividerSpacing"], outputs: ["itemClick", "moreButtonClick"] }, { kind: "component", type: DsMobileVendorAvatarComponent, selector: "ds-mobile-vendor-avatar", inputs: ["name", "logo", "size"] }] });
29480
+ }
29481
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileInteractiveListItemServiceComponent, decorators: [{
29482
+ type: Component,
29483
+ args: [{ selector: 'ds-mobile-interactive-list-item-service', standalone: true, imports: [CommonModule, DsIconComponent, DsMobileListItemComponent, DsMobileVendorAvatarComponent], template: `
29484
+ <ds-mobile-list-item
29485
+ [leadingSize]="'32px'"
29486
+ [align]="'top'"
29487
+ [interactive]="true"
29488
+ [enableLongPress]="false"
29489
+ (itemClick)="serviceClick.emit()">
29490
+
29491
+ <div content-leading>
29492
+ <ds-mobile-vendor-avatar
29493
+ [name]="title()"
29494
+ [logo]="logo()"
29495
+ size="md" />
29496
+ </div>
29497
+
29498
+ <div content-main>
29499
+ <div class="service-content">
29500
+ <h3 class="service-title">{{ title() }}</h3>
29501
+ @if (description()) {
29502
+ <p class="service-description">{{ description() }}</p>
29503
+ }
29504
+ </div>
29505
+ </div>
29506
+
29507
+ @if (showChevron()) {
29508
+ <div content-trailing>
29509
+ <div class="service-trailing">
29510
+ <ds-icon name="remixArrowRightSLine" size="20px" />
29511
+ </div>
29512
+ </div>
29513
+ }
29514
+ </ds-mobile-list-item>
29515
+ `, styles: [":host{display:block}:host:first-child{--item-padding-top: 0}:host:last-child{--divider-display: none;--item-padding-bottom: 0}.service-content{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.service-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.service-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.service-trailing{display:flex;align-items:center;color:var(--color-text-tertiary, #a3a3a3)}\n"] }]
29516
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], logo: [{ type: i0.Input, args: [{ isSignal: true, alias: "logo", required: false }] }], showChevron: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChevron", required: false }] }], serviceClick: [{ type: i0.Output, args: ["serviceClick"] }] } });
29517
+
29518
+ class DsMobileServiceVendorSheetComponent {
29519
+ vendorName;
29520
+ vendorDescription = '';
29521
+ vendorImage = '';
29522
+ vendorLogo = '';
29523
+ bookButtonLabel = 'Book';
29524
+ modalController = inject(ModalController);
29525
+ async handleBook() {
29526
+ await this.modalController.dismiss(null, 'book');
29527
+ }
29528
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileServiceVendorSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
29529
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileServiceVendorSheetComponent, isStandalone: true, selector: "ds-mobile-service-vendor-sheet", inputs: { vendorName: "vendorName", vendorDescription: "vendorDescription", vendorImage: "vendorImage", vendorLogo: "vendorLogo", bookButtonLabel: "bookButtonLabel" }, ngImport: i0, template: `
29530
+ <ds-mobile-modal-base
29531
+ [headerTitle]="vendorName"
29532
+ [showHeader]="true"
29533
+ [hasFixedBottom]="true">
29534
+
29535
+ <ds-mobile-vendor-avatar
29536
+ header-leading
29537
+ [name]="vendorName"
29538
+ [logo]="vendorLogo"
29539
+ size="md" />
29540
+
29541
+ <ds-mobile-section [showBorder]="false" padding="20px 20px 0 20px">
29542
+ @if (vendorImage) {
29543
+ <div class="hero-image-container">
29544
+ <img class="hero-image" [src]="vendorImage" [alt]="vendorName" />
29545
+ </div>
29546
+ } @else {
29547
+ <div class="hero-empty-state">
29548
+ <ds-mobile-vendor-avatar
29549
+ [name]="vendorName"
29550
+ [logo]="vendorLogo"
29551
+ size="xl" />
29552
+ </div>
29553
+ }
29554
+ </ds-mobile-section>
29555
+
29556
+ <ds-mobile-section padding="20px 20px 20px 20px">
29557
+ @if (vendorDescription) {
29558
+ <div class="vendor-description" [innerHTML]="vendorDescription"></div>
29559
+ }
29560
+ </ds-mobile-section>
29561
+
29562
+ <div fixed-bottom>
29563
+ <div class="booking-action">
29564
+ <ds-button
29565
+ size="md"
29566
+ variant="primary"
29567
+ [fullWidth]="true"
29568
+ (clicked)="handleBook()">
29569
+ {{ bookButtonLabel }}
29570
+ </ds-button>
29571
+ </div>
29572
+ </div>
29573
+ </ds-mobile-modal-base>
29574
+ `, isInline: true, styles: [".hero-image-container{width:100%;aspect-ratio:16 / 9;border-radius:12px;overflow:hidden;background:var(--color-surface-secondary, #f5f5f5)}.hero-image{width:100%;height:100%;object-fit:cover;display:block}.hero-empty-state{width:100%;aspect-ratio:16 / 9;border-radius:12px;background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center}.vendor-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-base, 16px);line-height:1.6;color:var(--text-color-default-primary, #202227)}::ng-deep .vendor-description p{margin:12px 0 0}::ng-deep .vendor-description p:first-child,::ng-deep .vendor-description h3+p{margin-top:0}::ng-deep .vendor-description h3{font-family:Brockmann,sans-serif;font-size:var(--font-size-lg, 18px);font-weight:600;line-height:1.4;color:var(--text-color-default-primary, #202227);margin:0!important;padding:24px 0 8px!important;display:block}::ng-deep .vendor-description h3:first-child{padding-top:0!important}::ng-deep .vendor-description ul{list-style:disc;padding-left:20px;margin:0 0 12px}::ng-deep .vendor-description ul li{font-family:Brockmann,sans-serif;font-size:var(--font-size-base, 16px);line-height:1.6;color:var(--text-color-default-primary, #202227);margin-top:4px}::ng-deep .vendor-description ul li:first-child{margin-top:0}.booking-action{padding:16px 20px;background:var(--color-surface-primary, #ffffff);border-top:1px solid var(--color-border, #e5e5e5)}.booking-action ::ng-deep ds-button{display:block;width:100%}.booking-action ::ng-deep ds-button button{width:100%;border-radius:100px;height:44px;min-height:44px;max-height:44px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsButtonComponent, selector: "ds-button", inputs: ["variant", "size", "disabled", "loading", "pressed", "expanded", "leadingIcon", "trailingIcon", "ariaLabel", "iconOnly"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["headerTitleInteractive", "showHeader"], outputs: ["titleClick"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileVendorAvatarComponent, selector: "ds-mobile-vendor-avatar", inputs: ["name", "logo", "size"] }] });
29575
+ }
29576
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileServiceVendorSheetComponent, decorators: [{
29577
+ type: Component,
29578
+ args: [{ selector: 'ds-mobile-service-vendor-sheet', standalone: true, imports: [
29579
+ CommonModule,
29580
+ DsButtonComponent,
29581
+ DsMobileModalBaseComponent,
29582
+ DsMobileSectionComponent,
29583
+ DsMobileVendorAvatarComponent,
29584
+ ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
29585
+ <ds-mobile-modal-base
29586
+ [headerTitle]="vendorName"
29587
+ [showHeader]="true"
29588
+ [hasFixedBottom]="true">
29589
+
29590
+ <ds-mobile-vendor-avatar
29591
+ header-leading
29592
+ [name]="vendorName"
29593
+ [logo]="vendorLogo"
29594
+ size="md" />
29595
+
29596
+ <ds-mobile-section [showBorder]="false" padding="20px 20px 0 20px">
29597
+ @if (vendorImage) {
29598
+ <div class="hero-image-container">
29599
+ <img class="hero-image" [src]="vendorImage" [alt]="vendorName" />
29600
+ </div>
29601
+ } @else {
29602
+ <div class="hero-empty-state">
29603
+ <ds-mobile-vendor-avatar
29604
+ [name]="vendorName"
29605
+ [logo]="vendorLogo"
29606
+ size="xl" />
29607
+ </div>
29608
+ }
29609
+ </ds-mobile-section>
29610
+
29611
+ <ds-mobile-section padding="20px 20px 20px 20px">
29612
+ @if (vendorDescription) {
29613
+ <div class="vendor-description" [innerHTML]="vendorDescription"></div>
29614
+ }
29615
+ </ds-mobile-section>
29616
+
29617
+ <div fixed-bottom>
29618
+ <div class="booking-action">
29619
+ <ds-button
29620
+ size="md"
29621
+ variant="primary"
29622
+ [fullWidth]="true"
29623
+ (clicked)="handleBook()">
29624
+ {{ bookButtonLabel }}
29625
+ </ds-button>
29626
+ </div>
29627
+ </div>
29628
+ </ds-mobile-modal-base>
29629
+ `, styles: [".hero-image-container{width:100%;aspect-ratio:16 / 9;border-radius:12px;overflow:hidden;background:var(--color-surface-secondary, #f5f5f5)}.hero-image{width:100%;height:100%;object-fit:cover;display:block}.hero-empty-state{width:100%;aspect-ratio:16 / 9;border-radius:12px;background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center}.vendor-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-base, 16px);line-height:1.6;color:var(--text-color-default-primary, #202227)}::ng-deep .vendor-description p{margin:12px 0 0}::ng-deep .vendor-description p:first-child,::ng-deep .vendor-description h3+p{margin-top:0}::ng-deep .vendor-description h3{font-family:Brockmann,sans-serif;font-size:var(--font-size-lg, 18px);font-weight:600;line-height:1.4;color:var(--text-color-default-primary, #202227);margin:0!important;padding:24px 0 8px!important;display:block}::ng-deep .vendor-description h3:first-child{padding-top:0!important}::ng-deep .vendor-description ul{list-style:disc;padding-left:20px;margin:0 0 12px}::ng-deep .vendor-description ul li{font-family:Brockmann,sans-serif;font-size:var(--font-size-base, 16px);line-height:1.6;color:var(--text-color-default-primary, #202227);margin-top:4px}::ng-deep .vendor-description ul li:first-child{margin-top:0}.booking-action{padding:16px 20px;background:var(--color-surface-primary, #ffffff);border-top:1px solid var(--color-border, #e5e5e5)}.booking-action ::ng-deep ds-button{display:block;width:100%}.booking-action ::ng-deep ds-button button{width:100%;border-radius:100px;height:44px;min-height:44px;max-height:44px}\n"] }]
29630
+ }], propDecorators: { vendorName: [{
29631
+ type: Input,
29632
+ args: [{ required: true }]
29633
+ }], vendorDescription: [{
29634
+ type: Input
29635
+ }], vendorImage: [{
29636
+ type: Input
29637
+ }], vendorLogo: [{
29638
+ type: Input
29639
+ }], bookButtonLabel: [{
29640
+ type: Input
29641
+ }] } });
29642
+ class DsMobileServiceVendorModalService extends BaseModalService {
29643
+ constructor(modalController) {
29644
+ super(modalController);
29645
+ }
29646
+ async open(props) {
29647
+ const modal = await this.createModal(DsMobileServiceVendorSheetComponent, props);
29648
+ await modal.present();
29649
+ return modal;
29650
+ }
29651
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileServiceVendorModalService, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Injectable });
29652
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileServiceVendorModalService, providedIn: 'root' });
29653
+ }
29654
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileServiceVendorModalService, decorators: [{
29655
+ type: Injectable,
29656
+ args: [{ providedIn: 'root' }]
29657
+ }], ctorParameters: () => [{ type: i1.ModalController }] });
29658
+
29659
+ class InquiriesService {
29660
+ inquiries = signal([
29661
+ {
29662
+ id: '1',
29663
+ title: 'Tørretumbler virker ikke',
29664
+ description: 'I de sidste tre dage har jeg oplevet vedvarende problemer med tørretumbleren. Den starter, men stopper efter få minutter.',
29665
+ status: 'open',
29666
+ timestamp: '12 dage siden',
29667
+ category: 'appliance',
29668
+ },
29669
+ {
29670
+ id: '2',
29671
+ title: 'Problem med vandtryk',
29672
+ description: 'Lavt vandtryk i badeværelseshåndvasken. Det er blevet gradvist værre i løbet af den sidste uge.',
29673
+ status: 'open',
29674
+ timestamp: '5 dage siden',
29675
+ category: 'plumbing',
29676
+ },
29677
+ {
29678
+ id: '3',
29679
+ title: 'Varme virker ikke ordentligt',
29680
+ description: 'Varmesystemet holder ikke den indstillede temperatur. Lejligheden er meget koldere, end den burde være.',
29681
+ status: 'closed',
29682
+ timestamp: '2 måneder siden',
29683
+ category: 'heating',
29684
+ },
29685
+ ], ...(ngDevMode ? [{ debugName: "inquiries" }] : []));
29686
+ openInquiries = computed(() => this.inquiries().filter(i => i.status === 'open'), ...(ngDevMode ? [{ debugName: "openInquiries" }] : []));
29687
+ getById(id) {
29688
+ return this.inquiries().find(i => i.id === id);
29689
+ }
29690
+ addInquiry(inquiry) {
29691
+ this.inquiries.update(list => [inquiry, ...list]);
29692
+ }
29693
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InquiriesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
29694
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InquiriesService, providedIn: 'root' });
29695
+ }
29696
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: InquiriesService, decorators: [{
29697
+ type: Injectable,
29698
+ args: [{ providedIn: 'root' }]
29699
+ }] });
29700
+
28950
29701
  /**
28951
29702
  * PageLoadingService
28952
29703
  *
@@ -29238,36 +29989,18 @@ class MobileHomePageComponent {
29238
29989
  recentPosts = computed(() => this.postsService.posts()
29239
29990
  .filter(post => post.id !== 'post-4') // Exclude pinned post
29240
29991
  .slice(0, 3), ...(ngDevMode ? [{ debugName: "recentPosts" }] : []));
29241
- // Mock inquiry data
29242
- allInquiries = signal([
29243
- {
29244
- id: '1',
29245
- title: 'Tørretumbler virker ikke',
29246
- description: 'I de sidste tre dage har jeg oplevet vedvarende problemer med tørretumbleren. Den starter, men stopper efter få minutter.',
29247
- status: 'open',
29248
- timestamp: '12 dage siden'
29249
- },
29250
- {
29251
- id: '2',
29252
- title: 'Problem med vandtryk',
29253
- description: 'Lavt vandtryk i badeværelseshåndvasken. Det er blevet gradvist værre i løbet af den sidste uge.',
29254
- status: 'open',
29255
- timestamp: '5 dage siden'
29256
- },
29257
- {
29258
- id: '3',
29259
- title: 'Varme virker ikke ordentligt',
29260
- description: 'Varmesystemet holder ikke den indstillede temperatur. Lejligheden er meget koldere, end den burde være.',
29261
- status: 'closed',
29262
- timestamp: '2 måneder siden'
29263
- }
29264
- ], ...(ngDevMode ? [{ debugName: "allInquiries" }] : []));
29265
- // Filter for open inquiries and limit to 3
29266
- openInquiries = computed(() => this.allInquiries()
29267
- .filter(inquiry => inquiry.status === 'open')
29268
- .slice(0, 3), ...(ngDevMode ? [{ debugName: "openInquiries" }] : []));
29992
+ inquiriesService = inject(InquiriesService);
29993
+ openInquiries = computed(() => this.inquiriesService.openInquiries().slice(0, 3), ...(ngDevMode ? [{ debugName: "openInquiries" }] : []));
29269
29994
  recentPeerMessages = computed(() => this.peerMessaging.conversations().slice(0, 3), ...(ngDevMode ? [{ debugName: "recentPeerMessages" }] : []));
29995
+ allVendors = signal([
29996
+ { id: 'v-1', name: 'CleanTeam ApS', category: 'Rengøring', description: 'Trappevask og vinduespolering', phone: '+45 70 20 30 40', logo: '/Assets/dummy-logos/cleanteam-logo.svg', thumbnail: '/Assets/Dummy-photos/clean-team.jpg', fullDescription: '<h3>Rengøring</h3><p>CleanTeam ApS tilbyder professionel trappevask og vinduespolering for ejendommen. Servicen udføres ugentligt og kan tilpasses jeres behov.</p><h3>Pris</h3><p>350 kr. per besøg</p>' },
29997
+ { id: 'v-3', name: 'Blik Partner A/S', category: 'VVS', description: 'VVS-service og akut udkald', phone: '+45 33 44 55 66', thumbnail: '/Assets/Dummy-photos/plumbing.jpg', fullDescription: '<h3>VVS</h3><p>BlikPartner A/S er jeres VVS-partner til alt fra løbende vedligeholdelse til akutte udkald. Vi dækker reparation af vandrør, afløb, radiatorer og blandingsbatterier.</p><h3>Pris</h3><p>450 kr. per udkald + tid</p>' },
29998
+ { id: 'v-4', name: 'ElektroTek ApS', category: 'Elektriker', description: 'El-installationer og fejlsøgning', phone: '+45 23 45 67 89', logo: '/Assets/dummy-logos/electrician-logo.svg', thumbnail: '/Assets/Dummy-photos/electrician.jpg', heroImage: '/Assets/Dummy-photos/electrician.jpg', fullDescription: '<h3>Elektriker</h3><p>ElektroTek ApS varetager el-installationer, fejlsøgning og lovpligtige eftersyn for ejendommen. Vi udfører også småopgaver som udskiftning af kontakter og lampeudtag.</p><h3>Pris</h3><p>395 kr. per time</p>' },
29999
+ ], ...(ngDevMode ? [{ debugName: "allVendors" }] : []));
30000
+ previewVendors = computed(() => this.allVendors().slice(0, 3), ...(ngDevMode ? [{ debugName: "previewVendors" }] : []));
29270
30001
  modalCtrl = inject(ModalController);
30002
+ vendorModal = inject(DsMobileServiceVendorModalService);
30003
+ newInquiryModal = inject(DsMobileNewInquiryModalService);
29271
30004
  constructor(router, navCtrl, userService, postsService, postModal, trackingPermissionService, bottomSheet, familyAccessService, peerMessaging, peerChat) {
29272
30005
  this.router = router;
29273
30006
  this.navCtrl = navCtrl;
@@ -29346,6 +30079,48 @@ class MobileHomePageComponent {
29346
30079
  });
29347
30080
  await modal.present();
29348
30081
  }
30082
+ navigateToServices() {
30083
+ void this.navCtrl.navigateForward(['/services'], { animation: customPageTransition });
30084
+ }
30085
+ async openVendorSheet(vendor) {
30086
+ const modal = await this.vendorModal.open({
30087
+ vendorName: vendor.name,
30088
+ vendorDescription: vendor.fullDescription || vendor.description || '',
30089
+ vendorImage: vendor.heroImage || '',
30090
+ vendorLogo: vendor.logo,
30091
+ });
30092
+ const result = await modal.onWillDismiss();
30093
+ if (result.role === 'book') {
30094
+ await this.openInquiryForVendor(vendor);
30095
+ }
30096
+ }
30097
+ async openInquiryForVendor(vendor) {
30098
+ await this.newInquiryModal.open({
30099
+ titlePlaceholder: 'Emne for henvendelsen',
30100
+ descriptionPlaceholder: 'Beskriv hvad du har brug for…',
30101
+ submitButtonLabel: 'Send henvendelse',
30102
+ category: vendor.category,
30103
+ onSubmit: async (data) => {
30104
+ const inquiryId = `service-${Date.now()}`;
30105
+ this.inquiriesService.addInquiry({
30106
+ id: inquiryId,
30107
+ title: data.title,
30108
+ description: data.description,
30109
+ status: 'open',
30110
+ timestamp: 'Lige nu',
30111
+ category: data.category || vendor.category,
30112
+ vendorName: vendor.name,
30113
+ vendorLogo: vendor.logo,
30114
+ });
30115
+ await this.newInquiryModal.close();
30116
+ setTimeout(() => {
30117
+ this.navCtrl.navigateForward([`/inquiry-detail/${inquiryId}`], {
30118
+ animation: customPageTransition,
30119
+ });
30120
+ }, 300);
30121
+ },
30122
+ });
30123
+ }
29349
30124
  navigateToMessages() {
29350
30125
  void this.navCtrl.navigateForward(['/messages'], { animation: customPageTransition });
29351
30126
  }
@@ -29525,6 +30300,24 @@ class MobileHomePageComponent {
29525
30300
  </div>
29526
30301
  </ds-mobile-section>
29527
30302
 
30303
+ <!-- Services preview -->
30304
+ @if (previewVendors().length > 0) {
30305
+ <ds-mobile-section
30306
+ headline="Services"
30307
+ linkText="Se alle"
30308
+ contentGap="0px"
30309
+ (linkClick)="navigateToServices()">
30310
+ @for (vendor of previewVendors(); track vendor.id) {
30311
+ <ds-mobile-interactive-list-item-service
30312
+ [title]="vendor.name"
30313
+ [description]="vendor.description || ''"
30314
+ [logo]="vendor.logo || ''"
30315
+ (serviceClick)="openVendorSheet(vendor)"
30316
+ />
30317
+ }
30318
+ </ds-mobile-section>
30319
+ }
30320
+
29528
30321
  <!-- Recent Community Posts Section (empty state) -->
29529
30322
  <ds-mobile-section>
29530
30323
  <div class="empty-state">
@@ -29582,7 +30375,7 @@ class MobileHomePageComponent {
29582
30375
  </ds-mobile-page-main>
29583
30376
  } <!-- end @if (!isCoveringScreen()) -->
29584
30377
 
29585
- `, isInline: true, styles: [".posts-list,.messages-preview-list{display:flex;flex-direction:column}.property-banner-nav{display:block;width:100%;border-radius:12px;cursor:pointer;-webkit-tap-highlight-color:transparent}.property-banner-nav:focus-visible{outline:2px solid var(--color-accent, #6B5FF5);outline-offset:2px}.inquiries-list{display:flex;flex-direction:column}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center}.empty-state ds-button{display:block;margin-top:16px}.empty-state ds-button::ng-deep .btn{width:100%;border-radius:9999px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}@keyframes slideDown{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.welcome-toast{padding:10px 14px;border-radius:12px;background:var(--color-background-brand-secondary, #EEF0FF);display:flex;align-items:flex-start;gap:10px;font-size:14px;font-weight:500;color:var(--color-accent, #6B5FF5);animation:slideDown .2s ease-out}.toast-icon{width:20px;height:20px;border-radius:50%;background:var(--color-accent, #6B5FF5);display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff;margin-top:1px}.welcome-toast-content{flex:1;display:flex;flex-direction:column;gap:2px}.welcome-toast-heading{font-family:Brockmann,sans-serif;font-size:14px;font-weight:600;color:var(--color-brand-content, #3B3691);margin:0}.welcome-toast-text{font-family:Brockmann,sans-serif;font-size:13px;line-height:1.4;color:var(--color-brand-content, #3B3691);margin:0;opacity:.8}.welcome-toast-text strong{font-weight:600;opacity:1}.toast-dismiss{margin-left:auto;background:none;border:none;cursor:pointer;flex-shrink:0;color:var(--color-accent, #6B5FF5);display:flex;align-items:center;justify-content:center}.home-content--animating{animation:homeReveal .3s var(--spring-curve-smooth) both}@keyframes homeReveal{0%{opacity:0;transform:translateY(128px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "component", type: DsButtonComponent, selector: "ds-button", inputs: ["variant", "size", "disabled", "loading", "pressed", "expanded", "leadingIcon", "trailingIcon", "ariaLabel", "iconOnly"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "firstEntry", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "contentPadding", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileIllustrationComponent, selector: "ds-mobile-illustration", inputs: ["variant", "size", "alt"] }, { kind: "component", type: DsMobilePropertyBannerComponent, selector: "ds-mobile-property-banner", inputs: ["address", "photoUrl", "tenantCount"] }, { kind: "component", type: DsMobileInteractiveListItemPostComponent, selector: "ds-mobile-interactive-list-item-post", inputs: ["authorName", "authorRole", "timestamp", "avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "showBadge", "variant", "align", "clickable", "enableLongPress", "moreActions"], outputs: ["postClick", "commentClick", "longPress"] }, { kind: "component", type: DsMobileInteractiveListItemInquiryComponent, selector: "ds-mobile-interactive-list-item-inquiry", inputs: ["title", "description", "status", "statusLabel", "timestamp", "iconName", "iconColor", "variant", "align", "clickable", "showChevron", "enableLongPress", "moreActions"], outputs: ["inquiryClick", "longPress"] }, { kind: "component", type: DsMobileInteractiveListItemMessageComponent, selector: "ds-mobile-interactive-list-item-message", inputs: ["senderName", "senderRole", "timestamp", "message", "avatarInitials", "avatarType", "avatarSrc", "unread", "clickable", "align", "showAvatarBadge", "groupStackMembers", "groupCustomAvatarUrl", "groupStackExcludeParticipantId"], outputs: ["messageClick", "longPress"] }, { kind: "component", type: DsMobileOfflineBannerComponent, selector: "ds-mobile-offline-banner", inputs: ["icon", "title", "message"] }, { kind: "component", type: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { kind: "component", type: PostActionsComponent, selector: "post-actions" }, { kind: "component", type: ActionLikeComponent, selector: "action-like", inputs: ["active", "count"], outputs: ["activeChange", "countChange", "likeClick"] }, { kind: "component", type: ActionCommentComponent, selector: "action-comment", inputs: ["count"], outputs: ["commentClick"] }] });
30378
+ `, isInline: true, styles: [".posts-list,.messages-preview-list{display:flex;flex-direction:column}.property-banner-nav{display:block;width:100%;border-radius:12px;cursor:pointer;-webkit-tap-highlight-color:transparent}.property-banner-nav:focus-visible{outline:2px solid var(--color-accent, #6B5FF5);outline-offset:2px}.inquiries-list,.services-preview-list{display:flex;flex-direction:column}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center}.empty-state ds-button{display:block;margin-top:16px}.empty-state ds-button::ng-deep .btn{width:100%;border-radius:9999px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}@keyframes slideDown{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.welcome-toast{padding:10px 14px;border-radius:12px;background:var(--color-background-brand-secondary, #EEF0FF);display:flex;align-items:flex-start;gap:10px;font-size:14px;font-weight:500;color:var(--color-accent, #6B5FF5);animation:slideDown .2s ease-out}.toast-icon{width:20px;height:20px;border-radius:50%;background:var(--color-accent, #6B5FF5);display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff;margin-top:1px}.welcome-toast-content{flex:1;display:flex;flex-direction:column;gap:2px}.welcome-toast-heading{font-family:Brockmann,sans-serif;font-size:14px;font-weight:600;color:var(--color-brand-content, #3B3691);margin:0}.welcome-toast-text{font-family:Brockmann,sans-serif;font-size:13px;line-height:1.4;color:var(--color-brand-content, #3B3691);margin:0;opacity:.8}.welcome-toast-text strong{font-weight:600;opacity:1}.toast-dismiss{margin-left:auto;background:none;border:none;cursor:pointer;flex-shrink:0;color:var(--color-accent, #6B5FF5);display:flex;align-items:center;justify-content:center}.home-content--animating{animation:homeReveal .3s var(--spring-curve-smooth) both}@keyframes homeReveal{0%{opacity:0;transform:translateY(128px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "component", type: DsButtonComponent, selector: "ds-button", inputs: ["variant", "size", "disabled", "loading", "pressed", "expanded", "leadingIcon", "trailingIcon", "ariaLabel", "iconOnly"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "firstEntry", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "contentPadding", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileIllustrationComponent, selector: "ds-mobile-illustration", inputs: ["variant", "size", "alt"] }, { kind: "component", type: DsMobilePropertyBannerComponent, selector: "ds-mobile-property-banner", inputs: ["address", "photoUrl", "tenantCount"] }, { kind: "component", type: DsMobileInteractiveListItemPostComponent, selector: "ds-mobile-interactive-list-item-post", inputs: ["authorName", "authorRole", "timestamp", "avatarInitials", "avatarType", "avatarSrc", "avatarIconName", "showBadge", "variant", "align", "clickable", "enableLongPress", "moreActions"], outputs: ["postClick", "commentClick", "longPress"] }, { kind: "component", type: DsMobileInteractiveListItemInquiryComponent, selector: "ds-mobile-interactive-list-item-inquiry", inputs: ["title", "description", "status", "statusLabel", "timestamp", "iconName", "iconColor", "variant", "align", "clickable", "showChevron", "enableLongPress", "moreActions"], outputs: ["inquiryClick", "longPress"] }, { kind: "component", type: DsMobileInteractiveListItemMessageComponent, selector: "ds-mobile-interactive-list-item-message", inputs: ["senderName", "senderRole", "timestamp", "message", "avatarInitials", "avatarType", "avatarSrc", "unread", "clickable", "align", "showAvatarBadge", "groupStackMembers", "groupCustomAvatarUrl", "groupStackExcludeParticipantId"], outputs: ["messageClick", "longPress"] }, { kind: "component", type: DsMobileInteractiveListItemServiceComponent, selector: "ds-mobile-interactive-list-item-service", inputs: ["title", "description", "logo", "showChevron"], outputs: ["serviceClick"] }, { kind: "component", type: DsMobileOfflineBannerComponent, selector: "ds-mobile-offline-banner", inputs: ["icon", "title", "message"] }, { kind: "component", type: PostContentComponent, selector: "post-content" }, { kind: "component", type: PostTextComponent, selector: "post-text" }, { kind: "component", type: PostActionsComponent, selector: "post-actions" }, { kind: "component", type: ActionLikeComponent, selector: "action-like", inputs: ["active", "count"], outputs: ["activeChange", "countChange", "likeClick"] }, { kind: "component", type: ActionCommentComponent, selector: "action-comment", inputs: ["count"], outputs: ["commentClick"] }] });
29586
30379
  }
29587
30380
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MobileHomePageComponent, decorators: [{
29588
30381
  type: Component,
@@ -29596,6 +30389,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
29596
30389
  DsMobileInteractiveListItemPostComponent,
29597
30390
  DsMobileInteractiveListItemInquiryComponent,
29598
30391
  DsMobileInteractiveListItemMessageComponent,
30392
+ DsMobileInteractiveListItemBookingComponent,
30393
+ DsMobileInteractiveListItemServiceComponent,
29599
30394
  DsMobileOfflineBannerComponent,
29600
30395
  PostContentComponent,
29601
30396
  PostTextComponent,
@@ -29745,6 +30540,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
29745
30540
  </div>
29746
30541
  </ds-mobile-section>
29747
30542
 
30543
+ <!-- Services preview -->
30544
+ @if (previewVendors().length > 0) {
30545
+ <ds-mobile-section
30546
+ headline="Services"
30547
+ linkText="Se alle"
30548
+ contentGap="0px"
30549
+ (linkClick)="navigateToServices()">
30550
+ @for (vendor of previewVendors(); track vendor.id) {
30551
+ <ds-mobile-interactive-list-item-service
30552
+ [title]="vendor.name"
30553
+ [description]="vendor.description || ''"
30554
+ [logo]="vendor.logo || ''"
30555
+ (serviceClick)="openVendorSheet(vendor)"
30556
+ />
30557
+ }
30558
+ </ds-mobile-section>
30559
+ }
30560
+
29748
30561
  <!-- Recent Community Posts Section (empty state) -->
29749
30562
  <ds-mobile-section>
29750
30563
  <div class="empty-state">
@@ -29802,7 +30615,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
29802
30615
  </ds-mobile-page-main>
29803
30616
  } <!-- end @if (!isCoveringScreen()) -->
29804
30617
 
29805
- `, styles: [".posts-list,.messages-preview-list{display:flex;flex-direction:column}.property-banner-nav{display:block;width:100%;border-radius:12px;cursor:pointer;-webkit-tap-highlight-color:transparent}.property-banner-nav:focus-visible{outline:2px solid var(--color-accent, #6B5FF5);outline-offset:2px}.inquiries-list{display:flex;flex-direction:column}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center}.empty-state ds-button{display:block;margin-top:16px}.empty-state ds-button::ng-deep .btn{width:100%;border-radius:9999px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}@keyframes slideDown{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.welcome-toast{padding:10px 14px;border-radius:12px;background:var(--color-background-brand-secondary, #EEF0FF);display:flex;align-items:flex-start;gap:10px;font-size:14px;font-weight:500;color:var(--color-accent, #6B5FF5);animation:slideDown .2s ease-out}.toast-icon{width:20px;height:20px;border-radius:50%;background:var(--color-accent, #6B5FF5);display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff;margin-top:1px}.welcome-toast-content{flex:1;display:flex;flex-direction:column;gap:2px}.welcome-toast-heading{font-family:Brockmann,sans-serif;font-size:14px;font-weight:600;color:var(--color-brand-content, #3B3691);margin:0}.welcome-toast-text{font-family:Brockmann,sans-serif;font-size:13px;line-height:1.4;color:var(--color-brand-content, #3B3691);margin:0;opacity:.8}.welcome-toast-text strong{font-weight:600;opacity:1}.toast-dismiss{margin-left:auto;background:none;border:none;cursor:pointer;flex-shrink:0;color:var(--color-accent, #6B5FF5);display:flex;align-items:center;justify-content:center}.home-content--animating{animation:homeReveal .3s var(--spring-curve-smooth) both}@keyframes homeReveal{0%{opacity:0;transform:translateY(128px)}to{opacity:1;transform:translateY(0)}}\n"] }]
30618
+ `, styles: [".posts-list,.messages-preview-list{display:flex;flex-direction:column}.property-banner-nav{display:block;width:100%;border-radius:12px;cursor:pointer;-webkit-tap-highlight-color:transparent}.property-banner-nav:focus-visible{outline:2px solid var(--color-accent, #6B5FF5);outline-offset:2px}.inquiries-list,.services-preview-list{display:flex;flex-direction:column}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center}.empty-state ds-button{display:block;margin-top:16px}.empty-state ds-button::ng-deep .btn{width:100%;border-radius:9999px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}@keyframes slideDown{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.welcome-toast{padding:10px 14px;border-radius:12px;background:var(--color-background-brand-secondary, #EEF0FF);display:flex;align-items:flex-start;gap:10px;font-size:14px;font-weight:500;color:var(--color-accent, #6B5FF5);animation:slideDown .2s ease-out}.toast-icon{width:20px;height:20px;border-radius:50%;background:var(--color-accent, #6B5FF5);display:flex;align-items:center;justify-content:center;flex-shrink:0;color:#fff;margin-top:1px}.welcome-toast-content{flex:1;display:flex;flex-direction:column;gap:2px}.welcome-toast-heading{font-family:Brockmann,sans-serif;font-size:14px;font-weight:600;color:var(--color-brand-content, #3B3691);margin:0}.welcome-toast-text{font-family:Brockmann,sans-serif;font-size:13px;line-height:1.4;color:var(--color-brand-content, #3B3691);margin:0;opacity:.8}.welcome-toast-text strong{font-weight:600;opacity:1}.toast-dismiss{margin-left:auto;background:none;border:none;cursor:pointer;flex-shrink:0;color:var(--color-accent, #6B5FF5);display:flex;align-items:center;justify-content:center}.home-content--animating{animation:homeReveal .3s var(--spring-curve-smooth) both}@keyframes homeReveal{0%{opacity:0;transform:translateY(128px)}to{opacity:1;transform:translateY(0)}}\n"] }]
29806
30619
  }], ctorParameters: () => [{ type: i1$3.Router }, { type: i1.NavController }, { type: UserService }, { type: PostsService }, { type: DsMobilePostDetailModalService }, { type: TrackingPermissionService }, { type: DsMobileBottomSheetService }, { type: FamilyAccessService }, { type: PeerMessagingService }, { type: PeerChatLauncherService }], propDecorators: { pageComponent: [{
29807
30620
  type: ViewChild,
29808
30621
  args: ['pageComponent']
@@ -29813,6 +30626,7 @@ class MobileInquiriesPageComponent {
29813
30626
  navCtrl;
29814
30627
  newInquiryModal;
29815
30628
  pageComponent;
30629
+ inquiriesService = inject(InquiriesService);
29816
30630
  constructor(userService, navCtrl, newInquiryModal) {
29817
30631
  this.userService = userService;
29818
30632
  this.navCtrl = navCtrl;
@@ -29824,52 +30638,13 @@ class MobileInquiriesPageComponent {
29824
30638
  { id: 'open', label: 'Åben' },
29825
30639
  { id: 'closed', label: 'Lukket' }
29826
30640
  ];
29827
- inquiries = signal([
29828
- {
29829
- id: '1',
29830
- title: 'Tørretumbler virker ikke',
29831
- description: 'I de sidste tre dage har jeg oplevet vedvarende problemer med tørretumbleren. Den starter, men stopper efter få minutter.',
29832
- status: 'open',
29833
- timestamp: '12 dage siden',
29834
- category: 'appliance'
29835
- },
29836
- {
29837
- id: '2',
29838
- title: 'Problem med vandtryk',
29839
- description: 'Lavt vandtryk i badeværelseshåndvasken. Det er blevet gradvist værre i løbet af den sidste uge.',
29840
- status: 'open',
29841
- timestamp: '5 dage siden',
29842
- category: 'plumbing'
29843
- },
29844
- {
29845
- id: '3',
29846
- title: 'Varme virker ikke ordentligt',
29847
- description: 'Varmesystemet holder ikke den indstillede temperatur. Lejligheden er meget koldere, end den burde være.',
29848
- status: 'closed',
29849
- timestamp: '2 måneder siden',
29850
- category: 'heating'
29851
- }
29852
- ], ...(ngDevMode ? [{ debugName: "inquiries" }] : []));
29853
- // Computed signals that automatically update when dependencies change
29854
30641
  filteredInquiries = computed(() => {
29855
- const all = this.inquiries();
30642
+ const all = this.inquiriesService.inquiries();
29856
30643
  const status = this.filterStatus();
29857
- if (status === 'all') {
30644
+ if (status === 'all')
29858
30645
  return all;
29859
- }
29860
- else if (status === 'open') {
29861
- return all.filter(i => i.status === 'open');
29862
- }
29863
- else {
29864
- return all.filter(i => i.status === 'closed');
29865
- }
30646
+ return all.filter(i => i.status === status);
29866
30647
  }, ...(ngDevMode ? [{ debugName: "filteredInquiries" }] : []));
29867
- openInquiries = computed(() => {
29868
- return this.inquiries().filter(i => i.status === 'open');
29869
- }, ...(ngDevMode ? [{ debugName: "openInquiries" }] : []));
29870
- closedInquiries = computed(() => {
29871
- return this.inquiries().filter(i => i.status === 'closed');
29872
- }, ...(ngDevMode ? [{ debugName: "closedInquiries" }] : []));
29873
30648
  setFilter(status) {
29874
30649
  this.filterStatus.set(status);
29875
30650
  }
@@ -29908,16 +30683,14 @@ class MobileInquiriesPageComponent {
29908
30683
  console.log('New inquiry submitted:', data);
29909
30684
  // In a real app, call your API to create the inquiry
29910
30685
  // await this.inquiryService.createInquiry(data);
29911
- // Add the new inquiry to the list (mock for now)
29912
- const newInquiry = {
30686
+ this.inquiriesService.addInquiry({
29913
30687
  id: `inquiry-${Date.now()}`,
29914
30688
  title: data.title,
29915
30689
  description: data.description,
29916
30690
  status: 'open',
29917
- timestamp: 'Just now',
29918
- category: 'other'
29919
- };
29920
- this.inquiries.update(inquiries => [newInquiry, ...inquiries]);
30691
+ timestamp: 'Lige nu',
30692
+ category: data.category || 'other',
30693
+ });
29921
30694
  // Close the modal
29922
30695
  await this.newInquiryModal.close();
29923
30696
  }
@@ -30086,12 +30859,25 @@ class MobileInquiryDetailPageComponent {
30086
30859
  userService;
30087
30860
  lightbox;
30088
30861
  chatModal;
30862
+ route = inject(ActivatedRoute);
30863
+ inquiriesService = inject(InquiriesService);
30089
30864
  inquiryTitle = 'Tørretumbler virker ikke';
30865
+ inquiryDescription = 'I de sidste tre dage har vi oplevet vedvarende problemer med tørretumbleren i vores lejlighed. På trods af at vi følger betjeningsvejledningen, fejler maskinen konsekvent i at fuldføre sine tørrecyklusser.';
30866
+ inquiryCategory = 'Husholdningsapparater';
30867
+ inquiryTimestamp = '22. feb 2025';
30868
+ vendorName = '';
30869
+ vendorInitials = '';
30870
+ vendorLogo = '';
30871
+ isServiceInquiry = false;
30090
30872
  activeTab = signal('details', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
30091
30873
  tabItems = [
30092
30874
  { id: 'details', label: 'Detaljer' },
30093
30875
  { id: 'messages', label: 'Beskeder', badge: 0 }
30094
30876
  ];
30877
+ serviceMessageThread = [];
30878
+ get activeMessages() {
30879
+ return this.isServiceInquiry ? this.serviceMessageThread : this.messageThreads;
30880
+ }
30095
30881
  messageThreads = [
30096
30882
  {
30097
30883
  id: '1',
@@ -30114,16 +30900,13 @@ class MobileInquiryDetailPageComponent {
30114
30900
  unread: false
30115
30901
  }
30116
30902
  ];
30117
- unreadMessagesCount = computed(() => {
30118
- const count = this.messageThreads.length;
30119
- // Update badge in tab items
30903
+ updateMessagesBadge() {
30904
+ const count = this.activeMessages.length;
30120
30905
  const messagesTab = this.tabItems.find(t => t.id === 'messages');
30121
30906
  if (messagesTab) {
30122
30907
  messagesTab.badge = count;
30123
30908
  }
30124
- return count;
30125
- }, ...(ngDevMode ? [{ debugName: "unreadMessagesCount" }] : []));
30126
- // Photos for lightbox
30909
+ }
30127
30910
  photos = [
30128
30911
  { type: 'image', src: '/Assets/Dummy-photos/handyman.jpg', alt: 'Handyman', title: 'Handyman' },
30129
30912
  { type: 'image', src: '/Assets/Dummy-photos/balcony-view.jpg', alt: 'Balcony view', title: 'Balcony view' },
@@ -30131,7 +30914,6 @@ class MobileInquiryDetailPageComponent {
30131
30914
  { type: 'image', src: '/Assets/Dummy-photos/yard.jpg', alt: 'Yard', title: 'Yard' },
30132
30915
  { type: 'image', src: '/Assets/Dummy-photos/mailboxes.jpg', alt: 'Mailboxes', title: 'Mailboxes' }
30133
30916
  ];
30134
- // Photo URLs for inline-photo component
30135
30917
  get photoUrls() {
30136
30918
  return this.photos.map(photo => photo.src);
30137
30919
  }
@@ -30139,16 +30921,48 @@ class MobileInquiryDetailPageComponent {
30139
30921
  this.userService = userService;
30140
30922
  this.lightbox = lightbox;
30141
30923
  this.chatModal = chatModal;
30142
- // Trigger initial badge update
30143
- this.unreadMessagesCount();
30924
+ this.updateMessagesBadge();
30925
+ }
30926
+ ngOnInit() {
30927
+ const id = this.route.snapshot.paramMap.get('id');
30928
+ if (id) {
30929
+ const inquiry = this.inquiriesService.getById(id);
30930
+ if (inquiry) {
30931
+ this.inquiryTitle = inquiry.title;
30932
+ this.inquiryDescription = inquiry.description;
30933
+ this.inquiryCategory = inquiry.category;
30934
+ this.inquiryTimestamp = inquiry.timestamp;
30935
+ if (inquiry.vendorName) {
30936
+ this.isServiceInquiry = true;
30937
+ this.vendorName = inquiry.vendorName;
30938
+ this.vendorInitials = inquiry.vendorName
30939
+ .split(/\s+/)
30940
+ .filter(w => w.length > 0)
30941
+ .slice(0, 2)
30942
+ .map(w => w[0].toUpperCase())
30943
+ .join('');
30944
+ this.vendorLogo = inquiry.vendorLogo || '';
30945
+ this.serviceMessageThread = [
30946
+ {
30947
+ id: 'service-msg-1',
30948
+ senderName: this.userService.displayName() || this.userService.avatarInitials(),
30949
+ senderAvatar: '',
30950
+ senderInitials: this.userService.avatarInitials(),
30951
+ message: inquiry.description,
30952
+ role: 'Beboer',
30953
+ timestamp: inquiry.timestamp,
30954
+ unread: false,
30955
+ },
30956
+ ];
30957
+ }
30958
+ }
30959
+ }
30960
+ this.updateMessagesBadge();
30144
30961
  }
30145
30962
  setActiveTab(tabId) {
30146
30963
  this.activeTab.set(tabId);
30147
30964
  }
30148
- goBack() {
30149
- // Navigation is handled by ds-mobile-page-details component
30150
- // This is just for any custom logic if needed
30151
- }
30965
+ goBack() { }
30152
30966
  handleRefresh(event) {
30153
30967
  console.log('Pull-to-refresh triggered');
30154
30968
  setTimeout(() => {
@@ -30156,30 +30970,21 @@ class MobileInquiryDetailPageComponent {
30156
30970
  event.target.complete();
30157
30971
  }, 1000);
30158
30972
  }
30159
- /**
30160
- * Check if there are unread messages
30161
- */
30162
30973
  hasUnreadMessages() {
30163
- return this.messageThreads.some(m => m.unread);
30974
+ return !this.isServiceInquiry && this.messageThreads.some(m => m.unread);
30164
30975
  }
30165
- /**
30166
- * Navigate to messages tab when banner is clicked
30167
- */
30168
30976
  navigateToMessagesTab() {
30169
30977
  this.setActiveTab('messages');
30170
30978
  }
30171
30979
  async openMessage(messageId) {
30172
- console.log('Opening message:', messageId);
30173
- // Find the message thread
30174
- const messageThread = this.messageThreads.find(m => m.id === messageId);
30175
- if (!messageThread) {
30176
- console.error('Message thread not found:', messageId);
30980
+ if (this.isServiceInquiry) {
30981
+ await this.openVendorChat();
30177
30982
  return;
30178
30983
  }
30179
- // Check if this is an empty state chat (no timestamp and system message)
30984
+ const messageThread = this.messageThreads.find(m => m.id === messageId);
30985
+ if (!messageThread)
30986
+ return;
30180
30987
  const isEmptyChat = messageThread.message.includes('har overtaget din henvendelse') && !messageThread.timestamp;
30181
- // Prepare chat modal data
30182
- // In a real app, you would fetch the actual messages from your API
30183
30988
  const chatData = {
30184
30989
  participant: {
30185
30990
  id: messageId,
@@ -30189,14 +30994,13 @@ class MobileInquiryDetailPageComponent {
30189
30994
  avatarType: 'initials'
30190
30995
  },
30191
30996
  messages: isEmptyChat ? [] : [
30192
- // Day 1 - Yesterday morning (9:15 AM)
30193
30997
  {
30194
30998
  id: '1',
30195
30999
  content: 'Godmorgen! Jeg ville lige følge op på din henvendelse vedrørende vedligeholdelsesplanen.',
30196
31000
  senderId: messageId,
30197
31001
  senderName: messageThread.senderName,
30198
31002
  senderRole: messageThread.role,
30199
- timestamp: new Date(Date.now() - 86400000 - 32700000), // Yesterday 9:15 AM
31003
+ timestamp: new Date(Date.now() - 86400000 - 32700000),
30200
31004
  isOwnMessage: false,
30201
31005
  avatarInitials: messageThread.senderInitials,
30202
31006
  avatarType: 'initials',
@@ -30207,7 +31011,7 @@ class MobileInquiryDetailPageComponent {
30207
31011
  senderId: messageId,
30208
31012
  senderName: messageThread.senderName,
30209
31013
  senderRole: messageThread.role,
30210
- timestamp: new Date(Date.now() - 86400000 - 32520000), // Yesterday 9:18 AM (grouped with previous)
31014
+ timestamp: new Date(Date.now() - 86400000 - 32520000),
30211
31015
  isOwnMessage: false,
30212
31016
  avatarInitials: messageThread.senderInitials,
30213
31017
  avatarType: 'initials',
@@ -30217,7 +31021,7 @@ class MobileInquiryDetailPageComponent {
30217
31021
  content: 'Tak fordi du kiggede på det! Hvad fandt du?',
30218
31022
  senderId: 'current-user',
30219
31023
  senderName: 'You',
30220
- timestamp: new Date(Date.now() - 86400000 - 32100000), // Yesterday 9:25 AM (new group - 7 min gap)
31024
+ timestamp: new Date(Date.now() - 86400000 - 32100000),
30221
31025
  isOwnMessage: true,
30222
31026
  avatarInitials: this.userService.avatarInitials(),
30223
31027
  avatarType: 'initials',
@@ -30227,19 +31031,18 @@ class MobileInquiryDetailPageComponent {
30227
31031
  content: 'Kan du også sende mig vedligeholdelsesrapporten?',
30228
31032
  senderId: 'current-user',
30229
31033
  senderName: 'You',
30230
- timestamp: new Date(Date.now() - 86400000 - 31980000), // Yesterday 9:27 AM (grouped with previous)
31034
+ timestamp: new Date(Date.now() - 86400000 - 31980000),
30231
31035
  isOwnMessage: true,
30232
31036
  avatarInitials: this.userService.avatarInitials(),
30233
31037
  avatarType: 'initials',
30234
31038
  },
30235
- // Day 1 - Yesterday afternoon (2:30 PM - large time gap)
30236
31039
  {
30237
31040
  id: '5',
30238
31041
  content: messageThread.message,
30239
31042
  senderId: messageId,
30240
31043
  senderName: messageThread.senderName,
30241
31044
  senderRole: messageThread.role,
30242
- timestamp: new Date(Date.now() - 86400000 - 13800000), // Yesterday 2:30 PM (new group - 5 hour gap)
31045
+ timestamp: new Date(Date.now() - 86400000 - 13800000),
30243
31046
  isOwnMessage: false,
30244
31047
  avatarInitials: messageThread.senderInitials,
30245
31048
  avatarType: 'initials',
@@ -30250,18 +31053,17 @@ class MobileInquiryDetailPageComponent {
30250
31053
  senderId: messageId,
30251
31054
  senderName: messageThread.senderName,
30252
31055
  senderRole: messageThread.role,
30253
- timestamp: new Date(Date.now() - 86400000 - 13620000), // Yesterday 2:33 PM (grouped with previous)
31056
+ timestamp: new Date(Date.now() - 86400000 - 13620000),
30254
31057
  isOwnMessage: false,
30255
31058
  avatarInitials: messageThread.senderInitials,
30256
31059
  avatarType: 'initials',
30257
31060
  },
30258
- // Day 2 - Today morning (10:45 AM - new day)
30259
31061
  {
30260
31062
  id: '7',
30261
31063
  content: 'Perfekt! Jeg har gennemgået rapporten, og alt ser godt ud.',
30262
31064
  senderId: 'current-user',
30263
31065
  senderName: 'You',
30264
- timestamp: new Date(Date.now() - 7500000), // Today 10:45 AM (new group - new day)
31066
+ timestamp: new Date(Date.now() - 7500000),
30265
31067
  isOwnMessage: true,
30266
31068
  avatarInitials: this.userService.avatarInitials(),
30267
31069
  avatarType: 'initials',
@@ -30271,19 +31073,18 @@ class MobileInquiryDetailPageComponent {
30271
31073
  content: 'Hvornår kan vi planlægge vedligeholdelsesarbejdet?',
30272
31074
  senderId: 'current-user',
30273
31075
  senderName: 'You',
30274
- timestamp: new Date(Date.now() - 7320000), // Today 10:48 AM (grouped with previous)
31076
+ timestamp: new Date(Date.now() - 7320000),
30275
31077
  isOwnMessage: true,
30276
31078
  avatarInitials: this.userService.avatarInitials(),
30277
31079
  avatarType: 'initials',
30278
31080
  },
30279
- // Day 2 - Today (just now - 2 minutes ago)
30280
31081
  {
30281
31082
  id: '9',
30282
31083
  content: 'Dejligt at høre! Jeg kan planlægge det til næste tirsdag kl. 09.00. Passer det dig?',
30283
31084
  senderId: messageId,
30284
31085
  senderName: messageThread.senderName,
30285
31086
  senderRole: messageThread.role,
30286
- timestamp: new Date(Date.now() - 120000), // 2 minutes ago (new group - several hours gap)
31087
+ timestamp: new Date(Date.now() - 120000),
30287
31088
  isOwnMessage: false,
30288
31089
  avatarInitials: messageThread.senderInitials,
30289
31090
  avatarType: 'initials',
@@ -30294,7 +31095,7 @@ class MobileInquiryDetailPageComponent {
30294
31095
  senderId: messageId,
30295
31096
  senderName: messageThread.senderName,
30296
31097
  senderRole: messageThread.role,
30297
- timestamp: new Date(Date.now() - 60000), // 1 minute ago (grouped with previous)
31098
+ timestamp: new Date(Date.now() - 60000),
30298
31099
  isOwnMessage: false,
30299
31100
  avatarInitials: messageThread.senderInitials,
30300
31101
  avatarType: 'initials',
@@ -30305,7 +31106,37 @@ class MobileInquiryDetailPageComponent {
30305
31106
  currentUserAvatarType: 'initials',
30306
31107
  autoFocus: false
30307
31108
  };
30308
- // Open the chat modal
31109
+ await this.chatModal.open(chatData);
31110
+ }
31111
+ async openVendorChat() {
31112
+ const chatData = {
31113
+ participant: {
31114
+ id: 'vendor',
31115
+ name: this.vendorName,
31116
+ role: 'Leverandør',
31117
+ avatarInitials: this.vendorInitials,
31118
+ avatarType: this.vendorLogo ? 'photo' : 'initials',
31119
+ avatarSrc: this.vendorLogo,
31120
+ avatarShape: 'squircle',
31121
+ },
31122
+ messages: [
31123
+ {
31124
+ id: 'service-initial',
31125
+ content: this.inquiryDescription,
31126
+ senderId: 'current-user',
31127
+ senderName: 'You',
31128
+ timestamp: new Date(),
31129
+ isOwnMessage: true,
31130
+ avatarInitials: this.userService.avatarInitials(),
31131
+ avatarType: 'initials',
31132
+ },
31133
+ ],
31134
+ threadContext: 'peer',
31135
+ currentUserId: 'current-user',
31136
+ currentUserInitials: this.userService.avatarInitials(),
31137
+ currentUserAvatarType: 'initials',
31138
+ autoFocus: true,
31139
+ };
30309
31140
  await this.chatModal.open(chatData);
30310
31141
  }
30311
31142
  async openPhotoLightbox(index) {
@@ -30330,26 +31161,35 @@ class MobileInquiryDetailPageComponent {
30330
31161
 
30331
31162
  <!-- Messages Tab Content -->
30332
31163
  @if (activeTab() === 'messages') {
30333
- <ds-mobile-section contentGap="0">
30334
- @for (message of messageThreads; track message.id) {
30335
- <ds-mobile-interactive-list-item-message
30336
- [senderName]="message.senderName"
30337
- [senderRole]="message.role"
30338
- [timestamp]="message.timestamp"
30339
- [message]="message.message"
30340
- [avatarInitials]="message.senderInitials"
30341
- [showAvatarBadge]="true"
30342
- [unread]="message.unread"
30343
- (messageClick)="openMessage(message.id)">
30344
- </ds-mobile-interactive-list-item-message>
30345
- }
30346
- </ds-mobile-section>
31164
+ @if (activeMessages.length > 0) {
31165
+ <ds-mobile-section contentGap="0">
31166
+ @for (message of activeMessages; track message.id) {
31167
+ <ds-mobile-interactive-list-item-message
31168
+ [senderName]="message.senderName"
31169
+ [senderRole]="message.role"
31170
+ [timestamp]="message.timestamp"
31171
+ [message]="message.message"
31172
+ [avatarInitials]="message.senderInitials"
31173
+ [showAvatarBadge]="!isServiceInquiry"
31174
+ [unread]="message.unread"
31175
+ (messageClick)="openMessage(message.id)">
31176
+ </ds-mobile-interactive-list-item-message>
31177
+ }
31178
+ </ds-mobile-section>
31179
+ } @else {
31180
+ <ds-mobile-section>
31181
+ <div class="empty-messages">
31182
+ <img class="empty-messages-image" src="/Assets/Empty state-chat.png" alt="Ingen beskeder" />
31183
+ <p class="empty-messages-text">Ingen beskeder endnu</p>
31184
+ </div>
31185
+ </ds-mobile-section>
31186
+ }
30347
31187
  }
30348
31188
 
30349
31189
  <!-- Details Tab Content -->
30350
31190
  @if (activeTab() === 'details') {
30351
- <!-- Unread Messages Banner -->
30352
- @if (hasUnreadMessages()) {
31191
+ <!-- Unread Messages Banner (legacy only) -->
31192
+ @if (!isServiceInquiry && hasUnreadMessages()) {
30353
31193
  <ds-mobile-section>
30354
31194
  <ds-mobile-card-inline-banner
30355
31195
  [title]="'Du har ulæste beskeder'"
@@ -30360,41 +31200,57 @@ class MobileInquiryDetailPageComponent {
30360
31200
  </ds-mobile-section>
30361
31201
  }
30362
31202
 
30363
- <!-- All Details in One Section -->
30364
31203
  <ds-mobile-section contentGap="0">
30365
- <!-- Assignee -->
30366
- <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
30367
- <div content-leading>
30368
- <ds-avatar-with-badge
30369
- [size]="'sm'"
30370
- [type]="'initials'"
30371
- [initials]="'R'" />
30372
- </div>
30373
- <div content-main>
30374
- <div class="detail-label">Sagsbehandler</div>
30375
- <div class="detail-value">Ricki Meihlen</div>
30376
- </div>
30377
- </ds-mobile-list-item>
30378
-
30379
- <!-- Technician -->
30380
- <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
30381
- <div content-leading>
30382
- <ds-avatar-with-badge
30383
- [size]="'sm'"
30384
- [type]="'initials'"
30385
- [initials]="'M'" />
30386
- </div>
30387
- <div content-main>
30388
- <div class="detail-label">Tekniker</div>
30389
- <div class="detail-value">Martin Smith</div>
30390
- </div>
30391
- </ds-mobile-list-item>
31204
+ <!-- Vendor company (service inquiries) -->
31205
+ @if (isServiceInquiry && vendorName) {
31206
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
31207
+ <div content-leading>
31208
+ <ds-mobile-vendor-avatar
31209
+ [name]="vendorName"
31210
+ [logo]="vendorLogo"
31211
+ size="md" />
31212
+ </div>
31213
+ <div content-main>
31214
+ <div class="detail-label">Leverandør</div>
31215
+ <div class="detail-value">{{ vendorName }}</div>
31216
+ </div>
31217
+ </ds-mobile-list-item>
31218
+ }
31219
+
31220
+ <!-- Assignee + Technician (legacy inquiries only) -->
31221
+ @if (!isServiceInquiry) {
31222
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
31223
+ <div content-leading>
31224
+ <ds-avatar-with-badge
31225
+ [size]="'sm'"
31226
+ [type]="'initials'"
31227
+ [initials]="'R'" />
31228
+ </div>
31229
+ <div content-main>
31230
+ <div class="detail-label">Sagsbehandler</div>
31231
+ <div class="detail-value">Ricki Meihlen</div>
31232
+ </div>
31233
+ </ds-mobile-list-item>
31234
+
31235
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
31236
+ <div content-leading>
31237
+ <ds-avatar-with-badge
31238
+ [size]="'sm'"
31239
+ [type]="'initials'"
31240
+ [initials]="'M'" />
31241
+ </div>
31242
+ <div content-main>
31243
+ <div class="detail-label">Tekniker</div>
31244
+ <div class="detail-value">Martin Smith</div>
31245
+ </div>
31246
+ </ds-mobile-list-item>
31247
+ }
30392
31248
 
30393
31249
  <!-- Creation Date -->
30394
31250
  <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true" [align]="'center'">
30395
31251
  <ds-icon content-leading name="remixTimeLine" size="20px" color="tertiary" />
30396
31252
  <div content-main>
30397
- <div class="detail-value">22. feb 2025</div>
31253
+ <div class="detail-value">{{ inquiryTimestamp }}</div>
30398
31254
  </div>
30399
31255
  </ds-mobile-list-item>
30400
31256
 
@@ -30407,30 +31263,32 @@ class MobileInquiryDetailPageComponent {
30407
31263
  </ds-mobile-list-item>
30408
31264
 
30409
31265
  <!-- Description -->
30410
- <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="photoUrls.length > 0">
31266
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="!isServiceInquiry && photoUrls.length > 0">
30411
31267
  <ds-icon content-leading name="remixAlignLeft" size="20px" color="tertiary" />
30412
31268
  <div content-main style="display:flex;flex-direction:column;gap:8px">
30413
31269
  <div class="detail-value description-text">
30414
- I de sidste tre dage har vi oplevet vedvarende problemer med tørretumbleren i vores lejlighed. På trods af at vi følger betjeningsvejledningen, fejler maskinen konsekvent i at fuldføre sine tørrecyklusser.
31270
+ {{ inquiryDescription }}
30415
31271
  </div>
30416
- <ds-badge content="Husholdningsapparater" size="sm"/>
31272
+ <ds-badge [content]="inquiryCategory" size="sm"/>
30417
31273
  </div>
30418
31274
  </ds-mobile-list-item>
30419
31275
 
30420
- <!-- Photos -->
30421
- <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="false">
30422
- <ds-icon content-leading name="remixCameraLine" size="20px" color="tertiary" />
30423
- <div content-main>
30424
- <ds-mobile-inline-photo
30425
- [images]="photoUrls"
30426
- [useGrid]="false"
30427
- (photoClick)="openPhotoLightbox($event.index)" />
30428
- </div>
30429
- </ds-mobile-list-item>
31276
+ <!-- Photos (legacy inquiries only) -->
31277
+ @if (!isServiceInquiry) {
31278
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="false">
31279
+ <ds-icon content-leading name="remixCameraLine" size="20px" color="tertiary" />
31280
+ <div content-main>
31281
+ <ds-mobile-inline-photo
31282
+ [images]="photoUrls"
31283
+ [useGrid]="false"
31284
+ (photoClick)="openPhotoLightbox($event.index)" />
31285
+ </div>
31286
+ </ds-mobile-list-item>
31287
+ }
30430
31288
  </ds-mobile-section>
30431
31289
  }
30432
31290
  </ds-mobile-page-details>
30433
- `, isInline: true, styles: [".activity-list{display:flex;flex-direction:column;gap:12px;position:relative}.activity-list ds-mobile-list-item:not(:last-child) [content-leading]:after{content:\"\";position:absolute;top:40px;left:50%;transform:translate(-50%);width:1px;height:calc(100% - 2px);background:var(--border-color-default, #e5e5e5);z-index:0}.activity-icon-wrapper{width:100%;height:100%;border-radius:8px;background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;z-index:1}.avatar-wrapper{position:relative;display:flex;align-items:start;justify-content:center;flex-shrink:0;width:100%;height:100%;z-index:1}.avatar-badge{position:absolute;bottom:-6px;right:-6px;width:20px;height:20px;border-radius:8px;background:var(--color-brand-secondary, #5d5fef);display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge svg{width:10px;position:relative;top:1px;fill:#fff}.activity-content{display:flex;flex-direction:column;gap:4px}.activity-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0}.activity-title .actor-name{font-weight:600;color:var(--text-color-default-primary, #202227)}.activity-title .activity-text{color:var(--text-color-default-secondary, #545B66);font-weight:400}.activity-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0}.activity-timestamp{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373);display:flex;align-items:center;gap:4px;margin-top:2px}.detail-label{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373)}.detail-value{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:24px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227)}.detail-tag{display:inline-flex;align-items:center;padding:4px 12px;border-radius:12px;background:var(--color-background-neutral-secondary, #f5f5f5);font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--text-color-default-secondary, #525866);margin-top:4px;margin-bottom:10px;width:-moz-fit-content;width:fit-content}.photo-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:8px}.photo-add{width:100%;aspect-ratio:1;border-radius:12px;border:1px dashed var(--border-color-default, #e5e5e5);background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;cursor:pointer}.photo-item{width:100%;aspect-ratio:1;border-radius:12px;-o-object-fit:cover;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsMobilePageDetailsComponent, selector: "ds-mobile-page-details", inputs: ["title", "backRoute", "contentPadding", "tabs", "activeTab", "showRefresh", "scrollThreshold", "headerFadeDistance"], outputs: ["back", "tabChange", "refresh", "scroll"] }, { kind: "component", type: DsMobileInteractiveListItemMessageComponent, selector: "ds-mobile-interactive-list-item-message", inputs: ["senderName", "senderRole", "timestamp", "message", "avatarInitials", "avatarType", "avatarSrc", "unread", "clickable", "align", "showAvatarBadge", "groupStackMembers", "groupCustomAvatarUrl", "groupStackExcludeParticipantId"], outputs: ["messageClick", "longPress"] }, { kind: "component", type: DsMobileListItemComponent, selector: "ds-mobile-list-item", inputs: ["leadingSize", "variant", "align", "flushTop", "interactive", "disabled", "loading", "enableLongPress", "showDesktopMoreButton", "moreActions", "moreButtonAriaLabel", "interactiveOffset", "title", "subtitle", "showDivider", "dividerSpacing"], outputs: ["itemClick", "moreButtonClick"] }, { kind: "component", type: DsBadgeComponent, selector: "ds-badge", inputs: ["variant", "contentType", "content", "leadingIcon", "indicatorShape"] }, { kind: "component", type: DsMobileCardInlineBannerComponent, selector: "ds-mobile-card-inline-banner", inputs: ["title", "timestamp", "unreadCount", "layout"], outputs: ["bannerClick"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileInlinePhotoComponent, selector: "ds-mobile-inline-photo", inputs: ["images", "loadingStates", "author", "maxVisible", "useGrid"], outputs: ["photoClick"] }] });
31291
+ `, isInline: true, styles: [".activity-list{display:flex;flex-direction:column;gap:12px;position:relative}.activity-list ds-mobile-list-item:not(:last-child) [content-leading]:after{content:\"\";position:absolute;top:40px;left:50%;transform:translate(-50%);width:1px;height:calc(100% - 2px);background:var(--border-color-default, #e5e5e5);z-index:0}.activity-icon-wrapper{width:100%;height:100%;border-radius:8px;background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;z-index:1}.avatar-wrapper{position:relative;display:flex;align-items:start;justify-content:center;flex-shrink:0;width:100%;height:100%;z-index:1}.avatar-badge{position:absolute;bottom:-6px;right:-6px;width:20px;height:20px;border-radius:8px;background:var(--color-brand-secondary, #5d5fef);display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge svg{width:10px;position:relative;top:1px;fill:#fff}.activity-content{display:flex;flex-direction:column;gap:4px}.activity-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0}.activity-title .actor-name{font-weight:600;color:var(--text-color-default-primary, #202227)}.activity-title .activity-text{color:var(--text-color-default-secondary, #545B66);font-weight:400}.activity-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0}.activity-timestamp{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373);display:flex;align-items:center;gap:4px;margin-top:2px}.detail-label{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373)}.detail-value{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:24px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227)}.detail-tag{display:inline-flex;align-items:center;padding:4px 12px;border-radius:12px;background:var(--color-background-neutral-secondary, #f5f5f5);font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--text-color-default-secondary, #525866);margin-top:4px;margin-bottom:10px;width:-moz-fit-content;width:fit-content}.photo-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:8px}.photo-add{width:100%;aspect-ratio:1;border-radius:12px;border:1px dashed var(--border-color-default, #e5e5e5);background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;cursor:pointer}.photo-item{width:100%;aspect-ratio:1;border-radius:12px;-o-object-fit:cover;object-fit:cover}.empty-messages{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;gap:12px}.empty-messages-image{width:96px;height:96px;-o-object-fit:contain;object-fit:contain}.empty-messages-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);color:var(--text-color-default-secondary, #71727a);margin:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsMobileVendorAvatarComponent, selector: "ds-mobile-vendor-avatar", inputs: ["name", "logo", "size"] }, { kind: "component", type: DsMobilePageDetailsComponent, selector: "ds-mobile-page-details", inputs: ["title", "backRoute", "contentPadding", "tabs", "activeTab", "showRefresh", "scrollThreshold", "headerFadeDistance"], outputs: ["back", "tabChange", "refresh", "scroll"] }, { kind: "component", type: DsMobileInteractiveListItemMessageComponent, selector: "ds-mobile-interactive-list-item-message", inputs: ["senderName", "senderRole", "timestamp", "message", "avatarInitials", "avatarType", "avatarSrc", "unread", "clickable", "align", "showAvatarBadge", "groupStackMembers", "groupCustomAvatarUrl", "groupStackExcludeParticipantId"], outputs: ["messageClick", "longPress"] }, { kind: "component", type: DsMobileListItemComponent, selector: "ds-mobile-list-item", inputs: ["leadingSize", "variant", "align", "flushTop", "interactive", "disabled", "loading", "enableLongPress", "showDesktopMoreButton", "moreActions", "moreButtonAriaLabel", "interactiveOffset", "title", "subtitle", "showDivider", "dividerSpacing"], outputs: ["itemClick", "moreButtonClick"] }, { kind: "component", type: DsBadgeComponent, selector: "ds-badge", inputs: ["variant", "contentType", "content", "leadingIcon", "indicatorShape"] }, { kind: "component", type: DsMobileCardInlineBannerComponent, selector: "ds-mobile-card-inline-banner", inputs: ["title", "timestamp", "unreadCount", "layout"], outputs: ["bannerClick"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileInlinePhotoComponent, selector: "ds-mobile-inline-photo", inputs: ["images", "loadingStates", "author", "maxVisible", "useGrid"], outputs: ["photoClick"] }] });
30434
31292
  }
30435
31293
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MobileInquiryDetailPageComponent, decorators: [{
30436
31294
  type: Component,
@@ -30438,6 +31296,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
30438
31296
  CommonModule,
30439
31297
  DsIconComponent,
30440
31298
  DsAvatarWithBadgeComponent,
31299
+ DsMobileVendorAvatarComponent,
30441
31300
  DsMobilePageDetailsComponent,
30442
31301
  DsMobileInteractiveListItemMessageComponent,
30443
31302
  DsMobileListItemComponent,
@@ -30458,26 +31317,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
30458
31317
 
30459
31318
  <!-- Messages Tab Content -->
30460
31319
  @if (activeTab() === 'messages') {
30461
- <ds-mobile-section contentGap="0">
30462
- @for (message of messageThreads; track message.id) {
30463
- <ds-mobile-interactive-list-item-message
30464
- [senderName]="message.senderName"
30465
- [senderRole]="message.role"
30466
- [timestamp]="message.timestamp"
30467
- [message]="message.message"
30468
- [avatarInitials]="message.senderInitials"
30469
- [showAvatarBadge]="true"
30470
- [unread]="message.unread"
30471
- (messageClick)="openMessage(message.id)">
30472
- </ds-mobile-interactive-list-item-message>
30473
- }
30474
- </ds-mobile-section>
31320
+ @if (activeMessages.length > 0) {
31321
+ <ds-mobile-section contentGap="0">
31322
+ @for (message of activeMessages; track message.id) {
31323
+ <ds-mobile-interactive-list-item-message
31324
+ [senderName]="message.senderName"
31325
+ [senderRole]="message.role"
31326
+ [timestamp]="message.timestamp"
31327
+ [message]="message.message"
31328
+ [avatarInitials]="message.senderInitials"
31329
+ [showAvatarBadge]="!isServiceInquiry"
31330
+ [unread]="message.unread"
31331
+ (messageClick)="openMessage(message.id)">
31332
+ </ds-mobile-interactive-list-item-message>
31333
+ }
31334
+ </ds-mobile-section>
31335
+ } @else {
31336
+ <ds-mobile-section>
31337
+ <div class="empty-messages">
31338
+ <img class="empty-messages-image" src="/Assets/Empty state-chat.png" alt="Ingen beskeder" />
31339
+ <p class="empty-messages-text">Ingen beskeder endnu</p>
31340
+ </div>
31341
+ </ds-mobile-section>
31342
+ }
30475
31343
  }
30476
31344
 
30477
31345
  <!-- Details Tab Content -->
30478
31346
  @if (activeTab() === 'details') {
30479
- <!-- Unread Messages Banner -->
30480
- @if (hasUnreadMessages()) {
31347
+ <!-- Unread Messages Banner (legacy only) -->
31348
+ @if (!isServiceInquiry && hasUnreadMessages()) {
30481
31349
  <ds-mobile-section>
30482
31350
  <ds-mobile-card-inline-banner
30483
31351
  [title]="'Du har ulæste beskeder'"
@@ -30488,41 +31356,57 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
30488
31356
  </ds-mobile-section>
30489
31357
  }
30490
31358
 
30491
- <!-- All Details in One Section -->
30492
31359
  <ds-mobile-section contentGap="0">
30493
- <!-- Assignee -->
30494
- <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
30495
- <div content-leading>
30496
- <ds-avatar-with-badge
30497
- [size]="'sm'"
30498
- [type]="'initials'"
30499
- [initials]="'R'" />
30500
- </div>
30501
- <div content-main>
30502
- <div class="detail-label">Sagsbehandler</div>
30503
- <div class="detail-value">Ricki Meihlen</div>
30504
- </div>
30505
- </ds-mobile-list-item>
30506
-
30507
- <!-- Technician -->
30508
- <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
30509
- <div content-leading>
30510
- <ds-avatar-with-badge
30511
- [size]="'sm'"
30512
- [type]="'initials'"
30513
- [initials]="'M'" />
30514
- </div>
30515
- <div content-main>
30516
- <div class="detail-label">Tekniker</div>
30517
- <div class="detail-value">Martin Smith</div>
30518
- </div>
30519
- </ds-mobile-list-item>
31360
+ <!-- Vendor company (service inquiries) -->
31361
+ @if (isServiceInquiry && vendorName) {
31362
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
31363
+ <div content-leading>
31364
+ <ds-mobile-vendor-avatar
31365
+ [name]="vendorName"
31366
+ [logo]="vendorLogo"
31367
+ size="md" />
31368
+ </div>
31369
+ <div content-main>
31370
+ <div class="detail-label">Leverandør</div>
31371
+ <div class="detail-value">{{ vendorName }}</div>
31372
+ </div>
31373
+ </ds-mobile-list-item>
31374
+ }
31375
+
31376
+ <!-- Assignee + Technician (legacy inquiries only) -->
31377
+ @if (!isServiceInquiry) {
31378
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
31379
+ <div content-leading>
31380
+ <ds-avatar-with-badge
31381
+ [size]="'sm'"
31382
+ [type]="'initials'"
31383
+ [initials]="'R'" />
31384
+ </div>
31385
+ <div content-main>
31386
+ <div class="detail-label">Sagsbehandler</div>
31387
+ <div class="detail-value">Ricki Meihlen</div>
31388
+ </div>
31389
+ </ds-mobile-list-item>
31390
+
31391
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true">
31392
+ <div content-leading>
31393
+ <ds-avatar-with-badge
31394
+ [size]="'sm'"
31395
+ [type]="'initials'"
31396
+ [initials]="'M'" />
31397
+ </div>
31398
+ <div content-main>
31399
+ <div class="detail-label">Tekniker</div>
31400
+ <div class="detail-value">Martin Smith</div>
31401
+ </div>
31402
+ </ds-mobile-list-item>
31403
+ }
30520
31404
 
30521
31405
  <!-- Creation Date -->
30522
31406
  <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="true" [align]="'center'">
30523
31407
  <ds-icon content-leading name="remixTimeLine" size="20px" color="tertiary" />
30524
31408
  <div content-main>
30525
- <div class="detail-value">22. feb 2025</div>
31409
+ <div class="detail-value">{{ inquiryTimestamp }}</div>
30526
31410
  </div>
30527
31411
  </ds-mobile-list-item>
30528
31412
 
@@ -30535,30 +31419,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
30535
31419
  </ds-mobile-list-item>
30536
31420
 
30537
31421
  <!-- Description -->
30538
- <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="photoUrls.length > 0">
31422
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="!isServiceInquiry && photoUrls.length > 0">
30539
31423
  <ds-icon content-leading name="remixAlignLeft" size="20px" color="tertiary" />
30540
31424
  <div content-main style="display:flex;flex-direction:column;gap:8px">
30541
31425
  <div class="detail-value description-text">
30542
- I de sidste tre dage har vi oplevet vedvarende problemer med tørretumbleren i vores lejlighed. På trods af at vi følger betjeningsvejledningen, fejler maskinen konsekvent i at fuldføre sine tørrecyklusser.
31426
+ {{ inquiryDescription }}
30543
31427
  </div>
30544
- <ds-badge content="Husholdningsapparater" size="sm"/>
31428
+ <ds-badge [content]="inquiryCategory" size="sm"/>
30545
31429
  </div>
30546
31430
  </ds-mobile-list-item>
30547
31431
 
30548
- <!-- Photos -->
30549
- <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="false">
30550
- <ds-icon content-leading name="remixCameraLine" size="20px" color="tertiary" />
30551
- <div content-main>
30552
- <ds-mobile-inline-photo
30553
- [images]="photoUrls"
30554
- [useGrid]="false"
30555
- (photoClick)="openPhotoLightbox($event.index)" />
30556
- </div>
30557
- </ds-mobile-list-item>
31432
+ <!-- Photos (legacy inquiries only) -->
31433
+ @if (!isServiceInquiry) {
31434
+ <ds-mobile-list-item [leadingSize]="'32px'" [showDivider]="false">
31435
+ <ds-icon content-leading name="remixCameraLine" size="20px" color="tertiary" />
31436
+ <div content-main>
31437
+ <ds-mobile-inline-photo
31438
+ [images]="photoUrls"
31439
+ [useGrid]="false"
31440
+ (photoClick)="openPhotoLightbox($event.index)" />
31441
+ </div>
31442
+ </ds-mobile-list-item>
31443
+ }
30558
31444
  </ds-mobile-section>
30559
31445
  }
30560
31446
  </ds-mobile-page-details>
30561
- `, styles: [".activity-list{display:flex;flex-direction:column;gap:12px;position:relative}.activity-list ds-mobile-list-item:not(:last-child) [content-leading]:after{content:\"\";position:absolute;top:40px;left:50%;transform:translate(-50%);width:1px;height:calc(100% - 2px);background:var(--border-color-default, #e5e5e5);z-index:0}.activity-icon-wrapper{width:100%;height:100%;border-radius:8px;background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;z-index:1}.avatar-wrapper{position:relative;display:flex;align-items:start;justify-content:center;flex-shrink:0;width:100%;height:100%;z-index:1}.avatar-badge{position:absolute;bottom:-6px;right:-6px;width:20px;height:20px;border-radius:8px;background:var(--color-brand-secondary, #5d5fef);display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge svg{width:10px;position:relative;top:1px;fill:#fff}.activity-content{display:flex;flex-direction:column;gap:4px}.activity-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0}.activity-title .actor-name{font-weight:600;color:var(--text-color-default-primary, #202227)}.activity-title .activity-text{color:var(--text-color-default-secondary, #545B66);font-weight:400}.activity-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0}.activity-timestamp{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373);display:flex;align-items:center;gap:4px;margin-top:2px}.detail-label{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373)}.detail-value{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:24px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227)}.detail-tag{display:inline-flex;align-items:center;padding:4px 12px;border-radius:12px;background:var(--color-background-neutral-secondary, #f5f5f5);font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--text-color-default-secondary, #525866);margin-top:4px;margin-bottom:10px;width:-moz-fit-content;width:fit-content}.photo-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:8px}.photo-add{width:100%;aspect-ratio:1;border-radius:12px;border:1px dashed var(--border-color-default, #e5e5e5);background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;cursor:pointer}.photo-item{width:100%;aspect-ratio:1;border-radius:12px;-o-object-fit:cover;object-fit:cover}\n"] }]
31447
+ `, styles: [".activity-list{display:flex;flex-direction:column;gap:12px;position:relative}.activity-list ds-mobile-list-item:not(:last-child) [content-leading]:after{content:\"\";position:absolute;top:40px;left:50%;transform:translate(-50%);width:1px;height:calc(100% - 2px);background:var(--border-color-default, #e5e5e5);z-index:0}.activity-icon-wrapper{width:100%;height:100%;border-radius:8px;background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;z-index:1}.avatar-wrapper{position:relative;display:flex;align-items:start;justify-content:center;flex-shrink:0;width:100%;height:100%;z-index:1}.avatar-badge{position:absolute;bottom:-6px;right:-6px;width:20px;height:20px;border-radius:8px;background:var(--color-brand-secondary, #5d5fef);display:flex;align-items:center;justify-content:center;border:2px solid var(--color-background-primary, #ffffff)}.avatar-badge svg{width:10px;position:relative;top:1px;fill:#fff}.activity-content{display:flex;flex-direction:column;gap:4px}.activity-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227);margin:0}.activity-title .actor-name{font-weight:600;color:var(--text-color-default-primary, #202227)}.activity-title .activity-text{color:var(--text-color-default-secondary, #545B66);font-weight:400}.activity-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;color:var(--text-color-default-secondary, #545B66);margin:0}.activity-timestamp{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373);display:flex;align-items:center;gap:4px;margin-top:2px}.detail-label{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--text-color-default-tertiary, #737373)}.detail-value{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:24px;letter-spacing:-.3px;color:var(--text-color-default-primary, #202227)}.detail-tag{display:inline-flex;align-items:center;padding:4px 12px;border-radius:12px;background:var(--color-background-neutral-secondary, #f5f5f5);font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--text-color-default-secondary, #525866);margin-top:4px;margin-bottom:10px;width:-moz-fit-content;width:fit-content}.photo-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:8px}.photo-add{width:100%;aspect-ratio:1;border-radius:12px;border:1px dashed var(--border-color-default, #e5e5e5);background:var(--color-background-neutral-secondary, #f5f5f5);display:flex;align-items:center;justify-content:center;cursor:pointer}.photo-item{width:100%;aspect-ratio:1;border-radius:12px;-o-object-fit:cover;object-fit:cover}.empty-messages{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:60px 20px;gap:12px}.empty-messages-image{width:96px;height:96px;-o-object-fit:contain;object-fit:contain}.empty-messages-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm, 14px);color:var(--text-color-default-secondary, #71727a);margin:0}\n"] }]
30562
31448
  }], ctorParameters: () => [{ type: UserService }, { type: DsMobileLightboxService }, { type: DsMobileChatModalService }] });
30563
31449
 
30564
31450
  /**
@@ -31727,6 +32613,12 @@ class MobileTabsExampleComponent {
31727
32613
  icon: 'remixGroupLine',
31728
32614
  destructive: false,
31729
32615
  },
32616
+ {
32617
+ action: 'manage-admins',
32618
+ title: 'Fællesskabsadministrator',
32619
+ icon: 'remixUserStarLine',
32620
+ destructive: false,
32621
+ },
31730
32622
  ];
31731
32623
  if (this.trackingPermissionService.shouldShowSettingsReminder()) {
31732
32624
  accountActions.push({
@@ -31829,6 +32721,13 @@ class MobileTabsExampleComponent {
31829
32721
  iconActive: 'remixMessage3Fill',
31830
32722
  route: 'messages',
31831
32723
  },
32724
+ {
32725
+ id: 'services',
32726
+ label: 'Services',
32727
+ icon: 'remixServiceLine',
32728
+ iconActive: 'remixServiceFill',
32729
+ route: 'services',
32730
+ },
31832
32731
  ];
31833
32732
  /**
31834
32733
  * Profile menu items configuration.
@@ -31854,6 +32753,11 @@ class MobileTabsExampleComponent {
31854
32753
  animation: customPageTransition
31855
32754
  });
31856
32755
  }
32756
+ if (result.action === 'manage-admins') {
32757
+ this.navCtrl.navigateForward(['/community-admins'], {
32758
+ animation: customPageTransition
32759
+ });
32760
+ }
31857
32761
  // Handle appearance action here (opens modal)
31858
32762
  if (result.action === 'appearance') {
31859
32763
  console.log('Opening whitelabel demo...');
@@ -34533,12 +35437,15 @@ class FamilyAccessPageComponent {
34533
35437
  <ds-mobile-section>
34534
35438
  <div class="members-list">
34535
35439
  @for (member of service.members(); track member.id; let isFirst = $first; let isLast = $last) {
34536
- <ds-mobile-list-item [showDivider]="!isLast" [leadingSize]="'36px'" [flushTop]="isFirst">
35440
+ <ds-mobile-list-item [showDivider]="!isLast" [leadingSize]="'32px'" [flushTop]="isFirst">
34537
35441
 
34538
35442
  <div content-leading>
34539
- <div class="member-avatar member-avatar--{{ member.status }}">
34540
- {{ member.initials }}
34541
- </div>
35443
+ <ds-avatar-with-badge
35444
+ type="initials"
35445
+ [initials]="member.initials"
35446
+ size="md"
35447
+ [showBadge]="false"
35448
+ />
34542
35449
  </div>
34543
35450
 
34544
35451
  <div content-main class="member-details">
@@ -34581,7 +35488,7 @@ class FamilyAccessPageComponent {
34581
35488
  }
34582
35489
 
34583
35490
  </ds-mobile-page-details>
34584
- `, isInline: true, styles: [".empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}.empty-state ds-button{display:block;margin-top:16px}.empty-state ds-button::ng-deep .btn{width:100%;border-radius:9999px}.invite-cta{padding:8px 0 4px}.invite-cta ds-button{display:block;width:100%}.invite-cta ::ng-deep ds-button>button{width:100%;border-radius:9999px}.members-list{display:flex;flex-direction:column;gap:0}.member-avatar{width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:600}.member-avatar--active{background:var(--color-background-brand-secondary, #EEF0FF);color:var(--color-brand-secondary, #6B5FF5)}.member-avatar--pending{background:var(--color-background-warning-secondary, #FEF3C7);color:var(--color-warning-base, #d97706)}.member-avatar--expired{background:var(--color-background-error-secondary, #FEE2E2);color:var(--color-error-base, #dc2626)}.member-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.member-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.member-status-row{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.status-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}.status-dot--active{background:var(--color-success-base, #158452)}.status-dot--pending{background:var(--color-warning-base, #d97706)}.status-dot--expired{background:var(--color-error-base, #dc2626)}.member-trailing-action{display:flex;align-items:center}.member-trailing-action ds-icon-button::ng-deep button{box-sizing:border-box;width:2rem;height:2rem;min-width:2rem;border-radius:50%!important}@keyframes slideDown{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.success-toast{padding:10px 14px;border-radius:12px;background:var(--color-background-success-secondary, #DCFCE7);display:flex;align-items:center;gap:10px;font-size:14px;font-weight:500;color:var(--color-success-base, #158452);animation:slideDown .2s ease-out}.toast-icon{width:20px;height:20px;border-radius:50%;background:var(--color-success-base, #158452);display:flex;align-items:center;justify-content:center;flex-shrink:0}.toast-dismiss{margin-left:auto;background:none;border:none;cursor:pointer;flex-shrink:0}\n"], dependencies: [{ kind: "component", type: DsMobilePageDetailsComponent, selector: "ds-mobile-page-details", inputs: ["title", "backRoute", "contentPadding", "tabs", "activeTab", "showRefresh", "scrollThreshold", "headerFadeDistance"], outputs: ["back", "tabChange", "refresh", "scroll"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileIllustrationComponent, selector: "ds-mobile-illustration", inputs: ["variant", "size", "alt"] }, { kind: "component", type: DsMobileListItemComponent, selector: "ds-mobile-list-item", inputs: ["leadingSize", "variant", "align", "flushTop", "interactive", "disabled", "loading", "enableLongPress", "showDesktopMoreButton", "moreActions", "moreButtonAriaLabel", "interactiveOffset", "title", "subtitle", "showDivider", "dividerSpacing"], outputs: ["itemClick", "moreButtonClick"] }, { kind: "component", type: DsButtonComponent, selector: "ds-button", inputs: ["variant", "size", "disabled", "loading", "pressed", "expanded", "leadingIcon", "trailingIcon", "ariaLabel", "iconOnly"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }] });
35491
+ `, isInline: true, styles: [".empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}.empty-state ds-button{display:block;margin-top:16px}.empty-state ds-button::ng-deep .btn{width:100%;border-radius:9999px}.invite-cta{padding:8px 0 4px}.invite-cta ds-button{display:block;width:100%}.invite-cta ::ng-deep ds-button>button{width:100%;border-radius:9999px}.members-list{display:flex;flex-direction:column;gap:0}.member-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.member-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.member-status-row{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.status-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}.status-dot--active{background:var(--color-success-base, #158452)}.status-dot--pending{background:var(--color-warning-base, #d97706)}.status-dot--expired{background:var(--color-error-base, #dc2626)}.member-trailing-action{display:flex;align-items:center}.member-trailing-action ds-icon-button::ng-deep button{box-sizing:border-box;width:2rem;height:2rem;min-width:2rem;border-radius:50%!important}@keyframes slideDown{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.success-toast{padding:10px 14px;border-radius:12px;background:var(--color-background-success-secondary, #DCFCE7);display:flex;align-items:center;gap:10px;font-size:14px;font-weight:500;color:var(--color-success-base, #158452);animation:slideDown .2s ease-out}.toast-icon{width:20px;height:20px;border-radius:50%;background:var(--color-success-base, #158452);display:flex;align-items:center;justify-content:center;flex-shrink:0}.toast-dismiss{margin-left:auto;background:none;border:none;cursor:pointer;flex-shrink:0}\n"], dependencies: [{ kind: "component", type: DsMobilePageDetailsComponent, selector: "ds-mobile-page-details", inputs: ["title", "backRoute", "contentPadding", "tabs", "activeTab", "showRefresh", "scrollThreshold", "headerFadeDistance"], outputs: ["back", "tabChange", "refresh", "scroll"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileIllustrationComponent, selector: "ds-mobile-illustration", inputs: ["variant", "size", "alt"] }, { kind: "component", type: DsMobileListItemComponent, selector: "ds-mobile-list-item", inputs: ["leadingSize", "variant", "align", "flushTop", "interactive", "disabled", "loading", "enableLongPress", "showDesktopMoreButton", "moreActions", "moreButtonAriaLabel", "interactiveOffset", "title", "subtitle", "showDivider", "dividerSpacing"], outputs: ["itemClick", "moreButtonClick"] }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsButtonComponent, selector: "ds-button", inputs: ["variant", "size", "disabled", "loading", "pressed", "expanded", "leadingIcon", "trailingIcon", "ariaLabel", "iconOnly"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }] });
34585
35492
  }
34586
35493
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FamilyAccessPageComponent, decorators: [{
34587
35494
  type: Component,
@@ -34590,6 +35497,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
34590
35497
  DsMobileSectionComponent,
34591
35498
  DsMobileIllustrationComponent,
34592
35499
  DsMobileListItemComponent,
35500
+ DsAvatarWithBadgeComponent,
34593
35501
  DsButtonComponent,
34594
35502
  DsIconButtonComponent,
34595
35503
  ], template: `
@@ -34634,12 +35542,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
34634
35542
  <ds-mobile-section>
34635
35543
  <div class="members-list">
34636
35544
  @for (member of service.members(); track member.id; let isFirst = $first; let isLast = $last) {
34637
- <ds-mobile-list-item [showDivider]="!isLast" [leadingSize]="'36px'" [flushTop]="isFirst">
35545
+ <ds-mobile-list-item [showDivider]="!isLast" [leadingSize]="'32px'" [flushTop]="isFirst">
34638
35546
 
34639
35547
  <div content-leading>
34640
- <div class="member-avatar member-avatar--{{ member.status }}">
34641
- {{ member.initials }}
34642
- </div>
35548
+ <ds-avatar-with-badge
35549
+ type="initials"
35550
+ [initials]="member.initials"
35551
+ size="md"
35552
+ [showBadge]="false"
35553
+ />
34643
35554
  </div>
34644
35555
 
34645
35556
  <div content-main class="member-details">
@@ -34682,7 +35593,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
34682
35593
  }
34683
35594
 
34684
35595
  </ds-mobile-page-details>
34685
- `, styles: [".empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}.empty-state ds-button{display:block;margin-top:16px}.empty-state ds-button::ng-deep .btn{width:100%;border-radius:9999px}.invite-cta{padding:8px 0 4px}.invite-cta ds-button{display:block;width:100%}.invite-cta ::ng-deep ds-button>button{width:100%;border-radius:9999px}.members-list{display:flex;flex-direction:column;gap:0}.member-avatar{width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:600}.member-avatar--active{background:var(--color-background-brand-secondary, #EEF0FF);color:var(--color-brand-secondary, #6B5FF5)}.member-avatar--pending{background:var(--color-background-warning-secondary, #FEF3C7);color:var(--color-warning-base, #d97706)}.member-avatar--expired{background:var(--color-background-error-secondary, #FEE2E2);color:var(--color-error-base, #dc2626)}.member-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.member-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.member-status-row{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.status-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}.status-dot--active{background:var(--color-success-base, #158452)}.status-dot--pending{background:var(--color-warning-base, #d97706)}.status-dot--expired{background:var(--color-error-base, #dc2626)}.member-trailing-action{display:flex;align-items:center}.member-trailing-action ds-icon-button::ng-deep button{box-sizing:border-box;width:2rem;height:2rem;min-width:2rem;border-radius:50%!important}@keyframes slideDown{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.success-toast{padding:10px 14px;border-radius:12px;background:var(--color-background-success-secondary, #DCFCE7);display:flex;align-items:center;gap:10px;font-size:14px;font-weight:500;color:var(--color-success-base, #158452);animation:slideDown .2s ease-out}.toast-icon{width:20px;height:20px;border-radius:50%;background:var(--color-success-base, #158452);display:flex;align-items:center;justify-content:center;flex-shrink:0}.toast-dismiss{margin-left:auto;background:none;border:none;cursor:pointer;flex-shrink:0}\n"] }]
35596
+ `, styles: [".empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20px;text-align:center}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}.empty-state ds-button{display:block;margin-top:16px}.empty-state ds-button::ng-deep .btn{width:100%;border-radius:9999px}.invite-cta{padding:8px 0 4px}.invite-cta ds-button{display:block;width:100%}.invite-cta ::ng-deep ds-button>button{width:100%;border-radius:9999px}.members-list{display:flex;flex-direction:column;gap:0}.member-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.member-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.member-status-row{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373)}.status-dot{width:7px;height:7px;border-radius:50%;flex-shrink:0}.status-dot--active{background:var(--color-success-base, #158452)}.status-dot--pending{background:var(--color-warning-base, #d97706)}.status-dot--expired{background:var(--color-error-base, #dc2626)}.member-trailing-action{display:flex;align-items:center}.member-trailing-action ds-icon-button::ng-deep button{box-sizing:border-box;width:2rem;height:2rem;min-width:2rem;border-radius:50%!important}@keyframes slideDown{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}.success-toast{padding:10px 14px;border-radius:12px;background:var(--color-background-success-secondary, #DCFCE7);display:flex;align-items:center;gap:10px;font-size:14px;font-weight:500;color:var(--color-success-base, #158452);animation:slideDown .2s ease-out}.toast-icon{width:20px;height:20px;border-radius:50%;background:var(--color-success-base, #158452);display:flex;align-items:center;justify-content:center;flex-shrink:0}.toast-dismiss{margin-left:auto;background:none;border:none;cursor:pointer;flex-shrink:0}\n"] }]
34686
35597
  }] });
34687
35598
 
34688
35599
  class AcceptInvitePageComponent {
@@ -35105,6 +36016,228 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
35105
36016
  `, styles: [".empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:64px 20px;text-align:center}.empty-state-image{width:96px;height:96px;margin-bottom:24px;opacity:.4}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}\n"] }]
35106
36017
  }] });
35107
36018
 
36019
+ const DEFAULT_SERVICE_PAGE_LABELS = {
36020
+ pageTitle: 'Services',
36021
+ emptyState: 'Ingen services tilknyttet',
36022
+ emptyStateDescription: 'Der er ingen serviceaftaler knyttet til din ejendom endnu.',
36023
+ };
36024
+ function stripHtml(html) {
36025
+ const div = document.createElement('div');
36026
+ div.innerHTML = html;
36027
+ return div.textContent?.trim() || '';
36028
+ }
36029
+ const MOCK_VENDORS = [
36030
+ {
36031
+ id: 'v-1',
36032
+ name: 'CleanTeam ApS',
36033
+ category: 'Rengøring',
36034
+ description: 'Trappevask og vinduespolering',
36035
+ phone: '+45 70 20 30 40',
36036
+ logo: '/Assets/dummy-logos/cleanteam-logo.svg',
36037
+ thumbnail: '/Assets/Dummy-photos/clean-team.jpg',
36038
+ fullDescription: '<h3>Rengøring</h3><p>CleanTeam ApS tilbyder professionel trappevask og vinduespolering for ejendommen. Servicen udføres ugentligt og kan tilpasses jeres behov.</p><h3>Pris</h3><p>350 kr. per besøg</p>',
36039
+ price: '350 kr. per besøg',
36040
+ availabilityStatus: 'available-today',
36041
+ statusLabel: 'Ledig i dag',
36042
+ },
36043
+ {
36044
+ id: 'v-2',
36045
+ name: 'Nordisk Rengøring',
36046
+ category: 'Rengøring',
36047
+ description: 'Erhvervs- og boligrengøring',
36048
+ logo: '/Assets/dummy-logos/nordiccleaning-logo.svg',
36049
+ thumbnail: '/Assets/Dummy-photos/nordic-cleaning.jpg',
36050
+ heroImage: '/Assets/Dummy-photos/nordic-cleaning.jpg',
36051
+ fullDescription: '<h3>Rengøring</h3><p>Nordisk Rengøring leverer fleksibel erhvervs- og boligrengøring. Vi tilpasser rengøringen til jeres specifikke behov.</p><h3>Pris</h3><p>275 kr. per time</p>',
36052
+ price: '275 kr. per time',
36053
+ availabilityStatus: 'available-from',
36054
+ statusLabel: 'Ledig fra 5. maj',
36055
+ },
36056
+ {
36057
+ id: 'v-3',
36058
+ name: 'Blik Partner A/S',
36059
+ category: 'VVS',
36060
+ description: 'VVS-service og akut udkald',
36061
+ phone: '+45 33 44 55 66',
36062
+ thumbnail: '/Assets/Dummy-photos/plumbing.jpg',
36063
+ fullDescription: '<h3>VVS</h3><p>BlikPartner A/S er jeres VVS-partner til alt fra løbende vedligeholdelse til akutte udkald. Vi dækker reparation af vandrør, afløb, radiatorer og blandingsbatterier.</p><h3>Pris</h3><p>450 kr. per udkald + tid</p>',
36064
+ price: '450 kr. per udkald + tid',
36065
+ availabilityStatus: 'available-today',
36066
+ statusLabel: 'Ledig i dag',
36067
+ },
36068
+ {
36069
+ id: 'v-4',
36070
+ name: 'ElektroTek ApS',
36071
+ category: 'Elektriker',
36072
+ description: 'El-installationer og fejlsøgning',
36073
+ phone: '+45 23 45 67 89',
36074
+ logo: '/Assets/dummy-logos/electrician-logo.svg',
36075
+ thumbnail: '/Assets/Dummy-photos/electrician.jpg',
36076
+ heroImage: '/Assets/Dummy-photos/electrician.jpg',
36077
+ fullDescription: '<h3>Elektriker</h3><p>ElektroTek ApS varetager el-installationer, fejlsøgning og lovpligtige eftersyn for ejendommen. Vi udfører også småopgaver som udskiftning af kontakter og lampeudtag.</p><h3>Pris</h3><p>395 kr. per time</p>',
36078
+ price: '395 kr. per time',
36079
+ availabilityStatus: 'available-today',
36080
+ statusLabel: 'Ledig i dag',
36081
+ },
36082
+ {
36083
+ id: 'v-5',
36084
+ name: 'HaveService Danmark',
36085
+ category: 'Have & Grønne arealer',
36086
+ description: 'Pleje af fællesarealer og haver',
36087
+ logo: '/Assets/dummy-logos/gardener-logo.svg',
36088
+ thumbnail: '/Assets/Dummy-photos/gardener.jpg',
36089
+ heroImage: '/Assets/Dummy-photos/gardener.jpg',
36090
+ fullDescription: '<h3>Have & Grønne arealer</h3><p>HaveService Danmark står for den løbende pleje af fællesarealer og haver — herunder græsslåning, hækklipning, ukrudtsbekæmpelse og sæsonbeplantning.</p><h3>Pris</h3><p>500 kr. per besøg</p>',
36091
+ price: '500 kr. per besøg',
36092
+ availabilityStatus: 'unavailable',
36093
+ statusLabel: 'Ikke tilgængelig',
36094
+ },
36095
+ ];
36096
+ class ServicesPageComponent {
36097
+ pageComponent;
36098
+ vendorModal = inject(DsMobileServiceVendorModalService);
36099
+ newInquiryModal = inject(DsMobileNewInquiryModalService);
36100
+ inquiriesService = inject(InquiriesService);
36101
+ navCtrl = inject(NavController);
36102
+ userService = inject(UserService);
36103
+ lbl = { ...DEFAULT_SERVICE_PAGE_LABELS };
36104
+ vendors = signal(MOCK_VENDORS, ...(ngDevMode ? [{ debugName: "vendors" }] : []));
36105
+ stripHtml = stripHtml;
36106
+ async openVendorSheet(vendor) {
36107
+ const modal = await this.vendorModal.open({
36108
+ vendorName: vendor.name,
36109
+ vendorDescription: vendor.fullDescription || vendor.description || '',
36110
+ vendorImage: vendor.heroImage || '',
36111
+ vendorLogo: vendor.logo,
36112
+ });
36113
+ const result = await modal.onWillDismiss();
36114
+ if (result.role === 'book') {
36115
+ await this.openInquiryForVendor(vendor);
36116
+ }
36117
+ }
36118
+ async openInquiryForVendor(vendor) {
36119
+ await this.newInquiryModal.open({
36120
+ titlePlaceholder: 'Emne for henvendelsen',
36121
+ descriptionPlaceholder: 'Beskriv hvad du har brug for…',
36122
+ submitButtonLabel: 'Send henvendelse',
36123
+ category: vendor.category,
36124
+ onSubmit: async (data) => {
36125
+ const inquiryId = `service-${Date.now()}`;
36126
+ this.inquiriesService.addInquiry({
36127
+ id: inquiryId,
36128
+ title: data.title,
36129
+ description: data.description,
36130
+ status: 'open',
36131
+ timestamp: 'Lige nu',
36132
+ category: data.category || vendor.category,
36133
+ vendorName: vendor.name,
36134
+ vendorLogo: vendor.logo,
36135
+ });
36136
+ await this.newInquiryModal.close();
36137
+ setTimeout(() => {
36138
+ this.navCtrl.navigateForward([`/inquiry-detail/${inquiryId}`], {
36139
+ animation: customPageTransition,
36140
+ });
36141
+ }, 300);
36142
+ },
36143
+ });
36144
+ }
36145
+ handleRefresh(event) {
36146
+ setTimeout(() => {
36147
+ event.target?.complete?.();
36148
+ }, 1000);
36149
+ }
36150
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ServicesPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
36151
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ServicesPageComponent, isStandalone: true, selector: "app-services-page", viewQueries: [{ propertyName: "pageComponent", first: true, predicate: ["pageComponent"], descendants: true }], ngImport: i0, template: `
36152
+ <ds-mobile-page-main
36153
+ #pageComponent
36154
+ [title]="lbl.pageTitle"
36155
+ [avatarInitials]="userService.avatarInitials()"
36156
+ [avatarType]="userService.avatarType()"
36157
+ (refresh)="handleRefresh($event)"
36158
+ >
36159
+ @if (pageComponent.isOffline()) {
36160
+ <ds-mobile-offline-banner
36161
+ offline-indicator
36162
+ title="Ingen internetforbindelse"
36163
+ message="Nogle funktioner kan være utilgængelige"
36164
+ />
36165
+ }
36166
+
36167
+ @if (vendors().length === 0) {
36168
+ <ds-mobile-section>
36169
+ <div class="empty-state">
36170
+ <ds-mobile-illustration variant="inquiry" [alt]="lbl.emptyState" />
36171
+ <h3 class="empty-state-title">{{ lbl.emptyState }}</h3>
36172
+ <p class="empty-state-description">{{ lbl.emptyStateDescription }}</p>
36173
+ </div>
36174
+ </ds-mobile-section>
36175
+ } @else {
36176
+ <ds-mobile-section contentGap="0px">
36177
+ @for (vendor of vendors(); track vendor.id) {
36178
+ <ds-mobile-interactive-list-item-service
36179
+ [title]="vendor.name"
36180
+ [description]="stripHtml(vendor.fullDescription || vendor.description || '')"
36181
+ [logo]="vendor.logo || ''"
36182
+ (serviceClick)="openVendorSheet(vendor)"
36183
+ />
36184
+ }
36185
+ </ds-mobile-section>
36186
+ }
36187
+ </ds-mobile-page-main>
36188
+ `, isInline: true, styles: [".empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;text-align:center}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "firstEntry", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "contentPadding", "profileMenuItems"], outputs: ["avatarClick", "profileActionSelected", "refresh", "scroll"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileIllustrationComponent, selector: "ds-mobile-illustration", inputs: ["variant", "size", "alt"] }, { kind: "component", type: DsMobileInteractiveListItemServiceComponent, selector: "ds-mobile-interactive-list-item-service", inputs: ["title", "description", "logo", "showChevron"], outputs: ["serviceClick"] }, { kind: "component", type: DsMobileOfflineBannerComponent, selector: "ds-mobile-offline-banner", inputs: ["icon", "title", "message"] }] });
36189
+ }
36190
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ServicesPageComponent, decorators: [{
36191
+ type: Component,
36192
+ args: [{ selector: 'app-services-page', standalone: true, imports: [
36193
+ DsMobilePageMainComponent,
36194
+ DsMobileSectionComponent,
36195
+ DsMobileIllustrationComponent,
36196
+ DsMobileInteractiveListItemServiceComponent,
36197
+ DsMobileOfflineBannerComponent,
36198
+ ], template: `
36199
+ <ds-mobile-page-main
36200
+ #pageComponent
36201
+ [title]="lbl.pageTitle"
36202
+ [avatarInitials]="userService.avatarInitials()"
36203
+ [avatarType]="userService.avatarType()"
36204
+ (refresh)="handleRefresh($event)"
36205
+ >
36206
+ @if (pageComponent.isOffline()) {
36207
+ <ds-mobile-offline-banner
36208
+ offline-indicator
36209
+ title="Ingen internetforbindelse"
36210
+ message="Nogle funktioner kan være utilgængelige"
36211
+ />
36212
+ }
36213
+
36214
+ @if (vendors().length === 0) {
36215
+ <ds-mobile-section>
36216
+ <div class="empty-state">
36217
+ <ds-mobile-illustration variant="inquiry" [alt]="lbl.emptyState" />
36218
+ <h3 class="empty-state-title">{{ lbl.emptyState }}</h3>
36219
+ <p class="empty-state-description">{{ lbl.emptyStateDescription }}</p>
36220
+ </div>
36221
+ </ds-mobile-section>
36222
+ } @else {
36223
+ <ds-mobile-section contentGap="0px">
36224
+ @for (vendor of vendors(); track vendor.id) {
36225
+ <ds-mobile-interactive-list-item-service
36226
+ [title]="vendor.name"
36227
+ [description]="stripHtml(vendor.fullDescription || vendor.description || '')"
36228
+ [logo]="vendor.logo || ''"
36229
+ (serviceClick)="openVendorSheet(vendor)"
36230
+ />
36231
+ }
36232
+ </ds-mobile-section>
36233
+ }
36234
+ </ds-mobile-page-main>
36235
+ `, styles: [".empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 20px;text-align:center}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;color:var(--color-text-primary);margin-top:-16px;z-index:4}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);color:var(--color-text-secondary);margin:0}\n"] }]
36236
+ }], propDecorators: { pageComponent: [{
36237
+ type: ViewChild,
36238
+ args: ['pageComponent']
36239
+ }] } });
36240
+
35108
36241
  /**
35109
36242
  * Services Barrel File
35110
36243
  *
@@ -35128,5 +36261,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
35128
36261
  * Generated bundle index. Do not edit.
35129
36262
  */
35130
36263
 
35131
- export { AcceptInvitePageComponent, ActionCommentComponent, ActionLikeComponent, AvatarUploadPageComponent, BaseModalService, ContentRowComponent, CreateAccountPageComponent, DsAppIconComponent, DsAvatarWithBadgeComponent, DsLogoComponent, DsMobileAccessSheetComponent, DsMobileActionListItemComponent, DsMobileActionsBottomSheetComponent, DsMobileAddGroupTenantsModalComponent, DsMobileAppLoadingComponent, DsMobileAttachmentPreviewComponent, DsMobileBookingConfirmationWrapperComponent, DsMobileBookingModalComponent, DsMobileBookingModalService, DsMobileBookingSummaryComponent, DsMobileBottomSheetHeaderComponent, DsMobileBottomSheetService, DsMobileBottomSheetWrapperComponent, DsMobileCapacitySheetComponent, DsMobileCardInlineBannerComponent, DsMobileCardInlineComponent, DsMobileCardInlineContactComponent, DsMobileCardInlineFileComponent, DsMobileChatModalComponent, DsMobileChatModalService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileConfirmationSheetComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileCreateGroupModalComponent, DsMobileDropdownComponent, DsMobileEditGroupModalComponent, DsMobileEmptyStateComponent, DsMobileFabComponent, DsMobileFacilityArchiveConfirmationComponent, DsMobileFacilityCreationConfirmationWrapperComponent, DsMobileFacilityCreationModalComponent, DsMobileFacilityCreationModalService, DsMobileFacilityDeleteConfirmationComponent, DsMobileFacilityDetailModalComponent, DsMobileFacilityDetailModalService, DsMobileFileAttachmentComponent, DsMobileGroupAvatarStackComponent, DsMobileGroupMembersModalComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileIllustrationComponent, DsMobileImagePlaceholderComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemBookingComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileListSearchComponent, DsMobileLoaderOverlayComponent, DsMobileLongPressDirective, DsMobileMediaActionsPanelComponent, DsMobileMessageBubbleComponent, DsMobileMessageComposerComponent, DsMobileModalBaseComponent, DsMobileModalService, DsMobileNewInquiryModalComponent, DsMobileNewInquiryModalService, DsMobileOfflineBannerComponent, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobilePillComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobilePriceSheetComponent, DsMobileProfileActionsSheetComponent, DsMobilePromptBottomSheetComponent, DsMobilePropertyBannerComponent, DsMobileRichTextEditorComponent, DsMobileSectionComponent, DsMobileSwiperComponent, DsMobileSwiperWithNavComponent, DsMobileSystemMessageBannerComponent, DsMobileTabBarComponent, DsMobileTabsComponent, DsMobileTenantPickerModalComponent, DsMobileWhenCanBookSheetComponent, DsMobileWhoCanBookSheetComponent, DsTextInputComponent, FamilyAccessPageComponent, FamilyAccessService, InviteSuccessPageComponent, MediaPickerService, MobileBookingPageComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobileModalBase, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PageLoadingService, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, PostsService, SectionHeaderComponent, SignInPageComponent, SignInToAcceptPageComponent, TenantChatPageComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, TrackingPermissionService, UserService, WhitelabelDemoModalComponent, WhitelabelDemoModalService, WhitelabelService, customBackTransition, customPageTransition };
36264
+ export { AcceptInvitePageComponent, ActionCommentComponent, ActionLikeComponent, AvatarUploadPageComponent, BaseModalService, ContentRowComponent, CreateAccountPageComponent, DEFAULT_SERVICE_PAGE_LABELS, DsAppIconComponent, DsAvatarWithBadgeComponent, DsLogoComponent, DsMobileAccessSheetComponent, DsMobileActionListItemComponent, DsMobileActionsBottomSheetComponent, DsMobileAddGroupTenantsModalComponent, DsMobileAppLoadingComponent, DsMobileAttachmentPreviewComponent, DsMobileBookingConfirmationWrapperComponent, DsMobileBookingModalComponent, DsMobileBookingModalService, DsMobileBookingSummaryComponent, DsMobileBottomSheetHeaderComponent, DsMobileBottomSheetService, DsMobileBottomSheetWrapperComponent, DsMobileCapacitySheetComponent, DsMobileCardInlineBannerComponent, DsMobileCardInlineComponent, DsMobileCardInlineContactComponent, DsMobileCardInlineFileComponent, DsMobileChatModalComponent, DsMobileChatModalService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileCommunityAdminPickerComponent, DsMobileCommunityAdminsModalComponent, DsMobileConfirmationSheetComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileCreateGroupModalComponent, DsMobileDropdownComponent, DsMobileEditGroupModalComponent, DsMobileEmptyStateComponent, DsMobileFabComponent, DsMobileFacilityArchiveConfirmationComponent, DsMobileFacilityCreationConfirmationWrapperComponent, DsMobileFacilityCreationModalComponent, DsMobileFacilityCreationModalService, DsMobileFacilityDeleteConfirmationComponent, DsMobileFacilityDetailModalComponent, DsMobileFacilityDetailModalService, DsMobileFileAttachmentComponent, DsMobileGlassSpinnerComponent, DsMobileGroupAvatarStackComponent, DsMobileGroupMembersModalComponent, DsMobileHandbookDetailModalComponent, DsMobileHandbookDetailModalService, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileIllustrationComponent, DsMobileImagePlaceholderComponent, DsMobileInlinePhotoComponent, DsMobileInlineTabsComponent, DsMobileInteractiveListItemBookingComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileListItemStaticComponent, DsMobileListSearchComponent, DsMobileLoaderOverlayComponent, DsMobileLongPressDirective, DsMobileMediaActionsPanelComponent, DsMobileMessageBubbleComponent, DsMobileMessageComposerComponent, DsMobileModalBaseComponent, DsMobileModalService, DsMobileNewInquiryModalComponent, DsMobileNewInquiryModalService, DsMobileOfflineBannerComponent, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobilePillComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobilePriceSheetComponent, DsMobileProfileActionsSheetComponent, DsMobilePromptBottomSheetComponent, DsMobilePropertyBannerComponent, DsMobileRichTextEditorComponent, DsMobileSectionComponent, DsMobileServiceVendorModalService, DsMobileServiceVendorSheetComponent, DsMobileSwiperComponent, DsMobileSwiperWithNavComponent, DsMobileSystemMessageBannerComponent, DsMobileTabBarComponent, DsMobileTabsComponent, DsMobileTenantPickerModalComponent, DsMobileWhenCanBookSheetComponent, DsMobileWhoCanBookSheetComponent, DsTextInputComponent, FamilyAccessPageComponent, FamilyAccessService, InquiriesService, InviteSuccessPageComponent, MediaPickerService, MobileBookingPageComponent, MobileCommunityPageComponent, MobileHandbookPageComponent, MobileHomePageComponent, MobileInquiriesPageComponent, MobileInquiryDetailPageComponent, MobileModalBase, MobilePageBase, MobilePostDetailPageComponent, MobileTabsExampleComponent, PageLoadingService, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostCreatePageComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, PostsService, SectionHeaderComponent, ServicesPageComponent, SignInPageComponent, SignInToAcceptPageComponent, TenantChatPageComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent, TrackingPermissionService, UserService, WhitelabelDemoModalComponent, WhitelabelDemoModalService, WhitelabelService, customBackTransition, customPageTransition };
35132
36265
  //# sourceMappingURL=propbinder-mobile-design.mjs.map