diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index e5fb9e1..ee8f7f7 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -22,6 +22,11 @@ export const routes: Routes = [ component: CreateWorkspace, canActivate: [authGuard] }, + { + path: 'workspaces/:id/edit', + loadComponent: () => import('./components/workspace/edit-workspace').then(m => m.EditWorkspaceComponent), + canActivate: [authGuard] + }, { path: 'workspaces/:id/settings/members', component: WorkspaceMembersComponent, diff --git a/src/app/components/dashboard/dashboard.html b/src/app/components/dashboard/dashboard.html index 0813b0b..f39c299 100644 --- a/src/app/components/dashboard/dashboard.html +++ b/src/app/components/dashboard/dashboard.html @@ -37,7 +37,7 @@

{{ ws.name }}

Created: {{ ws.createdDate | date: 'mediumDate' }}
Open - + Edit
diff --git a/src/app/components/dashboard/dashboard.ts b/src/app/components/dashboard/dashboard.ts index e682731..549a233 100644 --- a/src/app/components/dashboard/dashboard.ts +++ b/src/app/components/dashboard/dashboard.ts @@ -52,27 +52,6 @@ export class Dashboard implements OnInit { this.loadSignals(); } - 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) { diff --git a/src/app/components/workspace/create-workspace.css b/src/app/components/workspace/create-workspace.css index 4de2a73..81da6cf 100644 --- a/src/app/components/workspace/create-workspace.css +++ b/src/app/components/workspace/create-workspace.css @@ -1,69 +1,208 @@ -.create-workspace-container { - max-width: 480px; - margin: 40px auto; - padding: 24px; - border: 1px solid #d8dee4; +.page-container { + min-height: 100vh; + background-color: #ffffff; + display: flex; + flex-direction: column; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; +} + +.top-nav { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px 32px; + background: #ffffff; + border-bottom: 1px solid #e5e5e5; + position: sticky; + top: 0; + z-index: 10; +} + +.brand { + display: flex; + align-items: center; + gap: 12px; + color: #000000; +} + +.brand-icon { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + background: #000000; + color: #ffffff; border-radius: 8px; - background: #fff; +} + +.brand-name { + font-size: 18px; + font-weight: 700; + letter-spacing: -0.5px; +} + +.back-nav-btn { + color: #000000; + text-decoration: none; + font-size: 14px; + font-weight: 500; + padding: 8px 16px; + border-radius: 6px; + transition: all 0.2s ease; + background: #ffffff; + border: 1px solid #e5e5e5; +} + +.back-nav-btn:hover { + background: #f3f3f3; + border-color: #cccccc; +} + +.form-wrapper { + flex: 1; + display: flex; + align-items: flex-start; + justify-content: center; + padding: 64px 20px; +} + +.form-card { + width: 100%; + max-width: 480px; + background: #ffffff; + border-radius: 12px; + border: 1px solid #e5e5e5; + padding: 40px; +} + +.form-header { + margin-bottom: 32px; + text-align: center; } h2 { - margin-top: 0; - margin-bottom: 8px; + margin: 0 0 8px 0; + color: #000000; + font-size: 28px; + font-weight: 700; + letter-spacing: -0.5px; } -p { - margin-top: 0; - margin-bottom: 20px; - color: #57606a; +.form-header p { + margin: 0; + color: #666666; + font-size: 15px; } form { display: flex; flex-direction: column; - gap: 10px; + gap: 24px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 8px; } label { + font-size: 14px; font-weight: 600; + color: #000000; } -input, -textarea { - padding: 10px 12px; - border: 1px solid #d0d7de; - border-radius: 6px; - font: inherit; +.premium-input { + width: 100%; + padding: 12px 16px; + border: 1px solid #e5e5e5; + border-radius: 8px; + font-size: 15px; + color: #000000; + transition: all 0.2s ease; + box-sizing: border-box; + background: #ffffff; + font-family: inherit; +} + +.premium-input:hover { + border-color: #cccccc; +} + +.premium-input:focus { + outline: none; + border-color: #000000; + border-width: 2px; + padding: 11px 15px; +} + +.premium-input::placeholder { + color: #999999; +} + +textarea.premium-input { resize: vertical; + min-height: 100px; } -.actions { - display: flex; - align-items: center; - gap: 12px; - margin-top: 10px; +.form-actions { + margin-top: 8px; } -button { - padding: 10px 14px; +.premium-btn { + width: 100%; + background: #000000; + color: #ffffff; border: none; - border-radius: 6px; - background: #1f6feb; - color: #fff; + padding: 14px 24px; + border-radius: 8px; + font-size: 16px; + font-weight: 600; cursor: pointer; + transition: background 0.2s ease; +} + +.premium-btn:hover:not(:disabled) { + background: #333333; } -button:disabled { +.premium-btn:disabled { opacity: 0.6; cursor: not-allowed; } -a { - color: #0969da; - text-decoration: none; +.error-msg { + margin-top: 24px; + padding: 12px 16px; + background: #ffffff; + border-radius: 8px; + color: #cf222e; + font-size: 14px; + font-weight: 500; + text-align: center; + border: 1px solid #cf222e; } -.error { - margin-top: 16px; - color: #cf222e; +.loading-state { + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + padding: 40px 0; + color: #000000; + font-weight: 500; +} + +.spinner { + width: 20px; + height: 20px; + border: 2px solid #e5e5e5; + border-top-color: #000000; + border-radius: 50%; + 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 b7725db..760c351 100644 --- a/src/app/components/workspace/create-workspace.html +++ b/src/app/components/workspace/create-workspace.html @@ -1,36 +1,60 @@ -
-

Create Workspace

-

Set up a workspace to organize your decisions.

+
+
+
+
+ +
+ Sentinent +
+ Back to Dashboard +
-
- - +
+
+
+

Create Workspace

+

Set up a workspace to organize your decisions and signals.

+
- - + +
+ + +
-
- - Cancel -
- +
+ + +
-

{{ error }}

+
+ +
+ + +

{{ error }}

+
+
diff --git a/src/app/components/workspace/edit-workspace.css b/src/app/components/workspace/edit-workspace.css new file mode 100644 index 0000000..81da6cf --- /dev/null +++ b/src/app/components/workspace/edit-workspace.css @@ -0,0 +1,208 @@ +.page-container { + min-height: 100vh; + background-color: #ffffff; + display: flex; + flex-direction: column; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; +} + +.top-nav { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px 32px; + background: #ffffff; + border-bottom: 1px solid #e5e5e5; + position: sticky; + top: 0; + z-index: 10; +} + +.brand { + display: flex; + align-items: center; + gap: 12px; + color: #000000; +} + +.brand-icon { + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + background: #000000; + color: #ffffff; + border-radius: 8px; +} + +.brand-name { + font-size: 18px; + font-weight: 700; + letter-spacing: -0.5px; +} + +.back-nav-btn { + color: #000000; + text-decoration: none; + font-size: 14px; + font-weight: 500; + padding: 8px 16px; + border-radius: 6px; + transition: all 0.2s ease; + background: #ffffff; + border: 1px solid #e5e5e5; +} + +.back-nav-btn:hover { + background: #f3f3f3; + border-color: #cccccc; +} + +.form-wrapper { + flex: 1; + display: flex; + align-items: flex-start; + justify-content: center; + padding: 64px 20px; +} + +.form-card { + width: 100%; + max-width: 480px; + background: #ffffff; + border-radius: 12px; + border: 1px solid #e5e5e5; + padding: 40px; +} + +.form-header { + margin-bottom: 32px; + text-align: center; +} + +h2 { + margin: 0 0 8px 0; + color: #000000; + font-size: 28px; + font-weight: 700; + letter-spacing: -0.5px; +} + +.form-header p { + margin: 0; + color: #666666; + font-size: 15px; +} + +form { + display: flex; + flex-direction: column; + gap: 24px; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 8px; +} + +label { + font-size: 14px; + font-weight: 600; + color: #000000; +} + +.premium-input { + width: 100%; + padding: 12px 16px; + border: 1px solid #e5e5e5; + border-radius: 8px; + font-size: 15px; + color: #000000; + transition: all 0.2s ease; + box-sizing: border-box; + background: #ffffff; + font-family: inherit; +} + +.premium-input:hover { + border-color: #cccccc; +} + +.premium-input:focus { + outline: none; + border-color: #000000; + border-width: 2px; + padding: 11px 15px; +} + +.premium-input::placeholder { + color: #999999; +} + +textarea.premium-input { + resize: vertical; + min-height: 100px; +} + +.form-actions { + margin-top: 8px; +} + +.premium-btn { + width: 100%; + background: #000000; + color: #ffffff; + border: none; + padding: 14px 24px; + border-radius: 8px; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: background 0.2s ease; +} + +.premium-btn:hover:not(:disabled) { + background: #333333; +} + +.premium-btn:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.error-msg { + margin-top: 24px; + padding: 12px 16px; + background: #ffffff; + border-radius: 8px; + color: #cf222e; + font-size: 14px; + font-weight: 500; + text-align: center; + border: 1px solid #cf222e; +} + +.loading-state { + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + padding: 40px 0; + color: #000000; + font-weight: 500; +} + +.spinner { + width: 20px; + height: 20px; + border: 2px solid #e5e5e5; + border-top-color: #000000; + border-radius: 50%; + animation: spin 0.8s linear infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} diff --git a/src/app/components/workspace/edit-workspace.html b/src/app/components/workspace/edit-workspace.html new file mode 100644 index 0000000..fc328b8 --- /dev/null +++ b/src/app/components/workspace/edit-workspace.html @@ -0,0 +1,65 @@ +
+
+
+
+ +
+ Sentinent +
+ Back to Dashboard +
+ +
+
+
+

Edit Workspace

+

Update the details of your workspace below.

+
+ +
+
+ Loading workspace... +
+ +
+
+ + +
+ +
+ + +
+ +
+ +
+
+ +

{{ error }}

+
+
+
diff --git a/src/app/components/workspace/edit-workspace.ts b/src/app/components/workspace/edit-workspace.ts new file mode 100644 index 0000000..0ab4689 --- /dev/null +++ b/src/app/components/workspace/edit-workspace.ts @@ -0,0 +1,67 @@ +import { Component, OnInit, inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { ActivatedRoute, Router, RouterLink } from '@angular/router'; +import { WorkspaceService } from '../../services/workspace'; + +@Component({ + selector: 'app-edit-workspace', + standalone: true, + imports: [CommonModule, FormsModule, RouterLink], + templateUrl: './edit-workspace.html', + styleUrls: ['./edit-workspace.css'] +}) +export class EditWorkspaceComponent implements OnInit { + workspaceId: string | null = null; + name = ''; + description = ''; + error = ''; + isSubmitting = false; + isLoading = true; + + private workspaceService = inject(WorkspaceService); + private router = inject(Router); + private route = inject(ActivatedRoute); + + ngOnInit(): void { + this.route.paramMap.subscribe(params => { + this.workspaceId = params.get('id'); + if (this.workspaceId) { + this.loadWorkspace(this.workspaceId); + } else { + this.router.navigate(['/dashboard']); + } + }); + } + + loadWorkspace(id: string): void { + this.workspaceService.getWorkspace(id).subscribe(workspace => { + this.isLoading = false; + if (workspace) { + this.name = workspace.name; + this.description = workspace.description || ''; + } else { + this.error = 'Workspace not found'; + } + }); + } + + onSubmit() { + const trimmedName = this.name.trim(); + if (!trimmedName || !this.workspaceId) { + this.error = 'Workspace name is required.'; + return; + } + + this.isSubmitting = true; + this.error = ''; + + this.workspaceService.updateWorkspace(this.workspaceId, trimmedName, this.description.trim()).subscribe({ + next: () => this.router.navigate(['/dashboard']), + error: () => { + this.error = 'Unable to update workspace. Please try again.'; + this.isSubmitting = false; + } + }); + } +}