caterium-app/ops/demo/trial-extras-data.mjs
pavlov346346-source 40b5c146c2 feat: add photos for the 34 training-catalog items that had none
The banquet menu (18 dishes) and extras/supplies/delivery items (16)
in the training catalog were seeded with photo:'', which the catalog
tiles render as a plain red placeholder square. Sourced a real photo
for each item (mostly Pexels, free license, picked and visually
reviewed one by one to avoid mismatches -- several first search hits
were wrong: a live chicken for "chicken caesar salad", a person in
frame, branded bottles/cups) and two AI-generated (banquet-caprese,
banquet-roastbeef). Converted to square 1024x1024 WebP with sharp.

Wires the paths through the actual source of truth: ops/demo/trial-
banquet-data.mjs and trial-extras-data.mjs now set photo to the real
path, then ops/demo/build-trial-*.mjs regenerated public/demo/*.json
and the matching Supabase seed-function migrations, so the client's
static JSON fetch and the server-side company-provisioning function
stay in sync.

Bumped the demo-catalog fetch's own cache-busting query string in
training-catalog.js (and its script-tag/precache version), since it's
fetched by the client with a separate version from the outer script
tags -- the same stale-cache class of bug fixed earlier this session.

Verified: all 34 referenced files resolve (200) and decode as real
1024x1024 images; confirmed via the actual rendered catalog tiles
(#tiles img[src]) that the extras category -- where the user's
red-square screenshot was taken -- now serves the real photo paths.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 17:00:45 +03:00

37 lines
5.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Fictional items for empty trial tabs. Native category IDs must not follow visual order.
import {boxes} from './trial-demo-data.mjs';
const round=n=>Math.round(n*1000)/1000;
const mixes=[
['salmon-caprese','Премиум-сет «Лосось и капрезе»',3500,18,['salmon-cream','caprese']],
['meat-cheese','Премиум-сет «Мясо и сыры»',3900,0,['meat-assortment','cheese-fruit']],
['mini-buffet','Премиум-сет «Мини-фуршет»',2900,22,['bruschetta-tomato','mushroom-tartlet']]
];
const premium=mixes.map(([key,name,price,pieces,sourceIds],index)=>{
const sources=sourceIds.map(id=>boxes.find(b=>b.id===`demo-v1-${id}`)),map=new Map();
for(const b of sources)for(const r of b.ttk.rows){const old=map.get(r.productId)||{...r,gross:0,net:0};old.gross=round(old.gross+r.gross/2);old.net=round(old.net+r.net/2);map.set(r.productId,old)}
const rows=[...map.values()],outputGrams=Math.round(rows.filter(r=>r.unit==='кг').reduce((s,r)=>s+r.net*1000,0));
return {id:`demo-extras-v1-${key}`,name,category:5,catalogSection:'Демонстрационные премиум-сеты',price,pieces,weight:`${outputGrams} г`,photo:`demo/images/extras-${key}.webp`,demo:true,
composition:sources.map(b=>'Половина стандартного бокса: '+b.name),ingredients:rows.map(r=>[r.name,r.gross,r.unit]),
ttk:{number:`ДЕМО-П${index+1}`,basis:'На 1 готовый премиум-сет',outputGrams,pieces,rows,
steps:['Приготовить две мини-подборки в половинном объёме по указанным нормам.',...sources.flatMap(b=>b.ttk.steps.map(s=>b.name+': '+s)),'Уложить обе подборки в одну общую коробку.'],
allergens:[...new Set(sources.flatMap(b=>b.ttk.allergens))],ingredientCost:Math.round(rows.reduce((s,r)=>s+r.gross*r.unitCost,0)*100)/100,note:'Учебный сет и примерные цены. Все количества в таблице рассчитаны на один сет.'}};
});
const specs=[
// key, category, sale name, sale price, stock name, purchase cost, unit, supplier, description
['water',3,'Вода негазированная, 0,5 л',90,'Демо: вода негазированная 0,5 л',35,'шт.','grocery','Одна бутылка 0,5 л'],
['sparkling',3,'Вода газированная, 0,5 л',100,'Демо: вода газированная 0,5 л',40,'шт.','grocery','Одна бутылка 0,5 л'],
['juice',3,'Яблочный сок, 1 л',220,'Демо: сок яблочный 1 л',110,'шт.','grocery','Одна упаковка 1 л'],
['mors',3,'Клюквенный морс, 1 л',280,'Демо: морс клюквенный 1 л',140,'шт.','grocery','Одна бутылка готового морса 1 л'],
['plate',1,'Тарелка одноразовая, 1 шт.',25,'Демо: тарелка одноразовая',12,'шт.','pack','Одна сервировочная тарелка'],
['fork',1,'Вилка одноразовая, 1 шт.',10,'Демо: вилка одноразовая',4,'шт.','pack','Одна вилка'],
['glass',1,'Стакан одноразовый, 250 мл',15,'Демо: стакан одноразовый 250 мл',6,'шт.','pack','Один стакан'],
['napkin',1,'Салфетка сервировочная, 1 шт.',10,'Демо: салфетка сервировочная',3,'шт.','pack','Одна бумажная салфетка'],
['ice',2,'Лёд пищевой, пакет 1 кг',180,'Демо: лёд пищевой',70,'кг','grocery','Один пакет пищевого льда, 1 кг'],
['tablecloth',2,'Скатерть одноразовая, 1 шт.',250,'Демо: скатерть одноразовая',110,'шт.','pack','Одна одноразовая скатерть 120 × 180 см'],
['serving-kit',2,'Набор для подачи: щипцы и лопатка',190,'Демо: набор щипцы и лопатка',85,'шт.','pack','Один комплект одноразовых приборов для подачи']
];
const stock=specs.map(([key,category,name,price,productName,cost,unit,supplier])=>({id:`demo-extras-v1-stock-${key}`,name:productName,cost,unit,qty:0,min:unit==='кг'?1:10,supplierId:`demo-v1-supplier-${supplier}`,lastPurchaseDate:'',lastPurchasePrice:0}));
const packaged=specs.map(([key,category,name,price,productName,cost,unit,supplier,description])=>({id:`demo-extras-v1-${key}`,name,category,catalogSection:({1:'Одноразовая посуда',2:'Для сервировки',3:'Безалкогольные напитки'})[category],price,pieces:1,weight:key==='ice'?'1 кг':'',photo:`demo/images/extras-${key}.webp`,composition:[description],ingredients:[[productName,1,unit]],demo:true}));
const delivery=[['city','Доставка по городу',600,'Учебный тариф за один адрес в пределах города.'],['outer','Доставка за город',1200,'Учебный тариф за один адрес в ближайшем пригороде.']].map(([key,name,price,note])=>({id:`demo-extras-v1-delivery-${key}`,name,category:4,catalogSection:'Учебные тарифы доставки',price,pieces:0,weight:'',photo:`demo/images/extras-delivery-${key}.webp`,composition:[note],ingredients:[],demo:true}));
export const extrasDemo={version:1,items:[...premium,...packaged,...delivery],stock};