const { SectionHead, FilterBar, ProjectCard, ShowMoreButton, MicroCta } = window.CoolZoneSolutionDesignSystem_12e696; const CATS = ['klima', 'pompy', 'hydro', 'klima', 'pompy', 'pompy']; const CAT_KEYS = ['klima', 'pompy', 'hydro']; // Stock photos (Pexels, free license) standing in for real project photography // until real completed-job photos exist. Positions without an entry fall back // to the brand's navy grid placeholder. const IMAGES = [ 'assets/projects/ac-split-indoor.jpg', 'assets/projects/heat-pump-unit.jpg', 'assets/projects/underfloor-manifold.jpg', 'assets/projects/office-ac.jpg', 'assets/projects/solar-roof.jpg', 'assets/projects/thermostat.jpg', ]; // Dynamic project items live in one DB blob shared by every language, so // title/meta are stored as { it, de, pl } maps rather than plain strings — // otherwise editing a project in one language would show that same text to // visitors in every other language. Old single-string items (saved before // this existed) still work: they're shown as-is in every language until // someone edits them, at which point they become a proper per-language map. function pickLocale(field, lang) { if (field == null) return ''; if (typeof field === 'string') return field; return field[lang] || field.it || field.de || field.pl || Object.values(field)[0] || ''; } function setLocale(field, lang, value) { const base = (field && typeof field === 'object') ? field : (field ? { it: field } : {}); return { ...base, [lang]: value }; } function Projects({ t, images, sections }) { const { isAdmin, editMode, refresh, lang } = React.useContext(AdminEditContext); const [cat, setCat] = React.useState('all'); const [all, setAll] = React.useState(false); const [saving, setSaving] = React.useState(false); const dynamicItems = sections && sections.projects && sections.projects.items; const legacyItems = t.shots.map((s, i) => ({ title: s[0], meta: s[1], category: CATS[i], image: (images && images['gallery_' + (i + 1)]) || IMAGES[i], })); const items = (dynamicItems && dynamicItems.length) ? dynamicItems : legacyItems; const saveItems = (newItems) => { setSaving(true); fetch('/api/config-api.php/update-sections', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ projects: { visible: true, items: newItems } }), }).then(() => { if (refresh) refresh(); }).catch(() => {}).finally(() => setSaving(false)); }; const updateItem = (index, patch) => { const next = items.map((it, i) => (i === index ? { ...it, ...patch } : it)); saveItems(next); }; const addItem = () => { saveItems([...items, { title: { [lang]: t.adminAddProject.replace(/^\+\s*/, '') }, meta: {}, category: 'klima', image: null }]); setAll(true); }; const removeItem = (index) => { saveItems(items.filter((_, i) => i !== index)); }; const uploadImage = (index, file) => { if (!file) return; const formData = new FormData(); formData.append('image', file); fetch('/api/config-api.php/upload-project-image', { method: 'POST', body: formData }) .then((r) => (r.ok ? r.json() : null)) .then((data) => { if (data && data.path) updateItem(index, { image: data.path }); }) .catch(() => {}); }; const options = t.filters.map((label, i) => ({ value: ['all', ...CAT_KEYS][i], label })); const shown = items.map((it, i) => ({ it, i })).filter(({ it }) => cat === 'all' || it.category === cat); const visible = all ? shown : shown.slice(0, 3); const showAdminUi = isAdmin && editMode; return (
{t.projTag}} title={{t.projH2}} body={{t.projP}} /> { setCat(v); setAll(false); }} options={options} ariaLabel={t.projTag} />
{visible.map(({ it, i }) => (
updateItem(i, { title: setLocale(it.title, lang, v) })}>{pickLocale(it.title, lang)}} meta={ updateItem(i, { meta: setLocale(it.meta, lang, v) })}>{pickLocale(it.meta, lang)}} image={it.image} /> {showAdminUi && (
)}
))} {showAdminUi && ( )}
{!all && shown.length > 3 ? setAll(true)}>{t.showAll} : null}
); } Object.assign(window, { Projects });