Repository: LKosters/Cardan
Pull request #26: 10 bloemenwinkel   productenpagina
Author: login: Cocovg
Created: 2025-05-12T10:18:43Z | Merged: 2025-05-12T10:21:44Z



<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Introduced a comprehensive flower shop product page with category and subcategory filters, price range slider, and sorting options.
  - Added responsive product grid with images, prices, sale badges, and add-to-cart buttons.
  - Included newsletter signup and mobile app promotion sections.
  - Enhanced navigation with breadcrumbs, sidebar filters, and structured footer with useful links and social media icons.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/pages/bloemenwinkel-productpagina.vue b/pages/bloemenwinkel-productpagina.vue
new file mode 100644
index 0000000..c6dc099
--- /dev/null
+++ b/pages/bloemenwinkel-productpagina.vue
@@ -0,0 +1,855 @@
+<template>
+  <div class="bloemenwinkel-product-page">
+    <!-- Header -->
+    <header class="bg-white shadow-sm">
+      <div class="container mx-auto px-4 py-4">
+        <div class="flex flex-col md:flex-row items-center justify-between">
+          <!-- Logo -->
+          <div class="logo flex items-center mb-4 md:mb-0">
+            <div class="flex flex-col items-center md:items-start">
+              <div class="flex items-center">
+                <div class="w-6 h-6 bg-[#a02279] mr-1"></div>
+                <span class="text-[#2d5741] text-3xl font-bold"
+                  ><a href="/bloemenwinkel">Bloemenwinkel</a></span
+                >
+              </div>
+              <span class="text-[#2d5741] text-sm"
+                >tuincentrum vol groene ideeën</span
+              >
+            </div>
+          </div>
+
+          <!-- Search Bar -->
+          <div class="search-bar w-full md:w-1/3 mb-4 md:mb-0">
+            <div class="relative">
+              <input
+                type="text"
+                placeholder="Waar ben je naar op zoek?"
+                class="w-full py-2 px-4 border border-gray-300 rounded-full focus:outline-none focus:ring-1 focus:ring-[#2d5741]"
+                disabled
+              />
+              <div class="absolute right-3 top-1/2 transform -translate-y-1/2">
+                <span class="text-gray-400">zoek</span>
+              </div>
+            </div>
+          </div>
+
+          <!-- User Actions -->
+          <div class="user-actions flex items-center space-x-6">
+            <div class="relative">
+              <span class="text-gray-600">❤️</span>
+            </div>
+            <div class="relative">
+              <span class="text-gray-600">🛒</span>
+            </div>
+          </div>
+        </div>
+      </div>
+    </header>
+
+    <!-- Main Navigation -->
+    <nav class="bg-white border-t border-b border-gray-200">
+      <div class="container mx-auto px-4">
+        <ul
+          class="flex flex-wrap items-center justify-between md:justify-start"
+        >
+          <li class="py-4 px-2 md:px-4 relative group">
+            <div class="flex items-center text-[#2d5741] font-medium">
+              Assortiment
+              <span class="ml-1">▼</span>
+            </div>
+          </li>
+        </ul>
+      </div>
+    </nav>
+
+    <!-- Breadcrumbs -->
+    <div class="bg-gray-100 py-2">
+      <div class="container mx-auto px-4">
+        <div class="flex items-center text-sm text-gray-500">
+          <div class="hover:text-[#2d5741]">Home</div>
+          <ChevronRightIcon class="h-3 w-3 mx-1" />
+          <div class="hover:text-[#2d5741]">Assortiment</div>
+          <ChevronRightIcon class="h-3 w-3 mx-1" />
+          <span class="text-[#2d5741] font-medium">Producten</span>
+        </div>
+      </div>
+    </div>
+
+    <!-- Main Content -->
+    <main class="py-8">
+      <div class="container mx-auto px-4">
+        <div class="flex flex-col lg:flex-row gap-8">
+          <!-- Sidebar Filters -->
+          <div class="lg:w-1/4">
+            <div class="bg-white rounded-lg shadow-sm p-4 mb-6">
+              <h3 class="font-medium text-lg mb-4 text-[#2d5741]">
+                Categorieën
+              </h3>
+              <ul class="space-y-2">
+                <li v-for="category in categories" :key="category">
+                  <div
+                    :class="[
+                      'flex items-center',
+                      selectedCategory === category
+                        ? 'text-[#2d5741] font-medium'
+                        : 'text-gray-600 hover:text-[#2d5741]',
+                    ]"
+                    @click="setCategory(category)"
+                    style="cursor: pointer"
+                  >
+                    <span class="mr-1" v-if="selectedCategory === category"
+                      >▶</span
+                    >
+                    <span class="mr-1 opacity-0" v-else>▶</span>
+                    {{ category }}
+                  </div>
+                </li>
+              </ul>
+            </div>
+
+            <div
+              v-if="showProductTypeFilter"
+              class="bg-white rounded-lg shadow-sm p-4 mb-6"
+            >
+              <h3 class="font-medium text-lg mb-4 text-[#2d5741]">
+                Product type
+              </h3>
+              <ul class="space-y-2">
+                <li v-for="subcat in availableSubcategories" :key="subcat.name">
+                  <label class="flex items-center cursor-pointer">
+                    <input
+                      type="checkbox"
+                      class="form-checkbox text-[#2d5741] rounded mr-2"
+                      :checked="selectedSubcategories.includes(subcat.name)"
+                      @change="toggleSubcategory(subcat.name)"
+                    />
+                    <span>{{ subcat.name }} ({{ subcat.count }})</span>
+                  </label>
+                </li>
+              </ul>
+            </div>
+          </div>
+          <!-- Product Listing -->
+          <div class="lg:w-3/4">
+            <div class="mb-6">
+              <h1 class="text-3xl font-bold text-[#2d5741] mb-2">Producten</h1>
+              <p class="text-gray-600">Bekijk ons uitgebreide assortiment</p>
+            </div>
+
+            <!-- Sorting and Filters -->
+            <div
+              class="flex flex-wrap justify-between items-center bg-white p-4 rounded-lg shadow-sm mb-6"
+            >
+              <div class="flex items-center mb-2 md:mb-0">
+                <span class="text-sm text-gray-600 mr-2">Sorteer op:</span>
+                <select
+                  class="border border-gray-300 rounded px-2 py-1 text-sm"
+                  @change="updateSortOption"
+                >
+                  <option value="populariteit">Populariteit</option>
+                  <option value="price-asc">Prijs: laag naar hoog</option>
+                  <option value="price-desc">Prijs: hoog naar laag</option>
+                  <option value="name">Nieuwste eerst</option>
+                </select>
+              </div>
+            </div>
+
+            <!-- Products Grid -->
+            <div
+              class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"
+            >
+              <!-- Dynamic Products -->
+              <div
+                v-for="product in filteredProducts"
+                :key="product.id"
+                class="bg-white rounded-lg shadow-sm overflow-hidden"
+              >
+                <div class="relative">
+                  <img
+                    :src="product.image"
+                    :alt="product.name"
+                    class="w-full h-48 object-cover"
+                  />
+                  <button class="absolute top-2 right-2 z-10">
+                    <span class="text-gray-400">❤️</span>
+                  </button>
+                  <div
+                    v-if="product.sale"
+                    class="absolute top-2 left-2 bg-[#e4004f] text-white text-xs px-2 py-1 rounded-full"
+                  >
+                    Aanbieding
+                  </div>
+                </div>
+                <div class="p-3">
+                  <h3 class="text-[#2d5741] font-medium text-sm mb-1">
+                    {{ product.name }}
+                  </h3>
+                  <div class="flex justify-between items-center">
+                    <div>
+                      <span class="text-[#e4004f] font-bold">{{
+                        product.price.toFixed(2).replace(".", ",")
+                      }}</span>
+                      <span
+                        v-if="product.originalPrice"
+                        class="text-gray-400 text-xs line-through ml-1"
+                        >{{
+                          product.originalPrice.toFixed(2).replace(".", ",")
+                        }}</span
+                      >
+                    </div>
+                    <button class="bg-[#2d5741] text-white rounded-full p-1">
+                      <span class="text-sm">🛒</span>
+                    </button>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </main>
+
+    <!-- Newsletter -->
+    <section class="py-8 bg-[#f0f5f0]">
+      <div class="container mx-auto px-4">
+        <div
+          class="flex flex-col md:flex-row items-center justify-between gap-6 bg-white p-6 rounded-lg shadow-sm"
+        >
+          <div>
+            <h2 class="text-xl font-bold text-[#2d5741] mb-2">
+              Wees welkomen voor onze gratis prijsvragen!
+            </h2>
+            <p class="text-gray-600">
+              Schrijf je in voor onze nieuwsbrief en ontvang exclusieve
+              aanbiedingen en tuintips.
+            </p>
+          </div>
+          <div class="flex flex-col sm:flex-row gap-2">
+            <input
+              type="email"
+              placeholder="Je e-mailadres"
+              class="flex-grow py-2 px-4 border border-gray-300 rounded-full focus:outline-none focus:ring-1 focus:ring-[#2d5741]"
+            />
+            <button
+              class="bg-[#2d5741] text-white py-2 px-6 rounded-full hover:bg-opacity-90 transition-colors"
+            >
+              Aanmelden
+            </button>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- App Promotion -->
+    <section class="py-8">
+      <div class="container mx-auto px-4">
+        <div class="flex flex-col md:flex-row items-center gap-8">
+          <div class="md:w-1/2">
+            <img
+              src="/bloemenwinkel/app.jpg"
+              alt="Mobile app"
+              class="w-full h-auto rounded-lg shadow-lg"
+            />
+          </div>
+          <div class="md:w-1/2">
+            <h2 class="text-[#2d5741] text-2xl font-bold mb-4">
+              Maak het hier een stuk leuker met onze tuincentra groene vingers!
+            </h2>
+            <p class="text-gray-600 mb-6">
+              Krijg je de beste tips en adviezen rechtstreeks op je telefoon.
+              Download onze app en ontdek alle voordelen.
+            </p>
+            <div class="flex gap-4">
+              <button
+                class="bg-black text-white px-6 py-3 rounded-lg flex items-center gap-2"
+              >
+                <AppleIcon class="h-6 w-6" />
+                <div class="text-left">
+                  <span class="text-xs block">Download on the</span>
+                  <span class="font-medium">App Store</span>
+                </div>
+              </button>
+              <button
+                class="bg-black text-white px-6 py-3 rounded-lg flex items-center gap-2"
+              >
+                <SmartphoneIcon class="h-6 w-6" />
+                <div class="text-left">
+                  <span class="text-xs block">GET IT ON</span>
+                  <span class="font-medium">Google Play</span>
+                </div>
+              </button>
+            </div>
+          </div>
+        </div>
+      </div>
+    </section>
+
+    <!-- Footer -->
+    <footer class="bg-[#2d5741] text-white pt-12 pb-6">
+      <div class="container mx-auto px-4">
+        <div class="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8">
+          <!-- Column 1 -->
+          <div>
+            <h3 class="font-bold text-lg mb-4">Locaties bloemenwinkel</h3>
+            <ul class="space-y-2 text-sm">
+              <li><div class="hover:underline">Nuenen</div></li>
+              <li><div class="hover:underline">Valkenswaard</div></li>
+              <li><div class="hover:underline">Helmond</div></li>
+              <li><div class="hover:underline">Eindhoven</div></li>
+            </ul>
+          </div>
+
+          <!-- Column 2 -->
+          <div>
+            <h3 class="font-bold text-lg mb-4">Klantenservice</h3>
+            <ul class="space-y-2 text-sm">
+              <li><div class="hover:underline">Contact</div></li>
+              <li><div class="hover:underline">Veelgestelde vragen</div></li>
+              <li><div class="hover:underline">Bezorging</div></li>
+              <li><div class="hover:underline">Retourneren</div></li>
+              <li><div class="hover:underline">Privacy</div></li>
+              <li><div class="hover:underline">Cookies</div></li>
+            </ul>
+          </div>
+
+          <!-- Column 3 -->
+          <div>
+            <h3 class="font-bold text-lg mb-4">VIPpas</h3>
+            <ul class="space-y-2 text-sm">
+              <li><div class="hover:underline">Voordelen</div></li>
+              <li><div class="hover:underline">Aanvragen</div></li>
+              <li><div class="hover:underline">Voorwaarden</div></li>
+            </ul>
+          </div>
+
+          <!-- Column 4 -->
+          <div>
+            <h3 class="font-bold text-lg mb-4">
+              Blijf op de hoogte van de laatste trends
+            </h3>
+            <div class="flex space-x-3 mb-6">
+              <div class="hover:text-gray-300">
+                <FacebookIcon class="h-6 w-6" />
+              </div>
+              <div class="hover:text-gray-300">
+                <InstagramIcon class="h-6 w-6" />
+              </div>
+              <div class="hover:text-gray-300">
+                <YoutubeIcon class="h-6 w-6" />
+              </div>
+              <div class="hover:text-gray-300">
+                <TwitterIcon class="h-6 w-6" />
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <div class="border-t border-gray-600 pt-6 text-center text-sm">
+          <p>© Bloemenwinkel. Alle rechten voorbehouden.</p>
+        </div>
+      </div>
+    </footer>
+  </div>
+</template>
+
+<script setup>
+definePageMeta({
+  layout: "simulation",
+});
+
+import { ref, computed, onMounted, onUnmounted, watch } from "vue";
+
+// Products data
+const products = ref([
+  {
+    id: 1,
+    name: "Gemengd boeket",
+    price: 24.5,
+    image: "/bloemenwinkel/bloemenwinkel1.jpg",
+    category: "Bloemen",
+    subcategory: "Boeketten",
+  },
+  {
+    id: 2,
+    name: "Roze boeket",
+    price: 19.95,
+    image: "/bloemenwinkel/boeket.jpg",
+    category: "Bloemen",
+    subcategory: "Boeketten",
+  },
+  {
+    id: 3,
+    name: "Kleurrijk boeket",
+    price: 29.95,
+    image: "/bloemenwinkel/bloemenwinkel2.png",
+    category: "Bloemen",
+    subcategory: "Boeketten",
+  },
+  {
+    id: 4,
+    name: "Selectie cactus",
+    price: 4.95,
+    image: "/bloemenwinkel/plant5.jpg",
+    category: "Planten",
+    subcategory: "Snijbloemen",
+  },
+  {
+    id: 5,
+    name: "Cactus in pot",
+    price: 7.95,
+    image: "/bloemenwinkel/plant1.jpg",
+    category: "Planten",
+    subcategory: "Snijbloemen",
+  },
+  {
+    id: 6,
+    name: "Boeket Veronica",
+    price: 19.95,
+    image: "/bloemenwinkel/boeket4.jpg",
+    category: "Bloemen",
+    subcategory: "Boeketten",
+  },
+  {
+    id: 7,
+    name: "Boeket Rasa",
+    price: 22.5,
+    image: "/bloemenwinkel/boeket6.jpg",
+    category: "Bloemen",
+    subcategory: "Boeketten",
+  },
+  {
+    id: 8,
+    name: "Veldboeket",
+    price: 16.95,
+    image: "/bloemenwinkel/boeket3.jpg",
+    category: "Bloemen",
+    subcategory: "Boeketten",
+  },
+  {
+    id: 9,
+    name: "Witte rozen",
+    price: 29.95,
+    image: "/bloemenwinkel/boeket2.jpg",
+    category: "Bloemen",
+    subcategory: "Snijbloemen",
+  },
+  {
+    id: 10,
+    name: "Lelies",
+    price: 19.95,
+    image: "/bloemenwinkel/lillies.jpg",
+    category: "Bloemen",
+    subcategory: "Snijbloemen",
+  },
+  {
+    id: 11,
+    name: "Herfstboeket",
+    price: 24.95,
+    image: "/bloemenwinkel/boeket.jpg",
+    category: "Bloemen",
+    subcategory: "Boeketten",
+  },
+  {
+    id: 12,
+    name: "Rattan lounge set",
+    price: 824.95,
+    image: "/bloemenwinkel/tuinmeubel1.jpg",
+    category: "Tuinmeubelen",
+    subcategory: "Droogbloemen",
+  },
+  {
+    id: 13,
+    name: "Complete tuinset",
+    price: 435.95,
+    image: "/bloemenwinkel/tuinmeubel2.jpg",
+    category: "Tuinmeubelen",
+    subcategory: "Droogbloemen",
+  },
+  {
+    id: 14,
+    name: "Vaas",
+    price: 64.95,
+    image: "/bloemenwinkel/vase.jpg",
+    category: "Potterie",
+    subcategory: "Droogbloemen",
+  },
+  {
+    id: 15,
+    name: "Stoelenset Oslo",
+    price: 73.95,
+    image: "/bloemenwinkel/tuinmeubel.jpg",
+    category: "Tuinmeubelen",
+    subcategory: "Rouwbloemen",
+  },
+  {
+    id: 16,
+    name: "Zonnebloemen",
+    price: 9.99,
+    image: "/bloemenwinkel/boeket5.jpg",
+    category: "Bloemen",
+    subcategory: "Snijbloemen",
+    sale: true,
+    originalPrice: 14.95,
+  },
+]);
+
+// Category and filter states
+const selectedCategory = ref("Alle producten");
+const selectedSubcategories = ref([]);
+const priceRange = ref({ min: 0, max: 1000 });
+const minPrice = ref(0);
+const maxPrice = ref(1000);
+const sortOption = ref("populariteit");
+const isDraggingMin = ref(false);
+const isDraggingMax = ref(false);
+const sliderTrack = ref(null);
+const minHandle = ref(null);
+const maxHandle = ref(null);
+const userHasAdjustedPrice = ref(false);
+const absolutePriceRange = ref({ min: 0, max: 1000 });
+
+// Calculate overall price range across all products
+const calculateAbsolutePriceRange = () => {
+  const min = Math.floor(Math.min(...products.value.map((p) => p.price)));
+  const max = Math.ceil(Math.max(...products.value.map((p) => p.price)));
+  absolutePriceRange.value = { min, max };
+
+  // Initialize price range values if they're at defaults
+  if (priceRange.value.min === 0 && priceRange.value.max === 1000) {
+    priceRange.value.min = min;
+    priceRange.value.max = max;
+    minPrice.value = min;
+    maxPrice.value = max;
+  }
+};
+
+// Calculate price range for current category
+const categoryPriceRange = computed(() => {
+  const categoryProducts = products.value.filter(
+    (product) =>
+      selectedCategory.value === "Alle producten" ||
+      (product.category === selectedCategory.value &&
+        (selectedSubcategories.value.length === 0 ||
+          selectedSubcategories.value.includes(product.subcategory))),
+  );
+
+  if (categoryProducts.length === 0) return absolutePriceRange.value;
+
+  const min = Math.floor(Math.min(...categoryProducts.map((p) => p.price)));
+  const max = Math.ceil(Math.max(...categoryProducts.map((p) => p.price)));
+
+  return { min, max };
+});
+
+// For slider calculations - use fixed range to prevent jumps in the UI
+const sliderBaseRange = computed(() => {
+  // Use the absolute range for slider visualization to prevent UI jumps
+  return absolutePriceRange.value;
+});
+
+// Calculate slider position percentages based on fixed absolute range
+const sliderPositions = computed(() => {
+  const range = sliderBaseRange.value;
+  const totalRange = range.max - range.min;
+
+  // Avoid division by zero
+  if (totalRange === 0) return { minPos: 0, maxPos: 100, width: 100 };
+
+  // Calculate positions based on the fixed absolute range
+  const minPos = ((priceRange.value.min - range.min) / totalRange) * 100;
+  const maxPos = ((priceRange.value.max - range.min) / totalRange) * 100;
+
+  return {
+    minPos: Math.max(0, Math.min(100, minPos)),
+    maxPos: Math.max(0, Math.min(100, maxPos)),
+    width: Math.max(0, maxPos - minPos),
+  };
+});
+
+// Show the current price range in the UI
+const displayMin = computed(() => priceRange.value.min);
+const displayMax = computed(() => priceRange.value.max);
+
+// Products filtered by category and subcategory before price filtering
+const productsBeforePriceFilter = computed(() => {
+  return products.value.filter((product) => {
+    // Show all products when "Alle producten" is selected
+    if (selectedCategory.value === "Alle producten") {
+      return true;
+    }
+
+    // Category filter
+    if (selectedCategory.value && product.category !== selectedCategory.value) {
+      return false;
+    }
+
+    // Subcategory filter
+    if (
+      selectedSubcategories.value.length > 0 &&
+      !selectedSubcategories.value.includes(product.subcategory)
+    ) {
+      return false;
+    }
+
+    return true;
+  });
+});
+
+// Filter products with price filtering
+const filteredProducts = computed(() => {
+  let filtered = productsBeforePriceFilter.value.filter((product) => {
+    // Price range filter - always apply price filter
+    if (
+      product.price < priceRange.value.min ||
+      product.price > priceRange.value.max
+    ) {
+      return false;
+    }
+
+    return true;
+  });
+
+  // Apply sorting
+  switch (sortOption.value) {
+    case "price-asc":
+      filtered.sort((a, b) => a.price - b.price);
+      break;
+    case "price-desc":
+      filtered.sort((a, b) => b.price - a.price);
+      break;
+    case "name":
+      filtered.sort((a, b) => a.name.localeCompare(b.name));
+      break;
+    case "populariteit":
+    default:
+      // Default sorting (already as defined in the products array)
+      break;
+  }
+
+  return filtered;
+});
+
+// Watch for category changes to reset price range
+watch(selectedCategory, () => {
+  if (!userHasAdjustedPrice.value) {
+    resetPriceRange();
+  }
+});
+
+// Set category with fixed adjustment to price range
+const setCategory = (category) => {
+  selectedCategory.value = category;
+
+  // Only reset price range if user hasn't adjusted manually
+  if (!userHasAdjustedPrice.value) {
+    resetPriceRange();
+  }
+};
+
+// Update price range from category
+const resetPriceRange = () => {
+  if (categoryPriceRange.value) {
+    const range = categoryPriceRange.value;
+    priceRange.value.min = range.min;
+    priceRange.value.max = range.max;
+    minPrice.value = range.min;
+    maxPrice.value = range.max;
+  }
+};
+
+// Toggle subcategory
+const toggleSubcategory = (subcategory) => {
+  const index = selectedSubcategories.value.indexOf(subcategory);
+  if (index === -1) {
+    selectedSubcategories.value.push(subcategory);
+  } else {
+    selectedSubcategories.value.splice(index, 1);
+  }
+
+  // If user hasn't manually adjusted price, update to match new category range
+  if (!userHasAdjustedPrice.value) {
+    resetPriceRange();
+  }
+};
+
+// Initialize on mounted
+onMounted(() => {
+  calculateAbsolutePriceRange();
+  resetPriceRange();
+
+  const slider = document.querySelector('div[ref="sliderEl"]');
+  if (slider) {
+    sliderTrack.value = {
+      width: slider.clientWidth,
+      left: slider.getBoundingClientRect().left,
+    };
+  }
+});
+
+// Slider drag events
+const startDragMin = (e) => {
+  e.preventDefault();
+  userHasAdjustedPrice.value = true;
+  isDraggingMin.value = true;
+  document.addEventListener("mousemove", onMouseMove);
+  document.addEventListener("mouseup", stopDrag);
+};
+
+const startDragMax = (e) => {
+  e.preventDefault();
+  userHasAdjustedPrice.value = true;
+  isDraggingMax.value = true;
+  document.addEventListener("mousemove", onMouseMove);
+  document.addEventListener("mouseup", stopDrag);
+};
+
+const stopDrag = () => {
+  isDraggingMin.value = false;
+  isDraggingMax.value = false;
+  document.removeEventListener("mousemove", onMouseMove);
+  document.removeEventListener("mouseup", stopDrag);
+  updatePriceRange();
+};
+
+// Mouse move handler for slider
+const onMouseMove = (e) => {
+  if (!isDraggingMin.value && !isDraggingMax.value) return;
+
+  if (!sliderTrack.value) {
+    // Get the slider track element for position calculations
+    const slider =
+      document.querySelector('div[ref="sliderEl"]') ||
+      minHandle.value.parentElement;
+    sliderTrack.value = {
+      width: slider.clientWidth,
+      left: slider.getBoundingClientRect().left,
+    };
+  }
+
+  // Calculate relative position (0-1)
+  let relativePosition =
+    (e.clientX - sliderTrack.value.left) / sliderTrack.value.width;
+
+  // Ensure it's within 0-1 range
+  relativePosition = Math.max(0, Math.min(1, relativePosition));
+
+  // Convert to price value based on fixed range
+  const range = sliderBaseRange.value;
+  const priceValue = Math.round(
+    range.min + relativePosition * (range.max - range.min),
+  );
+
+  if (isDraggingMin.value) {
+    // Don't let min exceed max
+    const newMin = Math.min(priceValue, priceRange.value.max - 1);
+    minPrice.value = newMin;
+    priceRange.value.min = newMin;
+  } else if (isDraggingMax.value) {
+    // Don't let max go below min
+    const newMax = Math.max(priceValue, priceRange.value.min + 1);
+    maxPrice.value = newMax;
+    priceRange.value.max = newMax;
+  }
+
+  // Always mark as user adjusted when dragging
+  userHasAdjustedPrice.value = true;
+};
+
+// Clean up event listeners when component is unmounted
+onUnmounted(() => {
+  document.removeEventListener("mousemove", onMouseMove);
+  document.removeEventListener("mouseup", stopDrag);
+});
+
+// Update price range gets input values and updates the model
+const updatePriceRange = () => {
+  userHasAdjustedPrice.value = true;
+  priceRange.value.min =
+    parseFloat(minPrice.value) || categoryPriceRange.value.min;
+  priceRange.value.max =
+    parseFloat(maxPrice.value) || categoryPriceRange.value.max;
+};
+
+// Update sort option
+const updateSortOption = (e) => {
+  sortOption.value = e.target.value;
+};
+
+// Available categories
+const categories = [
+  "Alle producten",
+  "Bloemen",
+  "Planten",
+  "Potterie",
+  "Tuinmeubelen",
+];
+
+// Available subcategories
+const subcategories = [
+  { name: "Boeketten", count: 7 },
+  { name: "Snijbloemen", count: 5 },
+  { name: "Rouwbloemen", count: 2 },
+  { name: "Droogbloemen", count: 3 },
+];
+
+// Reset filters
+const resetFilters = () => {
+  resetPriceRange();
+  userHasAdjustedPrice.value = false;
+};
+
+// Available subcategories based on current category selection
+const availableSubcategories = computed(() => {
+  if (selectedCategory.value === "Alle producten") {
+    // Show all subcategories for "Alle producten"
+    return subcategories;
+  }
+
+  // Get all subcategories that exist in the current category
+  const subCatsInCategory = products.value
+    .filter((p) => p.category === selectedCategory.value)
+    .map((p) => p.subcategory);
+
+  // Get unique subcategories
+  const uniqueSubCats = [...new Set(subCatsInCategory)];
+
+  // Return only subcategories that exist in the current category with their counts
+  return subcategories
+    .filter((sc) => uniqueSubCats.includes(sc.name))
+    .map((sc) => ({
+      ...sc,
+      count: products.value.filter(
+        (p) =>
+          p.category === selectedCategory.value && p.subcategory === sc.name,
+      ).length,
+    }));
+});
+
+// Determine if product type filter should be shown
+const showProductTypeFilter = computed(() => {
+  return availableSubcategories.value.length > 0;
+});
+</script>
+
+<style scoped>
+/* Custom styles */
+.bloemenwinkel-product-page {
+  font-family: "Arial", sans-serif;
+}
+
+/* Hide scrollbar for the carousels */
+.flex.overflow-x-auto {
+  scrollbar-width: none; /* Firefox */
+  -ms-overflow-style: none; /* IE and Edge */
+}
+
+.flex.overflow-x-auto::-webkit-scrollbar {
+  display: none; /* Chrome, Safari, Opera */
+}
+
+/* Custom checkbox styling */
+.form-checkbox {
+  color: #2d5741;
+}
+</style>
diff --git a/public/bloemenwinkel/boeket2.jpg b/public/bloemenwinkel/boeket2.jpg
new file mode 100644
index 0000000..5a193cd
Binary files /dev/null and b/public/bloemenwinkel/boeket2.jpg differ
diff --git a/public/bloemenwinkel/boeket3.jpg b/public/bloemenwinkel/boeket3.jpg
new file mode 100644
index 0000000..f12503c
Binary files /dev/null and b/public/bloemenwinkel/boeket3.jpg differ
diff --git a/public/bloemenwinkel/boeket4.jpg b/public/bloemenwinkel/boeket4.jpg
new file mode 100644
index 0000000..69d0ac9
Binary files /dev/null and b/public/bloemenwinkel/boeket4.jpg differ
diff --git a/public/bloemenwinkel/boeket5.jpg b/public/bloemenwinkel/boeket5.jpg
new file mode 100644
index 0000000..927bb03
Binary files /dev/null and b/public/bloemenwinkel/boeket5.jpg differ
diff --git a/public/bloemenwinkel/boeket6.jpg b/public/bloemenwinkel/boeket6.jpg
new file mode 100644
index 0000000..c31237c
Binary files /dev/null and b/public/bloemenwinkel/boeket6.jpg differ
diff --git a/public/bloemenwinkel/lillies.jpg b/public/bloemenwinkel/lillies.jpg
new file mode 100644
index 0000000..7447633
Binary files /dev/null and b/public/bloemenwinkel/lillies.jpg differ
diff --git a/public/bloemenwinkel/tuinmeubel1.jpg b/public/bloemenwinkel/tuinmeubel1.jpg
new file mode 100644
index 0000000..23dbb91
Binary files /dev/null and b/public/bloemenwinkel/tuinmeubel1.jpg differ


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 3**

