From c9e5256933ab8475d18ae116e702580be6e8f6de Mon Sep 17 00:00:00 2001 From: Yash Rastogi Date: Mon, 27 Apr 2026 12:17:03 -0400 Subject: [PATCH 1/3] fix(workspace): resolve loading/spinning issue on workspace creation --- src/app/components/workspace/create-workspace.css | 13 +++++++++++++ src/app/components/workspace/create-workspace.html | 3 ++- src/app/components/workspace/create-workspace.ts | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/app/components/workspace/create-workspace.css b/src/app/components/workspace/create-workspace.css index d01db84..9354c9e 100644 --- a/src/app/components/workspace/create-workspace.css +++ b/src/app/components/workspace/create-workspace.css @@ -450,3 +450,16 @@ label { transform: translateY(0); } } + +.spinner { + width: 18px; + height: 18px; + border: 2px solid rgba(255, 255, 255, 0.3); + border-radius: 50%; + border-top-color: #ffffff; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} diff --git a/src/app/components/workspace/create-workspace.html b/src/app/components/workspace/create-workspace.html index 9e40e29..f5e41a0 100644 --- a/src/app/components/workspace/create-workspace.html +++ b/src/app/components/workspace/create-workspace.html @@ -96,8 +96,9 @@

Create Workspace

diff --git a/src/app/components/workspace/create-workspace.ts b/src/app/components/workspace/create-workspace.ts index 736bf1e..eccfa0b 100644 --- a/src/app/components/workspace/create-workspace.ts +++ b/src/app/components/workspace/create-workspace.ts @@ -88,8 +88,8 @@ export class CreateWorkspace { this.error = 'An error occurred while loading the dashboard.'; }); }, - error: () => { - this.error = 'Unable to create workspace. Please try again.'; + error: (err) => { + this.error = err.message || 'Unable to create workspace. Please try again.'; this.isSubmitting = false; } }); From 207a6bfdf120746fdc8cc5151946f2912fddf357 Mon Sep 17 00:00:00 2001 From: Yash Rastogi Date: Mon, 27 Apr 2026 12:54:14 -0400 Subject: [PATCH 2/3] Fix UI not refreshing on delete decision and add error handling --- .../decision-list/decision-list.component.css | 42 +++++++++++++++++++ .../decision-list.component.html | 8 ++++ .../decision-list/decision-list.component.ts | 39 +++++++++++++---- 3 files changed, 82 insertions(+), 7 deletions(-) diff --git a/src/app/components/decision-list/decision-list.component.css b/src/app/components/decision-list/decision-list.component.css index 7cb3995..59737e5 100644 --- a/src/app/components/decision-list/decision-list.component.css +++ b/src/app/components/decision-list/decision-list.component.css @@ -129,3 +129,45 @@ padding: 2px 6px; border-radius: 4px; } + +.error-banner { + background-color: #fee2e2; + color: #b91c1c; + padding: 12px 16px; + border-radius: 8px; + margin-bottom: 16px; + border: 1px solid #fecaca; + font-size: 14px; +} + +.empty-state { + padding: 48px; + text-align: center; + background: #f9f9f9; + border-radius: 12px; + border: 2px dashed #e5e5e5; + color: #666; +} + +.loading-state { + padding: 40px; + text-align: center; + color: #666; + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; +} + +.spinner { + width: 24px; + height: 24px; + border: 2px solid #e5e5e5; + border-top-color: #0a0a0a; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} diff --git a/src/app/components/decision-list/decision-list.component.html b/src/app/components/decision-list/decision-list.component.html index 72f8661..14f4d26 100644 --- a/src/app/components/decision-list/decision-list.component.html +++ b/src/app/components/decision-list/decision-list.component.html @@ -7,6 +7,14 @@

Decisions

+
+ {{ error }} +
+ +
+ Loading decisions... +
+
No decisions found. Create one to get started! diff --git a/src/app/components/decision-list/decision-list.component.ts b/src/app/components/decision-list/decision-list.component.ts index 48aac5b..432a775 100644 --- a/src/app/components/decision-list/decision-list.component.ts +++ b/src/app/components/decision-list/decision-list.component.ts @@ -1,9 +1,9 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ActivatedRoute, RouterModule } from '@angular/router'; import { Decision } from '../../models/decision.model'; import { DecisionService } from '../../services/decision.service'; -import { Observable } from 'rxjs'; +import { Observable, Subject, takeUntil, startWith, switchMap, catchError, of } from 'rxjs'; @Component({ selector: 'app-decision-list', @@ -12,8 +12,11 @@ import { Observable } from 'rxjs'; templateUrl: './decision-list.component.html', styleUrls: ['./decision-list.component.css'] }) -export class DecisionListComponent implements OnInit { +export class DecisionListComponent implements OnInit, OnDestroy { decisions$: Observable | undefined; + error: string | null = null; + private refresh$ = new Subject(); + private destroy$ = new Subject(); private workspaceId: string | null = null; constructor( @@ -24,15 +27,37 @@ export class DecisionListComponent implements OnInit { ngOnInit(): void { this.workspaceId = this.getWorkspaceIdFromRoute(); if (this.workspaceId) { - this.decisions$ = this.decisionService.getDecisions(this.workspaceId); + this.decisions$ = this.refresh$.pipe( + startWith(undefined), + switchMap(() => this.decisionService.getDecisions(this.workspaceId!).pipe( + catchError(err => { + this.error = 'Failed to load decisions. Please try again.'; + return of([]); + }) + )) + ); } } + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + deleteDecision(id: string): void { if (confirm('Are you sure you want to delete this decision?') && this.workspaceId) { - this.decisionService.deleteDecision(this.workspaceId, id).subscribe(() => { - this.decisions$ = this.decisionService.getDecisions(this.workspaceId!); - }); + this.error = null; + this.decisionService.deleteDecision(this.workspaceId, id) + .pipe(takeUntil(this.destroy$)) + .subscribe({ + next: () => { + this.refresh$.next(); + }, + error: (err) => { + console.error('Delete failed', err); + this.error = 'Failed to delete decision. Please try again.'; + } + }); } } From 8412e3032be1c72058228b4c64a7bc5461deec0f Mon Sep 17 00:00:00 2001 From: Yash Rastogi Date: Mon, 27 Apr 2026 13:13:43 -0400 Subject: [PATCH 3/3] feat: unify workspace navigation into a tab bar --- src/app/app.routes.ts | 20 ++++----- .../workspace-details/workspace-details.css | 41 +++++++++++-------- .../workspace-details/workspace-details.html | 4 +- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 298b112..569608d 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -36,16 +36,6 @@ export const routes: Routes = [ loadComponent: () => import('./components/workspace/edit-workspace').then(m => m.EditWorkspaceComponent), canActivate: [authGuard] }, - { - path: 'workspaces/:id/settings/members', - component: WorkspaceMembersComponent, - canActivate: [authGuard] - }, - { - path: 'workspaces/:id/settings/integrations', - component: WorkspaceIntegrationsComponent, - canActivate: [authGuard] - }, { path: 'workspaces/:id', loadComponent: () => import('./components/workspace/workspace-details/workspace-details').then(m => m.WorkspaceDetailsComponent), @@ -55,6 +45,16 @@ export const routes: Routes = [ path: 'decisions', loadComponent: () => import('./components/decision-list/decision-list.component').then(m => m.DecisionListComponent) }, + { + path: 'settings/members', + component: WorkspaceMembersComponent, + canActivate: [authGuard] + }, + { + path: 'settings/integrations', + component: WorkspaceIntegrationsComponent, + canActivate: [authGuard] + }, { path: 'decisions/new', loadComponent: () => import('./components/decision-form/decision-form.component').then(m => m.DecisionFormComponent) diff --git a/src/app/components/workspace/workspace-details/workspace-details.css b/src/app/components/workspace/workspace-details/workspace-details.css index 24ecf98..d103101 100644 --- a/src/app/components/workspace/workspace-details/workspace-details.css +++ b/src/app/components/workspace/workspace-details/workspace-details.css @@ -178,41 +178,46 @@ h1 { .workspace-nav { max-width: 1160px; - margin: 0 auto 20px; + margin: 0 auto 12px; display: flex; - gap: 8px; - padding: 6px; - border-radius: 14px; - border: 1px solid rgba(0, 0, 0, 0.12); - background: rgba(255, 255, 255, 0.86); - backdrop-filter: blur(5px); + gap: 24px; + padding: 0 20px; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + background: transparent; } .workspace-nav a { flex: 0 0 auto; - min-height: 36px; - padding: 0 14px; + min-height: 44px; + padding: 0 4px; display: inline-flex; align-items: center; justify-content: center; text-decoration: none; - border-radius: 10px; - color: #2a2a2a; + color: #666666; font-size: 14px; font-weight: 600; - border: 1px solid transparent; - transition: border-color 0.2s ease, background 0.2s ease; + position: relative; + transition: color 0.2s ease; } .workspace-nav a:hover { - border-color: rgba(0, 0, 0, 0.2); - background: rgba(255, 255, 255, 0.7); + color: #000000; } .workspace-nav a.active { - color: #ffffff; - background: #050505; - border-color: #050505; + color: #000000; +} + +.workspace-nav a.active::after { + content: ""; + position: absolute; + bottom: -1px; + left: 0; + right: 0; + height: 2px; + background: #000000; + border-radius: 2px 2px 0 0; } .content-shell { diff --git a/src/app/components/workspace/workspace-details/workspace-details.html b/src/app/components/workspace/workspace-details/workspace-details.html index ce0e7fb..1c7336d 100644 --- a/src/app/components/workspace/workspace-details/workspace-details.html +++ b/src/app/components/workspace/workspace-details/workspace-details.html @@ -37,8 +37,8 @@

{{ workspace.name }}