medos-sdk 1.1.9 → 1.1.11
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/client/MedosClient.d.ts +1 -0
- package/dist/client/MedosClient.js +7 -0
- package/dist/components/AppointmentCalender.js +22 -8
- package/dist/components/AppointmentConfirmationStep.d.ts +4 -0
- package/dist/components/AppointmentConfirmationStep.js +50 -52
- package/dist/components/AppointmentDateTimeModal.d.ts +4 -0
- package/dist/components/AppointmentDateTimeModal.js +216 -165
- package/dist/components/AppointmentSummaryStep.d.ts +12 -0
- package/dist/components/AppointmentSummaryStep.js +168 -0
- package/dist/components/BookingOptionStep.d.ts +14 -0
- package/dist/components/BookingOptionStep.js +346 -0
- package/dist/components/ContactInformationStep.js +13 -6
- package/dist/components/ContactPreferenceStep.js +16 -6
- package/dist/components/DoctorSelectModal.d.ts +5 -0
- package/dist/components/DoctorSelectModal.js +169 -74
- package/dist/components/EnquiryForm.js +84 -72
- package/dist/components/Icons/CloseIcon.d.ts +9 -0
- package/dist/components/Icons/CloseIcon.js +5 -0
- package/dist/components/InquiryDetailsStep.js +11 -6
- package/dist/components/PatientDetailsStep.js +17 -12
- package/dist/components/PatientSelectionStep.d.ts +12 -0
- package/dist/components/PatientSelectionStep.js +254 -0
- package/dist/components/PhoneVerificationStep.js +1 -1
- package/dist/components/SuccessStep.js +1 -1
- package/dist/components/appointment-booking/AppointmentCalender.d.ts +5 -0
- package/dist/components/appointment-booking/AppointmentCalender.js +247 -0
- package/dist/components/appointment-booking/hooks/index.d.ts +3 -0
- package/dist/components/appointment-booking/hooks/index.js +3 -0
- package/dist/components/appointment-booking/hooks/useAppointmentFlow.d.ts +8 -0
- package/dist/components/appointment-booking/hooks/useAppointmentFlow.js +318 -0
- package/dist/components/appointment-booking/hooks/useAppointmentState.d.ts +9 -0
- package/dist/components/appointment-booking/hooks/useAppointmentState.js +125 -0
- package/dist/components/appointment-booking/hooks/useInitializeAddresses.d.ts +1 -0
- package/dist/components/appointment-booking/hooks/useInitializeAddresses.js +55 -0
- package/dist/components/appointment-booking/index.d.ts +5 -0
- package/dist/components/appointment-booking/index.js +3 -0
- package/dist/components/appointment-booking/types.d.ts +291 -0
- package/dist/components/appointment-booking/types.js +49 -0
- package/dist/components/appointment-modal-styles.d.ts +259 -0
- package/dist/components/appointment-modal-styles.js +395 -0
- package/dist/components/constant.d.ts +2 -0
- package/dist/components/constant.js +15 -0
- package/dist/components/custom-calendar.js +20 -11
- package/dist/components/styles.js +93 -52
- package/dist/components/theme-styles.d.ts +5 -4
- package/dist/components/theme-styles.js +221 -125
- package/dist/components/types.d.ts +12 -139
- package/dist/components/types.js +15 -32
- package/dist/components/uiComponents/SelectDropdown.d.ts +1 -1
- package/dist/components/uiComponents/SelectDropdown.js +24 -24
- package/dist/components/utils.d.ts +3 -0
- package/dist/components/utils.js +59 -0
- package/dist/components/validation.d.ts +2 -0
- package/dist/components/validation.js +41 -0
- package/dist/core/theme/index.d.ts +1 -0
- package/dist/core/theme/index.js +1 -0
- package/dist/core/theme/responsive.d.ts +15 -0
- package/dist/core/theme/responsive.js +113 -0
- package/dist/core/theme/themes.js +16 -4
- package/dist/core/theme/types.d.ts +8 -0
- package/dist/enquiry-form/validation.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/react/ThemeProvider.d.ts +2 -1
- package/dist/react/ThemeProvider.js +49 -10
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +1 -1
- package/dist/services/AppointmentService.d.ts +80 -2
- package/dist/services/AppointmentService.js +114 -5
- package/dist/services/WorkspaceService.d.ts +58 -3
- package/dist/services/WorkspaceService.js +10 -1
- package/dist/vanilla/AppointmentCalendarWidget.d.ts +9 -7
- package/dist/vanilla/AppointmentCalendarWidget.js +834 -384
- package/dist/vanilla/EnquiryFormWidget.d.ts +1 -0
- package/dist/vanilla/EnquiryFormWidget.js +25 -43
- package/dist/vanilla/client/MedosClient.d.ts +1 -0
- package/dist/vanilla/components/AppointmentConfirmationStep.d.ts +4 -0
- package/dist/vanilla/components/AppointmentDateTimeModal.d.ts +4 -0
- package/dist/vanilla/components/AppointmentSummaryStep.d.ts +12 -0
- package/dist/vanilla/components/BookingOptionStep.d.ts +14 -0
- package/dist/vanilla/components/DoctorSelectModal.d.ts +5 -0
- package/dist/vanilla/components/Icons/CloseIcon.d.ts +9 -0
- package/dist/vanilla/components/PatientSelectionStep.d.ts +12 -0
- package/dist/vanilla/components/VanillaCalendar.js +33 -18
- package/dist/vanilla/components/VanillaIcons.d.ts +5 -0
- package/dist/vanilla/components/VanillaIcons.js +92 -0
- package/dist/vanilla/components/VanillaSelect.d.ts +3 -0
- package/dist/vanilla/components/VanillaSelect.js +93 -5
- package/dist/vanilla/components/appointment-booking/AppointmentCalender.d.ts +5 -0
- package/dist/vanilla/components/appointment-booking/hooks/index.d.ts +3 -0
- package/dist/vanilla/components/appointment-booking/hooks/useAppointmentFlow.d.ts +8 -0
- package/dist/vanilla/components/appointment-booking/hooks/useAppointmentState.d.ts +9 -0
- package/dist/vanilla/components/appointment-booking/hooks/useInitializeAddresses.d.ts +1 -0
- package/dist/vanilla/components/appointment-booking/index.d.ts +5 -0
- package/dist/vanilla/components/appointment-booking/types.d.ts +291 -0
- package/dist/vanilla/components/appointment-modal-styles.d.ts +259 -0
- package/dist/vanilla/components/constant.d.ts +2 -0
- package/dist/vanilla/components/theme-styles.d.ts +5 -4
- package/dist/vanilla/components/types.d.ts +12 -139
- package/dist/vanilla/components/uiComponents/SelectDropdown.d.ts +1 -1
- package/dist/vanilla/components/utils.d.ts +3 -0
- package/dist/vanilla/components/validation.d.ts +2 -0
- package/dist/vanilla/core/theme/index.d.ts +1 -0
- package/dist/vanilla/core/theme/responsive.d.ts +15 -0
- package/dist/vanilla/core/theme/types.d.ts +8 -0
- package/dist/vanilla/enquiry-widget.js +374 -53
- package/dist/vanilla/index.d.ts +3 -1
- package/dist/vanilla/react/ThemeProvider.d.ts +2 -1
- package/dist/vanilla/react/index.d.ts +2 -1
- package/dist/vanilla/services/AppointmentService.d.ts +80 -2
- package/dist/vanilla/services/WorkspaceService.d.ts +58 -3
- package/dist/vanilla/vanilla/AppointmentCalendarWidget.d.ts +9 -7
- package/dist/vanilla/vanilla/EnquiryFormWidget.d.ts +1 -0
- package/dist/vanilla/vanilla/components/VanillaIcons.d.ts +5 -0
- package/dist/vanilla/vanilla/components/VanillaSelect.d.ts +3 -0
- package/dist/vanilla/widget.css +833 -207
- package/dist/vanilla/widget.js +6463 -5687
- package/package.json +1 -1
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
onError?: (err: Error) => void;
|
|
4
|
-
};
|
|
1
|
+
export type { AppointmentState, AppointmentAction, Patient, SessionPack, AvailablePackage, BookingOptionType, } from "./appointment-booking/types";
|
|
2
|
+
export { INITIAL_STATE } from "./appointment-booking/types";
|
|
5
3
|
export type PhoneVerificationStepProps = {
|
|
6
|
-
state:
|
|
7
|
-
dispatch: React.Dispatch<
|
|
4
|
+
state: any;
|
|
5
|
+
dispatch: React.Dispatch<any>;
|
|
8
6
|
onSendOtp: () => Promise<void>;
|
|
9
7
|
onVerifyOtp: () => Promise<void>;
|
|
10
8
|
onBack: () => void;
|
|
11
9
|
onContinue: () => void;
|
|
12
10
|
};
|
|
13
11
|
export type PatientDetailsStepProps = {
|
|
14
|
-
state:
|
|
15
|
-
dispatch: React.Dispatch<
|
|
12
|
+
state: any;
|
|
13
|
+
dispatch: React.Dispatch<any>;
|
|
16
14
|
onBack: () => void;
|
|
17
15
|
onSubmit: () => Promise<void>;
|
|
16
|
+
isFirstStep?: boolean;
|
|
18
17
|
};
|
|
19
18
|
export type SuccessStepProps = {
|
|
20
19
|
onReset: () => void;
|
|
@@ -33,138 +32,12 @@ export type OtpInputSectionProps = {
|
|
|
33
32
|
onOtpChange: (code: string) => void;
|
|
34
33
|
};
|
|
35
34
|
export type PatientInfoSectionProps = {
|
|
36
|
-
state:
|
|
37
|
-
dispatch: React.Dispatch<
|
|
35
|
+
state: any;
|
|
36
|
+
dispatch: React.Dispatch<any>;
|
|
38
37
|
};
|
|
39
38
|
export type AddressInfoSectionProps = {
|
|
40
|
-
state:
|
|
41
|
-
dispatch: React.Dispatch<
|
|
42
|
-
};
|
|
43
|
-
export interface AppointmentState {
|
|
44
|
-
step: number;
|
|
45
|
-
loading: boolean;
|
|
46
|
-
error: string | null;
|
|
47
|
-
workspaceId: number | null;
|
|
48
|
-
addresses: AddressItem[];
|
|
49
|
-
addressDoctorsMap: Record<number, Doctor[]>;
|
|
50
|
-
selectedAddress: number | null;
|
|
51
|
-
selectedDoctor: number | null;
|
|
52
|
-
selectedDate: Date;
|
|
53
|
-
slots: Slot[];
|
|
54
|
-
selectedSlot: Slot | null;
|
|
55
|
-
consultationMode: "ONLINE" | "OFFLINE";
|
|
56
|
-
consultationCharge: string;
|
|
57
|
-
patientName: string;
|
|
58
|
-
patientAge: string;
|
|
59
|
-
patientEmail: string;
|
|
60
|
-
patientGender: string;
|
|
61
|
-
bloodGroup: string;
|
|
62
|
-
patientAddress: string;
|
|
63
|
-
patientCity: string;
|
|
64
|
-
patientState: string;
|
|
65
|
-
patientCountry: string;
|
|
66
|
-
patientZipcode: string;
|
|
67
|
-
patientLandmark: string;
|
|
68
|
-
countryCode: string;
|
|
69
|
-
patientPhone: string;
|
|
70
|
-
otpCode: string;
|
|
71
|
-
otpSent: boolean;
|
|
72
|
-
otpVerified: boolean;
|
|
73
|
-
otpSending: boolean;
|
|
74
|
-
otpVerifying: boolean;
|
|
75
|
-
}
|
|
76
|
-
export type AppointmentAction = {
|
|
77
|
-
type: "SET_STEP";
|
|
78
|
-
payload: number;
|
|
79
|
-
} | {
|
|
80
|
-
type: "SET_LOADING";
|
|
81
|
-
payload: boolean;
|
|
82
|
-
} | {
|
|
83
|
-
type: "SET_ERROR";
|
|
84
|
-
payload: string | null;
|
|
85
|
-
} | {
|
|
86
|
-
type: "SET_WORKSPACE";
|
|
87
|
-
payload: {
|
|
88
|
-
id: number;
|
|
89
|
-
addresses: AddressItem[];
|
|
90
|
-
};
|
|
91
|
-
} | {
|
|
92
|
-
type: "SET_SELECTED_ADDRESS";
|
|
93
|
-
payload: number | null;
|
|
94
|
-
} | {
|
|
95
|
-
type: "SET_SELECTED_DOCTOR";
|
|
96
|
-
payload: number | null;
|
|
97
|
-
} | {
|
|
98
|
-
type: "SET_SELECTED_DATE";
|
|
99
|
-
payload: Date;
|
|
100
|
-
} | {
|
|
101
|
-
type: "SET_SLOTS";
|
|
102
|
-
payload: Slot[];
|
|
103
|
-
} | {
|
|
104
|
-
type: "SET_SELECTED_SLOT";
|
|
105
|
-
payload: Slot | null;
|
|
106
|
-
} | {
|
|
107
|
-
type: "SET_CONSULTATION_MODE";
|
|
108
|
-
payload: "ONLINE" | "OFFLINE";
|
|
109
|
-
} | {
|
|
110
|
-
type: "SET_CONSULTATION_CHARGE";
|
|
111
|
-
payload: string;
|
|
112
|
-
} | {
|
|
113
|
-
type: "SET_PATIENT_NAME";
|
|
114
|
-
payload: string;
|
|
115
|
-
} | {
|
|
116
|
-
type: "SET_PATIENT_AGE";
|
|
117
|
-
payload: string;
|
|
118
|
-
} | {
|
|
119
|
-
type: "SET_PATIENT_EMAIL";
|
|
120
|
-
payload: string;
|
|
121
|
-
} | {
|
|
122
|
-
type: "SET_PATIENT_GENDER";
|
|
123
|
-
payload: string;
|
|
124
|
-
} | {
|
|
125
|
-
type: "SET_BLOOD_GROUP";
|
|
126
|
-
payload: string;
|
|
127
|
-
} | {
|
|
128
|
-
type: "SET_PATIENT_ADDRESS";
|
|
129
|
-
payload: string;
|
|
130
|
-
} | {
|
|
131
|
-
type: "SET_PATIENT_CITY";
|
|
132
|
-
payload: string;
|
|
133
|
-
} | {
|
|
134
|
-
type: "SET_PATIENT_STATE";
|
|
135
|
-
payload: string;
|
|
136
|
-
} | {
|
|
137
|
-
type: "SET_PATIENT_COUNTRY";
|
|
138
|
-
payload: string;
|
|
139
|
-
} | {
|
|
140
|
-
type: "SET_PATIENT_ZIPCODE";
|
|
141
|
-
payload: string;
|
|
142
|
-
} | {
|
|
143
|
-
type: "SET_PATIENT_LANDMARK";
|
|
144
|
-
payload: string;
|
|
145
|
-
} | {
|
|
146
|
-
type: "SET_COUNTRY_CODE";
|
|
147
|
-
payload: string;
|
|
148
|
-
} | {
|
|
149
|
-
type: "SET_PATIENT_PHONE";
|
|
150
|
-
payload: string;
|
|
151
|
-
} | {
|
|
152
|
-
type: "SET_OTP_CODE";
|
|
153
|
-
payload: string;
|
|
154
|
-
} | {
|
|
155
|
-
type: "SET_OTP_SENT";
|
|
156
|
-
payload: boolean;
|
|
157
|
-
} | {
|
|
158
|
-
type: "SET_OTP_VERIFIED";
|
|
159
|
-
payload: boolean;
|
|
160
|
-
} | {
|
|
161
|
-
type: "SET_OTP_SENDING";
|
|
162
|
-
payload: boolean;
|
|
163
|
-
} | {
|
|
164
|
-
type: "SET_OTP_VERIFYING";
|
|
165
|
-
payload: boolean;
|
|
166
|
-
} | {
|
|
167
|
-
type: "RESET_FORM";
|
|
39
|
+
state: any;
|
|
40
|
+
dispatch: React.Dispatch<any>;
|
|
168
41
|
};
|
|
169
42
|
export declare const COUNTRY_CODES: {
|
|
170
43
|
code: string;
|
|
@@ -178,4 +51,4 @@ export declare const BLOOD_GROUP_OPTIONS: {
|
|
|
178
51
|
value: string;
|
|
179
52
|
label: string;
|
|
180
53
|
}[];
|
|
181
|
-
export declare const
|
|
54
|
+
export declare const mapBloodGroupToApi: (uiBloodGroup: string) => string;
|
package/dist/components/types.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { INITIAL_STATE } from "./appointment-booking/types";
|
|
1
2
|
export const COUNTRY_CODES = [
|
|
2
3
|
{ code: "+91", label: "🇮🇳 +91" },
|
|
3
4
|
{ code: "+1", label: "🇺🇸 +1" },
|
|
@@ -19,37 +20,19 @@ export const BLOOD_GROUP_OPTIONS = [
|
|
|
19
20
|
{ value: "AB-", label: "AB-" },
|
|
20
21
|
{ value: "O+", label: "O+" },
|
|
21
22
|
{ value: "O-", label: "O-" },
|
|
23
|
+
{ value: "UNKNOWN", label: "Unknown" },
|
|
22
24
|
];
|
|
23
|
-
export const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
consultationCharge: "",
|
|
37
|
-
patientName: "",
|
|
38
|
-
patientAge: "",
|
|
39
|
-
patientEmail: "",
|
|
40
|
-
patientGender: "",
|
|
41
|
-
bloodGroup: "",
|
|
42
|
-
patientAddress: "",
|
|
43
|
-
patientCity: "",
|
|
44
|
-
patientState: "",
|
|
45
|
-
patientCountry: "",
|
|
46
|
-
patientZipcode: "",
|
|
47
|
-
patientLandmark: "",
|
|
48
|
-
countryCode: "+91",
|
|
49
|
-
patientPhone: "",
|
|
50
|
-
otpCode: "",
|
|
51
|
-
otpSent: false,
|
|
52
|
-
otpVerified: false,
|
|
53
|
-
otpSending: false,
|
|
54
|
-
otpVerifying: false,
|
|
25
|
+
export const mapBloodGroupToApi = (uiBloodGroup) => {
|
|
26
|
+
const bloodGroupMap = {
|
|
27
|
+
"A+": "A_POSITIVE",
|
|
28
|
+
"A-": "A_NEGATIVE",
|
|
29
|
+
"B+": "B_POSITIVE",
|
|
30
|
+
"B-": "B_NEGATIVE",
|
|
31
|
+
"AB+": "AB_POSITIVE",
|
|
32
|
+
"AB-": "AB_NEGATIVE",
|
|
33
|
+
"O+": "O_POSITIVE",
|
|
34
|
+
"O-": "O_NEGATIVE",
|
|
35
|
+
UNKNOWN: "UNKNOWN",
|
|
36
|
+
};
|
|
37
|
+
return bloodGroupMap[uiBloodGroup] || "UNKNOWN";
|
|
55
38
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import * as React from
|
|
3
|
-
import { ChevronDownIcon } from
|
|
4
|
-
import { Check } from
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { ChevronDownIcon } from "../Icons/ChevronDownIcon";
|
|
4
|
+
import { Check } from "../Icons/Check";
|
|
5
5
|
const cn = (...classes) => {
|
|
6
|
-
return classes.filter(Boolean).join(
|
|
6
|
+
return classes.filter(Boolean).join(" ");
|
|
7
7
|
};
|
|
8
|
-
if (typeof document !==
|
|
9
|
-
const styleId =
|
|
8
|
+
if (typeof document !== "undefined") {
|
|
9
|
+
const styleId = "custom-select-styles";
|
|
10
10
|
if (!document.getElementById(styleId)) {
|
|
11
|
-
const styleElement = document.createElement(
|
|
11
|
+
const styleElement = document.createElement("style");
|
|
12
12
|
styleElement.id = styleId;
|
|
13
13
|
styleElement.innerHTML = `
|
|
14
14
|
/* Container */
|
|
@@ -226,14 +226,14 @@ const SelectContext = React.createContext(undefined);
|
|
|
226
226
|
const useSelectContext = () => {
|
|
227
227
|
const context = React.useContext(SelectContext);
|
|
228
228
|
if (!context) {
|
|
229
|
-
throw new Error(
|
|
229
|
+
throw new Error("Select components must be used within a Select");
|
|
230
230
|
}
|
|
231
231
|
return context;
|
|
232
232
|
};
|
|
233
|
-
const Select = ({ children, value, onValueChange, defaultValue, disabled = false }) => {
|
|
233
|
+
const Select = ({ children, value, onValueChange, defaultValue, disabled = false, }) => {
|
|
234
234
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
235
|
-
const [selectedValue, setSelectedValue] = React.useState(value || defaultValue ||
|
|
236
|
-
const [selectedLabel, setSelectedLabel] = React.useState(
|
|
235
|
+
const [selectedValue, setSelectedValue] = React.useState(value || defaultValue || "");
|
|
236
|
+
const [selectedLabel, setSelectedLabel] = React.useState("");
|
|
237
237
|
const triggerRef = React.useRef(null);
|
|
238
238
|
const contentRef = React.useRef(null);
|
|
239
239
|
React.useEffect(() => {
|
|
@@ -251,8 +251,8 @@ const Select = ({ children, value, onValueChange, defaultValue, disabled = false
|
|
|
251
251
|
}
|
|
252
252
|
};
|
|
253
253
|
if (isOpen) {
|
|
254
|
-
document.addEventListener(
|
|
255
|
-
return () => document.removeEventListener(
|
|
254
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
255
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
256
256
|
}
|
|
257
257
|
}, [isOpen]);
|
|
258
258
|
const handleSelect = (value, label) => {
|
|
@@ -276,27 +276,27 @@ const Select = ({ children, value, onValueChange, defaultValue, disabled = false
|
|
|
276
276
|
};
|
|
277
277
|
const SelectTrigger = React.forwardRef(({ children, className, error = false, ...props }, ref) => {
|
|
278
278
|
const { isOpen, setIsOpen, triggerRef, disabled } = useSelectContext();
|
|
279
|
-
return (_jsxs("button", { ref: triggerRef, type: "button", className: cn(
|
|
279
|
+
return (_jsxs("button", { ref: triggerRef, type: "button", className: cn("select-trigger", error && "select-trigger-error", className), onClick: () => !disabled && setIsOpen(!isOpen), disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "listbox", ...props, children: [children, _jsx(ChevronDownIcon, { className: cn("select-icon", error && "select-icon-error") })] }));
|
|
280
280
|
});
|
|
281
|
-
SelectTrigger.displayName =
|
|
282
|
-
const SelectValue = ({ placeholder =
|
|
281
|
+
SelectTrigger.displayName = "SelectTrigger";
|
|
282
|
+
const SelectValue = ({ placeholder = "Select...", }) => {
|
|
283
283
|
const { selectedLabel, selectedValue } = useSelectContext();
|
|
284
|
-
return (_jsx("span", { className: cn(
|
|
284
|
+
return (_jsx("span", { className: cn("select-value", !selectedValue && "select-placeholder"), children: selectedLabel || placeholder }));
|
|
285
285
|
};
|
|
286
286
|
const SelectContent = React.forwardRef(({ children, className, ...props }, ref) => {
|
|
287
287
|
const { isOpen, contentRef } = useSelectContext();
|
|
288
288
|
if (!isOpen)
|
|
289
289
|
return null;
|
|
290
|
-
return (_jsx("div", { ref: contentRef, className: cn(
|
|
290
|
+
return (_jsx("div", { ref: contentRef, className: cn("select-content", className), role: "listbox", ...props, children: _jsx("div", { className: "select-viewport", children: children }) }));
|
|
291
291
|
});
|
|
292
|
-
SelectContent.displayName =
|
|
292
|
+
SelectContent.displayName = "SelectContent";
|
|
293
293
|
const SelectItem = React.forwardRef(({ children, value, className, disabled = false, ...props }, ref) => {
|
|
294
294
|
const { selectedValue, handleSelect } = useSelectContext();
|
|
295
295
|
const isSelected = selectedValue === value;
|
|
296
|
-
return (_jsxs("div", { ref: ref, className: cn(
|
|
296
|
+
return (_jsxs("div", { ref: ref, className: cn("select-item", isSelected && "select-item-selected", disabled && "select-item-disabled", className), onClick: () => !disabled && handleSelect(value, children), role: "option", "aria-selected": isSelected, "data-disabled": disabled, ...props, children: [isSelected && (_jsx("span", { className: "select-item-indicator", children: _jsx(Check, {}) })), _jsx("span", { className: "select-item-text", children: children })] }));
|
|
297
297
|
});
|
|
298
|
-
SelectItem.displayName =
|
|
299
|
-
const SelectGroup = ({ children, className }) => (_jsx("div", { className: cn(
|
|
300
|
-
const SelectLabel = ({ children, className }) => (_jsx("div", { className: cn(
|
|
301
|
-
const SelectSeparator = ({ className }) => (_jsx("div", { className: cn(
|
|
298
|
+
SelectItem.displayName = "SelectItem";
|
|
299
|
+
const SelectGroup = ({ children, className }) => (_jsx("div", { className: cn("select-group", className), children: children }));
|
|
300
|
+
const SelectLabel = ({ children, className }) => (_jsx("div", { className: cn("select-label", className), children: children }));
|
|
301
|
+
const SelectSeparator = ({ className }) => (_jsx("div", { className: cn("select-separator", className) }));
|
|
302
302
|
export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export declare const formatDateToISO: (date: Date) => string;
|
|
2
|
+
export declare const formatDate: (date: Date | string | null) => string;
|
|
3
|
+
export declare const formatTime: (timeStr: string | number) => string;
|
|
4
|
+
export declare const calculateDuration: (startTime?: string | number, endTime?: string | number, defaultDuration?: number) => number;
|
|
2
5
|
export declare const parsePatientName: (fullName: string) => {
|
|
3
6
|
firstName: string;
|
|
4
7
|
lastName: string;
|
package/dist/components/utils.js
CHANGED
|
@@ -4,6 +4,65 @@ export const formatDateToISO = (date) => {
|
|
|
4
4
|
const day = String(date.getDate()).padStart(2, "0");
|
|
5
5
|
return `${year}-${month}-${day}`;
|
|
6
6
|
};
|
|
7
|
+
export const formatDate = (date) => {
|
|
8
|
+
if (!date)
|
|
9
|
+
return "Not selected";
|
|
10
|
+
try {
|
|
11
|
+
const dateObj = typeof date === "string" ? new Date(date) : date;
|
|
12
|
+
return dateObj.toLocaleDateString("en-US", {
|
|
13
|
+
weekday: "long",
|
|
14
|
+
year: "numeric",
|
|
15
|
+
month: "long",
|
|
16
|
+
day: "numeric",
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return String(date);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export const formatTime = (timeStr) => {
|
|
24
|
+
try {
|
|
25
|
+
if (typeof timeStr === "number" || !Number.isNaN(Number(timeStr))) {
|
|
26
|
+
const time = new Date(Number(timeStr));
|
|
27
|
+
return time.toLocaleTimeString("en-US", {
|
|
28
|
+
hour: "numeric",
|
|
29
|
+
minute: "2-digit",
|
|
30
|
+
hour12: true,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (timeStr.includes(":") && timeStr.length <= 5) {
|
|
34
|
+
const time = new Date(`2000-01-01T${timeStr}`);
|
|
35
|
+
return time.toLocaleTimeString("en-US", {
|
|
36
|
+
hour: "numeric",
|
|
37
|
+
minute: "2-digit",
|
|
38
|
+
hour12: true,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const time = new Date(timeStr);
|
|
42
|
+
return time.toLocaleTimeString("en-US", {
|
|
43
|
+
hour: "numeric",
|
|
44
|
+
minute: "2-digit",
|
|
45
|
+
hour12: true,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return String(timeStr);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
export const calculateDuration = (startTime, endTime, defaultDuration = 60) => {
|
|
53
|
+
if (!startTime || !endTime)
|
|
54
|
+
return defaultDuration;
|
|
55
|
+
try {
|
|
56
|
+
const start = new Date(startTime);
|
|
57
|
+
const end = new Date(endTime);
|
|
58
|
+
const diffMs = end.getTime() - start.getTime();
|
|
59
|
+
const diffMinutes = Math.round(diffMs / (1000 * 60));
|
|
60
|
+
return diffMinutes > 0 ? diffMinutes : defaultDuration;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return defaultDuration;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
7
66
|
export const parsePatientName = (fullName) => {
|
|
8
67
|
const nameParts = fullName.trim().split(/\s+/);
|
|
9
68
|
const firstName = nameParts[0] || "Patient";
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export declare const validatePhoneNumber: (phone: string) => boolean;
|
|
2
2
|
export declare const validateCountryCode: (code: string) => boolean;
|
|
3
|
+
export declare const validateBloodGroup: (bloodGroup: string) => boolean;
|
|
4
|
+
export declare const validateDateOfBirth: (dob: string) => boolean;
|
|
@@ -5,3 +5,44 @@ export const validatePhoneNumber = (phone) => {
|
|
|
5
5
|
export const validateCountryCode = (code) => {
|
|
6
6
|
return /^\+[1-9]\d{0,3}$/.test(code);
|
|
7
7
|
};
|
|
8
|
+
export const validateBloodGroup = (bloodGroup) => {
|
|
9
|
+
const validBloodGroups = [
|
|
10
|
+
"A+",
|
|
11
|
+
"A-",
|
|
12
|
+
"B+",
|
|
13
|
+
"B-",
|
|
14
|
+
"AB+",
|
|
15
|
+
"AB-",
|
|
16
|
+
"O+",
|
|
17
|
+
"O-",
|
|
18
|
+
"UNKNOWN",
|
|
19
|
+
];
|
|
20
|
+
return validBloodGroups.includes(bloodGroup);
|
|
21
|
+
};
|
|
22
|
+
export const validateDateOfBirth = (dob) => {
|
|
23
|
+
if (!dob)
|
|
24
|
+
return false;
|
|
25
|
+
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
|
|
26
|
+
if (!dateRegex.test(dob))
|
|
27
|
+
return false;
|
|
28
|
+
const [yearStr, monthStr, dayStr] = dob.split("-");
|
|
29
|
+
const year = parseInt(yearStr, 10);
|
|
30
|
+
const month = parseInt(monthStr, 10);
|
|
31
|
+
const day = parseInt(dayStr, 10);
|
|
32
|
+
if (month < 1 || month > 12 || day < 1 || day > 31)
|
|
33
|
+
return false;
|
|
34
|
+
const date = new Date(year, month - 1, day);
|
|
35
|
+
if (date.getFullYear() !== year ||
|
|
36
|
+
date.getMonth() !== month - 1 ||
|
|
37
|
+
date.getDate() !== day) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const today = new Date();
|
|
41
|
+
today.setHours(0, 0, 0, 0);
|
|
42
|
+
date.setHours(0, 0, 0, 0);
|
|
43
|
+
if (date > today)
|
|
44
|
+
return false;
|
|
45
|
+
if (year < 1900)
|
|
46
|
+
return false;
|
|
47
|
+
return true;
|
|
48
|
+
};
|
package/dist/core/theme/index.js
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MedosTheme } from "./types";
|
|
2
|
+
export type Breakpoint = "mobile" | "tablet" | "desktop" | "wide";
|
|
3
|
+
export declare function useMediaQuery(query: string): boolean;
|
|
4
|
+
export declare function useBreakpoint(theme: MedosTheme): Breakpoint;
|
|
5
|
+
export declare function useIsMobile(theme: MedosTheme): boolean;
|
|
6
|
+
export declare function useIsTablet(theme: MedosTheme): boolean;
|
|
7
|
+
export declare function useIsDesktop(theme: MedosTheme): boolean;
|
|
8
|
+
export declare function useResponsiveValue<T>(theme: MedosTheme, values: Partial<Record<Breakpoint, T>>): T | undefined;
|
|
9
|
+
export declare function responsiveStyles(styles: Partial<Record<Breakpoint | "base", React.CSSProperties>>, currentBreakpoint: Breakpoint): React.CSSProperties;
|
|
10
|
+
export declare function getResponsiveMaxWidth(theme: MedosTheme, breakpoint: Breakpoint, customMaxWidths?: Partial<Record<Breakpoint, string>>): string;
|
|
11
|
+
export declare function getResponsivePadding(theme: MedosTheme, breakpoint: Breakpoint): string;
|
|
12
|
+
export declare function getResponsiveFontSize(theme: MedosTheme, breakpoint: Breakpoint, size?: keyof MedosTheme["typography"]): string;
|
|
13
|
+
export declare function isTouchDevice(): boolean;
|
|
14
|
+
export declare const MIN_TOUCH_TARGET_SIZE = "44px";
|
|
15
|
+
export declare function getResponsiveInputHeight(breakpoint: Breakpoint): string;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
export function useMediaQuery(query) {
|
|
3
|
+
const [matches, setMatches] = useState(false);
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
const mediaQuery = window.matchMedia(query);
|
|
6
|
+
setMatches(mediaQuery.matches);
|
|
7
|
+
const handler = (event) => {
|
|
8
|
+
setMatches(event.matches);
|
|
9
|
+
};
|
|
10
|
+
if (mediaQuery.addEventListener) {
|
|
11
|
+
mediaQuery.addEventListener("change", handler);
|
|
12
|
+
return () => mediaQuery.removeEventListener("change", handler);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
mediaQuery.addListener(handler);
|
|
16
|
+
return () => mediaQuery.removeListener(handler);
|
|
17
|
+
}
|
|
18
|
+
}, [query]);
|
|
19
|
+
return matches;
|
|
20
|
+
}
|
|
21
|
+
export function useBreakpoint(theme) {
|
|
22
|
+
const isWide = useMediaQuery(`(min-width: ${theme.breakpoints.wide})`);
|
|
23
|
+
const isDesktop = useMediaQuery(`(min-width: ${theme.breakpoints.desktop})`);
|
|
24
|
+
const isTablet = useMediaQuery(`(min-width: ${theme.breakpoints.tablet})`);
|
|
25
|
+
if (isWide)
|
|
26
|
+
return "wide";
|
|
27
|
+
if (isDesktop)
|
|
28
|
+
return "desktop";
|
|
29
|
+
if (isTablet)
|
|
30
|
+
return "tablet";
|
|
31
|
+
return "mobile";
|
|
32
|
+
}
|
|
33
|
+
export function useIsMobile(theme) {
|
|
34
|
+
return useMediaQuery(`(max-width: ${parseInt(theme.breakpoints.tablet) - 1}px)`);
|
|
35
|
+
}
|
|
36
|
+
export function useIsTablet(theme) {
|
|
37
|
+
const minWidth = theme.breakpoints.tablet;
|
|
38
|
+
const maxWidth = `${parseInt(theme.breakpoints.desktop) - 1}px`;
|
|
39
|
+
return useMediaQuery(`(min-width: ${minWidth}) and (max-width: ${maxWidth})`);
|
|
40
|
+
}
|
|
41
|
+
export function useIsDesktop(theme) {
|
|
42
|
+
return useMediaQuery(`(min-width: ${theme.breakpoints.desktop})`);
|
|
43
|
+
}
|
|
44
|
+
export function useResponsiveValue(theme, values) {
|
|
45
|
+
const breakpoint = useBreakpoint(theme);
|
|
46
|
+
if (values[breakpoint] !== undefined) {
|
|
47
|
+
return values[breakpoint];
|
|
48
|
+
}
|
|
49
|
+
if (breakpoint === "wide" && values.desktop !== undefined) {
|
|
50
|
+
return values.desktop;
|
|
51
|
+
}
|
|
52
|
+
if ((breakpoint === "desktop" || breakpoint === "wide") &&
|
|
53
|
+
values.tablet !== undefined) {
|
|
54
|
+
return values.tablet;
|
|
55
|
+
}
|
|
56
|
+
if (values.mobile !== undefined) {
|
|
57
|
+
return values.mobile;
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
export function responsiveStyles(styles, currentBreakpoint) {
|
|
62
|
+
const baseStyles = styles.base || {};
|
|
63
|
+
const breakpointStyles = styles[currentBreakpoint] || {};
|
|
64
|
+
return {
|
|
65
|
+
...baseStyles,
|
|
66
|
+
...breakpointStyles,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function getResponsiveMaxWidth(theme, breakpoint, customMaxWidths) {
|
|
70
|
+
if (customMaxWidths?.[breakpoint]) {
|
|
71
|
+
return customMaxWidths[breakpoint];
|
|
72
|
+
}
|
|
73
|
+
const defaults = {
|
|
74
|
+
mobile: "100%",
|
|
75
|
+
tablet: "100%",
|
|
76
|
+
desktop: "840px",
|
|
77
|
+
wide: "1200px",
|
|
78
|
+
};
|
|
79
|
+
return defaults[breakpoint];
|
|
80
|
+
}
|
|
81
|
+
export function getResponsivePadding(theme, breakpoint) {
|
|
82
|
+
const paddingMap = {
|
|
83
|
+
mobile: "md",
|
|
84
|
+
tablet: "lg",
|
|
85
|
+
desktop: "xl",
|
|
86
|
+
wide: "2xl",
|
|
87
|
+
};
|
|
88
|
+
return theme.spacing[paddingMap[breakpoint]];
|
|
89
|
+
}
|
|
90
|
+
export function getResponsiveFontSize(theme, breakpoint, size = "fontSizeMd") {
|
|
91
|
+
if (breakpoint === "mobile" && size.startsWith("fontSize")) {
|
|
92
|
+
const sizeMap = {
|
|
93
|
+
fontSize3xl: "fontSize2xl",
|
|
94
|
+
fontSize2xl: "fontSizeXl",
|
|
95
|
+
fontSizeXl: "fontSizeLg",
|
|
96
|
+
fontSizeLg: "fontSizeMd",
|
|
97
|
+
};
|
|
98
|
+
const adjustedSize = sizeMap[size] || size;
|
|
99
|
+
return theme.typography[adjustedSize];
|
|
100
|
+
}
|
|
101
|
+
return theme.typography[size];
|
|
102
|
+
}
|
|
103
|
+
export function isTouchDevice() {
|
|
104
|
+
return ("ontouchstart" in window ||
|
|
105
|
+
navigator.maxTouchPoints > 0 ||
|
|
106
|
+
navigator.msMaxTouchPoints > 0);
|
|
107
|
+
}
|
|
108
|
+
export const MIN_TOUCH_TARGET_SIZE = "44px";
|
|
109
|
+
export function getResponsiveInputHeight(breakpoint) {
|
|
110
|
+
return breakpoint === "mobile" && isTouchDevice()
|
|
111
|
+
? MIN_TOUCH_TARGET_SIZE
|
|
112
|
+
: "40px";
|
|
113
|
+
}
|
|
@@ -18,11 +18,11 @@ export const defaultTheme = {
|
|
|
18
18
|
borderFocus: "#27903F",
|
|
19
19
|
text: "#111827",
|
|
20
20
|
textSecondary: "#374151",
|
|
21
|
-
textTertiary: "#
|
|
21
|
+
textTertiary: "#4E8F50",
|
|
22
22
|
textDisabled: "#9ca3af",
|
|
23
23
|
textOnPrimary: "#fff",
|
|
24
24
|
textOnSecondary: "#fff",
|
|
25
|
-
success: "#
|
|
25
|
+
success: "#4E8F50",
|
|
26
26
|
successBackground: "#ecfdf5",
|
|
27
27
|
successBorder: "#6ee7b7",
|
|
28
28
|
error: "#ef4444",
|
|
@@ -84,6 +84,12 @@ export const defaultTheme = {
|
|
|
84
84
|
normal: "200ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
85
85
|
slow: "300ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
86
86
|
},
|
|
87
|
+
breakpoints: {
|
|
88
|
+
mobile: "320px",
|
|
89
|
+
tablet: "768px",
|
|
90
|
+
desktop: "1024px",
|
|
91
|
+
wide: "1280px",
|
|
92
|
+
},
|
|
87
93
|
};
|
|
88
94
|
export const modernTheme = {
|
|
89
95
|
name: "modern",
|
|
@@ -95,7 +101,7 @@ export const modernTheme = {
|
|
|
95
101
|
secondaryHover: "#ff5722",
|
|
96
102
|
accent: "#3b82f6",
|
|
97
103
|
accentHover: "#2563eb",
|
|
98
|
-
background: "#
|
|
104
|
+
background: "#fff",
|
|
99
105
|
backgroundSecondary: "#f8fafc",
|
|
100
106
|
backgroundTertiary: "#f1f5f9",
|
|
101
107
|
surface: "#ffffff",
|
|
@@ -109,7 +115,7 @@ export const modernTheme = {
|
|
|
109
115
|
textDisabled: "#cbd5e1",
|
|
110
116
|
textOnPrimary: "#ffffff",
|
|
111
117
|
textOnSecondary: "#ffffff",
|
|
112
|
-
success: "#
|
|
118
|
+
success: "#4E8F50",
|
|
113
119
|
successBackground: "#ecfdf5",
|
|
114
120
|
successBorder: "#6ee7b7",
|
|
115
121
|
error: "#ef4444",
|
|
@@ -171,6 +177,12 @@ export const modernTheme = {
|
|
|
171
177
|
normal: "200ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
172
178
|
slow: "300ms cubic-bezier(0.4, 0, 0.2, 1)",
|
|
173
179
|
},
|
|
180
|
+
breakpoints: {
|
|
181
|
+
mobile: "320px",
|
|
182
|
+
tablet: "768px",
|
|
183
|
+
desktop: "1024px",
|
|
184
|
+
wide: "1280px",
|
|
185
|
+
},
|
|
174
186
|
};
|
|
175
187
|
export const themes = {
|
|
176
188
|
default: defaultTheme,
|