Pixel 2 XL
Pixel 2 XL Reparation

Skærmskift

Skærm (Original)

Kontakt for pris

Batteriskift

Batteri (Original)

Kontakt for pris

Diagnose & fejlsøgning

Diagnose ?

0 kr

Valgte reparationer

Ingen reparationer valgt endnu
Vælg et tidspunkt
<!-- 1) Flatpickr CSS (CDN) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css" />
 
<style>
  /* Keep your existing styles plus slight additions for timeslots */
 
  .separator {
    border: none !important;
    height: 2px !important;
    background-color: var(--primary-color) !important;
    width: 100% !important;
    margin: 20px auto !important;
  }
 
  /* Loader placeholder */
  #content::before {
    min-height: 300px;
    content: "Indlæser...";
    display: block;
    text-align: center;
    color: #aaa;
    font-style: italic;
    padding-top: 2rem;
  }
 
  .content-loaded::before {
    content: none !important;
  }
 
  /* Search Bar Container */
  .search-bar-container {
    position: relative;
    display: flex;
    align-items: center;
    max-width: 100%;
    margin: 10px 0;
  }
 
  /* Search Icon */
  #search-icon {
    position: absolute;
    right: 15px;
    font-size: 16px;
    color: #666;
    pointer-events: none;
    background: url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2024%2024%22%20fill=%22none%22%20stroke=%22%2333658A%22%20stroke-width=%223%22%20stroke-linecap=%22round%22%20stroke-linejoin=%22round%22%20class=%22icon%20icon-search%22%3E%3Ccircle%20cx=%2210%22%20cy=%2210%22%20r=%227%22%3E%3C/circle%3E%3Cline%20x1=%2216%22%20y1=%2216%22%20x2=%2221%22%20y2=%2221%22%3E%3C/line%3E%3C/svg%3E') no-repeat center;
    background-size: 16px 16px;
    height: 100%;
    width: 20px;
  }
 
  /* Search Input */
  #device-search-bar {
    width: 100%;
    padding: 10px 40px 10px 15px;
    border: 1px solid var(--primary-color);
    border-radius: 8px;
    font-size: 16px;
    outline: none;
    transition: border-color 0.3s ease, box-shadow 0.3s ease;
    font-family: var(--font-family);
    color: var(--secondary-color);
  }
 
  #device-search-bar:focus {
    border-color: #007bff;
    box-shadow: 0 0 5px rgba(47, 102, 152, 0.5);
  }
 
  #header h1 {
    font-size: 26px;
    color: var(--primary-color);
    margin-bottom: 10px;
  }
 
  h3 {
    font-size: 16px;
    color: var(--primary-color);
  }
 
  /* General Widget Styles */
  #repair-widget {
    /* CSS Variables for common values */
    --primary-color: #33658A;
    --secondary-color: #12375A;
    --accent-color: #FADF63;
    --hover-color: #2F6699;
    --border-color: #ddd;
    --background-light: #ffffff;
    --background-muted: #f9f9f9;
    --font-family: 'Poppins', sans-serif;
 
    font-family: var(--font-family);
    max-width: 1200px;
    padding: 20px;
    margin: 0 auto; /* This centers the container */
    border-radius: 12px 12px 12px 12px;
    box-shadow: 0px 8px 20px rgba(0, 0, 0, 0.1);
    background-color: var(--background-light);
    margin-top: 20px;
  }
 
  /* Headings */
  #repair-widget h1, #repair-widget h2, #repair-widget h3 {
    font-family: var(--font-family);
    color: var(--secondary-color);
  }
 
  #repair-header {
    display: flex;
    align-items: center;
    gap: 15px;
    margin-bottom: 20px;
  }
 
  .device-header {
    display: flex;
    align-items: flex-end;
    gap: 10px;
    margin-bottom: 20px;
  }
 
  .device-thumbnail {
    width: 100px;
    height: 100px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid #ddd;
  }
 
  .device-info {
    font-size: 26px;
    font-weight: bold;
    color: var(--secondary-color);
    overflow-wrap: break-word;
  }
 
  .device-info p {
    margin: 0;
    font-size: 14px;
    color: #666;
  }
 
  /* Breadcrumb Styles */
  #breadcrumb {
    font-size: 12px;
    color: var(--primary-color);
  }
 
  .breadcrumb-step {
    cursor: pointer;
    color: var(--primary-color);
    text-decoration: none;
  }
 
  .breadcrumb-step:hover {
    text-decoration: underline;
  }
 
  /* Dropdown Styles */
  #dropdown-results {
    position: absolute;
    width: 100%;
    max-height: 300px;
    overflow-y: auto;
    background-color: var(--background-light);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    z-index: 10;
  }
 
  .dropdown-item {
    display: flex;
    align-items: center;
    padding: 10px;
    cursor: pointer;
    transition: background 0.2s ease;
  }
 
  .dropdown-item:hover {
    background-color: #f1f1f1;
  }
 
  .dropdown-image {
    width: 40px;
    height: 40px;
    object-fit: cover;
    border-radius: 50%;
    margin-right: 10px;
  }
 
  .dropdown-text {
    font-size: 14px;
    color: #333;
  }
 
  /* Content Grid */
  #content {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 20px;
  }
 
  /* Card Styles */
  .card {
    border: 1px solid var(--border-color);
    border-radius: 10px;
    overflow: hidden;
    cursor: pointer;
    text-align: center;
    transition: all 0.3s ease;
    height: 300px;
    max-height: 300px;
    pointer-events: auto;
    display: flex;
    flex-direction: column;    /* stack image above title */
    justify-content: center;   /* center vertically */
    align-items: center;       /* center horizontally */
  }
 
  .card:hover {
    transform: scale(1.05);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
  }
 
  .card-image {
    width: 100%;
    height: 200px;
    max-height: 200px;
    object-fit: contain;
    border-radius: 10px;
    padding: 10px;
  }
 
  .card-title {
    padding: 0px 6px 0px 6px;
    font-size: 16px;
    color: var(--primary-color);
    text-align: center;
    display: block;
  }
 
  /* Responsive Design */
  @media (max-width: 768px) {
      
    .device-info {
    font-size: 20px;
    }
  
#repair-widget {
    padding: 15px;
    margin-top: 0px;
    border-radius: 0px 0px 0px 0px;
}
 
    .card {
      width: 100%;
      height: auto;
    }
 
    .card-image {
      height: 150px;
      padding: 5px;
    }
 
    .card-title {
      font-size: 14px;
    }
  }
 
  @media (max-width: 480px) {
    .card {
      border: 1px solid var(--border-color);
      border-radius: 4px;
      overflow: hidden;
      cursor: pointer;
      text-align: center;
      transition: all 0.3s ease;
      height: 170px;
      max-height: 170px;
      pointer-events: auto;
      display: flex;
      flex-direction: column;    /* stack image above title */
      justify-content: center;   /* center vertically */
      align-items: center;       /* center horizontally */
    }
 
    .card:hover {
      transform: scale(1.05);
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
    }
 
    .card-image {
      width: 100%;
      height: 100px;
      max-height: 100px;
      object-fit: contain;
      border-radius: 4px;
      padding: 4px;
    }
 
    .card-title {
      padding: 10px 0;
      font-size: 12px;
      color: var(--primary-color);
      text-align: center;
      display: block;
    }
 
    #content {
      grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
      justify-content: center;
      gap: 10px;
    }
  }
 
  /* Problem List & Cards */
  .problem-list {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 2px;
    width: 100%;
  }
 
  @media (max-width: 768px) {
    .problem-list {
      grid-auto-flow: unset;
      grid-template-columns: 1fr;
    }
  }
 
  .problem-card {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding: 10px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background-color: var(--background-light);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
    transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
    width: calc(100%);
    cursor: pointer;
    position: relative;
    z-index: 10;
  }
 
  .problem-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
    z-index: 20;
  }
 
  .problem-card.selected {
    background-color: #e6f7ff;
    border-left: 4px solid var(--primary-color);
  }
 
  .problem-info {
    flex: 1;
    margin-right: 16px;
  }
 
  .problem-name {
    font-size: 16px;
    font-weight: bold;
    color: var(--secondary-color);
    margin: 0;
    display: flex;
    align-items: center;
    gap: 6px;
  }
 
  .problem-action {
    position: absolute;
    top: 12px;
    right: 12px;
  }
 
  .problem-price {
    font-size: 14px;
    font-weight: bold;
    color: var(--primary-color);
    white-space: nowrap;
  }
 
  /* Tooltip */
  .info-icon::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 10px);
    left: 50%;
    transform: translateX(-50%);
    max-width: 80vw;
    background-color: #333;
    color: #fff;
    font-size: 12px;
    padding: 5px 8px;
    border-radius: 4px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    visibility: hidden;
    opacity: 0;
    transition: opacity 0.2s ease, visibility 0.2s ease;
    z-index: 9999;
    text-align: center;
    word-wrap: break-word;
  }
 
  .info-icon.show-tooltip::after,
  .info-icon:hover::after {
    visibility: visible;
    opacity: 1;
  }
 
  @media (max-width: 768px) {
    .info-icon::after {
      bottom: auto;
      left: 50%;
      transform: translateX(-50%) translateY(20px);
      min-width: 250px;
      max-width: 80vw;
      font-size: 12px;
      padding: 8px 10px;
      z-index: 9999;
    }
  }
 
  /* Booking Form Container */
  .booking-form-container {
    padding: 4px;
    border: 0px solid var(--border-color);
    border-radius: 8px;
    background-color: var(--background-light);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.0);
  }
 
  #booking-form {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }
 
  #booking-form textarea,
  #booking-form input {
    font-family: var(--font-family);
    width: 100%;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 16px;
    box-sizing: border-box;
    color: var(--secondary-color);
  }
 
  #booking-form textarea {
    resize: none;
    height: 100px;
  }
 
  #booking-form button {
    padding: 12px;
    font-size: 16px;
    font-weight: bold;
    font-family: var(--font-family);
    color: var(--accent-color);
    background-color: var(--secondary-color);
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s ease;
  }
 
  #booking-form button:hover {
    background-color: var(--hover-color);
    color: var(--accent-color);
  }
 
  @media (max-width: 768px) {
    .booking-form-container {
      padding: 15px;
    }
 
    #booking-form button {
      font-size: 14px;
    }
  }
 
  #problem-summary {
    padding: 15px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background-color: var(--background-muted);
    font-size: 14px;
    color: var(--secondary-color);
    white-space: pre-wrap;
    overflow-y: auto;
    max-height: 200px;
    margin-bottom: 20px;
  }
 
  /* Timeslot UI */
  .timeslot-container {
    margin-top: 10px;
    display: none; /* shown once a date is selected */
  }
  .timeslot-heading {
    font-size: 14px;
    color: var(--primary-color);
    margin-bottom: 10px;
  }
  .timeslot-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
    gap: 10px;
    margin-bottom: 10px;
  }
  #repair-widget #booking-form .timeslot-btn {
    padding: 8px;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    background-color: var(--background-light);
    cursor: pointer;
    text-align: center;
    transition: background-color 0.2s ease, box-shadow 0.2s ease;
    font-size: 14px;
    color: var(--secondary-color);
  }
  .timeslot-btn:hover {
    background-color: var(--background-muted);
  }
  #repair-widget #booking-form .timeslot-btn.selected {
    background-color: #e6f7ff;
    border-color: var(--primary-color);
  }
  .timeslot-btn.booked {
    display: none !important;
  }
  
  .walk-in-info-box {
  background-color: #fff8dc; /* light, warm background */
  border: 1px solid #f0e68c; /* subtle border color */
  padding: 10px;
  margin: 10px auto; /* space above and below */
  font-size: 16px;
  color: #333;
  text-align: left;
  border-radius: 8px;
}
/* Improved Back Button Styling */
#back-button {
    background-color: transparent;
    border: none;
    outline: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    transition: transform 0.2s, opacity 0.2s;
}
 
