diff --git a/src/app/pages/project-details/project-details.component.css b/src/app/pages/project-details/project-details.component.css
new file mode 100644
index 0000000..c67b5fa
--- /dev/null
+++ b/src/app/pages/project-details/project-details.component.css
@@ -0,0 +1,239 @@
+.details-container {
+ min-height: 100vh;
+ background-color: #f5f7fa;
+}
+
+.content {
+ padding: 40px;
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+.header {
+ display: flex;
+ align-items: flex-start;
+ gap: 16px;
+ flex-wrap: wrap;
+ margin-bottom: 24px;
+}
+
+.btn-back {
+ padding: 8px 16px;
+ border-radius: 8px;
+ border: none;
+ background-color: #e2e8f0;
+ color: #1f2933;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+}
+
+.btn-back:hover {
+ background-color: #cbd5e1;
+}
+
+.title h2 {
+ margin: 0 0 6px 0;
+ font-size: 26px;
+ color: #1f2933;
+}
+
+.title p {
+ margin: 0;
+ color: #6b7280;
+}
+
+.project-card,
+.collaborators-card,
+.tasks-card,
+.danger-zone,
+.loading,
+.error-state,
+.empty-state {
+ background: #ffffff;
+ padding: 24px;
+ border-radius: 12px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+}
+
+.project-card {
+ margin-bottom: 20px;
+}
+
+.collaborators-card {
+ margin-bottom: 20px;
+}
+
+.danger-zone {
+ margin-top: 20px;
+ border: 1px solid #fee2e2;
+ background: #fff5f5;
+}
+
+.danger-header h3 {
+ margin: 0 0 6px 0;
+ color: #b91c1c;
+}
+
+.danger-header p {
+ margin: 0;
+ color: #7f1d1d;
+}
+
+.danger-actions {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ margin-top: 16px;
+}
+
+.danger-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 16px;
+ padding: 16px;
+ border-radius: 10px;
+ background: #ffffff;
+ border: 1px solid #fecaca;
+}
+
+.danger-item h4 {
+ margin: 0 0 4px 0;
+ color: #7f1d1d;
+ font-size: 16px;
+}
+
+.danger-item p {
+ margin: 0;
+ color: #991b1b;
+ font-size: 13px;
+}
+
+.btn-danger,
+.btn-danger-outline {
+ padding: 8px 14px;
+ border-radius: 8px;
+ font-weight: 600;
+ cursor: pointer;
+ transition:
+ background-color 0.2s ease,
+ color 0.2s ease,
+ border-color 0.2s ease;
+ white-space: nowrap;
+}
+
+.btn-danger {
+ border: none;
+ background-color: #dc2626;
+ color: #ffffff;
+}
+
+.btn-danger:hover {
+ background-color: #b91c1c;
+}
+
+.btn-danger-outline {
+ border: 1px solid #fca5a5;
+ background-color: #ffffff;
+ color: #b91c1c;
+}
+
+.btn-danger-outline:hover {
+ border-color: #f87171;
+ background-color: #fee2e2;
+}
+
+.project-card h3 {
+ margin: 0 0 12px 0;
+ font-size: 22px;
+ color: #111827;
+}
+
+.description {
+ margin: 0;
+ color: #4b5563;
+}
+
+.tasks-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 16px;
+ margin-bottom: 16px;
+}
+
+.collaborators-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 16px;
+ margin-bottom: 16px;
+}
+
+.collaborators-count {
+ font-size: 14px;
+ color: #6b7280;
+}
+
+.collaborators-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 16px;
+}
+
+.btn-add-task {
+ width: 100%;
+ padding: 8px 14px;
+ border-radius: 8px;
+ border: none;
+ background-color: #10b981;
+ color: #ffffff;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+ margin-top: 16px;
+}
+
+.btn-add-collaborator {
+ width: 100%;
+ padding: 8px 14px;
+ border-radius: 8px;
+ border: none;
+ background-color: #10b981;
+ color: #ffffff;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+ margin-top: 16px;
+}
+
+.btn-add-task:hover {
+ background-color: #059669;
+}
+
+.btn-add-collaborator:hover {
+ background-color: #059669;
+}
+
+.tasks-count {
+ font-size: 14px;
+ color: #6b7280;
+}
+
+.tasks-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 16px;
+}
+
+.loading p,
+.error-state p,
+.empty-state p {
+ margin: 0;
+ color: #4b5563;
+}
+
+.error-state p {
+ color: #b91c1c;
+}
diff --git a/src/app/pages/project-details/project-details.component.html b/src/app/pages/project-details/project-details.component.html
new file mode 100644
index 0000000..7440746
--- /dev/null
+++ b/src/app/pages/project-details/project-details.component.html
@@ -0,0 +1,86 @@
+
+
+ @if (isLoading()) {
+
+ } @else if (errorMessage()) {
+
+ } @else {
+
+ {{ project()?.name }}
+ Project description:
+
+ {{ project()?.description || 'No description available.' }}
+
+
+
+
+
+
+ @if ((project()?.users?.length ?? 0) > 0) {
+
+ @for (user of project()?.users ?? []; track user.id) {
+
+ }
+
+ } @else {
+
+
No collaborators yet.
+
+ }
+
+
+
+
+
+
+
+ @if ((project()?.tasks?.length ?? 0) > 0) {
+
+ @for (task of project()?.tasks ?? []; track task.id) {
+
+ }
+
+ } @else {
+
+ }
+
+
+
+
+
+
+
+
+
+
Edit project details
+
Update the project name or description.
+
+
+
+
+
+
Delete project
+
This will remove the project and all associated data.
+
+
+
+
+
+ }
+
+
diff --git a/src/app/pages/project-details/project-details.component.ts b/src/app/pages/project-details/project-details.component.ts
new file mode 100644
index 0000000..81d65d7
--- /dev/null
+++ b/src/app/pages/project-details/project-details.component.ts
@@ -0,0 +1,108 @@
+import { Component, inject, signal } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { ActivatedRoute, Router } from '@angular/router';
+import { ApiService } from '../../services/api.service';
+import { ProjectFull } from '../../models/projects.models';
+import { CollaboratorItemComponent } from '../../components/collaborator-item/collaborator-item.component';
+import { TaskItemComponent } from '../../components/task-item/task-item.component';
+import { User } from '../../models/auth.models';
+
+@Component({
+ selector: 'app-project-details',
+ standalone: true,
+ imports: [CommonModule, CollaboratorItemComponent, TaskItemComponent],
+ templateUrl: './project-details.component.html',
+ styleUrl: './project-details.component.css',
+})
+export class ProjectDetailsComponent {
+ private apiService = inject(ApiService);
+ private route = inject(ActivatedRoute);
+ private router = inject(Router);
+ private projectId: number | null = null;
+
+ project = signal(null);
+ isLoading = signal(true);
+ errorMessage = signal('');
+
+ constructor() {
+ const navState = this.router.getCurrentNavigation()?.extras.state ?? (history.state as any);
+ const initialProject = navState?.project as ProjectFull | undefined;
+
+ if (initialProject) {
+ this.project.set(initialProject);
+ this.isLoading.set(false);
+ }
+
+ const idParam = this.route.snapshot.paramMap.get('id');
+ const projectId = idParam ? Number(idParam) : Number.NaN;
+
+ if (!Number.isFinite(projectId)) {
+ this.isLoading.set(false);
+ this.errorMessage.set('Invalid project id.');
+ return;
+ }
+
+ this.projectId = projectId;
+
+ this.apiService.get(`/projects/${projectId}`).subscribe({
+ next: (project) => {
+ this.project.set(project);
+ this.isLoading.set(false);
+ },
+ error: (error) => {
+ this.isLoading.set(false);
+ if (!initialProject) {
+ this.errorMessage.set(error?.error?.message || 'Failed to load project details.');
+ }
+ },
+ });
+ }
+
+ onBack() {
+ this.router.navigate(['/']);
+ }
+
+ onRemoveCollaborator(user: User) {
+ const current = this.project();
+ if (!current || this.projectId == null) {
+ return;
+ }
+
+ const targetId = this.getUserId(user);
+ if (!targetId) {
+ return;
+ }
+
+ const previousUsers = current.users ?? [];
+ const updatedUsers = (current.users ?? []).filter(
+ (collaborator) => this.getUserId(collaborator) !== targetId,
+ );
+
+ this.project.set({
+ ...current,
+ users: updatedUsers,
+ });
+
+ this.apiService.delete(`/projects/${this.projectId}/users/${targetId}`).subscribe({
+ error: (error) => {
+ this.project.set({
+ ...current,
+ users: previousUsers,
+ });
+ this.errorMessage.set(error?.error?.message || 'Failed to remove collaborator.');
+ },
+ });
+ }
+
+ private getUserId(user: User): string {
+ return String(user.id ?? '');
+ }
+
+ onAddTask() {
+ if (this.projectId == null) {
+ return;
+ }
+
+ this.router.navigate(['/projects', this.projectId, 'tasks', 'new']);
+ }
+}