Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 41 additions & 11 deletions src/app/components/dashboard/dashboard.css
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,6 @@
place-items: center;
}

nav {
display: flex;
align-items: center;
gap: 20px;
}

.workspace-card-link {
text-decoration: none;
color: inherit;
}

.logout-btn {
border: 1px solid rgba(255, 255, 255, 0.24);
background: transparent;
Expand Down Expand Up @@ -158,6 +147,47 @@ nav {
letter-spacing: 0.04em;
}

.card-actions {
margin-top: 14px;
display: flex;
gap: 8px;
}

.action-btn {
text-decoration: none;
display: inline-flex;
align-items: center;
border-radius: 8px;
border: 1px solid #d0d0d0;
padding: 7px 12px;
font-size: 13px;
cursor: pointer;
background: #fff;
color: #111;
}

.open-btn {
background: #f3f3f3;
}

.open-btn:hover {
background: #e9e9e9;
}

.edit-btn:hover {
background: #f3f3f3;
}

.delete-btn {
border-color: #2b2b2b;
background: #111;
color: #fff;
}

.delete-btn:hover {
background: #000;
}

.empty-state {
border: 1px dashed #bcbcbc;
border-radius: 12px;
Expand Down
21 changes: 10 additions & 11 deletions src/app/components/dashboard/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,17 @@ <h2>Your Workspaces</h2>
<a routerLink="/workspace/create" class="create-btn">Create Workspace</a>
</div>

<div class="workspace-list">
<a *ngFor="let ws of workspaces" [routerLink]="['/workspaces', ws.id]" class="workspace-card-link">
<div class="workspace-card">
<h3>{{ ws.name }}</h3>
<p>{{ ws.description }}</p>
<small>Created: {{ ws.createdDate | date }}</small>
<div class="workspace-list" *ngIf="workspaces.length > 0; else empty">
<article *ngFor="let ws of workspaces" class="workspace-card">
<h3>{{ ws.name }}</h3>
<p>{{ ws.description || 'No description yet.' }}</p>
<small>Created: {{ ws.createdDate | date: 'mediumDate' }}</small>
<div class="card-actions">
<a [routerLink]="['/workspaces', ws.id, 'decisions']" class="action-btn open-btn">Open</a>
<button type="button" class="action-btn edit-btn" (click)="editWorkspace(ws)">Edit</button>
<button type="button" class="action-btn delete-btn" (click)="deleteWorkspace(ws)">Delete</button>
</div>
</a>
</div>

<div *ngIf="workspaces.length === 0" class="empty-state">
<p>No workspaces found. Create one to get started!</p>
</article>
</div>

<ng-template #empty>
Expand Down
35 changes: 35 additions & 0 deletions src/app/components/dashboard/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,41 @@ export class Dashboard implements OnInit {
});
}

editWorkspace(workspace: Workspace) {
const updatedName = window.prompt('Edit workspace name', workspace.name)?.trim();
if (!updatedName) {
return;
}

const updatedDescriptionInput = window.prompt('Edit workspace description', workspace.description ?? '');
if (updatedDescriptionInput === null) {
return;
}

const updatedDescription = updatedDescriptionInput.trim();

this.workspaceService.updateWorkspace(workspace.id, updatedName, updatedDescription).subscribe(updatedWorkspace => {
if (!updatedWorkspace) {
return;
}
this.workspaces = this.workspaces.map(ws => ws.id === updatedWorkspace.id ? updatedWorkspace : ws);
});
}

deleteWorkspace(workspace: Workspace) {
const confirmed = window.confirm(`Delete workspace "${workspace.name}"?`);
if (!confirmed) {
return;
}

this.workspaceService.deleteWorkspace(workspace.id).subscribe(deleted => {
if (!deleted) {
return;
}
this.workspaces = this.workspaces.filter(ws => ws.id !== workspace.id);
});
}

