{"id":12,"date":"2026-09-30T08:38:55","date_gmt":"2026-09-30T06:38:55","guid":{"rendered":"http:\/\/92.5.124.145\/?page_id=12"},"modified":"2026-09-30T11:37:08","modified_gmt":"2026-09-30T09:37:08","slug":"oenskeseddel","status":"publish","type":"page","link":"https:\/\/katsuidev.dk\/index.php\/oenskeseddel\/","title":{"rendered":"\ud83c\udf81 Min \u00d8nskeseddel"},"content":{"rendered":"\n<script>\n  let storesData = [];\n\n  async function fetchWishlist() {\n    const container = document.getElementById('stores-list');\n    try {\n      const res = await fetch('\/wp-json\/onskeseddel\/v1\/data');\n      storesData = await res.json() || [];\n      render();\n    } catch (e) {\n      container.innerHTML = '<p style=\"text-align: center; color: var(--accent-red);\">Kunne ikke indl\u00e6se \u00f8nskesedlen fra serveren.<\/p>';\n    }\n  }\n\n  function render() {\n    const container = document.getElementById('stores-list');\n    container.innerHTML = '';\n\n    if (!Array.isArray(storesData) || storesData.length === 0) {\n      container.innerHTML = '<p style=\"text-align: center; opacity: 0.6; margin-top: 40px;\">Din \u00f8nskeseddel er tom.<\/p>';\n      return;\n    }\n\n    storesData.forEach((store, sIdx) => {\n      const card = document.createElement('div');\n      card.className = 'store-card';\n\n      let subtotal = 0;\n      if (store.shopping_list) {\n        store.shopping_list.forEach(item => subtotal += (Number(item.price) || 0));\n      }\n\n      let shipCost = Number(store.flat_shipping) || Number(store.standard_shipping) || 0;\n      let shipStr = `Fragt: ${shipCost.toFixed(2)} ${store.currency || 'DKK'}`;\n\n      if (store.free_shipping_threshold) {\n        if (subtotal >= store.free_shipping_threshold) {\n          shipCost = 0;\n          shipStr = \"Fri fragt opn\u00e5et! \u2728\";\n        } else {\n          let diff = store.free_shipping_threshold - subtotal;\n          shipStr = `Fragt: ${shipCost.toFixed(2)} ${store.currency || 'DKK'} (Mangler ${diff.toFixed(2)} for fri fragt)`;\n        }\n      } else if (store.flat_shipping === 0) {\n        shipStr = \"Fri fragt!\";\n      }\n\n      let total = subtotal + shipCost;\n\n      let itemsHTML = (store.shopping_list || []).map((item) => `\n        <div class=\"item-row\">\n          <img decoding=\"async\" class=\"item-img\" src=\"${item.image_data || ''}\" onerror=\"this.src='data:image\/svg+xml;utf8,<svg xmlns=\\'http:\/\/www.w3.org\/2000\/svg\\' width=\\'60\\' height=\\'60\\'><rect width=\\'60\\' height=\\'60\\' fill=\\'%23313244\\'\/><\/svg>'\" onclick=\"showImage('${item.image_data || ''}', '${item.name}')\" \/>\n          <div class=\"item-info\">\n            <h4>${item.name}<\/h4>\n            <p>\u2022 ${item.details || ''}<\/p>\n            <p>Pris: ${(Number(item.price)||0).toFixed(2)} ${store.currency || 'DKK'}<\/p>\n          <\/div>\n          ${item.link ? `<a class=\"btn-blue\" href=\"${item.link}\" target=\"_blank\">\u00c5bn Link \ud83d\udd17<\/a>` : ''}\n        <\/div>\n      `).join('');\n\n      card.innerHTML = `\n        <button class=\"store-header\" onclick=\"toggleStore(${sIdx})\">\n          <span id=\"store-title-${sIdx}\">\u25b6 ${store.name} (${(store.shopping_list || []).length} \u00f8nsker)<\/span>\n        <\/button>\n        <!-- Fjerner 'open' herfra, s\u00e5 den starter lukket -->\n        <div class=\"store-content\" id=\"store-content-${sIdx}\">\n          <div class=\"store-actions\">\n            <a class=\"store-link\" href=\"${store.website}\" target=\"_blank\">Bes\u00f8g ${store.name} \ud83c\udf10<\/a>\n          <\/div>\n          ${itemsHTML}\n          <div class=\"summary-card\">\n            <div>\n              <b>Subtotal: ${subtotal.toFixed(2)} ${store.currency || 'DKK'}<\/b><br>\n              <span style=\"color: var(--accent-green);\"><b>Samlet Pris: ${total.toFixed(2)} ${store.currency || 'DKK'}<\/b><\/span>\n            <\/div>\n            <div><i>${shipStr}<\/i><\/div>\n          <\/div>\n        <\/div>\n      `;\n      container.appendChild(card);\n    });\n  }\n\n  function toggleStore(idx) {\n    const content = document.getElementById(`store-content-${idx}`);\n    const titleSpan = document.getElementById(`store-title-${idx}`);\n    const isOpen = content.classList.toggle('open');\n    \n    \/\/ Skifter pilen afh\u00e6ngigt af om den er \u00e5ben eller lukket\n    const storeName = storesData[idx].name;\n    const count = (storesData[idx].shopping_list || []).length;\n    titleSpan.innerText = `${isOpen ? '\u25bc' : '\u25b6'} ${storeName} (${count} \u00f8nsker)`;\n  }\n\n  function showImage(src, title) {\n    if (!src) return;\n    document.getElementById('img-title').innerText = title;\n    document.getElementById('preview-img').src = src;\n    document.getElementById('img-modal').classList.add('active');\n  }\n\n  function closeImgModal() {\n    document.getElementById('img-modal').classList.remove('active');\n  }\n\n  fetchWishlist();\n<\/script>\n\n\n\n<style>\n  \/* Catppuccin Mocha Color Palette 1:1 fra din index_2.html *\/\n  :root {\n    --bg-base: #1e1e2e;\n    --bg-mantle: #181825;\n    --bg-surface: #313244;\n    --bg-surface-hover: #45475a;\n    --text-main: #cdd6f4;\n    --accent-blue: #89b4fa;\n    --accent-blue-hover: #b4befe;\n    --accent-green: #a6e3a1;\n    --border-color: #45475a;\n  }\n\n  .wishlist-container {\n    background-color: var(--bg-base);\n    color: var(--text-main);\n    padding: 20px;\n    max-width: 900px;\n    margin: 0 auto;\n    border-radius: 12px;\n    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;\n  }\n\n  .wishlist-container header {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-bottom: 25px;\n  }\n\n  .wishlist-container h1 {\n    color: var(--accent-blue);\n    font-size: 1.6rem;\n  }\n\n  .wishlist-container button {\n    cursor: pointer;\n    border: none;\n    border-radius: 6px;\n    padding: 8px 14px;\n    font-weight: bold;\n    font-size: 0.85rem;\n    transition: background 0.2s;\n  }\n\n  .wishlist-container .btn-blue {\n    background-color: var(--accent-blue);\n    color: #11111b;\n  }\n  .wishlist-container .btn-blue:hover {\n    background-color: var(--accent-blue-hover);\n  }\n\n  .btn-cancel {\n    background-color: var(--bg-surface-hover);\n    color: var(--text-main);\n    border: none;\n    border-radius: 6px;\n    padding: 8px 14px;\n    font-weight: bold;\n    cursor: pointer;\n  }\n\n  \/* Store Cards *\/\n  .wishlist-container .store-card {\n    border: 1px solid var(--border-color);\n    border-radius: 8px;\n    margin-bottom: 15px;\n    overflow: hidden;\n    background-color: var(--bg-base);\n  }\n\n  .wishlist-container .store-header {\n    background-color: var(--bg-surface);\n    color: var(--accent-blue);\n    padding: 14px 18px;\n    font-weight: bold;\n    width: 100%;\n    text-align: left;\n    font-size: 1rem;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    border: none;\n  }\n  .wishlist-container .store-header:hover {\n    background-color: var(--bg-surface-hover);\n  }\n\n  .wishlist-container .store-content {\n    padding: 15px;\n    display: none;\n  }\n  .wishlist-container .store-content.open {\n    display: block;\n  }\n\n  .wishlist-container .store-actions {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-bottom: 12px;\n  }\n\n  .wishlist-container .store-link {\n    color: #89dceb;\n    text-decoration: underline;\n    font-size: 0.9rem;\n  }\n\n  \/* Item Rows *\/\n  .wishlist-container .item-row {\n    background-color: var(--bg-mantle);\n    border: 1px solid var(--border-color);\n    border-radius: 8px;\n    padding: 10px;\n    margin-bottom: 10px;\n    display: flex;\n    align-items: center;\n    gap: 12px;\n  }\n\n  .wishlist-container .item-img {\n    width: 60px;\n    height: 60px;\n    border-radius: 6px;\n    object-fit: cover;\n    background-color: var(--bg-surface);\n    cursor: pointer;\n    flex-shrink: 0;\n  }\n\n  .wishlist-container .item-info {\n    flex-grow: 1;\n  }\n\n  .wishlist-container .item-info h4 {\n    font-size: 0.95rem;\n    margin-bottom: 2px;\n    color: var(--text-main);\n  }\n\n  .wishlist-container .item-info p {\n    font-size: 0.85rem;\n    opacity: 0.8;\n    color: var(--text-main);\n  }\n\n  .wishlist-container .summary-card {\n    background-color: var(--bg-surface);\n    padding: 12px;\n    border-radius: 8px;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    font-size: 0.9rem;\n    margin-top: 10px;\n  }\n\n  \/* Billed-visning Modal - Sikret fuldsk\u00e6rm i WordPress *\/\n  .modal-overlay {\n    position: fixed !important;\n    top: 0 !important;\n    left: 0 !important;\n    width: 100vw !important;\n    height: 100vh !important;\n    background: rgba(0,0,0,0.8) !important;\n    display: none;\n    justify-content: center !important;\n    align-items: center !important;\n    z-index: 9999999 !important;\n  }\n  .modal-overlay.active {\n    display: flex !important;\n  }\n\n  .modal-card {\n    background-color: var(--bg-mantle);\n    border: 2px solid var(--accent-blue);\n    border-radius: 12px;\n    padding: 20px;\n    width: 90%;\n    max-width: 500px;\n    box-sizing: border-box;\n  }\n\n  .modal-card h3 {\n    color: var(--accent-blue);\n    margin-bottom: 15px;\n  }\n\n  #preview-img {\n    max-width: 100%;\n    max-height: 70vh;\n    object-fit: contain;\n    border-radius: 8px;\n  }\n<\/style>\n\n<div class=\"wishlist-container\">\n  <header>\n    <h1>Min \u00d8nskeseddel \ud83c\udf81<\/h1>\n  <\/header>\n\n  <div id=\"stores-list\">\n    <p style=\"text-align: center; opacity: 0.6; margin-top: 40px;\">Henter \u00f8nsker&#8230;<\/p>\n  <\/div>\n<\/div>\n\n<!-- Modal til at se billeder i stort format -->\n<div class=\"modal-overlay\" id=\"img-modal\" onclick=\"closeModal()\">\n  <div class=\"modal-card\" style=\"text-align: center;\" onclick=\"event.stopPropagation()\">\n    <h3 id=\"img-title\">Billede<\/h3>\n    <img decoding=\"async\" id=\"preview-img\" src=\"\" alt=\"Preview\" \/>\n    <div style=\"margin-top: 15px;\">\n      <button class=\"btn-cancel\" onclick=\"closeModal()\">Luk<\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script>\n  let storesData = [];\n\n  \/\/ Henter data fra WordPress Rest API i stedet for Oenskeseddel.json\n  async function loadWishlist() {\n    try {\n      const response = await fetch('\/wp-json\/onskeseddel\/v1\/data');\n      if (response.ok) {\n        storesData = await response.json() || [];\n        render();\n      } else {\n        document.getElementById('stores-list').innerHTML = \n          '<p style=\"text-align: center; color: var(--accent-red); margin-top: 40px;\">Kunne ikke hente \u00f8nskesedlen fra serveren.<\/p>';\n      }\n    } catch (err) {\n      console.error('Fejl ved indl\u00e6sning af API:', err);\n      document.getElementById('stores-list').innerHTML = \n        '<p style=\"text-align: center; opacity: 0.6; margin-top: 40px;\">Der opstod en fejl ved indl\u00e6sning af \u00f8nskesedlen.<\/p>';\n    }\n  }\n\n  function render() {\n    const container = document.getElementById('stores-list');\n    container.innerHTML = '';\n\n    if (!storesData || storesData.length === 0) {\n      container.innerHTML = '<p style=\"text-align: center; opacity: 0.6; margin-top: 40px;\">\u00d8nskesedlen er tom.<\/p>';\n      return;\n    }\n\n    storesData.forEach((store, sIdx) => {\n      const card = document.createElement('div');\n      card.className = 'store-card';\n\n      let subtotal = 0;\n      (store.shopping_list || []).forEach(item => subtotal += (Number(item.price) || 0));\n\n      let shipCost = Number(store.flat_shipping) || Number(store.standard_shipping) || 0;\n      let shipStr = `Fragt: ${shipCost.toFixed(2)} ${store.currency || 'DKK'}`;\n\n      if (store.free_shipping_threshold) {\n        if (subtotal >= store.free_shipping_threshold) {\n          shipCost = 0;\n          shipStr = \"Fri fragt opn\u00e5et! \u2728\";\n        } else {\n          let diff = store.free_shipping_threshold - subtotal;\n          shipStr = `Fragt: ${shipCost.toFixed(2)} ${store.currency || 'DKK'} (Mangler ${diff.toFixed(2)} for fri fragt)`;\n        }\n      } else if (store.flat_shipping === 0) {\n        shipStr = \"Fri fragt!\";\n      }\n\n      let total = subtotal + shipCost;\n\n      let itemsHTML = (store.shopping_list || []).map((item) => `\n        <div class=\"item-row\">\n          <img decoding=\"async\" class=\"item-img\" src=\"${item.image_data || ''}\" onerror=\"this.src='data:image\/svg+xml;utf8,<svg xmlns=\\'http:\/\/www.w3.org\/2000\/svg\\' width=\\'60\\' height=\\'60\\'><rect width=\\'60\\' height=\\'60\\' fill=\\'%23313244\\'\/><\/svg>'\" onclick=\"showImage('${item.image_data || ''}', '${item.name}')\" \/>\n          <div class=\"item-info\">\n            <h4>${item.name}<\/h4>\n            <p>\u2022 ${item.details || ''}<\/p>\n            <p>Pris: ${(Number(item.price)||0).toFixed(2)} ${store.currency || 'DKK'}<\/p>\n          <\/div>\n          <button class=\"btn-blue\" onclick=\"window.open('${item.link}', '_blank')\">\u00c5bn Link<\/button>\n        <\/div>\n      `).join('');\n\n      card.innerHTML = `\n        <button class=\"store-header\" onclick=\"toggleStore(${sIdx})\">\n          <span>\u25b6 ${store.name} (${(store.shopping_list || []).length} \u00f8nsker)<\/span>\n        <\/button>\n        <div class=\"store-content\" id=\"store-content-${sIdx}\">\n          <div class=\"store-actions\">\n            <a class=\"store-link\" href=\"${store.website}\" target=\"_blank\">Bes\u00f8g ${store.name} \ud83c\udf10<\/a>\n          <\/div>\n          ${itemsHTML}\n          <div class=\"summary-card\">\n            <div>\n              <b>Subtotal: ${subtotal.toFixed(2)} ${store.currency || 'DKK'}<\/b><br>\n              <span style=\"color: var(--accent-green);\"><b>Samlet Pris: ${total.toFixed(2)} ${store.currency || 'DKK'}<\/b><\/span>\n            <\/div>\n            <div><i>${shipStr}<\/i><\/div>\n          <\/div>\n        <\/div>\n      `;\n      container.appendChild(card);\n    });\n  }\n\n  function toggleStore(idx) {\n    const content = document.getElementById(`store-content-${idx}`);\n    content.classList.toggle('open');\n  }\n\n  function showImage(src, title) {\n    if (!src) return;\n    const modal = document.getElementById('img-modal');\n    \/\/ Tvinger modal ud til <body> i det \u00f8jeblik billedet \u00e5bnes for fuld m\u00f8rkel\u00e6gning\n    if (modal && modal.parentNode !== document.body) {\n      document.body.appendChild(modal);\n    }\n    document.getElementById('img-title').innerText = title;\n    document.getElementById('preview-img').src = src;\n    modal.classList.add('active');\n  }\n\n  function closeModal() {\n    document.getElementById('img-modal').classList.remove('active');\n  }\n\n  \/\/ Start indl\u00e6sning\n  loadWishlist();\n<\/script>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Min \u00d8nskeseddel \ud83c\udf81 Henter \u00f8nsker&#8230; Billede Luk<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-12","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/katsuidev.dk\/index.php\/wp-json\/wp\/v2\/pages\/12","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/katsuidev.dk\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/katsuidev.dk\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/katsuidev.dk\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/katsuidev.dk\/index.php\/wp-json\/wp\/v2\/comments?post=12"}],"version-history":[{"count":17,"href":"https:\/\/katsuidev.dk\/index.php\/wp-json\/wp\/v2\/pages\/12\/revisions"}],"predecessor-version":[{"id":77,"href":"https:\/\/katsuidev.dk\/index.php\/wp-json\/wp\/v2\/pages\/12\/revisions\/77"}],"wp:attachment":[{"href":"https:\/\/katsuidev.dk\/index.php\/wp-json\/wp\/v2\/media?parent=12"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}