added sale item count to db, and to be shown in "Flyers" area
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 4m22s

This commit is contained in:
2025-12-03 10:35:21 -08:00
parent 5f3de95d0e
commit 29484b61c2
9 changed files with 62 additions and 13 deletions

View File

@@ -36,6 +36,8 @@ export const FlyerList: React.FC<FlyerListProps> = ({ flyers, onFlyerSelect, sel
const from = formatShortDate(flyer.valid_from);
const to = formatShortDate(flyer.valid_to);
const dateRange = from && to ? (from === to ? from : `${from} - ${to}`) : from || to;
const processedDate = format(parseISO(flyer.created_at), 'P');
const tooltipText = `File: ${flyer.file_name}\nProcessed: ${processedDate}`;
return (
<li
@@ -43,22 +45,16 @@ export const FlyerList: React.FC<FlyerListProps> = ({ flyers, onFlyerSelect, sel
key={flyer.flyer_id}
onClick={() => onFlyerSelect(flyer)}
className={`group p-4 flex items-center space-x-3 cursor-pointer transition-colors duration-200 ${selectedFlyerId === flyer.flyer_id ? 'bg-brand-light dark:bg-brand-dark/30' : 'hover:bg-gray-50 dark:hover:bg-gray-800'}`}
title={tooltipText}
>
<DocumentTextIcon className="w-6 h-6 text-brand-primary shrink-0" />
<div className="grow min-w-0">
<p className="text-sm font-semibold text-gray-900 dark:text-white truncate" title={flyer.store?.name || 'Unknown Store'}>
{flyer.store?.name || 'Unknown Store'}
</p>
{/* The filename is now only visible on hover by default */}
<p className="text-sm text-gray-600 dark:text-gray-400 truncate opacity-0 group-hover:opacity-100 transition-opacity" title={flyer.file_name}>
{flyer.file_name}
</p>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
{/* The "Processed" date is now only visible on hover */}
<span className="opacity-0 group-hover:opacity-100 transition-opacity">
{`Processed: ${format(parseISO(flyer.created_at), 'P')}`}
</span>
{dateRange && `Valid: ${dateRange}`}
{`${flyer.item_count} items`}
{dateRange && ` • Valid: ${dateRange}`}
</p>
</div>
</li>

View File

@@ -74,7 +74,8 @@ describe('AI Routes (/api/ai)', () => {
created_at: new Date().toISOString(),
file_name: mockDataPayload.originalFileName,
image_url: '/assets/some-image.jpg',
...mockDataPayload.extractedData
...mockDataPayload.extractedData,
item_count: 0, // Add missing property to satisfy the Flyer type
});
mockedDb.logActivity.mockResolvedValue();

View File

@@ -23,7 +23,7 @@ const errMsg = (e: unknown) => {
};
// --- Multer Configuration for File Uploads ---
const storagePath = process.env.STORAGE_PATH || '/var/www/flyer-crawler.projectium.com/assets';
const storagePath = process.env.STORAGE_PATH || '/var/www/flyer-crawler.projectium.com/flyer-images';
// Ensure the storage path exists at startup so multer can write files there.
try {
@@ -243,6 +243,7 @@ router.post('/flyers/process', optionalAuth, uploadToDisk.single('flyerImage'),
valid_from: extractedData.valid_from,
valid_to: extractedData.valid_to,
store_address: extractedData.store_address,
item_count: 0, // Set default to 0; the trigger will update it.
uploaded_by: user?.user_id, // Associate with user if logged in
};

View File

@@ -22,6 +22,7 @@ export async function getFlyers(): Promise<Flyer[]> {
f.valid_from,
f.valid_to,
f.store_address,
f.item_count,
json_build_object(
'store_id', s.store_id,
'name', s.name,

View File

@@ -133,13 +133,14 @@ export const flyerWorker = new Worker<FlyerJobData>(
const flyerData = {
file_name: originalFileName,
image_url: `/assets/${path.basename(firstImage)}`,
icon_url: `/assets/icons/${iconFileName}`,
image_url: `/flyer-images/${path.basename(firstImage)}`,
icon_url: `/flyer-images/icons/${iconFileName}`,
checksum,
store_name: extractedData.store_name || 'Unknown Store (auto)',
valid_from: extractedData.valid_from,
valid_to: extractedData.valid_to,
store_address: extractedData.store_address,
item_count: 0, // Set default to 0; the trigger will update it.
uploaded_by: userId,
};

View File

@@ -17,6 +17,7 @@ export interface Flyer {
valid_from?: string | null;
valid_to?: string | null;
store_address?: string | null;
item_count: number;
uploaded_by?: string | null; // UUID of the user who uploaded it, can be null for anonymous uploads
store?: Store;
}