@blazeo.com/appointment-client 1.0.5 → 1.0.7

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.
Files changed (121) hide show
  1. package/blazeo.com-appointment-client-1.0.7.tgz +0 -0
  2. package/dist/calendar/blazeoCalendarRelationMethods.d.ts +4 -36
  3. package/dist/calendar/blazeoCalendarRelationMethods.js +0 -1
  4. package/dist/calendar/buildUnifiedCalendarView.d.ts +39 -0
  5. package/dist/calendar/buildUnifiedCalendarView.js +280 -0
  6. package/dist/calendar/calendarCreation.d.ts +27 -0
  7. package/dist/calendar/calendarCreation.js +167 -0
  8. package/dist/calendar/calendarCreationFacade.d.ts +4 -13
  9. package/dist/calendar/calendarCreationFacade.js +3 -5
  10. package/dist/calendar/createCalendar.d.ts +67 -37
  11. package/dist/calendar/createCalendar.js +1 -3
  12. package/dist/calendar/fetchCalendarDetails.d.ts +41 -18
  13. package/dist/calendar/fetchCalendarDetails.js +261 -51
  14. package/dist/calendar/fetchCalendarWithOpeningHours.d.ts +25 -21
  15. package/dist/calendar/fetchCalendarWithOpeningHours.js +114 -75
  16. package/dist/calendar/getAllParticipantOpeningHours.d.ts +22 -0
  17. package/dist/calendar/getAllParticipantOpeningHours.js +22 -0
  18. package/dist/calendar/getOpeningHours.d.ts +8 -0
  19. package/dist/calendar/getOpeningHours.js +9 -0
  20. package/dist/calendar/getParticipantOpeningHours.d.ts +37 -0
  21. package/dist/calendar/getParticipantOpeningHours.js +48 -0
  22. package/dist/calendar/getParticipants.d.ts +7 -0
  23. package/dist/calendar/getParticipants.js +13 -0
  24. package/dist/calendar/mapCalendarBoToBlazeoSnapshot.d.ts +9 -9
  25. package/dist/calendar/mapCalendarBoToBlazeoSnapshot.js +43 -43
  26. package/dist/calendar/mapCalendarToBlazeoSnapshot.d.ts +22 -3
  27. package/dist/calendar/mapCalendarToBlazeoSnapshot.js +0 -1
  28. package/dist/calendar/mapToDesiredResponse.d.ts +70 -0
  29. package/dist/calendar/mapToDesiredResponse.js +99 -0
  30. package/dist/config/applyBlazeoClientConfig.d.ts +2 -2
  31. package/dist/config/applyBlazeoClientConfig.js +13 -13
  32. package/dist/config/applyBlazeoDefaults.d.ts +0 -1
  33. package/dist/config/applyBlazeoDefaults.js +3 -3
  34. package/dist/config/blazeo.config.d.ts +10 -10
  35. package/dist/config/blazeo.config.js +10 -10
  36. package/dist/config/blazeoClientDefaults.d.ts +1 -2
  37. package/dist/config/blazeoClientDefaults.js +2 -3
  38. package/dist/config/ensureBlazeoHttpReady.d.ts +17 -0
  39. package/dist/config/ensureBlazeoHttpReady.js +31 -0
  40. package/dist/config/initializeAppointmentClient.d.ts +8 -28
  41. package/dist/config/initializeAppointmentClient.js +11 -24
  42. package/dist/config/syncBlazeoConnection.d.ts +6 -0
  43. package/dist/config/syncBlazeoConnection.js +18 -0
  44. package/dist/events/appointmentEventFacade.d.ts +55 -32
  45. package/dist/events/appointmentEventFacade.js +5 -10
  46. package/dist/events/mapAppointmentToEventSnapshot.d.ts +1 -4
  47. package/dist/events/mapAppointmentToEventSnapshot.js +0 -1
  48. package/dist/exampleData.d.ts +114 -10
  49. package/dist/exampleData.js +4 -5
  50. package/dist/facade/calendarCreationFacade.d.ts +39 -39
  51. package/dist/facade/calendarCreationFacade.js +95 -95
  52. package/dist/facade/mapCalendarBOToSnapshot.d.ts +9 -9
  53. package/dist/facade/mapCalendarBOToSnapshot.js +43 -43
  54. package/dist/facades/index.d.ts +11 -11
  55. package/dist/facades/index.js +11 -11
  56. package/dist/index.d.ts +26 -82
  57. package/dist/index.js +23 -33
  58. package/dist/models/CalendarRootModel.d.ts +36 -11
  59. package/dist/models/CalendarRootModel.js +22 -5
  60. package/dist/models/CalendarSlotModel.d.ts +8 -8
  61. package/dist/models/CalendarSlotModel.js +7 -7
  62. package/dist/models/EventModel.d.ts +10 -10
  63. package/dist/models/EventModel.js +9 -9
  64. package/dist/models/ParticipantModel.d.ts +8 -8
  65. package/dist/models/ParticipantModel.js +7 -7
  66. package/dist/models/index.d.ts +4 -4
  67. package/dist/models/index.js +4 -4
  68. package/dist/types/appointment.d.ts +27 -27
  69. package/dist/types/appointment.js +5 -5
  70. package/dist/types/calendar.d.ts +51 -51
  71. package/dist/types/calendar.js +5 -5
  72. package/dist/types/calendarBo.d.ts +61 -61
  73. package/dist/types/calendarBo.js +5 -5
  74. package/package.json +8 -2
  75. package/sample/.env.example +5 -0
  76. package/sample/build_error.txt +0 -0
  77. package/sample/demo.js +70 -0
  78. package/sample/package-lock.json +5 -2
  79. package/sample/package.json +3 -1
  80. package/sample/scripts/getInfoByCalendar.mjs +36 -0
  81. package/sample/scripts/getParticipantOpeningHours.mjs +48 -0
  82. package/sample/src/AllParticipantOpeningHoursTab.jsx +82 -0
  83. package/sample/src/App2.jsx +60 -3
  84. package/sample/src/AvailabilityTab.jsx +8 -3
  85. package/sample/src/BlazeoConnectionSettings.jsx +17 -16
  86. package/sample/src/CreateCalendarTab.jsx +23 -6
  87. package/sample/src/EventTab.jsx +31 -8
  88. package/sample/src/FetchCalendarTab.jsx +114 -38
  89. package/sample/src/OpeningHoursTab.jsx +87 -0
  90. package/sample/src/ParticipantInfoTab.jsx +77 -0
  91. package/sample/src/ParticipantOpeningHoursTab.jsx +98 -0
  92. package/sample/src/ParticipantTab.jsx +13 -4
  93. package/sample/src/blazeoBootstrap.js +30 -0
  94. package/sample/src/blazeoDemoError.js +14 -0
  95. package/sample/src/blazeoPushConnection.js +23 -0
  96. package/sample/src/main.jsx +3 -3
  97. package/sample/vite.config.js +19 -5
  98. package/src/calendar/blazeoCalendarRelationMethods.ts +19 -0
  99. package/src/calendar/buildUnifiedCalendarView.ts +345 -0
  100. package/src/calendar/calendarCreation.ts +179 -0
  101. package/src/calendar/createCalendar.ts +243 -0
  102. package/src/calendar/fetchCalendarDetails.ts +316 -0
  103. package/src/calendar/fetchCalendarWithOpeningHours.ts +130 -0
  104. package/src/calendar/getAllParticipantOpeningHours.ts +30 -0
  105. package/src/calendar/getOpeningHours.ts +10 -0
  106. package/src/calendar/getParticipantOpeningHours.ts +55 -0
  107. package/src/calendar/getParticipants.ts +17 -0
  108. package/src/calendar/mapCalendarToBlazeoSnapshot.ts +46 -0
  109. package/src/calendar/mapToDesiredResponse.ts +104 -0
  110. package/src/config/applyBlazeoDefaults.ts +14 -0
  111. package/src/config/blazeoClientDefaults.ts +11 -0
  112. package/src/config/ensureBlazeoHttpReady.ts +41 -0
  113. package/src/config/initializeAppointmentClient.ts +24 -0
  114. package/src/config/syncBlazeoConnection.ts +19 -0
  115. package/src/events/appointmentEventFacade.ts +148 -0
  116. package/src/events/mapAppointmentToEventSnapshot.ts +65 -0
  117. package/src/exampleData.ts +79 -0
  118. package/src/index.ts +51 -0
  119. package/src/models/CalendarRootModel.ts +60 -0
  120. package/tsconfig.json +16 -0
  121. package/blazeo.com-appointment-client-1.0.5.tgz +0 -0
