Public Access
- Dashboard MealCard: title truncate -> line-clamp-2, image shrinks to 40x40 on <md to give the title room (B6). - MealDetail: hero reworked to normal flow with stronger gradient; description runs through new cleanDescription() helper that strips 14 spoonacular SEO patterns and trims to the last full sentence. Raw description moved to a 'Notes from source' disclosure (B7). - Pantry: free-text aisle/unit replaced with <Select> populated from the new PANTRY_AISLES canonical enum; ingredient name field marked required. New PANTRY_AISLES export + PantryAisle type in types (B8). - backend: alembic 0015_normalize_pantry_aisles maps free-text ingredient.aisle and grocery_item.aisle to canonical labels in a single transaction; downgrade raises (restore from snapshot). backend/scripts/dry_run_aisle_migration.sql is the read-only preview helper. - ShoppingList: human-readable AISLE_LABEL map replaces raw snake_case aisle keys; 3-col stat grid with compact mobile sizing (B9 + S3.3). - Pantry table: role/aria-label region and a right-edge white gradient hint at mobile horizontal overflow (B10). - Recipes: pending/applied filter split, Apply and Reset buttons, active-count chip on the Filters button, role=region + aria-label on the panel (B11). - Review/sprint2-verification.md and fix-ui-audit.md updated. Build: npm run build (tsc + vite) green. tsc emits 0 errors. Co-located audit + plan docs kept in sync: Review/ui-nielsen-audit.md gains a Sprint 2 status block; fix-ui-audit.md has implementation notes for each Sprint 2 task.
77 lines
2.4 KiB
SQL
77 lines
2.4 KiB
SQL
-- Dry-run: show which rows WOULD change under the aisle normalization
|
|
-- migration 0015. Safe to run against any database; makes no changes.
|
|
--
|
|
-- Usage (from the deployment host):
|
|
-- psql "$DATABASE_URL" -f backend/scripts/dry_run_aisle_migration.sql
|
|
|
|
WITH src AS (
|
|
SELECT
|
|
'ingredient'::text AS tbl,
|
|
id::text AS id,
|
|
aisle AS old_aisle,
|
|
LOWER(COALESCE(aisle, '')) AS key
|
|
FROM ingredient
|
|
WHERE aisle IS NOT NULL
|
|
UNION ALL
|
|
SELECT
|
|
'grocery_item'::text,
|
|
id::text,
|
|
aisle,
|
|
LOWER(COALESCE(aisle, ''))
|
|
FROM grocery_item
|
|
WHERE aisle IS NOT NULL
|
|
),
|
|
mapped AS (
|
|
SELECT
|
|
tbl, id, old_aisle,
|
|
CASE key
|
|
WHEN 'canned goods' THEN 'Pantry'
|
|
WHEN 'canned' THEN 'Pantry'
|
|
WHEN 'freezer' THEN 'Frozen'
|
|
WHEN 'frozen' THEN 'Frozen'
|
|
WHEN 'produce' THEN 'Produce'
|
|
WHEN 'fruit' THEN 'Produce'
|
|
WHEN 'vegetable' THEN 'Produce'
|
|
WHEN 'dairy' THEN 'Dairy & Eggs'
|
|
WHEN 'eggs' THEN 'Dairy & Eggs'
|
|
WHEN 'cheese' THEN 'Dairy & Eggs'
|
|
WHEN 'milk' THEN 'Dairy & Eggs'
|
|
WHEN 'yogurt' THEN 'Dairy & Eggs'
|
|
WHEN 'meat' THEN 'Meat & Seafood'
|
|
WHEN 'seafood' THEN 'Meat & Seafood'
|
|
WHEN 'fish' THEN 'Meat & Seafood'
|
|
WHEN 'chicken' THEN 'Meat & Seafood'
|
|
WHEN 'beef' THEN 'Meat & Seafood'
|
|
WHEN 'pork' THEN 'Meat & Seafood'
|
|
WHEN 'meat_seafood' THEN 'Meat & Seafood'
|
|
WHEN 'bakery' THEN 'Bakery'
|
|
WHEN 'bread' THEN 'Bakery'
|
|
WHEN 'beverage' THEN 'Beverages'
|
|
WHEN 'beverages' THEN 'Beverages'
|
|
WHEN 'drinks' THEN 'Beverages'
|
|
WHEN 'spice' THEN 'Spices'
|
|
WHEN 'spices' THEN 'Spices'
|
|
WHEN 'seasoning' THEN 'Spices'
|
|
WHEN 'pantry' THEN 'Pantry'
|
|
WHEN 'dry' THEN 'Pantry'
|
|
WHEN 'snack' THEN 'Pantry'
|
|
WHEN 'snacks' THEN 'Pantry'
|
|
ELSE 'Other'
|
|
END AS new_aisle
|
|
FROM src
|
|
)
|
|
SELECT tbl,
|
|
COUNT(*) AS rows_to_change,
|
|
COUNT(DISTINCT old_aisle) AS distinct_old_values
|
|
FROM mapped
|
|
WHERE old_aisle IS DISTINCT FROM new_aisle
|
|
GROUP BY tbl
|
|
ORDER BY tbl;
|
|
|
|
-- Optional detail dump (uncomment to inspect actual rows):
|
|
-- SELECT tbl, old_aisle, new_aisle, COUNT(*)
|
|
-- FROM mapped
|
|
-- WHERE old_aisle IS DISTINCT FROM new_aisle
|
|
-- GROUP BY tbl, old_aisle, new_aisle
|
|
-- ORDER BY tbl, old_aisle;
|