Files
iistwin/server/routes/form-folders.routes.ts
Ильяс Султанов 1f5ecb6da4 fix(number-fields): избегаем потери точности длинных чисел
- number-поля теперь рендерятся как text + inputMode=numeric,
  чтобы браузер не округлял значения через input type=number
- пробелы при вставке в number-поля удаляются
- бэкенд нормализует значения number-полей в строку перед сохранением
- добавлен хелпер normalizeFieldValueForStorage

Closes: искажение расчётного счёта и других длинных числовых полей
2026-07-07 21:03:40 +03:00

103 lines
3.9 KiB
TypeScript

import { Router } from "express";
import { type AuthenticatedRequest } from "../middleware/auth.middleware";
import {
getFormFolders,
createFormFolder,
updateFormFolder,
deleteFormFolder,
moveFormToFolder,
reorderFormFolders,
moveFormFolder,
} from "../storage/folder.storage";
export function registerFormFolderRoutes(router: ReturnType<typeof Router>): void {
router.get('/api/forms/folders', async (req: AuthenticatedRequest, res) => {
try {
const folders = await getFormFolders(req.organizationId!);
res.json({ success: true, folders });
} catch (error) {
console.error('Get form folders error:', error);
res.status(500).json({ success: false, error: 'Ошибка при получении папок' });
}
});
router.post('/api/forms/folders', async (req: AuthenticatedRequest, res) => {
try {
const { name, parentId, position } = req.body;
if (!name || typeof name !== 'string') {
return res.status(400).json({ success: false, error: 'Название папки обязательно' });
}
const folder = await createFormFolder({
organizationId: req.organizationId!,
name,
parentId: parentId ?? null,
position: position ?? 0,
});
res.status(201).json({ success: true, folder });
} catch (error) {
console.error('Create form folder error:', error);
res.status(500).json({ success: false, error: 'Ошибка при создании папки' });
}
});
router.put('/api/forms/folders/:id', async (req: AuthenticatedRequest, res) => {
try {
const id = parseInt(req.params.id);
const { name, parentId, position } = req.body;
let folder;
if (parentId !== undefined || position !== undefined) {
folder = await moveFormFolder(id, req.organizationId!, parentId ?? null, position ?? 0);
} else {
folder = await updateFormFolder(id, req.organizationId!, { name });
}
if (!folder) {
return res.status(404).json({ success: false, error: 'Папка не найдена' });
}
res.json({ success: true, folder });
} catch (error) {
console.error('Update form folder error:', error);
res.status(500).json({ success: false, error: 'Ошибка при обновлении папки' });
}
});
router.delete('/api/forms/folders/:id', async (req: AuthenticatedRequest, res) => {
try {
const id = parseInt(req.params.id);
await deleteFormFolder(id, req.organizationId!);
res.json({ success: true });
} catch (error) {
console.error('Delete form folder error:', error);
res.status(500).json({ success: false, error: 'Ошибка при удалении папки' });
}
});
router.patch('/api/forms/folders/reorder', async (req: AuthenticatedRequest, res) => {
try {
const { updates } = req.body;
if (!Array.isArray(updates)) {
return res.status(400).json({ success: false, error: 'Некорректные данные' });
}
await reorderFormFolders(req.organizationId!, updates);
res.json({ success: true });
} catch (error) {
console.error('Reorder form folders error:', error);
res.status(500).json({ success: false, error: 'Ошибка при изменении порядка' });
}
});
router.patch('/api/forms/:id/folder', async (req: AuthenticatedRequest, res) => {
try {
const id = parseInt(req.params.id);
const { folderId } = req.body;
const form = await moveFormToFolder(id, req.organizationId!, folderId ?? null);
if (!form) {
return res.status(404).json({ success: false, error: 'Форма не найдена' });
}
res.json({ success: true, form });
} catch (error) {
console.error('Move form to folder error:', error);
res.status(500).json({ success: false, error: 'Ошибка при перемещении формы' });
}
});
}