@propbinder/mobile-design 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ng-package.json +7 -0
- package/package.json +12 -39
- package/src/animations/page-transitions.ts +86 -0
- package/src/assets/fonts/Brockmann-Bold.otf +0 -0
- package/src/assets/fonts/Brockmann-BoldItalic.otf +0 -0
- package/src/assets/fonts/Brockmann-Medium.otf +0 -0
- package/src/assets/fonts/Brockmann-MediumItalic.otf +0 -0
- package/src/assets/fonts/Brockmann-Regular.otf +0 -0
- package/src/assets/fonts/Brockmann-RegularItalic.otf +0 -0
- package/src/assets/fonts/Brockmann-SemiBold.otf +0 -0
- package/src/assets/fonts/Brockmann-SemiBoldItalic.otf +0 -0
- package/src/assets/fonts/Brockmann_desktop_license.pdf +0 -0
- package/src/assets/fonts/brockmann-medium-webfont.woff2 +0 -0
- package/src/assets/fonts/brockmann-regular-webfont.woff2 +0 -0
- package/src/assets/fonts/brockmann-semibold-webfont.woff2 +0 -0
- package/src/components/action-list-item/ds-mobile-action-list-item.ts +83 -0
- package/src/components/action-list-item/index.ts +2 -0
- package/src/components/app-layout/ds-mobile-app-layout.css +343 -0
- package/src/components/app-layout/ds-mobile-app-layout.ts +271 -0
- package/src/components/app-layout/index.ts +2 -0
- package/src/components/avatar-with-badge/ds-avatar-with-badge.ts +130 -0
- package/src/components/avatar-with-badge/index.ts +2 -0
- package/src/components/bottom-sheet/ds-mobile-actions-bottom-sheet.ts +273 -0
- package/src/components/bottom-sheet/ds-mobile-bottom-sheet.css +110 -0
- package/src/components/bottom-sheet/ds-mobile-bottom-sheet.service.ts +167 -0
- package/src/components/bottom-sheet/ds-mobile-post-create-bottom-sheet.ts +656 -0
- package/src/components/bottom-sheet/index.ts +3 -0
- package/src/components/comment/ds-mobile-comment.ts +516 -0
- package/src/components/comment/index.ts +2 -0
- package/src/components/contact-list-item/ds-mobile-contact-list-item.ts +182 -0
- package/src/components/contact-list-item/index.ts +2 -0
- package/src/components/content/ds-mobile-content.ts +158 -0
- package/src/components/content/index.ts +2 -0
- package/src/components/ds-mobile-tabs.css +372 -0
- package/src/components/ds-mobile-tabs.ts +217 -0
- package/src/components/file-attachment/ds-mobile-file-attachment.ts +164 -0
- package/src/components/file-attachment/index.ts +2 -0
- package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.service.ts +98 -0
- package/src/components/handbook-detail-modal/ds-mobile-handbook-detail-modal.ts +514 -0
- package/src/components/handbook-detail-modal/index.ts +3 -0
- package/src/components/handbook-folder/ds-mobile-handbook-folder-mini.ts +130 -0
- package/src/components/handbook-folder/ds-mobile-handbook-folder.ts +444 -0
- package/src/components/handbook-folder/index.ts +4 -0
- package/src/components/header-content/ds-mobile-header-content.ts +211 -0
- package/src/components/header-content/index.ts +2 -0
- package/src/components/index.ts +45 -0
- package/src/components/inline-photo/ds-mobile-inline-photo.ts +269 -0
- package/src/components/inline-photo/index.ts +1 -0
- package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.css +60 -0
- package/src/components/interactive-list-item-inquiry/ds-mobile-interactive-list-item-inquiry.ts +280 -0
- package/src/components/interactive-list-item-inquiry/index.ts +2 -0
- package/src/components/interactive-list-item-message/ds-mobile-interactive-list-item-message.ts +197 -0
- package/src/components/interactive-list-item-message/index.ts +2 -0
- package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.css +70 -0
- package/src/components/interactive-list-item-post/ds-mobile-interactive-list-item-post.ts +594 -0
- package/src/components/interactive-list-item-post/ds-mobile-post-pdf-attachment.ts +124 -0
- package/src/components/interactive-list-item-post/index.ts +13 -0
- package/src/components/lightbox/ds-mobile-lightbox-footer.ts +331 -0
- package/src/components/lightbox/ds-mobile-lightbox-header.ts +173 -0
- package/src/components/lightbox/ds-mobile-lightbox-image.ts +464 -0
- package/src/components/lightbox/ds-mobile-lightbox-pdf.css +375 -0
- package/src/components/lightbox/ds-mobile-lightbox-pdf.ts +374 -0
- package/src/components/lightbox/ds-mobile-lightbox.css +587 -0
- package/src/components/lightbox/ds-mobile-lightbox.service.ts +293 -0
- package/src/components/lightbox/ds-mobile-lightbox.ts +529 -0
- package/src/components/lightbox/index.ts +22 -0
- package/src/components/list-item/ds-mobile-list-item.ts +499 -0
- package/src/components/list-item/index.ts +2 -0
- package/src/components/list-item-static/ds-mobile-list-item-static.ts +133 -0
- package/src/components/list-item-static/index.ts +2 -0
- package/src/components/logo/ds-logo.ts +85 -0
- package/src/components/logo/index.ts +2 -0
- package/src/components/modal/ds-mobile-modal.css +163 -0
- package/src/components/modal/ds-mobile-modal.service.ts +329 -0
- package/src/components/modal/index.ts +8 -0
- package/src/components/page-details/ds-mobile-page-details.css +285 -0
- package/src/components/page-details/ds-mobile-page-details.ts +128 -0
- package/src/components/page-details/index.ts +2 -0
- package/src/components/page-main/ds-mobile-page-main.css +346 -0
- package/src/components/page-main/ds-mobile-page-main.ts +331 -0
- package/src/components/page-main/index.ts +2 -0
- package/src/components/post-card/ds-mobile-post-card.ts +685 -0
- package/src/components/post-card/ds-mobile-post-pdf-attachment.ts +124 -0
- package/src/components/post-card/index.ts +11 -0
- package/src/components/post-composer/ds-mobile-post-composer.ts +140 -0
- package/src/components/post-composer/index.ts +2 -0
- package/src/components/post-detail-modal/ds-mobile-post-detail-modal.service.ts +104 -0
- package/src/components/post-detail-modal/ds-mobile-post-detail-modal.ts +1273 -0
- package/src/components/post-detail-modal/index.ts +9 -0
- package/src/components/shared/directives/index.ts +2 -0
- package/src/components/shared/directives/long-press.directive.ts +208 -0
- package/src/components/shared/index.ts +3 -0
- package/src/components/shared/mobile-common.css +94 -0
- package/src/components/shared/mobile-page-base.css +315 -0
- package/src/components/shared/mobile-page-base.ts +70 -0
- package/src/components/swiper/ds-mobile-swiper.ts +123 -0
- package/src/components/swiper/index.ts +2 -0
- package/src/components/tab-bar/ds-mobile-tab-bar.ts +132 -0
- package/src/components/tab-bar/index.ts +2 -0
- package/src/components/tabs/ds-mobile-tabs.css +405 -0
- package/src/components/tabs/ds-mobile-tabs.ts +204 -0
- package/src/components/tabs/index.ts +2 -0
- package/src/pages/community.page.ts +768 -0
- package/src/pages/handbook.page.ts +298 -0
- package/src/pages/home.page.ts +192 -0
- package/src/pages/index.ts +9 -0
- package/src/pages/inquiries.example.ts +212 -0
- package/src/pages/inquiry-detail.example.css +434 -0
- package/src/pages/inquiry-detail.example.ts +416 -0
- package/src/pages/mobile-tabs-example.component.ts +146 -0
- package/src/pages/post-create.page.ts +311 -0
- package/src/pages/post-detail.page.ts +295 -0
- package/src/pages/whitelabel-demo.page.ts +548 -0
- package/src/public-api.ts +5 -0
- package/src/services/user.service.ts +35 -0
- package/src/services/whitelabel.service.ts +171 -0
- package/src/styles/ionic.css +673 -0
- package/tsconfig.lib.json +17 -0
- package/tsconfig.lib.prod.json +9 -0
- package/tsconfig.spec.json +13 -0
- package/fesm2022/propbinder-mobile-design.mjs +0 -8294
- package/fesm2022/propbinder-mobile-design.mjs.map +0 -1
- package/index.d.ts +0 -2860
|
@@ -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,295 @@
|
|
|
1
|
+
import { Component } from '@angular/core';
|
|
2
|
+
import { DsMobilePageDetailsComponent } from '../components/page-details';
|
|
3
|
+
import {
|
|
4
|
+
DsMobilePostCardComponent,
|
|
5
|
+
PostContentComponent,
|
|
6
|
+
PostTextComponent,
|
|
7
|
+
PostMediaComponent,
|
|
8
|
+
PostActionsComponent,
|
|
9
|
+
ActionLikeComponent,
|
|
10
|
+
ActionCommentComponent
|
|
11
|
+
} from '../components/post-card';
|
|
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
|
+
DsMobilePostCardComponent,
|
|
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-post-card
|
|
91
|
+
[authorName]="'Sophie Andersen'"
|
|
92
|
+
[authorRole]="'Lejer'"
|
|
93
|
+
[timestamp]="'4t siden'"
|
|
94
|
+
[avatarInitials]="'SA'"
|
|
95
|
+
[variant]="'detail'">
|
|
96
|
+
|
|
97
|
+
<post-content class="no-indent">
|
|
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 class="no-indent">
|
|
110
|
+
<action-like [active]="true" [count]="156" />
|
|
111
|
+
<action-comment [count]="34" />
|
|
112
|
+
</post-actions>
|
|
113
|
+
</ds-mobile-post-card>
|
|
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
|
+
images: [
|
|
235
|
+
{
|
|
236
|
+
type: 'image',
|
|
237
|
+
src: imageSrc,
|
|
238
|
+
alt: title,
|
|
239
|
+
title: title,
|
|
240
|
+
description: description,
|
|
241
|
+
isLiked: true,
|
|
242
|
+
likeCount: 156,
|
|
243
|
+
commentCount: 34
|
|
244
|
+
}
|
|
245
|
+
],
|
|
246
|
+
author: authorMeta,
|
|
247
|
+
enableZoom: true,
|
|
248
|
+
showControls: false, // Single image, no need for controls
|
|
249
|
+
showInfo: true
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Handle long press on a comment to show action sheet
|
|
255
|
+
*/
|
|
256
|
+
async handleCommentLongPress(authorName: string, content: string, isOwnComment: boolean): Promise<void> {
|
|
257
|
+
const sheet = await this.bottomSheet.create({
|
|
258
|
+
component: DsMobileCommentActionsBottomSheetComponent,
|
|
259
|
+
componentProps: {
|
|
260
|
+
isOwnContent: isOwnComment
|
|
261
|
+
},
|
|
262
|
+
breakpoints: [0, 1],
|
|
263
|
+
initialBreakpoint: 1,
|
|
264
|
+
handle: true,
|
|
265
|
+
backdropDismiss: true,
|
|
266
|
+
cssClass: 'auto-height'
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const result = await sheet.onWillDismiss();
|
|
270
|
+
|
|
271
|
+
if (result.role === 'select' && result.data) {
|
|
272
|
+
const action = (result.data as CommentActionResult).action;
|
|
273
|
+
|
|
274
|
+
switch (action) {
|
|
275
|
+
case 'like':
|
|
276
|
+
console.log('Like comment by', authorName);
|
|
277
|
+
// Implement like logic
|
|
278
|
+
break;
|
|
279
|
+
case 'reply':
|
|
280
|
+
console.log('Reply to comment by', authorName);
|
|
281
|
+
// Implement reply logic
|
|
282
|
+
break;
|
|
283
|
+
case 'edit':
|
|
284
|
+
console.log('Edit comment by', authorName);
|
|
285
|
+
// Implement edit logic
|
|
286
|
+
break;
|
|
287
|
+
case 'delete':
|
|
288
|
+
console.log('Delete comment by', authorName);
|
|
289
|
+
// Implement delete logic (with confirmation)
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|