feat(profile): read-first редизайн страницы пользователя, per-field как в задачах
- Раскладка: шапка-профиль → Основное/Контакты → Роль и доступ/Поля+Замещение → вторичные разделы чипами - ProfileFieldRow: двойной клик/карандаш, редактор в слоте, Esc, optimistic-кэш, все типы полей - Замещение: надпись + ⊕ popover, список под строкой - Удалены RHF-форма, zod-схема и кнопки «Сохранить» - server: PATCH /api/users/:id (частичное обновление, admin-градация, аудит) - server: history-number в REST PATCH пишет историю + пересчёт средней
This commit is contained in:
@@ -345,12 +345,38 @@ export function registerUserProfileRoutes(router: Router): void {
|
||||
if (readOnlyError) {
|
||||
return res.status(400).json({ success: false, error: readOnlyError });
|
||||
}
|
||||
const field = await storage.getUserProfileFieldById(fieldId, req.organizationId!);
|
||||
const existing = await storage.getUserProfileFieldValue(userId, fieldId);
|
||||
if (value === null || value === undefined) {
|
||||
// Удаление (null): очищается только значение поля, история history-number не трогается
|
||||
if (existing) {
|
||||
await storage.deleteUserProfileFieldValueWithAudit(userId, fieldId, req.organizationId!, changedBy);
|
||||
}
|
||||
res.json({ success: true, fieldValue: null });
|
||||
} else if (field!.type === 'history-number') {
|
||||
// history-number: число пишется в user_field_history (актор — текущий пользователь),
|
||||
// становится значением поля, месячная средняя пересчитывается
|
||||
let num: number;
|
||||
try {
|
||||
num = await storage.recordUserFieldHistoryValue(userId, field!, value, req.organizationId!, {
|
||||
auditActor: {
|
||||
changedBy,
|
||||
changedByName: `${req.user!.firstName || ''} ${req.user!.lastName || ''}`.trim(),
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: err instanceof Error ? err.message : 'Значение должно быть числом',
|
||||
});
|
||||
}
|
||||
if (existing) {
|
||||
const updated = await storage.updateUserProfileFieldValueWithAudit(userId, fieldId, { value: num }, req.organizationId!, changedBy);
|
||||
res.json({ success: true, fieldValue: updated });
|
||||
} else {
|
||||
const created = await storage.createUserProfileFieldValueWithAudit({ userId, fieldId, value: num }, req.organizationId!, changedBy);
|
||||
res.json({ success: true, fieldValue: created });
|
||||
}
|
||||
} else {
|
||||
if (existing) {
|
||||
const updated = await storage.updateUserProfileFieldValueWithAudit(userId, fieldId, { value }, req.organizationId!, changedBy);
|
||||
|
||||
Reference in New Issue
Block a user