#back-button svg {
    stroke: var(--primary-color);
    transition: stroke 0.2s;
}
 
#back-button:hover svg {
    stroke: #285177;
}
 
/* Responsive Handling */
@media (max-width: 768px) {
    #back-button svg {
        width: 18px;
        height: 18px;
    }
}
 
/* Breadcrumb Styling */
#breadcrumb-container {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    justify-content: flex-start; /* This ensures left alignment */
}
 
#breadcrumb-container #breadcrumb {
    font-size: 14px;
    color: var(--primary-color);
}
 
.breadcrumb-step {
    cursor: pointer;
    text-decoration: none;
    color: var(--primary-color);
}
 
.breadcrumb-step:hover {
    text-decoration: underline;
}
.booking-heading {
  margin-bottom: 10px;
}
 
 
 
 
</style>
 
<div id="repair-widget">
<!-- Breadcrumb Container with Back Button -->
<div id="breadcrumb-container" style="display: flex; align-items: center; gap: 8px; margin-bottom: 10px;">
  <button id="back-button" style="display: none;" aria-label="Tilbage">
    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
      <polyline points="15 18 9 12 15 6"></polyline>
    </svg>
  </button>
  <div id="breadcrumb"></div>
</div>
 
  <div id="header">
    <h1>Slå din pris op og book tid</h1>
    <div class="search-bar-container">
      <input type="text" id="device-search-bar" placeholder="Søg efter din enhed..." autocomplete="off" data-hj-allow />
      <button id="clear-search-bar" class="hidden">X</button>
      <span id="search-icon"></span>
    </div>
    <div id="dropdown-results" class="hidden"></div>
  </div>
  <div id="content"></div>
</div>
 
