@propbinder/mobile-design 0.2.48 → 0.2.50

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/ng-package.json +24 -0
  2. package/package.json +3 -39
  3. package/src/animations/page-transitions.ts +165 -0
  4. package/src/assets/fonts/brockmann-mediumitalic-webfont.woff2 +0 -0
  5. package/src/assets/fonts/brockmann-regularitalic-webfont.woff2 +0 -0
  6. package/src/assets/fonts/brockmann-semibolditalic-webfont.woff2 +0 -0
  7. package/src/components/action-list-item/ds-mobile-action-list-item.ts +102 -0
  8. package/src/components/action-list-item/index.ts +2 -0
  9. package/src/components/app-icon/ds-app-icon.ts +133 -0
  10. package/src/components/app-icon/index.ts +2 -0
  11. package/src/components/attachment-preview/ds-mobile-attachment-preview.css +139 -0
  12. package/src/components/attachment-preview/ds-mobile-attachment-preview.ts +164 -0
  13. package/src/components/attachment-preview/index.ts +1 -0
  14. package/src/components/avatar-with-badge/ds-avatar-with-badge.ts +142 -0
  15. package/src/components/avatar-with-badge/index.ts +2 -0
  16. package/src/components/booking-modal/ds-mobile-booking-confirmation-wrapper.ts +71 -0
  17. package/src/components/booking-modal/ds-mobile-booking-modal.service.ts +121 -0
  18. package/src/components/booking-modal/ds-mobile-booking-modal.ts +598 -0
  19. package/src/components/booking-modal/ds-mobile-booking-summary.ts +161 -0
  20. package/src/components/booking-modal/index.ts +4 -0
  21. package/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts +266 -0
  22. package/src/components/bottom-sheet/ds-mobile-bottom-sheet-header.ts +146 -0
  23. package/src/components/bottom-sheet/ds-mobile-bottom-sheet-wrapper.ts +156 -0
  24. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.css +101 -0
  25. package/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts +169 -0
  26. package/src/components/bottom-sheet/ds-mobile-confirmation-sheet.ts +211 -0
  27. package/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts +578 -0
  28. package/src/components/bottom-sheet/ds-mobile-profile-actions-sheet.ts +614 -0
  29. package/src/components/bottom-sheet/index.ts +8 -0
  30. package/src/components/bottom-sheet/modal-shadow-fix.ts +42 -0
  31. package/src/components/card-inline/ds-mobile-card-inline.ts +301 -0
  32. package/src/components/card-inline/index.ts +2 -0
  33. package/src/components/card-inline-banner/ds-mobile-card-inline-banner.ts +118 -0
  34. package/src/components/card-inline-banner/index.ts +1 -0
  35. package/src/components/card-inline-contact/ds-mobile-card-inline-contact.ts +120 -0
  36. package/src/components/card-inline-contact/index.ts +1 -0
  37. package/src/components/card-inline-file/ds-mobile-card-inline-file.ts +141 -0
  38. package/src/components/card-inline-file/index.ts +1 -0
  39. package/src/components/chat-modal/ds-mobile-chat-modal.css +159 -0
  40. package/src/components/chat-modal/ds-mobile-chat-modal.service.ts +105 -0
  41. package/src/components/chat-modal/ds-mobile-chat-modal.ts +918 -0
  42. package/src/components/chat-modal/index.ts +8 -0
  43. package/src/components/comment/ds-mobile-comment.ts +568 -0
  44. package/src/components/comment/index.ts +2 -0
  45. package/src/components/contact-list-item/ds-mobile-contact-list-item.ts +182 -0
  46. package/src/components/contact-list-item/index.ts +2 -0
  47. package/src/components/content/ds-mobile-content.ts +139 -0
  48. package/src/components/content/index.ts +2 -0
  49. package/src/components/dropdown/ds-mobile-dropdown.css +199 -0
  50. package/src/components/dropdown/ds-mobile-dropdown.ts +340 -0
  51. package/src/components/dropdown/index.ts +2 -0
  52. package/src/components/ds-mobile-tabs.css +407 -0
  53. package/src/components/ds-mobile-tabs.ts +216 -0
  54. package/src/components/empty-state/ds-mobile-empty-state.ts +120 -0
  55. package/src/components/empty-state/index.ts +2 -0
  56. package/src/components/fab/ds-mobile-fab.ts +315 -0
  57. package/src/components/fab/index.ts +1 -0
  58. package/src/components/facility-creation-modal/ds-mobile-facility-creation-confirmation-wrapper.ts +121 -0
  59. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.css +189 -0
  60. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.service.ts +135 -0
  61. package/src/components/facility-creation-modal/ds-mobile-facility-creation-modal.ts +656 -0
  62. package/src/components/facility-creation-modal/index.ts +9 -0
  63. package/src/components/facility-creation-modal/sheets/ds-mobile-access-sheet.ts +105 -0
  64. package/src/components/facility-creation-modal/sheets/ds-mobile-price-sheet.ts +188 -0
  65. package/src/components/facility-creation-modal/sheets/ds-mobile-when-can-book-sheet.ts +460 -0
  66. package/src/components/facility-creation-modal/sheets/ds-mobile-who-can-book-sheet.ts +134 -0
  67. package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.service.ts +69 -0
  68. package/src/components/facility-detail-modal/ds-mobile-facility-detail-modal.ts +379 -0
  69. package/src/components/facility-detail-modal/index.ts +2 -0
  70. package/src/components/file-attachment/ds-mobile-file-attachment.ts +164 -0
  71. package/src/components/file-attachment/index.ts +2 -0
  72. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.css +214 -0
  73. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts +84 -0
  74. package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts +424 -0
  75. package/src/components/handbook-detail-modal/index.ts +3 -0
  76. package/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts +175 -0
  77. package/src/components/handbook-folder/ds-mobile-handbook-folder.ts +533 -0
  78. package/src/components/handbook-folder/index.ts +4 -0
  79. package/src/components/header-content/ds-mobile-header-content.ts +222 -0
  80. package/src/components/header-content/index.ts +2 -0
  81. package/src/components/illustration/ds-mobile-illustration.ts +124 -0
  82. package/src/components/illustration/index.ts +2 -0
  83. package/src/components/index.ts +124 -0
  84. package/src/components/inline-photo/ds-mobile-inline-photo.ts +361 -0
  85. package/src/components/inline-photo/index.ts +1 -0
  86. package/src/components/inline-tabs/ds-mobile-inline-tabs.ts +132 -0
  87. package/src/components/inline-tabs/index.ts +2 -0
  88. package/src/components/interactive-list-item-booking/ds-mobile-interactive-list-item-booking.ts +350 -0
  89. package/src/components/interactive-list-item-booking/index.ts +1 -0
  90. package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts +321 -0
  91. package/src/components/interactive-list-item-inquiry/index.ts +2 -0
  92. package/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts +237 -0
  93. package/src/components/interactive-list-item-message/index.ts +2 -0
  94. package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts +549 -0
  95. package/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts +124 -0
  96. package/src/components/interactive-list-item-post/index.ts +13 -0
  97. package/src/components/lightbox/ds-mobile-lightbox-footer.ts +315 -0
  98. package/src/components/lightbox/ds-mobile-lightbox-header.ts +202 -0
  99. package/src/components/lightbox/ds-mobile-lightbox-image.ts +484 -0
  100. package/src/components/lightbox/ds-mobile-lightbox-pdf.css +377 -0
  101. package/src/components/lightbox/ds-mobile-lightbox-pdf.ts +374 -0
  102. package/src/components/lightbox/ds-mobile-lightbox.css +587 -0
  103. package/src/components/lightbox/ds-mobile-lightbox.service.ts +296 -0
  104. package/src/components/lightbox/ds-mobile-lightbox.ts +529 -0
  105. package/src/components/lightbox/index.ts +22 -0
  106. package/src/components/list-item/ds-mobile-list-item.ts +603 -0
  107. package/src/components/list-item/index.ts +2 -0
  108. package/src/components/list-item-static/ds-mobile-list-item-static.ts +133 -0
  109. package/src/components/list-item-static/index.ts +2 -0
  110. package/src/components/loader-overlay/ds-mobile-loader-overlay.css +49 -0
  111. package/src/components/loader-overlay/ds-mobile-loader-overlay.ts +77 -0
  112. package/src/components/loader-overlay/index.ts +1 -0
  113. package/src/components/logo/ds-logo.ts +95 -0
  114. package/src/components/logo/index.ts +2 -0
  115. package/src/components/message-bubble/ds-mobile-message-bubble.ts +633 -0
  116. package/src/components/message-bubble/index.ts +7 -0
  117. package/src/components/message-composer/ds-mobile-message-composer.ts +1146 -0
  118. package/src/components/message-composer/index.ts +7 -0
  119. package/src/components/modal/ds-mobile-modal.css +163 -0
  120. package/src/components/modal/ds-mobile-modal.service.ts +329 -0
  121. package/src/components/modal/index.ts +8 -0
  122. package/src/components/modal-base/ds-mobile-modal-base.css +378 -0
  123. package/src/components/modal-base/ds-mobile-modal-base.ts +261 -0
  124. package/src/components/modal-base/index.ts +2 -0
  125. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.css +112 -0
  126. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.service.ts +93 -0
  127. package/src/components/new-inquiry-modal/ds-mobile-new-inquiry-modal.ts +442 -0
  128. package/src/components/new-inquiry-modal/index.ts +4 -0
  129. package/src/components/offline-banner/ds-mobile-offline-banner.ts +135 -0
  130. package/src/components/offline-banner/index.ts +1 -0
  131. package/src/components/page-details/ds-mobile-page-details.css +83 -0
  132. package/src/components/page-details/ds-mobile-page-details.ts +282 -0
  133. package/src/components/page-details/index.ts +2 -0
  134. package/src/components/page-main/ds-mobile-page-main.css +68 -0
  135. package/src/components/page-main/ds-mobile-page-main.ts +421 -0
  136. package/src/components/page-main/index.ts +2 -0
  137. package/src/components/post-composer/ds-mobile-post-composer.ts +140 -0
  138. package/src/components/post-composer/index.ts +2 -0
  139. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.css +390 -0
  140. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts +108 -0
  141. package/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts +722 -0
  142. package/src/components/post-detail-modal/index.ts +9 -0
  143. package/src/components/property-banner/ds-mobile-property-banner.ts +95 -0
  144. package/src/components/property-banner/index.ts +2 -0
  145. package/src/components/section/ds-mobile-section.ts +263 -0
  146. package/src/components/section/index.ts +2 -0
  147. package/src/components/shared/directives/index.ts +2 -0
  148. package/src/components/shared/directives/long-press.directive.ts +212 -0
  149. package/src/components/shared/index.ts +3 -0
  150. package/src/components/shared/mobile-modal-base.ts +457 -0
  151. package/src/components/shared/mobile-page-base.ts +204 -0
  152. package/src/components/swiper/ds-mobile-swiper-with-nav.ts +160 -0
  153. package/src/components/swiper/ds-mobile-swiper.ts +327 -0
  154. package/src/components/swiper/index.ts +3 -0
  155. package/src/components/system-message-banner/ds-mobile-system-message-banner.ts +129 -0
  156. package/src/components/system-message-banner/index.ts +2 -0
  157. package/src/components/tab-bar/ds-mobile-tab-bar.css +533 -0
  158. package/src/components/tab-bar/ds-mobile-tab-bar.ts +735 -0
  159. package/src/components/tab-bar/index.ts +2 -0
  160. package/src/components/tabs/ds-mobile-tabs.css +25 -0
  161. package/src/components/tabs/ds-mobile-tabs.ts +89 -0
  162. package/src/components/tabs/index.ts +2 -0
  163. package/src/components/text-input/ds-text-input.ts +287 -0
  164. package/src/components/text-input/index.ts +2 -0
  165. package/src/examples/booking.page.ts +434 -0
  166. package/src/examples/community.page.ts +776 -0
  167. package/src/examples/handbook.page.ts +324 -0
  168. package/src/examples/home.page.ts +347 -0
  169. package/src/examples/index.ts +12 -0
  170. package/src/examples/inquiries.example.ts +273 -0
  171. package/src/examples/inquiry-detail.example.css +189 -0
  172. package/src/examples/inquiry-detail.example.ts +415 -0
  173. package/src/examples/mobile-tabs-example.component.ts +208 -0
  174. package/src/examples/post-create.page.ts +311 -0
  175. package/src/examples/post-detail.page.ts +296 -0
  176. package/src/examples/sign-in.page.ts +291 -0
  177. package/src/examples/whitelabel-demo-modal.component.ts +1094 -0
  178. package/src/examples/whitelabel-demo-modal.service.ts +77 -0
  179. package/src/models/index.ts +7 -0
  180. package/src/models/post.model.ts +41 -0
  181. package/src/pages/community.page.ts +769 -0
  182. package/src/pages/handbook.page.ts +388 -0
  183. package/src/pages/home.page.ts +303 -0
  184. package/src/pages/index.ts +11 -0
  185. package/src/pages/inquiries.example.ts +273 -0
  186. package/src/pages/inquiry-detail.example.css +189 -0
  187. package/src/pages/inquiry-detail.example.ts +415 -0
  188. package/src/pages/mobile-tabs-example.component.ts +179 -0
  189. package/src/pages/post-create.page.ts +311 -0
  190. package/src/pages/post-detail.page.ts +296 -0
  191. package/src/pages/sign-in.page.ts +291 -0
  192. package/src/pages/whitelabel-demo-modal.component.ts +1094 -0
  193. package/src/pages/whitelabel-demo-modal.service.ts +77 -0
  194. package/src/public-api.ts +6 -0
  195. package/src/services/base-modal.service.ts +101 -0
  196. package/src/services/index.ts +11 -0
  197. package/src/services/posts.service.ts +542 -0
  198. package/src/services/tracking-permission.service.ts +88 -0
  199. package/src/services/user.service.ts +60 -0
  200. package/src/services/whitelabel.service.ts +675 -0
  201. package/{styles → src/styles}/ionic.css +25 -0
  202. package/tsconfig.lib.json +17 -0
  203. package/tsconfig.lib.prod.json +9 -0
  204. package/tsconfig.spec.json +13 -0
  205. package/fesm2022/propbinder-mobile-design.mjs +0 -26168
  206. package/fesm2022/propbinder-mobile-design.mjs.map +0 -1
  207. package/index.d.ts +0 -8169
  208. /package/{assets → src/assets}/fonts/Brockmann-Bold.otf +0 -0
  209. /package/{assets → src/assets}/fonts/Brockmann-BoldItalic.otf +0 -0
  210. /package/{assets → src/assets}/fonts/Brockmann-Medium.otf +0 -0
  211. /package/{assets → src/assets}/fonts/Brockmann-MediumItalic.otf +0 -0
  212. /package/{assets → src/assets}/fonts/Brockmann-Regular.otf +0 -0
  213. /package/{assets → src/assets}/fonts/Brockmann-RegularItalic.otf +0 -0
  214. /package/{assets → src/assets}/fonts/Brockmann-SemiBold.otf +0 -0
  215. /package/{assets → src/assets}/fonts/Brockmann-SemiBoldItalic.otf +0 -0
  216. /package/{assets → src/assets}/fonts/Brockmann_desktop_license.pdf +0 -0
  217. /package/{assets → src/assets}/fonts/brockmann-medium-webfont.woff2 +0 -0
  218. /package/{assets → src/assets}/fonts/brockmann-regular-webfont.woff2 +0 -0
  219. /package/{assets → src/assets}/fonts/brockmann-semibold-webfont.woff2 +0 -0
  220. /package/{styles → src/components/shared}/mobile-common.css +0 -0
  221. /package/{styles → src/components/shared}/mobile-page-base.css +0 -0
