@shopbite-de/storefront 1.4.1 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,14 +3,110 @@ import { mockNuxtImport } from "@nuxt/test-utils/runtime";
3
3
  import { ref } from "vue";
4
4
  import { useDeliveryTime } from "~/composables/useDeliveryTime";
5
5
 
6
- const { mockDeliveryTime } = vi.hoisted(() => ({
7
- mockDeliveryTime: { value: 45 }, // Use object to keep reference
8
- }));
6
+ const { mockDeliveryTime, mockBusinessHours, mockHolidays } = vi.hoisted(
7
+ () => ({
8
+ mockDeliveryTime: { value: 45 },
9
+ mockBusinessHours: {
10
+ value: [
11
+ { dayOfWeek: 1, openingTime: "11:30", closingTime: "14:30" },
12
+ { dayOfWeek: 1, openingTime: "17:30", closingTime: "23:00" },
13
+ { dayOfWeek: 3, openingTime: "11:30", closingTime: "14:30" },
14
+ { dayOfWeek: 3, openingTime: "17:30", closingTime: "23:00" },
15
+ { dayOfWeek: 4, openingTime: "11:30", closingTime: "14:30" },
16
+ { dayOfWeek: 4, openingTime: "17:30", closingTime: "23:00" },
17
+ { dayOfWeek: 5, openingTime: "11:30", closingTime: "14:30" },
18
+ { dayOfWeek: 5, openingTime: "17:30", closingTime: "23:00" },
19
+ { dayOfWeek: 6, openingTime: "17:30", closingTime: "23:30" },
20
+ { dayOfWeek: 0, openingTime: "11:30", closingTime: "14:30" },
21
+ { dayOfWeek: 0, openingTime: "17:30", closingTime: "23:00" },
22
+ ],
23
+ },
24
+ mockHolidays: { value: [] },
25
+ }),
26
+ );
9
27
 
10
28
  mockNuxtImport("useShopBiteConfig", () => () => ({
11
29
  deliveryTime: mockDeliveryTime,
12
30
  }));
13
31
 