<!-- 2) Flatpickr JS (CDN) -->
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script>
  document.addEventListener("DOMContentLoaded", () => {
    /* ========================================
       PART 1: Existing Widget Initialization
    =========================================*/
    const repairWidget = document.getElementById("repair-widget");
    const main = document.getElementById("main");
    const breadcrumbDiv = document.getElementById("breadcrumb");
    const headerH1 = document.querySelector("#header h1");
    const contentDiv = document.getElementById("content");
    const searchBar = document.getElementById("device-search-bar");
    const dropdownResults = document.getElementById("dropdown-results");
    const clearSearchButton = document.getElementById("clear-search-bar");
    
    // --- SEARCH ICON TOGGLE CODE ---
    const searchIcon = document.getElementById("search-icon");
    const originalIconURL = 'data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2024%2024%22%20fill=%22none%22%20stroke=%22%2333658A%22%20stroke-width=%223%22%20stroke-linecap=%22round%22%20stroke-linejoin=%22round%22%20class=%22icon%20icon-search%22%3E%3Ccircle%20cx=%2210%22%20cy=%2210%22%20r=%227%22%3E%3C/circle%3E%3Cline%20x1=%2216%22%20y1=%2216%22%20x2=%2221%22%20y2=%2221%22%3E%3C/line%3E%3C/svg%3E';
 
     const clearIconURL = 'data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2024%2024%22%20fill=%22none%22%20stroke=%22%2333658A%22%20stroke-width=%222%22%20stroke-linecap=%22round%22%20stroke-linejoin=%22round%22%3E%3Cline%20x1=%2218%22%20y1=%226%22%20x2=%226%22%20y2=%2218%22/%3E%3Cline%20x1=%226%22%20y1=%226%22%20x2=%2218%22%20y2=%2218%22/%3E%3C/svg%3E';
    
    searchBar.addEventListener("input", function() {
      if (this.value.trim().length > 0) {
        // Change only the background-image property so the original CSS background-size remains.
        searchIcon.style.backgroundImage = `url("${clearIconURL}")`;
        searchIcon.style.pointerEvents = "auto";
      } else {
        searchIcon.style.backgroundImage = `url("${originalIconURL}")`;
        searchIcon.style.pointerEvents = "none";
        dropdownResults.classList.add("hidden");
      }
    });
    
    searchIcon.addEventListener("click", function() {
      if (searchBar.value.trim().length > 0) {
        searchBar.value = "";
        searchIcon.style.backgroundImage = `url("${originalIconURL}")`;
        searchIcon.style.pointerEvents = "none";
        dropdownResults.classList.add("hidden");
        searchBar.dispatchEvent(new Event("input"));
      }
    });
    
    // Clear search when ESC is pressed
    document.addEventListener("keydown", function(e) {
      if (e.key === "Escape") {
        if (searchBar.value.trim().length > 0) {
          searchBar.value = "";
          searchIcon.style.backgroundImage = `url("${originalIconURL}")`;
          searchIcon.style.pointerEvents = "none";
          dropdownResults.classList.add("hidden");
          searchBar.dispatchEvent(new Event("input", { bubbles: true }));
          //console.log("Search cleared via ESC");
        }
      }
    });
    
    // Clear search if user clicks outside the search container
    document.addEventListener("click", function(e) {
      if (!e.target.closest(".search-bar-container")) {
        if (searchBar.value.trim().length > 0) {
          searchBar.value = "";
          searchIcon.style.backgroundImage = `url("${originalIconURL}")`;
          searchIcon.style.pointerEvents = "none";
          dropdownResults.classList.add("hidden");
          searchBar.dispatchEvent(new Event("input", { bubbles: true }));
          //console.log("Search cleared via outside click");
        }
      }
     if (!e.target.closest(".info-icon")) {
      document.querySelectorAll(".info-icon").forEach((icon) => {
      icon.classList.remove("show-tooltip");
       });
     }
    });
 
    let jsonUrl = "something";
    let breadcrumb = [];
    let allDevices = [];
    let firstLoad = true;
 
    let debounceTimeout;
    function debounce(func, delay) {
      return function (...args) {
        clearTimeout(debounceTimeout);
        debounceTimeout = setTimeout(() => {
          func.apply(this, args);
        }, delay);
      };
    }
 
    async function getAttachedJsonUrl(postId) {
      try {
        const response = await fetch(
          `https://www.techdoktoren.dk/wp-json/wp/v2/media?parent=${postId}`
        );
        if (!response.ok) {
          throw new Error(`Failed to fetch media: ${response.status}`);
        }
        const mediaFiles = await response.json();
        const jsonFile = mediaFiles.find(
          (file) => file.mime_type === "application/json"
        );
        if (jsonFile) return jsonFile.source_url;
        throw new Error("No JSON file found attached to this post.");
      } catch (error) {
        console.error("Error fetching attached JSON file:", error);
        return null;
      }
    }
 
    async function initWidget() {
      const attachedJsonUrl = await getAttachedJsonUrl(9813);
      if (attachedJsonUrl) {
        jsonUrl = attachedJsonUrl;
        //console.log("JSON URL found:", jsonUrl);
        try {
          const response = await fetch(jsonUrl);
          const data = await response.json();
          allDevices = extractDevices(data.data);
          contentDiv.classList.add("content-loaded");
          
          //Check URL params
          const urlParams = new URLSearchParams(window.location.search);
          const categoryParam = urlParams.get("category");
          const manufacturerParam = urlParams.get("manufacturer");
          const deviceParam = urlParams.get("device");
            
          navigateTo("Categories", data.data);
          
          if (categoryParam) {
            const foundCategory = data.data.find(cat => cat.name === categoryParam);
            if (foundCategory) {
              selectedCategory = foundCategory;
              navigateTo("Manufacturers", foundCategory.manufacturers);
              
              if (manufacturerParam) {
                const foundManufacturer = foundCategory.manufacturers.find(man => man.name === manufacturerParam);
                if (foundManufacturer) {
                  selectedManufacturer = foundManufacturer;
                  navigateTo("Devices", foundManufacturer.devices);
                  
                  if (deviceParam) {
                    const foundDevice = foundManufacturer.devices.find(dev => dev.name === deviceParam);
                    if (foundDevice) {
                      navigateTo("Problems", foundDevice.problems, foundDevice);
                    }
                  }
                }
              }
            }
          }
          
        } catch (error) {
          console.error("Error fetching JSON data:", error);
          contentDiv.classList.add("content-loaded");
          contentDiv.innerText = "Failed to load data.";
        }
      } else {
        //console.log("No JSON file found. Cannot fetch data.");
        contentDiv.classList.add("content-loaded");
        contentDiv.innerText = "No data available.";
      }
    }
 
    function extractDevices(categories) {
      const devices = [];
      categories.forEach((category) => {
        category.manufacturers.forEach((manufacturer) => {
          manufacturer.devices.forEach((device) => {
            devices.push({
              name: device.name,
              image: device.image,
              problems: device.problems,
              hierarchy: [category.name, manufacturer.name, device.name],
              category,
              manufacturer,
            });
          });
        });
      });
      return devices;
    }
 
    function attachTooltipHandler(infoIcon) {
      infoIcon.addEventListener("click", (e) => {
        e.stopPropagation();
        document.querySelectorAll(".info-icon").forEach((icon) => {
          if (icon !== infoIcon) {
            icon.classList.remove("show-tooltip");
          }
        });
        infoIcon.classList.toggle("show-tooltip");
        const tooltipRect = infoIcon.getBoundingClientRect();
        const viewportWidth = window.innerWidth;
        if (tooltipRect.right > viewportWidth) {
          infoIcon.style.setProperty("--tooltip-left", `${viewportWidth - tooltipRect.right}px`);
        } else {
          infoIcon.style.removeProperty("--tooltip-left");
        }
      });
    }
 
    function highlightSearchTerms(text, term) {
      const terms = term.split(" ").filter(Boolean);
      const regex = new RegExp(`(${terms.join("|")})`, "gi");
      return text.replace(regex, (match) => `<mark>${match}</mark>`);
    }
 
    function renderDropdownResults(devices) {
      dropdownResults.innerHTML = "";
      if (devices.length === 0) {
        dropdownResults.innerHTML = `<div class="dropdown-item">Ingen enhed fundet med din søgning.</div>`;
        dropdownResults.classList.remove("hidden");
        return;
      }
      devices.forEach((device) => {
        const highlightedName = highlightSearchTerms(device.name, searchBar.value);
        const item = document.createElement("div");
        item.className = "dropdown-item";
        item.innerHTML = `
          <img src="${
            device.image || "https://www.techdoktoren.dk/wp-content/uploads/2024/12/device.png"
          }" class="dropdown-image" alt="${device.name}" />
          <span class="dropdown-text">${highlightedName}</span>
        `;
        item.addEventListener("click", () => {
          //console.log("Device Selected:", device);
            // Clear search input and hide dropdown
          searchBar.value = "";
          dropdownResults.classList.add("hidden");
          // **Set the state explicitly**
        selectedCategory = device.category;
        selectedManufacturer = device.manufacturer;
          navigateTo("Manufacturers", device.category.manufacturers);
          navigateTo("Devices", device.manufacturer.devices);
          navigateTo("Problems", device.problems, device);
        });
        dropdownResults.appendChild(item);
      });
      dropdownResults.classList.remove("hidden");
    }
 
function handleNormalSearch(e) {
  const searchTerm = e.target.value.toLowerCase().trim();
  if (!searchTerm) {
    dropdownResults.classList.add("hidden");
    dropdownResults.innerHTML = "";
    return;
  }
 
  // Split the search term into words
  const searchTerms = searchTerm.split(" ").filter(Boolean);
 
  const matchingDevices = allDevices.filter((device) => {
    // Combine manufacturer and device name into one string
    const combinedText = `${device.manufacturer.name} ${device.name}`.toLowerCase();
    // Ensure every word in the search query is found in the combined text
    return searchTerms.every(term => combinedText.includes(term));
  });
 
  renderDropdownResults(matchingDevices);
}
 
    const debouncedNormalSearch = debounce(handleNormalSearch, 300);
 
function handleFilterSearch(e) {
  const searchTerm = e.target.value.toLowerCase().trim();
  const currentLevel = breadcrumb[breadcrumb.length - 1];
  
  if (!searchTerm) {
    renderContent(currentLevel.level, currentLevel.items);
    return;
  }
  
  // Split the search term into words
  const searchTerms = searchTerm.split(" ").filter(Boolean);
  
  const filteredItems = currentLevel.items.filter(item => {
    // If the item has a manufacturer (for device level), combine both fields.
    let combinedText = "";
    if (item.manufacturer && item.name) {
      combinedText = `${item.manufacturer.name} ${item.name}`.toLowerCase();
    } else {
      combinedText = item.name.toLowerCase();
    }
    
    // Ensure every search term is present in the combined text
    return searchTerms.every(term => combinedText.includes(term));
  });
  
  renderContent(currentLevel.level, filteredItems);
}
 
    const debouncedFilterSearch = debounce(handleFilterSearch, 300);
    
    function updateURL(level, currentDevice = null) {
      const urlParams = new URLSearchParams(window.location.search);
    
      // Update URL based on the current level
      if (level === "Categories") {
        urlParams.delete("category");
        urlParams.delete("manufacturer");
        urlParams.delete("device");
        urlParams.delete("problem");
      } else if (level === "Manufacturers" && selectedCategory) {
        urlParams.set("category", selectedCategory.name);
        urlParams.delete("manufacturer");
        urlParams.delete("device");
        urlParams.delete("problem");
      } else if (level === "Devices" && selectedCategory && selectedManufacturer) {
        urlParams.set("category", selectedCategory.name);
        urlParams.set("manufacturer", selectedManufacturer.name);
        urlParams.delete("device");
        urlParams.delete("problem");
      } else if (level === "Problems" && currentDevice) {
        urlParams.set("category", selectedCategory.name);
        urlParams.set("manufacturer", selectedManufacturer.name);
        urlParams.set("device", currentDevice.name);
      }
    
      // Push the new URL state to the browser's history
      const newURL = window.location.pathname + "?" + urlParams.toString();
      window.history.pushState({}, "", newURL);
    }
 
    function navigateTo(level, items, device = null) {
      breadcrumb.push({ level, items });
      renderBreadcrumb();
      renderContent(level, items, device);
 
      if (device) {
        headerH1.textContent = "";
      } else {
        headerH1.textContent = "Slå din pris op og book tid";
      }
 
      contentDiv.style.display = level === "Problems" ? "block" : "grid";
 
      if (level === "Categories") {
        searchBar.style.display = "block";
        searchBar.placeholder = "Søg efter din enhed";
        dropdownResults.classList.add("hidden");
        searchBar.removeEventListener("input", debouncedFilterSearch);
        searchBar.addEventListener("input", debouncedNormalSearch);
      } else if (level === "Manufacturers" || level === "Devices") {
        searchBar.style.display = "block";
        searchBar.placeholder =
          level === "Manufacturers" ? "Filtrer efter mærke..." : "Filtrer efter model...";
        dropdownResults.classList.add("hidden");
        searchBar.removeEventListener("input", debouncedNormalSearch);
        searchBar.addEventListener("input", debouncedFilterSearch);
      } else {
        searchBar.style.display = "none";
        searchBar.removeEventListener("input", debouncedFilterSearch);
        searchBar.removeEventListener("input", debouncedNormalSearch);
        dropdownResults.classList.add("hidden");
      }
 
      if (!firstLoad) {
        main.scrollIntoView({ behavior: "smooth" });
      }
      firstLoad = false;
      
      updateURL(level, device);
      updateBackButton(); // Ensure the back button visibility is updated whenever navigation happens
    }
 
    function navigateBreadcrumb(index) {
      const breadcrumbStep = breadcrumb[index];
      if (!breadcrumbStep.items) return;
      if (index === breadcrumb.length - 1) return;
      breadcrumb = breadcrumb.slice(0, index + 1);
      renderBreadcrumb();
      renderContent(breadcrumbStep.level, breadcrumbStep.items);
      headerH1.textContent =
        breadcrumbStep.level === "Problems" ? "" : "Slå din pris op og book tid";
      searchBar.style.display = index === 0 ? "block" : "none";
      contentDiv.style.display = "grid";
 
      if (breadcrumbStep.level === "Categories") {
        searchBar.style.display = "block";
        searchBar.placeholder = "Søg efter din enhed";
        dropdownResults.classList.add("hidden");
        searchBar.removeEventListener("input", debouncedFilterSearch);
        searchBar.addEventListener("input", debouncedNormalSearch);
      } else if (breadcrumbStep.level === "Manufacturers" || breadcrumbStep.level === "Devices") {
        searchBar.style.display = "block";
        searchBar.placeholder =
          breadcrumbStep.level === "Manufacturers" ? "Filtrer efter mærke..." : "Filtrer efter model...";
        dropdownResults.classList.add("hidden");
        searchBar.removeEventListener("input", debouncedNormalSearch);
        searchBar.addEventListener("input", debouncedFilterSearch);
      } else {
        searchBar.style.display = "none";
        dropdownResults.classList.add("hidden");
      }
      updateURL(breadcrumbStep.level);
       }
 
    const breadcrumbTranslations = {
      Categories: "Kategorier",
      Manufacturers: "Mærker",
      Devices: "Modeller",
      Problems: "Reparationer",
    };
 
    function renderBreadcrumb() {
      updateBackButton(); 
      breadcrumbDiv.innerHTML = breadcrumb
        .map((step, index) => {
          if (step.level === "Categories" && index === breadcrumb.length - 1) {
            return "";
          }
          return `<span class="breadcrumb-step ${
            step.items ? "" : "non-clickable"
          }" data-index="${index}">${
            breadcrumbTranslations[step.level] || step.level
          }</span>`;
        })
        .filter(Boolean)
        .join(" > ");
      document.querySelectorAll(".breadcrumb-step").forEach((step) => {
        step.addEventListener("click", () => {
          const index = parseInt(step.getAttribute("data-index"), 10);
          navigateBreadcrumb(index);
        });
      });
    }
    
    const backButton = document.getElementById("back-button");
    
    function updateBackButton() {
        if (breadcrumb.length > 1) {
            backButton.style.display = "flex";
        } else {
            backButton.style.display = "none";
        }
    }
    
    // Handle Back Button Click
    backButton.addEventListener("click", () => {
        if (breadcrumb.length > 1) {
            const previousIndex = breadcrumb.length - 2; // Navigate to the previous level
            navigateBreadcrumb(previousIndex);
        }
    });
 
 
    /* ========================================
       PART 2: Rendering the Content
    =========================================*/
    
    let selectedCategory = null;
    let selectedManufacturer = null;
 
    function renderContent(level, items, device = null) {
      contentDiv.innerHTML = "";
      if (level === "Categories") {
        items.forEach((category) => {
          const card = createCard(
            category.name,
            category.image || "default-category.jpg",
            () => {
          // Save the selected category
          selectedCategory = category;
          // Reset the manufacturer
          selectedManufacturer = null;
          navigateTo("Manufacturers", category.manufacturers);
        }
          );
          contentDiv.appendChild(card);
        });
      } else if (level === "Manufacturers") {
        items.forEach((manufacturer) => {
          const card = createCard(
            manufacturer.name,
            manufacturer.image || "default-manufacturer.jpg",
            () => {
          // Save the selected manufacturer
          selectedManufacturer = manufacturer;
          navigateTo("Devices", manufacturer.devices);
        }
          );
          contentDiv.appendChild(card);
        });
      } else if (level === "Devices") {
        items.forEach((deviceItem) => {
          const card = createCard(
            deviceItem.name,
            deviceItem.image || "https://www.techdoktoren.dk/wp-content/uploads/2024/12/device.png",
            () => {
                    //console.log("Device Card Clicked:", deviceItem);
                    //console.log("Category:", selectedCategory);
                    //console.log("Manufacturer:", selectedManufacturer);
                    // Continue navigating to the next level:
                    navigateTo("Problems", deviceItem.problems, deviceItem);
                  }
          );
          contentDiv.appendChild(card);
        });
      }
 
      /* ============= PROBLEMS + BOOKING FORM ============= */
      if (level === "Problems" && device) {
          
        generateSchemaMarkup(device.name, selectedManufacturer.name, items);
        
        // Device header
        const deviceHeader = document.createElement("div");
        deviceHeader.className = "device-header";
        deviceHeader.innerHTML = `
          <img src="${
            device.image || "https://www.techdoktoren.dk/wp-content/uploads/2024/12/device.png"
          }" alt="${device.name}" class="device-thumbnail" />
          <div class="device-info">${device.name} Reparation</div>
        `;
        contentDiv.appendChild(deviceHeader);
        
          // Conditional information box for iPhone devices
          if (device.name.toLowerCase().includes("iphone")) {
            const infoBox = document.createElement("div");
            infoBox.className = "walk-in-info-box";
            infoBox.innerHTML = `
              <strong>Bemærk:</strong> Vi tilbyder <em>walk-in reparation</em> uden booking, og de fleste iPhone reparationer tager under 60 minutter.
            `;
            contentDiv.appendChild(infoBox);
          }
          
        if (device.name.toLowerCase().includes("macbook")) {
          const yearMatch = device.name.match(/\b(20\d{2})\b/);
          const year = yearMatch ? parseInt(yearMatch[1], 10) : null;
        
          if (year !== null && year <= 2020) {
            const infoBox = document.createElement("div");
            infoBox.className = "walk-in-info-box";
            infoBox.innerHTML = `
              <strong>Bemærk:</strong> Vi tilbyder <em>walk-in reparation</em> uden booking, 
              og de fleste MacBook reparationer kan klares samme dag.
            `;
            contentDiv.appendChild(infoBox);
          }
        }
 
 
        // Problem list
        const problemList = document.createElement("div");
        problemList.className = "problem-list";
        const selectedProblems = new Set();
 
        function updateSummary() {
          const summaryBox = document.getElementById("problem-summary");
          const selectedProblemsArray = Array.from(selectedProblems);
          const summary = selectedProblemsArray
            .map((problem) => {
              const displayPrice =
                problem.original_price == 0
                  ? "Pris ved forespørgsel"
                  : `${Math.round(problem.original_price)} kr`;
              return `- ${problem.name}: ${displayPrice}`;
            })
            .join("\n");
          const totalPrice = selectedProblemsArray.reduce(
            (sum, problem) => sum + Math.round(problem.original_price),
            0
          );
          const totalPriceText = totalPrice > 0 ? `\n\nSamlet pris: ${totalPrice} kr` : "";
          summaryBox.textContent = summary || "Ingen reparationer valgt endnu.";
          if (selectedProblemsArray.length > 0) {
            summaryBox.textContent += totalPriceText;
          }
        }
 
        function updateSubmitButtonState() {
          if (selectedProblems.size > 0) {
            submitButton.disabled = false;
            submitButton.classList.remove("disabled");
          } else {
            submitButton.disabled = true;
            submitButton.classList.add("disabled");
          }
        }
 
        items.forEach((problem) => {
          const problemCard = document.createElement("div");
          problemCard.className = "problem-card";
          const displayPrice =
            problem.original_price == 0
              ? "Pris ved forespørgsel"
              : `${Math.round(problem.original_price)} kr`;
          problemCard.innerHTML = `
            <div class="problem-info">
              <h3 class="problem-name">
                ${problem.name}
                ${
                  problem.description
                    ? `<span class="info-icon" data-tooltip="${problem.description}">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#33658A" viewBox="0 0 24 24">
                          <circle cx="12" cy="12" r="10" fill="#ffffff" stroke="#12375A" stroke-width="2"></circle>
                          <text x="12" y="16" fill="#33658A" font-size="12" font-family="Arial" text-anchor="middle">?</text>
                        </svg>
                      </span>`
                    : ""
                }
              </h3>
            </div>
            <div class="problem-action">
              <span class="problem-price">${displayPrice}</span>
            </div>
          `;
          const infoIcon = problemCard.querySelector(".info-icon");
          if (infoIcon) {
            attachTooltipHandler(infoIcon);
          }
          problemCard.addEventListener("click", () => {
            if (problemCard.classList.contains("selected")) {
              selectedProblems.delete(problem);
              problemCard.classList.remove("selected");
            } else {
              selectedProblems.add(problem);
              problemCard.classList.add("selected");
              bookingFormContainer.scrollIntoView({ behavior: "smooth" });
            }
            
            bookingDatePicker.set('minDate', calculateMinDate());
            updateSummary();
            updateSubmitButtonState();
            updateColorFieldVisibility();
 
          });
          problemList.appendChild(problemCard);
        });
        contentDiv.appendChild(problemList);
 
        //<textarea id="problem-description" placeholder="Beskriv venligst dit problem"></textarea>
        // Booking form container
        const bookingFormContainer = document.createElement("div");
        bookingFormContainer.className = "booking-form-container";
bookingFormContainer.innerHTML = `
  <hr class="separator">
  <h3 class="booking-heading">Valgte reparationer</h3>
  <form id="booking-form">
    <div id="problem-summary">Ingen reparationer valgt endnu</div>
    
    <input type="text" id="customer-name" placeholder="Navn" required />
    <input type="email" id="customer-email" placeholder="E-mail" required />
    <input type="tel" id="customer-phone" placeholder="Telefonnummer" maxlength="8" required />
    <!-- Color Field Wrapper (hidden by default) -->
    <div id="device-color-field-wrapper" style="display: none;">
      <input type="text" id="device-color" placeholder="Farve på enhed" required />
    </div>
 
 
    <!-- 1) DATE PICKER (FLATPICKR, date-only) -->
    <input type="text" id="booking-date" placeholder="Vælg en dato og tid" required />
 
    <!-- 2) TIME SLOTS UI -->
    <div class="timeslot-container" id="timeslot-container">
      <div class="timeslot-heading" id="timeslot-heading">Vælg et tidspunkt</div>
      <div class="timeslot-grid" id="timeslot-grid"></div>
    </div>
 
    <input type="text" id="kommentar" placeholder="Evt. kommentar til bestillingen" />
    <button type="submit" id="submit-booking">Send Booking</button>
 
    <!-- The new call-us section -->
    <div
  id="call-us"
  style="
    border-top: 1px solid #ddd;
    padding-top: 15px;
    margin-top: 20px;
    text-align: center;
    font-size: 14px;
    line-height: 1.4;
  "
>
    <strong style="display: block; margin-bottom: 5px;">Har du spørgsmål?</strong>
  Ønsker du at snakke med en medarbejder, så giv os et kald:
  <a
    href="tel:81113337"
    style="
      display: inline-flex;
      align-items: center;
      color: #33658A;
      background-color: #f9f9f9;
      padding: 5px 10px;
      border: 1px solid #33658A;
      border-radius: 4px;
      text-decoration: none;
      margin-left: 5px;
    "
  >
    <!-- Phone icon (inline SVG) -->
    <svg
      xmlns="http://www.w3.org/2000/svg"
      width="16"
      height="16"
      fill="none"
      stroke="#33658A"
      stroke-width="2"
      stroke-linecap="round"
      stroke-linejoin="round"
      style="margin-right: 5px;"
      viewBox="0 0 24 24"
    >
      <path d="M22 16.92V21a1 1 0 01-1.11 1 19.86 19.86 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.86 19.86 0 01-3.07-8.63A1 1 0 013 2h4.09a1 1 0 011 .75c.2.92.52 1.8.96 2.62a1 1 0 01-.27 1.11l-2.2 2.2a16 16 0 006 6l2.2-2.2a1 1 0 011.11-.27 16 16 0 002.62.96 1 1 0 01.75 1V22z"></path>
    </svg>
    81 11 33 37
  </a>
</div>
  </form>
`;
 
 
 
        contentDiv.appendChild(bookingFormContainer);
        
        // Run once on load and then update periodically (e.g., every minute)
        showCallUsIfOpen();
 
        /* ============================================
           PART 3: DATE PICKER + TIME SLOT LOGIC
        ============================================*/
        const disabledDates = [
          "2024-12-24",
          "2024-12-25",
          "2024-12-26",
          "2024-12-27",
          "2024-12-28",
          "2024-12-29",
          "2024-12-30",
          "2024-12-31",
          "2025-01-01",
          "2025-04-17",
          "2025-04-18",
          "2025-04-21",
          "2025-05-26",
          "2025-05-29",
          "2025-06-05",
          "2025-06-06",
          "2025-06-08",
          "2025-06-09",
          "2025-06-12",
          "2025-06-14",
          "2025-06-23",
          "2025-06-30",
          "2025-12-24",
          "2025-12-25",
          "2025-12-26",
          "2025-12-31",
          "2025-11-03",
          "2025-11-01"
        ];
 
        // Example: booked time slots in "YYYY-MM-DD HH:mm" format
        // These timeslots should appear as "booked" (unavailable) in the UI
        const bookedTimeslots = [
            "2025-06-25 10:00",
            "2025-06-25 10:15",
            "2025-06-25 10:30",
            "2025-06-25 10:45",
            "2025-06-25 11:00",
            "2025-06-25 11:15",
            "2025-06-25 11:30",
            "2025-06-25 11:45",
            "2025-06-25 12:00",
            
            "2025-06-27 15:00",
            "2025-06-27 15:15",
            "2025-06-27 15:30",
            "2025-06-27 15:45",
            "2025-06-27 16:00",
            "2025-06-27 16:15",
            "2025-06-27 16:30",
            "2025-06-27 16:45",
            "2025-06-27 17:00",
            "2025-06-27 17:15",
            "2025-06-27 17:30",
            "2025-06-27 17:45",
            "2025-06-27 18:00",
 
            "2025-07-01 15:00",
            "2025-07-01 15:15",
            "2025-07-01 15:30",
            "2025-07-01 15:45",
            "2025-07-01 16:00",
            "2025-07-01 16:15",
            "2025-07-01 16:30",
            "2025-07-01 16:45",
            "2025-07-01 17:00",
            "2025-07-01 17:15",
            "2025-07-01 17:30",
            "2025-07-01 17:45",
            "2025-07-01 18:00",
            
            "2025-10-30 15:00",
            "2025-10-30 15:15",
            "2025-10-30 15:30",
            "2025-10-30 15:45",
            "2025-10-30 16:00",
            "2025-10-30 16:15",
            "2025-10-30 16:30",
            "2025-10-30 16:45",
            "2025-10-30 17:00",
            "2025-10-30 17:15",
            "2025-10-30 17:30",
            "2025-10-30 17:45",
            "2025-10-30 18:00",
            
            "2025-10-31 15:00",
            "2025-10-31 15:15",
            "2025-10-31 15:30",
            "2025-10-31 15:45",
            "2025-10-31 16:00",
            "2025-10-31 16:15",
            "2025-10-31 16:30",
            "2025-10-31 16:45",
            "2025-10-31 17:00",
            "2025-10-31 17:15",
            "2025-10-31 17:30",
            "2025-10-31 17:45",
            "2025-10-31 18:00",
            
            "2025-11-05 14:00",
            "2025-11-05 14:15",
            "2025-11-05 14:30",
            "2025-11-05 14:45",
            "2025-11-05 15:00",
            "2025-11-05 15:15",
            "2025-11-05 15:30",
            "2025-11-05 15:45",
            "2025-11-05 16:00",
            "2025-11-05 16:15",
            "2025-11-05 16:30",
            "2025-11-05 16:45",
            "2025-11-05 17:00",
            "2025-11-05 17:15",
            "2025-11-05 17:30",
            "2025-11-05 17:45",
            "2025-11-05 18:00",
 
        ];
 
        const deviceName = document.querySelector(".device-info")?.textContent || "Ukendt enhed";
 
        // We'll define standard time slots for weekdays vs. Saturday
        const timeSlots = {
  weekday: [
    "10:00", "10:15", "10:30", "10:45",
    "11:00", "11:15", "11:30", "11:45",
    "12:00", "12:15", "12:30", "12:45",
    "13:00", "13:15", "13:30", "13:45",
    "14:00", "14:15", "14:30", "14:45",
    "15:00", "15:15", "15:30", "15:45",
    "16:00", "16:15", "16:30", "16:45",
    "17:00"
  ],
  saturday: [
    "10:00", "10:15", "10:30", "10:45",
    "11:00", "11:15", "11:30", "11:45",
    "12:00", "12:15", "12:30", "12:45",
    "13:00", "13:15", "13:30", "13:45",
    "14:00", "14:15", "14:30", "14:45",
    "15:00"
  ]
};
 
 
        function isSameDate(d1, d2) {
          return (
            d1.getFullYear() === d2.getFullYear() &&
            d1.getMonth() === d2.getMonth() &&
            d1.getDate() === d2.getDate()
          );
        }
        
        function formatDateYYYYMMDD(date) {
          const y = date.getFullYear();
          const m = String(date.getMonth() + 1).padStart(2, "0");
          const d = String(date.getDate()).padStart(2, "0");
          return `${y}-${m}-${d}`;
        }
        
        function addAvailableDays(startDate, daysToAdd, disabledDates) {
          let result = new Date(startDate);
          
          while (daysToAdd > 0) {
            result.setDate(result.getDate() + 1);
            // Skip if weekend
            if (result.getDay() === 0 || result.getDay() === 6) continue;
            // Skip if disabled date
            if (disabledDates.includes(formatDateYYYYMMDD(result))) continue;
            // Otherwise, count this day as available
            daysToAdd--;
          }
          return result;
        }
 
        function calculateMinDate() {
          const now = new Date();
          //console.log("Current date:", now);
          const isWeekend = now.getDay() === 0 || now.getDay() === 6;
          const isDisabledDate = disabledDates.includes(formatDateYYYYMMDD(now));
 
        
          // Log the current selected problems
          //console.log("Selected Problems:", Array.from(selectedProblems));
        
          let availableDaysToAdd = 0;
          //console.log("Device name:", deviceName);
 
          
          // Check if "Skærm (Original Apple)" is selected among the chosen problems.
          const hasSkærmOriginal = Array.from(selectedProblems).some(problem => problem.name === "Skærm (Apple Original)");
          //console.log("Has 'Skærm (Apple Original)' selected:", hasSkærmOriginal);
          
          // Check if "Diagnose is selected among the chosen problems.
          const hasDiagnose = Array.from(selectedProblems).some(problem => problem.name === "Diagnose");
          //console.log("Has 'hasDiagnose' selected:", hasDiagnose);
          
          
            const deviceName = document.querySelector(".device-info")?.textContent.toLowerCase() || "";
            const lowerName = deviceName.toLowerCase();
            const macbookMatch = deviceName.match(/\b(20\d{2})\b/); // finds year like 2019, 2020, 2021
            const macbookYear = macbookMatch ? parseInt(macbookMatch[1], 10) : null;
 
            const isOldMacbook = lowerName.includes("macbook") && macbookYear !== null && macbookYear <= 2020;
            const isNewMacbook = lowerName.includes("macbook") && macbookYear !== null && macbookYear > 2020;
            
          // Apply non‑iPhone rules if the device isn’t an iPhone OR if the specific problem is selected.
          const problemsArray = Array.from(selectedProblems);
          
          //console.log("problemsArray length:", problemsArray.length);
          if (hasDiagnose && problemsArray.length === 1) {
              availableDaysToAdd = 0;
          } else if (!deviceName.includes("iphone") && isNewMacbook || hasSkærmOriginal) {
              if (!isWeekend && !isDisabledDate && now.getHours() < 13 || (now.getHours() === 13 && now.getMinutes() < 30)) {
                  availableDaysToAdd = 2;
              } else {
                  availableDaysToAdd = 3;
              }
          }
          
          //console.log("Available days to add:", availableDaysToAdd);
          
          const minDate = addAvailableDays(now, availableDaysToAdd, disabledDates);
          //console.log("Calculated minDate:", minDate);
          
          return minDate;
        }
        
        function updateColorFieldVisibility() {
          const colorFieldWrapper = document.getElementById("device-color-field-wrapper");
          const deviceColorInput = document.getElementById("device-color");
          
          if (!colorFieldWrapper) return;
        
          // Collect selected problems that mention "skærm", "bagside", or "topcase"
          let problemsWithKeyword = [];
          selectedProblems.forEach(problem => {
            const pname = problem.name.toLowerCase();
            if (pname.includes("skærm") || pname.includes("bagside") || pname.includes("topcase")) {
              problemsWithKeyword.push(problem);
            }
          });
        
          // Default: if there is at least one problem triggering the keywords, require color.
          let requireColor = problemsWithKeyword.length > 0;
        
          // Exception: For mobile repairs by Apple, if the only keyword present is "skærm",
          // then we do NOT require a color.
          const isMobileRepair = selectedCategory && selectedCategory.name.toLowerCase() === "mobil reparation";
          const isApple = selectedManufacturer && selectedManufacturer.name.toLowerCase().includes("apple");
        
          if (isMobileRepair && isApple && requireColor) {
            // Check if any selected problem includes "bagside" or "topcase"
            const hasBagsideOrTopcase = problemsWithKeyword.some(problem => {
              const pname = problem.name.toLowerCase();
              return pname.includes("bagside") || pname.includes("topcase");
            });
            // If there are none, then do not require a color.
            if (!hasBagsideOrTopcase) {
              requireColor = false;
            }
          }
        
            if (requireColor) {
            colorFieldWrapper.style.display = "block";
            deviceColorInput.disabled = false;
            deviceColorInput.required = true;
          } else {
            colorFieldWrapper.style.display = "none";
            deviceColorInput.disabled = true;
            deviceColorInput.required = false;
          }
        }
 
 
 
 
 
        /* Flatpickr for date-only */
        let bookingDatePicker = flatpickr("#booking-date", {
          enableTime: false,
          dateFormat: "d/m/Y",
          minDate: calculateMinDate(),
          /* Disable Sundays & disabledDates array */
          disable: [
            function(date) {
              // Sunday
              if (date.getDay() === 0) return true;
              // Format date as YYYY-MM-DD
              const fmtd = formatDateYYYYMMDD(date);
              return disabledDates.includes(fmtd);
            }
          ],
          locale: {
            firstDayOfWeek: 1,
            weekdays: {
              shorthand: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør"],
              longhand: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag"]
            },
            months: {
              shorthand: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"],
              longhand: [
                "Januar","Februar","Marts","April","Maj","Juni",
                "Juli","August","September","Oktober","November","December"
              ]
            }
          },
          onReady: function(selectedDates, dateStr, instance) {
            // Clear default selection
            instance.setDate(null);
            // Optionally add a note
            const info = instance.calendarContainer.querySelector(".flatpickr-info");
            if (!info) {
              const note = document.createElement("div");
              note.className = "flatpickr-info";
              note.innerText = "Booking tilgængelig: Man-Fre: 10:00-17:00. Lørdage: 10:00-15:00. (Søndag lukket)";
              instance.calendarContainer.appendChild(note);
            }
          },
          onChange: function(selectedDates) {
            if (!selectedDates.length) return;
            const chosenDate = selectedDates[0];
            // Generate timeslots
            generateTimeSlots(chosenDate);
          }
        });
 
        const timeslotContainer = document.getElementById("timeslot-container");
        const timeslotHeading = document.getElementById("timeslot-heading");
        const timeslotGrid = document.getElementById("timeslot-grid");
        let selectedSlot = null;
 
        function generateTimeSlots(chosenDate) {
          timeslotContainer.style.display = "block";
          timeslotGrid.innerHTML = "";
          selectedSlot = null;
 
          const dayOfWeek = chosenDate.getDay(); // 1=Monday, 6=Saturday
          const now = new Date();
          const isToday = isSameDate(chosenDate, now);
 
          // Determine if it's Saturday or a weekday
          let possibleSlots = [];
          if (dayOfWeek === 6) {
            possibleSlots = timeSlots.saturday;
          } else {
            possibleSlots = timeSlots.weekday;
          }
 
          // Filter out anything <2 hours from now if it's "today"
          const finalSlots = [];
          possibleSlots.forEach(time => {
            const [hh, mm] = time.split(":").map(Number);
            const slotDate = new Date(chosenDate);
            slotDate.setHours(hh, mm, 0, 0);
 
            if (isToday) {
              // Add 2 hours lead time
              const twoHoursFromNow = new Date(now);
              twoHoursFromNow.setHours(now.getHours() + 0, now.getMinutes());
              if (slotDate < twoHoursFromNow) {
                return; // skip
              }
            }
            finalSlots.push(time);
          });
 
          // If no finalSlots, show a message
          if (!finalSlots.length) {
            timeslotHeading.textContent = "Ingen ledige tider på denne dato";
            return;
          } else {
            timeslotHeading.textContent = "Vælg et tidspunkt";
          }
 
          // Render the final slots
          const dateStr = formatDateYYYYMMDD(chosenDate);
          finalSlots.forEach(time => {
            const fullDateTime = `${dateStr} ${time}`;
            const btn = document.createElement("button");
            btn.type = "button";
            btn.className = "timeslot-btn";
            btn.textContent = time;
 
            // Mark as booked if in bookedTimeslots
            if (bookedTimeslots.includes(fullDateTime)) {
              btn.classList.add("booked");
              btn.disabled = true;
            }
 
            btn.addEventListener("click", (e) => {
              e.stopPropagation();
              if (btn.classList.contains("booked")) return;
              // Unselect previous
              document.querySelectorAll(".timeslot-btn").forEach(b => b.classList.remove("selected"));
              btn.classList.add("selected");
              selectedSlot = time;
              //console.log("Timeslot selected:", selectedSlot);
 
            });
            timeslotGrid.appendChild(btn);
          });
        }
 
        /* ============================================
           PART 4: FORM SUBMISSION
        ============================================*/
        const bookingForm = document.getElementById("booking-form");
        const submitButton = document.getElementById("submit-booking");
 
        bookingForm.addEventListener("submit", async (e) => {
          e.preventDefault();
                      
          const kommentarInput = document.getElementById("kommentar");
          const deviceName = document.querySelector(".device-info")?.textContent.toLowerCase() || "";
          
          // Check if device name contains "Enhver" and comment is empty
          if (deviceName.includes("enhver") && !kommentarInput.value.trim()) {
            alert("Angiv venligst den præcise model i kommentarfeltet for din enhed.");
            kommentarInput.focus();
            return;
          }
 
          // Validate user picked a date & time
          const dateInput = document.getElementById("booking-date");
          if (!dateInput.value) {
            alert("Vælg en dato før du fortsætter.");
            dateInput.focus();
            return;
          }
          if (!selectedSlot) {
            alert("Vælg et tidspunkt før du fortsætter.");
            return;
          }
 
          // Because we have date in d/m/Y format, let's parse it or keep as is
          // For the final "datetime" field, combine date + selectedSlot
          const finalDateTime = `${dateInput.value} ${selectedSlot}`;
 
          submitButton.disabled = true;
          submitButton.textContent = "Vent venligst...";
 
          const validProblems = Array.from(selectedProblems).filter((p) => p && p.id);
          //console.log("Valid Problems:", validProblems);
 
          const problemNames = validProblems.map((p) => p.name).join("|");
          const problemPrices = validProblems
            .map((p) => parseFloat(p.original_price).toFixed(0))
            .join(", ");
          const totalPrice = validProblems.reduce((sum, p) => sum + parseFloat(p.original_price), 0).toFixed(0);
          const problemIds = validProblems.map((p) => p.id).join(", ");
          const category_id = validProblems.map((p) => p.category_id).join(", ");
          const device_id = validProblems.map((p) => p.device).join(", ");
          const deviceNameCurrent = document.querySelector(".device-info")?.textContent || "Ukendt enhed";
 
          const formData = new FormData();
          formData.append("action", "send_booking_data");
          formData.append("name", document.getElementById("customer-name").value);
          formData.append("email", document.getElementById("customer-email").value);
          formData.append("phone", document.getElementById("customer-phone").value);
 
          // Instead of the old datetime field, we now pass finalDateTime
          formData.append("datetime", finalDateTime);
 
          formData.append("device_name", deviceNameCurrent);
          formData.append("problem_names", problemNames);
          formData.append("problem_prices", problemPrices);
          formData.append("total", totalPrice);
          formData.append("problem_ids", problemIds);
          formData.append("category_id", category_id);
          formData.append("device_id", device_id);
          formData.append("enhed_farve", document.getElementById("device-color").value);
          formData.append("kommentar", document.getElementById("kommentar").value);
          formData.append("utm_source", sessionStorage.getItem("utm_source") || "");
          formData.append("utm_medium", sessionStorage.getItem("utm_medium") || "");
          formData.append("utm_campaign", sessionStorage.getItem("utm_campaign") || "");
          formData.append("utm_term", sessionStorage.getItem("utm_term") || "");
          formData.append("utm_content", sessionStorage.getItem("utm_content") || "");
          formData.append("landing_url", sessionStorage.getItem("td_landing_url") || localStorage.getItem("td_first_landing_url") || window.location.href);
  formData.append("landing_referrer", sessionStorage.getItem("td_referrer") || localStorage.getItem("td_first_referrer") || document.referrer || "");
  formData.append("booking_page_url", window.location.href);
 
          try {
            const response = await fetch("/wp-admin/admin-ajax.php", {
              method: "POST",
              body: formData,
            });
            const result = await response.json();
            if (result.success) {
              window.location.href = "/tak-for-din-booking/";
            } else {
              alert("Fejl ved afsendelse af booking: Prøv igen eller kontakt os direkte");
              submitButton.disabled = false;
              submitButton.textContent = "Send Booking";
            }
          } catch (error) {
            console.error("Error submitting booking:", error);
            alert("Fejl ved afsendelse af booking: Prøv igen eller kontakt os direkte");
            submitButton.disabled = false;
            submitButton.textContent = "Send Booking";
          }
        });
 
        // Initially disable the submit button until a problem is selected
        updateSubmitButtonState();
      }
    }
    
    function generateSchemaMarkup(deviceName, manufacturerName, repairItems) {
    const repairServices = repairItems.map(problem => ({
        "@type": "Service",
        "serviceType": problem.name,
        "provider": {
            "@type": "LocalBusiness",
            "name": "TechDoktoren",
            "url": "https://www.techdoktoren.dk",
            "address": {
                "@type": "PostalAddress",
                "addressCountry": "DK",
                "addressRegion": "Denmark",
                "addressLocality": "København"
            }
        },
        "areaServed": {
            "@type": "AdministrativeArea",
            "name": "Danmark"
        },
        "category": `${manufacturerName} ${deviceName} Reparation`,
        "serviceOutput": `Repareret ${problem.name}`,
        "offers": {
            "@type": "Offer",
            "price": problem.original_price > 0 ? problem.original_price.toString() : "Pris ved forespørgsel",
            "priceCurrency": "DKK"
        }
    }));
 
    const schemaMarkup = {
        "@context": "https://schema.org",
        "@type": "ItemList",
        "itemListElement": repairServices
    };
 
    injectSchemaMarkup(schemaMarkup);
}
 
    function injectSchemaMarkup(schemaMarkup) {
    // Convert schema object to JSON-LD format
    const schemaJSON = JSON.stringify(schemaMarkup, null, 2);
 
    // Create a new script tag for the schema
    const schemaScript = document.createElement("script");
    schemaScript.type = "application/ld+json";
    schemaScript.innerHTML = schemaJSON;
 
    // Remove any old schema tags to avoid duplication
    const oldSchema = document.querySelector('script[type="application/ld+json"]');
    if (oldSchema) oldSchema.remove();
 
    // Inject the new schema into the document head
    document.head.appendChild(schemaScript);
}
 
 
function showCallUsIfOpen() {
  const now = new Date();
  const day = now.getDay(); // 0 = Sunday, 1 = Monday, …, 6 = Saturday
  const hours = now.getHours();
  let open = false;
 
  // Monday - Friday: 10:00 - 18:00
  if (day >= 1 && day <= 5) {
    open = (hours >= 10 && hours < 18);
  }
  // Saturday: 10:00 - 16:00
  else if (day === 6) {
    open = (hours >= 10 && hours < 16);
  }
  // Sunday: closed
  else {
    open = false;
  }
 
  const callUsDiv = document.getElementById("call-us");
  if (callUsDiv) {
    callUsDiv.style.display = open ? "block" : "none";
  }
}
    /* Card creation helper */
function createCard(title, imageUrl, onClick) {
      const card = document.createElement("div");
      card.className = "card";
      card.innerHTML = `
        <img src="${imageUrl}" alt="${title}" class="card-image">
        <h3 class="card-title">${title}</h3>
      `;
      card.addEventListener("click", onClick);
      card.style.pointerEvents = "auto";
      return card;
    }
 
    /* Initialize the entire widget */
    initWidget();
  });
