Update/add frontend pages for categories, brands, vendors new routes, update products page to use new route

This commit is contained in:
2025-04-01 14:34:57 -04:00
parent 1b9f01d101
commit dbd0232285
18 changed files with 2844 additions and 2619 deletions

View File

@@ -192,7 +192,28 @@ router.get('/', async (req, res) => {
]);
const total = parseInt(countResult.rows[0].total, 10);
const brands = dataResult.rows;
const brands = dataResult.rows.map(row => {
// Create a new object with both snake_case and camelCase keys
const transformedRow = { ...row }; // Start with original data
for (const key in row) {
// Skip null/undefined values
if (row[key] === null || row[key] === undefined) {
continue; // Original already has the null value
}
// Transform keys to match frontend expectations (add camelCase versions)
// First handle cases like sales_7d -> sales7d
let camelKey = key.replace(/_(\d+[a-z])/g, '$1');
// Then handle regular snake_case -> camelCase
camelKey = camelKey.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
if (camelKey !== key) { // Only add if different from original
transformedRow[camelKey] = row[key];
}
}
return transformedRow;
});
// --- Respond ---
res.json({

View File

@@ -222,17 +222,20 @@ router.get('/', async (req, res) => {
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
// Need JOIN for parent_name if sorting/filtering by it, or always include for display
const needParentJoin = sortColumn === 'p.name' || conditions.some(c => c.includes('p.name'));
const sortColumn = sortColumnInfo?.dbCol;
// Always include the parent join for consistency
const parentJoinSql = 'LEFT JOIN public.categories p ON cm.parent_id = p.cat_id';
const baseSql = `
FROM public.category_metrics cm
${needParentJoin ? 'LEFT JOIN public.categories p ON cm.parent_id = p.cat_id' : ''}
${parentJoinSql}
${whereClause}
`;
const countSql = `SELECT COUNT(*) AS total ${baseSql}`;
const dataSql = `
SELECT cm.* ${needParentJoin ? ', p.name as parent_name' : ''}
SELECT cm.*, p.name as parent_name
${baseSql}
${sortClause}
LIMIT $${paramCounter} OFFSET $${paramCounter + 1}
@@ -248,7 +251,28 @@ router.get('/', async (req, res) => {
]);
const total = parseInt(countResult.rows[0].total, 10);
const categories = dataResult.rows;
const categories = dataResult.rows.map(row => {
// Create a new object with both snake_case and camelCase keys
const transformedRow = { ...row }; // Start with original data
for (const key in row) {
// Skip null/undefined values
if (row[key] === null || row[key] === undefined) {
continue; // Original already has the null value
}
// Transform keys to match frontend expectations (add camelCase versions)
// First handle cases like sales_7d -> sales7d
let camelKey = key.replace(/_(\d+[a-z])/g, '$1');
// Then handle regular snake_case -> camelCase
camelKey = camelKey.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
if (camelKey !== key) { // Only add if different from original
transformedRow[camelKey] = row[key];
}
}
return transformedRow;
});
// --- Respond ---
res.json({

View File

@@ -196,7 +196,28 @@ router.get('/', async (req, res) => {
]);
const total = parseInt(countResult.rows[0].total, 10);
const vendors = dataResult.rows;
const vendors = dataResult.rows.map(row => {
// Create a new object with both snake_case and camelCase keys
const transformedRow = { ...row }; // Start with original data
for (const key in row) {
// Skip null/undefined values
if (row[key] === null || row[key] === undefined) {
continue; // Original already has the null value
}
// Transform keys to match frontend expectations (add camelCase versions)
// First handle cases like sales_7d -> sales7d
let camelKey = key.replace(/_(\d+[a-z])/g, '$1');
// Then handle regular snake_case -> camelCase
camelKey = camelKey.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
if (camelKey !== key) { // Only add if different from original
transformedRow[camelKey] = row[key];
}
}
return transformedRow;
});
// --- Respond ---
res.json({