Spaces:
Running
Running
import { Component, Inject, OnInit } from '@angular/core'; | |
import { CommonModule } from '@angular/common'; | |
import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms'; | |
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; | |
import { MatFormFieldModule } from '@angular/material/form-field'; | |
import { MatInputModule } from '@angular/material/input'; | |
import { MatButtonModule } from '@angular/material/button'; | |
import { MatIconModule } from '@angular/material/icon'; | |
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar'; | |
import { ApiService } from '../../services/api.service'; | |
({ | |
selector: 'app-project-edit-dialog', | |
standalone: true, | |
imports: [ | |
CommonModule, | |
ReactiveFormsModule, | |
MatDialogModule, | |
MatFormFieldModule, | |
MatInputModule, | |
MatButtonModule, | |
MatIconModule, | |
MatSnackBarModule | |
], | |
template: ` | |
<h2 mat-dialog-title>{{ data.mode === 'create' ? 'Create New Project' : 'Edit Project' }}</h2> | |
<mat-dialog-content> | |
<form [formGroup]="form"> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Name*</mat-label> | |
<input matInput formControlName="name" | |
[readonly]="data.mode === 'edit'" | |
placeholder="e.g., airline_agent"> | |
<mat-hint>Use only letters, numbers, and underscores</mat-hint> | |
<mat-error *ngIf="form.get('name')?.hasError('required')">Name is required</mat-error> | |
<mat-error *ngIf="form.get('name')?.hasError('pattern')">Invalid characters in name</mat-error> | |
</mat-form-field> | |
<mat-form-field appearance="outline" class="full-width"> | |
<mat-label>Caption</mat-label> | |
<input matInput formControlName="caption" | |
placeholder="e.g., Airline Customer Service Agent"> | |
</mat-form-field> | |
<div class="metadata" *ngIf="data.mode === 'edit' && data.project"> | |
<div class="metadata-item"> | |
<mat-icon>calendar_today</mat-icon> | |
<span>Created: {{ formatDate(data.project.created_date) }} by <strong>{{ data.project.created_by || 'unknown' }}</strong></span> | |
</div> | |
<div class="metadata-item"> | |
<mat-icon>update</mat-icon> | |
<span>Modified: {{ formatDate(data.project.last_update_date) }} by <strong>{{ data.project.last_update_user || 'unknown' }}</strong></span> | |
</div> | |
</div> | |
</form> | |
</mat-dialog-content> | |
<mat-dialog-actions align="end"> | |
<button mat-button (click)="cancel()">Cancel</button> | |
<button mat-raised-button color="primary" | |
(click)="save()" | |
[disabled]="form.invalid || saving"> | |
{{ saving ? 'Saving...' : 'Save' }} | |
</button> | |
</mat-dialog-actions> | |
`, | |
styles: [` | |
mat-dialog-content { | |
padding: 20px 24px; | |
min-width: 400px; | |
} | |
.full-width { | |
width: 100%; | |
margin-bottom: 16px; | |
} | |
.metadata { | |
margin-top: 24px; | |
padding: 16px; | |
background-color: #f5f5f5; | |
border-radius: 4px; | |
.metadata-item { | |
display: flex; | |
align-items: center; | |
gap: 8px; | |
margin-bottom: 8px; | |
&:last-child { | |
margin-bottom: 0; | |
} | |
mat-icon { | |
color: #666; | |
font-size: 20px; | |
width: 20px; | |
height: 20px; | |
} | |
span { | |
color: #666; | |
font-size: 14px; | |
strong { | |
color: #333; | |
} | |
} | |
} | |
} | |
mat-dialog-actions { | |
padding: 16px 24px; | |
margin: 0; | |
} | |
`] | |
}) | |
export default class ProjectEditDialogComponent implements OnInit { | |
form!: FormGroup; | |
saving = false; | |
constructor( | |
private fb: FormBuilder, | |
private apiService: ApiService, | |
private snackBar: MatSnackBar, | |
public dialogRef: MatDialogRef<ProjectEditDialogComponent>, | |
public data: any (MAT_DIALOG_DATA) | |
) {} | |
ngOnInit() { | |
this.form = this.fb.group({ | |
name: [ | |
{ value: '', disabled: this.data.mode === 'edit' }, | |
[Validators.required, Validators.pattern(/^[a-zA-Z0-9_]+$/)] | |
], | |
caption: [''], | |
last_update_date: [''] | |
}); | |
if (this.data.mode === 'edit' && this.data.project) { | |
this.form.patchValue(this.data.project); | |
} | |
} | |
formatDate(dateString: string | undefined): string { | |
if (!dateString) return 'Unknown'; | |
return new Date(dateString).toLocaleDateString(); | |
} | |
async save() { | |
if (this.form.invalid) return; | |
this.saving = true; | |
try { | |
const formData = this.form.getRawValue(); | |
if (this.data.mode === 'create') { | |
await this.apiService.createProject(formData).toPromise(); | |
this.snackBar.open('Project created successfully', 'Close', { duration: 3000 }); | |
} else { | |
await this.apiService.updateProject(this.data.project.id, formData).toPromise(); | |
this.snackBar.open('Project updated successfully', 'Close', { duration: 3000 }); | |
} | |
this.dialogRef.close(true); | |
} catch (error: any) { | |
const message = error.error?.detail || | |
(this.data.mode === 'create' ? 'Failed to create project' : 'Failed to update project'); | |
this.snackBar.open(message, 'Close', { | |
duration: 5000, | |
panelClass: 'error-snackbar' | |
}); | |
} finally { | |
this.saving = false; | |
} | |
} | |
cancel() { | |
this.dialogRef.close(false); | |
} | |
} |