</script>
Hvad kan du få repareret

Vi laver reparation på iPhone, iPad, Macbook, Samsung, Lenovo, Dell med flere. Du kan booke en tid hvis du vil være sikker på at vi har reservedelen og tid til dig når du kommer. Dog laver vi de fleste reparationer på stedet så du kan også sagtens blot kigge forbi eller stikke os et kald på 81113337. Vi befinder os på Tagensvej 67, Nørrebro, 2200 København N, kig forbi.

For at gøre din oplevelse endnu mere bekvem, tilbyder vi en online booking service. Dette giver dig mulighed for at planlægge din reparation, når det passer dig bedst, og sikrer, at vi har de nødvendige reservedele på lager og kan dedikere vores tid specifikt til din enhed. Booking i forvejen sikrer en problemfri service og mindsker din ventetid, så du hurtigt kan få din enhed tilbage.

Nogle gange kan et reparationbehov ikke vente. Derfor tilbyder TechDoktoren også walk-in service for akutte reparationer. Vores erfarne teknikere står klar til at udføre de fleste reparationer på stedet, så du hurtigt kan få din enhed tilbage. Hvis du har brug for øjeblikkelig assistance eller har spørgsmål til specifikke reparationer, er du altid velkommen til at kigge forbi eller ringe til os. Vores team er her for at hjælpe dig med kyndig rådgivning og support.

