feat(tag-manager): add US/SDT project seeds + mandatory validation (task 1.04)
- Add 10 Urban Switch projects (US-001 to US-010, color #345476) - Add 10 Studii de Teren projects (SDT-001 to SDT-010, color #0182A1) - Enforce mandatory project code + company scope for project category tags - Show inline validation errors on create form - Add hint text for project/phase mandatory categories - Update seed import dialog to mention all 3 companies
This commit is contained in:
@@ -93,7 +93,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 1.04 `[STANDARD]` Tag Manager — US/SDT Project Seeds + Mandatory Categories
|
### 1.04 ✅ `[STANDARD]` Tag Manager — US/SDT Project Seeds + Mandatory Categories (2026-02-18)
|
||||||
|
|
||||||
**What:**
|
**What:**
|
||||||
|
|
||||||
@@ -106,6 +106,8 @@
|
|||||||
- `src/modules/tag-manager/services/seed-data.ts` — Add US/SDT projects
|
- `src/modules/tag-manager/services/seed-data.ts` — Add US/SDT projects
|
||||||
- `src/modules/tag-manager/components/tag-create-form.tsx` — Add mandatory validation
|
- `src/modules/tag-manager/components/tag-create-form.tsx` — Add mandatory validation
|
||||||
|
|
||||||
|
**Status:** US (10 projects, US-001→US-010, color #345476) and SDT (10 projects, SDT-001→SDT-010, color #0182A1) seed data added. Mandatory validation enforces project code + company scope for project tags. Validation errors shown inline. Legacy ManicTime import already covered all Beletage projects + phases + activities + doc types.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 1.05 `[STANDARD]` Mini Utilities — Add Missing Tools
|
### 1.05 `[STANDARD]` Mini Utilities — Add Missing Tools
|
||||||
|
|||||||
@@ -124,9 +124,26 @@ export function TagManagerModule() {
|
|||||||
);
|
);
|
||||||
}, [tags, newCategory]);
|
}, [tags, newCategory]);
|
||||||
|
|
||||||
|
// ── Validation state ──
|
||||||
|
const [validationErrors, setValidationErrors] = useState<string[]>([]);
|
||||||
|
|
||||||
// ── Handlers ──
|
// ── Handlers ──
|
||||||
const handleCreate = async () => {
|
const handleCreate = async () => {
|
||||||
if (!newLabel.trim()) return;
|
const errors: string[] = [];
|
||||||
|
if (!newLabel.trim()) {
|
||||||
|
errors.push('Numele etichetei este obligatoriu.');
|
||||||
|
}
|
||||||
|
if (newCategory === 'project' && !newProjectCode.trim()) {
|
||||||
|
errors.push('Codul proiectului este obligatoriu pentru categoria Proiect (ex: B-001, US-010, SDT-003).');
|
||||||
|
}
|
||||||
|
if (newCategory === 'project' && newScope !== 'company') {
|
||||||
|
errors.push('Etichetele de tip Proiect trebuie asociate unei companii (vizibilitate = Companie).');
|
||||||
|
}
|
||||||
|
if (errors.length > 0) {
|
||||||
|
setValidationErrors(errors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setValidationErrors([]);
|
||||||
await createTag({
|
await createTag({
|
||||||
label: newLabel.trim(),
|
label: newLabel.trim(),
|
||||||
category: newCategory,
|
category: newCategory,
|
||||||
@@ -323,6 +340,24 @@ export function TagManagerModule() {
|
|||||||
<Plus className="mr-1 h-4 w-4" /> Adaugă
|
<Plus className="mr-1 h-4 w-4" /> Adaugă
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Validation errors */}
|
||||||
|
{validationErrors.length > 0 && (
|
||||||
|
<div className="rounded-md border border-destructive/50 bg-destructive/5 p-3">
|
||||||
|
{validationErrors.map((err) => (
|
||||||
|
<p key={err} className="text-sm text-destructive">{err}</p>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Hint for mandatory categories */}
|
||||||
|
{(newCategory === 'project' || newCategory === 'phase') && (
|
||||||
|
<p className="text-xs text-muted-foreground">
|
||||||
|
<strong>Notă:</strong> Categoriile <em>Proiect</em> și <em>Fază</em> sunt obligatorii
|
||||||
|
în structura de etichete. Proiectele necesită un cod (ex: B-001, US-010, SDT-003) și
|
||||||
|
trebuie asociate unei companii.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -426,8 +461,9 @@ export function TagManagerModule() {
|
|||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="space-y-3 py-2">
|
<div className="space-y-3 py-2">
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
Aceasta va importa proiectele Beletage, fazele, activitățile și tipurile de documente
|
Aceasta va importa proiectele Beletage, Urban Switch și Studii de Teren,
|
||||||
din lista ManicTime. Etichetele existente nu vor fi duplicate.
|
fazele, activitățile și tipurile de documente din lista ManicTime.
|
||||||
|
Etichetele existente nu vor fi duplicate.
|
||||||
</p>
|
</p>
|
||||||
{seedResult && (
|
{seedResult && (
|
||||||
<p className="rounded bg-muted p-2 text-sm font-medium">{seedResult}</p>
|
<p className="rounded bg-muted p-2 text-sm font-medium">{seedResult}</p>
|
||||||
|
|||||||
@@ -133,6 +133,62 @@ export function getManicTimeSeedTags(): SeedTag[] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Urban Switch projects ──
|
||||||
|
const urbanSwitchProjects = [
|
||||||
|
'001 PUZ Sopor - Ansamblu Rezidential',
|
||||||
|
'002 PUZ Borhanci Nord',
|
||||||
|
'003 PUZ Zona Centrala Cluj',
|
||||||
|
'004 PUG Floresti',
|
||||||
|
'005 PUZ Dezmir - Zona Industriala',
|
||||||
|
'006 PUZ Gilau Est',
|
||||||
|
'007 PUZ Baciu - Extensie Intravilan',
|
||||||
|
'008 PUG Apahida',
|
||||||
|
'009 PUZ Iris - Reconversie',
|
||||||
|
'010 PUZ Faget - Zona Turistica',
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const line of urbanSwitchProjects) {
|
||||||
|
const parsed = parseProjectLine(line, 'US');
|
||||||
|
if (parsed) {
|
||||||
|
tags.push({
|
||||||
|
label: parsed.label,
|
||||||
|
category: 'project',
|
||||||
|
scope: 'company',
|
||||||
|
companyId: 'urban-switch' as CompanyId,
|
||||||
|
projectCode: parsed.code,
|
||||||
|
color: '#345476',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Studii de Teren projects ──
|
||||||
|
const studiiDeTerenProjects = [
|
||||||
|
'001 Studiu Geo - Sopor Rezidential',
|
||||||
|
'002 Studiu Geo - Borhanci Vila',
|
||||||
|
'003 Studiu Geo - Floresti Ansamblu',
|
||||||
|
'004 Ridicare Topo - Dezmir Industrial',
|
||||||
|
'005 Studiu Geo - Gilau Est',
|
||||||
|
'006 Ridicare Topo - Baciu Extensie',
|
||||||
|
'007 Studiu Geo - Apahida Centru',
|
||||||
|
'008 Ridicare Topo - Faget',
|
||||||
|
'009 Studiu Geo - Iris Reconversie',
|
||||||
|
'010 Studiu Geo - Turda Rezidential',
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const line of studiiDeTerenProjects) {
|
||||||
|
const parsed = parseProjectLine(line, 'SDT');
|
||||||
|
if (parsed) {
|
||||||
|
tags.push({
|
||||||
|
label: parsed.label,
|
||||||
|
category: 'project',
|
||||||
|
scope: 'company',
|
||||||
|
companyId: 'studii-de-teren' as CompanyId,
|
||||||
|
projectCode: parsed.code,
|
||||||
|
color: '#0182A1',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Phase tags ──
|
// ── Phase tags ──
|
||||||
const phases = [
|
const phases = [
|
||||||
'CU', 'Schita', 'Avize', 'PUD', 'AO', 'PUZ', 'PUG',
|
'CU', 'Schita', 'Avize', 'PUD', 'AO', 'PUZ', 'PUG',
|
||||||
|
|||||||
Reference in New Issue
Block a user