@@ -1,6 +1,6 @@
1
- /**
2
- * Plain shapes aligned with CalendarBO / MemberBO / OpeningHourBO for mapping
3
- * into `@blazeo.com/calendar-client` `CalendarModel.create` (see `mapCalendarBoToBlazeoSnapshot.ts`).
4
- */
5
- export {};
1
+ /**
2
+ * Plain shapes aligned with CalendarBO / MemberBO / OpeningHourBO for mapping
3
+ * into `@blazeo.com/calendar-client` `CalendarModel.create` (see `mapCalendarBoToBlazeoSnapshot.ts`).
4
+ */
5
+ export {};
6
6
  //# sourceMappingURL=calendar.js.map
@@ -1,62 +1,62 @@
1
- /**
2
- * Plain shapes aligned with CalendarBO / MemberBO / OpeningHourBO for mapping
3
- * into `@blazeo.com/calendar-client` `CalendarModel.create` (see `mapCalendarBoToBlazeoSnapshot.ts`).
4
- */
5
- export type CalendarBOInput = {
6
- /** Blazeo / API calendar identifier; falls back to `thirdPartyCalendarId` or `"new"`. */
7
- calendarId?: string;
8
- thirdPartyCalendarId?: string;
9
- /** Apex / DB numeric id when known */
10
- serverId?: number;
11
- companyKey?: string | null;
12
- purpose?: string;
13
- name?: string | null;
14
- timeZoneId?: string | null;
15
- description?: string | null;
16
- /** Apex `AssignmentType` — mapped to Blazeo `assignmentMethod`. */
17
- assignmentType?: number;
18
- assignmentMethod?: number;
19
- duration?: number;
20
- bookingLimit?: number | null;
21
- calendarJson?: string | null;
22
- isThirdPartySaved?: boolean;
23
- durationUnit?: number;
24
- minimumBookingNotice?: number;
25
- minimumBookingNoticeUnit?: number;
26
- minimumCancelationNotice?: number;
27
- minimumCancelationNoticeUnit?: number;
28
- futureLimit?: number;
29
- futureLimitUnit?: number;
30
- bufferTime?: number | null;
31
- bufferTimeUnit?: number;
32
- calendarLink?: string | null;
33
- status?: number;
34
- location?: string | null;
35
- bookingPageTitle?: string | null;
36
- themeId?: number | null;
37
- createdOn?: string | null;
38
- modifiedOn?: string | null;
39
- /** Not part of Blazeo Calendar MST — reserved for future participant/hours steps. */
40
- members?: MemberBOInput[];
41
- openingHours?: OpeningHourBOInput[];
42
- };
43
- export type MemberBOInput = {
44
- id: number;
45
- name?: string | null;
46
- email?: string;
47
- thirdPartyMemberId?: string | null;
48
- };
49
- export type OpeningHourBOInput = {
50
- id: number;
51
- openingHourId?: string;
52
- calendarId?: string;
53
- participantId?: string;
54
- days: number[];
55
- startHour: number;
56
- startMinute: number;
57
- endHour: number;
58
- endMinute: number;
59
- off: boolean;
60
- member: number;
61
- };
1
+ /**
2
+ * Plain shapes aligned with CalendarBO / MemberBO / OpeningHourBO for mapping
3
+ * into `@blazeo.com/calendar-client` `CalendarModel.create` (see `mapCalendarBoToBlazeoSnapshot.ts`).
4
+ */
5
+ export type CalendarBOInput = {
6
+ /** Blazeo / API calendar identifier; falls back to `thirdPartyCalendarId` or `"new"`. */
7
+ calendarId?: string;
8
+ thirdPartyCalendarId?: string;
9
+ /** Apex / DB numeric id when known */
10
+ serverId?: number;
11
+ companyKey?: string | null;
12
+ purpose?: string;
13
+ name?: string | null;
14
+ timeZoneId?: string | null;
15
+ description?: string | null;
16
+ /** Apex `AssignmentType` — mapped to Blazeo `assignmentMethod`. */
17
+ assignmentType?: number;
18
+ assignmentMethod?: number;
19
+ duration?: number;
20
+ bookingLimit?: number | null;
21
+ calendarJson?: string | null;
22
+ isThirdPartySaved?: boolean;
23
+ durationUnit?: number;
24
+ minimumBookingNotice?: number;
25
+ minimumBookingNoticeUnit?: number;
26
+ minimumCancelationNotice?: number;
27
+ minimumCancelationNoticeUnit?: number;
28
+ futureLimit?: number;
29
+ futureLimitUnit?: number;
30
+ bufferTime?: number | null;
31
+ bufferTimeUnit?: number;
32
+ calendarLink?: string | null;
33
+ status?: number;
34
+ location?: string | null;
35
+ bookingPageTitle?: string | null;
36
+ themeId?: number | null;
37
+ createdOn?: string | null;
38
+ modifiedOn?: string | null;
39
+ /** Not part of Blazeo Calendar MST — reserved for future participant/hours steps. */
40
+ members?: MemberBOInput[];
41
+ openingHours?: OpeningHourBOInput[];
42
+ };
43
+ export type MemberBOInput = {
44
+ id: number;
45
+ name?: string | null;
46
+ email?: string;
47
+ thirdPartyMemberId?: string | null;
48
+ };
49
+ export type OpeningHourBOInput = {
50
+ id: number;
51
+ openingHourId?: string;
52
+ calendarId?: string;
53
+ participantId?: string;
54
+ days: number[];
55
+ startHour: number;
56
+ startMinute: number;
57
+ endHour: number;
58
+ endMinute: number;
59
+ off: boolean;
60
+ member: number;
61
+ };
62
62
  //# sourceMappingURL=calendarBo.d.ts.map
