@bigz-app/booking-widget 0.3.5 → 0.3.6

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.
package/dist/index.esm.js CHANGED
@@ -10908,16 +10908,7 @@ const spinner = (borderColor) => (jsx("div", { style: {
10908
10908
  } }) }));
10909
10909
  function EventInstanceSelection({ eventInstances, selectedEventType, onEventInstanceSelect, onBackToEventTypes, isOpen, onClose, isLoadingEventInstances = false, isLoadingEventDetails = false, }) {
10910
10910
  const [selectedEventInstanceId, setSelectedEventInstanceId] = useState(null);
10911
- const [openMonths, setOpenMonths] = useState(new Set());
10912
- const getEventsForMonth = (monthIndex) => {
10913
- return eventInstances.filter((instance) => new Date(instance.startTime).getMonth() === monthIndex);
10914
- };
10915
- const getMinPriceForMonth = (monthIndex) => {
10916
- const monthEvents = getEventsForMonth(monthIndex);
10917
- if (monthEvents.length === 0)
10918
- return 0;
10919
- return Math.min(...monthEvents.map((event) => event.price));
10920
- };
10911
+ const [openGroups, setOpenGroups] = useState(new Set());
10921
10912
  const getMonthPriceDisplayInfo = (minPrice) => {
10922
10913
  return getPriceDisplayInfo(minPrice, yearPrices);
10923
10914
  };
@@ -10927,27 +10918,48 @@ function EventInstanceSelection({ eventInstances, selectedEventType, onEventInst
10927
10918
  .filter((instance) => new Date(instance.startTime).getFullYear() === currentYear)
10928
10919
  .map((instance) => instance.price);
10929
10920
  const today = new Date();
10930
- // Get months that have events
10931
- const monthsWithEvents = months
10932
- .map((month, index) => ({
10933
- month,
10934
- index,
10935
- events: getEventsForMonth(index).sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime()),
10936
- minPrice: getMinPriceForMonth(index),
10937
- }))
10938
- .filter((monthData) => monthData.events.length > 0);
10921
+ // Group events by month and year, then sort chronologically (e.g., Aug 2025 before Apr 2026)
10922
+ const monthYearGroups = (() => {
10923
+ const groupsMap = new Map();
10924
+ for (const instance of eventInstances) {
10925
+ const date = new Date(instance.startTime);
10926
+ const year = date.getFullYear();
10927
+ const monthIndex = date.getMonth();
10928
+ const key = `${year}-${monthIndex}`;
10929
+ if (!groupsMap.has(key)) {
10930
+ groupsMap.set(key, {
10931
+ key,
10932
+ year,
10933
+ monthIndex,
10934
+ label: `${months[monthIndex]} ${year}`,
10935
+ events: [],
10936
+ minPrice: Number.POSITIVE_INFINITY,
10937
+ });
10938
+ }
10939
+ const group = groupsMap.get(key);
10940
+ group.events.push(instance);
10941
+ if (instance.price < group.minPrice)
10942
+ group.minPrice = instance.price;
10943
+ }
10944
+ return Array.from(groupsMap.values())
10945
+ .map((group) => ({
10946
+ ...group,
10947
+ events: group.events.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime()),
10948
+ }))
10949
+ .sort((a, b) => (a.year === b.year ? a.monthIndex - b.monthIndex : a.year - b.year));
10950
+ })();
10939
10951
  const handleEventInstanceSelect = (eventInstance) => {
10940
10952
  setSelectedEventInstanceId(eventInstance.id);
10941
10953
  onEventInstanceSelect(eventInstance);
10942
10954
  };
10943
- const toggleMonth = (monthIndex) => {
10944
- if (openMonths.has(monthIndex)) {
10955
+ const toggleGroup = (key) => {
10956
+ if (openGroups.has(key)) {
10945
10957
  // Close if already open
10946
- setOpenMonths(new Set());
10958
+ setOpenGroups(new Set());
10947
10959
  }
10948
10960
  else {
10949
10961
  // Open only this one, close others
10950
- setOpenMonths(new Set([monthIndex]));
10962
+ setOpenGroups(new Set([key]));
10951
10963
  }
10952
10964
  };
10953
10965
  const handleClose = () => {
@@ -11204,10 +11216,7 @@ function EventInstanceSelection({ eventInstances, selectedEventType, onEventInst
11204
11216
  minHeight: "400px",
11205
11217
  textAlign: "center",
11206
11218
  padding: "var(--bw-spacing)",
11207
- }, children: jsxs("div", { children: [jsx("div", { style: {
11208
- margin: "0 auto 16px",
11209
- fontSize: "48px",
11210
- }, children: "\uD83D\uDCC5" }), jsx("h3", { style: {
11219
+ }, children: jsxs("div", { children: [jsx("h3", { style: {
11211
11220
  marginBottom: "8px",
11212
11221
  fontWeight: "600",
11213
11222
  fontSize: "var(--bw-font-size-large)",
@@ -11275,137 +11284,137 @@ function EventInstanceSelection({ eventInstances, selectedEventType, onEventInst
11275
11284
  font-size: 1.1rem !important;
11276
11285
  }
11277
11286
  }
11278
- ` }), jsx(Sidebar, { isOpen: isOpen, onClose: handleClose, title: `Terminauswahl - ${selectedEventType?.name || "Event"}`, children: jsx("div", { className: "bw-event-instance-list", style: { padding: "24px" }, children: jsx("div", { style: {
11279
- display: "flex",
11280
- flexDirection: "column",
11281
- gap: "20px",
11282
- }, children: monthsWithEvents.map(({ month, index, events, minPrice }) => {
11283
- const monthPriceDisplayInfo = getMonthPriceDisplayInfo(minPrice);
11284
- return (jsx(Accordion, { title: month, priceInfo: jsx("div", { style: {
11285
- fontSize: "1rem",
11286
- backgroundColor: monthPriceDisplayInfo
11287
- ? monthPriceDisplayInfo.backgroundColor
11288
- : "#14532d",
11289
- color: monthPriceDisplayInfo ? monthPriceDisplayInfo.textColor : "#4ade80",
11290
- fontWeight: 500,
11291
- marginLeft: "auto",
11292
- padding: "4px 8px",
11293
- borderRadius: "var(--bw-border-radius-small)",
11294
- border: monthPriceDisplayInfo ? "none" : undefined,
11295
- boxShadow: monthPriceDisplayInfo
11296
- ? "0 2px 4px rgba(0, 0, 0, 0.2)"
11297
- : undefined,
11298
- }, children: `ab ${formatCurrency(minPrice)}` }), isOpen: openMonths.has(index), onToggle: () => toggleMonth(index), children: jsx("div", { style: {
11299
- display: "flex",
11300
- flexDirection: "column",
11301
- gap: "12px",
11302
- paddingTop: "12px",
11303
- }, children: events.map((event) => {
11304
- const availableSpots = event.maxParticipants - event.participantCount;
11305
- const isFullyBooked = availableSpots === 0;
11306
- const startDate = new Date(event.startTime);
11307
- const isPastEvent = today.toISOString() >= startDate.toISOString();
11308
- return (jsxs("div", { className: "bw-event-instance-card", style: {
11309
- position: "relative",
11310
- cursor: !isFullyBooked && !isPastEvent && event.bookingOpen
11311
- ? "pointer"
11312
- : "not-allowed",
11313
- border: "1px solid var(--bw-border-color)",
11314
- backgroundColor: "var(--bw-surface-color)",
11315
- borderRadius: "var(--bw-border-radius)",
11316
- padding: "16px 20px",
11317
- transition: "all 0.2s ease",
11318
- opacity: isFullyBooked || isPastEvent ? 0.3 : 1,
11319
- filter: isFullyBooked || isPastEvent ? "grayscale(40%)" : "none",
11320
- fontFamily: "var(--bw-font-family)",
11321
- }, onClick: () => {
11322
- if (!isFullyBooked && !isPastEvent && event.bookingOpen) {
11323
- handleEventInstanceSelect(event);
11324
- }
11325
- }, onMouseEnter: (e) => {
11326
- if (!isFullyBooked && !isPastEvent && event.bookingOpen) {
11327
- e.currentTarget.style.transform = "scale(1.02)";
11328
- e.currentTarget.style.backgroundColor =
11329
- "var(--bw-surface-muted, rgba(59, 130, 246, 0.1))";
11330
- }
11331
- }, onMouseLeave: (e) => {
11332
- if (!isFullyBooked && !isPastEvent && event.bookingOpen) {
11333
- e.currentTarget.style.transform = "scale(1)";
11334
- e.currentTarget.style.backgroundColor = "var(--bw-surface-color)";
11335
- }
11336
- }, children: [selectedEventInstanceId === event.id && isLoadingEventDetails && (jsx("div", { style: {
11337
- position: "absolute",
11338
- top: 0,
11339
- left: 0,
11340
- width: "100%",
11341
- height: "100%",
11342
- backgroundColor: "var(--bw-overlay-color, rgba(15, 23, 42, 0.8))",
11343
- borderRadius: "var(--bw-border-radius)",
11344
- display: "flex",
11345
- alignItems: "center",
11346
- justifyContent: "center",
11347
- }, children: jsx("div", { style: {
11348
- width: "32px",
11349
- height: "32px",
11350
- color: "var(--bw-highlight-color-muted, rgba(59, 130, 246, 0.8))",
11351
- animation: "spin 1s linear infinite",
11352
- fontSize: "32px",
11353
- }, children: spinner() }) })), jsx(SpecialPriceBadge, { price: event.price, yearPrices: yearPrices }), jsx(AllocationBadge, { availableSpots: availableSpots, maxParticipants: event.maxParticipants }), jsxs("div", { style: {
11354
- display: "flex",
11355
- justifyContent: "space-between",
11356
- width: "100%",
11357
- alignItems: "start",
11358
- gap: "12px",
11359
- marginBottom: "4px",
11360
- }, children: [jsxs("div", { style: { display: "flex", alignItems: "start", gap: "12px" }, children: [jsx("div", { className: "bw-event-instance-datebox", style: {
11361
- fontSize: "var(--bw-font-size)",
11362
- transition: "all 0.2s ease",
11363
- borderRadius: "var(--bw-border-radius-small)",
11364
- borderTop: `4px solid var(--bw-border-color)`,
11365
- border: "1px solid var(--bw-border-color)",
11366
- width: "40px",
11367
- height: "40px",
11368
- display: "flex",
11369
- alignItems: "center",
11370
- justifyContent: "center",
11371
- fontWeight: "bold",
11372
- color: "var(--bw-text-color)",
11373
- backgroundColor: "var(--bw-background-color)",
11374
- }, children: startDate.getDate() }), jsxs("div", { style: {
11375
- fontSize: "var(--bw-font-size)",
11376
- color: "var(--bw-text-color)",
11377
- display: "flex",
11378
- flexDirection: "column",
11379
- alignItems: "start",
11380
- justifyContent: "start",
11381
- lineHeight: "1.2",
11382
- }, children: [jsxs("div", { children: [jsx("span", { className: "bw-event-instance-title", style: { fontWeight: "600", marginBottom: "2px" }, children: formatWeekday(event.startTime) }), formatWeekday(event.startTime) !==
11383
- formatWeekday(event.endTime) && (jsxs(Fragment, { children: [jsx("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: " - " }), jsx("span", { className: "bw-event-instance-title", style: { fontWeight: "600", marginBottom: "2px" }, children: formatWeekday(event.endTime) })] }))] }), jsx("div", { children: formatWeekday(event.startTime) ===
11384
- formatWeekday(event.endTime) ? (jsxs(Fragment, { children: [jsx("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: formatTime(event.startTime) }), jsx("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: " - " }), jsx("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: formatTime(event.endTime) })] })) : (jsxs("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: [formatTime(event.startTime), " Uhr"] })) })] }), jsxs("span", { style: {
11385
- fontSize: "12px",
11386
- fontWeight: 400,
11387
- color: "var(--bw-text-muted)",
11388
- marginLeft: "6px",
11389
- background: "var(--bw-background-muted)",
11390
- whiteSpace: "nowrap",
11391
- }, children: [event.durationDays, " Tag", event.durationDays > 1 ? "e" : ""] })] }), jsx("div", { className: "bw-event-instance-price", style: {
11392
- textAlign: "right",
11393
- display: "flex",
11394
- flexDirection: "column",
11395
- alignItems: "end",
11396
- }, children: jsx(PriceDisplay, { price: event.price, yearPrices: yearPrices }) })] }), event.name !== selectedEventType?.name && (jsx("h4", { className: "bw-event-instance-title", style: {
11397
- fontSize: "var(--bw-font-size)",
11398
- fontWeight: "600",
11399
- color: "var(--bw-text-color)",
11400
- lineHeight: "1.25",
11401
- margin: "0 0 2px 0",
11402
- display: "flex",
11403
- alignItems: "center",
11404
- gap: "8px",
11405
- maxWidth: "230px",
11406
- }, children: event.name }))] }, event.id));
11407
- }) }) }, month));
11408
- }) }) }) })] }));
11287
+ ` }), jsxs(Sidebar, { isOpen: isOpen, onClose: handleClose, title: "Termin-Auswahl", children: [jsx("p", { className: "bw-event-instance-title", children: selectedEventType?.name }), jsx("div", { className: "bw-event-instance-list", style: { padding: "24px" }, children: jsx("div", { style: {
11288
+ display: "flex",
11289
+ flexDirection: "column",
11290
+ gap: "20px",
11291
+ }, children: monthYearGroups.map(({ key, label, events, minPrice }) => {
11292
+ const monthPriceDisplayInfo = getMonthPriceDisplayInfo(minPrice);
11293
+ return (jsx(Accordion, { title: label, priceInfo: jsx("div", { style: {
11294
+ fontSize: "1rem",
11295
+ backgroundColor: monthPriceDisplayInfo
11296
+ ? monthPriceDisplayInfo.backgroundColor
11297
+ : "#14532d",
11298
+ color: monthPriceDisplayInfo ? monthPriceDisplayInfo.textColor : "#4ade80",
11299
+ fontWeight: 500,
11300
+ marginLeft: "auto",
11301
+ padding: "4px 8px",
11302
+ borderRadius: "var(--bw-border-radius-small)",
11303
+ border: monthPriceDisplayInfo ? "none" : undefined,
11304
+ boxShadow: monthPriceDisplayInfo
11305
+ ? "0 2px 4px rgba(0, 0, 0, 0.2)"
11306
+ : undefined,
11307
+ }, children: `ab ${formatCurrency(minPrice)}` }), isOpen: openGroups.has(key), onToggle: () => toggleGroup(key), children: jsx("div", { style: {
11308
+ display: "flex",
11309
+ flexDirection: "column",
11310
+ gap: "12px",
11311
+ paddingTop: "12px",
11312
+ }, children: events.map((event) => {
11313
+ const availableSpots = event.maxParticipants - event.participantCount;
11314
+ const isFullyBooked = availableSpots === 0;
11315
+ const startDate = new Date(event.startTime);
11316
+ const isPastEvent = today.toISOString() >= startDate.toISOString();
11317
+ return (jsxs("div", { className: "bw-event-instance-card", style: {
11318
+ position: "relative",
11319
+ cursor: !isFullyBooked && !isPastEvent && event.bookingOpen
11320
+ ? "pointer"
11321
+ : "not-allowed",
11322
+ border: "1px solid var(--bw-border-color)",
11323
+ backgroundColor: "var(--bw-surface-color)",
11324
+ borderRadius: "var(--bw-border-radius)",
11325
+ padding: "16px 20px",
11326
+ transition: "all 0.2s ease",
11327
+ opacity: isFullyBooked || isPastEvent ? 0.3 : 1,
11328
+ filter: isFullyBooked || isPastEvent ? "grayscale(40%)" : "none",
11329
+ fontFamily: "var(--bw-font-family)",
11330
+ }, onClick: () => {
11331
+ if (!isFullyBooked && !isPastEvent && event.bookingOpen) {
11332
+ handleEventInstanceSelect(event);
11333
+ }
11334
+ }, onMouseEnter: (e) => {
11335
+ if (!isFullyBooked && !isPastEvent && event.bookingOpen) {
11336
+ e.currentTarget.style.transform = "scale(1.02)";
11337
+ e.currentTarget.style.backgroundColor =
11338
+ "var(--bw-surface-muted, rgba(59, 130, 246, 0.1))";
11339
+ }
11340
+ }, onMouseLeave: (e) => {
11341
+ if (!isFullyBooked && !isPastEvent && event.bookingOpen) {
11342
+ e.currentTarget.style.transform = "scale(1)";
11343
+ e.currentTarget.style.backgroundColor = "var(--bw-surface-color)";
11344
+ }
11345
+ }, children: [selectedEventInstanceId === event.id && isLoadingEventDetails && (jsx("div", { style: {
11346
+ position: "absolute",
11347
+ top: 0,
11348
+ left: 0,
11349
+ width: "100%",
11350
+ height: "100%",
11351
+ backgroundColor: "var(--bw-overlay-color, rgba(15, 23, 42, 0.8))",
11352
+ borderRadius: "var(--bw-border-radius)",
11353
+ display: "flex",
11354
+ alignItems: "center",
11355
+ justifyContent: "center",
11356
+ }, children: jsx("div", { style: {
11357
+ width: "32px",
11358
+ height: "32px",
11359
+ color: "var(--bw-highlight-color-muted, rgba(59, 130, 246, 0.8))",
11360
+ animation: "spin 1s linear infinite",
11361
+ fontSize: "32px",
11362
+ }, children: spinner() }) })), jsx(SpecialPriceBadge, { price: event.price, yearPrices: yearPrices }), jsx(AllocationBadge, { availableSpots: availableSpots, maxParticipants: event.maxParticipants }), jsxs("div", { style: {
11363
+ display: "flex",
11364
+ justifyContent: "space-between",
11365
+ width: "100%",
11366
+ alignItems: "start",
11367
+ gap: "12px",
11368
+ marginBottom: "4px",
11369
+ }, children: [jsxs("div", { style: { display: "flex", alignItems: "start", gap: "12px" }, children: [jsx("div", { className: "bw-event-instance-datebox", style: {
11370
+ fontSize: "var(--bw-font-size)",
11371
+ transition: "all 0.2s ease",
11372
+ borderRadius: "var(--bw-border-radius-small)",
11373
+ borderTop: `4px solid var(--bw-border-color)`,
11374
+ border: "1px solid var(--bw-border-color)",
11375
+ width: "40px",
11376
+ height: "40px",
11377
+ display: "flex",
11378
+ alignItems: "center",
11379
+ justifyContent: "center",
11380
+ fontWeight: "bold",
11381
+ color: "var(--bw-text-color)",
11382
+ backgroundColor: "var(--bw-background-color)",
11383
+ }, children: startDate.getDate() }), jsxs("div", { style: {
11384
+ fontSize: "var(--bw-font-size)",
11385
+ color: "var(--bw-text-color)",
11386
+ display: "flex",
11387
+ flexDirection: "column",
11388
+ alignItems: "start",
11389
+ justifyContent: "start",
11390
+ lineHeight: "1.2",
11391
+ }, children: [jsxs("div", { children: [jsx("span", { className: "bw-event-instance-title", style: { fontWeight: "600", marginBottom: "2px" }, children: formatWeekday(event.startTime) }), formatWeekday(event.startTime) !==
11392
+ formatWeekday(event.endTime) && (jsxs(Fragment, { children: [jsx("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: " - " }), jsx("span", { className: "bw-event-instance-title", style: { fontWeight: "600", marginBottom: "2px" }, children: formatWeekday(event.endTime) })] }))] }), jsx("div", { children: formatWeekday(event.startTime) ===
11393
+ formatWeekday(event.endTime) ? (jsxs(Fragment, { children: [jsx("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: formatTime(event.startTime) }), jsx("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: " - " }), jsx("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: formatTime(event.endTime) })] })) : (jsxs("span", { style: { color: "var(--bw-text-muted)", fontSize: "14px" }, children: [formatTime(event.startTime), " Uhr"] })) })] }), jsxs("span", { style: {
11394
+ fontSize: "12px",
11395
+ fontWeight: 400,
11396
+ color: "var(--bw-text-muted)",
11397
+ marginLeft: "6px",
11398
+ background: "var(--bw-background-muted)",
11399
+ whiteSpace: "nowrap",
11400
+ }, children: [event.durationDays, " Tag", event.durationDays > 1 ? "e" : ""] })] }), jsx("div", { className: "bw-event-instance-price", style: {
11401
+ textAlign: "right",
11402
+ display: "flex",
11403
+ flexDirection: "column",
11404
+ alignItems: "end",
11405
+ }, children: jsx(PriceDisplay, { price: event.price, yearPrices: yearPrices }) })] }), event.name !== selectedEventType?.name && (jsx("h4", { className: "bw-event-instance-title", style: {
11406
+ fontSize: "var(--bw-font-size)",
11407
+ fontWeight: "600",
11408
+ color: "var(--bw-text-color)",
11409
+ lineHeight: "1.25",
11410
+ margin: "0 0 2px 0",
11411
+ display: "flex",
11412
+ alignItems: "center",
11413
+ gap: "8px",
11414
+ maxWidth: "230px",
11415
+ }, children: event.name }))] }, event.id));
11416
+ }) }) }, key));
11417
+ }) }) })] })] }));
11409
11418
  }
11410
11419
 
11411
11420
  // Loading skeleton component for NextEventsPreview