<details>
<summary>🧹 Nitpick comments (2)</summary><blockquote>

<details>
<summary>pages/bloemenwinkel-productpagina.vue (2)</summary><blockquote>

`594-598`: **`parseFloat` on numbers is redundant**

`minPrice.value` and `maxPrice.value` are already numbers. Parsing can be dropped to avoid unnecessary coercion.

```diff
-priceRange.value.min = parseFloat(minPrice.value) || categoryPriceRange.value.min;
-priceRange.value.max = parseFloat(maxPrice.value) || categoryPriceRange.value.max;
+priceRange.value.min = minPrice.value || categoryPriceRange.value.min;
+priceRange.value.max = maxPrice.value || categoryPriceRange.value.max;
```

---

`622-627`: **`resetFilters()` is declared but never used**

Either wire it up with a “Reset filters” button/CTA or remove the dead code to keep the component lean.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 37b81f69a4d35b61f67b3343d7216f5db5ea7f8f and 7b8e40df539392c31c2c60dc06890821955a3fa7.

</details>

<details>
<summary>⛔ Files ignored due to path filters (7)</summary>

* `public/bloemenwinkel/boeket2.jpg` is excluded by `!**/*.jpg`
* `public/bloemenwinkel/boeket3.jpg` is excluded by `!**/*.jpg`
* `public/bloemenwinkel/boeket4.jpg` is excluded by `!**/*.jpg`
* `public/bloemenwinkel/boeket5.jpg` is excluded by `!**/*.jpg`
* `public/bloemenwinkel/boeket6.jpg` is excluded by `!**/*.jpg`
* `public/bloemenwinkel/lillies.jpg` is excluded by `!**/*.jpg`
* `public/bloemenwinkel/tuinmeubel1.jpg` is excluded by `!**/*.jpg`

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `pages/bloemenwinkel-productpagina.vue` (1 hunks)

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>pages/bloemenwinkel-productpagina.vue (2)</summary>

