import { Component, inject, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { StatusEntity, StatusesStore } from './statuses.store'; type FormMode = 'create' | 'edit'; type StatusForm = { id: string; label: string; bg: string; color: string }; @Component({ selector: 'app-statuses', imports: [FormsModule], templateUrl: './statuses.html', styleUrl: './statuses.css', }) export class Statuses { protected readonly statusesStore = inject(StatusesStore); protected readonly statuses = this.statusesStore.statuses; protected dragIndex: number | null = null; protected dragOverIndex: number | null = null; protected formMode = signal(null); protected editingId = signal(null); protected form: StatusForm = this.emptyForm(); protected idError = signal(null); protected openCreate(): void { this.form = this.emptyForm(); this.idError.set(null); this.editingId.set(null); this.formMode.set('create'); } protected openEdit(status: StatusEntity): void { this.form = { id: status.id, label: status.label, bg: status.bg, color: status.color }; this.idError.set(null); this.editingId.set(status.id); this.formMode.set('edit'); } protected cancel(): void { this.formMode.set(null); this.editingId.set(null); } protected save(): void { if (this.formMode() === 'create') { const id = this.slugify(this.form.id || this.form.label); if (!id) return; if (this.statusesStore.getById(id)) { this.idError.set('Un statut avec cet identifiant existe déjà.'); return; } this.statusesStore.create({ id, label: this.form.label.trim(), bg: this.form.bg, color: this.form.color }); } else { const id = this.editingId(); if (!id) return; this.statusesStore.update(id, { label: this.form.label.trim(), bg: this.form.bg, color: this.form.color }); } this.formMode.set(null); this.editingId.set(null); } protected isFormValid(): boolean { return this.form.label.trim().length > 0; } protected onDragStart(index: number): void { this.dragIndex = index; } protected onDragOver(event: DragEvent, index: number): void { event.preventDefault(); this.dragOverIndex = index; } protected onDrop(event: DragEvent, dropIndex: number): void { event.preventDefault(); if (this.dragIndex === null || this.dragIndex === dropIndex) { this.dragIndex = null; this.dragOverIndex = null; return; } const newOrder = [...this.statuses()]; const [dragged] = newOrder.splice(this.dragIndex, 1); newOrder.splice(dropIndex, 0, dragged); this.statusesStore.setOrder(newOrder); this.dragIndex = null; this.dragOverIndex = null; } protected onDragEnd(): void { this.dragIndex = null; this.dragOverIndex = null; } private slugify(value: string): string { return value .trim() .toLowerCase() .normalize('NFD') .replace(/[̀-ͯ]/g, '') .replace(/[^a-z0-9]+/g, '-') .replace(/^-+|-+$/g, ''); } private emptyForm(): StatusForm { return { id: '', label: '', bg: '#e2e8f0', color: '#475569' }; } }