@propbinder/mobile-design 0.2.50 → 0.2.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/fesm2022/propbinder-mobile-design.mjs +26206 -0
  2. package/fesm2022/propbinder-mobile-design.mjs.map +1 -0
  3. package/index.d.ts +8193 -0
  4. package/package.json +39 -3
  5. package/ng-package.json +0 -24
  6. package/src/animations/page-transitions.ts +0 -165
  7. package/src/components/action-list-item/ds-mobile-action-list-item.ts +0 -102
  8. package/src/components/action-list-item/index.ts +0 -2
  9. package/src/components/app-icon/ds-app-icon.ts +0 -133
  10. package/src/components/app-icon/index.ts +0 -2
  11. package/src/components/attachment-preview/ds-mobile-attachment-preview.css +0 -139
  12. package/src/components/attachment-preview/ds-mobile-attachment-preview.ts +0 -164
  13. package/src/components/attachment-preview/index.ts +0 -1
  14. package/src/components/avatar-with-badge/ds-avatar-with-badge.ts +0 -142
  15. package/src/components/avatar-with-badge/index.ts +0 -2
  16. package/src/components/booking-modal/ds-mobile-booking-confirmation-wrapper.ts +0 -71
  17. package/src/components/booking-modal/ds-mobile-booking-modal.service.ts +0 -121
  18. package/src/components/booking-modal/ds-mobile-booking-modal.ts +0 -598
  19. package/src/components/booking-modal/ds-mobile-booking-summary.ts +0 -161
  20. package/src/components/booking-modal/index.ts +0 -4
  21. package/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts +0 -266
  22. package/src/components/bottom-sheet/ds-mobile-bottom-sheet-header.ts +0 -146
  23. package/src/components/bottom-sheet/ds-mobile-bottom-sheet-wrapper.ts +0 -156
  24. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.css +0 -101
  25. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts +0 -169
  26. package/src/components/bottom-sheet/ds-mobile-confirmation-sheet.ts +0 -211
  27. package/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts +0 -578
  28. package/src/components/bottom-sheet/ds-mobile-profile-actions-sheet.ts +0 -614
  29. package/src/components/bottom-sheet/index.ts +0 -8
  30. package/src/components/bottom-sheet/modal-shadow-fix.ts +0 -42
  31. package/src/components/card-inline/ds-mobile-card-inline.ts +0 -301
  32. package/src/components/card-inline/index.ts +0 -2
  33. package/src/components/card-inline-banner/ds-mobile-card-inline-banner.ts +0 -118
  34. package/src/components/card-inline-banner/index.ts +0 -1
  35. package/src/components/card-inline-contact/ds-mobile-card-inline-contact.ts +0 -120
  36. package/src/components/card-inline-contact/index.ts +0 -1
  37. package/src/components/card-inline-file/ds-mobile-card-inline-file.ts +0 -141
  38. package/src/components/card-inline-file/index.ts +0 -1
  39. package/src/components/chat-modal/ds-mobile-chat-modal.css +0 -159
  40. package/src/components/chat-modal/ds-mobile-chat-modal.service.ts +0 -105
  41. package/src/components/chat-modal/ds-mobile-chat-modal.ts +0 -918
  42. package/src/components/chat-modal/index.ts +0 -8
  43. package/src/components/comment/ds-mobile-comment.ts +0 -568
  44. package/src/components/comment/index.ts +0 -2
  45. package/src/components/contact-list-item/ds-mobile-contact-list-item.ts +0 -182
  46. package/src/components/contact-list-item/index.ts +0 -2
  47. package/src/components/content/ds-mobile-content.ts +0 -139
  48. package/src/components/content/index.ts +0 -2
  49. package/src/components/dropdown/ds-mobile-dropdown.css +0 -199
  50. package/src/components/dropdown/ds-mobile-dropdown.ts +0 -340
  51. package/src/components/dropdown/index.ts +0 -2
  52. package/src/components/ds-mobile-tabs.css +0 -407
  53. package/src/components/ds-mobile-tabs.ts +0 -216
  54. package/src/components/empty-state/ds-mobile-empty-state.ts +0 -120
  55. package/src/components/empty-state/index.ts +0 -2
  56. package/src/components/fab/ds-mobile-fab.ts +0 -315
  57. package/src/components/fab/index.ts +0 -1
  58. package/src/components/facility-creation-modal/ds-mobile-facility-creation-confirmation-wrapper.ts +0 -121
  59. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.css +0 -189
  60. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.service.ts +0 -135
  61. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.ts +0 -656
  62. package/src/components/facility-creation-modal/index.ts +0 -9
  63. package/src/components/facility-creation-modal/sheets/ds-mobile-access-sheet.ts +0 -105
  64. package/src/components/facility-creation-modal/sheets/ds-mobile-price-sheet.ts +0 -188
  65. package/src/components/facility-creation-modal/sheets/ds-mobile-when-can-book-sheet.ts +0 -460
  66. package/src/components/facility-creation-modal/sheets/ds-mobile-who-can-book-sheet.ts +0 -134
  67. package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.service.ts +0 -69
  68. package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.ts +0 -379
  69. package/src/components/facility-detail-modal/index.ts +0 -2
  70. package/src/components/file-attachment/ds-mobile-file-attachment.ts +0 -164
  71. package/src/components/file-attachment/index.ts +0 -2
  72. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.css +0 -214
  73. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts +0 -84
  74. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts +0 -424
  75. package/src/components/handbook-detail-modal/index.ts +0 -3
  76. package/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts +0 -175
  77. package/src/components/handbook-folder/ds-mobile-handbook-folder.ts +0 -533
  78. package/src/components/handbook-folder/index.ts +0 -4
  79. package/src/components/header-content/ds-mobile-header-content.ts +0 -222
  80. package/src/components/header-content/index.ts +0 -2
  81. package/src/components/illustration/ds-mobile-illustration.ts +0 -124
  82. package/src/components/illustration/index.ts +0 -2
  83. package/src/components/index.ts +0 -124
  84. package/src/components/inline-photo/ds-mobile-inline-photo.ts +0 -361
  85. package/src/components/inline-photo/index.ts +0 -1
  86. package/src/components/inline-tabs/ds-mobile-inline-tabs.ts +0 -132
  87. package/src/components/inline-tabs/index.ts +0 -2
  88. package/src/components/interactive-list-item-booking/ds-mobile-interactive-list-item-booking.ts +0 -350
  89. package/src/components/interactive-list-item-booking/index.ts +0 -1
  90. package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts +0 -321
  91. package/src/components/interactive-list-item-inquiry/index.ts +0 -2
  92. package/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts +0 -237
  93. package/src/components/interactive-list-item-message/index.ts +0 -2
  94. package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts +0 -549
  95. package/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts +0 -124
  96. package/src/components/interactive-list-item-post/index.ts +0 -13
  97. package/src/components/lightbox/ds-mobile-lightbox-footer.ts +0 -315
  98. package/src/components/lightbox/ds-mobile-lightbox-header.ts +0 -202
  99. package/src/components/lightbox/ds-mobile-lightbox-image.ts +0 -484
  100. package/src/components/lightbox/ds-mobile-lightbox-pdf.css +0 -377
  101. package/src/components/lightbox/ds-mobile-lightbox-pdf.ts +0 -374
  102. package/src/components/lightbox/ds-mobile-lightbox.css +0 -587
  103. package/src/components/lightbox/ds-mobile-lightbox.service.ts +0 -296
  104. package/src/components/lightbox/ds-mobile-lightbox.ts +0 -529
  105. package/src/components/lightbox/index.ts +0 -22
  106. package/src/components/list-item/ds-mobile-list-item.ts +0 -603
  107. package/src/components/list-item/index.ts +0 -2
  108. package/src/components/list-item-static/ds-mobile-list-item-static.ts +0 -133
  109. package/src/components/list-item-static/index.ts +0 -2
  110. package/src/components/loader-overlay/ds-mobile-loader-overlay.css +0 -49
  111. package/src/components/loader-overlay/ds-mobile-loader-overlay.ts +0 -77
  112. package/src/components/loader-overlay/index.ts +0 -1
  113. package/src/components/logo/ds-logo.ts +0 -95
  114. package/src/components/logo/index.ts +0 -2
  115. package/src/components/message-bubble/ds-mobile-message-bubble.ts +0 -633
  116. package/src/components/message-bubble/index.ts +0 -7
  117. package/src/components/message-composer/ds-mobile-message-composer.ts +0 -1146
  118. package/src/components/message-composer/index.ts +0 -7
  119. package/src/components/modal/ds-mobile-modal.css +0 -163
  120. package/src/components/modal/ds-mobile-modal.service.ts +0 -329
  121. package/src/components/modal/index.ts +0 -8
  122. package/src/components/modal-base/ds-mobile-modal-base.css +0 -378
  123. package/src/components/modal-base/ds-mobile-modal-base.ts +0 -261
  124. package/src/components/modal-base/index.ts +0 -2
  125. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.css +0 -112
  126. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.service.ts +0 -93
  127. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.ts +0 -442
  128. package/src/components/new-inquiry-modal/index.ts +0 -4
  129. package/src/components/offline-banner/ds-mobile-offline-banner.ts +0 -135
  130. package/src/components/offline-banner/index.ts +0 -1
  131. package/src/components/page-details/ds-mobile-page-details.css +0 -83
  132. package/src/components/page-details/ds-mobile-page-details.ts +0 -282
  133. package/src/components/page-details/index.ts +0 -2
  134. package/src/components/page-main/ds-mobile-page-main.css +0 -68
  135. package/src/components/page-main/ds-mobile-page-main.ts +0 -421
  136. package/src/components/page-main/index.ts +0 -2
  137. package/src/components/post-composer/ds-mobile-post-composer.ts +0 -140
  138. package/src/components/post-composer/index.ts +0 -2
  139. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.css +0 -390
  140. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts +0 -108
  141. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts +0 -722
  142. package/src/components/post-detail-modal/index.ts +0 -9
  143. package/src/components/property-banner/ds-mobile-property-banner.ts +0 -95
  144. package/src/components/property-banner/index.ts +0 -2
  145. package/src/components/section/ds-mobile-section.ts +0 -263
  146. package/src/components/section/index.ts +0 -2
  147. package/src/components/shared/directives/index.ts +0 -2
  148. package/src/components/shared/directives/long-press.directive.ts +0 -212
  149. package/src/components/shared/index.ts +0 -3
  150. package/src/components/shared/mobile-modal-base.ts +0 -457
  151. package/src/components/shared/mobile-page-base.ts +0 -204
  152. package/src/components/swiper/ds-mobile-swiper-with-nav.ts +0 -160
  153. package/src/components/swiper/ds-mobile-swiper.ts +0 -327
  154. package/src/components/swiper/index.ts +0 -3
  155. package/src/components/system-message-banner/ds-mobile-system-message-banner.ts +0 -129
  156. package/src/components/system-message-banner/index.ts +0 -2
  157. package/src/components/tab-bar/ds-mobile-tab-bar.css +0 -533
  158. package/src/components/tab-bar/ds-mobile-tab-bar.ts +0 -735
  159. package/src/components/tab-bar/index.ts +0 -2
  160. package/src/components/tabs/ds-mobile-tabs.css +0 -25
  161. package/src/components/tabs/ds-mobile-tabs.ts +0 -89
  162. package/src/components/tabs/index.ts +0 -2
  163. package/src/components/text-input/ds-text-input.ts +0 -287
  164. package/src/components/text-input/index.ts +0 -2
  165. package/src/examples/booking.page.ts +0 -434
  166. package/src/examples/community.page.ts +0 -776
  167. package/src/examples/handbook.page.ts +0 -324
  168. package/src/examples/home.page.ts +0 -347
  169. package/src/examples/index.ts +0 -12
  170. package/src/examples/inquiries.example.ts +0 -273
  171. package/src/examples/inquiry-detail.example.css +0 -189
  172. package/src/examples/inquiry-detail.example.ts +0 -415
  173. package/src/examples/mobile-tabs-example.component.ts +0 -208
  174. package/src/examples/post-create.page.ts +0 -311
  175. package/src/examples/post-detail.page.ts +0 -296
  176. package/src/examples/sign-in.page.ts +0 -291
  177. package/src/examples/whitelabel-demo-modal.component.ts +0 -1094
  178. package/src/examples/whitelabel-demo-modal.service.ts +0 -77
  179. package/src/models/index.ts +0 -7
  180. package/src/models/post.model.ts +0 -41
  181. package/src/pages/community.page.ts +0 -769
  182. package/src/pages/handbook.page.ts +0 -388
  183. package/src/pages/home.page.ts +0 -303
  184. package/src/pages/index.ts +0 -11
  185. package/src/pages/inquiries.example.ts +0 -273
  186. package/src/pages/inquiry-detail.example.css +0 -189
  187. package/src/pages/inquiry-detail.example.ts +0 -415
  188. package/src/pages/mobile-tabs-example.component.ts +0 -179
  189. package/src/pages/post-create.page.ts +0 -311
  190. package/src/pages/post-detail.page.ts +0 -296
  191. package/src/pages/sign-in.page.ts +0 -291
  192. package/src/pages/whitelabel-demo-modal.component.ts +0 -1094
  193. package/src/pages/whitelabel-demo-modal.service.ts +0 -77
  194. package/src/public-api.ts +0 -6
  195. package/src/services/base-modal.service.ts +0 -101
  196. package/src/services/index.ts +0 -11
  197. package/src/services/posts.service.ts +0 -542
  198. package/src/services/tracking-permission.service.ts +0 -88
  199. package/src/services/user.service.ts +0 -60
  200. package/src/services/whitelabel.service.ts +0 -675
  201. package/tsconfig.lib.json +0 -17
  202. package/tsconfig.lib.prod.json +0 -9
  203. package/tsconfig.spec.json +0 -13
  204. /package/{src/assets → assets}/fonts/Brockmann-Bold.otf +0 -0
  205. /package/{src/assets → assets}/fonts/Brockmann-BoldItalic.otf +0 -0
  206. /package/{src/assets → assets}/fonts/Brockmann-Medium.otf +0 -0
  207. /package/{src/assets → assets}/fonts/Brockmann-MediumItalic.otf +0 -0
  208. /package/{src/assets → assets}/fonts/Brockmann-Regular.otf +0 -0
  209. /package/{src/assets → assets}/fonts/Brockmann-RegularItalic.otf +0 -0
  210. /package/{src/assets → assets}/fonts/Brockmann-SemiBold.otf +0 -0
  211. /package/{src/assets → assets}/fonts/Brockmann-SemiBoldItalic.otf +0 -0
  212. /package/{src/assets → assets}/fonts/Brockmann_desktop_license.pdf +0 -0
  213. /package/{src/assets → assets}/fonts/brockmann-medium-webfont.woff2 +0 -0
  214. /package/{src/assets → assets}/fonts/brockmann-mediumitalic-webfont.woff2 +0 -0
  215. /package/{src/assets → assets}/fonts/brockmann-regular-webfont.woff2 +0 -0
  216. /package/{src/assets → assets}/fonts/brockmann-regularitalic-webfont.woff2 +0 -0
  217. /package/{src/assets → assets}/fonts/brockmann-semibold-webfont.woff2 +0 -0
  218. /package/{src/assets → assets}/fonts/brockmann-semibolditalic-webfont.woff2 +0 -0
  219. /package/{src/styles → styles}/ionic.css +0 -0
  220. /package/{src/components/shared → styles}/mobile-common.css +0 -0
  221. /package/{src/components/shared → styles}/mobile-page-base.css +0 -0