`514-559`: **Slider logic references DOM that is never rendered**

`document.querySelector('div[ref="sliderEl"]')`, `minHandle`, and `maxHandle` are used, yet no element in the template carries those `ref`s or handles. As a result:

* Drag events never bind to anything.
* `sliderTrack` dimensions may be `null`, breaking calculations.

Minimum fix:

```html
<!-- inside the filters card -->
<div ref="sliderEl" class="relative h-2 bg-gray-200 rounded mb-4">
  <div
    class="absolute bg-[#2d5741] h-2 rounded"
    :style="{ left: sliderPositions.minPos + '%', width: sliderPositions.width + '%' }"
  />
  <div
    ref="minHandle"
    class="absolute w-4 h-4 bg-white border border-[#2d5741] rounded-full cursor-pointer -top-1"
    :style="{ left: sliderPositions.minPos + '%' }"
    @mousedown="startDragMin"
  />
  <div
    ref="maxHandle"
    class="absolute w-4 h-4 bg-white border border-[#2d5741] rounded-full cursor-pointer -top-1"
    :style="{ left: sliderPositions.maxPos + '%' }"
    @mousedown="startDragMax"
  />
</div>
```

[ suggest_essential_refactor ]

---

`139-143`: **Sorting label ↔︎ implementation mismatch**

The option text “Nieuwste eerst” suggests date-based sorting, but the code sorts alphabetically by `name`. Either rename the label (e.g. “Alfabetisch”) or add a `createdAt` property to products and sort on that.




Also applies to: 447-456

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-12T10:20:48Z

Review comments:
diff_hunk: @@ -0,0 +1,680 @@
+<template>
+    <div class="bloemenwinkel-product-page">
+      <!-- Header -->
+    <header class="bg-white shadow-sm">
+      <div class="container mx-auto px-4 py-4">
+        <div class="flex flex-col md:flex-row items-center justify-between">
+          <!-- Logo -->
+          <div class="logo flex items-center mb-4 md:mb-0">
+            <div class="flex flex-col items-center md:items-start">
+              <div class="flex items-center">
+                <div class="w-6 h-6 bg-[#a02279] mr-1"></div>
+                <span class="text-[#2d5741] text-3xl font-bold"
+                  ><a href="/bloemenwinkel">Bloemenwinkel</a></span
+                >
+              </div>
+              <span class="text-[#2d5741] text-sm"
+                >tuincentrum vol groene ideeën</span
+              >
+            </div>
+          </div>
+
+          <!-- Search Bar -->
+          <div class="search-bar w-full md:w-1/3 mb-4 md:mb-0">
+            <div class="relative">
+              <input
+                type="text"
+                placeholder="Waar ben je naar op zoek?"
+                class="w-full py-2 px-4 border border-gray-300 rounded-full focus:outline-none focus:ring-1 focus:ring-[#2d5741]"
+                disabled
+              />
+              <div
+                class="absolute right-3 top-1/2 transform -translate-y-1/2"
+              >
+                <span class="text-gray-400">zoek</span>
+              </div>
+            </div>
+          </div>
+            
+            <!-- User Actions -->
+          <div class="user-actions flex items-center space-x-6">
+            
+            <div class="relative">
+              <span class="text-gray-600">❤️</span>
+            </div>
+            <div class="relative">
+              <span class="text-gray-600">🛒</span>
+            </div>
+          </div>
+        </div>
+      </div>
+      </header>
+      
+      <!-- Main Navigation -->
+    <nav class="bg-white border-t border-b border-gray-200">
+      <div class="container mx-auto px-4">
+        <ul
+          class="flex flex-wrap items-center justify-between md:justify-start"
+        >
+          <li class="py-4 px-2 md:px-4 relative group">
+            <div
+              class="flex items-center text-[#2d5741] font-medium"
+            >
+              Assortiment
+              <span class="ml-1">▼</span>
+            </div>
+          </li>
+        </ul>
+      </div>
+    </nav>
+      
+      <!-- Breadcrumbs -->
+      <div class="bg-gray-100 py-2">
+        <div class="container mx-auto px-4">
+          <div class="flex items-center text-sm text-gray-500">
+            <div class="hover:text-[#2d5741]">Home</div>
+            <ChevronRightIcon class="h-3 w-3 mx-1" />
+            <div class="hover:text-[#2d5741]">Assortiment</div>
+            <ChevronRightIcon class="h-3 w-3 mx-1" />
+            <span class="text-[#2d5741] font-medium">Producten</span>
+          </div>
+        </div>
+      </div>
+      
+      <!-- Main Content -->
+      <main class="py-8">
+        <div class="container mx-auto px-4">
+          <div class="flex flex-col lg:flex-row gap-8">
+            <!-- Sidebar Filters -->
+            <div class="lg:w-1/4">
+              <div class="bg-white rounded-lg shadow-sm p-4 mb-6">
+                <h3 class="font-medium text-lg mb-4 text-[#2d5741]">Categorieën</h3>
+                <ul class="space-y-2">
+                  <li v-for="category in categories" :key="category">
+                    <div 
+                      :class="[
+                        'flex items-center', 
+                        selectedCategory === category ? 'text-[#2d5741] font-medium' : 'text-gray-600 hover:text-[#2d5741]'
+                      ]"
+                      @click="setCategory(category)"
+                      style="cursor: pointer;"
+                    >
+                      <span class="mr-1" v-if="selectedCategory === category">▶</span>
+                      <span class="mr-1 opacity-0" v-else>▶</span>
+                      {{ category }}
+                    </div>
+                  </li>
+                </ul>
+              </div>
+                
+              <div v-if="showProductTypeFilter" class="bg-white rounded-lg shadow-sm p-4 mb-6">
+                <h3 class="font-medium text-lg mb-4 text-[#2d5741]">Product type</h3>
+                <ul class="space-y-2">
+                  <li v-for="subcat in availableSubcategories" :key="subcat.name">
+                    <label class="flex items-center cursor-pointer">
+                      <input 
+                        type="checkbox" 
+                        class="form-checkbox text-[#2d5741] rounded mr-2" 
+                        :checked="selectedSubcategories.includes(subcat.name)"
+                        @change="toggleSubcategory(subcat.name)"
+                      />
+                      <span>{{ subcat.name }} ({{ subcat.count }})</span>
+                    </label>
+                  </li>
+                </ul>
+              </div>
+              </div>
+            <!-- Product Listing -->
+            <div class="lg:w-3/4">
+              <div class="mb-6">
+                <h1 class="text-3xl font-bold text-[#2d5741] mb-2">Producten</h1>
+                <p class="text-gray-600">Bekijk ons uitgebreide assortiment</p>
+              </div>
+              
+              <!-- Sorting and Filters -->
+              <div class="flex flex-wrap justify-between items-center bg-white p-4 rounded-lg shadow-sm mb-6">
+                <div class="flex items-center mb-2 md:mb-0">
+                  <span class="text-sm text-gray-600 mr-2">Sorteer op:</span>
+                  <select class="border border-gray-300 rounded px-2 py-1 text-sm" @change="updateSortOption">
+                    <option value="populariteit">Populariteit</option>
+                    <option value="price-asc">Prijs: laag naar hoog</option>
+                    <option value="price-desc">Prijs: hoog naar laag</option>
+                    <option value="name">Nieuwste eerst</option>
+                  </select>
+                </div>
+              </div>
+              
+              <!-- Products Grid -->
+              <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
+                <!-- Dynamic Products -->
+                <div v-for="product in filteredProducts" :key="product.id" class="bg-white rounded-lg shadow-sm overflow-hidden">
+                  <div class="relative">
+                    <img 
+                      :src="product.image" 
+                      :alt="product.name" 
+                      class="w-full h-48 object-cover"
+                    />
+                    <button class="absolute top-2 right-2 z-10">
+                      <span class="text-gray-400">❤️</span>
+                    </button>
+                    <div v-if="product.sale" class="absolute top-2 left-2 bg-[#e4004f] text-white text-xs px-2 py-1 rounded-full">
+                      Aanbieding
+                    </div>
+                  </div>
+                  <div class="p-3">
+                    <h3 class="text-[#2d5741] font-medium text-sm mb-1">{{ product.name }}</h3>
+                    <div class="flex justify-between items-center">
+                      <div>
+                        <span class="text-[#e4004f] font-bold">{{ product.price.toFixed(2).replace('.', ',') }}</span>
+                        <span v-if="product.originalPrice" class="text-gray-400 text-xs line-through ml-1">{{ product.originalPrice.toFixed(2).replace('.', ',') }}</span>
+                      </div>
+                      <button class="bg-[#2d5741] text-white rounded-full p-1">
+                        <span class="text-sm">🛒</span>
+                      </button>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </main>
+      
+      <!-- Newsletter -->
+      <section class="py-8 bg-[#f0f5f0]">
+        <div class="container mx-auto px-4">
+          <div class="flex flex-col md:flex-row items-center justify-between gap-6 bg-white p-6 rounded-lg shadow-sm">
+            <div>
+              <h2 class="text-xl font-bold text-[#2d5741] mb-2">Wees welkomen voor onze gratis prijsvragen!</h2>
+              <p class="text-gray-600">Schrijf je in voor onze nieuwsbrief en ontvang exclusieve aanbiedingen en tuintips.</p>
+            </div>
+            <div class="flex flex-col sm:flex-row gap-2">
+              <input 
+                type="email" 
+                placeholder="Je e-mailadres" 
+                class="flex-grow py-2 px-4 border border-gray-300 rounded-full focus:outline-none focus:ring-1 focus:ring-[#2d5741]"
+              />
+              <button class="bg-[#2d5741] text-white py-2 px-6 rounded-full hover:bg-opacity-90 transition-colors">
+                Aanmelden
+              </button>
+            </div>
+          </div>
+        </div>
+      </section>
+      
+      <!-- App Promotion -->
+      <section class="py-8">
+        <div class="container mx-auto px-4">
+          <div class="flex flex-col md:flex-row items-center gap-8">
+            <div class="md:w-1/2">
+              <img 
+                src="/bloemenwinkel/app.jpg" 
+                alt="Mobile app" 
+                class="w-full h-auto rounded-lg shadow-lg"
+              />
+            </div>
+            <div class="md:w-1/2">
+              <h2 class="text-[#2d5741] text-2xl font-bold mb-4">
+                Maak het hier een stuk leuker met onze tuincentra groene vingers!
+              </h2>
+              <p class="text-gray-600 mb-6">
+                Krijg je de beste tips en adviezen rechtstreeks op je telefoon. Download onze app en ontdek alle voordelen.
+              </p>
+              <div class="flex gap-4">
+                <button class="bg-black text-white px-6 py-3 rounded-lg flex items-center gap-2">
+                  <AppleIcon class="h-6 w-6" />
+                  <div class="text-left">
+                    <span class="text-xs block">Download on the</span>
+                    <span class="font-medium">App Store</span>
+                  </div>
+                </button>
+                <button class="bg-black text-white px-6 py-3 rounded-lg flex items-center gap-2">
+                  <SmartphoneIcon class="h-6 w-6" />
+                  <div class="text-left">
path: pages/bloemenwinkel-productpagina.vue
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**`AppleIcon` and `SmartphoneIcon` are undefined**

These two components do not exist in Heroicons. Either:

1. Swap them for icons that do exist in the chosen icon set, or  
2. Install another package (e.g. `oh-vue-icons`, `vue-feather-icons`, etc.) and import the correct symbols.

Compilation will fail until this is resolved.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-12T10:20:47Z
author_association: NONE
diff_hunk: @@ -0,0 +1,680 @@
+<template>
+    <div class="bloemenwinkel-product-page">
+      <!-- Header -->
+    <header class="bg-white shadow-sm">
+      <div class="container mx-auto px-4 py-4">
+        <div class="flex flex-col md:flex-row items-center justify-between">
+          <!-- Logo -->
+          <div class="logo flex items-center mb-4 md:mb-0">
+            <div class="flex flex-col items-center md:items-start">
+              <div class="flex items-center">
+                <div class="w-6 h-6 bg-[#a02279] mr-1"></div>
+                <span class="text-[#2d5741] text-3xl font-bold"
+                  ><a href="/bloemenwinkel">Bloemenwinkel</a></span
+                >
+              </div>
+              <span class="text-[#2d5741] text-sm"
+                >tuincentrum vol groene ideeën</span
+              >
+            </div>
+          </div>
+
+          <!-- Search Bar -->
+          <div class="search-bar w-full md:w-1/3 mb-4 md:mb-0">
+            <div class="relative">
+              <input
+                type="text"
+                placeholder="Waar ben je naar op zoek?"
+                class="w-full py-2 px-4 border border-gray-300 rounded-full focus:outline-none focus:ring-1 focus:ring-[#2d5741]"
+                disabled
+              />
+              <div
+                class="absolute right-3 top-1/2 transform -translate-y-1/2"
+              >
+                <span class="text-gray-400">zoek</span>
+              </div>
+            </div>
+          </div>
+            
+            <!-- User Actions -->
+          <div class="user-actions flex items-center space-x-6">
+            
+            <div class="relative">
+              <span class="text-gray-600">❤️</span>
+            </div>
+            <div class="relative">
+              <span class="text-gray-600">🛒</span>
+            </div>
+          </div>
+        </div>
+      </div>
+      </header>
+      
+      <!-- Main Navigation -->
+    <nav class="bg-white border-t border-b border-gray-200">
+      <div class="container mx-auto px-4">
+        <ul
+          class="flex flex-wrap items-center justify-between md:justify-start"
+        >
+          <li class="py-4 px-2 md:px-4 relative group">
+            <div
+              class="flex items-center text-[#2d5741] font-medium"
+            >
+              Assortiment
+              <span class="ml-1">▼</span>
+            </div>
+          </li>
+        </ul>
+      </div>
+    </nav>
+      
+      <!-- Breadcrumbs -->
+      <div class="bg-gray-100 py-2">
+        <div class="container mx-auto px-4">
+          <div class="flex items-center text-sm text-gray-500">
+            <div class="hover:text-[#2d5741]">Home</div>
+            <ChevronRightIcon class="h-3 w-3 mx-1" />
+            <div class="hover:text-[#2d5741]">Assortiment</div>
+            <ChevronRightIcon class="h-3 w-3 mx-1" />
+            <span class="text-[#2d5741] font-medium">Producten</span>
+          </div>
+        </div>
+      </div>
+      
+      <!-- Main Content -->
+      <main class="py-8">
+        <div class="container mx-auto px-4">
+          <div class="flex flex-col lg:flex-row gap-8">
+            <!-- Sidebar Filters -->
+            <div class="lg:w-1/4">
+              <div class="bg-white rounded-lg shadow-sm p-4 mb-6">
+                <h3 class="font-medium text-lg mb-4 text-[#2d5741]">Categorieën</h3>
+                <ul class="space-y-2">
+                  <li v-for="category in categories" :key="category">
+                    <div 
+                      :class="[
+                        'flex items-center', 
+                        selectedCategory === category ? 'text-[#2d5741] font-medium' : 'text-gray-600 hover:text-[#2d5741]'
+                      ]"
+                      @click="setCategory(category)"
+                      style="cursor: pointer;"
+                    >
+                      <span class="mr-1" v-if="selectedCategory === category">▶</span>
+                      <span class="mr-1 opacity-0" v-else>▶</span>
+                      {{ category }}
+                    </div>
+                  </li>
+                </ul>
+              </div>
+                
+              <div v-if="showProductTypeFilter" class="bg-white rounded-lg shadow-sm p-4 mb-6">
+                <h3 class="font-medium text-lg mb-4 text-[#2d5741]">Product type</h3>
+                <ul class="space-y-2">
+                  <li v-for="subcat in availableSubcategories" :key="subcat.name">
+                    <label class="flex items-center cursor-pointer">
+                      <input 
+                        type="checkbox" 
+                        class="form-checkbox text-[#2d5741] rounded mr-2" 
+                        :checked="selectedSubcategories.includes(subcat.name)"
+                        @change="toggleSubcategory(subcat.name)"
+                      />
+                      <span>{{ subcat.name }} ({{ subcat.count }})</span>
+                    </label>
+                  </li>
+                </ul>
+              </div>
+              </div>
+            <!-- Product Listing -->
+            <div class="lg:w-3/4">
+              <div class="mb-6">
+                <h1 class="text-3xl font-bold text-[#2d5741] mb-2">Producten</h1>
+                <p class="text-gray-600">Bekijk ons uitgebreide assortiment</p>
+              </div>
+              
+              <!-- Sorting and Filters -->
+              <div class="flex flex-wrap justify-between items-center bg-white p-4 rounded-lg shadow-sm mb-6">
+                <div class="flex items-center mb-2 md:mb-0">
+                  <span class="text-sm text-gray-600 mr-2">Sorteer op:</span>
+                  <select class="border border-gray-300 rounded px-2 py-1 text-sm" @change="updateSortOption">
+                    <option value="populariteit">Populariteit</option>
+                    <option value="price-asc">Prijs: laag naar hoog</option>
+                    <option value="price-desc">Prijs: hoog naar laag</option>
+                    <option value="name">Nieuwste eerst</option>
+                  </select>
+                </div>
+              </div>
+              
+              <!-- Products Grid -->
+              <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
+                <!-- Dynamic Products -->
+                <div v-for="product in filteredProducts" :key="product.id" class="bg-white rounded-lg shadow-sm overflow-hidden">
+                  <div class="relative">
+                    <img 
+                      :src="product.image" 
+                      :alt="product.name" 
+                      class="w-full h-48 object-cover"
+                    />
+                    <button class="absolute top-2 right-2 z-10">
+                      <span class="text-gray-400">❤️</span>
+                    </button>
+                    <div v-if="product.sale" class="absolute top-2 left-2 bg-[#e4004f] text-white text-xs px-2 py-1 rounded-full">
+                      Aanbieding
+                    </div>
+                  </div>
+                  <div class="p-3">
+                    <h3 class="text-[#2d5741] font-medium text-sm mb-1">{{ product.name }}</h3>
+                    <div class="flex justify-between items-center">
+                      <div>
+                        <span class="text-[#e4004f] font-bold">{{ product.price.toFixed(2).replace('.', ',') }}</span>
+                        <span v-if="product.originalPrice" class="text-gray-400 text-xs line-through ml-1">{{ product.originalPrice.toFixed(2).replace('.', ',') }}</span>
+                      </div>
+                      <button class="bg-[#2d5741] text-white rounded-full p-1">
+                        <span class="text-sm">🛒</span>
+                      </button>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </main>
+      
+      <!-- Newsletter -->
+      <section class="py-8 bg-[#f0f5f0]">
+        <div class="container mx-auto px-4">
+          <div class="flex flex-col md:flex-row items-center justify-between gap-6 bg-white p-6 rounded-lg shadow-sm">
+            <div>
+              <h2 class="text-xl font-bold text-[#2d5741] mb-2">Wees welkomen voor onze gratis prijsvragen!</h2>
+              <p class="text-gray-600">Schrijf je in voor onze nieuwsbrief en ontvang exclusieve aanbiedingen en tuintips.</p>
+            </div>
+            <div class="flex flex-col sm:flex-row gap-2">
+              <input 
+                type="email" 
+                placeholder="Je e-mailadres" 
+                class="flex-grow py-2 px-4 border border-gray-300 rounded-full focus:outline-none focus:ring-1 focus:ring-[#2d5741]"
+              />
+              <button class="bg-[#2d5741] text-white py-2 px-6 rounded-full hover:bg-opacity-90 transition-colors">
+                Aanmelden
+              </button>
+            </div>
+          </div>
+        </div>
+      </section>
+      
+      <!-- App Promotion -->
+      <section class="py-8">
+        <div class="container mx-auto px-4">
+          <div class="flex flex-col md:flex-row items-center gap-8">
+            <div class="md:w-1/2">
+              <img 
+                src="/bloemenwinkel/app.jpg" 
+                alt="Mobile app" 
+                class="w-full h-auto rounded-lg shadow-lg"
+              />
+            </div>
+            <div class="md:w-1/2">
+              <h2 class="text-[#2d5741] text-2xl font-bold mb-4">
+                Maak het hier een stuk leuker met onze tuincentra groene vingers!
+              </h2>
+              <p class="text-gray-600 mb-6">
+                Krijg je de beste tips en adviezen rechtstreeks op je telefoon. Download onze app en ontdek alle voordelen.
+              </p>
+              <div class="flex gap-4">
+                <button class="bg-black text-white px-6 py-3 rounded-lg flex items-center gap-2">
+                  <AppleIcon class="h-6 w-6" />
+                  <div class="text-left">
+                    <span class="text-xs block">Download on the</span>
+                    <span class="font-medium">App Store</span>
+                  </div>
+                </button>
+                <button class="bg-black text-white px-6 py-3 rounded-lg flex items-center gap-2">
+                  <SmartphoneIcon class="h-6 w-6" />
+                  <div class="text-left">
+                    <span class="text-xs block">GET IT ON</span>
+                    <span class="font-medium">Google Play</span>
+                  </div>
+                </button>
+              </div>
+            </div>
+          </div>
+        </div>
+      </section>
+      
+      <!-- Footer -->
+      <footer class="bg-[#2d5741] text-white pt-12 pb-6">
+        <div class="container mx-auto px-4">
+          <div class="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8">
+            <!-- Column 1 -->
+            <div>
+              <h3 class="font-bold text-lg mb-4">Locaties bloemenwinkel</h3>
+              <ul class="space-y-2 text-sm">
+                <li><div class="hover:underline">Nuenen</div></li>
+                <li><div class="hover:underline">Valkenswaard</div></li>
+                <li><div class="hover:underline">Helmond</div></li>
+                <li><div class="hover:underline">Eindhoven</div></li>
+              </ul>
+            </div>
+            
+            <!-- Column 2 -->
+            <div>
+              <h3 class="font-bold text-lg mb-4">Klantenservice</h3>
+              <ul class="space-y-2 text-sm">
+                <li><div class="hover:underline">Contact</div></li>
+                <li><div class="hover:underline">Veelgestelde vragen</div></li>
+                <li><div class="hover:underline">Bezorging</div></li>
+                <li><div class="hover:underline">Retourneren</div></li>
+                <li><div class="hover:underline">Privacy</div></li>
+                <li><div class="hover:underline">Cookies</div></li>
+              </ul>
+            </div>
+            
+            <!-- Column 3 -->
+            <div>
+              <h3 class="font-bold text-lg mb-4">VIPpas</h3>
+              <ul class="space-y-2 text-sm">
+                <li><div class="hover:underline">Voordelen</div></li>
+                <li><div class="hover:underline">Aanvragen</div></li>
+                <li><div class="hover:underline">Voorwaarden</div></li>
+              </ul>
+            </div>
+            
+            <!-- Column 4 -->
+            <div>
+              <h3 class="font-bold text-lg mb-4">Blijf op de hoogte van de laatste trends</h3>
+              <div class="flex space-x-3 mb-6">
+                <div class="hover:text-gray-300">
+                  <FacebookIcon class="h-6 w-6" />
+                </div>
+                <div class="hover:text-gray-300">
+                  <InstagramIcon class="h-6 w-6" />
+                </div>
+                <div class="hover:text-gray-300">
+                  <YoutubeIcon class="h-6 w-6" />
+                </div>
+                <div class="hover:text-gray-300">
+                  <TwitterIcon class="h-6 w-6" />
+                </div>
path: pages/bloemenwinkel-productpagina.vue
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Social-media icons unresolved**

`FacebookIcon`, `InstagramIcon`, `YoutubeIcon`, `TwitterIcon` are referenced without import statements. Import or register them, or replace them with inline SVG/FontAwesome classes.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-12T10:20:47Z
author_association: NONE
diff_hunk: @@ -0,0 +1,680 @@
+<template>
+    <div class="bloemenwinkel-product-page">
+      <!-- Header -->
+    <header class="bg-white shadow-sm">
+      <div class="container mx-auto px-4 py-4">
+        <div class="flex flex-col md:flex-row items-center justify-between">
+          <!-- Logo -->
+          <div class="logo flex items-center mb-4 md:mb-0">
+            <div class="flex flex-col items-center md:items-start">
+              <div class="flex items-center">
+                <div class="w-6 h-6 bg-[#a02279] mr-1"></div>
+                <span class="text-[#2d5741] text-3xl font-bold"
+                  ><a href="/bloemenwinkel">Bloemenwinkel</a></span
+                >
+              </div>
+              <span class="text-[#2d5741] text-sm"
+                >tuincentrum vol groene ideeën</span
+              >
+            </div>
+          </div>
+
+          <!-- Search Bar -->
+          <div class="search-bar w-full md:w-1/3 mb-4 md:mb-0">
+            <div class="relative">
+              <input
+                type="text"
+                placeholder="Waar ben je naar op zoek?"
+                class="w-full py-2 px-4 border border-gray-300 rounded-full focus:outline-none focus:ring-1 focus:ring-[#2d5741]"
+                disabled
+              />
+              <div
+                class="absolute right-3 top-1/2 transform -translate-y-1/2"
+              >
+                <span class="text-gray-400">zoek</span>
+              </div>
+            </div>
+          </div>
+            
+            <!-- User Actions -->
+          <div class="user-actions flex items-center space-x-6">
+            
+            <div class="relative">
+              <span class="text-gray-600">❤️</span>
+            </div>
+            <div class="relative">
+              <span class="text-gray-600">🛒</span>
+            </div>
+          </div>
+        </div>
+      </div>
+      </header>
+      
+      <!-- Main Navigation -->
+    <nav class="bg-white border-t border-b border-gray-200">
+      <div class="container mx-auto px-4">
+        <ul
+          class="flex flex-wrap items-center justify-between md:justify-start"
+        >
+          <li class="py-4 px-2 md:px-4 relative group">
+            <div
+              class="flex items-center text-[#2d5741] font-medium"
+            >
+              Assortiment
+              <span class="ml-1">▼</span>
+            </div>
+          </li>
+        </ul>
+      </div>
+    </nav>
+      
+      <!-- Breadcrumbs -->
+      <div class="bg-gray-100 py-2">
+        <div class="container mx-auto px-4">
+          <div class="flex items-center text-sm text-gray-500">
+            <div class="hover:text-[#2d5741]">Home</div>
+            <ChevronRightIcon class="h-3 w-3 mx-1" />
+            <div class="hover:text-[#2d5741]">Assortiment</div>
+            <ChevronRightIcon class="h-3 w-3 mx-1" />
+            <span class="text-[#2d5741] font-medium">Producten</span>
+          </div>
path: pages/bloemenwinkel-productpagina.vue
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Missing icon component imports will break template compilation**

`<ChevronRightIcon />` is used in the breadcrumbs but the component is never imported (same issue further down with several other icons). Vue will throw “failed to resolve component” errors at runtime.

```diff
+import { ChevronRightIcon } from '@heroicons/vue/24/solid'   // example
```

Make sure every icon (ChevronRightIcon, HeartIcon, ShoppingCartIcon, AppleIcon, SmartphoneIcon, FacebookIcon, InstagramIcon, YoutubeIcon, TwitterIcon) is imported from a known library **or** registered globally.




<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
<!-- file_start: pages/bloemenwinkel-productpagina.vue -->
<script setup>
+import { ChevronRightIcon } from '@heroicons/vue/24/solid'
</script>

<!-- Breadcrumbs -->
<div class="bg-gray-100 py-2">
  <div class="container mx-auto px-4">
    <div class="flex items-center text-sm text-gray-500">
      <div class="hover:text-[#2d5741]">Home</div>
      <ChevronRightIcon class="h-3 w-3 mx-1" />
      <div class="hover:text-[#2d5741]">Assortiment</div>
      <ChevronRightIcon class="h-3 w-3 mx-1" />
      <span class="text-[#2d5741] font-medium">Producten</span>
    </div>
  </div>
</div>
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-05-12T10:20:47Z
author_association: NONE