logout() {
this.authService.logout();
this.router.navigate(['/login']);
Expand Down
27 changes: 17 additions & 10 deletions src/app/components/decision-form/decision-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class DecisionFormComponent implements OnInit {
isEditMode = false;
decisionId: string | null = null;
isLoading = false;
workspaceId: string | null = null;

constructor(
private fb: FormBuilder,
Expand All @@ -32,13 +33,7 @@ export class DecisionFormComponent implements OnInit {
}

ngOnInit(): void {
// Get workspaceId from parent
this.route.parent?.paramMap.subscribe(params => {
const workspaceId = params.get('id');
if (workspaceId) {
this.decisionForm.patchValue({ workspaceId });
}
});
this.workspaceId = this.getWorkspaceIdFromRoute();

// Get decisionId from current route
this.route.paramMap.subscribe(params => {
Expand Down Expand Up @@ -78,11 +73,23 @@ export class DecisionFormComponent implements OnInit {
this.router.navigate(['../../'], { relativeTo: this.route });
});
} else {
// Include workspaceId from parent route if available
const workspaceId = this.route.parent?.snapshot.paramMap.get('id');
this.decisionService.createDecision({ ...formValue, workspaceId }).subscribe(() => {
if (!this.workspaceId) {
return;
}

this.decisionService.createDecision({ ...formValue, workspaceId: this.workspaceId }).subscribe(() => {
this.router.navigate(['../'], { relativeTo: this.route });
});
}
}

private getWorkspaceIdFromRoute(): string | null {
for (const route of this.route.pathFromRoot) {
const id = route.snapshot.paramMap.get('id');
if (id) {
return id;
}
}
return null;
}
}
21 changes: 14 additions & 7 deletions src/app/components/decision-list/decision-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,25 @@ export class DecisionListComponent implements OnInit {
) { }

ngOnInit(): void {
// Get workspaceId from the parent route (workspaces/:id)
this.route.parent?.paramMap.subscribe(params => {
const workspaceId = params.get('id');
if (workspaceId) {
this.decisions$ = this.decisionService.getDecisions(workspaceId);
}
});
const workspaceId = this.getWorkspaceIdFromRoute();
if (workspaceId) {
this.decisions$ = this.decisionService.getDecisions(workspaceId);
}
}

deleteDecision(id: string): void {
if (confirm('Are you sure you want to delete this decision?')) {
this.decisionService.deleteDecision(id);
}
}

private getWorkspaceIdFromRoute(): string | null {
for (const route of this.route.pathFromRoot) {
const id = route.snapshot.paramMap.get('id');
if (id) {
return id;
}
}
return null;
}
}
5 changes: 4 additions & 1 deletion src/app/components/workspace/create-workspace.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ label {
font-weight: 600;
}

input {
input,
textarea {
padding: 10px 12px;
border: 1px solid #d0d7de;
border-radius: 6px;
font: inherit;
resize: vertical;
}

.actions {
Expand Down
10 changes: 10 additions & 0 deletions src/app/components/workspace/create-workspace.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ <h2>Create Workspace</h2>
placeholder="e.g. Product Team"
/>

<label for="workspace-description">Description</label>
<textarea
id="workspace-description"
name="workspaceDescription"
[(ngModel)]="description"
[disabled]="isSubmitting"
rows="4"
placeholder="Describe this workspace"
></textarea>

<div class="actions">
<button type="submit" [disabled]="isSubmitting || !workspaceForm.form.valid">
{{ isSubmitting ? 'Creating...' : 'Create Workspace' }}
Expand Down
3 changes: 2 additions & 1 deletion src/app/components/workspace/create-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { WorkspaceService } from '../../services/workspace';
})
export class CreateWorkspace {
name = '';
description = '';
error = '';
isSubmitting = false;

Expand All @@ -29,7 +30,7 @@ export class CreateWorkspace {
this.isSubmitting = true;
this.error = '';

this.workspaceService.createWorkspace(trimmedName).subscribe({
this.workspaceService.createWorkspace(trimmedName, this.description.trim()).subscribe({
next: () => this.router.navigate(['/dashboard']),
error: () => {
this.error = 'Unable to create workspace. Please try again.';
Expand Down
6 changes: 5 additions & 1 deletion src/app/services/decision.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,16 @@ export class DecisionService {
}

createDecision(decision: Partial<Decision>): Observable<Decision> {
if (!decision.workspaceId) {
throw new Error('workspaceId is required to create a decision');
}

const newDecision: Decision = {
id: Math.random().toString(36).substring(2, 9),
title: decision.title!,
description: decision.description,
status: decision.status || 'DRAFT',
workspaceId: decision.workspaceId || 'ws-1', // Default to ws-1 for now
workspaceId: decision.workspaceId,
userId: 'user-1', // Mock user
createdAt: new Date(),
updatedAt: new Date(),
Expand Down
21 changes: 19 additions & 2 deletions src/app/services/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,32 @@ export class WorkspaceService {
return of(this.mockWorkspaces.find(w => w.id === id));
}

createWorkspace(name: string): Observable<Workspace> {
createWorkspace(name: string, description: string): Observable<Workspace> {
const newWorkspace: Workspace = {
id: Math.random().toString(36).substring(7),
name,
description: '',
description,
createdDate: new Date(),
ownerId: 'user1' // Mock owner
};
this.mockWorkspaces.push(newWorkspace);
return of(newWorkspace);
}

updateWorkspace(id: string, name: string, description: string): Observable<Workspace | undefined> {
const workspace = this.mockWorkspaces.find(w => w.id === id);
if (!workspace) {
return of(undefined);
}

workspace.name = name;
workspace.description = description;
return of(workspace);
}

deleteWorkspace(id: string): Observable<boolean> {
const initialLength = this.mockWorkspaces.length;
this.mockWorkspaces = this.mockWorkspaces.filter(w => w.id !== id);
return of(this.mockWorkspaces.length < initialLength);
}
}