@@ -1,112 +0,0 @@
1
- /* ============================================
2
- NEW INQUIRY MODAL STYLES
3
- ============================================ */
4
-
5
- /* Large Title Textarea - Matches design system pattern */
6
- .inquiry-title-input {
7
- flex: 0 0 auto; /* Don't grow like description */
8
- }
9
-
10
- .inquiry-title-input ::ng-deep textarea {
11
- font-size: var(--font-size-2xl);
12
- font-weight: 400;
13
- line-height: 1.2;
14
- overflow-y: hidden;
15
- resize: none;
16
- box-sizing: border-box;
17
- /* Add right padding to prevent overlap with close button */
18
- padding-right: 52px; /* 36px button + 16px spacing */
19
- /* Height will be controlled dynamically by JavaScript */
20
- }
21
-
22
- /* ============================================
23
- FIXED BOTTOM CONTAINER (Slides with keyboard)
24
- ============================================ */
25
-
26
- .fixed-bottom-container {
27
- background: var(--color-background-neutral-primary);
28
- border-top: 1px solid var(--border-color-default);
29
- }
30
-
31
- /* Attachment Previews Section (Inside Fixed Bottom) */
32
- .attachment-previews-section {
33
- padding: 16px 20px;
34
- border-bottom: 1px solid var(--border-color-default);
35
- }
36
-
37
- .image-previews {
38
- display: flex;
39
- gap: 8px;
40
- overflow-x: auto;
41
- padding-bottom: 4px;
42
- }
43
-
44
- /* Hide scrollbar for photo previews */
45
- .image-previews::-webkit-scrollbar {
46
- display: none;
47
- }
48
-
49
- /* Submit Actions Container */
50
- .submit-container {
51
- padding: 16px 20px;
52
- }
53
-
54
- .submit-content {
55
- display: flex;
56
- align-items: center;
57
- justify-content: space-between;
58
- gap: 16px;
59
- }
60
-
61
- /* Upload Actions (Left Side) */
62
- .upload-actions {
63
- display: flex;
64
- align-items: center;
65
- gap: 8px;
66
- }
67
-
68
- .upload-actions ds-icon-button::ng-deep button {
69
- width: 44px;
70
- height: 44px;
71
- border-radius: 50%;
72
- }
73
-
74
- /* Submit Button (Right Side) */
75
- .submit-content ds-button::ng-deep button {
76
- border-radius: 100px;
77
- }
78
-
79
- .submit-content ds-button.submit-action-button::ng-deep button {
80
- height: 44px;
81
- min-height: 44px;
82
- max-height: 44px;
83
- padding-left: 16px;
84
- padding-right: 16px;
85
- }
86
-
87
- /* Description Textarea - Expand to fill available space */
88
- .inquiry-description-input {
89
- display: flex;
90
- flex: 1;
91
- min-height: 0;
92
- }
93
-
94
- .inquiry-description-input ::ng-deep .textarea-container {
95
- display: flex;
96
- flex: 1;
97
- min-height: 0;
98
- }
99
-
100
- .inquiry-description-input ::ng-deep textarea {
101
- flex: 1;
102
- min-height: 80px;
103
- overflow-y: hidden;
104
- resize: none;
105
- }
106
-
107
- /* Responsive adjustments */
108
- @media (min-width: 768px) {
109
- .submit-container {
110
- padding: 20px 32px;
111
- }
112
- }
@@ -1,93 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import { ModalController } from '@ionic/angular/standalone';
3
- import { DsMobileNewInquiryModalComponent, NewInquiryData } from './ds-mobile-new-inquiry-modal';
4
- import { BaseModalService } from '../../services/base-modal.service';
5
-
6
- /**
7
- * Options for opening the new inquiry modal
8
- */
9
- export interface NewInquiryModalOptions {
10
- /** Callback function when inquiry is submitted */
11
- onSubmit?: (data: NewInquiryData) => void | Promise<void>;
12
- /** Initial loading state */
13
- loading?: boolean;
14
- /** Initial error message */
15
- error?: string;
16
- /** Custom placeholder for title field */
17
- titlePlaceholder?: string;
18
- /** Custom placeholder for description field */
19
- descriptionPlaceholder?: string;
20
- /** Custom label for submit button */
21
- submitButtonLabel?: string;
22
- }
23
-
24
- /**
25
- * DsMobileNewInquiryModalService
26
- *
27
- * Service for displaying the new inquiry creation modal.
28
- * Built on Ionic's modal system with native gestures and animations.
29
- *
30
- * Features:
31
- * - Full-screen modal with form
32
- * - Title and description inputs
33
- * - Photo upload with camera/gallery
34
- * - Form validation
35
- * - Submit handling
36
- * - Loading and error states
37
- *
38
- * @example
39
- * ```typescript
40
- * constructor(private newInquiryModal: DsMobileNewInquiryModalService) {}
41
- *
42
- * async createNewInquiry(): Promise<void> {
43
- * console.log('[InquiriesPage] FAB clicked, opening modal...');
44
- *
45
- * await this.newInquiryModal.open({
46
- * onSubmit: async (data) => {
47
- * console.log('Creating inquiry:', data);
48
- * // Call your API to create the inquiry
49
- * await this.apiService.createInquiry(data);
50
- * // Close the modal
51
- * await this.newInquiryModal.close();
52
- * }
53
- * });
54
- * }
55
- * ```
56
- */
57
- @Injectable({
58
- providedIn: 'root',
59
- })
60
- export class DsMobileNewInquiryModalService extends BaseModalService {
61
- constructor(modalController: ModalController) {
62
- super(modalController);
63
- }
64
-
65
- /**
66
- * Open the new inquiry modal
67
- *
68
- * @param options Modal options including onSubmit callback
69
- * @returns Promise that resolves when the modal is presented
70
- */
71
- async open(options?: NewInquiryModalOptions): Promise<void> {
72
- // console.log('[NewInquiryModal] Opening modal with options:', options);
73
-
74
- const modal = await this.createModal(
75
- DsMobileNewInquiryModalComponent,
76
- {
77
- onSubmit: options?.onSubmit,
78
- loading: options?.loading ?? false,
79
- ...(options?.error && { error: options.error }),
80
- ...(options?.titlePlaceholder && { titlePlaceholder: options.titlePlaceholder }),
81
- ...(options?.descriptionPlaceholder && { descriptionPlaceholder: options.descriptionPlaceholder }),
82
- ...(options?.submitButtonLabel && { submitButtonLabel: options.submitButtonLabel }),
83
- },
84
- {
85
- keyboardClose: false, // Don't close on keyboard hide for this modal
86
- },
87
- );
88
-
89
- console.log('[NewInquiryModal] Modal created, presenting...');
90
- await modal.present();
91
- console.log('[NewInquiryModal] Modal presented');
92
- }
93
- }
@@ -1,442 +0,0 @@
1
- import { Component, signal, Input, ViewChild, ElementRef, OnInit, AfterViewInit, CUSTOM_ELEMENTS_SCHEMA, inject } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
- import { ModalController } from '@ionic/angular/standalone';
5
- import { Capacitor } from '@capacitor/core';
6
- import { FilePicker } from '@capawesome/capacitor-file-picker';
7
- import { DsButtonComponent, DsTextareaComponent, DsIconButtonComponent } from '@propbinder/design-system';
8
- import { DsMobileModalBaseComponent } from '../modal-base/ds-mobile-modal-base';
9
- import { DsMobileAttachmentPreviewComponent, type AttachmentData, type AttachmentFileType } from '../attachment-preview';
10
- import { DsMobileSectionComponent } from '../section';
11
-
12
- /**
13
- * Photo interface for inquiry (deprecated - use AttachmentData)
14
- * @deprecated Use AttachmentData from attachment-preview component instead
15
- */
16
- export interface InquiryPhoto {
17
- id: string;
18
- src: string;
19
- alt?: string;
20
- }
21
-
22
- /**
23
- * New inquiry form data
24
- */
25
- export interface NewInquiryData {
26
- title: string;
27
- description: string;
28
- attachments: AttachmentData[];
29
- category?: string;
30
- }
31
-
32
- /**
33
- * DsMobileNewInquiryModalComponent
34
- *
35
- * Modal component for creating new inquiries.
36
- * Uses ds-mobile-modal-base for consistent layout and behavior.
37
- *
38
- * Features:
39
- * - Title and description fields
40
- * - Photo upload with preview
41
- * - Submit button at bottom
42
- * - Form validation
43
- * - Camera/photo picker integration
44
- *
45
- * This component is typically not used directly - use DsMobileNewInquiryModalService instead.
46
- *
47
- * @example
48
- * ```typescript
49
- * // Don't instantiate directly - use the service:
50
- * constructor(private inquiryModal: DsMobileNewInquiryModalService) {}
51
- *
52
- * createInquiry() {
53
- * this.inquiryModal.open({
54
- * onSubmit: (data) => console.log('Inquiry created:', data)
55
- * });
56
- * }
57
- * ```
58
- */
59
- @Component({
60
- selector: 'ds-mobile-new-inquiry-modal',
61
- standalone: true,
62
- imports: [
63
- CommonModule,
64
- FormsModule,
65
- DsButtonComponent,
66
- DsTextareaComponent,
67
- DsIconButtonComponent,
68
- DsMobileModalBaseComponent,
69
- DsMobileAttachmentPreviewComponent,
70
- DsMobileSectionComponent,
71
- ],
72
- styleUrls: ['../shared/mobile-common.css', './ds-mobile-new-inquiry-modal.css'],
73
- schemas: [CUSTOM_ELEMENTS_SCHEMA],
74
- template: `
75
- <ds-mobile-modal-base [loading]="loading" [error]="error" [showHeader]="false" [hasFixedBottom]="true" [enableKeyboardHandling]="true" [keyboardContentBehavior]="'overlay'" closeButtonLabel="Close">
76
- <!-- Form Content -->
77
- <ds-mobile-section>
78
- <!-- Title Field (Large Ghost Textarea) -->
79
- <ds-textarea
80
- #titleInput
81
- [(ngModel)]="title"
82
- [ghost]="true"
83
- [required]="true"
84
- [rows]="1"
85
- [placeholder]="titlePlaceholder"
86
- class="inquiry-title-input ghost-input-clean"
87
- (valueChange)="handleTitleChange($event)"
88
- />
89
-
90
- <!-- Description Field (Ghost Textarea) -->
91
- <ds-textarea
92
- #descriptionInput
93
- [(ngModel)]="description"
94
- [ghost]="true"
95
- [rows]="1"
96
- [placeholder]="descriptionPlaceholder"
97
- class="inquiry-description-input ghost-input-clean"
98
- (valueChange)="handleDescriptionChange($event)"
99
- />
100
- </ds-mobile-section>
101
-
102
- <!-- Fixed Bottom Container (Slides with keyboard) -->
103
- <div footer class="fixed-bottom-container">
104
- <!-- Attachment Previews (if any) -->
105
- @if (attachments().length > 0) {
106
- <div class="attachment-previews-section">
107
- <div class="image-previews">
108
- @for (attachment of attachments(); track attachment.id) {
109
- <ds-mobile-attachment-preview [attachment]="attachment" (remove)="removeAttachment($event)" />
110
- }
111
- </div>
112
- </div>
113
- }
114
-
115
- <!-- Submit Actions Container -->
116
- <div class="submit-container">
117
- <div class="submit-content">
118
- <!-- Upload Actions (Left) -->
119
- <div class="upload-actions">
120
- <ds-icon-button icon="remixImageLine" variant="secondary" size="md" (clicked)="addPhoto()" [disabled]="attachments().length >= 6" aria-label="Add photo">
121
- </ds-icon-button>
122
- <ds-icon-button
123
- icon="remixAttachmentLine"
124
- variant="secondary"
125
- size="md"
126
- (clicked)="handleAddAttachment()"
127
- [disabled]="attachments().length >= 6"
128
- aria-label="Add attachment"
129
- >
130
- </ds-icon-button>
131
-
132
- <!-- Hidden file input for file selection -->
133
- <input #fileInput type="file" accept="*/*" multiple (change)="handleFileSelect($event)" style="display: none;" aria-hidden="true" />
134
- </div>
135
-
136
- <!-- Submit Button (Right) -->
137
- <ds-button class="submit-action-button" variant="primary" size="md" [disabled]="!isFormValid() || isSubmitting()" (clicked)="handleSubmit()">
138
- {{ submitButtonLabel }}
139
- </ds-button>
140
- </div>
141
- </div>
142
- </div>
143
- </ds-mobile-modal-base>
144
- `,
145
- })
146
- export class DsMobileNewInquiryModalComponent implements OnInit, AfterViewInit {
147
- private modalController = inject(ModalController);
148
- @ViewChild('titleInput', { read: ElementRef }) titleInputRef?: ElementRef<HTMLElement>;
149
- @ViewChild('descriptionInput', { read: ElementRef }) descriptionInputRef?: ElementRef<HTMLElement>;
150
- @ViewChild('titleInput') titleInput?: DsTextareaComponent;
151
- @ViewChild('fileInput') fileInput?: ElementRef<HTMLInputElement>;
152
-
153
- /**
154
- * Loading state for the modal
155
- */
156
- @Input() loading: boolean = false;
157
-
158
- /**
159
- * Error message to display
160
- */
161
- @Input() error?: string;
162
-
163
- /**
164
- * Callback function when form is submitted
165
- */
166
- @Input() onSubmit?: (data: NewInquiryData) => void | Promise<void>;
167
-
168
- /**
169
- * Placeholder for the title field
170
- */
171
- @Input() titlePlaceholder: string = 'Name your inquiry';
172
-
173
- /**
174
- * Placeholder for the description field
175
- */
176
- @Input() descriptionPlaceholder: string = 'Tell us what this inquiry is about...';
177
-
178
- /**
179
- * Label for the submit button
180
- */
181
- @Input() submitButtonLabel: string = 'Submit';
182
-
183
- /**
184
- * Form title field
185
- */
186
- title = '';
187
-
188
- /**
189
- * Form description field
190
- */
191
- description = '';
192
-
193
- /**
194
- * Attachments array (replaces photos)
195
- */
196
- attachments = signal<AttachmentData[]>([]);
197
-
198
- /**
199
- * Form validation state
200
- */
201
- isFormValid = signal<boolean>(false);
202
-
203
- /**
204
- * Submitting state
205
- */
206
- isSubmitting = signal<boolean>(false);
207
-
208
- ngOnInit(): void {
209
- console.log('[NewInquiryModal] Component initialized');
210
- }
211
-
212
- ngAfterViewInit(): void {
213
- // Setup auto-resize for title textarea
214
- setTimeout(() => {
215
- this.autoResizeTitleTextarea();
216
- this.autoResizeDescriptionTextarea();
217
-
218
- // Focus the title textarea after view initialization to trigger keyboard on iOS
219
- if (this.titleInputRef) {
220
- const textareaElement = this.titleInputRef.nativeElement.querySelector('textarea');
221
- if (textareaElement) {
222
- textareaElement.focus();
223
- }
224
- }
225
- }, 300);
226
- }
227
-
228
- /**
229
- * Auto-resize the title textarea based on content
230
- */
231
- private autoResizeTitleTextarea(): void {
232
- if (!this.titleInputRef) return;
233
-
234
- // Access the native textarea element
235
- const textareaElement = this.titleInputRef.nativeElement.querySelector('textarea');
236
- if (textareaElement) {
237
- textareaElement.style.height = 'auto';
238
- textareaElement.style.height = textareaElement.scrollHeight + 'px';
239
- }
240
- }
241
-
242
- /**
243
- * Auto-resize the description textarea based on content
244
- */
245
- private autoResizeDescriptionTextarea(): void {
246
- if (!this.descriptionInputRef) return;
247
-
248
- const textareaElement = this.descriptionInputRef.nativeElement.querySelector('textarea');
249
- if (textareaElement) {
250
- textareaElement.style.height = 'auto';
251
- textareaElement.style.height = textareaElement.scrollHeight + 'px';
252
- }
253
- }
254
-
255
- /**
256
- * Handle title change with auto-resize
257
- */
258
- handleTitleChange(value: string): void {
259
- this.validateForm();
260
- this.autoResizeTitleTextarea();
261
- }
262
-
263
- /**
264
- * Handle description change with auto-resize
265
- */
266
- handleDescriptionChange(value: string): void {
267
- this.validateForm();
268
- this.autoResizeDescriptionTextarea();
269
- }
270
-
271
- /**
272
- * Validate form fields
273
- */
274
- validateForm(): void {
275
- const isValid = this.title.trim().length > 0 && this.description.trim().length > 0;
276
- this.isFormValid.set(isValid);
277
- }
278
-
279
- /**
280
- * Add a new photo from camera/library
281
- */
282
- async addPhoto(): Promise<void> {
283
- if (this.attachments().length >= 6) {
284
- return;
285
- }
286
-
287
- try {
288
- const result = await FilePicker.pickImages({
289
- limit: 1,
290
- });
291
-
292
- const image = result.files?.[0];
293
- if (image) {
294
- const newAttachment: AttachmentData = {
295
- id: `photo-${Date.now()}`,
296
- src: image.path ? Capacitor.convertFileSrc(image.path) : (image.blob ? URL.createObjectURL(image.blob) : ''),
297
- type: 'image',
298
- name: image.name || `Photo ${this.attachments().length + 1}`,
299
- size: this.formatFileSize(image.size ?? 0),
300
- };
301
-
302
- this.attachments.update((attachments) => [...attachments, newAttachment]);
303
- }
304
- } catch (error) {
305
- console.error('[NewInquiryModal] Error adding photo:', error);
306
- // User cancelled or error occurred - just ignore
307
- }
308
- }
309
-
310
- /**
311
- * Remove an attachment
312
- */
313
- removeAttachment(attachmentId: string): void {
314
- this.attachments.update((attachments) => attachments.filter((a) => a.id !== attachmentId));
315
- }
316
-
317
- /**
318
- * Handle attachment button click
319
- */
320
- handleAddAttachment(): void {
321
- if (this.attachments().length >= 6) {
322
- return;
323
- }
324
-
325
- // Trigger the hidden file input
326
- if (this.fileInput) {
327
- this.fileInput.nativeElement.click();
328
- }
329
- }
330
-
331
- /**
332
- * Detect file type from file name or mime type
333
- */
334
- private detectFileType(file: File): AttachmentFileType {
335
- const fileName = file.name.toLowerCase();
336
- const mimeType = file.type.toLowerCase();
337
-
338
- // Check if it's an image
339
- if (mimeType.startsWith('image/')) {
340
- return 'image';
341
- }
342
-
343
- // Check file extension
344
- if (fileName.endsWith('.pdf')) {
345
- return 'pdf';
346
- } else if (fileName.endsWith('.doc')) {
347
- return 'doc';
348
- } else if (fileName.endsWith('.docx')) {
349
- return 'docx';
350
- } else if (fileName.endsWith('.xls')) {
351
- return 'xls';
352
- } else if (fileName.endsWith('.xlsx')) {
353
- return 'xlsx';
354
- }
355
-
356
- return 'other';
357
- }
358
-
359
- /**
360
- * Format file size for display
361
- */
362
- private formatFileSize(bytes: number): string {
363
- if (bytes === 0) return '0 B';
364
- const k = 1024;
365
- const sizes = ['B', 'KB', 'MB', 'GB'];
366
- const i = Math.floor(Math.log(bytes) / Math.log(k));
367
- return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
368
- }
369
-
370
- /**
371
- * Handle file selection from file input
372
- */
373
- handleFileSelect(event: Event): void {
374
- const input = event.target as HTMLInputElement;
375
- const files = input.files;
376
-
377
- if (!files || files.length === 0) {
378
- return;
379
- }
380
-
381
- // Process each selected file (up to the limit)
382
- const remainingSlots = 6 - this.attachments().length;
383
- const filesToProcess = Array.from(files).slice(0, remainingSlots);
384
-
385
- filesToProcess.forEach((file) => {
386
- const fileType = this.detectFileType(file);
387
-
388
- // Create a data URL for preview
389
- const reader = new FileReader();
390
- reader.onload = (e) => {
391
- const result = e.target?.result as string;
392
- if (result) {
393
- const newAttachment: AttachmentData = {
394
- id: `file-${Date.now()}-${Math.random()}`,
395
- src: result,
396
- type: fileType,
397
- name: file.name,
398
- size: this.formatFileSize(file.size),
399
- };
400
- this.attachments.update((attachments) => [...attachments, newAttachment]);
401
- }
402
- };
403
- reader.readAsDataURL(file);
404
- });
405
-
406
- // Reset the input so the same file can be selected again
407
- input.value = '';
408
- }
409
-
410
- /**
411
- * Handle form submission
412
- */
413
- async handleSubmit(): Promise<void> {
414
- if (!this.isFormValid() || this.isSubmitting()) {
415
- return;
416
- }
417
-
418
- this.isSubmitting.set(true);
419
-
420
- try {
421
- const inquiryData: NewInquiryData = {
422
- title: this.title.trim(),
423
- description: this.description.trim(),
424
- attachments: this.attachments(),
425
- };
426
-
427
- console.log('[NewInquiryModal] Submitting inquiry:', inquiryData);
428
-
429
- if (this.onSubmit) {
430
- await this.onSubmit(inquiryData);
431
- }
432
-
433
- // Success - close the modal
434
- this.modalController.dismiss();
435
- } catch (error) {
436
- console.error('[NewInquiryModal] Error submitting inquiry:', error);
437
- this.error = 'Failed to create inquiry. Please try again.';
438
- } finally {
439
- this.isSubmitting.set(false);
440
- }
441
- }
442
- }
@@ -1,4 +0,0 @@
1
- export { DsMobileNewInquiryModalComponent } from './ds-mobile-new-inquiry-modal';
2
- export type { NewInquiryData, InquiryPhoto } from './ds-mobile-new-inquiry-modal';
3
- export { DsMobileNewInquiryModalService } from './ds-mobile-new-inquiry-modal.service';
4
- export type { NewInquiryModalOptions } from './ds-mobile-new-inquiry-modal.service';