@@ -1,6 +1,6 @@
1
- /**
2
- * Plain shapes aligned with CalendarBO / MemberBO / OpeningHourBO for mapping
3
- * into `@blazeo.com/calendar-client` `CalendarModel.create` (see `mapCalendarBoToBlazeoSnapshot.ts`).
4
- */
5
- export {};
1
+ /**
2
+ * Plain shapes aligned with CalendarBO / MemberBO / OpeningHourBO for mapping
3
+ * into `@blazeo.com/calendar-client` `CalendarModel.create` (see `mapCalendarBoToBlazeoSnapshot.ts`).
4
+ */
5
+ export {};
6
6
  //# sourceMappingURL=calendarBo.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blazeo.com/appointment-client",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -14,9 +14,15 @@
14
14
  "types": "./dist/index.d.ts"
15
15
  }
16
16
  },
17
+ "scripts": {
18
+ "build": "tsc"
19
+ },
17
20
  "dependencies": {
18
- "@blazeo.com/calendar-client": "^1.0.17",
21
+ "@blazeo.com/calendar-client": "^1.0.18",
19
22
  "mobx": "^6.13.7",
20
23
  "mobx-state-tree": "^7.0.2"
24
+ },
25
+ "devDependencies": {
26
+ "typescript": "^5.0.0"
21
27
  }