@@ -0,0 +1,311 @@
1
+ import { Component, signal, ViewChild, ElementRef, AfterViewInit, OnInit } from '@angular/core';
2
+ import { Router, ActivatedRoute } from '@angular/router';
3
+ import { CommonModule } from '@angular/common';
4
+ import { FormsModule } from '@angular/forms';
5
+ import {
6
+ DsAvatarComponent,
7
+ DsIconComponent,
8
+ DsButtonComponent
9
+ } from '@propbinder/design-system';
10
+ import { DsMobilePageDetailsComponent } from '../components/page-details';
11
+ import { UserService } from '../services/user.service';
12
+
13
+ /**
14
+ * PostCreatePageComponent
15
+ *
16
+ * Full-screen detail page for creating new posts in the community feed.
17
+ * Features Threads-inspired interface with rich text editing capabilities.
18
+ */
19
+ @Component({
20
+ selector: 'app-post-create-page',
21
+ standalone: true,
22
+ imports: [
23
+ CommonModule,
24
+ FormsModule,
25
+ DsAvatarComponent,
26
+ DsIconComponent,
27
+ DsButtonComponent,
28
+ DsMobilePageDetailsComponent
29
+ ],
30
+ styles: [`
31
+ .post-create-container {
32
+ display: flex;
33
+ flex-direction: column;
34
+ height: 100%;
35
+ max-width: 640px;
36
+ }
37
+
38
+ /* ============================================
39
+ CONTENT AREA
40
+ ============================================ */
41
+
42
+ .content {
43
+ flex: 1;
44
+ overflow-y: auto;
45
+ padding: 16px;
46
+ }
47
+
48
+ .post-composer {
49
+ display: flex;
50
+ gap: 12px;
51
+ margin-bottom: 24px;
52
+ align-items: flex-start;
53
+ }
54
+
55
+ .post-composer__avatar {
56
+ flex-shrink: 0;
57
+ padding-top: 2px;
58
+ }
59
+
60
+ .post-composer__main {
61
+ flex: 1;
62
+ min-width: 0;
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: 12px;
66
+ }
67
+
68
+ .post-composer__header {
69
+ display: flex;
70
+ align-items: center;
71
+ gap: 8px;
72
+ height: 32px;
73
+ }
74
+
75
+ .post-composer__username {
76
+ font-family: 'Brockmann', sans-serif;
77
+ font-size: 15px;
78
+ font-weight: 600;
79
+ line-height: 20px;
80
+ letter-spacing: -0.3px;
81
+ color: var(--color-text-primary, #1a1a1a);
82
+ }
83
+
84
+ .post-composer__textarea {
85
+ width: 100%;
86
+ min-height: 120px;
87
+ border: none;
88
+ outline: none;
89
+ resize: none;
90
+ font-family: 'Brockmann', sans-serif;
91
+ font-size: 15px;
92
+ font-weight: 400;
93
+ line-height: 22px;
94
+ letter-spacing: -0.3px;
95
+ color: var(--color-text-primary, #1a1a1a);
96
+ background: transparent;
97
+ padding: 0;
98
+ }
99
+
100
+ .post-composer__textarea::placeholder {
101
+ color: var(--color-text-tertiary, #999999);
102
+ }
103
+
104
+ .post-composer__actions {
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: space-between;
108
+ gap: 16px;
109
+ }
110
+
111
+ .post-composer__action-btns {
112
+ display: flex;
113
+ align-items: center;
114
+ gap: 16px;
115
+ }
116
+
117
+ .post-composer__action-btn {
118
+ background: none;
119
+ border: none;
120
+ padding: 0;
121
+ cursor: pointer;
122
+ display: flex;
123
+ align-items: center;
124
+ justify-content: center;
125
+ color: var(--color-text-secondary, #737373);
126
+ transition: color 0.2s ease;
127
+ }
128
+
129
+ .post-composer__action-btn:hover {
130
+ color: var(--color-text-primary, #1a1a1a);
131
+ }
132
+
133
+ /* Thread connector line */
134
+ .thread-line {
135
+ position: absolute;
136
+ left: 35px;
137
+ top: 60px;
138
+ bottom: 0;
139
+ width: 2px;
140
+ background: var(--border-color-default);
141
+ }
142
+
143
+ /* ============================================
144
+ MOBILE OPTIMIZATIONS
145
+ ============================================ */
146
+
147
+ @media (max-width: 768px) {
148
+ .content {
149
+ padding: 12px 16px;
150
+ }
151
+ }
152
+ `],
153
+ template: `
154
+ <ds-mobile-page-details
155
+ [title]="pageTitle()"
156
+ [backRoute]="'/mobile-tabs-example/announcements'"
157
+ (back)="handleCancel()">
158
+
159
+ <div class="post-create-container">
160
+ <div class="post-composer">
161
+ <div class="post-composer__avatar">
162
+ <ds-avatar
163
+ [initials]="userService.avatarInitials()"
164
+ [type]="userService.avatarType()"
165
+ [src]="userService.avatarSrc()"
166
+ size="md" />
167
+ </div>
168
+
169
+ <div class="post-composer__main">
170
+ <div class="post-composer__header">
171
+ <span class="post-composer__username">{{ username() }}</span>
172
+ </div>
173
+
174
+ <textarea
175
+ #textareaInput
176
+ class="post-composer__textarea"
177
+ [(ngModel)]="postContent"
178
+ [placeholder]="placeholder()"
179
+ (input)="handleInput()">
180
+ </textarea>
181
+
182
+ <div class="post-composer__actions">
183
+ <div class="post-composer__action-btns">
184
+ <button class="post-composer__action-btn" (click)="handleAddImage()">
185
+ <ds-icon name="remixImageLine" size="22px" />
186
+ </button>
187
+ <button class="post-composer__action-btn" (click)="handleAddEmoji()">
188
+ <ds-icon name="remixEmotionLine" size="22px" />
189
+ </button>
190
+ </div>
191
+
192
+ <ds-button
193
+ variant="primary"
194
+ size="md"
195
+ [disabled]="!canPost()"
196
+ (clicked)="handlePost()">
197
+ {{ submitButtonLabel() }}
198
+ </ds-button>
199
+ </div>
200
+ </div>
201
+ </div>
202
+ </div>
203
+ </ds-mobile-page-details>
204
+ `
205
+ })
206
+ export class PostCreatePageComponent implements AfterViewInit, OnInit {
207
+ @ViewChild('textareaInput') textareaInput?: ElementRef<HTMLTextAreaElement>;
208
+
209
+ postContent = '';
210
+ username = signal('Lars Mikkelsen');
211
+ placeholder = signal("What's new?");
212
+
213
+ // Edit mode state
214
+ isEditMode = signal(false);
215
+ postId = signal<string | null>(null);
216
+ pageTitle = signal('New post');
217
+ submitButtonLabel = signal('Post');
218
+
219
+ constructor(
220
+ private router: Router,
221
+ private route: ActivatedRoute,
222
+ public userService: UserService
223
+ ) {}
224
+
225
+ ngOnInit(): void {
226
+ // Check for edit mode via query parameters
227
+ this.route.queryParams.subscribe(params => {
228
+ const editMode = params['edit'] === 'true';
229
+ const postId = params['id'];
230
+ const content = params['content'];
231
+
232
+ if (editMode && postId) {
233
+ this.isEditMode.set(true);
234
+ this.postId.set(postId);
235
+ this.pageTitle.set('Edit post');
236
+ this.submitButtonLabel.set('Save');
237
+
238
+ // Prefill content if provided
239
+ if (content) {
240
+ this.postContent = decodeURIComponent(content);
241
+ }
242
+ } else {
243
+ // Reset to create mode
244
+ this.isEditMode.set(false);
245
+ this.postId.set(null);
246
+ this.pageTitle.set('New post');
247
+ this.submitButtonLabel.set('Post');
248
+ this.postContent = '';
249
+ }
250
+ });
251
+ }
252
+
253
+ ngAfterViewInit(): void {
254
+ // Focus the textarea after view initialization to trigger keyboard on mobile
255
+ setTimeout(() => {
256
+ this.textareaInput?.nativeElement.focus();
257
+ }, 300);
258
+ }
259
+
260
+ handleInput(): void {
261
+ // Handle text input changes
262
+ }
263
+
264
+ canPost(): boolean {
265
+ return this.postContent.trim().length > 0;
266
+ }
267
+
268
+ handleCancel(): void {
269
+ if (this.postContent.trim().length > 0) {
270
+ // Show confirmation dialog
271
+ const confirmed = confirm('Discard this post?');
272
+ if (confirmed) {
273
+ this.router.navigate(['/mobile-tabs-example/community']);
274
+ }
275
+ } else {
276
+ this.router.navigate(['/mobile-tabs-example/community']);
277
+ }
278
+ }
279
+
280
+ handlePost(): void {
281
+ if (!this.canPost()) return;
282
+
283
+ if (this.isEditMode()) {
284
+ console.log('Updating post:', this.postId(), this.postContent);
285
+ // TODO: Implement post update logic
286
+ // this.postService.updatePost(this.postId(), this.postContent).subscribe(() => {
287
+ // this.router.navigate(['/mobile-tabs-example/community']);
288
+ // });
289
+ } else {
290
+ console.log('Creating post:', this.postContent);
291
+ // TODO: Implement post creation logic
292
+ // this.postService.createPost(this.postContent).subscribe(() => {
293
+ // this.router.navigate(['/mobile-tabs-example/community']);
294
+ // });
295
+ }
296
+
297
+ // For now, just navigate back
298
+ this.router.navigate(['/mobile-tabs-example/community']);
299
+ }
300
+
301
+ handleAddImage(): void {
302
+ console.log('Add image');
303
+ // TODO: Open image picker
304
+ }
305
+
306
+ handleAddEmoji(): void {
307
+ console.log('Add emoji');
308
+ // TODO: Open emoji picker
309
+ }
310
+ }
311
+
@@ -0,0 +1,296 @@
1
+ import { Component } from '@angular/core';
2
+ import { DsMobilePageDetailsComponent } from '../components/page-details';
3
+ import {
4
+ DsMobileInteractiveListItemPostComponent,
5
+ PostContentComponent,
6
+ PostTextComponent,
7
+ PostMediaComponent,
8
+ PostActionsComponent,
9
+ ActionLikeComponent,
10
+ ActionCommentComponent
11
+ } from '../components/interactive-list-item-post';
12
+ import { DsMobileCommentComponent } from '../components/comment';
13
+ import { DsMobileLightboxService, LightboxAuthor } from '../components/lightbox';
14
+ import { DsMobileBottomSheetService } from '../components/bottom-sheet/ds-mobile-bottom-sheet.service';
15
+ import { DsMobileCommentActionsBottomSheetComponent, CommentActionResult } from '../components/bottom-sheet';
16
+
17
+ @Component({
18
+ selector: 'app-mobile-post-detail-page',
19
+ standalone: true,
20
+ imports: [
21
+ DsMobilePageDetailsComponent,
22
+ DsMobileInteractiveListItemPostComponent,
23
+ PostContentComponent,
24
+ PostTextComponent,
25
+ PostMediaComponent,
26
+ PostActionsComponent,
27
+ ActionLikeComponent,
28
+ ActionCommentComponent,
29
+ DsMobileCommentComponent
30
+ ],
31
+ styles: [`
32
+ .post-detail-container {
33
+ display: flex;
34
+ flex-direction: column;
35
+ gap: 16px;
36
+ max-width: 640px;
37
+ }
38
+
39
+ .post-section {
40
+ border-bottom: 1px solid var(--border-color-default);
41
+ padding-bottom: 16px;
42
+ }
43
+
44
+ .clickable-image {
45
+ cursor: pointer;
46
+ transition: transform 0.2s ease, opacity 0.2s ease;
47
+ border-radius: 8px;
48
+ display: block;
49
+ width: 100%;
50
+ aspect-ratio: 16/9;
51
+ object-fit: cover;
52
+ }
53
+
54
+ .clickable-image:active {
55
+ transform: scale(0.98);
56
+ opacity: 0.9;
57
+ }
58
+
59
+ .comments-section {
60
+ display: flex;
61
+ flex-direction: column;
62
+ /* Negative margin to pull comments out by 8px on each side */
63
+ /* Page has 20px padding, this makes comments effectively 12px from edge */
64
+ margin-left: -8px;
65
+ margin-right: -8px;
66
+ }
67
+
68
+ .comments-header {
69
+ font-family: 'Brockmann', sans-serif;
70
+ font-size: 18px;
71
+ font-weight: 600;
72
+ line-height: 24px;
73
+ color: var(--color-text-primary, #1a1a1a);
74
+ margin-bottom: 16px;
75
+ /* Add padding to keep header at 20px from edge (8px to offset negative margin) */
76
+ padding-left: 8px;
77
+ padding-right: 8px;
78
+ }
79
+
80
+ .comments-list {
81
+ display: flex;
82
+ flex-direction: column;
83
+ }
84
+ `],
85
+ template: `
86
+ <ds-mobile-page-details title="Opslag">
87
+ <div class="post-detail-container">
88
+ <!-- Post Section -->
89
+ <div class="post-section">
90
+ <ds-mobile-interactive-list-item-post
91
+ [authorName]="'Sophie Andersen'"
92
+ [authorRole]="'Lejer'"
93
+ [timestamp]="'4t siden'"
94
+ [avatarInitials]="'SA'"
95
+ [clickable]="false">
96
+
97
+ <post-content>
98
+ <post-text>Se denne smukke udsigt fra min altan! Morgenkaffe har aldrig smagt så godt ☕️</post-text>
99
+ <post-media>
100
+ <img
101
+ src="/Assets/Dummy-photos/balcony-view.jpg"
102
+ alt="Altanudsigt"
103
+ class="clickable-image"
104
+ (click)="openImageLightbox('/Assets/Dummy-photos/balcony-view.jpg', 'Altanudsigt', 'Morgenkaffe har aldrig smagt så godt ☕️')"
105
+ />
106
+ </post-media>
107
+ </post-content>
108
+
109
+ <post-actions>
110
+ <action-like [active]="true" [count]="156" />
111
+ <action-comment [count]="34" />
112
+ </post-actions>
113
+ </ds-mobile-interactive-list-item-post>
114
+ </div>
115
+
116
+ <!-- Comments Section -->
117
+ <div class="comments-section">
118
+ <h2 class="comments-header">{{ repliesCount }} svar</h2>
119
+
120
+ <div class="comments-list">
121
+ <ds-mobile-comment
122
+ [authorName]="'Anders Jensen'"
123
+ [authorRole]="'Lejer'"
124
+ [timestamp]="'3t siden'"
125
+ [avatarInitials]="'AJ'"
126
+ [content]="'Wow, den udsigt er fantastisk! Hvilken etage er du på?'"
127
+ [likeCount]="12"
128
+ [clickable]="true"
129
+ [isOwnComment]="false"
130
+ (longPress)="handleCommentLongPress('Anders Jensen', 'Wow, den udsigt er fantastisk! Hvilken etage er du på?', false)" />
131
+
132
+ <ds-mobile-comment
133
+ [authorName]="'Thomas Hansen'"
134
+ [authorRole]="'Lejer'"
135
+ [timestamp]="'3t siden'"
136
+ [avatarInitials]="'TH'"
137
+ [content]="'Smuk! Jeg kan også se byens silhuet fra min lejlighed 🌆'"
138
+ [isLiked]="true"
139
+ [likeCount]="8"
140
+ [clickable]="true"
141
+ [isOwnComment]="true"
142
+ (longPress)="handleCommentLongPress('Thomas Hansen', 'Smuk! Jeg kan også se byens silhuet fra min lejlighed 🌆', true)" />
143
+
144
+ <ds-mobile-comment
145
+ [authorName]="'Emma Petersen'"
146
+ [authorRole]="'Lejer'"
147
+ [timestamp]="'2t siden'"
148
+ [avatarInitials]="'EP'"
149
+ [content]="'Dette er præcis derfor jeg elsker at bo her. Godt billede!'"
150
+ [likeCount]="15"
151
+ [clickable]="true"
152
+ [isOwnComment]="false"
153
+ (longPress)="handleCommentLongPress('Emma Petersen', 'Dette er præcis derfor jeg elsker at bo her. Godt billede!', false)" />
154
+
155
+ <ds-mobile-comment
156
+ [authorName]="'Nikolaj Sørensen'"
157
+ [authorRole]="'Lejer'"
158
+ [timestamp]="'2t siden'"
159
+ [avatarInitials]="'NS'"
160
+ [content]="'Solnedgangene fra den vinkel må være utrolige'"
161
+ [likeCount]="6"
162
+ [clickable]="true"
163
+ [isOwnComment]="false"
164
+ (longPress)="handleCommentLongPress('Nikolaj Sørensen', 'Solnedgangene fra den vinkel må være utrolige', false)" />
165
+
166
+ <ds-mobile-comment
167
+ [authorName]="'Mette Larsen'"
168
+ [authorRole]="'Lejer'"
169
+ [timestamp]="'1t siden'"
170
+ [avatarInitials]="'ML'"
171
+ [content]="'Giver mig lyst til at få min morgenkaffe på altanen også! ☕'"
172
+ [likeCount]="9"
173
+ [clickable]="true"
174
+ [isOwnComment]="false"
175
+ (longPress)="handleCommentLongPress('Mette Larsen', 'Giver mig lyst til at få min morgenkaffe på altanen også! ☕', false)" />
176
+
177
+ <ds-mobile-comment
178
+ [authorName]="'Frederik Nielsen'"
179
+ [authorRole]="'Lejer'"
180
+ [timestamp]="'1t siden'"
181
+ [avatarInitials]="'FN'"
182
+ [content]="'Heldig! Min altan vender den anden vej, men stadig pæn'"
183
+ [likeCount]="4"
184
+ [clickable]="true"
185
+ [isOwnComment]="false"
186
+ (longPress)="handleCommentLongPress('Frederik Nielsen', 'Heldig! Min altan vender den anden vej, men stadig pæn', false)" />
187
+
188
+ <ds-mobile-comment
189
+ [authorName]="'Caroline Jensen'"
190
+ [authorRole]="'Lejer'"
191
+ [timestamp]="'45m siden'"
192
+ [avatarInitials]="'CJ'"
193
+ [content]="'Denne bygning har den bedste udsigt i byen, uden tvivl'"
194
+ [likeCount]="11"
195
+ [clickable]="true"
196
+ [isOwnComment]="false"
197
+ (longPress)="handleCommentLongPress('Caroline Jensen', 'Denne bygning har den bedste udsigt i byen, uden tvivl', false)" />
198
+
199
+ <ds-mobile-comment
200
+ [authorName]="'Anna Hansen'"
201
+ [authorRole]="'Lejer'"
202
+ [timestamp]="'30m siden'"
203
+ [avatarInitials]="'AH'"
204
+ [content]="'Jeg skal se din altan en dag! 😍'"
205
+ [clickable]="true"
206
+ [isOwnComment]="false"
207
+ (longPress)="handleCommentLongPress('Anna Hansen', 'Jeg skal se din altan en dag! 😍', false)" />
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </ds-mobile-page-details>
212
+ `
213
+ })
214
+ export class MobilePostDetailPageComponent {
215
+ repliesCount = 6;
216
+
217
+ constructor(
218
+ private lightbox: DsMobileLightboxService,
219
+ private bottomSheet: DsMobileBottomSheetService
220
+ ) {}
221
+
222
+ /**
223
+ * Open an image in the lightbox viewer
224
+ */
225
+ openImageLightbox(imageSrc: string, title: string, description: string): void {
226
+ const authorMeta: LightboxAuthor = {
227
+ name: 'Sophie Andersen',
228
+ role: 'Lejer',
229
+ avatarInitials: 'SA',
230
+ timestamp: '4t siden'
231
+ };
232
+
233
+ this.lightbox.open({
234
+ showActions: true, // Show like & comment actions
235
+ images: [
236
+ {
237
+ type: 'image',
238
+ src: imageSrc,
239
+ alt: title,
240
+ title: title,
241
+ description: description,
242
+ isLiked: true,
243
+ likeCount: 156,
244
+ commentCount: 34
245
+ }
246
+ ],
247
+ author: authorMeta,
248
+ enableZoom: true,
249
+ showControls: false, // Single image, no need for controls
250
+ showInfo: true
251
+ });
252
+ }
253
+
254
+ /**
255
+ * Handle long press on a comment to show action sheet
256
+ */
257
+ async handleCommentLongPress(authorName: string, content: string, isOwnComment: boolean): Promise<void> {
258
+ const sheet = await this.bottomSheet.create({
259
+ component: DsMobileCommentActionsBottomSheetComponent,
260
+ componentProps: {
261
+ isOwnContent: isOwnComment
262
+ },
263
+ breakpoints: [0, 1],
264
+ initialBreakpoint: 1,
265
+ handle: true,
266
+ backdropDismiss: true,
267
+ cssClass: 'auto-height'
268
+ });
269
+
270
+ const result = await sheet.onWillDismiss();
271
+
272
+ if (result.role === 'select' && result.data) {
273
+ const action = (result.data as CommentActionResult).action;
274
+
275
+ switch (action) {
276
+ case 'like':
277
+ console.log('Like comment by', authorName);
278
+ // Implement like logic
279
+ break;
280
+ case 'reply':
281
+ console.log('Reply to comment by', authorName);
282
+ // Implement reply logic
283
+ break;
284
+ case 'edit':
285
+ console.log('Edit comment by', authorName);
286
+ // Implement edit logic
287
+ break;
288
+ case 'delete':
289
+ console.log('Delete comment by', authorName);
290
+ // Implement delete logic (with confirmation)
291
+ break;
292
+ }
293
+ }
294
+ }
295
+ }
296
+