32
+ mockNuxtImport("useBusinessHours", () => () => ({
33
+ businessHours: mockBusinessHours,
34
+ getServiceIntervals: (date: Date) => {
35
+ const dayOfWeek = date.getDay();
36
+ return mockBusinessHours.value
37
+ .filter((bh) => bh.dayOfWeek === dayOfWeek)
38
+ .map((bh) => {
39
+ const [startH, startM] = bh.openingTime.split(":").map(Number);
40
+ const [endH, endM] = bh.closingTime.split(":").map(Number);
41
+ const start = new Date(date);
42
+ start.setHours(startH, startM, 0, 0);
43
+ const end = new Date(date);
44
+ end.setHours(endH, endM, 0, 0);
45
+ return { start, end };
46
+ });
47
+ },
48
+ getEarliestSelectableTime: (
49
+ currentTime: Date,
50
+ currentDeliveryTime: number | null,
51
+ ) => {
52
+ const earliest = new Date(currentTime);
53
+ earliest.setMinutes(earliest.getMinutes() + (currentDeliveryTime ?? 30));
54
+ earliest.setSeconds(0, 0);
55
+ return earliest;
56
+ },
57
+ findActiveInterval: (
58
+ currentTime: Date,
59
+ currentDeliveryTime: number | null,
60
+ ) => {
61
+ const intervals = [
62
+ { dayOfWeek: 1, openingTime: "11:30", closingTime: "14:30" },
63
+ { dayOfWeek: 1, openingTime: "17:30", closingTime: "23:00" },
64
+ { dayOfWeek: 3, openingTime: "11:30", closingTime: "14:30" },
65
+ { dayOfWeek: 3, openingTime: "17:30", closingTime: "23:00" },
66
+ { dayOfWeek: 4, openingTime: "11:30", closingTime: "14:30" },
67
+ { dayOfWeek: 4, openingTime: "17:30", closingTime: "23:00" },
68
+ { dayOfWeek: 5, openingTime: "11:30", closingTime: "14:30" },
69
+ { dayOfWeek: 5, openingTime: "17:30", closingTime: "23:00" },
70
+ { dayOfWeek: 6, openingTime: "17:30", closingTime: "23:30" },
71
+ { dayOfWeek: 0, openingTime: "11:30", closingTime: "14:30" },
72
+ { dayOfWeek: 0, openingTime: "17:30", closingTime: "23:00" },
73
+ ]
74
+ .filter((bh) => bh.dayOfWeek === currentTime.getDay())
75
+ .map((bh) => {
76
+ const [startH, startM] = bh.openingTime.split(":").map(Number);
77
+ const [endH, endM] = bh.closingTime.split(":").map(Number);
78
+ const start = new Date(currentTime);
79
+ start.setHours(startH, startM, 0, 0);
80
+ const end = new Date(currentTime);
81
+ end.setHours(endH, endM, 0, 0);
82
+ return { start, end };
83
+ });
84
+
85
+ const earliest = new Date(currentTime);
86
+ earliest.setMinutes(earliest.getMinutes() + (currentDeliveryTime ?? 30));
87
+ earliest.setSeconds(0, 0);
88
+
89
+ if (intervals.length === 0) return null;
90
+ const current = intervals.find(
91
+ (i) => earliest >= i.start && earliest <= i.end,
92
+ );
93
+ if (current) return current;
94
+ return intervals.find((i) => i.start > earliest) ?? null;
95
+ },
96
+ }));
97
+
98
+ mockNuxtImport("useHolidays", () => () => ({
99
+ isClosedHoliday: (date: Date) => {
100
+ if (!mockHolidays.value) return undefined;
101
+ const formattedDate = date.toISOString().split("T")[0];
102
+ return mockHolidays.value.some((h: any) => {
103
+ const start = h.start.split("T")[0];
104
+ const end = h.end.split("T")[0];
105
+ return formattedDate >= start && formattedDate <= end;
106
+ });
107
+ },
108
+ }));
109
+
14
110
  describe("useDeliveryTime", () => {
15
111
  const now = ref(new Date("2023-10-27T12:00:00")); // A Friday
16
112
 
@@ -65,4 +161,11 @@ describe("useDeliveryTime", () => {
65
161
  );
66
162
  }
67
163
  });
164
+
165
+ it("should return loading message when holidays are not loaded", () => {
166
+ mockHolidays.value = null;
167
+ const { helperText } = useDeliveryTime(now);
168
+ expect(helperText.value).toBe("Lade Informationen...");
169
+ mockHolidays.value = []; // Reset for other tests
170
+ });
68
171
  });