Erfarne Teknikere: Vores certificerede teknikere har års erfaring og en dybdegående forståelse for teknologi, hvilket sikrer kvalitetsreparationer hver gang.

Højeste Kvalitetsdele: Vi bruger kun reservedele af højeste kvalitet for at garantere, at din enhed fungerer som ny efter reparationen.

Garanti på Reparation: Vi tilbyder garanti på alle vores reparationer for at give dig ro i sindet. Skulle der opstå problemer efterfølgende, står vi klar til at løse dem.

Kundetilfredshed i Højsædet: Din tilfredshed er vores højeste prioritet. Vi stræber efter at levere en service, der overstiger dine forventninger og sikrer, at din oplevelse med os er uden lige.

Vi ved, hvor frustrerende det kan være at have en defekt eller beskadiget enhed. Derfor er TechDoktoren dedikeret til at tilbyde hurtig, pålidelig og kvalitetsbevidst reparationsservice for iPhones, MacBooks, iPads og meget mere. Med vores nemme prisoverslag, bekvemme bookingmuligheder og kompetente reparationer, har det aldrig været lettere at få repareret din enhed. Stol på os til at bringe dine enheder tilbage til livet med professionel omhu. Besøg os i dag og oplev problemfri elektronikreparation, der holder.

Komplet Reparationsservice for Alle iPhone-modeller

