@eka-care/abdm-dashboard-stg 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +73 -0
  2. package/eslint.config.js +23 -0
  3. package/index.html +27 -0
  4. package/package.json +46 -0
  5. package/postcss.config.js +6 -0
  6. package/public/headerImg.png +0 -0
  7. package/public/iphoneStep2.png +0 -0
  8. package/public/iphoneStep3.png +0 -0
  9. package/public/vite.svg +1 -0
  10. package/src/abdm-dashboard.tsx +18 -0
  11. package/src/app/store.ts +15 -0
  12. package/src/appointment-token-pdf/pdf-page1.tsx +324 -0
  13. package/src/appointment-token-pdf/pdf-page2.tsx +346 -0
  14. package/src/assets/react.svg +1 -0
  15. package/src/components/abha-metric.tsx +322 -0
  16. package/src/components/abha-workflows.tsx +225 -0
  17. package/src/components/automate-strip.tsx +29 -0
  18. package/src/components/cards/metric-card.tsx +75 -0
  19. package/src/components/cards/request-card.tsx +23 -0
  20. package/src/components/cards/request-cards.tsx +24 -0
  21. package/src/components/cards/workflow-card.tsx +55 -0
  22. package/src/components/custom/calendar.tsx +59 -0
  23. package/src/components/custom/switch.tsx +32 -0
  24. package/src/components/loader/abdm-dash-loader.tsx +21 -0
  25. package/src/components/loader/card-loader.tsx +20 -0
  26. package/src/components/modal/automateTaks-modal.tsx +110 -0
  27. package/src/components/modal/modal.tsx +67 -0
  28. package/src/components/modal/select-lang-modal.tsx +38 -0
  29. package/src/components/notification-header.tsx +11 -0
  30. package/src/features/api/baseApi.ts +23 -0
  31. package/src/features/cardApis/cardApi.ts +15 -0
  32. package/src/features/landingApi/landingApi.ts +20 -0
  33. package/src/features/slice/landingApiSlice.ts +49 -0
  34. package/src/features/tasksApis/taskGetApi.ts +12 -0
  35. package/src/features/tasksApis/taskUpdateApi.ts +15 -0
  36. package/src/home.tsx +132 -0
  37. package/src/index.css +297 -0
  38. package/src/main.tsx +107 -0
  39. package/src/tailwind-theme-config/pds2/border.ts +69 -0
  40. package/src/tailwind-theme-config/pds2/colors.ts +88 -0
  41. package/src/tailwind-theme-config/pds2/spacing.ts +1007 -0
  42. package/src/types/pagify-sdk.d.ts +17 -0
  43. package/src/utils/constants.ts +19 -0
  44. package/src/utils/helpers.ts +32 -0
  45. package/tailwind.config.ts +131 -0
  46. package/tsconfig.app.json +28 -0
  47. package/tsconfig.json +7 -0
  48. package/tsconfig.node.json +26 -0
  49. package/vite.config.ts +62 -0
