(() => { "use strict"; const fixture = new URLSearchParams(window.location.search).get("fixture") || ""; const formatWon = (value) => `${new Intl.NumberFormat("ko-KR").format(value)}원`; const markBrokenImage = (image) => { const shell = image.closest(".image-shell"); if (shell) shell.classList.add("is-broken"); }; document.querySelectorAll(".image-shell img").forEach((image) => { image.addEventListener("error", () => markBrokenImage(image)); if (image.complete && image.naturalWidth === 0) markBrokenImage(image); }); const menuButtons = [...document.querySelectorAll("[data-menu-filter]")]; const menuItems = [...document.querySelectorAll("[data-menu-category]")]; const menuEmpty = document.querySelector("#menu-empty"); const setMenuFilter = (filter) => { const forceMenuEmpty = new URLSearchParams(window.location.search).get("fixture") === "menu-empty"; let visibleCount = 0; menuButtons.forEach((button) => { const active = button.dataset.menuFilter === filter; button.classList.toggle("is-active", active); button.setAttribute("aria-pressed", String(active)); }); menuItems.forEach((item) => { const visible = !forceMenuEmpty && (filter === "all" || item.dataset.menuCategory === filter); item.hidden = !visible; if (visible) visibleCount += 1; }); if (menuEmpty) menuEmpty.hidden = visibleCount > 0; }; menuButtons.forEach((button) => { button.addEventListener("click", () => setMenuFilter(button.dataset.menuFilter || "all")); }); document.querySelector("[data-show-all-menu]")?.addEventListener("click", () => { if (fixture === "menu-empty") { const nextUrl = new URL(window.location.href); nextUrl.searchParams.delete("fixture"); window.history.replaceState({}, "", nextUrl); } setMenuFilter("all"); }); if (fixture === "menu-empty") setMenuFilter("all"); const builder = document.querySelector("#burger-builder"); const builderSection = document.querySelector("#builder"); const setOptions = document.querySelector("#set-options"); const summaryHeading = document.querySelector("#summary-heading"); const summaryLines = document.querySelector("#summary-lines"); const summaryServing = document.querySelector("#summary-serving"); const summaryStore = document.querySelector("#summary-store"); const summaryStoreState = document.querySelector("#summary-store-state"); const summaryAllergens = document.querySelector("#summary-allergens"); const summaryTotal = document.querySelector("#summary-total"); const stores = { seongsu: { label: "성수점", state: "영업 중" }, yeonnam: { label: "연남점", state: "오늘 영업 종료" }, mullae: { label: "문래점", state: "오늘 휴무" }, }; const fieldValue = (name) => { const field = builder?.elements.namedItem(name); if (!field) return ""; if (field instanceof RadioNodeList) return field.value; return field.value; }; const setRadio = (name, value) => { const radio = builder?.querySelector(`input[name="${name}"][value="${value}"]`); if (radio instanceof HTMLInputElement) radio.checked = true; }; const builderPrice = ({ flavor, patty, cheese, serving }) => { const flavorBase = flavor === "spicy" ? 7400 : 6900; const pattyAdd = Number(patty) === 2 ? 2000 : 0; const cheeseAdd = Number(cheese) === 0 ? -400 : Number(cheese) === 2 ? 400 : 0; const setAdd = serving === "set" ? 4100 : 0; return flavorBase + pattyAdd + cheeseAdd + setAdd; }; const updateBuilder = () => { if (!builder) return; const flavor = fieldValue("flavor"); const patty = fieldValue("patty"); const cheese = fieldValue("cheese"); const onion = fieldValue("onion"); const pickle = fieldValue("pickle"); const sauce = fieldValue("sauce"); const serving = fieldValue("serving"); const storeKey = fieldValue("store"); const store = stores[storeKey] || stores.seongsu; const soldOut = fixture === "sold-out"; const setEnabled = serving === "set"; builder.querySelectorAll("select[name='side'], select[name='drink']").forEach((select) => { select.disabled = !setEnabled; }); setOptions?.classList.toggle("is-disabled", !setEnabled); const names = { onion: { none: "양파 없음", regular: "양파 기본", extra: "양파 많이" }, pickle: { none: "피클 없음", regular: "피클 기본", extra: "피클 많이" }, sauce: { none: "소스 없음", regular: "소스 기본", side: "소스 따로" }, }; const pattyLabel = Number(patty) === 2 ? "더블" : "싱글"; const flavorLabel = flavor === "spicy" ? "고추 피클" : "철판"; const cheeseLabel = Number(cheese) === 0 ? "치즈 없음" : `치즈 ${cheese === "2" ? "두" : "한"} 장`; const productName = `${flavorLabel} ${pattyLabel}`; const servingLabel = serving === "set" ? "세트 · 얇은 감자와 음료" : "단품"; if (summaryHeading) summaryHeading.textContent = productName; if (summaryLines) { summaryLines.textContent = `패티 ${patty === "2" ? "두" : "한"} 장 / ${cheeseLabel} / ${names.onion[onion]} / ${names.pickle[pickle]} / ${names.sauce[sauce]}`; } if (summaryServing) summaryServing.textContent = servingLabel; if (summaryStore) summaryStore.textContent = store.label; if (summaryStoreState) summaryStoreState.textContent = soldOut ? "오늘 품절 예시" : store.state; const allergens = ["알", "대두", "밀", "쇠고기"]; if (Number(cheese) > 0) allergens.splice(1, 0, "우유"); if (flavor === "spicy") allergens.push("토마토"); if (summaryAllergens) summaryAllergens.textContent = allergens.join(", "); if (summaryTotal) summaryTotal.textContent = formatWon(builderPrice({ flavor, patty, cheese, serving })); }; builder?.addEventListener("change", updateBuilder); const applyPreset = (preset) => { if (!builder) return; if (preset === "single") { setRadio("flavor", "classic"); setRadio("patty", "1"); } else if (preset === "spicy") { setRadio("flavor", "spicy"); setRadio("patty", "2"); } else { setRadio("flavor", "classic"); setRadio("patty", "2"); } updateBuilder(); builderSection?.scrollIntoView({ behavior: "smooth", block: "start" }); window.setTimeout(() => builder.querySelector("input:checked")?.focus({ preventScroll: true }), 350); }; document.querySelectorAll("[data-preset]").forEach((button) => { button.addEventListener("click", () => applyPreset(button.dataset.preset || "double")); }); const storeCards = [...document.querySelectorAll("[data-store]")]; const mapPins = [...document.querySelectorAll("[data-map-store]")]; const storeSearch = document.querySelector("#store-search"); const clearStoreSearch = document.querySelector("#clear-store-search"); const storeEmpty = document.querySelector("#store-empty"); const regionButtons = [...document.querySelectorAll("[data-region]")]; let activeRegion = "all"; const selectStore = (storeKey, shouldMove = false) => { const select = builder?.elements.namedItem("store"); if (select instanceof HTMLSelectElement) select.value = storeKey; storeCards.forEach((card) => card.classList.toggle("is-selected", card.dataset.store === storeKey)); mapPins.forEach((pin) => pin.classList.toggle("is-active", pin.dataset.mapStore === storeKey)); updateBuilder(); if (shouldMove) builderSection?.scrollIntoView({ behavior: "smooth", block: "start" }); }; document.querySelectorAll("[data-select-store]").forEach((button) => { button.addEventListener("click", () => selectStore(button.dataset.selectStore, true)); }); mapPins.forEach((button) => { button.addEventListener("click", () => selectStore(button.dataset.mapStore, false)); }); const filterStores = () => { const query = storeSearch instanceof HTMLInputElement ? storeSearch.value.trim().toLocaleLowerCase("ko-KR") : ""; let visibleCount = 0; storeCards.forEach((card) => { const regionMatch = activeRegion === "all" || card.dataset.region === activeRegion; const queryMatch = !query || (card.dataset.search || "").toLocaleLowerCase("ko-KR").includes(query); const visible = fixture !== "store-none" && regionMatch && queryMatch; card.hidden = !visible; if (visible) visibleCount += 1; const pin = mapPins.find((item) => item.dataset.mapStore === card.dataset.store); if (pin) pin.hidden = !visible; }); if (storeEmpty) storeEmpty.hidden = visibleCount > 0; if (clearStoreSearch) clearStoreSearch.hidden = !query; }; storeSearch?.addEventListener("input", filterStores); clearStoreSearch?.addEventListener("click", () => { if (storeSearch instanceof HTMLInputElement) { storeSearch.value = ""; storeSearch.focus(); } filterStores(); }); regionButtons.forEach((button) => { button.addEventListener("click", () => { activeRegion = button.dataset.region || "all"; regionButtons.forEach((item) => { const active = item === button; item.classList.toggle("is-active", active); item.setAttribute("aria-pressed", String(active)); }); filterStores(); }); }); document.querySelector("#reset-store-search")?.addEventListener("click", () => { activeRegion = "all"; if (storeSearch instanceof HTMLInputElement) storeSearch.value = ""; regionButtons.forEach((button) => { const active = button.dataset.region === "all"; button.classList.toggle("is-active", active); button.setAttribute("aria-pressed", String(active)); }); filterStores(); storeSearch?.focus(); }); updateBuilder(); filterStores(); })();