Hos TechDoktoren er vi stolte over at kunne tilbyde en omfattende reparationservice for et bredt udvalg af iPhone-modeller. Vores erfarne teknikere er uddannede til at udføre professionelle skærmskift og batteriudskiftninger på følgende modeller:

  • iPhone SE (2. generation) og iPhone SE (3. generation)
  • iPhone 13 Pro Max, iPhone 13 Pro, iPhone 13, og iPhone 13 mini
  • iPhone 12 Pro Max, iPhone 12 Pro, iPhone 12, og iPhone 12 mini
  • iPhone 11 Pro Max, iPhone 11 Pro, og iPhone 11
  • iPhone XS Max, iPhone XS, og iPhone XR
  • iPhone X, iPhone 8 Plus, og iPhone 8
  • iPhone 7 Plus, iPhone 7, iPhone 6s Plus, iPhone 6s, iPhone 6 Plus, og iPhone 6
  • Ældre modeller: iPhone 5s, iPhone 5c, og iPhone 5

Så skal du have ny skærm eller nyt batteri så er vi det rette sted

Q: Hvordan fungerer prisoverslagswidgetten?

A: Vores prisoverslagswidget er designet til at være brugervenlig. Du skal blot vælge din enhedstype (f.eks. iPhone, MacBook, iPad) og den specifikke model. Herefter vil widgetten give dig et øjeblikkeligt estimat over reparationsomkostningerne. Dette estimat er baseret på de mest almindelige reparationer for netop din model.