@@ -0,0 +1,322 @@
1
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2
+ import { useGetCardMutation } from "../features/cardApis/cardApi";
3
+ import {
4
+ faChartLine,
5
+ faCheck,
6
+ faClinicMedical,
7
+ faFileMedicalAlt,
8
+ faLink,
9
+ } from "@fortawesome/free-solid-svg-icons";
10
+ import MetricCard from "./cards/metric-card";
11
+ import { useEffect, useState } from "react";
12
+ import { formatDateToBackendISO, getYesterday } from "../utils/helpers";
13
+ import { DATA_DATE_FILTERS } from "../utils/constants";
14
+ import { getClinicId, getHfrId } from "../features/slice/landingApiSlice";
15
+ import { useSelector } from "react-redux";
16
+ import CustomCalendar from "./custom/calendar";
17
+
18
+ type ValuePiece = Date | null;
19
+
20
+ type Value = ValuePiece | [ValuePiece, ValuePiece];
21
+
22
+ const AbhaMetric = () => {
23
+ const clinicId = useSelector(getClinicId);
24
+ const hfrId = useSelector(getHfrId);
25
+ const [isStartDateOpen, setIsStartDateOpen] = useState<boolean>(false);
26
+ const [isEndDateOpen, setIsEndDateOpen] = useState<boolean>(false);
27
+ const [getCard, { data, isSuccess }] = useGetCardMutation();
28
+ const [metricData, setMetricData] = useState<any[]>([
29
+ { title: "loader" },
30
+ { title: "loader" },
31
+ { title: "loader" },
32
+ ]);
33
+ const [date, setDate] = useState<{
34
+ from: Value;
35
+ to: Value;
36
+ }>({
37
+ from: null,
38
+ to: null,
39
+ });
40
+
41
+ const [selectedDataFilter, setSelectedDataFilter] =
42
+ useState<DATA_DATE_FILTERS>(DATA_DATE_FILTERS.YESTERDAY);
43
+
44
+ const [cardApiBody, setCardApiBody] = useState<{
45
+ from?: string;
46
+ to?: string;
47
+ }>({
48
+ from: getYesterday().start,
49
+ to: getYesterday().end,
50
+ });
51
+
52
+ const today = new Date();
53
+
54
+ useEffect(() => {
55
+ getCard({
56
+ clinicId: clinicId ?? "",
57
+ body: {
58
+ start_date: cardApiBody?.from,
59
+ end_date: cardApiBody?.to,
60
+ },
61
+ });
62
+ }, [cardApiBody]);
63
+
64
+ useEffect(() => {
65
+ if (isSuccess && data) {
66
+ setMetricData(data);
67
+ }
68
+ }, [isSuccess, data]);
69
+
70
+ const handleDateChange = (key: "from" | "to", value: Value) => {
71
+ if (Array.isArray(value)) {
72
+ console.warn("Range mode not supported here", value);
73
+ return;
74
+ }
75
+
76
+ setDate({
77
+ ...date,
78
+ [key]: value,
79
+ });
80
+
81
+ setCardApiBody((prev) => ({
82
+ ...prev,
83
+ [key]: value ? value.toISOString() : "",
84
+ }));
85
+ };
86
+
87
+ const handleDateFilterChange = (dateFilter: DATA_DATE_FILTERS): void => {
88
+ if (dateFilter === DATA_DATE_FILTERS.YESTERDAY) {
89
+ setCardApiBody({
90
+ from: getYesterday().start,
91
+ to: getYesterday().end,
92
+ });
93
+ setSelectedDataFilter(dateFilter);
94
+ return;
95
+ } else if (dateFilter === DATA_DATE_FILTERS.MONTHLY) {
96
+ const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
97
+
98
+ const endDate = today;
99
+
100
+ const from = formatDateToBackendISO(
101
+ startOfMonth.toISOString().split("T")[0]
102
+ );
103
+
104
+ const to = formatDateToBackendISO(endDate.toISOString().split("T")[0]);
105
+
106
+ setCardApiBody({ from, to });
107
+ setSelectedDataFilter(dateFilter);
108
+ return;
109
+ } else if (dateFilter === DATA_DATE_FILTERS.CUSTOM) {
110
+ setIsStartDateOpen(true);
111
+
112
+ if (Array.isArray(date?.from) || Array.isArray(date?.to)) {
113
+ console.warn("Range mode not supported here");
114
+ return;
115
+ }
116
+
117
+ setCardApiBody({
118
+ from: date?.from ? date?.from?.toISOString() : "",
119
+ to: date?.to ? date?.to?.toISOString() : "",
120
+ });
121
+ setSelectedDataFilter(dateFilter);
122
+ }
123
+ };
124
+
125
+ return (
126
+ <div className="abhaDash-bg-gradient-to-r abhaDash-from-[#DBE5FF] abhaDash-to-[#8EAEFF] abhaDash-p-25 ">
127
+ <div className="abhaDash-flex abhaDash-gap-20 max-md:abhaDash-justify-between">
128
+ <div className="AbhaTitlesSubheadline max-md:AbhaTitle2Subheadline">ABHA Metrics</div>
129
+ {hfrId && (
130
+ <div
131
+ className="AbhaBody2Regular
132
+ abhaDash-gap-5 abhaDash-py-5
133
+ abhaDash-w-fit abhaDash-px-20
134
+ abhaDash-flex abhaDash-justify-center
135
+ abhaDash-items-center
136
+ abhaDash-text-text-primary-dark
137
+ abhaDash-bg-bg-primary-container
138
+ abhaDash-border
139
+ abhaDash-border-bg-white
140
+ abhaDash-rounded-20
141
+
142
+ max-md:abhaDash-px-10"
143
+ >
144
+ <FontAwesomeIcon icon={faClinicMedical} />
145
+ HFR ID: {hfrId}
146
+ </div>
147
+ )}
148
+ </div>
149
+ <div className="AbhaBody2Regular abhaDash-text-text-neutral-800-dark abhaDash-py-10">
150
+ Data for today and this month (last synced 1 day ago)
151
+ </div>
152
+ <div className="abhaDash-flex abhaDash-flex-wrap abhaDash-gap-8 ">
153
+ <div
154
+ onClick={
155
+ isSuccess
156
+ ? () => handleDateFilterChange(DATA_DATE_FILTERS.YESTERDAY)
157
+ : undefined
158
+ }
159
+ className={`
160
+ ${isSuccess ? "abhaDash-cursor-pointer" : "abhaDash-cursor-not-allowed"}
161
+ ${
162
+ selectedDataFilter === DATA_DATE_FILTERS.YESTERDAY
163
+ ? "abhaDash-border-text-primary abhaDash-text-text-primary"
164
+ : "abhaDash-border-border-neutral-300-strokedark"
165
+ } abhaDash-flex abhaDash-items-center abhaDash-gap-5 abhaDash-py-10 abhaDash-px-12 abhaDash-bg-bg-white abhaDash-border-1 abhaDash-rounded-10`}
166
+ >
167
+ {selectedDataFilter === DATA_DATE_FILTERS.YESTERDAY && (
168
+ <FontAwesomeIcon icon={faCheck} />
169
+ )}
170
+ Yesterday
171
+ </div>
172
+ <div
173
+ onClick={
174
+ isSuccess
175
+ ? () => handleDateFilterChange(DATA_DATE_FILTERS.MONTHLY)
176
+ : undefined
177
+ }
178
+ className={`
179
+ ${isSuccess ? "abhaDash-cursor-pointer" : "abhaDash-cursor-not-allowed"}
180
+ ${
181
+ selectedDataFilter === DATA_DATE_FILTERS.MONTHLY
182
+ ? "abhaDash-border-text-primary abhaDash-text-text-primary"
183
+ : "abhaDash-border-border-neutral-300-strokedark"
184
+ } abhaDash-flex abhaDash-items-center abhaDash-gap-5 abhaDash-py-10 abhaDash-px-12 abhaDash-bg-bg-white abhaDash-border-1 abhaDash-rounded-10`}
185
+ >
186
+ {selectedDataFilter === DATA_DATE_FILTERS.MONTHLY && (
187
+ <FontAwesomeIcon icon={faCheck} />
188
+ )}
189
+ Monthly
190
+ </div>
191
+ <div
192
+ className={`abhaDash-flex ${isSuccess ? "abhaDash-cursor-pointer" : "abhaDash-cursor-not-allowed"}`}
193
+ >
194
+ <div
195
+ onClick={
196
+ isSuccess
197
+ ? () => handleDateFilterChange(DATA_DATE_FILTERS.CUSTOM)
198
+ : undefined
199
+ }
200
+ className={`${
201
+ selectedDataFilter === DATA_DATE_FILTERS.CUSTOM
202
+ ? "abhaDash-border-text-primary abhaDash-text-text-primary"
203
+ : "abhaDash-border-border-neutral-300-strokedark"
204
+ } abhaDash-flex abhaDash-items-center abhaDash-gap-5 abhaDash-py-10 abhaDash-px-12 abhaDash-bg-bg-white abhaDash-border-y-1 abhaDash-border-l-1 abhaDash-rounded-l-10`}
205
+ >
206
+ {selectedDataFilter === DATA_DATE_FILTERS.CUSTOM && (
207
+ <FontAwesomeIcon icon={faCheck} />
208
+ )}
209
+ Custom
210
+ </div>
211
+
212
+ <div
213
+ className={`${
214
+ selectedDataFilter === DATA_DATE_FILTERS.CUSTOM
215
+ ? "abhaDash-border-text-primary"
216
+ : "abhaDash-border-border-neutral-300-strokedark abhaDash-text-border-neutral-300-strokedark abhaDash-cursor-not-allowed"
217
+ } abhaDash-flex abhaDash-items-center abhaDash-gap-5 abhaDash-py-10 abhaDash-px-12 abhaDash-bg-bg-white abhaDash-border-y-1 abhaDash-border-l-1 text-center`}
218
+ >
219
+ <CustomCalendar
220
+ value={date.from}
221
+ onChange={(val) => handleDateChange("from", val)}
222
+ placeholder="Start Date"
223
+ disabled={selectedDataFilter !== DATA_DATE_FILTERS.CUSTOM}
224
+ minDate={undefined}
225
+ isOpen={isStartDateOpen}
226
+ onCalendarClose={() => {
227
+ setIsEndDateOpen(true);
228
+ }}
229
+ />
230
+ </div>
231
+ <div
232
+ className={`${
233
+ selectedDataFilter === DATA_DATE_FILTERS.CUSTOM
234
+ ? "abhaDash-border-text-primary"
235
+ : "abhaDash-border-border-neutral-300-strokedark abhaDash-text-border-neutral-300-strokedark abhaDash-cursor-not-allowed"
236
+ } abhaDash-py-10 abhaDash-px-12 abhaDash-bg-bg-white abhaDash-border-y-1`}
237
+ >
238
+ -
239
+ </div>
240
+ <div
241
+ className={`${
242
+ selectedDataFilter === DATA_DATE_FILTERS.CUSTOM
243
+ ? "abhaDash-border-text-primary"
244
+ : "abhaDash-border-border-neutral-300-strokedark abhaDash-text-border-neutral-300-strokedark abhaDash-cursor-not-allowed"
245
+ } abhaDash-flex abhaDash-items-center abhaDash-gap-5 abhaDash-py-10 abhaDash-px-12 abhaDash-bg-bg-white abhaDash-border-y-1 abhaDash-border-r-1 abhaDash-rounded-r-10 text-center`}
246
+ >
247
+ <CustomCalendar
248
+ value={date.to}
249
+ onChange={(val) => handleDateChange("to", val)}
250
+ placeholder="End Date"
251
+ disabled={selectedDataFilter !== DATA_DATE_FILTERS.CUSTOM}
252
+ isOpen={isEndDateOpen}
253
+ minDate={
254
+ date.from instanceof Date
255
+ ? new Date(
256
+ date.from.getFullYear(),
257
+ date.from.getMonth(),
258
+ date.from.getDate() + 1
259
+ )
260
+ : undefined
261
+ }
262
+ onCalendarClose={() => {
263
+ setIsEndDateOpen(false);
264
+ setIsStartDateOpen(false);
265
+ }}
266
+ />
267
+ </div>
268
+ </div>
269
+ </div>
270
+ <div className="abhaDash-flex abhaDash-flex-wrap abhaDash-gap-20 abhaDash-h-full abhaDash-pt-20 ">
271
+ {metricData?.map((val, idx) => {
272
+ return (
273
+ <MetricCard
274
+ isDataLoaded={isSuccess}
275
+ key={val?.id ?? idx}
276
+ title={val?.title}
277
+ successText={
278
+ val?.title?.includes("Consent") ? "Successful" : "KYC Linked"
279
+ }
280
+ failedText={
281
+ val?.title?.includes("Consent") ? "Unsuccessful" : "Non KYC"
282
+ }
283
+ success={
284
+ val?.id?.includes("consent")
285
+ ? val?.data?.success
286
+ : val?.data?.kyc
287
+ }
288
+ failed={
289
+ val?.id?.includes("consent")
290
+ ? val?.data?.failed
291
+ : val?.data?.non_kyc
292
+ }
293
+ total={val?.data?.total}
294
+ cardIcon={
295
+ val?.id?.includes("abha")
296
+ ? faChartLine
297
+ : val?.id?.includes("records")
298
+ ? faLink
299
+ : faFileMedicalAlt
300
+ }
301
+ />
302
+ );
303
+ })}
304
+ {/* <div className="abhaDash-w-260 abhaDash-h-[55%] abhaDash-border-1 abhaDash-rounded-20 abhaDash-border-bg-primary-light abhaDash-bg-gradient-to-r abhaDash-from-[#95E9C1] abhaDash-to-[#D8FF71] abhaDash-p-20">
305
+ <div className="AbhaTitleHeadline abhaDash-text-text-primary-dark">
306
+ ₹400
307
+ </div>
308
+ <div className="AbhaTitle2Headline">DHIS Earnings</div>
309
+ <div className="abhaDash-border abhaDash-border-border-green-light abhaDash-my-10"></div>
310
+ <div className="AbhaTitle2Headline abhaDash-text-text-primary abhaDash-py-6">
311
+ See Calculation
312
+ </div>
313
+ <div className="AbhaBody3Regular abhaDash-text-text-neutral-800-dark">
314
+ Last synced 1 day ago*
315
+ </div>
316
+ </div> */}
317
+ </div>
318
+ </div>
319
+ );
320
+ };
321
+
322
+ export default AbhaMetric;
@@ -0,0 +1,225 @@
1
+ import {
2
+ faDownload,
3
+ faLink,
4
+ faUserPlus,
5
+ } from "@fortawesome/free-solid-svg-icons";
6
+ import WorkFlowCard from "./cards/workflow-card";
7
+ import pagify from "@eka-care/pagify-sdk";
8
+ import { PdfPage1 } from "../appointment-token-pdf/pdf-page1";
9
+ import { renderToStaticMarkup } from "react-dom/server";
10
+ import { PdfPage2 } from "../appointment-token-pdf/pdf-page2";
11
+ import { useSelector } from "react-redux";
12
+ import { getQrURl, getClinicName } from "../features/slice/landingApiSlice";
13
+ import QRCode from "react-qr-code";
14
+
15
+ const AbhaWorkFlows = ({
16
+ setShowAbhaSDK,
17
+ setShowWorkflowIframe,
18
+ }: {
19
+ setShowAbhaSDK: (show: boolean) => void;
20
+ setShowWorkflowIframe: (show: boolean) => void;
21
+ }) => {
22
+ const qrUrl = useSelector(getQrURl);
23
+ const clinicName = useSelector(getClinicName);
24
+
25
+ const handlePdfGenerate = async () => {
26
+ const innerHtml = renderToStaticMarkup(
27
+ <PdfPage1
28
+ qrUrl={qrUrl ?? "test"}
29
+ clinicName={clinicName ?? "Test Clinic"}
30
+ />
31
+ );
32
+ const innerHtml1 = renderToStaticMarkup(<PdfPage2 />);
33
+
34
+ const bodyHtml =
35
+ "<!doctype html>" +
36
+ `<div id="pagify-root" class="page-break" style="transform:rotate(90deg);">` +
37
+ innerHtml +
38
+ `</div>` +
39
+ `<div class="page-break-avoid" style="transform:rotate(90deg);">` +
40
+ innerHtml1 +
41
+ `</div>`;
42
+
43
+ await pagify.render({
44
+ head_html: `
45
+ <style>
46
+ .page-break-avoid { page-break-inside: avoid; }
47
+ .page-break {
48
+ page-break-after: always;
49
+ }
50
+ </style>
51
+ `,
52
+ body_html: bodyHtml,
53
+ page_size: "A4",
54
+ onPdfReady: (blobUrl: string) => {
55
+ const a = document.createElement("a");
56
+ a.href = blobUrl;
57
+ a.target = "_blank";
58
+ document.body.appendChild(a);
59
+ a.click();
60
+ a.remove();
61
+ },
62
+ onPdfError: (error: any) => {
63
+ console.error("PDF generation failed:", error);
64
+ },
65
+ } as any);
66
+ };
67
+
68
+ function waitForElement(
69
+ id: string,
70
+ callback: (element: HTMLElement) => void
71
+ ): void {
72
+ const interval = setInterval(() => {
73
+ const el = document.getElementById(id);
74
+ if (el) {
75
+ clearInterval(interval);
76
+ callback(el);
77
+ }
78
+ }, 50);
79
+ }
80
+
81
+ const handleAbhaSDKMount = () => {
82
+ setShowAbhaSDK(true);
83
+
84
+ if (typeof window === "undefined") return;
85
+
86
+ waitForElement("abha-container", () => {
87
+ console.log("🎉 abha-container found!");
88
+
89
+ if (typeof window.initAbhaApp !== "function") {
90
+ console.error("❌ initAbhaApp is not available on window.");
91
+ return;
92
+ }
93
+
94
+ window.initAbhaApp({
95
+ clientId: "doc-web",
96
+ containerId: "abha-container",
97
+ method: "create_abha_with_mobile",
98
+ data: {},
99
+
100
+ onSuccess: ({ response }) => {
101
+ console.log("✅ ABHA Success:", response);
102
+ const t = new window.Bridge();
103
+ t.refreshPatientDirectory();
104
+ setShowAbhaSDK(false);
105
+ },
106
+
107
+ onError: ({ error, response }) => {
108
+ console.error("❌ ABHA Error:", error || response);
109
+ setShowAbhaSDK(false);
110
+ },
111
+
112
+ onAbhaClose: () => {
113
+ console.log("❌ ABHA Close");
114
+ const t = new window.Bridge();
115
+ t.refreshPatientDirectory();
116
+ setShowAbhaSDK(false);
117
+ },
118
+ });
119
+ });
120
+ };
121
+
122
+ const handleIframeMount = (type: string) => {
123
+ setShowWorkflowIframe(true);
124
+ const iframeUrl =
125
+ type === "upload"
126
+ ? "https://demo.arcade.software/R8kEyxUclnWTItas93qN?embed&embed_mobile=tab&embed_desktop=inline&show_copy_link=true"
127
+ : "https://demo.arcade.software/Bx1vEspdLmt5omIcks6H?embed&embed_mobile=tab&embed_desktop=inline&show_copy_link=true";
128
+ waitForElement("iframe-container", () => {
129
+ const container = document.getElementById("iframe-container");
130
+ if (!container) return;
131
+
132
+ container.innerHTML = "";
133
+ const iframe = document.createElement("iframe");
134
+ iframe.src = iframeUrl;
135
+ iframe.title = "Upload and Organize Patient Lab Reports";
136
+ iframe.frameBorder = "0";
137
+ iframe.loading = "lazy";
138
+ iframe.allowFullscreen = true;
139
+ iframe.allow = "clipboard-write";
140
+ iframe.className = "abhaDash-h-full abhaDash-w-full";
141
+ iframe.style.colorScheme = "light";
142
+
143
+ container.appendChild(iframe);
144
+ });
145
+ };
146
+
147
+ return (
148
+ <div className="abhaDash-p-25 abhaDash-h-[25%] ">
149
+ <div className="AbhaTitlesSubheadline">ABHA Workflows</div>
150
+
151
+ <div className="AbhaBody2Regular abhaDash-text-text-neutral-800-dark abhaDash-py-10">
152
+ Direct access to ABDM functions
153
+ </div>
154
+
155
+ <div className="abhaDash-flex abhaDash-flex-wrap abhaDash-gap-20 abhaDash-pt-20 abhaDash-pb-70 abhaDash-gap-y-20">
156
+ <WorkFlowCard
157
+ bodyColor="abhaDash-bg-bg-primary-light"
158
+ bodyText="Generate ABHA for new patients"
159
+ icon={faUserPlus}
160
+ iconBgGradColorFrom="abhaDash-from-[#2B7FFF]"
161
+ iconBgGradColorTo="abhaDash-to-[#155DFC]"
162
+ btnText="Create ABHA"
163
+ disabled={false}
164
+ cta={handleAbhaSDKMount}
165
+ mobileStyling={"max-md:abhaDash-w-169"}
166
+ />
167
+
168
+ <WorkFlowCard
169
+ bodyColor="abhaDash-bg-bg-yellow-light"
170
+ bodyText="Retrieve patient data from ABDM"
171
+ icon={faDownload}
172
+ iconBgGradColorFrom="abhaDash-from-[#FE9A00]"
173
+ iconBgGradColorTo="abhaDash-to-[#FF6900]"
174
+ btnText="Fetch Records"
175
+ disabled={false}
176
+ cta={() => handleIframeMount("fetch")}
177
+ mobileStyling={"max-md:abhaDash-w-169"}
178
+ />
179
+ <WorkFlowCard
180
+ bodyColor="abhaDash-bg-bg-green-light"
181
+ bodyText="Connect patient records to ABHA"
182
+ icon={faLink}
183
+ iconBgGradColorFrom="abhaDash-from-[#00BC7D]"
184
+ iconBgGradColorTo="abhaDash-to-[#009966]"
185
+ btnText="Upload & Link Records"
186
+ disabled={false}
187
+ cta={() => handleIframeMount("upload")}
188
+ mobileStyling={"max-md:abhaDash-w-360 max-md:abhaDash-flex max-md:abhaDash-gap-10 max-md:abhaDash-items-center"}
189
+ />
190
+
191
+ <div className="abhaDash-h-full abhaDash-w-380 abhaDash-pb-20">
192
+ <div className="abhaDash-w-full abhaDash-from-[#205CFF] abhaDash-to-[#AE71D2] abhaDash-bg-gradient-to-r abhaDash-border-1 abhaDash-rounded-20 abhaDash-border-bg-neutral-100-bg-dark abhaDash-p-20 ">
193
+ <div className="abhaDash-flex abhaDash-h-135 abhaDash-gap-20 abhaDash-text-text-white ">
194
+ <div className="abhaDash-h-full">
195
+ <QRCode
196
+ className="abhaDash-h-full abhaDash-w-full abhaDash-border abhaDash-border-bg-04 abhaDash-p-10 abhaDash-rounded-10"
197
+ value={qrUrl ?? ""}
198
+ />
199
+ </div>
200
+
201
+ <div className="abhaDash-flex-col abhaDash-flex abhaDash-justify-center">
202
+ <div className="AbhaTitle2Headline abhaDash-mb-10">
203
+ Instant Appointment for Patients
204
+ </div>
205
+ <div className="AbhaBody3Regular abhaDash-mb-10">
206
+ Patients can generate ABHA and book appointments using this QR
207
+ Code.
208
+ </div>
209
+ <div
210
+ className="AbhaTitle3Headline abhaDash-py-5 abhaDash-w-fit abhaDash-px-20 abhaDash-flex abhaDash-justify-center abhaDash-text-text-primary abhaDash-bg-bg-white abhaDash-rounded-20 abhaDash-cursor-pointer"
211
+ onClick={handlePdfGenerate}
212
+ >
213
+ {/* Download in your Language adding soon */}
214
+ Download and Share
215
+ </div>
216
+ </div>
217
+ </div>
218
+ </div>
219
+ </div>
220
+ </div>
221
+ </div>
222
+ );
223
+ };
224
+
225
+ export default AbhaWorkFlows;
@@ -0,0 +1,29 @@
1
+ const AutomateStrip = ({
2
+ setShowAutomateModal,
3
+ }: {
4
+ setShowAutomateModal: (show: boolean) => void;
5
+ }) => {
6
+ return (
7
+ <div className="abhaDash-px-25">
8
+ <div className="max-md:abhaDash-flex-col max-md:abhaDash-py-14 max-md:abhaDash-items-start abhaDash-bg-bg-green-light abhaDash-mx-auto abhaDash-flex abhaDash-px-20 abhaDash-py-8 abhaDash-rounded-10 abhaDash-justify-between abhaDash-items-center abhaDash-mt-20">
9
+ <div className="AbhaBody2Regular max-md:abhaDash-hidden">
10
+ Maximise your earnings by sending patients KYC requests, ABHA creation
11
+ and consent for accessing medical history
12
+ </div>
13
+
14
+ <div className="AbhaBody2Regular md:abhaDash-hidden">
15
+ Maximise your earnings by sending patients <br />
16
+ - KYC requests, <br />
17
+ - ABHA creation, and <br />- Consent for accessing medical history
18
+ </div>
19
+ <div
20
+ onClick={() => setShowAutomateModal(true)}
21
+ className="max-md:abhaDash-w-full max-md:abhaDash-text-center max-md:abhaDash-mt-14 AbhaTitle3Headline abhaDash-px-12 abhaDash-py-10 abhaDash-rounded-8 abhaDash-bg-bg-doc abhaDash-text-text-white abhaDash-cursor-pointer"
22
+ >
23
+ Automate tasks
24
+ </div>
25
+ </div>
26
+ </div>
27
+ );
28
+ };
29
+ export default AutomateStrip;
@@ -0,0 +1,75 @@
1
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
2
+ import CardLoader from "../loader/card-loader";
3
+ import { faCircleInfo } from "@fortawesome/free-solid-svg-icons";
4
+ import Loader from "../loader/abdm-dash-loader";
5
+
6
+ const MetricCard = ({
7
+ isDataLoaded,
8
+ total,
9
+ success,
10
+ failed,
11
+ successText,
12
+ failedText,
13
+ title,
14
+ cardIcon,
15
+ }: {
16
+ isDataLoaded?: boolean;
17
+ total?: number;
18
+ success?: number;
19
+ failed?: number;
20
+ successText?: string;
21
+ failedText?: string;
22
+ title?: string;
23
+ cardIcon?: any;
24
+ }) => {
25
+ return isDataLoaded ? (
26
+ <>
27
+ <div className="abhaDash-w-260 max-md:abhaDash-w-[47%] abhaDash-border-1 abhaDash-rounded-20 abhaDash-border-bg-green-dark abhaDash-bg-bg-white abhaDash-p-20">
28
+ <div className="abhaDash-flex abhaDash-justify-between">
29
+ <div className="AbhaTitleHeadline abhaDash-text-text-primary-dark">
30
+ {total ?? 0}
31
+ </div>
32
+ <FontAwesomeIcon
33
+ className="abhaDash-text-text-primary abhaDash-w-28 abhaDash-h-28"
34
+ icon={cardIcon}
35
+ />
36
+ </div>
37
+ <div className="AbhaTitle2Headline">{title}</div>
38
+
39
+ <CardLoader value={success ?? 0} total={total ?? 0} />
40
+
41
+ <div className="abhaDash-flex abhaDash-justify-between abhaDash-pt-5">
42
+ <div className="AbhaBody2Regular abhaDash-text-text-neutral-800-dark abhaDash-flex">
43
+ {successText}
44
+ <div
45
+ title={
46
+ title?.includes("Consent")
47
+ ? "No. Of consent requests granted with atleast 1 medical record(s) successfully retrieved"
48
+ : title?.includes("Records")
49
+ ? "No. Of records linked to KYC verified ABHA"
50
+ : "No. Of patients with KYC verified ABHA"
51
+ }
52
+ >
53
+ <FontAwesomeIcon
54
+ className="abhaDash-pl-5 abhaDash-w-14 abhaDash-h-14 abhaDash-cursor-pointer"
55
+ icon={faCircleInfo}
56
+ />
57
+ </div>
58
+ </div>
59
+ <div className="abhaDash-text-text-primary-dark">{success}</div>
60
+ </div>
61
+ <div className="abhaDash-flex abhaDash-justify-between">
62
+ <div className="AbhaBody2Regular abhaDash-text-text-neutral-800-dark">
63
+ {failedText}
64
+ </div>
65
+ <div className="abhaDash-text-text-red-primary">{failed}</div>
66
+ </div>
67
+ </div>
68
+ </>
69
+ ) : (
70
+ <div className="abhaDash-w-260 max-md:abhaDash-w-[47%] abhaDash-h-1/2 abhaDash-border-1 abhaDash-rounded-20 abhaDash-border-bg-green-dark abhaDash-bg-bg-white abhaDash-p-65">
71
+ <Loader bgColor="abhaDash-bg-bg-white" />
72
+ </div>
73
+ );
74
+ };
75
+ export default MetricCard;
@@ -0,0 +1,23 @@
1
+ const RequestCard = ({
2
+ bodyText,
3
+ btnText,
4
+ bodyColor,
5
+ }: {
6
+ bodyText: string;
7
+ btnText: string;
8
+ bodyColor: string;
9
+ }) => {
10
+ return (
11
+ <div
12
+ className={`${bodyColor} abhaDash-gap-10 abhaDash-text-neutral-1000-black abhaDash-flex abhaDash-items-center abhaDash-p-20 abhaDash-m-5 abhaDash-rounded-20 abhaDash-w-450`}
13
+ >
14
+ <div>
15
+ {bodyText}
16
+ </div>
17
+ <div className="AbhaTitle3Headline abhaDash-flex abhaDash-justify-center abhaDash-w-130 abhaDash-text-text-white abhaDash-bg-bg-doc abhaDash-py-12 abhaDash-px-10 abhaDash-rounded-8">
18
+ {btnText}
19
+ </div>
20
+ </div>
21
+ );
22
+ };
23
+ export default RequestCard;