22
28
  }
@@ -0,0 +1,5 @@
1
+ # Copy to `.env` or `.env.local` in this folder and set your API host (no trailing slash).
2
+ # Vite exposes only vars prefixed with VITE_ to the browser.
3
+ VITE_BLAZEO_BASE_URL=https://your-blazeo-api.example.com
4
+ # Optional, if your tenant uses it:
5
+ # VITE_BLAZEO_CONSUMER=
Binary file
package/sample/demo.js ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Demo usage of appointment-client
3
+ * Run with: node demo.js
4
+ */
5
+ import {
6
+ initializeAppointmentClient,
7
+ fetchCalendarDetails
8
+ } from "../dist/index.js"; // In a real app, use 'appointment-client'
9
+
10
+ async function runDemo() {
11
+ const TEST_CALENDAR_ID = "66f42c26-f48e-4965-b772-88155986898d"; // Example ID
12
+ const BASE_URL = "https://api.blazeo.com"; // Example API URL
13
+
14
+ console.log("--- Appointment Client Demo ---");
15
+
16
+ // 1. Initialize the client
17
+ console.log(`Initializing client with BASE_URL: ${BASE_URL}`);
18
+ initializeAppointmentClient({
19
+ baseUrl: BASE_URL,
20
+ consumer: "demo-app"
21
+ });
22
+
23
+ try {
24
+ // 2. Pass calendarId and fetch details
25
+ console.log(`Fetching details for calendarId: ${TEST_CALENDAR_ID}...`);
26
+ const details = await fetchCalendarDetails(TEST_CALENDAR_ID);
27
+
28
+ if (!details.meta.ok) {
29
+ console.error("Failed to fetch calendar details:", details.meta.reason);
30
+ return;
31
+ }
32
+
33
+ if (details.calendarView) {
34
+ console.log("\n--- calendarView (preview) ---");
35
+ console.log(
36
+ JSON.stringify({
37
+ members: details.calendarView.members?.length ?? 0,
38
+ openingHours: details.calendarView.openingHours?.length ?? 0,
39
+ })
40
+ );
41
+ }
42
+
43
+ // 3. Retrieve and print Opening hours
44
+ console.log("\n--- Opening Hours ---");
45
+ if (details.openingHours.length > 0) {
46
+ details.openingHours.forEach((oh, idx) => {
47
+ console.log(`[${idx + 1}] Day: ${oh.day}, Start: ${oh.startHour}:${oh.startMinute}, End: ${oh.endHour}:${oh.endMinute}`);
48
+ });
49
+ } else {
50
+ console.log("No opening hours found.");
51
+ }
52
+
53
+ // 4. Retrieve and print Participants
54
+ console.log("\n--- Participants ---");
55
+ if (details.participants.length > 0) {
56
+ details.participants.forEach((p, idx) => {
57
+ console.log(`[${idx + 1}] Name: ${p.name}, Email: ${p.email || 'N/A'}`);
58
+ });
59
+ } else {
60
+ console.log("No participants found.");
61
+ }
62
+
63
+ console.log("\nDemo completed successfully.");
64
+
65
+ } catch (error) {
66
+ console.error("An error occurred during the demo:", error.message);
67
+ }
68
+ }
69
+
70
+ runDemo();
@@ -17,11 +17,14 @@
17
17
  },
