mirror of
https://github.com/a-mayb3/KanbanCloneAngular.git
synced 2026-03-21 09:55:37 +01:00
Started working on project creation form page
This commit is contained in:
parent
2f3f8354a7
commit
773fa7ad6d
4 changed files with 202 additions and 2 deletions
|
|
@ -1,5 +1,8 @@
|
||||||
<app-navbar />
|
<app-navbar />
|
||||||
<main class="main">
|
<main class="main"></main>
|
||||||
</main>
|
|
||||||
|
|
||||||
|
<app-footer />
|
||||||
|
|
||||||
<router-outlet />
|
<router-outlet />
|
||||||
|
|
||||||
|
|
|
||||||
89
src/app/pages/project-create/project-create.component.css
Normal file
89
src/app/pages/project-create/project-create.component.css
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
.create-project {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
padding: 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 640px;
|
||||||
|
height: fit-content;
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 32px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card h1 {
|
||||||
|
margin: 0 0 24px 0;
|
||||||
|
font-size: 28px;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input,
|
||||||
|
.form-group textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px 14px;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group textarea {
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
padding: 10px 16px;
|
||||||
|
background-color: #10b981;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
padding: 10px 16px;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid #cbd5f0;
|
||||||
|
color: #334155;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #fee2e2;
|
||||||
|
color: #b91c1c;
|
||||||
|
}
|
||||||
49
src/app/pages/project-create/project-create.component.html
Normal file
49
src/app/pages/project-create/project-create.component.html
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
<div class="create-project">
|
||||||
|
<div class="card">
|
||||||
|
<h1>Create project</h1>
|
||||||
|
|
||||||
|
@if (errorMessage()) {
|
||||||
|
<div class="error">{{ errorMessage() }}</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<form (ngSubmit)="onSubmit()" #projectForm="ngForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">Project name</label>
|
||||||
|
<input
|
||||||
|
id="name"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
[(ngModel)]="name"
|
||||||
|
placeholder="Enter a project name"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description">Description</label>
|
||||||
|
<textarea
|
||||||
|
id="description"
|
||||||
|
name="description"
|
||||||
|
[(ngModel)]="description"
|
||||||
|
rows="4"
|
||||||
|
placeholder="Optional description"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
<button type="button" class="btn-secondary" (click)="onCancel()">Cancel</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="btn-primary"
|
||||||
|
[disabled]="isSaving() || !projectForm.form.valid"
|
||||||
|
>
|
||||||
|
@if (isSaving()) {
|
||||||
|
<span>Creating...</span>
|
||||||
|
} @else {
|
||||||
|
<span>Create project</span>
|
||||||
|
}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
59
src/app/pages/project-create/project-create.component.ts
Normal file
59
src/app/pages/project-create/project-create.component.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { Component, inject, signal } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { ApiService } from '../../services/api.service';
|
||||||
|
import { CreateProjectRequest, Project } from '../../models/projects.models';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-project-create',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule, FormsModule],
|
||||||
|
templateUrl: './project-create.component.html',
|
||||||
|
styleUrl: './project-create.component.css'
|
||||||
|
})
|
||||||
|
export class ProjectCreateComponent {
|
||||||
|
private apiService = inject(ApiService);
|
||||||
|
private router = inject(Router);
|
||||||
|
|
||||||
|
name = '';
|
||||||
|
description = '';
|
||||||
|
isSaving = signal(false);
|
||||||
|
errorMessage = signal('');
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
if (!this.name.trim()) {
|
||||||
|
this.errorMessage.set('Project name is required.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload: CreateProjectRequest = {
|
||||||
|
name: this.name.trim(),
|
||||||
|
description: this.description.trim() || undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isSaving.set(true);
|
||||||
|
this.errorMessage.set('');
|
||||||
|
|
||||||
|
this.apiService.post<Project>('/projects', payload).subscribe({
|
||||||
|
next: (project) => {
|
||||||
|
this.isSaving.set(false);
|
||||||
|
if (project?.id != null) {
|
||||||
|
this.router.navigate(['/projects', project.id]);
|
||||||
|
} else {
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: (error) => {
|
||||||
|
this.isSaving.set(false);
|
||||||
|
this.errorMessage.set(
|
||||||
|
error?.error?.message || 'Failed to create project. Please try again.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancel() {
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue