<div class="space-y-4 md:pb-0" x-data="listStoreLocator()">
    <template x-for="store in paginatedStores" :key="store.mur_code">
        <div class="flex flex-col p-5 gap-5 bg-white rounded-lg shadow-sm border border-neutral-200 font-medium">

            <div class="flex justify-between items-start">
                <div class="flex flex-wrap gap-2">

                    <template x-for="location in store.locations" :key="location.id">
                        <span class="px-3 py-1 text-xs rounded-md text-white" :class="location.is_audio ? 'bg-audio-700' : 'bg-neutral-800'">
                            <span x-text="location.is_audio ? 'Acousticien' : 'Opticien'"></span>
                        </span>
                    </template>

                    <template x-if="store.locations.some(location => location.attributes.teleophtalmologie?.value === '1')">
                        <span class="px-3 py-1 text-xs rounded-md text-gray-600 border border-neutral-200">
                            Télémédecine
                        </span>
                    </template>
                </div>
            </div>

            <div class="text-sm text-neutral-800">
                <div class="flex justify-between items-start">
                    <div>
                        <p class="mb-1" x-text="store.address"></p>
                        <p class="mb-2 uppercase">
                            <span x-text="store.city"></span>,
                            <span x-text="store.zip"></span>,
                            <span x-text="store.country"></span>
                        </p>
                    </div>

                    <div class="flex items-center justify-end gap-2 w-1/2">
                        <span class="text-sm" x-text="store.distance"></span>
                        <button type="button" x-data x-init="" @click="$store.locator.goToStore(store)" class="max-md:btn-size-sm btn btn-dark-ghost  btn-only-icon">
                            <svg class=" shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path fill-rule="evenodd" clip-rule="evenodd" d="M12 3.75C8.55638 3.75 5.75 6.53739 5.75 9.92308C5.75 12.7655 7.35594 15.361 9.06325 17.3029C9.9074 18.263 10.7535 19.0373 11.3889 19.5713C11.6267 19.7713 11.8342 19.9369 12 20.0653C12.1658 19.9369 12.3733 19.7713 12.6111 19.5713C13.2465 19.0373 14.0926 18.263 14.9367 17.3029C16.6441 15.361 18.25 12.7655 18.25 9.92308C18.25 6.53739 15.4436 3.75 12 3.75ZM12 21C11.5731 21.6166 11.5729 21.6165 11.5726 21.6163L11.5704 21.6147L11.5651 21.6111L11.5471 21.5984C11.5318 21.5876 11.5101 21.5722 11.4824 21.5521C11.4269 21.5121 11.3473 21.4537 11.247 21.3779C11.0464 21.2263 10.7628 21.0046 10.4236 20.7195C9.74646 20.1502 8.8426 19.3236 7.93675 18.2933C6.14406 16.2544 4.25 13.3114 4.25 9.92308C4.25 5.69338 7.74362 2.25 12 2.25C16.2564 2.25 19.75 5.69338 19.75 9.92308C19.75 13.3114 17.8559 16.2544 16.0633 18.2933C15.1574 19.3236 14.2535 20.1502 13.5764 20.7195C13.2372 21.0046 12.9536 21.2263 12.753 21.3779C12.6527 21.4537 12.5731 21.5121 12.5176 21.5521C12.4899 21.5722 12.4682 21.5876 12.4529 21.5984L12.4349 21.6111L12.4296 21.6147L12.428 21.6159C12.4277 21.6161 12.4269 21.6166 12 21ZM12 21L12.4269 21.6166L12 21.9122L11.5726 21.6163L12 21ZM12 7.75C10.7574 7.75 9.75 8.75736 9.75 10C9.75 11.2426 10.7574 12.25 12 12.25C13.2426 12.25 14.25 11.2426 14.25 10C14.25 8.75736 13.2426 7.75 12 7.75ZM8.25 10C8.25 7.92893 9.92893 6.25 12 6.25C14.0711 6.25 15.75 7.92893 15.75 10C15.75 12.0711 14.0711 13.75 12 13.75C9.92893 13.75 8.25 12.0711 8.25 10Z" fill="currentColor" />
                            </svg>

                        </button>
                    </div>
                </div>

                <p x-data="{
                status: null,
                async checkOpenStatus(store) {
                    this.status = await isStoreOpen(store);
                }
            }" x-init="checkOpenStatus(store)">
                    <template x-if="!status">
                        <span class="text-gray-500">Chargement...</span>
                    </template>

                    <!-- État chargé -->
                    <template x-if="status">
                        <span>
                            <span :class="status.isOpen ? 'text-green-600' : 'text-red-700'" x-text="status.isOpen ? 'Ouvert' : 'Fermé'">
                            </span>
                            ·
                            <span class="text-sm text-gray-800" x-text="status.text">
                            </span>
                        </span>
                    </template>
                </p>
            </div>

            <div class="flex gap-3 justify-between">
                <a href="#" class="max-md:btn-size-sm btn btn-dark-ghost ">
                    Voir le magasin

                </a>
                <button type="button" x-data="{}" x-init="$store.asideBlocs.addAside('storeLocatorAppointment')" @click="
                (!$store.locator.stepperData ||
                $store.locator.stepperData.code_mur !== store.mur_code ||
                $store.locator.stepperData.type !== $store.locator.isAudio)
                    ? $store.locator.initStepper(store)
                    : null;
                $store.asideBlocs.toggleAside('storeLocatorAppointment')
            " class="max-md:btn-size-sm btn btn-dark-ghost  btn-icons">
                    <svg class=" shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path fill-rule="evenodd" clip-rule="evenodd" d="M8 1.25C8.41421 1.25 8.75 1.58579 8.75 2V3.25H15.25V2C15.25 1.58579 15.5858 1.25 16 1.25C16.4142 1.25 16.75 1.58579 16.75 2V3.25H20C21.5188 3.25 22.75 4.48122 22.75 6V20C22.75 21.5188 21.5188 22.75 20 22.75H4C2.48122 22.75 1.25 21.5188 1.25 20V6C1.25 4.48122 2.48122 3.25 4 3.25H7.25V2C7.25 1.58579 7.58579 1.25 8 1.25ZM7.25 4.75H4C3.30964 4.75 2.75 5.30964 2.75 6V8.25H21.25V6C21.25 5.30964 20.6904 4.75 20 4.75H16.75V6C16.75 6.41421 16.4142 6.75 16 6.75C15.5858 6.75 15.25 6.41421 15.25 6V4.75H8.75V6C8.75 6.41421 8.41421 6.75 8 6.75C7.58579 6.75 7.25 6.41421 7.25 6V4.75ZM21.25 9.75H2.75V20C2.75 20.6904 3.30964 21.25 4 21.25H20C20.6904 21.25 21.25 20.6904 21.25 20V9.75ZM12 14.5C12.5523 14.5 13 14.0523 13 13.5C13 12.9477 12.5523 12.5 12 12.5C11.4477 12.5 11 12.9477 11 13.5C11 14.0523 11.4477 14.5 12 14.5ZM8 17.5C8 18.0523 7.55228 18.5 7 18.5C6.44772 18.5 6 18.0523 6 17.5C6 16.9477 6.44772 16.5 7 16.5C7.55228 16.5 8 16.9477 8 17.5ZM12 18.5C12.5523 18.5 13 18.0523 13 17.5C13 16.9477 12.5523 16.5 12 16.5C11.4477 16.5 11 16.9477 11 17.5C11 18.0523 11.4477 18.5 12 18.5ZM17 14.5C17.5523 14.5 18 14.0523 18 13.5C18 12.9477 17.5523 12.5 17 12.5C16.4477 12.5 16 12.9477 16 13.5C16 14.0523 16.4477 14.5 17 14.5ZM17 18.5C17.5523 18.5 18 18.0523 18 17.5C18 16.9477 17.5523 16.5 17 16.5C16.4477 16.5 16 16.9477 16 17.5C16 18.0523 16.4477 18.5 17 18.5Z" fill="currentColor" />
                    </svg>
                    Prendre rendez-vous

                </button>
            </div>
        </div>
    </template>

    <div class="py-4 border-t flex justify-around items-center">
        <button type="button" @click="previousPage()" :disabled="currentPage === 1" class="disabled:opacity-50  btn btn-dark-ghost  btn-only-icon">
            <svg class=" shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path fill-rule="evenodd" clip-rule="evenodd" d="M9.46967 12.5303C9.17678 12.2374 9.17678 11.7626 9.46967 11.4697L13.4697 7.46967C13.7626 7.17678 14.2374 7.17678 14.5303 7.46967C14.8232 7.76256 14.8232 8.23744 14.5303 8.53033L11.0607 12L14.5303 15.4697C14.8232 15.7626 14.8232 16.2374 14.5303 16.5303C14.2374 16.8232 13.7626 16.8232 13.4697 16.5303L9.46967 12.5303Z" fill="currentColor" />
            </svg>

        </button>

        <div class="flex items-center">
            <template x-for="(item, index) in paginationItems" :key="index">
                <div class="mt-4 flex gap-4 m-2 justify-center">
                    <span x-show="item.type === 'dots'" class="flex items-center justify-center font-semibold text-black/60">...</span>
                    <button x-show="item.type === 'page'" @click="goToPage(item.value)" class="flex items-center justify-center font-semibold" :class="currentPage === item.value ? 'px-2 border-b border-black/80' : 'text-black/60'" x-text="item.value">
                    </button>
                </div>
            </template>
        </div>

        <button type="button" @click="nextPage()" :disabled="currentPage === totalPages" class="disabled:opacity-50  btn btn-dark-ghost  btn-only-icon">
            <svg class=" shrink-0" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path fill-rule="evenodd" clip-rule="evenodd" d="M14.5303 11.4697C14.8232 11.7626 14.8232 12.2374 14.5303 12.5303L10.5303 16.5303C10.2374 16.8232 9.76256 16.8232 9.46967 16.5303C9.17678 16.2374 9.17678 15.7626 9.46967 15.4697L12.9393 12L9.46967 8.53033C9.17678 8.23744 9.17678 7.76256 9.46967 7.46967C9.76256 7.17678 10.2374 7.17678 10.5303 7.46967L14.5303 11.4697Z" fill="currentColor" />
            </svg>

        </button>
    </div>
</div>

<script>
    function listStoreLocator() {
        return {
            currentPage: 1,
            itemsPerPage: 10,
            get stores() {
                return Object.values(this.$store.locator.filteredDistanceStores || {});
            },
            get paginatedStores() {
                const start = (this.currentPage - 1) * this.itemsPerPage;
                const paginatedResults = this.stores.slice(start, start + this.itemsPerPage);
                // If current page is empty, redirect into the first page
                if (paginatedResults.length === 0 && this.stores.length > 0) {
                    this.currentPage = 1;
                    return this.stores.slice(0, this.itemsPerPage);
                }
                return paginatedResults;
            },
            get totalPages() {
                return Math.ceil(this.stores.length / this.itemsPerPage);
            },
            get paginationItems() {
                const items = [];
                items.push({
                    type: 'page',
                    value: 1
                });
                if (this.currentPage > 3) {
                    items.push({
                        type: 'dots'
                    });
                }
                if (this.currentPage > 2) {
                    items.push({
                        type: 'page',
                        value: this.currentPage - 1
                    });
                }
                if (this.currentPage !== 1 && this.currentPage !== this.totalPages) {
                    items.push({
                        type: 'page',
                        value: this.currentPage
                    });
                }
                if (this.currentPage < this.totalPages - 1) {
                    items.push({
                        type: 'page',
                        value: this.currentPage + 1
                    });
                }
                if (this.currentPage < this.totalPages - 2) {
                    items.push({
                        type: 'dots'
                    });
                }
                if (this.totalPages > 1) {
                    items.push({
                        type: 'page',
                        value: this.totalPages
                    });
                }
                return items;
            },
            scrollToTopOfList() {},
            goToPage(page) {
                this.currentPage = page;
                this.scrollToTopOfList();
            },
            nextPage() {
                if (this.currentPage < this.totalPages) {
                    this.currentPage++;
                    this.scrollToTopOfList();
                }
            },
            previousPage() {
                if (this.currentPage > 1) {
                    this.currentPage--;
                    this.scrollToTopOfList();
                }
            },
            async isStoreOpen(store) {
                const DAYS_SHORT = ['dim', 'lun', 'mar', 'mer', 'jeu', 'ven', 'sam'];
                const DAYS_LONG = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'];
                try {
                    if (!store?.locations?.length) {
                        return {
                            isOpen: false,
                            text: 'Horaires non disponibles'
                        };
                    }
                    const service = store.locations.find(s => !s.is_audio);
                    if (!service?.attributes?.schedule_opening_hours?.value) {
                        return {
                            isOpen: false,
                            text: 'Horaires non disponibles'
                        };
                    }
                    const timezone = service.attributes.timezone?.value || 'Europe/Paris';
                    const now = new Intl.DateTimeFormat('fr-FR', {
                        timeZone: timezone,
                        year: 'numeric',
                        month: '2-digit',
                        day: '2-digit',
                        hour: '2-digit',
                        minute: '2-digit',
                        hour12: false
                    }).format(new Date());
                    const [date, time] = now.split(' ');
                    const [hours, minutes] = time.split(':').map(Number);
                    const storeDate = new Date();
                    const currentDay = DAYS_SHORT[storeDate.getDay()];
                    const currentHour = hours + minutes / 60;
                    const schedule = service.attributes.schedule_opening_hours.value
                        .split('|')
                        .reduce((acc, day) => {
                            const [key, hours] = day.split('=');
                            if (!key || !hours) return acc;
                            acc[key] = hours === 'null' ? 'Fermé' : hours;
                            return acc;
                        }, {});
                    // Check if close today
                    if (!schedule[currentDay] || schedule[currentDay] === 'Fermé' || schedule[currentDay] === 'null') {
                        let nextDay = (storeDate.getDay() + 1) % 7;
                        let daysChecked = 0;
                        while (daysChecked < 7) {
                            const daySchedule = schedule[DAYS_SHORT[nextDay]];
                            if (daySchedule && daySchedule !== 'Fermé' && daySchedule !== 'null') {
                                const [firstPeriod] = daySchedule.split(',');
                                if (firstPeriod && firstPeriod !== '-') {
                                    const openTime = firstPeriod.split('-')[0];
                                    return {
                                        isOpen: false,
                                        text: `Ouvre ${DAYS_LONG[nextDay]} à ${openTime}`
                                    };
                                }
                            }
                            nextDay = (nextDay + 1) % 7;
                            daysChecked++;
                        }
                        return {
                            isOpen: false,
                            text: 'Fermé aujourd\'hui'
                        };
                    }
                    // Check openning periods
                    const periods = schedule[currentDay].split(',').filter(p => p && p !== '-');
                    for (const period of periods) {
                        const [start, end] = period.split('-');
                        if (!start || !end) continue;
                        const [startHour, startMin] = start.split(':').map(Number);
                        const [endHour, endMin] = end.split(':').map(Number);
                        if (isNaN(startHour) || isNaN(startMin) || isNaN(endHour) || isNaN(endMin)) continue;
                        const startTime = startHour + startMin / 60;
                        const endTime = endHour + endMin / 60;
                        if (currentHour >= startTime && currentHour < endTime) {
                            return {
                                isOpen: true,
                                text: `Ferme à ${end}`
                            };
                        }
                        if (currentHour < startTime) {
                            return {
                                isOpen: false,
                                text: `Ouvre à ${start}`
                            };
                        }
                    }
                    // Search next opening day
                    let nextDay = (storeDate.getDay() + 1) % 7;
                    let daysChecked = 0;
                    while (daysChecked < 7) {
                        const daySchedule = schedule[DAYS_SHORT[nextDay]];
                        if (daySchedule && daySchedule !== 'Fermé' && daySchedule !== 'null') {
                            const [firstPeriod] = daySchedule.split(',');
                            if (firstPeriod && firstPeriod !== '-') {
                                const openTime = firstPeriod.split('-')[0];
                                return {
                                    isOpen: false,
                                    text: `Ouvre ${DAYS_LONG[nextDay]} à ${openTime}`
                                };
                            }
                        }
                        nextDay = (nextDay + 1) % 7;
                        daysChecked++;
                    }
                    return {
                        isOpen: false,
                        text: 'Fermé'
                    };
                } catch (error) {
                    console.error('Erreur dans isStoreOpen:', error);
                    return {
                        isOpen: false,
                        text: 'Horaires non disponibles'
                    };
                }
            }
        }
    }
</script>
<div class="space-y-4 md:pb-0"
     x-data="listStoreLocator()"
>
    <template x-for="store in paginatedStores" :key="store.mur_code">
        {% render "@storelocator-card" %}
    </template>

    <div class="py-4 border-t flex justify-around items-center">
        {% render "@template-button" with {
            color: "dark-ghost",
            type: "only-icon",
            icon: {
                name: "library--chevron-left"
            },
            button_attribute: '@click="previousPage()" :disabled="currentPage === 1"',
            button_class: "disabled:opacity-50"
        } %}

        <div class="flex items-center">
            <template x-for="(item, index) in paginationItems" :key="index">
                <div class="mt-4 flex gap-4 m-2 justify-center">
                    <span x-show="item.type === 'dots'"
                          class="flex items-center justify-center font-semibold text-black/60">...</span>
                    <button
                            x-show="item.type === 'page'"
                            @click="goToPage(item.value)"
                            class="flex items-center justify-center font-semibold"
                            :class="currentPage === item.value ? 'px-2 border-b border-black/80' : 'text-black/60'"
                            x-text="item.value">
                    </button>
                </div>
            </template>
        </div>

        {% render "@template-button" with {
            color: "dark-ghost",
            type: "only-icon",
            icon: {
                name: "library--chevron-right"
            },
            button_attribute: '@click="nextPage()" :disabled="currentPage === totalPages"',
            button_class: "disabled:opacity-50"
        } %}
    </div>
</div>

<script>
	function listStoreLocator() {
		return {
			currentPage: 1,
			itemsPerPage: 10,

			get stores() {
				return Object.values(this.$store.locator.filteredDistanceStores || {});
			},

			get paginatedStores() {
				const start = (this.currentPage - 1) * this.itemsPerPage;
				const paginatedResults = this.stores.slice(start, start + this.itemsPerPage);

				// If current page is empty, redirect into the first page
				if (paginatedResults.length === 0 && this.stores.length > 0) {
					this.currentPage = 1;
					return this.stores.slice(0, this.itemsPerPage);
				}

				return paginatedResults;
			},

			get totalPages() {
				return Math.ceil(this.stores.length / this.itemsPerPage);
			},

			get paginationItems() {
				const items = [];

				items.push({type: 'page', value: 1});

				if (this.currentPage > 3) {
					items.push({type: 'dots'});
				}

				if (this.currentPage > 2) {
					items.push({type: 'page', value: this.currentPage - 1});
				}

				if (this.currentPage !== 1 && this.currentPage !== this.totalPages) {
					items.push({type: 'page', value: this.currentPage});
				}

				if (this.currentPage < this.totalPages - 1) {
					items.push({type: 'page', value: this.currentPage + 1});
				}

				if (this.currentPage < this.totalPages - 2) {
					items.push({type: 'dots'});
				}

				if (this.totalPages > 1) {
					items.push({type: 'page', value: this.totalPages});
				}

				return items;
			},

			scrollToTopOfList() {

			},

			goToPage(page) {
				this.currentPage = page;
				this.scrollToTopOfList();
			},

			nextPage() {
				if (this.currentPage < this.totalPages) {
					this.currentPage++;
					this.scrollToTopOfList();
				}
			},

			previousPage() {
				if (this.currentPage > 1) {
					this.currentPage--;
					this.scrollToTopOfList();
				}
			},

			async isStoreOpen(store) {
				const DAYS_SHORT = ['dim', 'lun', 'mar', 'mer', 'jeu', 'ven', 'sam'];
				const DAYS_LONG = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'];

				try {
					if (!store?.locations?.length) {
						return {isOpen: false, text: 'Horaires non disponibles'};
					}

					const service = store.locations.find(s => !s.is_audio);
					if (!service?.attributes?.schedule_opening_hours?.value) {
						return {isOpen: false, text: 'Horaires non disponibles'};
					}

					const timezone = service.attributes.timezone?.value || 'Europe/Paris';
					const now = new Intl.DateTimeFormat('fr-FR', {
						timeZone: timezone,
						year: 'numeric',
						month: '2-digit',
						day: '2-digit',
						hour: '2-digit',
						minute: '2-digit',
						hour12: false
					}).format(new Date());

					const [date, time] = now.split(' ');
					const [hours, minutes] = time.split(':').map(Number);

					const storeDate = new Date();
					const currentDay = DAYS_SHORT[storeDate.getDay()];
					const currentHour = hours + minutes / 60;

					const schedule = service.attributes.schedule_opening_hours.value
						.split('|')
						.reduce((acc, day) => {
							const [key, hours] = day.split('=');
							if (!key || !hours) return acc;
							acc[key] = hours === 'null' ? 'Fermé' : hours;
							return acc;
						}, {});

					// Check if close today
					if (!schedule[currentDay] || schedule[currentDay] === 'Fermé' || schedule[currentDay] === 'null') {
						let nextDay = (storeDate.getDay() + 1) % 7;
						let daysChecked = 0;

						while (daysChecked < 7) {
							const daySchedule = schedule[DAYS_SHORT[nextDay]];
							if (daySchedule && daySchedule !== 'Fermé' && daySchedule !== 'null') {
								const [firstPeriod] = daySchedule.split(',');
								if (firstPeriod && firstPeriod !== '-') {
									const openTime = firstPeriod.split('-')[0];
									return {
										isOpen: false,
										text: `Ouvre ${DAYS_LONG[nextDay]} à ${openTime}`
									};
								}
							}
							nextDay = (nextDay + 1) % 7;
							daysChecked++;
						}
						return {isOpen: false, text: 'Fermé aujourd\'hui'};
					}

					// Check openning periods
					const periods = schedule[currentDay].split(',').filter(p => p && p !== '-');

					for (const period of periods) {
						const [start, end] = period.split('-');
						if (!start || !end) continue;

						const [startHour, startMin] = start.split(':').map(Number);
						const [endHour, endMin] = end.split(':').map(Number);

						if (isNaN(startHour) || isNaN(startMin) || isNaN(endHour) || isNaN(endMin)) continue;

						const startTime = startHour + startMin / 60;
						const endTime = endHour + endMin / 60;

						if (currentHour >= startTime && currentHour < endTime) {
							return {isOpen: true, text: `Ferme à ${end}`};
						}

						if (currentHour < startTime) {
							return {isOpen: false, text: `Ouvre à ${start}`};
						}
					}

					// Search next opening day
					let nextDay = (storeDate.getDay() + 1) % 7;
					let daysChecked = 0;

					while (daysChecked < 7) {
						const daySchedule = schedule[DAYS_SHORT[nextDay]];
						if (daySchedule && daySchedule !== 'Fermé' && daySchedule !== 'null') {
							const [firstPeriod] = daySchedule.split(',');
							if (firstPeriod && firstPeriod !== '-') {
								const openTime = firstPeriod.split('-')[0];
								return {
									isOpen: false,
									text: `Ouvre ${DAYS_LONG[nextDay]} à ${openTime}`
								};
							}
						}
						nextDay = (nextDay + 1) % 7;
						daysChecked++;
					}

					return {isOpen: false, text: 'Fermé'};
				} catch (error) {
					console.error('Erreur dans isStoreOpen:', error);
					return {isOpen: false, text: 'Horaires non disponibles'};
				}
			}
		}
	}
</script>
/* No context defined. */

No notes defined.