PR comments:
user: login: vercel[bot]
created_at: 2025-05-12T10:18:48Z
body: [vc]: #umcLIegT4yIavT4eLPp/0ie7ydYIVvzvSXj8JitJ12s=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJjYXJkYW4iLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiY2FyZGFuLWdpdC0xMC1ibG9lbWVud2lua2VsLXByb2R1Y3RlbnBhZ2luYS1sa29zdGVycy1wcm9qZWN0cy52ZXJjZWwuYXBwIn0sImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9sa29zdGVycy1wcm9qZWN0cy9jYXJkYW4vNm1FTW9DQW5zNzJFalV0OGM4UEplTWtablRyUyIsInByZXZpZXdVcmwiOiJjYXJkYW4tZ2l0LTEwLWJsb2VtZW53aW5rZWwtcHJvZHVjdGVucGFnaW5hLWxrb3N0ZXJzLXByb2plY3RzLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJyb290RGlyZWN0b3J5IjpudWxsfV19
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **cardan** | ✅ Ready ([Inspect](https://vercel.com/lkosters-projects/cardan/6mEMoCAns72EjUt8c8PJeMkZnTrS)) | [Visit Preview](https://cardan-git-10-bloemenwinkel-productenpagina-lkosters-projects.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/cardan-git-10-bloemenwinkel-productenpagina-lkosters-projects.vercel.app?via=pr-comment-feedback-link) | May 12, 2025 10:21am |


author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-05-12T10:18:49Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: failure by coderabbit.ai -->

> [!CAUTION]
> ## Review failed
> 
> The pull request is closed.

<!-- end of auto-generated comment: failure by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

A new Vue component for a flower shop product page was added. It includes a structured layout with header, navigation, breadcrumbs, sidebar filters, dynamic product listing, newsletter signup, app promotion, and footer. Filtering, sorting, and price range selection are handled reactively using Vue's Composition API, with custom slider logic and responsive design.

## Changes

| File(s)                                            | Change Summary                                                                                             |
|----------------------------------------------------|-----------------------------------------------------------------------------------------------------------|
| pages/bloemenwinkel-productpagina.vue              | Added a new Vue component implementing a full-featured product page for a flower shop, with UI, filters, sorting, price slider, newsletter, app promotion, and footer. Exposes multiple reactive state variables, computed properties, and methods using the Composition API. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant ProductPage
    participant Filters
    participant ProductList

    User->>ProductPage: Loads bloemenwinkel-productpagina
    ProductPage->>Filters: Initializes categories, subcategories, price range
    User->>Filters: Selects category/subcategory or adjusts price slider
    Filters->>ProductPage: Updates reactive state
    ProductPage->>ProductList: Computes filtered and sorted products
    User->>ProductList: Views products, adds to cart
    User->>ProductPage: Submits newsletter or app promotion interaction
```

## Possibly related PRs

- LKosters/Cardan#26: Adds the same `pages/bloemenwinkel-productpagina.vue` component with identical reactive state and functionality for the flower shop product page.

## Poem

> 🐰  
> In the garden of petals, a page now blooms,  
> With filters and sliders, in digital rooms.  
> Products arranged, with care and delight,  
> Newsletters and promos, all shining bright.  
> From header to footer, the shop’s in full swing—  
> Hooray for the flowers this new page will bring!  
> 🌸

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡️ Faster reviews with caching</summary>
> 
> - CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure `Review - Disable Cache` at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the `Data Retention` setting under your Organization Settings.
> 
> Enjoy the performance boost—your workflow just got faster.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 7b8e40df539392c31c2c60dc06890821955a3fa7 and 2ceea2b4549627b0331f1881e8f8f82d8208914c.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `pages/bloemenwinkel-productpagina.vue` (1 hunks)

</details>

</details>
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=LKosters/Cardan&utm_content=26):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE