@propbinder/mobile-design 0.3.34 → 0.3.35

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.
@@ -20,16 +20,16 @@ import { FilePicker } from '@capawesome/capacitor-file-picker';
20
20
  import { Subject, isObservable } from 'rxjs';
21
21
  import { createAnimation } from '@ionic/core';
22
22
  import { Share } from '@capacitor/share';
23
- import Swiper from 'swiper';
24
23
  import { Filesystem, Directory } from '@capacitor/filesystem';
24
+ import Swiper from 'swiper';
25
25
  import { Browser } from '@capacitor/browser';
26
26
  import { filter } from 'rxjs/operators';
27
27
  import { Pagination } from 'swiper/modules';
28
28
  import { AppTrackingTransparency } from 'capacitor-plugin-app-tracking-transparency';
29
29
 
30
30
  const DEFAULT_CONFIG = {
31
- logoUrl: '/Assets/logos/propbinder-logomark.svg',
32
- logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',
31
+ logoUrl: '/assets/logos/propbinder-logomark.svg',
32
+ logoMarkUrl: '/assets/logos/propbinder-logomark.svg',
33
33
  logoAlt: 'Propbinder',
34
34
  logoSize: 'md', // Propbinder default: md (28px mobile, 32px desktop)
35
35
  // App icon (brand identity)
@@ -63,8 +63,8 @@ const DEFAULT_CONFIG = {
63
63
  * Initialize with custom config:
64
64
  * ```typescript
65
65
  * whitelabelService.initialize({
66
- * logoUrl: '/Assets/logos/acme-logo.svg',
67
- * logoMarkUrl: '/Assets/logos/acme-mark.svg',
66
+ * logoUrl: '/assets/logos/acme-logo.svg',
67
+ * logoMarkUrl: '/assets/logos/acme-mark.svg',
68
68
  * accent: '#2563eb',
69
69
  * onAccent: '#ffffff',
70
70
  * headerSurface: '#1e40af',
@@ -202,8 +202,8 @@ class WhitelabelService {
202
202
  // Example: Different configs for different organizations
203
203
  if (organizationId === 'demo-client') {
204
204
  this.initialize({
205
- logoUrl: '/Assets/logos/demo-logo.svg',
206
- logoMarkUrl: '/Assets/logos/demo-mark.svg',
205
+ logoUrl: '/assets/logos/demo-logo.svg',
206
+ logoMarkUrl: '/assets/logos/demo-mark.svg',
207
207
  logoAlt: 'Demo Client',
208
208
  appIconSurface: '#2563eb',
209
209
  appIconContent: '#FFFFFF',
@@ -219,8 +219,8 @@ class WhitelabelService {
219
219
  }
220
220
  else if (organizationId === 'cobblestone') {
221
221
  this.initialize({
222
- logoUrl: '/Assets/logos/cobblestone-logo.svg',
223
- logoMarkUrl: '/Assets/logos/cobblestone-logomark.svg',
222
+ logoUrl: '/assets/logos/cobblestone-logo.svg',
223
+ logoMarkUrl: '/assets/logos/cobblestone-logomark.svg',
224
224
  logoAlt: 'Cobblestone',
225
225
  logoSize: 'sm',
226
226
  appIconSurface: '#2C3E50',
@@ -14611,9 +14611,6 @@ class DsMobileLightboxImageComponent {
14611
14611
  this.onCloseRequested();
14612
14612
  }
14613
14613
  }
14614
- /**
14615
- * Handle share button click
14616
- */
14617
14614
  async onShare() {
14618
14615
  console.log('[Lightbox] Share button clicked');
14619
14616
  const currentImg = this.currentImage();
@@ -14622,20 +14619,78 @@ class DsMobileLightboxImageComponent {
14622
14619
  return;
14623
14620
  }
14624
14621
  try {
14622
+ let shareUrl = currentImg.src;
14623
+ // Handle native platform sharing of remote URLs
14624
+ if (Capacitor.isNativePlatform()) {
14625
+ if (currentImg.src.startsWith('http')) {
14626
+ try {
14627
+ // Fetch image as blob
14628
+ const response = await fetch(currentImg.src);
14629
+ const blob = await response.blob();
14630
+ // Convert to base64
14631
+ const reader = new FileReader();
14632
+ const base64Data = await new Promise((resolve, reject) => {
14633
+ reader.onloadend = () => {
14634
+ if (typeof reader.result === 'string') {
14635
+ const base64 = reader.result.split(',')[1];
14636
+ resolve(base64);
14637
+ }
14638
+ else {
14639
+ reject(new Error('Failed to read blob as base64'));
14640
+ }
14641
+ };
14642
+ reader.onerror = reject;
14643
+ reader.readAsDataURL(blob);
14644
+ });
14645
+ // Write to cache directory
14646
+ const fileName = `shared_image_${Date.now()}.jpg`;
14647
+ const writeResult = await Filesystem.writeFile({
14648
+ path: fileName,
14649
+ data: base64Data,
14650
+ directory: Directory.Cache
14651
+ });
14652
+ shareUrl = writeResult.uri;
14653
+ }
14654
+ catch (e) {
14655
+ console.error('[Lightbox] Failed to prepare native image share:', e);
14656
+ // Fallback to sharing the URL directly
14657
+ }
14658
+ }
14659
+ }
14625
14660
  // Check if Web Share API is available (for browser)
14626
- if (navigator.share) {
14661
+ if (navigator.share && !Capacitor.isNativePlatform()) {
14662
+ try {
14663
+ if (currentImg.src.startsWith('http')) {
14664
+ const response = await fetch(currentImg.src);
14665
+ const blob = await response.blob();
14666
+ const file = new File([blob], 'shared_image.jpg', { type: blob.type || 'image/jpeg' });
14667
+ if (navigator.canShare && navigator.canShare({ files: [file] })) {
14668
+ await navigator.share({
14669
+ title: currentImg.title || 'Shared Image',
14670
+ text: currentImg.description || '',
14671
+ files: [file]
14672
+ });
14673
+ console.log('[Lightbox] Shared file via Web Share API');
14674
+ return;
14675
+ }
14676
+ }
14677
+ }
14678
+ catch (e) {
14679
+ console.error('[Lightbox] Web Share API file share failed:', e);
14680
+ }
14681
+ // Fallback to URL web share
14627
14682
  await navigator.share({
14628
14683
  title: currentImg.title || 'Shared Image',
14629
14684
  text: currentImg.description || '',
14630
14685
  url: currentImg.src,
14631
14686
  });
14632
- console.log('[Lightbox] Shared via Web Share API');
14687
+ console.log('[Lightbox] Shared URL via Web Share API');
14633
14688
  }
14634
14689
  else {
14635
14690
  // Fallback to Capacitor Share API (for native apps)
14636
14691
  await Share.share({
14637
14692
  title: currentImg.title || 'Shared Image',
14638
- url: currentImg.src,
14693
+ url: shareUrl,
14639
14694
  dialogTitle: 'Share Image',
14640
14695
  });
14641
14696
  console.log('[Lightbox] Shared via Capacitor Share API');
@@ -21924,7 +21979,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
21924
21979
  * ```html
21925
21980
  * <!-- With image -->
21926
21981
  * <ds-mobile-empty-state
21927
- * [imageSrc]="'/Assets/empty-state-inquiry.svg'"
21982
+ * [imageSrc]="'/assets/empty-state-inquiry.svg'"
21928
21983
  * [imageAlt]="'No messages'"
21929
21984
  * [title]="'Ingen beskeder endnu'"
21930
21985
  * [description]="'Start samtalen ved at sende en besked'">
@@ -22042,6 +22097,20 @@ class DsMobilePostDetailModalComponent {
22042
22097
  onEditComment;
22043
22098
  // Callback for deleting a comment
22044
22099
  onDeleteComment;
22100
+ // Translations
22101
+ textReplySingle = 'svar';
22102
+ textReplyPlural = 'svar';
22103
+ textNoRepliesTitle = 'Ingen svar endnu';
22104
+ textNoRepliesDesc = 'Vær den første til at svare på dette opslag';
22105
+ textAddReply = 'Tilføj et svar...';
22106
+ textEditComment = 'Rediger din kommentar...';
22107
+ textEditingComment = 'Redigerer kommentar';
22108
+ textReplyingTo = 'Svarer til';
22109
+ textSend = 'Send kommentar';
22110
+ textClosePost = 'Luk opslag';
22111
+ textJustNow = 'Lige nu';
22112
+ textEdited = 'redigeret';
22113
+ textConfirmDelete = 'Er du sikker på, at du vil slette denne kommentar?';
22045
22114
  // ViewChild for comment input
22046
22115
  commentInput;
22047
22116
  // Signal for reactive post data
@@ -22232,7 +22301,7 @@ class DsMobilePostDetailModalComponent {
22232
22301
  return {
22233
22302
  ...comment,
22234
22303
  content: text,
22235
- timestamp: 'Just now (edited)',
22304
+ timestamp: `${this.textJustNow} (${this.textEdited})`,
22236
22305
  };
22237
22306
  }
22238
22307
  return comment;
@@ -22256,7 +22325,7 @@ class DsMobilePostDetailModalComponent {
22256
22325
  const newComment = {
22257
22326
  authorName: this.currentUserName || 'Dig',
22258
22327
  authorRole: 'Dig',
22259
- timestamp: 'Just now',
22328
+ timestamp: this.textJustNow,
22260
22329
  avatarInitials: this.currentUserInitials(),
22261
22330
  content: finalText,
22262
22331
  isLiked: false,
@@ -22272,6 +22341,9 @@ class DsMobilePostDetailModalComponent {
22272
22341
  });
22273
22342
  // Clear reply state
22274
22343
  this.replyingTo.set(null);
22344
+ if (this.onSubmitComment) {
22345
+ this.onSubmitComment({ postId, text: finalText });
22346
+ }
22275
22347
  }
22276
22348
  // Clear the input
22277
22349
  this.commentText.set('');
@@ -22283,11 +22355,6 @@ class DsMobilePostDetailModalComponent {
22283
22355
  }
22284
22356
  // Hide keyboard explicitly
22285
22357
  Keyboard.hide().catch(() => { });
22286
- // In a real app, you would also send this to your backend
22287
- // this.commentService.addComment(currentPost.postId, text);
22288
- if (this.onSubmitComment) {
22289
- this.onSubmitComment({ postId, text: finalText });
22290
- }
22291
22358
  }
22292
22359
  /**
22293
22360
  * Open image in lightbox
@@ -22382,9 +22449,8 @@ class DsMobilePostDetailModalComponent {
22382
22449
  }
22383
22450
  break;
22384
22451
  case 'delete':
22385
- // console.log('Delete comment by', authorName);
22386
22452
  // Show confirmation before deleting
22387
- if (confirm('Are you sure you want to delete this comment?')) {
22453
+ if (confirm(this.textConfirmDelete)) {
22388
22454
  const commentToDelete = currentPost.comments?.find((comment) => comment.authorName === authorName && comment.content === content);
22389
22455
  const updatedCommentsAfterDelete = currentPost.comments?.filter((comment) => !(comment.authorName === authorName && comment.content === content));
22390
22456
  this.post.set({
@@ -22402,7 +22468,7 @@ class DsMobilePostDetailModalComponent {
22402
22468
  }
22403
22469
  }
22404
22470
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobilePostDetailModalComponent, deps: [{ token: DsMobileLightboxService }, { token: DsMobileBottomSheetService }], target: i0.ɵɵFactoryTarget.Component });
22405
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobilePostDetailModalComponent, isStandalone: true, selector: "ds-mobile-post-detail-modal", inputs: { postData: "postData", currentUserName: "currentUserName", currentUserInitialsInput: "currentUserInitialsInput", loading: "loading", error: "error", onTogglePostLike: "onTogglePostLike", onSubmitComment: "onSubmitComment", onToggleCommentLike: "onToggleCommentLike", onEditComment: "onEditComment", onDeleteComment: "onDeleteComment" }, viewQueries: [{ propertyName: "commentInput", first: true, predicate: ["commentInput"], descendants: true }], ngImport: i0, template: `
22471
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobilePostDetailModalComponent, isStandalone: true, selector: "ds-mobile-post-detail-modal", inputs: { postData: "postData", currentUserName: "currentUserName", currentUserInitialsInput: "currentUserInitialsInput", loading: "loading", error: "error", onTogglePostLike: "onTogglePostLike", onSubmitComment: "onSubmitComment", onToggleCommentLike: "onToggleCommentLike", onEditComment: "onEditComment", onDeleteComment: "onDeleteComment", textReplySingle: "textReplySingle", textReplyPlural: "textReplyPlural", textNoRepliesTitle: "textNoRepliesTitle", textNoRepliesDesc: "textNoRepliesDesc", textAddReply: "textAddReply", textEditComment: "textEditComment", textEditingComment: "textEditingComment", textReplyingTo: "textReplyingTo", textSend: "textSend", textClosePost: "textClosePost", textJustNow: "textJustNow", textEdited: "textEdited", textConfirmDelete: "textConfirmDelete" }, viewQueries: [{ propertyName: "commentInput", first: true, predicate: ["commentInput"], descendants: true }], ngImport: i0, template: `
22406
22472
  <ds-mobile-modal-base
22407
22473
  [loading]="loading"
22408
22474
  [error]="error"
@@ -22410,7 +22476,7 @@ class DsMobilePostDetailModalComponent {
22410
22476
  [headerMeta]="post().authorRole + ' · ' + post().timestamp"
22411
22477
  [hasFixedBottom]="true"
22412
22478
  [enableKeyboardHandling]="true"
22413
- closeButtonLabel="Luk opslag"
22479
+ [closeButtonLabel]="textClosePost"
22414
22480
  >
22415
22481
  <!-- Header Avatar -->
22416
22482
  <ds-avatar header-leading [initials]="post().avatarInitials || ''" [type]="post().avatarType || 'initials'" [src]="post().avatarSrc || ''" size="md" />
@@ -22441,7 +22507,7 @@ class DsMobilePostDetailModalComponent {
22441
22507
 
22442
22508
  <!-- Comments Section -->
22443
22509
  <ds-mobile-section
22444
- [headline]="post().comments && post().comments!.length > 0 ? (post().comments!.length + ' ' + (post().comments!.length === 1 ? 'reply' : 'replies')) : ''">
22510
+ [headline]="post().comments && post().comments!.length > 0 ? (post().comments!.length + ' ' + (post().comments!.length === 1 ? textReplySingle : textReplyPlural)) : ''">
22445
22511
  @if (post().comments && post().comments!.length > 0) {
22446
22512
  <div class="comments-list">
22447
22513
  @for (comment of post().comments!; track comment.id) {
@@ -22464,10 +22530,10 @@ class DsMobilePostDetailModalComponent {
22464
22530
  } @else {
22465
22531
  <!-- Empty State -->
22466
22532
  <ds-mobile-empty-state
22467
- [imageSrc]="'/Assets/empty-state-inquiry.svg'"
22468
- [imageAlt]="'Ingen kommentarer endnu'"
22469
- [title]="'Ingen svar endnu'"
22470
- [description]="'Vær den første til at svare på dette opslag'">
22533
+ [imageSrc]="'/assets/empty-state-inquiry.svg'"
22534
+ [imageAlt]="textNoRepliesTitle"
22535
+ [title]="textNoRepliesTitle"
22536
+ [description]="textNoRepliesDesc">
22471
22537
  </ds-mobile-empty-state>
22472
22538
  }
22473
22539
  </ds-mobile-section>
@@ -22480,7 +22546,7 @@ class DsMobilePostDetailModalComponent {
22480
22546
  <div class="edit-indicator">
22481
22547
  <div class="edit-indicator-content">
22482
22548
  <ds-icon name="remixEditLine" size="16px" />
22483
- <span class="edit-text">Redigerer kommentar</span>
22549
+ <span class="edit-text">{{ textEditingComment }}</span>
22484
22550
  </div>
22485
22551
  <button class="cancel-edit" (click)="cancelEdit()">
22486
22552
  <ds-icon name="remixCloseLine" size="16px" />
@@ -22492,7 +22558,7 @@ class DsMobilePostDetailModalComponent {
22492
22558
  <div class="reply-indicator-content">
22493
22559
  <ds-icon name="remixReplyLine" size="16px" />
22494
22560
  <span class="reply-to-text">
22495
- Svarer til <span class="reply-author">{{ replyingTo()!.authorName }}</span>
22561
+ {{ textReplyingTo }} <span class="reply-author">{{ replyingTo()!.authorName }}</span>
22496
22562
  </span>
22497
22563
  </div>
22498
22564
  <button class="cancel-reply" (click)="cancelReply()">
@@ -22507,7 +22573,7 @@ class DsMobilePostDetailModalComponent {
22507
22573
  <textarea
22508
22574
  #commentInput
22509
22575
  class="composer-input"
22510
- [placeholder]="editingComment() ? 'Rediger din kommentar...' : replyingTo() ? 'Tilføj et svar...' : 'Tilføj et svar...'"
22576
+ [placeholder]="editingComment() ? textEditComment : textAddReply"
22511
22577
  [ngModel]="commentText()"
22512
22578
  (ngModelChange)="commentText.set($event)"
22513
22579
  (input)="handleInput($event)"
@@ -22521,7 +22587,7 @@ class DsMobilePostDetailModalComponent {
22521
22587
  variant="primary"
22522
22588
  size="sm"
22523
22589
  (clicked)="submitComment()"
22524
- aria-label="Send kommentar"
22590
+ [attr.aria-label]="textSend"
22525
22591
  [class.send-button-fixed]="true"
22526
22592
  [class.show]="commentText().trim().length > 0"
22527
22593
  >
@@ -22556,7 +22622,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
22556
22622
  [headerMeta]="post().authorRole + ' · ' + post().timestamp"
22557
22623
  [hasFixedBottom]="true"
22558
22624
  [enableKeyboardHandling]="true"
22559
- closeButtonLabel="Luk opslag"
22625
+ [closeButtonLabel]="textClosePost"
22560
22626
  >
22561
22627
  <!-- Header Avatar -->
22562
22628
  <ds-avatar header-leading [initials]="post().avatarInitials || ''" [type]="post().avatarType || 'initials'" [src]="post().avatarSrc || ''" size="md" />
@@ -22587,7 +22653,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
22587
22653
 
22588
22654
  <!-- Comments Section -->
22589
22655
  <ds-mobile-section
22590
- [headline]="post().comments && post().comments!.length > 0 ? (post().comments!.length + ' ' + (post().comments!.length === 1 ? 'reply' : 'replies')) : ''">
22656
+ [headline]="post().comments && post().comments!.length > 0 ? (post().comments!.length + ' ' + (post().comments!.length === 1 ? textReplySingle : textReplyPlural)) : ''">
22591
22657
  @if (post().comments && post().comments!.length > 0) {
22592
22658
  <div class="comments-list">
22593
22659
  @for (comment of post().comments!; track comment.id) {
@@ -22610,10 +22676,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
22610
22676
  } @else {
22611
22677
  <!-- Empty State -->
22612
22678
  <ds-mobile-empty-state
22613
- [imageSrc]="'/Assets/empty-state-inquiry.svg'"
22614
- [imageAlt]="'Ingen kommentarer endnu'"
22615
- [title]="'Ingen svar endnu'"
22616
- [description]="'Vær den første til at svare på dette opslag'">
22679
+ [imageSrc]="'/assets/empty-state-inquiry.svg'"
22680
+ [imageAlt]="textNoRepliesTitle"
22681
+ [title]="textNoRepliesTitle"
22682
+ [description]="textNoRepliesDesc">
22617
22683
  </ds-mobile-empty-state>
22618
22684
  }
22619
22685
  </ds-mobile-section>
@@ -22626,7 +22692,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
22626
22692
  <div class="edit-indicator">
22627
22693
  <div class="edit-indicator-content">
22628
22694
  <ds-icon name="remixEditLine" size="16px" />
22629
- <span class="edit-text">Redigerer kommentar</span>
22695
+ <span class="edit-text">{{ textEditingComment }}</span>
22630
22696
  </div>
22631
22697
  <button class="cancel-edit" (click)="cancelEdit()">
22632
22698
  <ds-icon name="remixCloseLine" size="16px" />
@@ -22638,7 +22704,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
22638
22704
  <div class="reply-indicator-content">
22639
22705
  <ds-icon name="remixReplyLine" size="16px" />
22640
22706
  <span class="reply-to-text">
22641
- Svarer til <span class="reply-author">{{ replyingTo()!.authorName }}</span>
22707
+ {{ textReplyingTo }} <span class="reply-author">{{ replyingTo()!.authorName }}</span>
22642
22708
  </span>
22643
22709
  </div>
22644
22710
  <button class="cancel-reply" (click)="cancelReply()">
@@ -22653,7 +22719,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
22653
22719
  <textarea
22654
22720
  #commentInput
22655
22721
  class="composer-input"
22656
- [placeholder]="editingComment() ? 'Rediger din kommentar...' : replyingTo() ? 'Tilføj et svar...' : 'Tilføj et svar...'"
22722
+ [placeholder]="editingComment() ? textEditComment : textAddReply"
22657
22723
  [ngModel]="commentText()"
22658
22724
  (ngModelChange)="commentText.set($event)"
22659
22725
  (input)="handleInput($event)"
@@ -22667,7 +22733,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
22667
22733
  variant="primary"
22668
22734
  size="sm"
22669
22735
  (clicked)="submitComment()"
22670
- aria-label="Send kommentar"
22736
+ [attr.aria-label]="textSend"
22671
22737
  [class.send-button-fixed]="true"
22672
22738
  [class.show]="commentText().trim().length > 0"
22673
22739
  >
@@ -22697,6 +22763,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
22697
22763
  type: Input
22698
22764
  }], onDeleteComment: [{
22699
22765
  type: Input
22766
+ }], textReplySingle: [{
22767
+ type: Input
22768
+ }], textReplyPlural: [{
22769
+ type: Input
22770
+ }], textNoRepliesTitle: [{
22771
+ type: Input
22772
+ }], textNoRepliesDesc: [{
22773
+ type: Input
22774
+ }], textAddReply: [{
22775
+ type: Input
22776
+ }], textEditComment: [{
22777
+ type: Input
22778
+ }], textEditingComment: [{
22779
+ type: Input
22780
+ }], textReplyingTo: [{
22781
+ type: Input
22782
+ }], textSend: [{
22783
+ type: Input
22784
+ }], textClosePost: [{
22785
+ type: Input
22786
+ }], textJustNow: [{
22787
+ type: Input
22788
+ }], textEdited: [{
22789
+ type: Input
22790
+ }], textConfirmDelete: [{
22791
+ type: Input
22700
22792
  }], commentInput: [{
22701
22793
  type: ViewChild,
22702
22794
  args: ['commentInput']
@@ -24103,7 +24195,7 @@ class DsMobileBookingModalComponent {
24103
24195
  </ds-button>
24104
24196
  </div>
24105
24197
  </ds-mobile-modal-base>
24106
- `, isInline: true, styles: [".date-item{display:flex;flex-direction:column;align-items:center;justify-content:center;width:80px;padding:12px 8px;border-radius:12px;border:1px solid var(--color-border, #e5e5e5);background:var(--color-surface-primary, #ffffff);cursor:pointer;transition:all .2s ease;-webkit-tap-highlight-color:transparent;gap:4px}.date-item .day-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;color:var(--text-color-default-secondary, #71727a);text-transform:uppercase}.date-item .date-number{font-family:Brockmann,sans-serif;font-size:var(--font-size-xl, 20px);font-weight:600;color:var(--text-color-default-primary, #202227)}.date-item .month-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;color:var(--text-color-default-secondary, #71727a);text-transform:capitalize}.date-item.selected{background:var(--color-accent, #5d5fef);border-color:var(--color-accent, #5d5fef)}.date-item.selected .day-name,.date-item.selected .date-number,.date-item.selected .month-name{color:#fff}.date-item.disabled{background:var(--color-background-neutral-secondary, #f5f5f5);border-color:var(--color-border, #e5e5e5);cursor:not-allowed;opacity:.6}.date-item.disabled .day-name,.date-item.disabled .date-number,.date-item.disabled .month-name{color:var(--text-color-default-tertiary, #9a9aa2)}.date-item:not(.disabled):not(.selected):hover{border-color:var(--color-accent, #5d5fef);background:var(--color-background-neutral-secondary, #f5f5f5)}.time-slots-list{display:flex;flex-direction:column;gap:8px}.time-slot-item{display:flex;align-items:center;justify-content:space-between;width:100%;padding:16px 20px;border-radius:12px;border:1px solid var(--color-border, #e5e5e5);background:var(--color-surface-primary, #ffffff);cursor:pointer;transition:all .2s ease;-webkit-tap-highlight-color:transparent}.time-slot-item span{font-family:Brockmann,sans-serif;font-size:var(--font-size-base, 16px);font-weight:400;color:var(--text-color-default-primary, #202227)}.time-slot-item.selected{background:var(--color-accent, #5d5fef);border-color:var(--color-accent, #5d5fef)}.time-slot-item.selected span{color:#fff;font-weight:500}.time-slot-item.disabled{background:var(--color-background-neutral-secondary, #f5f5f5);border-color:var(--color-border, #e5e5e5);cursor:not-allowed;opacity:.6}.time-slot-item.disabled span{color:var(--text-color-default-tertiary, #9a9aa2)}.time-slot-item:not(.disabled):not(.selected):hover{border-color:var(--color-accent, #5d5fef);background:var(--color-background-neutral-secondary, #f5f5f5)}.booking-confirm-action{width:100%;padding:16px 20px;background:var(--color-surface-primary, #ffffff);border-top:1px solid var(--color-border, #e5e5e5);box-sizing:border-box}.booking-confirm-action ::ng-deep ds-button{display:block;width:100%}.booking-confirm-action ::ng-deep ds-button button{width:100%;border-radius:100px;height:40px}::ng-deep .date-swiper .swiper-slide{width:auto!important}.calendar-link{display:flex;align-items:center;gap:2px;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--color-accent, #5d5fef);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;line-height:1}::ng-deep .cdk-overlay-container{z-index:20001}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["headerTitleInteractive", "textLoading", "textErrorTitle", "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: DsMobileSwiperComponent, selector: "ds-mobile-swiper", inputs: ["slideWidth", "gap", "pagination", "autoHeight", "progressiveOpacity", "progressiveScale"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { 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: DsDatepickerComponent, selector: "ds-datepicker", inputs: ["variant", "disabled", "placeholder", "ariaLabel", "ariaDescribedBy", "disableFutureDates", "disablePastDates", "isDateDisabled", "locale"], outputs: ["dateChange", "opened", "closed"] }] });
24198
+ `, isInline: true, styles: [".date-item{display:flex;flex-direction:column;align-items:center;justify-content:center;width:80px;padding:12px 8px;border-radius:12px;border:1px solid var(--color-border, #e5e5e5);background:var(--color-surface-primary, #ffffff);cursor:pointer;transition:all .2s ease;-webkit-tap-highlight-color:transparent;gap:4px}.date-item .day-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;color:var(--text-color-default-secondary, #71727a);text-transform:uppercase}.date-item .date-number{font-family:Brockmann,sans-serif;font-size:var(--font-size-xl, 20px);font-weight:600;color:var(--text-color-default-primary, #202227)}.date-item .month-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;color:var(--text-color-default-secondary, #71727a);text-transform:capitalize}.date-item.selected{background:var(--color-accent, #5d5fef);border-color:var(--color-accent, #5d5fef)}.date-item.selected .day-name,.date-item.selected .date-number,.date-item.selected .month-name{color:#fff}.date-item.disabled{background:var(--color-background-neutral-secondary, #f5f5f5);border-color:var(--color-border, #e5e5e5);cursor:not-allowed;opacity:.6}.date-item.disabled .day-name,.date-item.disabled .date-number,.date-item.disabled .month-name{color:var(--text-color-default-tertiary, #9a9aa2)}.date-item:not(.disabled):not(.selected):hover{border-color:var(--color-accent, #5d5fef);background:var(--color-background-neutral-secondary, #f5f5f5)}.time-slots-list{display:flex;flex-direction:column;gap:8px}.time-slot-item{display:flex;align-items:center;justify-content:space-between;width:100%;padding:16px 20px;border-radius:12px;border:1px solid var(--color-border, #e5e5e5);background:var(--color-surface-primary, #ffffff);cursor:pointer;transition:all .2s ease;-webkit-tap-highlight-color:transparent}.time-slot-item span{font-family:Brockmann,sans-serif;font-size:var(--font-size-base, 16px);font-weight:400;color:var(--text-color-default-primary, #202227)}.time-slot-item.selected{background:var(--color-accent, #5d5fef);border-color:var(--color-accent, #5d5fef)}.time-slot-item.selected span{color:#fff;font-weight:500}.time-slot-item.disabled{background:var(--color-background-neutral-secondary, #f5f5f5);border-color:var(--color-border, #e5e5e5);cursor:not-allowed;opacity:.6}.time-slot-item.disabled span{color:var(--text-color-default-tertiary, #9a9aa2)}.time-slot-item:not(.disabled):not(.selected):hover{border-color:var(--color-accent, #5d5fef);background:var(--color-background-neutral-secondary, #f5f5f5)}.booking-confirm-action{width:100%;padding:16px 20px;background:var(--color-surface-primary, #ffffff);border-top:1px solid var(--color-border, #e5e5e5);box-sizing:border-box}.booking-confirm-action ::ng-deep ds-button{display:block;width:100%}.booking-confirm-action ::ng-deep ds-button button{width:100%;border-radius:100px;height:40px}::ng-deep .date-swiper .swiper-slide{width:auto!important}.calendar-link{display:flex;align-items:center;gap:2px;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--color-accent, #5d5fef);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;line-height:1}::ng-deep .cdk-overlay-container,::ng-deep .floating-container,::ng-deep [data-floating-ui]{z-index:20005!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["headerTitleInteractive", "textLoading", "textErrorTitle", "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: DsMobileSwiperComponent, selector: "ds-mobile-swiper", inputs: ["slideWidth", "gap", "pagination", "autoHeight", "progressiveOpacity", "progressiveScale"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { 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: DsDatepickerComponent, selector: "ds-datepicker", inputs: ["variant", "disabled", "placeholder", "ariaLabel", "ariaDescribedBy", "disableFutureDates", "disablePastDates", "isDateDisabled", "locale"], outputs: ["dateChange", "opened", "closed"] }] });
24107
24199
  }
24108
24200
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileBookingModalComponent, decorators: [{
24109
24201
  type: Component,
@@ -24187,7 +24279,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
24187
24279
  </ds-button>
24188
24280
  </div>
24189
24281
  </ds-mobile-modal-base>
24190
- `, styles: [".date-item{display:flex;flex-direction:column;align-items:center;justify-content:center;width:80px;padding:12px 8px;border-radius:12px;border:1px solid var(--color-border, #e5e5e5);background:var(--color-surface-primary, #ffffff);cursor:pointer;transition:all .2s ease;-webkit-tap-highlight-color:transparent;gap:4px}.date-item .day-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;color:var(--text-color-default-secondary, #71727a);text-transform:uppercase}.date-item .date-number{font-family:Brockmann,sans-serif;font-size:var(--font-size-xl, 20px);font-weight:600;color:var(--text-color-default-primary, #202227)}.date-item .month-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;color:var(--text-color-default-secondary, #71727a);text-transform:capitalize}.date-item.selected{background:var(--color-accent, #5d5fef);border-color:var(--color-accent, #5d5fef)}.date-item.selected .day-name,.date-item.selected .date-number,.date-item.selected .month-name{color:#fff}.date-item.disabled{background:var(--color-background-neutral-secondary, #f5f5f5);border-color:var(--color-border, #e5e5e5);cursor:not-allowed;opacity:.6}.date-item.disabled .day-name,.date-item.disabled .date-number,.date-item.disabled .month-name{color:var(--text-color-default-tertiary, #9a9aa2)}.date-item:not(.disabled):not(.selected):hover{border-color:var(--color-accent, #5d5fef);background:var(--color-background-neutral-secondary, #f5f5f5)}.time-slots-list{display:flex;flex-direction:column;gap:8px}.time-slot-item{display:flex;align-items:center;justify-content:space-between;width:100%;padding:16px 20px;border-radius:12px;border:1px solid var(--color-border, #e5e5e5);background:var(--color-surface-primary, #ffffff);cursor:pointer;transition:all .2s ease;-webkit-tap-highlight-color:transparent}.time-slot-item span{font-family:Brockmann,sans-serif;font-size:var(--font-size-base, 16px);font-weight:400;color:var(--text-color-default-primary, #202227)}.time-slot-item.selected{background:var(--color-accent, #5d5fef);border-color:var(--color-accent, #5d5fef)}.time-slot-item.selected span{color:#fff;font-weight:500}.time-slot-item.disabled{background:var(--color-background-neutral-secondary, #f5f5f5);border-color:var(--color-border, #e5e5e5);cursor:not-allowed;opacity:.6}.time-slot-item.disabled span{color:var(--text-color-default-tertiary, #9a9aa2)}.time-slot-item:not(.disabled):not(.selected):hover{border-color:var(--color-accent, #5d5fef);background:var(--color-background-neutral-secondary, #f5f5f5)}.booking-confirm-action{width:100%;padding:16px 20px;background:var(--color-surface-primary, #ffffff);border-top:1px solid var(--color-border, #e5e5e5);box-sizing:border-box}.booking-confirm-action ::ng-deep ds-button{display:block;width:100%}.booking-confirm-action ::ng-deep ds-button button{width:100%;border-radius:100px;height:40px}::ng-deep .date-swiper .swiper-slide{width:auto!important}.calendar-link{display:flex;align-items:center;gap:2px;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--color-accent, #5d5fef);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;line-height:1}::ng-deep .cdk-overlay-container{z-index:20001}\n"] }]
24282
+ `, styles: [".date-item{display:flex;flex-direction:column;align-items:center;justify-content:center;width:80px;padding:12px 8px;border-radius:12px;border:1px solid var(--color-border, #e5e5e5);background:var(--color-surface-primary, #ffffff);cursor:pointer;transition:all .2s ease;-webkit-tap-highlight-color:transparent;gap:4px}.date-item .day-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;color:var(--text-color-default-secondary, #71727a);text-transform:uppercase}.date-item .date-number{font-family:Brockmann,sans-serif;font-size:var(--font-size-xl, 20px);font-weight:600;color:var(--text-color-default-primary, #202227)}.date-item .month-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;color:var(--text-color-default-secondary, #71727a);text-transform:capitalize}.date-item.selected{background:var(--color-accent, #5d5fef);border-color:var(--color-accent, #5d5fef)}.date-item.selected .day-name,.date-item.selected .date-number,.date-item.selected .month-name{color:#fff}.date-item.disabled{background:var(--color-background-neutral-secondary, #f5f5f5);border-color:var(--color-border, #e5e5e5);cursor:not-allowed;opacity:.6}.date-item.disabled .day-name,.date-item.disabled .date-number,.date-item.disabled .month-name{color:var(--text-color-default-tertiary, #9a9aa2)}.date-item:not(.disabled):not(.selected):hover{border-color:var(--color-accent, #5d5fef);background:var(--color-background-neutral-secondary, #f5f5f5)}.time-slots-list{display:flex;flex-direction:column;gap:8px}.time-slot-item{display:flex;align-items:center;justify-content:space-between;width:100%;padding:16px 20px;border-radius:12px;border:1px solid var(--color-border, #e5e5e5);background:var(--color-surface-primary, #ffffff);cursor:pointer;transition:all .2s ease;-webkit-tap-highlight-color:transparent}.time-slot-item span{font-family:Brockmann,sans-serif;font-size:var(--font-size-base, 16px);font-weight:400;color:var(--text-color-default-primary, #202227)}.time-slot-item.selected{background:var(--color-accent, #5d5fef);border-color:var(--color-accent, #5d5fef)}.time-slot-item.selected span{color:#fff;font-weight:500}.time-slot-item.disabled{background:var(--color-background-neutral-secondary, #f5f5f5);border-color:var(--color-border, #e5e5e5);cursor:not-allowed;opacity:.6}.time-slot-item.disabled span{color:var(--text-color-default-tertiary, #9a9aa2)}.time-slot-item:not(.disabled):not(.selected):hover{border-color:var(--color-accent, #5d5fef);background:var(--color-background-neutral-secondary, #f5f5f5)}.booking-confirm-action{width:100%;padding:16px 20px;background:var(--color-surface-primary, #ffffff);border-top:1px solid var(--color-border, #e5e5e5);box-sizing:border-box}.booking-confirm-action ::ng-deep ds-button{display:block;width:100%}.booking-confirm-action ::ng-deep ds-button button{width:100%;border-radius:100px;height:40px}::ng-deep .date-swiper .swiper-slide{width:auto!important}.calendar-link{display:flex;align-items:center;gap:2px;font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:500;color:var(--color-accent, #5d5fef);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;line-height:1}::ng-deep .cdk-overlay-container,::ng-deep .floating-container,::ng-deep [data-floating-ui]{z-index:20005!important}\n"] }]
24191
24283
  }], ctorParameters: () => [{ type: i1.ModalController }], propDecorators: { facilityId: [{
24192
24284
  type: Input
24193
24285
  }], facilityTitle: [{
@@ -24382,10 +24474,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
24382
24474
  class DsMobileBookingConfirmationWrapperComponent {
24383
24475
  booking;
24384
24476
  facilityThumbnail;
24477
+ textTitle = 'Booking accepteret';
24478
+ textMessageTemplate = 'Din booking til den {{date}} er bekræftet. Du kan annullere fra startdatoen.';
24479
+ textClose = 'Luk';
24480
+ monthNamesShort = [
24481
+ 'jan', 'feb', 'mar', 'apr', 'maj', 'jun',
24482
+ 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'
24483
+ ];
24385
24484
  get confirmationMessage() {
24386
24485
  const date = this.booking.selectedDate.fullDate;
24387
24486
  const dateStr = this.formatFullDate(date);
24388
- return `Din booking til den ${dateStr} er bekræftet. Du kan annullere fra startdatoen.`;
24487
+ return this.textMessageTemplate.replace('{{date}}', dateStr);
24389
24488
  }
24390
24489
  get formattedDate() {
24391
24490
  const { dayName, date, monthName } = this.booking.selectedDate;
@@ -24397,20 +24496,16 @@ class DsMobileBookingConfirmationWrapperComponent {
24397
24496
  }
24398
24497
  formatFullDate(date) {
24399
24498
  const day = date.getDate();
24400
- const monthNames = [
24401
- 'januar', 'februar', 'marts', 'april', 'maj', 'juni',
24402
- 'juli', 'august', 'september', 'oktober', 'november', 'december'
24403
- ];
24404
- const month = monthNames[date.getMonth()];
24499
+ const month = this.monthNamesShort[date.getMonth()];
24405
24500
  const year = date.getFullYear();
24406
- return `${day}. ${month}, ${year}`;
24501
+ return `${day}. ${month} ${year}`;
24407
24502
  }
24408
24503
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileBookingConfirmationWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
24409
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: DsMobileBookingConfirmationWrapperComponent, isStandalone: true, selector: "ds-mobile-booking-confirmation-wrapper", inputs: { booking: "booking", facilityThumbnail: "facilityThumbnail" }, ngImport: i0, template: `
24504
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: DsMobileBookingConfirmationWrapperComponent, isStandalone: true, selector: "ds-mobile-booking-confirmation-wrapper", inputs: { booking: "booking", facilityThumbnail: "facilityThumbnail", textTitle: "textTitle", textMessageTemplate: "textMessageTemplate", textClose: "textClose", monthNamesShort: "monthNamesShort" }, ngImport: i0, template: `
24410
24505
  <ds-mobile-confirmation-sheet
24411
- [title]="'Booking accepteret'"
24506
+ [title]="textTitle"
24412
24507
  [message]="confirmationMessage"
24413
- [buttonText]="'Luk'"
24508
+ [buttonText]="textClose"
24414
24509
  [illustrationVariant]="'confirmation'">
24415
24510
  <ng-template #summary>
24416
24511
  <ds-mobile-booking-summary
@@ -24435,9 +24530,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
24435
24530
  ],
24436
24531
  template: `
24437
24532
  <ds-mobile-confirmation-sheet
24438
- [title]="'Booking accepteret'"
24533
+ [title]="textTitle"
24439
24534
  [message]="confirmationMessage"
24440
- [buttonText]="'Luk'"
24535
+ [buttonText]="textClose"
24441
24536
  [illustrationVariant]="'confirmation'">
24442
24537
  <ng-template #summary>
24443
24538
  <ds-mobile-booking-summary
@@ -24454,6 +24549,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
24454
24549
  type: Input
24455
24550
  }], facilityThumbnail: [{
24456
24551
  type: Input
24552
+ }], textTitle: [{
24553
+ type: Input
24554
+ }], textMessageTemplate: [{
24555
+ type: Input
24556
+ }], textClose: [{
24557
+ type: Input
24558
+ }], monthNamesShort: [{
24559
+ type: Input
24457
24560
  }] } });
24458
24561
 
24459
24562
  /**
@@ -24506,7 +24609,7 @@ class DsMobileBookingModalService extends BaseModalService {
24506
24609
  // Dismiss all open modals (booking modal + facility detail modal)
24507
24610
  await this.dismissAllModals();
24508
24611
  // Show confirmation sheet after all modals are dismissed
24509
- await this.openConfirmationSheet(result.data, facilityThumbnail);
24612
+ await this.openConfirmationSheet(result.data, facilityThumbnail, extras?.labels);
24510
24613
  }
24511
24614
  }
24512
24615
  /**
@@ -24526,12 +24629,16 @@ class DsMobileBookingModalService extends BaseModalService {
24526
24629
  * @param facilityThumbnail Optional thumbnail image URL
24527
24630
  * @returns Promise that resolves when the sheet is dismissed
24528
24631
  */
24529
- async openConfirmationSheet(booking, facilityThumbnail) {
24632
+ async openConfirmationSheet(booking, facilityThumbnail, labels) {
24530
24633
  const sheet = await this.modalController.create({
24531
24634
  component: DsMobileBookingConfirmationWrapperComponent,
24532
24635
  componentProps: {
24533
24636
  booking,
24534
- facilityThumbnail
24637
+ facilityThumbnail,
24638
+ ...(labels?.confirmationTitle && { textTitle: labels.confirmationTitle }),
24639
+ ...(labels?.confirmationMessageTemplate && { textMessageTemplate: labels.confirmationMessageTemplate }),
24640
+ ...(labels?.confirmationClose && { textClose: labels.confirmationClose }),
24641
+ ...(labels?.monthNamesShort && { monthNamesShort: labels.monthNamesShort })
24535
24642
  },
24536
24643
  breakpoints: [0, 1],
24537
24644
  initialBreakpoint: 1,
@@ -27659,7 +27766,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
27659
27766
  * await this.facilityModal.open({
27660
27767
  * id: 'facility-1',
27661
27768
  * facilityTitle: 'Festlokale på taget',
27662
- * heroImage: '/Assets/Dummy-photos/balcony-view.jpg',
27769
+ * heroImage: '/assets/Dummy-photos/balcony-view.jpg',
27663
27770
  * fullDescription: '<p>The rooftop terrace is designed...</p>',
27664
27771
  * requirements: ['Kræver nøglekort'],
27665
27772
  * bookingType: 'Instant booking',
@@ -27839,7 +27946,8 @@ class DsMobileHandbookDetailModalComponent {
27839
27946
  // Translations
27840
27947
  textLoading = 'Henter...';
27841
27948
  textError = 'Fejl';
27842
- textItems = 'emner';
27949
+ textItemSingle = 'emne';
27950
+ textItemsPlural = 'emner';
27843
27951
  textClose = 'Luk';
27844
27952
  textEmptyTitle = 'Ingen emner endnu';
27845
27953
  textEmptyDescription = 'Denne mappe er tom';
@@ -28023,8 +28131,8 @@ class DsMobileHandbookDetailModalComponent {
28023
28131
  // Attachment action is now handled by DsMobileCardInlineFileComponent via fileUrl input
28024
28132
  }
28025
28133
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileHandbookDetailModalComponent, deps: [{ token: i1.ModalController }], target: i0.ɵɵFactoryTarget.Component });
28026
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileHandbookDetailModalComponent, isStandalone: true, selector: "ds-mobile-handbook-detail-modal", inputs: { handbookData: "handbookData", loading: "loading", error: "error", textLoading: "textLoading", textError: "textError", textItems: "textItems", textClose: "textClose", textEmptyTitle: "textEmptyTitle", textEmptyDescription: "textEmptyDescription", textCall: "textCall", textCopyPhone: "textCopyPhone", textEmail: "textEmail", textCopyEmail: "textCopyEmail" }, ngImport: i0, template: `
28027
- <ds-mobile-modal-base [loading]="loading" [error]="error" [textLoading]="textLoading" [textErrorTitle]="textError" [headerTitle]="handbook().title" [headerMeta]="handbook().itemCount + ' ' + textItems" [closeButtonLabel]="textClose">
28134
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileHandbookDetailModalComponent, isStandalone: true, selector: "ds-mobile-handbook-detail-modal", inputs: { handbookData: "handbookData", loading: "loading", error: "error", textLoading: "textLoading", textError: "textError", textItemSingle: "textItemSingle", textItemsPlural: "textItemsPlural", textClose: "textClose", textEmptyTitle: "textEmptyTitle", textEmptyDescription: "textEmptyDescription", textCall: "textCall", textCopyPhone: "textCopyPhone", textEmail: "textEmail", textCopyEmail: "textCopyEmail" }, ngImport: i0, template: `
28135
+ <ds-mobile-modal-base [loading]="loading" [error]="error" [textLoading]="textLoading" [textErrorTitle]="textError" [headerTitle]="handbook().title" [headerMeta]="handbook().itemCount + ' ' + (handbook().itemCount === 1 ? textItemSingle : textItemsPlural)" [closeButtonLabel]="textClose">
28028
28136
  <!-- Header Folder Icon -->
28029
28137
  <ds-mobile-handbook-folder-mini header-leading [variant]="handbook().variant" [customColor]="handbook().customColor" [iconName]="handbook().iconName">
28030
28138
  </ds-mobile-handbook-folder-mini>
@@ -28085,7 +28193,7 @@ class DsMobileHandbookDetailModalComponent {
28085
28193
  <!-- Empty State -->
28086
28194
  <ds-mobile-section>
28087
28195
  <div class="handbook-empty-state">
28088
- <img src="/Assets/Empty%20state-chat.png" alt="No items yet" class="empty-state-image" />
28196
+ <img src="/assets/Empty%20state-chat.png" alt="No items yet" class="empty-state-image" />
28089
28197
  <h3 class="empty-state-title">{{ textEmptyTitle }}</h3>
28090
28198
  <p class="empty-state-description">{{ textEmptyDescription }}</p>
28091
28199
  </div>
@@ -28105,7 +28213,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28105
28213
  DsMobileModalBaseComponent,
28106
28214
  DsMobileSectionComponent,
28107
28215
  ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `
28108
- <ds-mobile-modal-base [loading]="loading" [error]="error" [textLoading]="textLoading" [textErrorTitle]="textError" [headerTitle]="handbook().title" [headerMeta]="handbook().itemCount + ' ' + textItems" [closeButtonLabel]="textClose">
28216
+ <ds-mobile-modal-base [loading]="loading" [error]="error" [textLoading]="textLoading" [textErrorTitle]="textError" [headerTitle]="handbook().title" [headerMeta]="handbook().itemCount + ' ' + (handbook().itemCount === 1 ? textItemSingle : textItemsPlural)" [closeButtonLabel]="textClose">
28109
28217
  <!-- Header Folder Icon -->
28110
28218
  <ds-mobile-handbook-folder-mini header-leading [variant]="handbook().variant" [customColor]="handbook().customColor" [iconName]="handbook().iconName">
28111
28219
  </ds-mobile-handbook-folder-mini>
@@ -28166,7 +28274,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28166
28274
  <!-- Empty State -->
28167
28275
  <ds-mobile-section>
28168
28276
  <div class="handbook-empty-state">
28169
- <img src="/Assets/Empty%20state-chat.png" alt="No items yet" class="empty-state-image" />
28277
+ <img src="/assets/Empty%20state-chat.png" alt="No items yet" class="empty-state-image" />
28170
28278
  <h3 class="empty-state-title">{{ textEmptyTitle }}</h3>
28171
28279
  <p class="empty-state-description">{{ textEmptyDescription }}</p>
28172
28280
  </div>
@@ -28184,7 +28292,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28184
28292
  type: Input
28185
28293
  }], textError: [{
28186
28294
  type: Input
28187
- }], textItems: [{
28295
+ }], textItemSingle: [{
28296
+ type: Input
28297
+ }], textItemsPlural: [{
28188
28298
  type: Input
28189
28299
  }], textClose: [{
28190
28300
  type: Input
@@ -28257,16 +28367,17 @@ class DsMobileHandbookDetailModalService extends BaseModalService {
28257
28367
  handbookData: handbookData,
28258
28368
  loading: options?.loading ?? false,
28259
28369
  error: options?.error,
28260
- textLoading: handbookData.textLoading,
28261
- textError: handbookData.textError,
28262
- textItems: handbookData.textItems,
28263
- textClose: handbookData.textClose,
28264
- textEmptyTitle: handbookData.textEmptyTitle,
28265
- textEmptyDescription: handbookData.textEmptyDescription,
28266
- textCall: handbookData.textCall,
28267
- textCopyPhone: handbookData.textCopyPhone,
28268
- textEmail: handbookData.textEmail,
28269
- textCopyEmail: handbookData.textCopyEmail,
28370
+ textLoading: handbookData.textLoading ?? 'Henter...',
28371
+ textError: handbookData.textError ?? 'Fejl',
28372
+ textItemSingle: handbookData.textItemSingle ?? 'emne',
28373
+ textItemsPlural: handbookData.textItemsPlural ?? 'emner',
28374
+ textClose: handbookData.textClose ?? 'Luk',
28375
+ textEmptyTitle: handbookData.textEmptyTitle ?? 'Ingen emner endnu',
28376
+ textEmptyDescription: handbookData.textEmptyDescription ?? 'Denne mappe er tom',
28377
+ textCall: handbookData.textCall ?? 'Ring',
28378
+ textCopyPhone: handbookData.textCopyPhone ?? 'Kopier nummer',
28379
+ textEmail: handbookData.textEmail ?? 'Skriv e-mail',
28380
+ textCopyEmail: handbookData.textCopyEmail ?? 'Kopier e-mail',
28270
28381
  }, {
28271
28382
  keyboardClose: true, // Keep keyboard close behavior for this modal
28272
28383
  });
@@ -28353,7 +28464,8 @@ class DsMobileHandbookFolderComponent {
28353
28464
  // Translations
28354
28465
  textLoading = 'Henter...';
28355
28466
  textError = 'Fejl';
28356
- textItems = 'emner';
28467
+ textItemSingle = 'emne';
28468
+ textItemsPlural = 'emner';
28357
28469
  textClose = 'Luk';
28358
28470
  textEmptyTitle = 'Ingen emner endnu';
28359
28471
  textEmptyDescription = 'Denne mappe er tom';
@@ -28448,7 +28560,8 @@ class DsMobileHandbookFolderComponent {
28448
28560
  items: this.items,
28449
28561
  textLoading: this.textLoading,
28450
28562
  textError: this.textError,
28451
- textItems: this.textItems,
28563
+ textItemSingle: this.textItemSingle,
28564
+ textItemsPlural: this.textItemsPlural,
28452
28565
  textClose: this.textClose,
28453
28566
  textEmptyTitle: this.textEmptyTitle,
28454
28567
  textEmptyDescription: this.textEmptyDescription,
@@ -28474,7 +28587,7 @@ class DsMobileHandbookFolderComponent {
28474
28587
  this.handbookModal = handbookModal;
28475
28588
  }
28476
28589
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileHandbookFolderComponent, deps: [{ token: DsMobileHandbookDetailModalService }], target: i0.ɵɵFactoryTarget.Component });
28477
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileHandbookFolderComponent, isStandalone: true, selector: "ds-mobile-handbook-folder", inputs: { variant: "variant", customColor: "customColor", iconName: "iconName", itemCount: "itemCount", label: "label", items: "items", loading: "loading", error: "error", textLoading: "textLoading", textError: "textError", textItems: "textItems", textClose: "textClose", textEmptyTitle: "textEmptyTitle", textEmptyDescription: "textEmptyDescription", textCall: "textCall", textCopyPhone: "textCopyPhone", textEmail: "textEmail", textCopyEmail: "textCopyEmail" }, host: { listeners: { "mouseenter": "open()", "mouseleave": "close()", "touchstart": "onTouchStart($event)", "touchend": "onTouchEnd()", "touchcancel": "onTouchCancel()", "click": "onClick()" } }, ngImport: i0, template: `
28590
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileHandbookFolderComponent, isStandalone: true, selector: "ds-mobile-handbook-folder", inputs: { variant: "variant", customColor: "customColor", iconName: "iconName", itemCount: "itemCount", label: "label", items: "items", loading: "loading", error: "error", textLoading: "textLoading", textError: "textError", textItemSingle: "textItemSingle", textItemsPlural: "textItemsPlural", textClose: "textClose", textEmptyTitle: "textEmptyTitle", textEmptyDescription: "textEmptyDescription", textCall: "textCall", textCopyPhone: "textCopyPhone", textEmail: "textEmail", textCopyEmail: "textCopyEmail" }, host: { listeners: { "mouseenter": "open()", "mouseleave": "close()", "touchstart": "onTouchStart($event)", "touchend": "onTouchEnd()", "touchcancel": "onTouchCancel()", "click": "onClick()" } }, ngImport: i0, template: `
28478
28591
  <div class="folder-container" [class.open]="isOpen()">
28479
28592
  <!-- Folder Tab SVG -->
28480
28593
  <svg class="folder-tab" width="101" height="24" viewBox="0 0 101 24" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -28504,18 +28617,18 @@ class DsMobileHandbookFolderComponent {
28504
28617
  <!-- Label and Item Count -->
28505
28618
  <div class="folder-label-container">
28506
28619
  <div class="folder-label ui-sm-semiBold">{{ label }}</div>
28507
- <div class="item-count ui-sm-regular" [style.color]="'var(--color-text-secondary, #6b7280)'">
28620
+ <div class="item-count ui-xs-regular" [style.color]="'var(--color-text-secondary, #6b7280)'">
28508
28621
  @if (loading) {
28509
28622
  <span class="loading-indicator">{{ textLoading }}</span>
28510
28623
  } @else if (error) {
28511
28624
  <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">{{ textError }}</span>
28512
28625
  } @else {
28513
28626
  <span>{{ itemCount }}</span>
28514
- <span class="item-count-label">{{ textItems }}</span>
28627
+ <span>{{ itemCount === 1 ? textItemSingle : textItemsPlural }}</span>
28515
28628
  }
28516
28629
  </div>
28517
28630
  </div>
28518
- `, isInline: true, styles: [":host{display:inline-flex;flex-direction:column;align-items:center;gap:16px;width:100%;min-width:140px;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;padding:16px;border-radius:16px;background:var(--color-background-neutral-secondary, #f0f0f0);transition:background .2s ease}:host:active{background:var(--color-background-neutral-secondary-hover, #ebebeb)}@media (hover: hover){:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}}:host{--color-red-base: #dc3545;--color-red-strong: #ae1d3b;--color-green-base: #28a745;--color-green-strong: #058057;--color-yellow-base: #ffc107;--color-yellow-strong: #e4b200;--color-purple-base: #6f42c1;--color-purple-strong: #4204c5;--color-indigo-base: #6610f2;--color-indigo-strong: #a527a2;--color-lime-base: #82c91e;--color-lime-strong: #58a503;--color-teal-base: #20c997;--color-teal-strong: #0ca678;--color-cyan-base: #17a2b8;--color-cyan-strong: #1098ad;--color-brown-base: #795548;--color-brown-strong: #5c4033;--color-light-blue-base: #add8e6;--color-light-blue-strong: #87ceeb;--color-light-green-base: #90ee90;--color-light-green-strong: #32cd32;--color-coral-base: #f08080;--color-coral-strong: #cd5c5c;--color-salmon-base: #ffa07a;--color-salmon-strong: #fa8072;--color-seagreen-base: #20b2aa;--color-seagreen-strong: #2e8b57}.folder-container{position:relative;width:100%;display:flex;flex-direction:column;perspective:800px;-webkit-perspective:800px;max-width:160px;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}.folder-container.open .page-sheet{-webkit-transform:translateY(-8px);transform:translateY(-8px);transition-delay:.2s}.folder-container.open .page-sheet:nth-child(1){-webkit-transform:scale(1) translateY(-8px) rotateX(-45deg) translateZ(.1px);transform:scale(1) translateY(-8px) rotateX(-45deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(2){-webkit-transform:scale(.98) translateY(-12px) rotateX(-36deg) translateZ(.1px);transform:scale(.98) translateY(-12px) rotateX(-36deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(3){-webkit-transform:scale(.96) translateY(-16px) rotateX(-27deg) translateZ(.1px);transform:scale(.96) translateY(-16px) rotateX(-27deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(4){-webkit-transform:scale(.94) translateY(-20px) rotateX(-18deg) translateZ(.1px);transform:scale(.94) translateY(-20px) rotateX(-18deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(5){-webkit-transform:scale(.92) translateY(-24px) rotateX(-9deg) translateZ(.1px);transform:scale(.92) translateY(-24px) rotateX(-9deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(6){-webkit-transform:scale(.9) translateY(-28px) rotateX(0deg) translateZ(.1px);transform:scale(.9) translateY(-28px) rotateX(.1px)}.folder-container.open .folder-front{-webkit-transform:translate3d(0,0,0) rotateX(-45deg);transform:translateZ(0) rotateX(-45deg)}.folder-tab{width:50%;height:auto;display:block}.folder-back{height:128px;border-radius:0 12px 12px;position:relative;margin-top:-1px;transform-style:preserve-3d;-webkit-transform-style:preserve-3d;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0)}.page-sheet{position:absolute;width:80%;height:120px;background:#fff;border-radius:8px;box-shadow:0 -1px 5px #0000001a;border:1px solid var(--border-color-default);transition:transform .3s ease-out;-webkit-transition:-webkit-transform .3s ease-out;left:10%;-webkit-transform:translateZ(0);transform:translateZ(0);transform-style:preserve-3d;-webkit-transform-style:preserve-3d;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-font-smoothing:antialiased;will-change:transform}.page-sheet:nth-child(1){bottom:2px;z-index:6;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(1) translateZ(.1px);transform:scale(1) translateZ(.1px)}.page-sheet:nth-child(2){bottom:8px;z-index:5;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.98) translateZ(.1px);transform:scale(.98) translateZ(.1px)}.page-sheet:nth-child(3){bottom:14px;z-index:4;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.96) translateZ(.1px);transform:scale(.96) translateZ(.1px)}.page-sheet:nth-child(4){bottom:20px;z-index:3;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.94) translateZ(.1px);transform:scale(.94) translateZ(.1px)}.page-sheet:nth-child(5){bottom:26px;z-index:2;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.92) translateZ(.1px);transform:scale(.92) translateZ(.1px)}.page-sheet:nth-child(6){bottom:32px;z-index:1;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.9) translateZ(.1px);transform:scale(.9) translateZ(.1px)}.folder-front{position:absolute;bottom:0;left:0;right:0;height:116px;border-radius:12px;display:flex;align-items:center;justify-content:center;padding:8px;z-index:2;transform-origin:bottom center;-webkit-transform-origin:bottom center;transform-style:preserve-3d;-webkit-transform-style:preserve-3d;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out;-webkit-transition:-webkit-transform .4s ease-in-out;will-change:transform;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-font-smoothing:antialiased;-webkit-transform:rotateX(-20deg) translateZ(.1px);transform:rotateX(-20deg) translateZ(.1px);-webkit-transform:translate3d(0,0,0) rotateX(-20deg);transform:translateZ(0) rotateX(-20deg);box-shadow:inset 0 64px 48px #fff3,inset 0 2px 4px #ffffff4d,inset 0 1px 1px #ffffff4d}.item-count{display:flex;align-items:center;gap:4px}.item-count-label{letter-spacing:.5px}.folder-icon{display:flex;align-items:center;justify-content:center}.folder-label-container{display:flex;flex-direction:column;align-items:center;gap:4px;width:100%;min-width:0}.folder-label{text-align:center;width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.loading-indicator,.error-indicator{font-size:var(--font-size-xs)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
28631
+ `, isInline: true, styles: [":host{display:inline-flex;flex-direction:column;align-items:center;gap:16px;width:100%;min-width:140px;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;padding:16px;border-radius:16px;background:var(--color-background-neutral-secondary, #f0f0f0);transition:background .2s ease}:host:active{background:var(--color-background-neutral-secondary-hover, #ebebeb)}@media (hover: hover){:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}}:host{--color-red-base: #dc3545;--color-red-strong: #ae1d3b;--color-green-base: #28a745;--color-green-strong: #058057;--color-yellow-base: #ffc107;--color-yellow-strong: #e4b200;--color-purple-base: #6f42c1;--color-purple-strong: #4204c5;--color-indigo-base: #6610f2;--color-indigo-strong: #a527a2;--color-lime-base: #82c91e;--color-lime-strong: #58a503;--color-teal-base: #20c997;--color-teal-strong: #0ca678;--color-cyan-base: #17a2b8;--color-cyan-strong: #1098ad;--color-brown-base: #795548;--color-brown-strong: #5c4033;--color-light-blue-base: #add8e6;--color-light-blue-strong: #87ceeb;--color-light-green-base: #90ee90;--color-light-green-strong: #32cd32;--color-coral-base: #f08080;--color-coral-strong: #cd5c5c;--color-salmon-base: #ffa07a;--color-salmon-strong: #fa8072;--color-seagreen-base: #20b2aa;--color-seagreen-strong: #2e8b57}.folder-container{position:relative;width:100%;display:flex;flex-direction:column;perspective:800px;-webkit-perspective:800px;max-width:160px;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}.folder-container.open .page-sheet{-webkit-transform:translateY(-8px);transform:translateY(-8px);transition-delay:.2s}.folder-container.open .page-sheet:nth-child(1){-webkit-transform:scale(1) translateY(-8px) rotateX(-45deg) translateZ(.1px);transform:scale(1) translateY(-8px) rotateX(-45deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(2){-webkit-transform:scale(.98) translateY(-12px) rotateX(-36deg) translateZ(.1px);transform:scale(.98) translateY(-12px) rotateX(-36deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(3){-webkit-transform:scale(.96) translateY(-16px) rotateX(-27deg) translateZ(.1px);transform:scale(.96) translateY(-16px) rotateX(-27deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(4){-webkit-transform:scale(.94) translateY(-20px) rotateX(-18deg) translateZ(.1px);transform:scale(.94) translateY(-20px) rotateX(-18deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(5){-webkit-transform:scale(.92) translateY(-24px) rotateX(-9deg) translateZ(.1px);transform:scale(.92) translateY(-24px) rotateX(-9deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(6){-webkit-transform:scale(.9) translateY(-28px) rotateX(0deg) translateZ(.1px);transform:scale(.9) translateY(-28px) rotateX(.1px)}.folder-container.open .folder-front{-webkit-transform:translate3d(0,0,0) rotateX(-45deg);transform:translateZ(0) rotateX(-45deg)}.folder-tab{width:50%;height:auto;display:block}.folder-back{height:128px;border-radius:0 12px 12px;position:relative;margin-top:-1px;transform-style:preserve-3d;-webkit-transform-style:preserve-3d;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0)}.page-sheet{position:absolute;width:80%;height:120px;background:#fff;border-radius:8px;box-shadow:0 -1px 5px #0000001a;border:1px solid var(--border-color-default);transition:transform .3s ease-out;-webkit-transition:-webkit-transform .3s ease-out;left:10%;-webkit-transform:translateZ(0);transform:translateZ(0);transform-style:preserve-3d;-webkit-transform-style:preserve-3d;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-font-smoothing:antialiased;will-change:transform}.page-sheet:nth-child(1){bottom:2px;z-index:6;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(1) translateZ(.1px);transform:scale(1) translateZ(.1px)}.page-sheet:nth-child(2){bottom:8px;z-index:5;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.98) translateZ(.1px);transform:scale(.98) translateZ(.1px)}.page-sheet:nth-child(3){bottom:14px;z-index:4;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.96) translateZ(.1px);transform:scale(.96) translateZ(.1px)}.page-sheet:nth-child(4){bottom:20px;z-index:3;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.94) translateZ(.1px);transform:scale(.94) translateZ(.1px)}.page-sheet:nth-child(5){bottom:26px;z-index:2;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.92) translateZ(.1px);transform:scale(.92) translateZ(.1px)}.page-sheet:nth-child(6){bottom:32px;z-index:1;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.9) translateZ(.1px);transform:scale(.9) translateZ(.1px)}.folder-front{position:absolute;bottom:0;left:0;right:0;height:116px;border-radius:12px;display:flex;align-items:center;justify-content:center;padding:8px;z-index:2;transform-origin:bottom center;-webkit-transform-origin:bottom center;transform-style:preserve-3d;-webkit-transform-style:preserve-3d;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out;-webkit-transition:-webkit-transform .4s ease-in-out;will-change:transform;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-font-smoothing:antialiased;-webkit-transform:rotateX(-20deg) translateZ(.1px);transform:rotateX(-20deg) translateZ(.1px);-webkit-transform:translate3d(0,0,0) rotateX(-20deg);transform:translateZ(0) rotateX(-20deg);box-shadow:inset 0 64px 48px #fff3,inset 0 2px 4px #ffffff4d,inset 0 1px 1px #ffffff4d}.item-count{display:flex;align-items:center;gap:4px}.folder-icon{display:flex;align-items:center;justify-content:center}.folder-label-container{display:flex;flex-direction:column;align-items:center;gap:4px;width:100%;min-width:0}.folder-label{text-align:center;width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.loading-indicator,.error-indicator{font-size:var(--font-size-xs)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
28519
28632
  }
28520
28633
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileHandbookFolderComponent, decorators: [{
28521
28634
  type: Component,
@@ -28549,18 +28662,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28549
28662
  <!-- Label and Item Count -->
28550
28663
  <div class="folder-label-container">
28551
28664
  <div class="folder-label ui-sm-semiBold">{{ label }}</div>
28552
- <div class="item-count ui-sm-regular" [style.color]="'var(--color-text-secondary, #6b7280)'">
28665
+ <div class="item-count ui-xs-regular" [style.color]="'var(--color-text-secondary, #6b7280)'">
28553
28666
  @if (loading) {
28554
28667
  <span class="loading-indicator">{{ textLoading }}</span>
28555
28668
  } @else if (error) {
28556
28669
  <span class="error-indicator" [style.color]="'var(--color-destructive-base)'">{{ textError }}</span>
28557
28670
  } @else {
28558
28671
  <span>{{ itemCount }}</span>
28559
- <span class="item-count-label">{{ textItems }}</span>
28672
+ <span>{{ itemCount === 1 ? textItemSingle : textItemsPlural }}</span>
28560
28673
  }
28561
28674
  </div>
28562
28675
  </div>
28563
- `, styles: [":host{display:inline-flex;flex-direction:column;align-items:center;gap:16px;width:100%;min-width:140px;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;padding:16px;border-radius:16px;background:var(--color-background-neutral-secondary, #f0f0f0);transition:background .2s ease}:host:active{background:var(--color-background-neutral-secondary-hover, #ebebeb)}@media (hover: hover){:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}}:host{--color-red-base: #dc3545;--color-red-strong: #ae1d3b;--color-green-base: #28a745;--color-green-strong: #058057;--color-yellow-base: #ffc107;--color-yellow-strong: #e4b200;--color-purple-base: #6f42c1;--color-purple-strong: #4204c5;--color-indigo-base: #6610f2;--color-indigo-strong: #a527a2;--color-lime-base: #82c91e;--color-lime-strong: #58a503;--color-teal-base: #20c997;--color-teal-strong: #0ca678;--color-cyan-base: #17a2b8;--color-cyan-strong: #1098ad;--color-brown-base: #795548;--color-brown-strong: #5c4033;--color-light-blue-base: #add8e6;--color-light-blue-strong: #87ceeb;--color-light-green-base: #90ee90;--color-light-green-strong: #32cd32;--color-coral-base: #f08080;--color-coral-strong: #cd5c5c;--color-salmon-base: #ffa07a;--color-salmon-strong: #fa8072;--color-seagreen-base: #20b2aa;--color-seagreen-strong: #2e8b57}.folder-container{position:relative;width:100%;display:flex;flex-direction:column;perspective:800px;-webkit-perspective:800px;max-width:160px;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}.folder-container.open .page-sheet{-webkit-transform:translateY(-8px);transform:translateY(-8px);transition-delay:.2s}.folder-container.open .page-sheet:nth-child(1){-webkit-transform:scale(1) translateY(-8px) rotateX(-45deg) translateZ(.1px);transform:scale(1) translateY(-8px) rotateX(-45deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(2){-webkit-transform:scale(.98) translateY(-12px) rotateX(-36deg) translateZ(.1px);transform:scale(.98) translateY(-12px) rotateX(-36deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(3){-webkit-transform:scale(.96) translateY(-16px) rotateX(-27deg) translateZ(.1px);transform:scale(.96) translateY(-16px) rotateX(-27deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(4){-webkit-transform:scale(.94) translateY(-20px) rotateX(-18deg) translateZ(.1px);transform:scale(.94) translateY(-20px) rotateX(-18deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(5){-webkit-transform:scale(.92) translateY(-24px) rotateX(-9deg) translateZ(.1px);transform:scale(.92) translateY(-24px) rotateX(-9deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(6){-webkit-transform:scale(.9) translateY(-28px) rotateX(0deg) translateZ(.1px);transform:scale(.9) translateY(-28px) rotateX(.1px)}.folder-container.open .folder-front{-webkit-transform:translate3d(0,0,0) rotateX(-45deg);transform:translateZ(0) rotateX(-45deg)}.folder-tab{width:50%;height:auto;display:block}.folder-back{height:128px;border-radius:0 12px 12px;position:relative;margin-top:-1px;transform-style:preserve-3d;-webkit-transform-style:preserve-3d;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0)}.page-sheet{position:absolute;width:80%;height:120px;background:#fff;border-radius:8px;box-shadow:0 -1px 5px #0000001a;border:1px solid var(--border-color-default);transition:transform .3s ease-out;-webkit-transition:-webkit-transform .3s ease-out;left:10%;-webkit-transform:translateZ(0);transform:translateZ(0);transform-style:preserve-3d;-webkit-transform-style:preserve-3d;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-font-smoothing:antialiased;will-change:transform}.page-sheet:nth-child(1){bottom:2px;z-index:6;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(1) translateZ(.1px);transform:scale(1) translateZ(.1px)}.page-sheet:nth-child(2){bottom:8px;z-index:5;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.98) translateZ(.1px);transform:scale(.98) translateZ(.1px)}.page-sheet:nth-child(3){bottom:14px;z-index:4;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.96) translateZ(.1px);transform:scale(.96) translateZ(.1px)}.page-sheet:nth-child(4){bottom:20px;z-index:3;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.94) translateZ(.1px);transform:scale(.94) translateZ(.1px)}.page-sheet:nth-child(5){bottom:26px;z-index:2;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.92) translateZ(.1px);transform:scale(.92) translateZ(.1px)}.page-sheet:nth-child(6){bottom:32px;z-index:1;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.9) translateZ(.1px);transform:scale(.9) translateZ(.1px)}.folder-front{position:absolute;bottom:0;left:0;right:0;height:116px;border-radius:12px;display:flex;align-items:center;justify-content:center;padding:8px;z-index:2;transform-origin:bottom center;-webkit-transform-origin:bottom center;transform-style:preserve-3d;-webkit-transform-style:preserve-3d;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out;-webkit-transition:-webkit-transform .4s ease-in-out;will-change:transform;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-font-smoothing:antialiased;-webkit-transform:rotateX(-20deg) translateZ(.1px);transform:rotateX(-20deg) translateZ(.1px);-webkit-transform:translate3d(0,0,0) rotateX(-20deg);transform:translateZ(0) rotateX(-20deg);box-shadow:inset 0 64px 48px #fff3,inset 0 2px 4px #ffffff4d,inset 0 1px 1px #ffffff4d}.item-count{display:flex;align-items:center;gap:4px}.item-count-label{letter-spacing:.5px}.folder-icon{display:flex;align-items:center;justify-content:center}.folder-label-container{display:flex;flex-direction:column;align-items:center;gap:4px;width:100%;min-width:0}.folder-label{text-align:center;width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.loading-indicator,.error-indicator{font-size:var(--font-size-xs)}\n"] }]
28676
+ `, styles: [":host{display:inline-flex;flex-direction:column;align-items:center;gap:16px;width:100%;min-width:140px;cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;padding:16px;border-radius:16px;background:var(--color-background-neutral-secondary, #f0f0f0);transition:background .2s ease}:host:active{background:var(--color-background-neutral-secondary-hover, #ebebeb)}@media (hover: hover){:host:hover{background:var(--color-background-neutral-secondary-hover, #ebebeb)}}:host{--color-red-base: #dc3545;--color-red-strong: #ae1d3b;--color-green-base: #28a745;--color-green-strong: #058057;--color-yellow-base: #ffc107;--color-yellow-strong: #e4b200;--color-purple-base: #6f42c1;--color-purple-strong: #4204c5;--color-indigo-base: #6610f2;--color-indigo-strong: #a527a2;--color-lime-base: #82c91e;--color-lime-strong: #58a503;--color-teal-base: #20c997;--color-teal-strong: #0ca678;--color-cyan-base: #17a2b8;--color-cyan-strong: #1098ad;--color-brown-base: #795548;--color-brown-strong: #5c4033;--color-light-blue-base: #add8e6;--color-light-blue-strong: #87ceeb;--color-light-green-base: #90ee90;--color-light-green-strong: #32cd32;--color-coral-base: #f08080;--color-coral-strong: #cd5c5c;--color-salmon-base: #ffa07a;--color-salmon-strong: #fa8072;--color-seagreen-base: #20b2aa;--color-seagreen-strong: #2e8b57}.folder-container{position:relative;width:100%;display:flex;flex-direction:column;perspective:800px;-webkit-perspective:800px;max-width:160px;transform-style:preserve-3d;-webkit-transform-style:preserve-3d}.folder-container.open .page-sheet{-webkit-transform:translateY(-8px);transform:translateY(-8px);transition-delay:.2s}.folder-container.open .page-sheet:nth-child(1){-webkit-transform:scale(1) translateY(-8px) rotateX(-45deg) translateZ(.1px);transform:scale(1) translateY(-8px) rotateX(-45deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(2){-webkit-transform:scale(.98) translateY(-12px) rotateX(-36deg) translateZ(.1px);transform:scale(.98) translateY(-12px) rotateX(-36deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(3){-webkit-transform:scale(.96) translateY(-16px) rotateX(-27deg) translateZ(.1px);transform:scale(.96) translateY(-16px) rotateX(-27deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(4){-webkit-transform:scale(.94) translateY(-20px) rotateX(-18deg) translateZ(.1px);transform:scale(.94) translateY(-20px) rotateX(-18deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(5){-webkit-transform:scale(.92) translateY(-24px) rotateX(-9deg) translateZ(.1px);transform:scale(.92) translateY(-24px) rotateX(-9deg) translateZ(.1px)}.folder-container.open .page-sheet:nth-child(6){-webkit-transform:scale(.9) translateY(-28px) rotateX(0deg) translateZ(.1px);transform:scale(.9) translateY(-28px) rotateX(.1px)}.folder-container.open .folder-front{-webkit-transform:translate3d(0,0,0) rotateX(-45deg);transform:translateZ(0) rotateX(-45deg)}.folder-tab{width:50%;height:auto;display:block}.folder-back{height:128px;border-radius:0 12px 12px;position:relative;margin-top:-1px;transform-style:preserve-3d;-webkit-transform-style:preserve-3d;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-transform:translateZ(0);transform:translateZ(0)}.page-sheet{position:absolute;width:80%;height:120px;background:#fff;border-radius:8px;box-shadow:0 -1px 5px #0000001a;border:1px solid var(--border-color-default);transition:transform .3s ease-out;-webkit-transition:-webkit-transform .3s ease-out;left:10%;-webkit-transform:translateZ(0);transform:translateZ(0);transform-style:preserve-3d;-webkit-transform-style:preserve-3d;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-font-smoothing:antialiased;will-change:transform}.page-sheet:nth-child(1){bottom:2px;z-index:6;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(1) translateZ(.1px);transform:scale(1) translateZ(.1px)}.page-sheet:nth-child(2){bottom:8px;z-index:5;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.98) translateZ(.1px);transform:scale(.98) translateZ(.1px)}.page-sheet:nth-child(3){bottom:14px;z-index:4;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.96) translateZ(.1px);transform:scale(.96) translateZ(.1px)}.page-sheet:nth-child(4){bottom:20px;z-index:3;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.94) translateZ(.1px);transform:scale(.94) translateZ(.1px)}.page-sheet:nth-child(5){bottom:26px;z-index:2;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.92) translateZ(.1px);transform:scale(.92) translateZ(.1px)}.page-sheet:nth-child(6){bottom:32px;z-index:1;transform-origin:bottom center;-webkit-transform-origin:bottom center;-webkit-transform:scale(.9) translateZ(.1px);transform:scale(.9) translateZ(.1px)}.folder-front{position:absolute;bottom:0;left:0;right:0;height:116px;border-radius:12px;display:flex;align-items:center;justify-content:center;padding:8px;z-index:2;transform-origin:bottom center;-webkit-transform-origin:bottom center;transform-style:preserve-3d;-webkit-transform-style:preserve-3d;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out;-webkit-transition:-webkit-transform .4s ease-in-out;will-change:transform;backface-visibility:hidden;-webkit-backface-visibility:hidden;-webkit-font-smoothing:antialiased;-webkit-transform:rotateX(-20deg) translateZ(.1px);transform:rotateX(-20deg) translateZ(.1px);-webkit-transform:translate3d(0,0,0) rotateX(-20deg);transform:translateZ(0) rotateX(-20deg);box-shadow:inset 0 64px 48px #fff3,inset 0 2px 4px #ffffff4d,inset 0 1px 1px #ffffff4d}.item-count{display:flex;align-items:center;gap:4px}.folder-icon{display:flex;align-items:center;justify-content:center}.folder-label-container{display:flex;flex-direction:column;align-items:center;gap:4px;width:100%;min-width:0}.folder-label{text-align:center;width:100%;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.loading-indicator,.error-indicator{font-size:var(--font-size-xs)}\n"] }]
28564
28677
  }], ctorParameters: () => [{ type: DsMobileHandbookDetailModalService }], propDecorators: { variant: [{
28565
28678
  type: Input
28566
28679
  }], customColor: [{
@@ -28581,7 +28694,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28581
28694
  type: Input
28582
28695
  }], textError: [{
28583
28696
  type: Input
28584
- }], textItems: [{
28697
+ }], textItemSingle: [{
28698
+ type: Input
28699
+ }], textItemsPlural: [{
28585
28700
  type: Input
28586
28701
  }], textClose: [{
28587
28702
  type: Input
@@ -28845,7 +28960,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
28845
28960
  * ```html
28846
28961
  * <ds-mobile-property-banner
28847
28962
  * address="Toftegårds Allé 5A, 2. tv."
28848
- * photoUrl="/Assets/building.jpg"
28963
+ * photoUrl="/assets/building.jpg"
28849
28964
  * [tenantCount]="12">
28850
28965
  * </ds-mobile-property-banner>
28851
28966
  * ```
@@ -29172,7 +29287,7 @@ const SAMPLE_NOTIFICATIONS = [
29172
29287
  // Today — Marcus Lindqvist sent message in conv-2
29173
29288
  { id: '3', type: 'message_new', leading: 'avatar', targetId: 'conv-2', avatarInitials: 'ML', title: 'Marcus Lindqvist', message: 'Kan du tjekke støjproblemet igen?', createdAt: minutesAgo(10), read: false },
29174
29289
  // Today — booking-1 "Festlokale på taget" confirmed
29175
- { id: '4', type: 'booking_confirmed', leading: 'image', targetId: 'booking-1', imageSrc: '/Assets/Dummy-photos/rooftop-party.jpg', title: 'Festlokale på taget', message: 'Din booking d. 14. feb kl. 9:00–17:00 er bekræftet.', createdAt: hoursAgo(2), read: true },
29290
+ { id: '4', type: 'booking_confirmed', leading: 'image', targetId: 'booking-1', imageSrc: '/assets/Dummy-photos/rooftop-party.jpg', title: 'Festlokale på taget', message: 'Din booking d. 14. feb kl. 9:00–17:00 er bekræftet.', createdAt: hoursAgo(2), read: true },
29176
29291
  // Today — Anders Jensen commented on post-2
29177
29292
  { id: '5', type: 'community_comment', leading: 'avatar', targetId: 'post-2', avatarInitials: 'AJ', title: 'Anders Jensen', message: 'Kommenterede: "Wow, den udsigt er fantastisk!"', createdAt: hoursAgo(3), read: true },
29178
29293
  // Yesterday — Blik Partner A/S assigned to inquiry #2
@@ -29180,9 +29295,9 @@ const SAMPLE_NOTIFICATIONS = [
29180
29295
  // Yesterday — Sophie Andersen posted in community (post-2)
29181
29296
  { id: '7', type: 'community_post', leading: 'avatar', targetId: 'post-2', avatarInitials: 'SA', title: 'Sophie Andersen', message: 'Nyt opslag med billeder fra ejendommen.', createdAt: daysAgo(1, 14, 20), read: true },
29182
29297
  // Yesterday — booking-3 "Boremaskinen" reminder
29183
- { id: '8', type: 'booking_reminder', leading: 'image', targetId: 'booking-3', imageSrc: '/Assets/Dummy-photos/handyman.jpg', title: 'Boremaskinen', message: 'Du har en booking d. 25. mar kl. 10:00–14:00.', createdAt: daysAgo(1, 9, 0), read: true },
29298
+ { id: '8', type: 'booking_reminder', leading: 'image', targetId: 'booking-3', imageSrc: '/assets/Dummy-photos/handyman.jpg', title: 'Boremaskinen', message: 'Du har en booking d. 25. mar kl. 10:00–14:00.', createdAt: daysAgo(1, 9, 0), read: true },
29184
29299
  // Yesterday — facility-1 "Boremaskinen" available
29185
- { id: '9', type: 'facility_available', leading: 'image', targetId: 'facility-1', imageSrc: '/Assets/Dummy-photos/handyman.jpg', title: 'Boremaskinen', message: 'Boremaskinen er nu ledig til booking.', createdAt: daysAgo(1, 8, 15), read: true },
29300
+ { id: '9', type: 'facility_available', leading: 'image', targetId: 'facility-1', imageSrc: '/assets/Dummy-photos/handyman.jpg', title: 'Boremaskinen', message: 'Boremaskinen er nu ledig til booking.', createdAt: daysAgo(1, 8, 15), read: true },
29186
29301
  // Yesterday — group "Vaskeri & møde" message
29187
29302
  { id: '10', type: 'message_group', leading: 'avatar', targetId: 'conv-group-demo', avatarInitials: 'VM', title: 'Vaskeri & møde', message: 'Anna Berg: "Vi mødes kl. 19 i fællesrummet."', createdAt: daysAgo(1, 19, 30), read: true },
29188
29303
  // Earlier — inquiry #3 resolved
@@ -29190,11 +29305,11 @@ const SAMPLE_NOTIFICATIONS = [
29190
29305
  // Earlier — handbook updated
29191
29306
  { id: '12', type: 'handbook_update', leading: 'logo', title: 'Håndbog opdateret', message: 'Afsnittet "Forsyninger" er blevet opdateret med ny information.', createdAt: daysAgo(4), read: true },
29192
29307
  // Earlier — ElektroTek ApS service update
29193
- { id: '13', type: 'service_update', leading: 'image', targetId: 'v-4', imageSrc: '/Assets/dummy-logos/electrician-logo.svg', title: 'ElektroTek ApS', message: 'El-service er nu tilgængelig via Services.', createdAt: daysAgo(5), read: true },
29308
+ { id: '13', type: 'service_update', leading: 'image', targetId: 'v-4', imageSrc: '/assets/dummy-logos/electrician-logo.svg', title: 'ElektroTek ApS', message: 'El-service er nu tilgængelig via Services.', createdAt: daysAgo(5), read: true },
29194
29309
  // Earlier — Thomas Hansen commented on post-2
29195
29310
  { id: '14', type: 'community_comment', leading: 'avatar', targetId: 'post-2', avatarInitials: 'TH', title: 'Thomas Hansen', message: 'Kommenterede: "Smuk! Jeg kan også se byens silhuet fra min lejlighed 🌆"', createdAt: daysAgo(6), read: true },
29196
29311
  // Earlier — booking-2 "Gæsteparkering" cancelled
29197
- { id: '15', type: 'booking_cancelled', leading: 'image', targetId: 'booking-2', imageSrc: '/Assets/Dummy-photos/parking.jpg', title: 'Gæsteparkering', message: 'Din booking d. 20. mar kl. 8:00–20:00 er blevet annulleret.', createdAt: daysAgo(7), read: true },
29312
+ { id: '15', type: 'booking_cancelled', leading: 'image', targetId: 'booking-2', imageSrc: '/assets/Dummy-photos/parking.jpg', title: 'Gæsteparkering', message: 'Din booking d. 20. mar kl. 8:00–20:00 er blevet annulleret.', createdAt: daysAgo(7), read: true },
29198
29313
  // Earlier — system announcement
29199
29314
  { id: '16', type: 'system_announcement', leading: 'logo', title: 'Systemmeddelelse', message: 'Planlagt vedligeholdelse d. 1. maj kl. 02:00–04:00.', createdAt: daysAgo(8), read: true },
29200
29315
  // Earlier — Karl Johansson message in conv-4
@@ -29538,7 +29653,7 @@ class DsMobileNotificationModalComponent {
29538
29653
  }
29539
29654
  } @else {
29540
29655
  <ds-mobile-empty-state
29541
- imageSrc="/Assets/empty-state-notification.svg"
29656
+ imageSrc="/assets/empty-state-notification.svg"
29542
29657
  imageAlt="Ingen notifikationer"
29543
29658
  title="Alt er stille herinde"
29544
29659
  description="Når der sker noget nyt, finder du det her."
@@ -29636,7 +29751,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
29636
29751
  }
29637
29752
  } @else {
29638
29753
  <ds-mobile-empty-state
29639
- imageSrc="/Assets/empty-state-notification.svg"
29754
+ imageSrc="/assets/empty-state-notification.svg"
29640
29755
  imageAlt="Ingen notifikationer"
29641
29756
  title="Alt er stille herinde"
29642
29757
  description="Når der sker noget nyt, finder du det her."
@@ -30563,7 +30678,7 @@ const BOOKING_DETAIL_MAP = {
30563
30678
  'booking-1': {
30564
30679
  id: 'booking-1',
30565
30680
  facilityTitle: 'Festlokale på taget',
30566
- heroImage: '/Assets/Dummy-photos/rooftop-party.jpg',
30681
+ heroImage: '/assets/Dummy-photos/rooftop-party.jpg',
30567
30682
  bookingDate: '14. februar',
30568
30683
  bookingTime: '9:00 - 17:00',
30569
30684
  price: '200 kr. per booking',
@@ -30572,7 +30687,7 @@ const BOOKING_DETAIL_MAP = {
30572
30687
  'booking-2': {
30573
30688
  id: 'booking-2',
30574
30689
  facilityTitle: 'Gæsteparkering',
30575
- heroImage: '/Assets/Dummy-photos/parking.jpg',
30690
+ heroImage: '/assets/Dummy-photos/parking.jpg',
30576
30691
  bookingDate: '20. marts',
30577
30692
  bookingTime: '8:00 - 20:00',
30578
30693
  price: '50 kr. per booking',
@@ -30581,7 +30696,7 @@ const BOOKING_DETAIL_MAP = {
30581
30696
  'booking-3': {
30582
30697
  id: 'booking-3',
30583
30698
  facilityTitle: 'Boremaskinen',
30584
- heroImage: '/Assets/Dummy-photos/handyman.jpg',
30699
+ heroImage: '/assets/Dummy-photos/handyman.jpg',
30585
30700
  bookingDate: '25. marts',
30586
30701
  bookingTime: '10:00 - 14:00',
30587
30702
  price: 'Gratis',
@@ -30592,31 +30707,31 @@ const VENDOR_DETAIL_MAP = {
30592
30707
  'v-1': {
30593
30708
  vendorName: 'CleanTeam ApS',
30594
30709
  vendorDescription: '<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>',
30595
- vendorImage: '/Assets/Dummy-photos/clean-team.jpg',
30596
- vendorLogo: '/Assets/dummy-logos/cleanteam-logo.svg',
30710
+ vendorImage: '/assets/Dummy-photos/clean-team.jpg',
30711
+ vendorLogo: '/assets/dummy-logos/cleanteam-logo.svg',
30597
30712
  },
30598
30713
  'v-2': {
30599
30714
  vendorName: 'Nordisk Rengøring',
30600
30715
  vendorDescription: '<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>',
30601
- vendorImage: '/Assets/Dummy-photos/nordic-cleaning.jpg',
30602
- vendorLogo: '/Assets/dummy-logos/nordiccleaning-logo.svg',
30716
+ vendorImage: '/assets/Dummy-photos/nordic-cleaning.jpg',
30717
+ vendorLogo: '/assets/dummy-logos/nordiccleaning-logo.svg',
30603
30718
  },
30604
30719
  'v-3': {
30605
30720
  vendorName: 'Blik Partner A/S',
30606
30721
  vendorDescription: '<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>',
30607
- vendorImage: '/Assets/Dummy-photos/plumbing.jpg',
30722
+ vendorImage: '/assets/Dummy-photos/plumbing.jpg',
30608
30723
  },
30609
30724
  'v-4': {
30610
30725
  vendorName: 'ElektroTek ApS',
30611
30726
  vendorDescription: '<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>',
30612
- vendorImage: '/Assets/Dummy-photos/electrician.jpg',
30613
- vendorLogo: '/Assets/dummy-logos/electrician-logo.svg',
30727
+ vendorImage: '/assets/Dummy-photos/electrician.jpg',
30728
+ vendorLogo: '/assets/dummy-logos/electrician-logo.svg',
30614
30729
  },
30615
30730
  'v-5': {
30616
30731
  vendorName: 'HaveService Danmark',
30617
30732
  vendorDescription: '<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>',
30618
- vendorImage: '/Assets/Dummy-photos/gardener.jpg',
30619
- vendorLogo: '/Assets/dummy-logos/gardener-logo.svg',
30733
+ vendorImage: '/assets/Dummy-photos/gardener.jpg',
30734
+ vendorLogo: '/assets/dummy-logos/gardener-logo.svg',
30620
30735
  },
30621
30736
  };
30622
30737
  class DsMobileNotificationModalService extends BaseModalService {
@@ -31002,7 +31117,7 @@ class MobileCommunityPageComponent {
31002
31117
  await this.lightbox.openPdf({
31003
31118
  pdf: {
31004
31119
  type: 'pdf',
31005
- src: '/Assets/House_Rules.pdf', // Capital A to match public/Assets folder structure
31120
+ src: '/assets/House_Rules.pdf', // Capital A to match public/Assets folder structure
31006
31121
  title: 'House Rules',
31007
31122
  description: 'Building regulations and community guidelines',
31008
31123
  fileSize: 250880, // 245 KB in bytes
@@ -31248,10 +31363,10 @@ class MobileCommunityPageComponent {
31248
31363
  <post-text>{{ post.content }}</post-text>
31249
31364
  <ds-mobile-inline-photo
31250
31365
  [images]="[
31251
- '/Assets/Dummy-photos/balcony-view.jpg',
31252
- '/Assets/Dummy-photos/staircase.jpg',
31253
- '/Assets/Dummy-photos/park.jpg',
31254
- '/Assets/Dummy-photos/yard.jpg'
31366
+ '/assets/Dummy-photos/balcony-view.jpg',
31367
+ '/assets/Dummy-photos/staircase.jpg',
31368
+ '/assets/Dummy-photos/park.jpg',
31369
+ '/assets/Dummy-photos/yard.jpg'
31255
31370
  ]"
31256
31371
  [author]="{
31257
31372
  name: 'Sophie Andersen',
@@ -31287,12 +31402,12 @@ class MobileCommunityPageComponent {
31287
31402
  <post-text>{{ post.content }}</post-text>
31288
31403
  <ds-mobile-inline-photo
31289
31404
  [images]="[
31290
- '/Assets/Dummy-photos/mailboxes.jpg',
31291
- '/Assets/Dummy-photos/staircase.jpg',
31292
- '/Assets/Dummy-photos/yard.jpg',
31293
- '/Assets/Dummy-photos/park.jpg',
31294
- '/Assets/Dummy-photos/balcony-view.jpg',
31295
- '/Assets/Dummy-photos/handyman.jpg'
31405
+ '/assets/Dummy-photos/mailboxes.jpg',
31406
+ '/assets/Dummy-photos/staircase.jpg',
31407
+ '/assets/Dummy-photos/yard.jpg',
31408
+ '/assets/Dummy-photos/park.jpg',
31409
+ '/assets/Dummy-photos/balcony-view.jpg',
31410
+ '/assets/Dummy-photos/handyman.jpg'
31296
31411
  ]"
31297
31412
  [author]="{
31298
31413
  name: 'Karen Nielsen',
@@ -31353,7 +31468,7 @@ class MobileCommunityPageComponent {
31353
31468
  <!-- Empty State -->
31354
31469
  <div class="community-empty-state">
31355
31470
  <img
31356
- src="/Assets/Empty%20state-chat.png"
31471
+ src="/assets/Empty%20state-chat.png"
31357
31472
  alt="Ingen opslag endnu"
31358
31473
  class="empty-state-image"
31359
31474
  />
@@ -31531,10 +31646,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
31531
31646
  <post-text>{{ post.content }}</post-text>
31532
31647
  <ds-mobile-inline-photo
31533
31648
  [images]="[
31534
- '/Assets/Dummy-photos/balcony-view.jpg',
31535
- '/Assets/Dummy-photos/staircase.jpg',
31536
- '/Assets/Dummy-photos/park.jpg',
31537
- '/Assets/Dummy-photos/yard.jpg'
31649
+ '/assets/Dummy-photos/balcony-view.jpg',
31650
+ '/assets/Dummy-photos/staircase.jpg',
31651
+ '/assets/Dummy-photos/park.jpg',
31652
+ '/assets/Dummy-photos/yard.jpg'
31538
31653
  ]"
31539
31654
  [author]="{
31540
31655
  name: 'Sophie Andersen',
@@ -31570,12 +31685,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
31570
31685
  <post-text>{{ post.content }}</post-text>
31571
31686
  <ds-mobile-inline-photo
31572
31687
  [images]="[
31573
- '/Assets/Dummy-photos/mailboxes.jpg',
31574
- '/Assets/Dummy-photos/staircase.jpg',
31575
- '/Assets/Dummy-photos/yard.jpg',
31576
- '/Assets/Dummy-photos/park.jpg',
31577
- '/Assets/Dummy-photos/balcony-view.jpg',
31578
- '/Assets/Dummy-photos/handyman.jpg'
31688
+ '/assets/Dummy-photos/mailboxes.jpg',
31689
+ '/assets/Dummy-photos/staircase.jpg',
31690
+ '/assets/Dummy-photos/yard.jpg',
31691
+ '/assets/Dummy-photos/park.jpg',
31692
+ '/assets/Dummy-photos/balcony-view.jpg',
31693
+ '/assets/Dummy-photos/handyman.jpg'
31579
31694
  ]"
31580
31695
  [author]="{
31581
31696
  name: 'Karen Nielsen',
@@ -31636,7 +31751,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
31636
31751
  <!-- Empty State -->
31637
31752
  <div class="community-empty-state">
31638
31753
  <img
31639
- src="/Assets/Empty%20state-chat.png"
31754
+ src="/assets/Empty%20state-chat.png"
31640
31755
  alt="Ingen opslag endnu"
31641
31756
  class="empty-state-image"
31642
31757
  />
@@ -31750,7 +31865,7 @@ class MobileHandbookPageComponent {
31750
31865
  {
31751
31866
  title: 'Fælles områder og sikkerhed',
31752
31867
  description: 'Trappeopgange med nødbelysning og brandsikre døre. Postkasser placeret i indgangspartiet. Hold altid flugtveje fri.',
31753
- images: ['/Assets/Dummy-photos/staircase.jpg', '/Assets/Dummy-photos/mailboxes.jpg'],
31868
+ images: ['/assets/Dummy-photos/staircase.jpg', '/assets/Dummy-photos/mailboxes.jpg'],
31754
31869
  },
31755
31870
  {
31756
31871
  title: 'Hjertestarter (AED)',
@@ -31813,7 +31928,7 @@ class MobileHandbookPageComponent {
31813
31928
  {
31814
31929
  title: 'Udendørs arealer',
31815
31930
  description: 'Fælles grønne områder med bede, siddepladser og terrasse. Beboere må frit benytte området. Respektér planterne og hold området pænt.',
31816
- images: ['/Assets/Dummy-photos/park.jpg', '/Assets/Dummy-photos/yard.jpg'],
31931
+ images: ['/assets/Dummy-photos/park.jpg', '/assets/Dummy-photos/yard.jpg'],
31817
31932
  },
31818
31933
  {
31819
31934
  title: 'Havevedligeholdelse',
@@ -31868,7 +31983,7 @@ class MobileHandbookPageComponent {
31868
31983
  {
31869
31984
  title: 'Balkon udsigt',
31870
31985
  description: 'Eksempel på udsigt fra øverste etagers balkoner. Flere lejligheder har privat altan med fantastisk udsyn.',
31871
- images: ['/Assets/Dummy-photos/balcony-view.jpg'],
31986
+ images: ['/assets/Dummy-photos/balcony-view.jpg'],
31872
31987
  },
31873
31988
  {
31874
31989
  title: 'Vaskerum',
@@ -31892,7 +32007,7 @@ class MobileHandbookPageComponent {
31892
32007
  {
31893
32008
  title: 'Vedligeholdelse og reparationer',
31894
32009
  description: 'Ved behov for reparationer eller vedligeholdelse i din lejlighed, kontakt vores hausmeister. Akutte problemer håndteres samme dag.',
31895
- images: ['/Assets/Dummy-photos/handyman.jpg'],
32010
+ images: ['/assets/Dummy-photos/handyman.jpg'],
31896
32011
  contacts: [
31897
32012
  {
31898
32013
  name: 'Hausmeister Service',
@@ -31955,7 +32070,7 @@ class MobileHandbookPageComponent {
31955
32070
  </div>
31956
32071
  </ds-mobile-section>
31957
32072
  </ds-mobile-page-main>
31958
- `, isInline: true, styles: [".folders-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;justify-items:center}@media (min-width: 768px){.folders-grid{grid-template-columns:repeat(3,1fr)}}ds-mobile-handbook-folder{width:100%;min-width:0}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "firstEntry", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showNotification", "notificationCount", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "contentPadding", "profileMenuItems"], outputs: ["notificationClick", "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: DsMobileHandbookFolderComponent, selector: "ds-mobile-handbook-folder", inputs: ["variant", "customColor", "iconName", "itemCount", "label", "items", "loading", "error", "textLoading", "textError", "textItems", "textClose", "textEmptyTitle", "textEmptyDescription", "textCall", "textCopyPhone", "textEmail", "textCopyEmail"] }, { kind: "component", type: DsMobileOfflineBannerComponent, selector: "ds-mobile-offline-banner", inputs: ["icon", "title", "message"] }] });
32073
+ `, isInline: true, styles: [".folders-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;justify-items:center}@media (min-width: 768px){.folders-grid{grid-template-columns:repeat(3,1fr)}}ds-mobile-handbook-folder{width:100%;min-width:0}\n"], dependencies: [{ kind: "component", type: DsMobilePageMainComponent, selector: "ds-mobile-page-main", inputs: ["title", "headerTitle", "headerSubtitle", "firstEntry", "avatarType", "avatarInitials", "avatarSrc", "avatarIconName", "showNotification", "notificationCount", "showRefresh", "showCondensedHeader", "scrollThreshold", "headerFadeDistance", "contentPadding", "profileMenuItems"], outputs: ["notificationClick", "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: DsMobileHandbookFolderComponent, selector: "ds-mobile-handbook-folder", inputs: ["variant", "customColor", "iconName", "itemCount", "label", "items", "loading", "error", "textLoading", "textError", "textItemSingle", "textItemsPlural", "textClose", "textEmptyTitle", "textEmptyDescription", "textCall", "textCopyPhone", "textEmail", "textCopyEmail"] }, { kind: "component", type: DsMobileOfflineBannerComponent, selector: "ds-mobile-offline-banner", inputs: ["icon", "title", "message"] }] });
31959
32074
  }
31960
32075
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MobileHandbookPageComponent, decorators: [{
31961
32076
  type: Component,
@@ -32551,8 +32666,8 @@ class MobileHomePageComponent {
32551
32666
  category: 'Rengøring',
32552
32667
  description: 'Trappevask og vinduespolering',
32553
32668
  phone: '+45 70 20 30 40',
32554
- logo: '/Assets/dummy-logos/cleanteam-logo.svg',
32555
- thumbnail: '/Assets/Dummy-photos/clean-team.jpg',
32669
+ logo: '/assets/dummy-logos/cleanteam-logo.svg',
32670
+ thumbnail: '/assets/Dummy-photos/clean-team.jpg',
32556
32671
  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>',
32557
32672
  },
32558
32673
  {
@@ -32561,7 +32676,7 @@ class MobileHomePageComponent {
32561
32676
  category: 'VVS',
32562
32677
  description: 'VVS-service og akut udkald',
32563
32678
  phone: '+45 33 44 55 66',
32564
- thumbnail: '/Assets/Dummy-photos/plumbing.jpg',
32679
+ thumbnail: '/assets/Dummy-photos/plumbing.jpg',
32565
32680
  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>',
32566
32681
  },
32567
32682
  {
@@ -32570,9 +32685,9 @@ class MobileHomePageComponent {
32570
32685
  category: 'Elektriker',
32571
32686
  description: 'El-installationer og fejlsøgning',
32572
32687
  phone: '+45 23 45 67 89',
32573
- logo: '/Assets/dummy-logos/electrician-logo.svg',
32574
- thumbnail: '/Assets/Dummy-photos/electrician.jpg',
32575
- heroImage: '/Assets/Dummy-photos/electrician.jpg',
32688
+ logo: '/assets/dummy-logos/electrician-logo.svg',
32689
+ thumbnail: '/assets/Dummy-photos/electrician.jpg',
32690
+ heroImage: '/assets/Dummy-photos/electrician.jpg',
32576
32691
  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>',
32577
32692
  },
32578
32693
  ], ...(ngDevMode ? [{ debugName: "allVendors" }] : []));
@@ -32781,7 +32896,7 @@ class MobileHomePageComponent {
32781
32896
  (keydown.space)="$event.preventDefault(); navigateToTenants()"
32782
32897
  aria-label="Se beboere på ejendommen"
32783
32898
  >
32784
- <ds-mobile-property-banner address="Toftegårds Allé 5A, 2. tv." photoUrl="/Assets/Dummy-photos/building.jpg" [tenantCount]="24"> </ds-mobile-property-banner>
32899
+ <ds-mobile-property-banner address="Toftegårds Allé 5A, 2. tv." photoUrl="/assets/Dummy-photos/building.jpg" [tenantCount]="24"> </ds-mobile-property-banner>
32785
32900
  </div>
32786
32901
 
32787
32902
  @if (familyAccessService.acceptedInviteContext(); as invite) {
@@ -32993,7 +33108,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
32993
33108
  (keydown.space)="$event.preventDefault(); navigateToTenants()"
32994
33109
  aria-label="Se beboere på ejendommen"
32995
33110
  >
32996
- <ds-mobile-property-banner address="Toftegårds Allé 5A, 2. tv." photoUrl="/Assets/Dummy-photos/building.jpg" [tenantCount]="24"> </ds-mobile-property-banner>
33111
+ <ds-mobile-property-banner address="Toftegårds Allé 5A, 2. tv." photoUrl="/assets/Dummy-photos/building.jpg" [tenantCount]="24"> </ds-mobile-property-banner>
32997
33112
  </div>
32998
33113
 
32999
33114
  @if (familyAccessService.acceptedInviteContext(); as invite) {
@@ -33451,11 +33566,11 @@ class MobileInquiryDetailPageComponent {
33451
33566
  }
33452
33567
  }
33453
33568
  photos = [
33454
- { type: 'image', src: '/Assets/Dummy-photos/handyman.jpg', alt: 'Handyman', title: 'Handyman' },
33455
- { type: 'image', src: '/Assets/Dummy-photos/balcony-view.jpg', alt: 'Balcony view', title: 'Balcony view' },
33456
- { type: 'image', src: '/Assets/Dummy-photos/staircase.jpg', alt: 'Staircase', title: 'Staircase' },
33457
- { type: 'image', src: '/Assets/Dummy-photos/yard.jpg', alt: 'Yard', title: 'Yard' },
33458
- { type: 'image', src: '/Assets/Dummy-photos/mailboxes.jpg', alt: 'Mailboxes', title: 'Mailboxes' }
33569
+ { type: 'image', src: '/assets/Dummy-photos/handyman.jpg', alt: 'Handyman', title: 'Handyman' },
33570
+ { type: 'image', src: '/assets/Dummy-photos/balcony-view.jpg', alt: 'Balcony view', title: 'Balcony view' },
33571
+ { type: 'image', src: '/assets/Dummy-photos/staircase.jpg', alt: 'Staircase', title: 'Staircase' },
33572
+ { type: 'image', src: '/assets/Dummy-photos/yard.jpg', alt: 'Yard', title: 'Yard' },
33573
+ { type: 'image', src: '/assets/Dummy-photos/mailboxes.jpg', alt: 'Mailboxes', title: 'Mailboxes' }
33459
33574
  ];
33460
33575
  get photoUrls() {
33461
33576
  return this.photos.map(photo => photo.src);
@@ -33755,7 +33870,7 @@ class MobileInquiryDetailPageComponent {
33755
33870
  } @else {
33756
33871
  <ds-mobile-section>
33757
33872
  <div class="empty-messages">
33758
- <img class="empty-messages-image" src="/Assets/Empty state-chat.png" alt="Ingen beskeder" />
33873
+ <img class="empty-messages-image" src="/assets/Empty state-chat.png" alt="Ingen beskeder" />
33759
33874
  <p class="empty-messages-text">Ingen beskeder endnu</p>
33760
33875
  </div>
33761
33876
  </ds-mobile-section>
@@ -33911,7 +34026,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
33911
34026
  } @else {
33912
34027
  <ds-mobile-section>
33913
34028
  <div class="empty-messages">
33914
- <img class="empty-messages-image" src="/Assets/Empty state-chat.png" alt="Ingen beskeder" />
34029
+ <img class="empty-messages-image" src="/assets/Empty state-chat.png" alt="Ingen beskeder" />
33915
34030
  <p class="empty-messages-text">Ingen beskeder endnu</p>
33916
34031
  </div>
33917
34032
  </ds-mobile-section>
@@ -34168,8 +34283,8 @@ class WhitelabelDemoModalComponent {
34168
34283
  applyDefaultTheme() {
34169
34284
  this.currentTheme = 'default';
34170
34285
  this.whitelabelService.updateConfig({
34171
- logoUrl: '/Assets/logos/propbinder-logomark.svg',
34172
- logoMarkUrl: '/Assets/logos/propbinder-logomark.svg',
34286
+ logoUrl: '/assets/logos/propbinder-logomark.svg',
34287
+ logoMarkUrl: '/assets/logos/propbinder-logomark.svg',
34173
34288
  logoAlt: 'Propbinder',
34174
34289
  logoSize: 'md',
34175
34290
  appIconSurface: '#6B5FF5',
@@ -34196,8 +34311,8 @@ class WhitelabelDemoModalComponent {
34196
34311
  applyCejTheme() {
34197
34312
  this.currentTheme = 'cej';
34198
34313
  this.whitelabelService.updateConfig({
34199
- logoUrl: '/Assets/logos/cej-logo.png',
34200
- logoMarkUrl: '/Assets/logos/cej-logo.png',
34314
+ logoUrl: '/assets/logos/cej-logo.png',
34315
+ logoMarkUrl: '/assets/logos/cej-logo.png',
34201
34316
  logoAlt: 'CEJ',
34202
34317
  logoSize: 'xl',
34203
34318
  appIconSurface: '#A70923',
@@ -34224,8 +34339,8 @@ class WhitelabelDemoModalComponent {
34224
34339
  applyPkaTheme() {
34225
34340
  this.currentTheme = 'pka';
34226
34341
  this.whitelabelService.updateConfig({
34227
- logoUrl: '/Assets/logos/pka-logo.svg',
34228
- logoMarkUrl: '/Assets/logos/pka-logo.svg',
34342
+ logoUrl: '/assets/logos/pka-logo.svg',
34343
+ logoMarkUrl: '/assets/logos/pka-logo.svg',
34229
34344
  logoAlt: 'PKA',
34230
34345
  logoSize: 'md',
34231
34346
  appIconSurface: '#CC006C',
@@ -34252,8 +34367,8 @@ class WhitelabelDemoModalComponent {
34252
34367
  applyClaveTheme() {
34253
34368
  this.currentTheme = 'clave';
34254
34369
  this.whitelabelService.updateConfig({
34255
- logoUrl: '/Assets/logos/clave-logo.svg',
34256
- logoMarkUrl: '/Assets/logos/clave-logo.svg',
34370
+ logoUrl: '/assets/logos/clave-logo.svg',
34371
+ logoMarkUrl: '/assets/logos/clave-logo.svg',
34257
34372
  logoAlt: 'Clave',
34258
34373
  logoSize: 'lg',
34259
34374
  appIconSurface: '#262424',
@@ -34280,8 +34395,8 @@ class WhitelabelDemoModalComponent {
34280
34395
  applyFreedomTheme() {
34281
34396
  this.currentTheme = 'freedom';
34282
34397
  this.whitelabelService.updateConfig({
34283
- logoUrl: '/Assets/logos/freedom-logo.svg',
34284
- logoMarkUrl: '/Assets/logos/freedom-logomark.svg',
34398
+ logoUrl: '/assets/logos/freedom-logo.svg',
34399
+ logoMarkUrl: '/assets/logos/freedom-logomark.svg',
34285
34400
  logoAlt: 'Freedom',
34286
34401
  logoSize: 'md',
34287
34402
  appIconSurface: '#1D4A49',
@@ -34308,8 +34423,8 @@ class WhitelabelDemoModalComponent {
34308
34423
  applyCobblestoneTheme() {
34309
34424
  this.currentTheme = 'cobblestone';
34310
34425
  this.whitelabelService.updateConfig({
34311
- logoUrl: '/Assets/logos/cobblestone-logo.svg',
34312
- logoMarkUrl: '/Assets/logos/cobblestone-logomark.svg',
34426
+ logoUrl: '/assets/logos/cobblestone-logo.svg',
34427
+ logoMarkUrl: '/assets/logos/cobblestone-logomark.svg',
34313
34428
  logoAlt: 'Cobblestone',
34314
34429
  logoSize: 'sm',
34315
34430
  appIconSurface: '#2C3E50',
@@ -35681,12 +35796,12 @@ class MobileBookingPageComponent {
35681
35796
  activeBookings = signal([
35682
35797
  {
35683
35798
  id: 'booking-1',
35684
- thumbnail: '/Assets/Dummy-photos/rooftop-party.jpg',
35799
+ thumbnail: '/assets/Dummy-photos/rooftop-party.jpg',
35685
35800
  facilityTitle: 'Festlokale på taget',
35686
35801
  bookingDate: '14. februar, 2026',
35687
35802
  bookingTime: '9:00 - 17:00',
35688
35803
  price: '200 kr. per booking',
35689
- heroImage: '/Assets/Dummy-photos/rooftop-party.jpg',
35804
+ heroImage: '/assets/Dummy-photos/rooftop-party.jpg',
35690
35805
  fullDescription: '<p>Festlokalet på taget giver jer et lyst og indbydende rum med flot udsigt over byen. Lokalet er velegnet til fødselsdage, mindre sammenkomster og hyggelige middage med naboer og venner.</p>',
35691
35806
  requirements: ['Kræver nøglekort'],
35692
35807
  bookingType: 'Øjeblikkelig booking',
@@ -35699,12 +35814,12 @@ class MobileBookingPageComponent {
35699
35814
  },
35700
35815
  {
35701
35816
  id: 'booking-2',
35702
- thumbnail: '/Assets/Dummy-photos/parking.jpg',
35817
+ thumbnail: '/assets/Dummy-photos/parking.jpg',
35703
35818
  facilityTitle: 'Gæsteparkering',
35704
35819
  bookingDate: '20. marts, 2026',
35705
35820
  bookingTime: '8:00 - 20:00',
35706
35821
  price: '50 kr. per booking',
35707
- heroImage: '/Assets/Dummy-photos/parking.jpg',
35822
+ heroImage: '/assets/Dummy-photos/parking.jpg',
35708
35823
  fullDescription: '<p>Ekstra gæsteparkeringspladser er tilgængelige for beboere, der har brug for parkering til besøgende.</p>',
35709
35824
  requirements: ['Kræver nøglekort'],
35710
35825
  bookingType: 'Forudgående booking påkrævet',
@@ -35715,12 +35830,12 @@ class MobileBookingPageComponent {
35715
35830
  },
35716
35831
  {
35717
35832
  id: 'booking-3',
35718
- thumbnail: '/Assets/Dummy-photos/handyman.jpg',
35833
+ thumbnail: '/assets/Dummy-photos/handyman.jpg',
35719
35834
  facilityTitle: 'Boremaskinen',
35720
35835
  bookingDate: '25. marts, 2026',
35721
35836
  bookingTime: '10:00 - 14:00',
35722
35837
  price: 'Gratis',
35723
- heroImage: '/Assets/Dummy-photos/handyman.jpg',
35838
+ heroImage: '/assets/Dummy-photos/handyman.jpg',
35724
35839
  fullDescription: '<p>Vores boremaskine i professionel kvalitet er tilgængelig for alle beboere til mindre forbedringer i hjemmet.</p>',
35725
35840
  requirements: ['Kræver nøglekort'],
35726
35841
  bookingType: 'Øjeblikkelig booking',
@@ -35734,14 +35849,14 @@ class MobileBookingPageComponent {
35734
35849
  availableFacilities = signal([
35735
35850
  {
35736
35851
  id: 'facility-1',
35737
- thumbnail: '/Assets/Dummy-photos/handyman.jpg',
35852
+ thumbnail: '/assets/Dummy-photos/handyman.jpg',
35738
35853
  facilityTitle: 'Boremaskinen',
35739
35854
  availabilityStatus: 'available-today',
35740
35855
  statusLabel: 'Ledig i dag',
35741
35856
  whenCanBook: 'Lørdag, søndag, 09:00 til 17:30, Op til 48 timer',
35742
35857
  price: 'Gratis',
35743
35858
  capacity: '2–5 personer',
35744
- heroImage: '/Assets/Dummy-photos/handyman.jpg',
35859
+ heroImage: '/assets/Dummy-photos/handyman.jpg',
35745
35860
  fullDescription: `
35746
35861
  <p>Vores boremaskine i professionel kvalitet er tilgængelig for alle beboere til mindre forbedringer i hjemmet. Den er ideel til ophængning af hylder, montering af beslag og andre boreopgaver i lejligheden.</p>
35747
35862
 
@@ -35763,14 +35878,14 @@ class MobileBookingPageComponent {
35763
35878
  },
35764
35879
  {
35765
35880
  id: 'facility-2',
35766
- thumbnail: '/Assets/Dummy-photos/rooftop-party.jpg',
35881
+ thumbnail: '/assets/Dummy-photos/rooftop-party.jpg',
35767
35882
  facilityTitle: 'Festlokale på taget',
35768
35883
  availabilityStatus: 'available-today',
35769
35884
  statusLabel: 'Ledig i dag',
35770
35885
  whenCanBook: 'Fredag–søndag, 10:00 til 22:00, Op til 3 timer',
35771
35886
  price: '200 kr. per booking',
35772
35887
  capacity: '6–15 personer',
35773
- heroImage: '/Assets/Dummy-photos/rooftop-party.jpg',
35888
+ heroImage: '/assets/Dummy-photos/rooftop-party.jpg',
35774
35889
  fullDescription: `
35775
35890
  <p>Tagterrassen er indrettet som et afslappende fristed og et levende samlingspunkt for beboerne med flot udsigt over byen. Uanset om du planlægger en mindre sammenkomst, en rolig aften udendørs eller en hyggelig stund med venner, giver terrassen de perfekte rammer.</p>
35776
35891
 
@@ -35810,14 +35925,14 @@ class MobileBookingPageComponent {
35810
35925
  },
35811
35926
  {
35812
35927
  id: 'facility-3',
35813
- thumbnail: '/Assets/Dummy-photos/parking.jpg',
35928
+ thumbnail: '/assets/Dummy-photos/parking.jpg',
35814
35929
  facilityTitle: 'Gæsteparkering',
35815
35930
  availabilityStatus: 'available-from',
35816
35931
  statusLabel: 'Ledig fra 28. februar, 2026',
35817
35932
  whenCanBook: 'Alle dage, 08:00 til 20:00, Op til 12 timer',
35818
35933
  price: '50 kr. per booking',
35819
35934
  capacity: '1 person',
35820
- heroImage: '/Assets/Dummy-photos/parking.jpg',
35935
+ heroImage: '/assets/Dummy-photos/parking.jpg',
35821
35936
  fullDescription: `
35822
35937
  <p>Ekstra gæsteparkeringspladser er tilgængelige for beboere, der har brug for parkering til besøgende. Pladserne giver dine gæster en nem og tryg parkeringsmulighed tæt på boligen.</p>
35823
35938
 
@@ -35839,14 +35954,14 @@ class MobileBookingPageComponent {
35839
35954
  },
35840
35955
  {
35841
35956
  id: 'facility-4',
35842
- thumbnail: '/Assets/Dummy-photos/yard.jpg',
35957
+ thumbnail: '/assets/Dummy-photos/yard.jpg',
35843
35958
  facilityTitle: 'BBQ område',
35844
35959
  availabilityStatus: 'unavailable',
35845
35960
  statusLabel: 'Ikke tilgængelig',
35846
35961
  whenCanBook: 'Maj–september, 12:00 til 22:00, Op til 4 timer',
35847
35962
  price: 'Gratis',
35848
35963
  capacity: '16–30 personer',
35849
- heroImage: '/Assets/Dummy-photos/yard.jpg',
35964
+ heroImage: '/assets/Dummy-photos/yard.jpg',
35850
35965
  fullDescription: `
35851
35966
  <p>BBQ-området har grill i professionel kvalitet og udendørs siddepladser, perfekt til sommerarrangementer og fællesspisning. Området er velegnet til både mindre familiemåltider og større sociale arrangementer.</p>
35852
35967
 
@@ -36078,7 +36193,7 @@ class MobileBookingPageComponent {
36078
36193
  onSubmit: async (data) => {
36079
36194
  const id = `facility-${Date.now()}`;
36080
36195
  const hero = data.attachments.find((a) => a.type === 'image')?.src;
36081
- const thumb = hero ?? '/Assets/Dummy-photos/handyman.jpg';
36196
+ const thumb = hero ?? '/assets/Dummy-photos/handyman.jpg';
36082
36197
  const row = {
36083
36198
  id,
36084
36199
  thumbnail: thumb,
@@ -36742,10 +36857,10 @@ class MobilePostDetailPageComponent {
36742
36857
  <post-text>Se denne smukke udsigt fra min altan! Morgenkaffe har aldrig smagt så godt ☕️</post-text>
36743
36858
  <post-media>
36744
36859
  <img
36745
- src="/Assets/Dummy-photos/balcony-view.jpg"
36860
+ src="/assets/Dummy-photos/balcony-view.jpg"
36746
36861
  alt="Altanudsigt"
36747
36862
  class="clickable-image"
36748
- (click)="openImageLightbox('/Assets/Dummy-photos/balcony-view.jpg', 'Altanudsigt', 'Morgenkaffe har aldrig smagt så godt ☕️')"
36863
+ (click)="openImageLightbox('/assets/Dummy-photos/balcony-view.jpg', 'Altanudsigt', 'Morgenkaffe har aldrig smagt så godt ☕️')"
36749
36864
  />
36750
36865
  </post-media>
36751
36866
  </post-content>
@@ -36883,10 +36998,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
36883
36998
  <post-text>Se denne smukke udsigt fra min altan! Morgenkaffe har aldrig smagt så godt ☕️</post-text>
36884
36999
  <post-media>
36885
37000
  <img
36886
- src="/Assets/Dummy-photos/balcony-view.jpg"
37001
+ src="/assets/Dummy-photos/balcony-view.jpg"
36887
37002
  alt="Altanudsigt"
36888
37003
  class="clickable-image"
36889
- (click)="openImageLightbox('/Assets/Dummy-photos/balcony-view.jpg', 'Altanudsigt', 'Morgenkaffe har aldrig smagt så godt ☕️')"
37004
+ (click)="openImageLightbox('/assets/Dummy-photos/balcony-view.jpg', 'Altanudsigt', 'Morgenkaffe har aldrig smagt så godt ☕️')"
36890
37005
  />
36891
37006
  </post-media>
36892
37007
  </post-content>
@@ -37125,7 +37240,7 @@ class SignInPageComponent {
37125
37240
  <!-- City background decoration -->
37126
37241
  @if (whitelabelService.showCityIllustration()) {
37127
37242
  <div class="tw-absolute tw-bottom-0 tw-left-0 tw-right-0 tw-w-full tw-h-[35%] tw-z-0 tw-pointer-events-none tw-overflow-hidden md:tw-h-[50%] md:tw-min-h-[400px]" aria-hidden="true">
37128
- <img src="/Assets/city.svg" alt="" class="tw-w-full tw-h-full tw-object-cover tw-object-top" />
37243
+ <img src="/assets/city.svg" alt="" class="tw-w-full tw-h-full tw-object-cover tw-object-top" />
37129
37244
  </div>
37130
37245
  }
37131
37246
 
@@ -37220,7 +37335,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
37220
37335
  <!-- City background decoration -->
37221
37336
  @if (whitelabelService.showCityIllustration()) {
37222
37337
  <div class="tw-absolute tw-bottom-0 tw-left-0 tw-right-0 tw-w-full tw-h-[35%] tw-z-0 tw-pointer-events-none tw-overflow-hidden md:tw-h-[50%] md:tw-min-h-[400px]" aria-hidden="true">
37223
- <img src="/Assets/city.svg" alt="" class="tw-w-full tw-h-full tw-object-cover tw-object-top" />
37338
+ <img src="/assets/city.svg" alt="" class="tw-w-full tw-h-full tw-object-cover tw-object-top" />
37224
37339
  </div>
37225
37340
  }
37226
37341
 
@@ -38227,7 +38342,7 @@ class TenantChatPageComponent {
38227
38342
  @if (peerMessaging.conversations().length === 0) {
38228
38343
  <div class="empty-state">
38229
38344
  <img
38230
- src="/Assets/Empty%20state-chat.png"
38345
+ src="/assets/Empty%20state-chat.png"
38231
38346
  alt="Ingen beskeder"
38232
38347
  class="empty-state-image"
38233
38348
  />
@@ -38303,7 +38418,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
38303
38418
  @if (peerMessaging.conversations().length === 0) {
38304
38419
  <div class="empty-state">
38305
38420
  <img
38306
- src="/Assets/Empty%20state-chat.png"
38421
+ src="/assets/Empty%20state-chat.png"
38307
38422
  alt="Ingen beskeder"
38308
38423
  class="empty-state-image"
38309
38424
  />
@@ -38375,8 +38490,8 @@ const MOCK_VENDORS = [
38375
38490
  category: 'Rengøring',
38376
38491
  description: 'Trappevask og vinduespolering',
38377
38492
  phone: '+45 70 20 30 40',
38378
- logo: '/Assets/dummy-logos/cleanteam-logo.svg',
38379
- thumbnail: '/Assets/Dummy-photos/clean-team.jpg',
38493
+ logo: '/assets/dummy-logos/cleanteam-logo.svg',
38494
+ thumbnail: '/assets/Dummy-photos/clean-team.jpg',
38380
38495
  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>',
38381
38496
  price: '350 kr. per besøg',
38382
38497
  availabilityStatus: 'available-today',
@@ -38387,9 +38502,9 @@ const MOCK_VENDORS = [
38387
38502
  name: 'Nordisk Rengøring',
38388
38503
  category: 'Rengøring',
38389
38504
  description: 'Erhvervs- og boligrengøring',
38390
- logo: '/Assets/dummy-logos/nordiccleaning-logo.svg',
38391
- thumbnail: '/Assets/Dummy-photos/nordic-cleaning.jpg',
38392
- heroImage: '/Assets/Dummy-photos/nordic-cleaning.jpg',
38505
+ logo: '/assets/dummy-logos/nordiccleaning-logo.svg',
38506
+ thumbnail: '/assets/Dummy-photos/nordic-cleaning.jpg',
38507
+ heroImage: '/assets/Dummy-photos/nordic-cleaning.jpg',
38393
38508
  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>',
38394
38509
  price: '275 kr. per time',
38395
38510
  availabilityStatus: 'available-from',
@@ -38401,7 +38516,7 @@ const MOCK_VENDORS = [
38401
38516
  category: 'VVS',
38402
38517
  description: 'VVS-service og akut udkald',
38403
38518
  phone: '+45 33 44 55 66',
38404
- thumbnail: '/Assets/Dummy-photos/plumbing.jpg',
38519
+ thumbnail: '/assets/Dummy-photos/plumbing.jpg',
38405
38520
  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>',
38406
38521
  price: '450 kr. per udkald + tid',
38407
38522
  availabilityStatus: 'available-today',
@@ -38413,9 +38528,9 @@ const MOCK_VENDORS = [
38413
38528
  category: 'Elektriker',
38414
38529
  description: 'El-installationer og fejlsøgning',
38415
38530
  phone: '+45 23 45 67 89',
38416
- logo: '/Assets/dummy-logos/electrician-logo.svg',
38417
- thumbnail: '/Assets/Dummy-photos/electrician.jpg',
38418
- heroImage: '/Assets/Dummy-photos/electrician.jpg',
38531
+ logo: '/assets/dummy-logos/electrician-logo.svg',
38532
+ thumbnail: '/assets/Dummy-photos/electrician.jpg',
38533
+ heroImage: '/assets/Dummy-photos/electrician.jpg',
38419
38534
  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>',
38420
38535
  price: '395 kr. per time',
38421
38536
  availabilityStatus: 'available-today',
@@ -38426,9 +38541,9 @@ const MOCK_VENDORS = [
38426
38541
  name: 'HaveService Danmark',
38427
38542
  category: 'Have & Grønne arealer',
38428
38543
  description: 'Pleje af fællesarealer og haver',
38429
- logo: '/Assets/dummy-logos/gardener-logo.svg',
38430
- thumbnail: '/Assets/Dummy-photos/gardener.jpg',
38431
- heroImage: '/Assets/Dummy-photos/gardener.jpg',
38544
+ logo: '/assets/dummy-logos/gardener-logo.svg',
38545
+ thumbnail: '/assets/Dummy-photos/gardener.jpg',
38546
+ heroImage: '/assets/Dummy-photos/gardener.jpg',
38432
38547
  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>',
38433
38548
  price: '500 kr. per besøg',
38434
38549
  availabilityStatus: 'unavailable',