@@ -1,114 +0,0 @@
1
- export type ServiceInterval = { start: Date; end: Date };
2
-
3
- export function isTuesday(date: Date): boolean {
4
- return date.getDay() === 2;
5
- }
6
-
7
- export function isSaturday(date: Date): boolean {
8
- return date.getDay() === 6;
9
- }
10
-
11
- export function getServiceIntervals(date: Date): Array<ServiceInterval> {
12
- if (isTuesday(date)) return [];
13
-
14
- const lunchStart = setTime(date, 11, 30);
15
- const lunchEnd = setTime(date, 14, 30);
16
- const dinnerStart = setTime(date, 17, 30);
17
- const dinnerEnd = isSaturday(date)
18
- ? setTime(date, 23, 30)
19
- : setTime(date, 23, 0);
20
-
21
- if (isSaturday(date)) {
22
- // Saturday: only dinner, no lunch
23
- return [{ start: dinnerStart, end: dinnerEnd }];
24
- }
25
-
26
- return [
27
- { start: lunchStart, end: lunchEnd },
28
- { start: dinnerStart, end: dinnerEnd },
29
- ];
30
- }
31
-
32
- export function getEarliestSelectableTime(
33
- currentTime: Date,
34
- currentDeliveryTime: number | null,
35
- ): Date {
36
- const earliest = new Date(currentTime);
37
- earliest.setMinutes(earliest.getMinutes() + (currentDeliveryTime ?? 30));
38
- earliest.setSeconds(0, 0);
39
- return earliest;
40
- }
41
-
42
- export function getNextOpeningTime(now: Ref<Date>): string | null {
43
- const currentDate = now.value;
44
-
45
- // Try up to 60 days ahead to find next opening (covers long holiday periods)
46
- for (let i = 0; i < 60; i++) {
47
- const checkDate = new Date(currentDate);
48
- checkDate.setDate(checkDate.getDate() + i);
49
- checkDate.setHours(12, 0, 0, 0); // Set to midday to avoid timezone issues
50
-
51
- // Skip holidays
52
- if (isClosedHoliday(checkDate)) continue;
53
-
54
- const intervals = getServiceIntervals(checkDate);
55
- if (intervals.length === 0) continue;
56
-
57
- // For today, check if there's still an opening coming
58
- if (i === 0) {
59
- for (const interval of intervals) {
60
- if (interval.start.getTime() > currentDate.getTime()) {
61
- const hours = interval.start.getHours().toString().padStart(2, "0");
62
- const minutes = interval.start
63
- .getMinutes()
64
- .toString()
65
- .padStart(2, "0");
66
- return `${hours}:${minutes} Uhr`;
67
- }
68
- }
69
- continue; // Today's openings have passed, check next days
70
- }
71
-
72
- const nextOpen = intervals[0].start;
73
- const day = nextOpen.getDate().toString().padStart(2, "0");
74
- const month = (nextOpen.getMonth() + 1).toString().padStart(2, "0");
75
- const dayName = [
76
- "Sonntag",
77
- "Montag",
78
- "Dienstag",
79
- "Mittwoch",
80
- "Donnerstag",
81
- "Freitag",
82
- "Samstag",
83
- ][nextOpen.getDay()];
84
- const hours = nextOpen.getHours().toString().padStart(2, "0");
85
- const minutes = nextOpen.getMinutes().toString().padStart(2, "0");
86
-
87
- if (i === 1) {
88
- return `morgen um ${hours}:${minutes} Uhr`;
89
- }
90
- return `${dayName}, ${day}.${month}. um ${hours}:${minutes} Uhr`;
91
- }
92
-
93
- return null;
94
- }
95
-
96
- export function findActiveInterval(
97
- currentTime: Date,
98
- currentDeliveryTime: number | null,
99
- ): ServiceInterval | null {
100
- const intervals = getServiceIntervals(currentTime);
101
- const earliest = getEarliestSelectableTime(
102
- currentTime,
103
- currentDeliveryTime ?? 30,
104
- );
105
-
106
- if (intervals.length === 0) return null;
107
-
108
- const current = intervals.find(
109
- (interval) => earliest >= interval.start && earliest <= interval.end,
110
- );
111
- if (current) return current;
112
-
113
- return intervals.find((interval) => interval.start > earliest) ?? null;
114
- }
@@ -1,24 +0,0 @@
1
- export function isClosedHoliday(date?: Date): boolean {
2
- // Use provided date or current date
3
- const checkDate = date ?? new Date();
4
- // Format date as YYYY-MM-DD for comparison
5
- const formattedDate = formatDateYYYYMMDD(checkDate);
6
-
7
- // List of holidays (YYYY-MM-DD format)
8
- const holidays = ["2025-12-31", "2026-01-01"];
9
-
10
- return holidays.includes(formattedDate);
11
- }
12
-
13
- /**
14
- * Formats a date as YYYY-MM-DD
15
- * @param date The date to format
16
- * @returns The formatted date string
17
- */
18
- function formatDateYYYYMMDD(date: Date): string {
19
- const year = date.getFullYear();
20
- const month = String(date.getMonth() + 1).padStart(2, "0");
21
- const day = String(date.getDate()).padStart(2, "0");
22
-
23
- return `${year}-${month}-${day}`;
24
- }
@@ -1,8 +0,0 @@
1
- // utils/storeHours.ts
2
- export function isStoreOpen(date: Date = new Date()): boolean {
3
- if (isClosedHoliday(date)) return false;
4
-
5
- const intervals = getServiceIntervals(date);
6
- if (intervals.length === 0) return false;
7
- return intervals.some(({ start, end }) => date >= start && date <= end);
8
- }