const catalog = window.EUROWET_CATALOG || { categories: {}, products: [] };
const translations = {
ro: {
brandSub: "Materiale de produs pentru parteneri",
navCatalog: "Catalog",
navCategories: "Categorii",
navSource: "Sursă",
navInquiry: "Cerere",
heroEyebrow: "Catalog partener",
heroTitle: "Fotografii, descrieri și categorii de produs într-un singur spațiu",
heroText:
"Catalog bilingv distinct, construit din materiale Eurowet autorizate, cu filtrare rapidă, detalii de produs și selecție pentru cereri.",
browseProducts: "Vezi produsele",
prepareInquiry: "Pregătește cererea",
metricProducts: "produse",
metricImages: "fotografii",
metricCategories: "categorii",
sourceNotice:
"Materialele sunt organizate din fișiere de produs autorizate de partener. Designul, structura catalogului și interacțiunile sunt personalizate și intenționat diferite de eurowet.pl.",
categoryEyebrow: "Împărțire produse",
categoryTitle: "Categorii pregătite din setul de materiale",
filterEyebrow: "Filtre",
filterTitle: "Caută produs",
searchPlaceholder: "Caută după nume, categorie sau descriere",
categoryFilter: "Categorie",
animalFilter: "Animal",
materialFilter: "Material",
onlyEnglish: "Descriere engleză extrasă",
resetFilters: "Resetează filtre",
catalogEyebrow: "Catalog",
sortLabel: "Sortare",
sortName: "Nume A-Z",
sortCategory: "Categorie",
sortSource: "Cu sursă mai întâi",
detailsEyebrow: "Detalii produs",
inquiryEyebrow: "Cerere",
inquiryTitle: "Produse selectate",
emptyInquiry: "Adaugă produse pentru a pregăti o cerere de ofertă.",
copyInquiry: "Copiază lista",
all: "Toate",
multi: "Mai multe",
dog: "Câini",
cat: "Pisici",
small: "Animale mici",
livestock: "Fermă",
productsFound: "{count} produse",
oneProductFound: "1 produs",
noResults: "Nu există produse pentru filtrele selectate.",
details: "Detalii",
add: "Adaugă",
added: "Adăugat la cerere",
removed: "Eliminat din cerere",
sourceDescription: "Descriere sursă",
englishDescription: "Descriere engleză",
shortDescription: "Descriere scurtă",
sourceFiles: "Fișiere sursă",
openFile: "Deschide fișier",
noExtractedText: "Textul extras nu este disponibil; folosește fișierul sursă.",
copied: "Lista de produse a fost copiată",
copyFallback: "Selectează și copiază lista din panoul cererii.",
},
en: {
brandSub: "Partner product materials",
navCatalog: "Catalog",
navCategories: "Categories",
navSource: "Source",
navInquiry: "Inquiry",
heroEyebrow: "Partner catalogue",
heroTitle: "Product photos, descriptions and categories in one workspace",
heroText:
"A distinct bilingual catalogue built from authorised Eurowet materials, with fast filtering, product detail panels and inquiry selection.",
browseProducts: "Browse products",
prepareInquiry: "Prepare inquiry",
metricProducts: "products",
metricImages: "photos",
metricCategories: "categories",
sourceNotice:
"Materials are organised from authorised partner product files. The design, catalogue structure and interaction model are custom and intentionally different from eurowet.pl.",
categoryEyebrow: "Product division",
categoryTitle: "Categories prepared from the material set",
filterEyebrow: "Filters",
filterTitle: "Find product",
searchPlaceholder: "Search by name, category or description",
categoryFilter: "Category",
animalFilter: "Animal",
materialFilter: "Material",
onlyEnglish: "English description extracted",
resetFilters: "Reset filters",
catalogEyebrow: "Catalogue",
sortLabel: "Sort",
sortName: "Name A-Z",
sortCategory: "Category",
sortSource: "With source first",
detailsEyebrow: "Product details",
inquiryEyebrow: "Inquiry",
inquiryTitle: "Selected products",
emptyInquiry: "Add products to prepare a partner offer request.",
copyInquiry: "Copy product list",
all: "All",
multi: "Multiple",
dog: "Dogs",
cat: "Cats",
small: "Small animals",
livestock: "Livestock",
productsFound: "{count} products",
oneProductFound: "1 product",
noResults: "No products match the selected filters.",
details: "Details",
add: "Add",
added: "Added to inquiry",
removed: "Removed from inquiry",
sourceDescription: "Source description",
englishDescription: "English description",
shortDescription: "Short description",
sourceFiles: "Source files",
openFile: "Open file",
noExtractedText: "Extracted text is not available; use the source file.",
copied: "Product list copied",
copyFallback: "Select and copy the list from the inquiry panel.",
},
};
const state = {
lang: localStorage.getItem("vetbridgeLang") || "ro",
query: "",
category: "all",
animal: "all",
onlyEnglish: false,
sort: "name",
inquiry: [],
};
const categoryIcons = {
dermo: "sparkles",
"eye-ear": "eye",
oral: "smile-plus",
digestive: "activity",
supplements: "pill",
repellents: "shield",
hygiene: "package-check",
};
const els = {
productGrid: document.querySelector("#productGrid"),
categoryCards: document.querySelector("#categoryCards"),
categoryFilters: document.querySelector("#categoryFilters"),
animalFilters: document.querySelector("#animalFilters"),
searchInput: document.querySelector("#searchInput"),
onlyEnglish: document.querySelector("#onlyEnglish"),
sortSelect: document.querySelector("#sortSelect"),
resultCount: document.querySelector("#resultCount"),
previewStack: document.querySelector("#previewStack"),
detailsDrawer: document.querySelector(".details-drawer"),
drawerTitle: document.querySelector("#drawerTitle"),
drawerContent: document.querySelector("#drawerContent"),
inquiryPanel: document.querySelector(".inquiry-panel"),
inquiryItems: document.querySelector("#inquiryItems"),
emptyInquiry: document.querySelector("#emptyInquiry"),
inquiryCount: document.querySelector(".inquiry-count"),
overlay: document.querySelector(".overlay"),
toast: document.querySelector(".toast"),
};
function t(key) {
return translations[state.lang][key] || translations.en[key] || key;
}
function interpolate(template, values) {
return Object.entries(values).reduce(
(text, [key, value]) => text.replaceAll(`{${key}}`, value),
template,
);
}
function categoryLabel(key) {
return catalog.categories[key]?.[state.lang] || catalog.categories[key]?.en || key;
}
function animalLabel(key) {
return t(key);
}
function refreshIcons() {
if (window.lucide) window.lucide.createIcons();
}
function applyTranslations() {
document.documentElement.lang = state.lang;
document.querySelectorAll("[data-i18n]").forEach((node) => {
node.textContent = t(node.dataset.i18n);
});
document.querySelectorAll("[data-i18n-placeholder]").forEach((node) => {
node.setAttribute("placeholder", t(node.dataset.i18nPlaceholder));
});
document.querySelectorAll("[data-i18n-aria-label]").forEach((node) => {
node.setAttribute("aria-label", t(node.dataset.i18nAriaLabel));
});
document.querySelectorAll(".lang-btn").forEach((button) => {
button.classList.toggle("active", button.dataset.lang === state.lang);
button.setAttribute("aria-pressed", String(button.dataset.lang === state.lang));
});
}
function getVisibleProducts() {
const query = state.query.trim().toLowerCase();
return catalog.products
.filter((product) => {
const categoryMatch = state.category === "all" || product.category === state.category;
const animalMatch = state.animal === "all" || product.animals.includes(state.animal);
const englishMatch = !state.onlyEnglish || Boolean(product.details.en);
const queryMatch =
!query ||
[
product.name,
categoryLabel(product.category),
product.description[state.lang],
product.description.en,
product.description.ro,
product.details.en,
product.details.source,
]
.join(" ")
.toLowerCase()
.includes(query);
return categoryMatch && animalMatch && englishMatch && queryMatch;
})
.sort((a, b) => {
if (state.sort === "category") {
return categoryLabel(a.category).localeCompare(categoryLabel(b.category), state.lang);
}
if (state.sort === "source") {
return Number(Boolean(b.details.en)) - Number(Boolean(a.details.en)) || a.name.localeCompare(b.name);
}
return a.name.localeCompare(b.name, state.lang);
});
}
function renderPreview() {
const featured = catalog.products
.filter((product) => product.image)
.slice(0, 4)
.map((product) => ``)
.join("");
els.previewStack.innerHTML = featured;
}
function renderCategoryCards() {
const counts = catalog.products.reduce((acc, product) => {
acc[product.category] = (acc[product.category] || 0) + 1;
return acc;
}, {});
els.categoryCards.innerHTML = Object.keys(catalog.categories)
.map(
(key) => `
${product.description[state.lang]}
${product.description[state.lang]}