18
18
  "..": {
19
19
  "name": "@blazeo.com/appointment-client",
20
- "version": "1.0.4",
20
+ "version": "1.0.6",
21
21
  "dependencies": {
22
- "@blazeo.com/calendar-client": "^1.0.17",
22
+ "@blazeo.com/calendar-client": "^1.0.18",
23
23
  "mobx": "^6.13.7",
24
24
  "mobx-state-tree": "^7.0.2"
25
+ },
26
+ "devDependencies": {
27
+ "typescript": "^5.0.0"
25
28
  }
26
29
  },
27
30
  "../node_modules/@blazeo.com/calendar-client": {
@@ -5,7 +5,9 @@
5
5
  "scripts": {
6
6
  "dev": "vite",
7
7
  "build": "vite build",
8
- "preview": "vite preview"
8
+ "preview": "vite preview",
9
+ "openinghours:participant": "node ./scripts/getParticipantOpeningHours.mjs",
10
+ "participants:info": "node ./scripts/getInfoByCalendar.mjs"
9
11
  },
10
12
  "dependencies": {
11
13
  "appointment-client": "file:..",
@@ -0,0 +1,36 @@
1
+ import { initializeAppointmentClient, CalendarParticipantModel } from "appointment-client";
2
+
3
+ function reqEnv(name, fallback = "") {
4
+ const v = (process.env[name] ?? fallback).trim();
5
+ return v;
6
+ }
7
+
8
+ const baseUrl = reqEnv("BLAZEO_BASE_URL");
9
+ const consumer = reqEnv("BLAZEO_CONSUMER");
10
+ const calendarId = reqEnv("CALENDAR_ID");
11
+
12
+ if (!baseUrl) {
13
+ console.error("Missing env BLAZEO_BASE_URL");
14
+ process.exit(1);
15
+ }
16
+ if (!calendarId) {
17
+ console.error("Missing env CALENDAR_ID");
18
+ process.exit(1);
19
+ }
20
+
21
+ initializeAppointmentClient({ baseUrl, ...(consumer ? { consumer } : {}) });
22
+
23
+ const info = await CalendarParticipantModel.getInfoByCalendar(calendarId);
24
+
25
+ console.log(
26
+ JSON.stringify(
27
+ {
28
+ calendarId,
29
+ count: Array.isArray(info) ? info.length : 0,
30
+ info,
31
+ },
32
+ null,
33
+ 2
34
+ )
35
+ );
36
+
@@ -0,0 +1,48 @@
1
+ import {
2
+ initializeAppointmentClient,
3
+ CalendarModel,
4
+ normalizeParticipantOpeningHoursResponse,
5
+ } from "appointment-client";
6
+
7
+ function reqEnv(name, fallback = "") {
8
+ const v = (process.env[name] ?? fallback).trim();
9
+ return v;
10
+ }
11
+
12
+ const baseUrl = reqEnv("BLAZEO_BASE_URL");
13
+ const consumer = reqEnv("BLAZEO_CONSUMER");
14
+ const calendarId = reqEnv("CALENDAR_ID");
15
+
16
+ if (!baseUrl) {
17
+ console.error("Missing env BLAZEO_BASE_URL");
18
+ process.exit(1);
19
+ }
20
+ if (!calendarId) {
21
+ console.error("Missing env CALENDAR_ID");
22
+ process.exit(1);
23
+ }
24
+
25
+ initializeAppointmentClient({ baseUrl, ...(consumer ? { consumer } : {}) });
26
+
27
+ const cal = await CalendarModel.get(calendarId);
28
+ if (!cal) {
29
+ console.error("Calendar not found:", calendarId);
30
+ process.exit(2);
31
+ }
32
+
33
+ const raw = await cal.getParticipantOpeningHours({});
34
+ const { list } = normalizeParticipantOpeningHoursResponse(raw);
35
+
36
+ console.log(
37
+ JSON.stringify(
38
+ {
39
+ calendarId,
40
+ count: Array.isArray(list) ? list.length : 0,
41
+ openingHours: Array.isArray(list) ? list : null,
42
+ raw,
43
+ },
44
+ null,
45
+ 2
46
+ )
47
+ );
48
+
@@ -0,0 +1,82 @@
1
+ import { useState } from "react";
2
+ import { ensureBlazeoHttpReady, getAllParticipantOpeningHours } from "appointment-client";
3
+ import { configureBlazeoFromEffective, useBlazeoConnection } from "./BlazeoConnectionSettings.jsx";
4
+ import { mapBlazeoDemoError } from "./blazeoDemoError.js";
5
+
6
+ export function AllParticipantOpeningHoursTab() {
7
+ const { effective, connectionOpts } = useBlazeoConnection();
8
+ const [calendarId, setCalendarId] = useState("");
9
+ const [busy, setBusy] = useState(false);
10
+ const [error, setError] = useState("");
11
+ const [output, setOutput] = useState("");
12
+
13
+ async function handleFetch(e) {
14
+ e.preventDefault();
15
+ setError("");
16
+ setOutput("");
17
+ const id = calendarId.trim();
18
+ if (!id) return setError("Enter a calendar id.");
19
+ if (!effective.baseUrl) return setError("Set Base URL in the connection card above.");
20
+
21
+ configureBlazeoFromEffective(effective);
22
+ ensureBlazeoHttpReady({
23
+ baseUrl: effective.baseUrl,
24
+ ...(effective.consumer ? { consumer: effective.consumer } : {}),
25
+ });
26
+ setBusy(true);
27
+ try {
28
+ const res = await getAllParticipantOpeningHours(id, {
29
+ ...connectionOpts,
30
+ baseUrl: effective.baseUrl,
31
+ ...(effective.consumer ? { consumer: effective.consumer } : {}),
32
+ });
33
+ setOutput(JSON.stringify(res, null, 2));
34
+ } catch (err) {
35
+ setError(mapBlazeoDemoError(err instanceof Error ? err.message : String(err)));
36
+ } finally {
37
+ setBusy(false);
38
+ }
39
+ }
40
+
41
+ return (
42
+ <>
43
+ <div className="card">
44
+ <h2>All Participant Opening Hours</h2>
45
+ <p className="muted small">
46
+ Calls <code>getAllParticipantOpeningHours(calendarId)</code> (API:{" "}
47
+ <code>GET /Calendar/Participant/OpeningHours/All/Get</code>).
48
+ </p>
49
+ <form onSubmit={handleFetch} className="form">
50
+ <label className="form__label">
51
+ <span>Calendar id</span>
52
+ <input
53
+ type="text"
54
+ className="form__input"
55
+ value={calendarId}
56
+ onChange={(e) => setCalendarId(e.target.value)}
57
+ autoComplete="off"
58
+ />
59
+ </label>
60
+ <button type="submit" className="btn btn--secondary" disabled={busy}>
61
+ {busy ? "Loading…" : "Fetch all participant opening hours"}
62
+ </button>
63
+ </form>
64
+ </div>
65
+
66
+ {error ? (
67
+ <div className="card card--error" role="alert">
68
+ <h2>Error</h2>
69
+ <pre className="pre-block">{error}</pre>
70
+ </div>
71
+ ) : null}
72
+
73
+ {output ? (
74
+ <div className="card card--success">
75
+ <h2>Result</h2>
76
+ <pre className="pre-block">{output}</pre>
77
+ </div>
78
+ ) : null}
79
+ </>
80
+ );
81
+ }
82
+
@@ -3,19 +3,29 @@ import {
3
3
  BlazeoConnectionProvider,
4
4
  useBlazeoConnection,
5
5
  } from "./BlazeoConnectionSettings.jsx";
6
+ import { ensureBlazeoHttpReady, getConfig } from "appointment-client";
6
7
  import { CalendarTab } from "./CalendarTab.jsx";
7
8
  import { EventTab } from "./EventTab.jsx";
8
9
  import { ParticipantTab } from "./ParticipantTab.jsx";
10
+ import { ParticipantInfoTab } from "./ParticipantInfoTab.jsx";
11
+ import { ParticipantOpeningHoursTab } from "./ParticipantOpeningHoursTab.jsx";
12
+ import { AllParticipantOpeningHoursTab } from "./AllParticipantOpeningHoursTab.jsx";
9
13
  import { AvailabilityTab } from "./AvailabilityTab.jsx";
10
14
  import { CreateCalendarTab } from "./CreateCalendarTab.jsx";
11
15
  import { FetchCalendarTab } from "./FetchCalendarTab.jsx";
16
+ import { OpeningHoursTab } from "./OpeningHoursTab.jsx";
12
17
 
13
18
  const TABS = [
14
19
  { id: "calendar", label: "Calendar" },
15
- { id: "fetch", label: "Fetch calendar" },
20
+ /** `FetchCalendarTab` `fetchCalendarDetails` + `calendarView` (unified object). */
21
+ { id: "fetch", label: "Fetch · calendarView" },
16
22
  { id: "create", label: "Create calendar" },
17
23
  { id: "event", label: "Event" },
18
24
  { id: "participant", label: "Participant" },
25
+ { id: "participant-info", label: "Participant info" },
26
+ { id: "opening-hours", label: "Opening Hours" },
27
+ { id: "participant-opening-hours", label: "Participant opening hours" },
28
+ { id: "all-participant-opening-hours", label: "All participant opening hours" },
19
29
  { id: "availability", label: "Availability / booking" },
20
30
  ];
21
31
 
@@ -26,14 +36,23 @@ function ConnectionSettingsCard() {
26
36
  setBaseUrlInput,
27
37
  setConsumerInput,
28
38
  effective,
39
+ connectionOpts,
29
40
  } = useBlazeoConnection();
30
41
 
42
+ const ready = ensureBlazeoHttpReady({
43
+ baseUrl: effective.baseUrl,
44
+ ...(effective.consumer ? { consumer: effective.consumer } : {}),
45
+ });
46
+ const cfg = getConfig?.() ?? null;
47
+
31
48
  return (
32
49
  <div className="card connection-card">
33
50
  <h2>Blazeo connection</h2>
34
51
  <p className="muted small">
35
52
  Values are saved in <code>localStorage</code>. Empty fields fall back to{" "}
36
- <code>appointment-client/src/config/blazeoClientDefaults.ts</code>.
53
+ <code>appointment-client/src/config/blazeoClientDefaults.ts</code>. All tabs use the <strong>effective</strong> URL
54
+ here and run <code>pushBlazeoConnection</code> + <code>ensureBlazeoHttpReady</code> so calendar APIs receive{" "}
55
+ <code>baseUrl</code> from this card.
37
56
  </p>
38
57
  <p className="muted small">
39
58
  Effective:{" "}
@@ -45,6 +64,12 @@ function ConnectionSettingsCard() {
45
64
  </>
46
65
  ) : null}
47
66
  </p>
67
+ <p className="muted small">
68
+ Debug: <code>connectionOpts</code> → <code>{JSON.stringify(connectionOpts)}</code> ·{" "}
69
+ <code>ensureBlazeoHttpReady</code> →{" "}
70
+ <code>{ready.ok ? "ok" : "missing_base_url"}</code> · <code>getConfig().baseUrl</code> →{" "}
71
+ <code>{cfg?.baseUrl ?? "(null)"}</code>
72
+ </p>
48
73
  <div className="connection-card__row">
49
74
  <label className="form__label">
50
75
  <span>Base URL</span>
@@ -80,7 +105,11 @@ function AppShell() {
80
105
  <main className="page">
81
106
  <header className="header">
82
107
  <h1>appointment-client</h1>
83
- <p className="muted">Browser sample — tabbed explorer for the npm package</p>
108
+ <p className="muted">
109
+ Browser sample — set <strong>Base URL</strong> in <strong>Blazeo connection</strong> below first; every tab uses
110
+ those values for <code>configure</code> + API calls. Tab <strong>Fetch · calendarView</strong> shows the unified{" "}
111
+ <code>calendarView</code> object.
112
+ </p>
84
113
  </header>
85
114
 
86
115
  <ConnectionSettingsCard />
@@ -128,6 +157,34 @@ function AppShell() {
128
157
  <ParticipantTab />
129
158
  </section>
130
159
  )}
160
+ {activeId === "participant-info" && (
161
+ <section role="tabpanel" id="panel-participant-info" aria-labelledby="tab-participant-info">
162
+ <ParticipantInfoTab />
163
+ </section>
164
+ )}
165
+ {activeId === "opening-hours" && (
166
+ <section role="tabpanel" id="panel-opening-hours" aria-labelledby="tab-opening-hours">
167
+ <OpeningHoursTab />
168
+ </section>
169
+ )}
170
+ {activeId === "participant-opening-hours" && (
171
+ <section
172
+ role="tabpanel"
173
+ id="panel-participant-opening-hours"
174
+ aria-labelledby="tab-participant-opening-hours"
175
+ >
176
+ <ParticipantOpeningHoursTab />
177
+ </section>
178
+ )}
179
+ {activeId === "all-participant-opening-hours" && (
180
+ <section
181
+ role="tabpanel"
182
+ id="panel-all-participant-opening-hours"
183
+ aria-labelledby="tab-all-participant-opening-hours"
184
+ >
185
+ <AllParticipantOpeningHoursTab />
186
+ </section>
187
+ )}
131
188
  {activeId === "availability" && (
132
189
  <section role="tabpanel" id="panel-availability" aria-labelledby="tab-availability">
133
190
  <AvailabilityTab />
@@ -1,6 +1,7 @@
1
1
  import { useMemo, useState } from "react";
2
- import { EventModel } from "appointment-client";
2
+ import { ensureBlazeoHttpReady, EventModel } from "appointment-client";
3
3
  import { configureBlazeoFromEffective, useBlazeoConnection } from "./BlazeoConnectionSettings.jsx";
4
+ import { mapBlazeoDemoError } from "./blazeoDemoError.js";
4
5
 
5
6
  function parseYmd(ymd) {
6
7
  const t = (ymd ?? "").trim();
@@ -10,7 +11,7 @@ function parseYmd(ymd) {
10
11
  }
11
12
 
12
13
  export function AvailabilityTab() {
13
- const { effective } = useBlazeoConnection();
14
+ const { effective, connectionOpts } = useBlazeoConnection();
14
15
  const [calendarId, setCalendarId] = useState("");
15
16
  const [date, setDate] = useState(() => new Date().toISOString().slice(0, 10));
16
17
  const [offsetMinutes, setOffsetMinutes] = useState(-new Date().getTimezoneOffset());
@@ -30,13 +31,17 @@ export function AvailabilityTab() {
30
31
  if (!parts) return setError("Pick a valid date.");
31
32
  if (!effective.baseUrl) return setError("Set Base URL above.");
32
33
  configureBlazeoFromEffective(effective);
34
+ ensureBlazeoHttpReady({
35
+ baseUrl: effective.baseUrl,
36
+ ...(effective.consumer ? { consumer: effective.consumer } : {}),
37
+ });
33
38
 
34
39
  setBusy(true);
35
40
  try {
36
41
  const list = await EventModel.getAvailability(id, parts.y, parts.m, parts.d, opts);
37
42
  setOutput(JSON.stringify(list.map((n) => n.toJSON?.() ?? n), null, 2));
38
43
  } catch (err) {
39
- setError(err instanceof Error ? err.message : String(err));
44
+ setError(mapBlazeoDemoError(err instanceof Error ? err.message : String(err)));
40
45
  } finally {
41
46
  setBusy(false);
42
47
  }