Q: Skal jeg booke en tid før jeg kommer forbi med min enhed?

A: Selvom det ikke er nødvendigt at booke en tid før du kigger forbi, anbefaler vi booking for at sikre, at vi har de nødvendige reservedele på lager og kan dedikere vores tid specifikt til din reparation. Det minimerer også din ventetid og sikrer en hurtigere service.

Q: Hvilke typer af reparationer kan udføres på stedet?

A: De fleste almindelige reparationer såsom skærmskift, batteriudskiftning og mindre hardwareproblemer kan oftest udføres på stedet. For mere komplekse reparationer, som kræver specielle reservedele eller længere tid, vil vi informere dig om den forventede tidsramme.

Q: Hvordan sikrer I kvaliteten af reservedelene?

A: Vi bruger kun reservedele af højeste kvalitet fra pålidelige leverandører. Vores teknikere vurderer og tester alle dele for at sikre, at de opfylder vores strenge kvalitetskrav, før de anvendes i reparationer.

Q: Hvad dækker garantien på jeres reparationer?

A: Vores garanti dækker eventuelle fejl relateret til den udførte reparation eller de anvendte reservedele. Garantiperioden er standard 3 år og det vil tydeligt blive oplyst hvis andet skulle være gældende i dit tilfælde

Q: Kan jeg få et estimat over reparationen, før jeg beslutter mig?

A: Absolut. Vores prisoverslagswidget giver dig et hurtigt estimat. For mere specifikke reparationer eller hvis din enhed kræver en detaljeret vurdering, er du velkommen til at kigge forbi butikken eller kontakte os for et mere præcist tilbud.

Q: Hvad sker der, hvis min enhed ikke kan repareres?

A: I sjældne tilfælde, hvor en enhed ikke kan repareres eller hvis omkostningerne ved reparationen overstiger enhedens værdi, vil vi informere dig om dette og foreslå alternative løsninger. Disse kan inkludere udskiftning eller genbrug af enheden på en miljøvenlig måde.

Vi værdsætter din tid og ønsker at gøre reparationprocessen så gennemsigtig som mulig. Med vores brugervenlige prisoverslagswidget her på hjemmesiden, er det nemt at få et overblik over omkostningerne ved reparation af din specifikke enhed. Uanset om det drejer sig om en iPhone, MacBook eller iPad, hjælper vores værktøj dig med at få et hurtigt og præcist prisestimat, så du ved, hvad du kan forvente, før du forpligter dig.

ManTirOnsTorFreLørSøn
27282930311234567891011121314151617181920212223242526272829301234567
Booking tilgængelig: Man-Fre: 10:00-17:00. Lørdage: 10:00-15:00. (Søndag lukket)