feat: Sprint A Wahab review batch — categories, property hierarchy, priority grouping
Items 1-5, 9, 11 from denya-wahab-feedback-s2: - Category.show_in_form (alert-only flag): Gas Leak hidden from issue picker but kept urgent for SLA/alert and reporting; emergency quick path on the new-issue form creates urgent tickets via include_hidden categories. - Seed: Aluminum/Glass, Carpentry, Mould & Damp (Medium default) maintenance categories; Lost Property renamed Missing Item (+ sub). - One alembic migration: add show_in_form (backfill True, Gas Leak False) + data rename Lost Property -> Missing Item. - Property -> Building -> Apartment cascade with searchable apartment combobox on the new-issue form and ticket list filters; /api/tickets/units gains building filter + /units/grouped variant; /api/tickets gains additive building/unit_id filters. apartment_mapping.json committed (deterministic). - Group-by-priority toggle on /tickets (four sections + unknown bucket, age-sortable, composes with filters, URL deep links), FM dashboard active tickets, and CS dashboard priority card click-through. - Tests: 13 new (category visibility, seed idempotency/sync, unit grouping, ticket building/unit filters).
This commit is contained in:
@@ -355,6 +355,32 @@
|
||||
if (diffHrs < 1) return '< 1h';
|
||||
if (diffHrs < 24) return `${diffHrs}h`;
|
||||
return `${diffDays}d`;
|
||||
},
|
||||
|
||||
groupByPriority(tickets, ageDir = 'desc') {
|
||||
// Group tickets into Urgent/High/Medium/Low + an other bucket,
|
||||
// each sorted by age (desc = newest first, asc = oldest first).
|
||||
const order = ['urgent', 'high', 'medium', 'low'];
|
||||
const groups = { urgent: [], high: [], medium: [], low: [], other: [] };
|
||||
const age = (t) => new Date(t.created_at).getTime() || 0;
|
||||
(tickets || []).forEach(t => {
|
||||
const p = String(t.priority || '').toLowerCase();
|
||||
groups[order.includes(p) ? p : 'other'].push(t);
|
||||
});
|
||||
Object.keys(groups).forEach(k => {
|
||||
groups[k].sort((a, b) => (ageDir === 'asc' ? age(a) - age(b) : age(b) - age(a)));
|
||||
});
|
||||
return groups;
|
||||
},
|
||||
|
||||
priorityGroupMeta() {
|
||||
return [
|
||||
{ key: 'urgent', label: '🔴 Urgent', cls: 'border-red-200 bg-red-50' },
|
||||
{ key: 'high', label: '🟠 High', cls: 'border-orange-200 bg-orange-50' },
|
||||
{ key: 'medium', label: '🟡 Medium', cls: 'border-yellow-200 bg-yellow-50' },
|
||||
{ key: 'low', label: '🟢 Low', cls: 'border-green-200 bg-green-50' },
|
||||
{ key: 'other', label: '⚪ No priority / Unknown', cls: 'border-gray-200 bg-gray-50' },
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user