pih-appointment-widget 0.0.27 → 0.0.28
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/README.md +70 -70
- package/babel.config.js +5 -5
- package/dist/App.js +10 -9
- package/dist/components/AppointmentPage.js +79 -55
- package/dist/pih-appointment-widget.umd.js +113 -114
- package/dist/pih-appointment-widget.umd.min.js +1 -1
- package/dist/services/appointmentService.js +20 -20
- package/dist/services/httpService.js +14 -18
- package/package.json +67 -67
- package/public/index.html +43 -43
- package/public/manifest.json +25 -25
- package/public/robots.txt +3 -3
- package/rollup.config.js +43 -43
- package/src/App.js +48 -48
- package/src/Example.js +11 -11
- package/src/components/AppointmentPage.js +2458 -2455
- package/src/constants/apiConfig.js +28 -28
- package/src/index.js +6 -6
- package/src/services/appointmentService.js +88 -88
- package/src/services/httpService.js +103 -103
package/README.md
CHANGED
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
# Getting Started with Create React App
|
|
2
|
-
|
|
3
|
-
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
|
4
|
-
|
|
5
|
-
## Available Scripts
|
|
6
|
-
|
|
7
|
-
In the project directory, you can run:
|
|
8
|
-
|
|
9
|
-
### `npm start`
|
|
10
|
-
|
|
11
|
-
Runs the app in the development mode.\
|
|
12
|
-
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
|
13
|
-
|
|
14
|
-
The page will reload when you make changes.\
|
|
15
|
-
You may also see any lint errors in the console.
|
|
16
|
-
|
|
17
|
-
### `npm test`
|
|
18
|
-
|
|
19
|
-
Launches the test runner in the interactive watch mode.\
|
|
20
|
-
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
|
21
|
-
|
|
22
|
-
### `npm run build`
|
|
23
|
-
|
|
24
|
-
Builds the app for production to the `build` folder.\
|
|
25
|
-
It correctly bundles React in production mode and optimizes the build for the best performance.
|
|
26
|
-
|
|
27
|
-
The build is minified and the filenames include the hashes.\
|
|
28
|
-
Your app is ready to be deployed!
|
|
29
|
-
|
|
30
|
-
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
|
31
|
-
|
|
32
|
-
### `npm run eject`
|
|
33
|
-
|
|
34
|
-
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
|
35
|
-
|
|
36
|
-
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
|
37
|
-
|
|
38
|
-
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
|
39
|
-
|
|
40
|
-
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
|
41
|
-
|
|
42
|
-
## Learn More
|
|
43
|
-
|
|
44
|
-
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
|
45
|
-
|
|
46
|
-
To learn React, check out the [React documentation](https://reactjs.org/).
|
|
47
|
-
|
|
48
|
-
### Code Splitting
|
|
49
|
-
|
|
50
|
-
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
|
51
|
-
|
|
52
|
-
### Analyzing the Bundle Size
|
|
53
|
-
|
|
54
|
-
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
|
55
|
-
|
|
56
|
-
### Making a Progressive Web App
|
|
57
|
-
|
|
58
|
-
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
|
59
|
-
|
|
60
|
-
### Advanced Configuration
|
|
61
|
-
|
|
62
|
-
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
|
63
|
-
|
|
64
|
-
### Deployment
|
|
65
|
-
|
|
66
|
-
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
|
67
|
-
|
|
68
|
-
### `npm run build` fails to minify
|
|
69
|
-
|
|
70
|
-
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
|
1
|
+
# Getting Started with Create React App
|
|
2
|
+
|
|
3
|
+
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
|
4
|
+
|
|
5
|
+
## Available Scripts
|
|
6
|
+
|
|
7
|
+
In the project directory, you can run:
|
|
8
|
+
|
|
9
|
+
### `npm start`
|
|
10
|
+
|
|
11
|
+
Runs the app in the development mode.\
|
|
12
|
+
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
|
13
|
+
|
|
14
|
+
The page will reload when you make changes.\
|
|
15
|
+
You may also see any lint errors in the console.
|
|
16
|
+
|
|
17
|
+
### `npm test`
|
|
18
|
+
|
|
19
|
+
Launches the test runner in the interactive watch mode.\
|
|
20
|
+
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
|
21
|
+
|
|
22
|
+
### `npm run build`
|
|
23
|
+
|
|
24
|
+
Builds the app for production to the `build` folder.\
|
|
25
|
+
It correctly bundles React in production mode and optimizes the build for the best performance.
|
|
26
|
+
|
|
27
|
+
The build is minified and the filenames include the hashes.\
|
|
28
|
+
Your app is ready to be deployed!
|
|
29
|
+
|
|
30
|
+
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
|
31
|
+
|
|
32
|
+
### `npm run eject`
|
|
33
|
+
|
|
34
|
+
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
|
35
|
+
|
|
36
|
+
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
|
37
|
+
|
|
38
|
+
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
|
39
|
+
|
|
40
|
+
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
|
41
|
+
|
|
42
|
+
## Learn More
|
|
43
|
+
|
|
44
|
+
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
|
45
|
+
|
|
46
|
+
To learn React, check out the [React documentation](https://reactjs.org/).
|
|
47
|
+
|
|
48
|
+
### Code Splitting
|
|
49
|
+
|
|
50
|
+
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
|
51
|
+
|
|
52
|
+
### Analyzing the Bundle Size
|
|
53
|
+
|
|
54
|
+
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
|
55
|
+
|
|
56
|
+
### Making a Progressive Web App
|
|
57
|
+
|
|
58
|
+
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
|
59
|
+
|
|
60
|
+
### Advanced Configuration
|
|
61
|
+
|
|
62
|
+
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
|
63
|
+
|
|
64
|
+
### Deployment
|
|
65
|
+
|
|
66
|
+
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
|
67
|
+
|
|
68
|
+
### `npm run build` fails to minify
|
|
69
|
+
|
|
70
|
+
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
package/babel.config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
presets: [
|
|
3
|
-
'@babel/preset-env',
|
|
4
|
-
'@babel/preset-react'
|
|
5
|
-
],
|
|
1
|
+
module.exports = {
|
|
2
|
+
presets: [
|
|
3
|
+
'@babel/preset-env',
|
|
4
|
+
'@babel/preset-react'
|
|
5
|
+
],
|
|
6
6
|
};
|
package/dist/App.js
CHANGED
|
@@ -19,20 +19,21 @@ exports.default = void 0;
|
|
|
19
19
|
var _react = _interopRequireDefault(require("react"));
|
|
20
20
|
var _reactDom = _interopRequireDefault(require("react-dom"));
|
|
21
21
|
var _AppointmentPage = _interopRequireWildcard(require("./components/AppointmentPage.js"));
|
|
22
|
-
function
|
|
22
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
23
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
23
24
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
24
25
|
let bookingWidgetInstance = null;
|
|
25
26
|
|
|
26
27
|
// SDK for embedding appointment widget
|
|
27
28
|
const BookingSDK = {
|
|
28
|
-
/**
|
|
29
|
-
* Show appointment widget with configuration
|
|
30
|
-
* @param {object} config - Configuration object
|
|
31
|
-
* @param {string} config.apiBaseUrl - Base URL for API
|
|
32
|
-
* @param {string} config.hospitalId - Hospital ID
|
|
33
|
-
* @param {number} config.doctorId - Doctor ID
|
|
34
|
-
* @param {string} config.joinCallUrl - Video call URL
|
|
35
|
-
* @param {function} onAction - Optional callback for actions
|
|
29
|
+
/**
|
|
30
|
+
* Show appointment widget with configuration
|
|
31
|
+
* @param {object} config - Configuration object
|
|
32
|
+
* @param {string} config.apiBaseUrl - Base URL for API
|
|
33
|
+
* @param {string} config.hospitalId - Hospital ID
|
|
34
|
+
* @param {number} config.doctorId - Doctor ID
|
|
35
|
+
* @param {string} config.joinCallUrl - Video call URL
|
|
36
|
+
* @param {function} onAction - Optional callback for actions
|
|
36
37
|
*/
|
|
37
38
|
showWidget: (config, onAction) => {
|
|
38
39
|
if (!bookingWidgetInstance) {
|
|
@@ -8,10 +8,8 @@ var _react = _interopRequireWildcard(require("react"));
|
|
|
8
8
|
var _appointmentService = require("../services/appointmentService");
|
|
9
9
|
var _httpService = require("../services/httpService");
|
|
10
10
|
var _apiConfig = require("../constants/apiConfig");
|
|
11
|
-
function
|
|
12
|
-
function
|
|
13
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
14
|
-
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
11
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
12
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
15
13
|
// Decode JWT payload (no verification; for display only). Returns {} on invalid/missing.
|
|
16
14
|
function getJwtPayload(token) {
|
|
17
15
|
if (!token || typeof token !== "string") return {};
|
|
@@ -21,7 +19,7 @@ function getJwtPayload(token) {
|
|
|
21
19
|
const base64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
22
20
|
const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, "=");
|
|
23
21
|
return JSON.parse(atob(padded));
|
|
24
|
-
} catch
|
|
22
|
+
} catch {
|
|
25
23
|
return {};
|
|
26
24
|
}
|
|
27
25
|
}
|
|
@@ -41,32 +39,26 @@ const PIH_APPOINTMENT_WIDGET_DATA_ATTR = "data-pih-widget";
|
|
|
41
39
|
|
|
42
40
|
// Extract from SSO login response (not from appToken JWT — these are only in login response)
|
|
43
41
|
function extractAppToken(response) {
|
|
44
|
-
var _ref, _ref2, _ref3, _response$data$access, _response$data, _response$data2;
|
|
45
42
|
if (!response || response.err) return null;
|
|
46
|
-
return
|
|
43
|
+
return response.data?.access_token ?? response.data?.token ?? response.token ?? response.accessToken ?? null;
|
|
47
44
|
}
|
|
48
45
|
function extractDoctorIdFromLoginResponse(response) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const id = (_ref4 = (_response$data$doctor = response.data.doctor_id) !== null && _response$data$doctor !== void 0 ? _response$data$doctor : response.data.doctorId) !== null && _ref4 !== void 0 ? _ref4 : null;
|
|
46
|
+
if (!response?.data) return null;
|
|
47
|
+
const id = response.data.doctor_id ?? response.data.doctorId ?? null;
|
|
52
48
|
console.log(id, 'extractDoctorIdFromLoginResponse -> id');
|
|
53
49
|
return id != null ? String(id) : null;
|
|
54
50
|
}
|
|
55
51
|
function extractUserNameFromLoginResponse(response) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const name = (_ref5 = (_ref6 = (_response$data$name = response.data.name) !== null && _response$data$name !== void 0 ? _response$data$name : response.data.doctor_name) !== null && _ref6 !== void 0 ? _ref6 : response.data.userName) !== null && _ref5 !== void 0 ? _ref5 : null;
|
|
52
|
+
if (!response?.data) return null;
|
|
53
|
+
const name = response.data.name ?? response.data.doctor_name ?? response.data.userName ?? null;
|
|
59
54
|
return name != null ? String(name) : null;
|
|
60
55
|
}
|
|
61
56
|
|
|
62
57
|
// Error boundary so a render error never shows a blank screen
|
|
63
58
|
class AppointmentErrorBoundary extends _react.Component {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
hasError: false
|
|
68
|
-
});
|
|
69
|
-
}
|
|
59
|
+
state = {
|
|
60
|
+
hasError: false
|
|
61
|
+
};
|
|
70
62
|
static getDerivedStateFromError() {
|
|
71
63
|
return {
|
|
72
64
|
hasError: true
|
|
@@ -123,21 +115,21 @@ class AppointmentErrorBoundary extends _react.Component {
|
|
|
123
115
|
}
|
|
124
116
|
|
|
125
117
|
// SDK Component - accepts configuration from parent app
|
|
126
|
-
const AppointmentPage =
|
|
118
|
+
const AppointmentPage = _ref => {
|
|
127
119
|
let {
|
|
128
120
|
config = {}
|
|
129
|
-
} =
|
|
121
|
+
} = _ref;
|
|
130
122
|
const [storedApiBaseUrl, setStoredApiBaseUrl] = (0, _react.useState)(() => {
|
|
131
123
|
try {
|
|
132
124
|
return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_API_BASE_URL) : null;
|
|
133
|
-
} catch
|
|
125
|
+
} catch {
|
|
134
126
|
return null;
|
|
135
127
|
}
|
|
136
128
|
});
|
|
137
129
|
const [storedHospitalId, setStoredHospitalId] = (0, _react.useState)(() => {
|
|
138
130
|
try {
|
|
139
131
|
return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_HOSPITAL_ID) : null;
|
|
140
|
-
} catch
|
|
132
|
+
} catch {
|
|
141
133
|
return null;
|
|
142
134
|
}
|
|
143
135
|
});
|
|
@@ -148,14 +140,14 @@ const AppointmentPage = _ref7 => {
|
|
|
148
140
|
const [storedIdToken, setStoredIdToken] = (0, _react.useState)(() => {
|
|
149
141
|
try {
|
|
150
142
|
return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_ID_TOKEN) : null;
|
|
151
|
-
} catch
|
|
143
|
+
} catch {
|
|
152
144
|
return null;
|
|
153
145
|
}
|
|
154
146
|
});
|
|
155
147
|
const [storedEmail, setStoredEmail] = (0, _react.useState)(() => {
|
|
156
148
|
try {
|
|
157
149
|
return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_EMAIL) : null;
|
|
158
|
-
} catch
|
|
150
|
+
} catch {
|
|
159
151
|
return null;
|
|
160
152
|
}
|
|
161
153
|
});
|
|
@@ -198,21 +190,21 @@ const AppointmentPage = _ref7 => {
|
|
|
198
190
|
const [appToken, setAppToken] = (0, _react.useState)(() => {
|
|
199
191
|
try {
|
|
200
192
|
return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_APP_TOKEN) : null;
|
|
201
|
-
} catch
|
|
193
|
+
} catch {
|
|
202
194
|
return null;
|
|
203
195
|
}
|
|
204
196
|
});
|
|
205
197
|
const [doctorIdFromLogin, setDoctorIdFromLogin] = (0, _react.useState)(() => {
|
|
206
198
|
try {
|
|
207
199
|
return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_DOCTOR_ID) : null;
|
|
208
|
-
} catch
|
|
200
|
+
} catch {
|
|
209
201
|
return null;
|
|
210
202
|
}
|
|
211
203
|
});
|
|
212
204
|
const [userName, setUserName] = (0, _react.useState)(() => {
|
|
213
205
|
try {
|
|
214
206
|
return typeof localStorage !== "undefined" ? localStorage.getItem(STORAGE_KEY_USER_NAME) : null;
|
|
215
|
-
} catch
|
|
207
|
+
} catch {
|
|
216
208
|
return null;
|
|
217
209
|
}
|
|
218
210
|
});
|
|
@@ -223,7 +215,7 @@ const AppointmentPage = _ref7 => {
|
|
|
223
215
|
const hasId = localStorage.getItem(STORAGE_KEY_ID_TOKEN);
|
|
224
216
|
const hasEmail = localStorage.getItem(STORAGE_KEY_EMAIL);
|
|
225
217
|
return !hasApp && !!(hasId && hasEmail);
|
|
226
|
-
} catch
|
|
218
|
+
} catch {
|
|
227
219
|
return false;
|
|
228
220
|
}
|
|
229
221
|
});
|
|
@@ -285,7 +277,7 @@ const AppointmentPage = _ref7 => {
|
|
|
285
277
|
const y = date.getFullYear();
|
|
286
278
|
const m = String(date.getMonth() + 1).padStart(2, "0");
|
|
287
279
|
const d = String(date.getDate()).padStart(2, "0");
|
|
288
|
-
return
|
|
280
|
+
return `${y}-${m}-${d}`;
|
|
289
281
|
};
|
|
290
282
|
const getDateRange = option => {
|
|
291
283
|
const today = new Date();
|
|
@@ -316,8 +308,8 @@ const AppointmentPage = _ref7 => {
|
|
|
316
308
|
to = formatLocalDate(lastOfMonth);
|
|
317
309
|
break;
|
|
318
310
|
case "currentYear":
|
|
319
|
-
from =
|
|
320
|
-
to =
|
|
311
|
+
from = `${today.getFullYear()}-01-01`;
|
|
312
|
+
to = `${today.getFullYear()}-12-31`;
|
|
321
313
|
break;
|
|
322
314
|
default:
|
|
323
315
|
from = to = getTodayDate();
|
|
@@ -342,7 +334,7 @@ const AppointmentPage = _ref7 => {
|
|
|
342
334
|
case "currentYear":
|
|
343
335
|
return "Current Year";
|
|
344
336
|
case "custom":
|
|
345
|
-
return isMobile ? "Custom" :
|
|
337
|
+
return isMobile ? "Custom" : `${fromDate} to ${toDate}`;
|
|
346
338
|
default:
|
|
347
339
|
return "Today";
|
|
348
340
|
}
|
|
@@ -427,12 +419,12 @@ const AppointmentPage = _ref7 => {
|
|
|
427
419
|
|
|
428
420
|
// Helper to get unique identifier from appointment
|
|
429
421
|
const getAppointmentId = appointment => {
|
|
430
|
-
return
|
|
422
|
+
return appointment?.id || appointment?._id || appointment?.appointmentId || appointment?.patientId || JSON.stringify(appointment);
|
|
431
423
|
};
|
|
432
424
|
|
|
433
425
|
// Generate avatar with first letter if no image
|
|
434
426
|
const getPatientAvatar = appointment => {
|
|
435
|
-
if (appointment
|
|
427
|
+
if (appointment?.image) {
|
|
436
428
|
return appointment.image;
|
|
437
429
|
}
|
|
438
430
|
// Return null to use the letter avatar component
|
|
@@ -471,6 +463,7 @@ const AppointmentPage = _ref7 => {
|
|
|
471
463
|
}
|
|
472
464
|
};
|
|
473
465
|
const fetchAppointments = (0, _react.useCallback)(async () => {
|
|
466
|
+
console.log(appToken, 'fetchAppointments -> appToken');
|
|
474
467
|
if (!appToken) return;
|
|
475
468
|
console.log(doctorIdFromLogin, 'fetchAppointments -> doctorIdFromLogin');
|
|
476
469
|
const doctorId = doctorIdFromLogin;
|
|
@@ -551,7 +544,6 @@ const AppointmentPage = _ref7 => {
|
|
|
551
544
|
setCallLoading(true);
|
|
552
545
|
setCallError(null);
|
|
553
546
|
try {
|
|
554
|
-
var _response$data3;
|
|
555
547
|
const callConfig = {
|
|
556
548
|
apiBaseUrl,
|
|
557
549
|
hospitalId,
|
|
@@ -579,7 +571,7 @@ const AppointmentPage = _ref7 => {
|
|
|
579
571
|
setCallError("Session expired. Re-authenticating...");
|
|
580
572
|
return;
|
|
581
573
|
}
|
|
582
|
-
if (response.err || !
|
|
574
|
+
if (response.err || !response.data?.token) {
|
|
583
575
|
setCallError(String(response.err || "Failed to initiate call"));
|
|
584
576
|
return;
|
|
585
577
|
}
|
|
@@ -798,6 +790,8 @@ const AppointmentPage = _ref7 => {
|
|
|
798
790
|
}, [showPipVideo, isPipMinimized, isPipFullscreen, pipSize]);
|
|
799
791
|
|
|
800
792
|
// Call login API only when we have no appToken (or got 401 / 403 and need refresh). Otherwise use stored appToken.
|
|
793
|
+
// appToken is intentionally included in deps: when the persist effect clears it (new idToken from Flutter after
|
|
794
|
+
// re-login), this effect re-evaluates needLogin with appToken=null and fires SSO for the new session.
|
|
801
795
|
(0, _react.useEffect)(() => {
|
|
802
796
|
const needLogin = idToken && email && (!appToken || refreshLoginTrigger > 0);
|
|
803
797
|
if (!needLogin) return;
|
|
@@ -849,7 +843,7 @@ const AppointmentPage = _ref7 => {
|
|
|
849
843
|
return () => {
|
|
850
844
|
cancelled = true;
|
|
851
845
|
};
|
|
852
|
-
}, [apiBaseUrl, hospitalId, idToken, email, refreshLoginTrigger]);
|
|
846
|
+
}, [apiBaseUrl, hospitalId, idToken, email, refreshLoginTrigger, appToken]);
|
|
853
847
|
|
|
854
848
|
// Reset page to 1 and clear call error when filters/tab change
|
|
855
849
|
(0, _react.useEffect)(() => {
|
|
@@ -872,7 +866,32 @@ const AppointmentPage = _ref7 => {
|
|
|
872
866
|
|
|
873
867
|
// Add responsive styles and animations
|
|
874
868
|
const style = document.createElement("style");
|
|
875
|
-
style.innerHTML =
|
|
869
|
+
style.innerHTML = `
|
|
870
|
+
@keyframes spin {
|
|
871
|
+
0% { transform: rotate(0deg); }
|
|
872
|
+
100% { transform: rotate(360deg); }
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
@media (max-width: 768px) {
|
|
876
|
+
.appointments-grid {
|
|
877
|
+
grid-template-columns: 1.5fr 1fr 0.8fr !important;
|
|
878
|
+
}
|
|
879
|
+
.appointments-header-grid {
|
|
880
|
+
grid-template-columns: 1.5fr 1fr 0.8fr !important;
|
|
881
|
+
}
|
|
882
|
+
.hide-on-mobile {
|
|
883
|
+
display: none !important;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
@media (max-width: 480px) {
|
|
887
|
+
.appointments-header-grid {
|
|
888
|
+
font-size: 10px !important;
|
|
889
|
+
}
|
|
890
|
+
.appointments-grid {
|
|
891
|
+
font-size: 11px !important;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
`;
|
|
876
895
|
document.head.appendChild(style);
|
|
877
896
|
|
|
878
897
|
// Handle window resize
|
|
@@ -925,7 +944,7 @@ const AppointmentPage = _ref7 => {
|
|
|
925
944
|
justifyContent: "center",
|
|
926
945
|
padding: "24px"
|
|
927
946
|
}
|
|
928
|
-
}, /*#__PURE__*/_react.default.createElement("style", null,
|
|
947
|
+
}, /*#__PURE__*/_react.default.createElement("style", null, `@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }`), /*#__PURE__*/_react.default.createElement("div", {
|
|
929
948
|
style: {
|
|
930
949
|
width: "40px",
|
|
931
950
|
height: "40px",
|
|
@@ -1676,7 +1695,7 @@ const AppointmentPage = _ref7 => {
|
|
|
1676
1695
|
style: {
|
|
1677
1696
|
fontSize: "13px"
|
|
1678
1697
|
}
|
|
1679
|
-
}, searchQuery ?
|
|
1698
|
+
}, searchQuery ? `No appointments found for "${searchQuery}"` : "No appointments found"), searchQuery && /*#__PURE__*/_react.default.createElement("button", {
|
|
1680
1699
|
onClick: () => setSearchQuery(""),
|
|
1681
1700
|
style: {
|
|
1682
1701
|
marginTop: "12px",
|
|
@@ -1955,7 +1974,7 @@ const AppointmentPage = _ref7 => {
|
|
|
1955
1974
|
fontWeight: "700",
|
|
1956
1975
|
fontSize: isMobile ? "12px" : "13px"
|
|
1957
1976
|
}
|
|
1958
|
-
},
|
|
1977
|
+
}, selectedAppointment?.specialisation || selectedAppointment?.speciality || "N/A")), /*#__PURE__*/_react.default.createElement("div", {
|
|
1959
1978
|
style: {
|
|
1960
1979
|
textAlign: "right"
|
|
1961
1980
|
}
|
|
@@ -1970,7 +1989,7 @@ const AppointmentPage = _ref7 => {
|
|
|
1970
1989
|
fontWeight: "700",
|
|
1971
1990
|
fontSize: isMobile ? "12px" : "13px"
|
|
1972
1991
|
}
|
|
1973
|
-
},
|
|
1992
|
+
}, selectedAppointment?.type || selectedAppointment?.appointmentType || "Online"))), /*#__PURE__*/_react.default.createElement("div", {
|
|
1974
1993
|
style: {
|
|
1975
1994
|
display: "flex",
|
|
1976
1995
|
justifyContent: "space-between"
|
|
@@ -1990,7 +2009,7 @@ const AppointmentPage = _ref7 => {
|
|
|
1990
2009
|
fontWeight: "700",
|
|
1991
2010
|
fontSize: isMobile ? "12px" : "13px"
|
|
1992
2011
|
}
|
|
1993
|
-
},
|
|
2012
|
+
}, selectedAppointment?.date || selectedAppointment?.appointmentDate || "N/A")), /*#__PURE__*/_react.default.createElement("div", {
|
|
1994
2013
|
style: {
|
|
1995
2014
|
textAlign: "right"
|
|
1996
2015
|
}
|
|
@@ -2005,7 +2024,7 @@ const AppointmentPage = _ref7 => {
|
|
|
2005
2024
|
fontWeight: "700",
|
|
2006
2025
|
fontSize: isMobile ? "12px" : "13px"
|
|
2007
2026
|
}
|
|
2008
|
-
},
|
|
2027
|
+
}, selectedAppointment?.time || selectedAppointment?.appointmentTime || "N/A"))), /*#__PURE__*/_react.default.createElement("div", {
|
|
2009
2028
|
style: {
|
|
2010
2029
|
display: "flex",
|
|
2011
2030
|
justifyContent: "space-between"
|
|
@@ -2025,7 +2044,7 @@ const AppointmentPage = _ref7 => {
|
|
|
2025
2044
|
fontWeight: "700",
|
|
2026
2045
|
fontSize: isMobile ? "12px" : "13px"
|
|
2027
2046
|
}
|
|
2028
|
-
},
|
|
2047
|
+
}, selectedAppointment?.doctor || selectedAppointment?.doctorName || "N/A"))), /*#__PURE__*/_react.default.createElement("div", {
|
|
2029
2048
|
style: {
|
|
2030
2049
|
display: "flex",
|
|
2031
2050
|
justifyContent: "space-between"
|
|
@@ -2045,7 +2064,7 @@ const AppointmentPage = _ref7 => {
|
|
|
2045
2064
|
fontWeight: "700",
|
|
2046
2065
|
fontSize: isMobile ? "12px" : "13px"
|
|
2047
2066
|
}
|
|
2048
|
-
},
|
|
2067
|
+
}, selectedAppointment?.hospital || selectedAppointment?.hospitalName || "N/A"))), /*#__PURE__*/_react.default.createElement("div", {
|
|
2049
2068
|
style: {
|
|
2050
2069
|
display: "flex",
|
|
2051
2070
|
justifyContent: "space-between"
|
|
@@ -2066,7 +2085,7 @@ const AppointmentPage = _ref7 => {
|
|
|
2066
2085
|
fontSize: isMobile ? "11px" : "12px",
|
|
2067
2086
|
lineHeight: "1.4"
|
|
2068
2087
|
}
|
|
2069
|
-
},
|
|
2088
|
+
}, selectedAppointment?.reason || selectedAppointment?.reasonForAppointment || "No reason provided"))), activeTab === "upcoming" && /*#__PURE__*/_react.default.createElement("div", {
|
|
2070
2089
|
style: {
|
|
2071
2090
|
display: "flex",
|
|
2072
2091
|
flexDirection: isMobile ? "column" : "row",
|
|
@@ -2119,12 +2138,12 @@ const AppointmentPage = _ref7 => {
|
|
|
2119
2138
|
}, "Select an appointment to view details"))))))), showPipVideo && /*#__PURE__*/_react.default.createElement("div", {
|
|
2120
2139
|
style: {
|
|
2121
2140
|
position: "fixed",
|
|
2122
|
-
left: isPipFullscreen ? "0" : isMobile ? "10px" :
|
|
2123
|
-
top: isPipFullscreen ? "0" : isMobile ? "70px" :
|
|
2141
|
+
left: isPipFullscreen ? "0" : isMobile ? "10px" : `${pipPosition.x}px`,
|
|
2142
|
+
top: isPipFullscreen ? "0" : isMobile ? "70px" : `${pipPosition.y}px`,
|
|
2124
2143
|
right: isPipFullscreen ? "0" : isMobile ? "10px" : "auto",
|
|
2125
2144
|
bottom: isPipFullscreen ? "0" : "auto",
|
|
2126
|
-
width: isPipFullscreen ? "100vw" : isMobile ? "calc(100vw - 20px)" : isPipMinimized ? "350px" :
|
|
2127
|
-
height: isPipFullscreen ? "100vh" : isPipMinimized ? "auto" : isMobile ? "300px" :
|
|
2145
|
+
width: isPipFullscreen ? "100vw" : isMobile ? "calc(100vw - 20px)" : isPipMinimized ? "350px" : `${pipSize.width}px`,
|
|
2146
|
+
height: isPipFullscreen ? "100vh" : isPipMinimized ? "auto" : isMobile ? "300px" : `${pipSize.height}px`,
|
|
2128
2147
|
background: "#FFFFFF",
|
|
2129
2148
|
borderRadius: isPipFullscreen ? "0" : "8px",
|
|
2130
2149
|
boxShadow: "0 8px 24px rgba(0, 0, 0, 0.3)",
|
|
@@ -2175,7 +2194,7 @@ const AppointmentPage = _ref7 => {
|
|
|
2175
2194
|
textOverflow: "ellipsis",
|
|
2176
2195
|
whiteSpace: "nowrap"
|
|
2177
2196
|
}
|
|
2178
|
-
}, "Video Call - ",
|
|
2197
|
+
}, "Video Call - ", selectedAppointment?.patientName || "Patient")), /*#__PURE__*/_react.default.createElement("div", {
|
|
2179
2198
|
style: {
|
|
2180
2199
|
display: "flex",
|
|
2181
2200
|
gap: isMobile ? "4px" : "6px",
|
|
@@ -2304,7 +2323,7 @@ const AppointmentPage = _ref7 => {
|
|
|
2304
2323
|
src: (() => {
|
|
2305
2324
|
if (!callToken) return "";
|
|
2306
2325
|
const base = String(joinCallUrlBase || "").replace(/\/?$/, "/");
|
|
2307
|
-
return
|
|
2326
|
+
return `${base}${callToken}`;
|
|
2308
2327
|
})(),
|
|
2309
2328
|
style: {
|
|
2310
2329
|
width: "100%",
|
|
@@ -2375,7 +2394,12 @@ const AppointmentPage = _ref7 => {
|
|
|
2375
2394
|
background: "transparent",
|
|
2376
2395
|
zIndex: 10001
|
|
2377
2396
|
}
|
|
2378
|
-
})), /*#__PURE__*/_react.default.createElement("style", null,
|
|
2397
|
+
})), /*#__PURE__*/_react.default.createElement("style", null, `
|
|
2398
|
+
@keyframes pulse {
|
|
2399
|
+
0%, 100% { opacity: 1; }
|
|
2400
|
+
50% { opacity: 0.5; }
|
|
2401
|
+
}
|
|
2402
|
+
`))), showAuthError && /*#__PURE__*/_react.default.createElement("div", {
|
|
2379
2403
|
style: {
|
|
2380
2404
|
position: "fixed",
|
|
2381
2405
|
inset: 0,
|