Compare commits

..

5 Commits

Author SHA1 Message Date
Kelly
53445fe72a fix: Findagram brands page crash and PWA icon errors
- Fix mapBrandForUI to use correct 'brand' field from API response
- Add null check in Brands.jsx filter to prevent crash on undefined names
- Fix BrandPenetrationService sps.brand_name -> sps.brand_name_raw
- Remove missing logo192.png and logo512.png from PWA manifest

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 13:06:23 -07:00
kelly
37cc8956c5 Merge pull request 'fix: Join states through dispensaries in BrandPenetrationService' (#15) from feat/ci-auto-merge into master 2025-12-10 19:36:06 +00:00
kelly
2c52493a9c Merge pull request 'fix(docker): Use npm install instead of npm ci for reliability' (#14) from feat/ci-auto-merge into master 2025-12-10 18:44:21 +00:00
kelly
bafcf1694a Merge pull request 'feat(analytics): Brand promotional history + specials fix + API key editing' (#13) from feat/ci-auto-merge into master
Reviewed-on: https://code.cannabrands.app/Creationshop/dispensary-scraper/pulls/13
2025-12-10 18:12:59 +00:00
kelly
38ae2c3a3e Merge pull request 'feat/ci-auto-merge' (#12) from feat/ci-auto-merge into master
Reviewed-on: https://code.cannabrands.app/Creationshop/dispensary-scraper/pulls/12
2025-12-10 17:26:21 +00:00
4 changed files with 13 additions and 21 deletions

View File

@@ -75,7 +75,7 @@ export class BrandPenetrationService {
DATE(sps.captured_at) AS date,
COUNT(DISTINCT sps.dispensary_id) AS dispensary_count
FROM store_product_snapshots sps
WHERE sps.brand_name = $1
WHERE sps.brand_name_raw = $1
AND sps.captured_at >= $2
AND sps.captured_at <= $3
AND sps.is_in_stock = TRUE
@@ -368,23 +368,23 @@ export class BrandPenetrationService {
const result = await this.pool.query(`
WITH start_counts AS (
SELECT
brand_name,
brand_name_raw AS brand_name,
COUNT(DISTINCT dispensary_id) AS dispensary_count
FROM store_product_snapshots
WHERE captured_at >= $1 AND captured_at < $1 + INTERVAL '1 day'
AND brand_name IS NOT NULL
AND brand_name_raw IS NOT NULL
AND is_in_stock = TRUE
GROUP BY brand_name
GROUP BY brand_name_raw
),
end_counts AS (
SELECT
brand_name,
brand_name_raw AS brand_name,
COUNT(DISTINCT dispensary_id) AS dispensary_count
FROM store_product_snapshots
WHERE captured_at >= $2 - INTERVAL '1 day' AND captured_at <= $2
AND brand_name IS NOT NULL
AND brand_name_raw IS NOT NULL
AND is_in_stock = TRUE
GROUP BY brand_name
GROUP BY brand_name_raw
)
SELECT
COALESCE(sc.brand_name, ec.brand_name) AS brand_name,

View File

@@ -7,16 +7,6 @@
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",

View File

@@ -373,10 +373,12 @@ export function mapCategoryForUI(apiCategory) {
* Map API brand to UI-compatible format
*/
export function mapBrandForUI(apiBrand) {
// API returns 'brand' field (see /api/v1/brands endpoint)
const brandName = apiBrand.brand || apiBrand.brand_name || '';
return {
id: apiBrand.brand_name,
name: apiBrand.brand_name,
slug: apiBrand.brand_name?.toLowerCase().replace(/\s+/g, '-'),
id: brandName,
name: brandName,
slug: brandName ? brandName.toLowerCase().replace(/\s+/g, '-') : '',
logo: apiBrand.brand_logo_url || null,
productCount: parseInt(apiBrand.product_count || 0, 10),
dispensaryCount: parseInt(apiBrand.dispensary_count || 0, 10),

View File

@@ -27,7 +27,7 @@ const Brands = () => {
}, []);
const filteredBrands = brands.filter((brand) =>
brand.name.toLowerCase().includes(searchQuery.toLowerCase())
brand.name && brand.name.toLowerCase().includes(searchQuery.toLowerCase())
);
// Group brands alphabetically