Skip to content

Commit 0e5afcb

Browse files
committed
feat(task-create): add live task preview card for form consistency with project create
1 parent 3c2f55d commit 0e5afcb

3 files changed

Lines changed: 93 additions & 0 deletions

File tree

src/app/features/task-item/components/task-item-create/task-item-create.component.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,18 @@ <h2>Create Task</h2>
148148
<i class="pi pi-check-circle"></i>
149149
<span>Set due dates only when a concrete deadline exists.</span>
150150
</div>
151+
152+
<div class="task-preview-card">
153+
<div class="task-preview-card__title">Live Preview</div>
154+
<div class="task-preview-card__name">{{ previewTitle }}</div>
155+
<div class="task-preview-card__description">{{ previewDescription }}</div>
156+
<div class="task-preview-card__meta">
157+
<span class="preview-pill"><i class="pi pi-folder"></i> {{ previewProjectName }}</span>
158+
<span class="preview-pill"><i class="pi pi-flag"></i> {{ previewStatusLabel }}</span>
159+
<span class="preview-pill"><i class="pi pi-user"></i> {{ previewAssigneeLabel }}</span>
160+
<span class="preview-pill"><i class="pi pi-calendar"></i> {{ previewDueDateLabel }}</span>
161+
</div>
162+
</div>
151163
</p-card>
152164
</div>
153165
</div>

src/app/features/task-item/components/task-item-create/task-item-create.component.scss

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,53 @@
206206
margin-top: 0.1rem;
207207
}
208208

209+
.task-preview-card {
210+
margin-top: 1rem;
211+
border: 1px solid var(--surface-border);
212+
border-radius: 12px;
213+
padding: 0.8rem;
214+
background: color-mix(in srgb, var(--surface-100) 58%, transparent);
215+
}
216+
217+
.task-preview-card__title {
218+
font-size: 0.78rem;
219+
text-transform: uppercase;
220+
letter-spacing: 0.04em;
221+
color: var(--text-color-secondary);
222+
margin-bottom: 0.45rem;
223+
}
224+
225+
.task-preview-card__name {
226+
font-size: 0.98rem;
227+
font-weight: 600;
228+
margin-bottom: 0.35rem;
229+
}
230+
231+
.task-preview-card__description {
232+
font-size: 0.84rem;
233+
line-height: 1.35;
234+
color: var(--text-color-secondary);
235+
}
236+
237+
.task-preview-card__meta {
238+
margin-top: 0.7rem;
239+
display: flex;
240+
flex-wrap: wrap;
241+
gap: 0.35rem;
242+
}
243+
244+
.preview-pill {
245+
display: inline-flex;
246+
align-items: center;
247+
gap: 0.3rem;
248+
border: 1px solid var(--surface-border);
249+
border-radius: 999px;
250+
padding: 0.16rem 0.52rem;
251+
font-size: 0.75rem;
252+
color: var(--text-color-secondary);
253+
background: var(--surface-0);
254+
}
255+
209256
:host ::ng-deep .task-create-form .p-inputtext,
210257
:host ::ng-deep .task-create-form .p-inputtextarea,
211258
:host ::ng-deep .task-create-form .p-dropdown,

src/app/features/task-item/components/task-item-create/task-item-create.component.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,40 @@ export class TaskItemCreateComponent implements OnInit, OnDestroy {
9393
return this.taskForm.valid ? 2 : 1;
9494
}
9595

96+
get previewTitle(): string {
97+
const value = (this.taskForm.get('title')?.value as string | null)?.trim();
98+
return value && value.length > 0 ? value : 'Untitled task';
99+
}
100+
101+
get previewDescription(): string {
102+
const value = (this.taskForm.get('description')?.value as string | null)?.trim();
103+
return value && value.length > 0 ? value : 'Add context and acceptance criteria to improve handoff quality.';
104+
}
105+
106+
get previewProjectName(): string {
107+
const selectedProjectId = this.taskForm.get('projectId')?.value as string | null;
108+
if (!selectedProjectId) {
109+
return 'No project selected';
110+
}
111+
112+
return this.projects.find((project) => project.id === selectedProjectId)?.name ?? 'Selected project';
113+
}
114+
115+
get previewStatusLabel(): string {
116+
const status = this.taskForm.get('status')?.value as TaskStatus | null;
117+
return this.statusOptions.find((option) => option.value === status)?.label ?? 'To Do';
118+
}
119+
120+
get previewAssigneeLabel(): string {
121+
const assignedUserId = this.taskForm.get('assignedUserId')?.value as string | null;
122+
return this.assigneeOptions.find((option) => option.value === assignedUserId)?.label ?? 'Unassigned';
123+
}
124+
125+
get previewDueDateLabel(): string {
126+
const dueDate = this.taskForm.get('dueDate')?.value as Date | null;
127+
return dueDate ? dueDate.toLocaleDateString() : 'No due date';
128+
}
129+
96130
isInvalid(controlName: string): boolean {
97131
const control = this.taskForm.get(controlName);
98132
return !!control && control.invalid && (control.dirty || control.touched);

0 commit comments

Comments
 (0)