@ammarkhalidfarooq/dashboard-package 0.5.16 → 0.5.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -887,6 +887,1485 @@ var Dashboard = function Dashboard(_ref) {
887
887
  });
888
888
  };
889
889
 
890
+ function formatNumber(num) {
891
+ if (num >= 1000000000) {
892
+ return (num / 1000000000).toFixed(1).replace(/\.0$/, "") + "B";
893
+ }
894
+ if (num >= 1000000) {
895
+ return (num / 1000000).toFixed(1).replace(/\.0$/, "") + "M";
896
+ }
897
+ if (num >= 1000) {
898
+ return (num / 1000).toFixed(1).replace(/\.0$/, "") + "K";
899
+ }
900
+ return (num !== null && num !== void 0 ? num : 0).toString();
901
+ }
902
+
903
+ var W = 794;
904
+ var H = 1123;
905
+ var MX = 32; // horizontal margin
906
+ var CW = W - MX * 2; // 730 px usable width
907
+
908
+ // ─── Number helpers ───────────────────────────────────────────────────────────
909
+ var d$ = function d$(v) {
910
+ return "$".concat(formatNumber(Number(v !== null && v !== void 0 ? v : 0)));
911
+ };
912
+ var pct = function pct(v) {
913
+ var dp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
914
+ return "".concat(Number(v !== null && v !== void 0 ? v : 0).toFixed(dp), "%");
915
+ };
916
+ var signed = function signed(v) {
917
+ var suffix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "%";
918
+ var n = Number(v !== null && v !== void 0 ? v : 0);
919
+ return "".concat(n >= 0 ? "+" : "").concat(n.toFixed(2)).concat(suffix);
920
+ };
921
+
922
+ // ─── SVG line sparkline ───────────────────────────────────────────────────────
923
+ var Sparkline = function Sparkline(_ref) {
924
+ var _ref$data = _ref.data,
925
+ data = _ref$data === void 0 ? [] : _ref$data,
926
+ _ref$color = _ref.color,
927
+ color = _ref$color === void 0 ? "#6366F1" : _ref$color,
928
+ _ref$width = _ref.width,
929
+ width = _ref$width === void 0 ? 120 : _ref$width,
930
+ _ref$height = _ref.height,
931
+ height = _ref$height === void 0 ? 40 : _ref$height;
932
+ var vals = data.length >= 2 ? data : [0, 0];
933
+ var max = Math.max.apply(Math, _toConsumableArray(vals).concat([0]));
934
+ var min = Math.min.apply(Math, _toConsumableArray(vals).concat([0]));
935
+ var range = max - min || 1;
936
+ var pad = 3;
937
+ var pts = vals.map(function (v, i) {
938
+ return [pad + i / (vals.length - 1) * (width - pad * 2), pad + (height - pad * 2) - (v - min) / range * (height - pad * 2)];
939
+ });
940
+ var d = pts.map(function (p, i) {
941
+ return "".concat(i === 0 ? "M" : "L").concat(p[0].toFixed(1), ",").concat(p[1].toFixed(1));
942
+ }).join(" ");
943
+ var area = "".concat(d, " L").concat((width - pad).toFixed(1), ",").concat(height, " L").concat(pad, ",").concat(height, " Z");
944
+ var gradId = "sp-".concat(color.replace(/[^a-z0-9]/gi, ""));
945
+ return /*#__PURE__*/jsxRuntime.jsxs("svg", {
946
+ width: width,
947
+ height: height,
948
+ style: {
949
+ display: "block",
950
+ overflow: "visible"
951
+ },
952
+ children: [/*#__PURE__*/jsxRuntime.jsx("defs", {
953
+ children: /*#__PURE__*/jsxRuntime.jsxs("linearGradient", {
954
+ id: gradId,
955
+ x1: "0",
956
+ y1: "0",
957
+ x2: "0",
958
+ y2: "1",
959
+ children: [/*#__PURE__*/jsxRuntime.jsx("stop", {
960
+ offset: "0%",
961
+ stopColor: color,
962
+ stopOpacity: "0.15"
963
+ }), /*#__PURE__*/jsxRuntime.jsx("stop", {
964
+ offset: "100%",
965
+ stopColor: color,
966
+ stopOpacity: "0"
967
+ })]
968
+ })
969
+ }), /*#__PURE__*/jsxRuntime.jsx("path", {
970
+ d: area,
971
+ fill: "url(#".concat(gradId, ")")
972
+ }), /*#__PURE__*/jsxRuntime.jsx("path", {
973
+ d: d,
974
+ fill: "none",
975
+ stroke: color,
976
+ strokeWidth: 2,
977
+ strokeLinecap: "round",
978
+ strokeLinejoin: "round"
979
+ })]
980
+ });
981
+ };
982
+
983
+ // ─── SVG multi-series line chart ──────────────────────────────────────────────
984
+ var LineChart = function LineChart(_ref2) {
985
+ var _ref2$series = _ref2.series,
986
+ series = _ref2$series === void 0 ? [] : _ref2$series,
987
+ _ref2$categories = _ref2.categories,
988
+ categories = _ref2$categories === void 0 ? [] : _ref2$categories,
989
+ _ref2$width = _ref2.width,
990
+ width = _ref2$width === void 0 ? CW : _ref2$width,
991
+ _ref2$height = _ref2.height,
992
+ height = _ref2$height === void 0 ? 180 : _ref2$height;
993
+ var allVals = series.flatMap(function (s) {
994
+ return s.data || [];
995
+ });
996
+ if (!allVals.length) {
997
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
998
+ style: {
999
+ height: height,
1000
+ background: "#F9FAFB",
1001
+ borderRadius: 6
1002
+ }
1003
+ });
1004
+ }
1005
+ var COLORS = ["#6366F1", "#10B981", "#06B6D4"];
1006
+ var PL = 46,
1007
+ PR = 8,
1008
+ PT = 8,
1009
+ PB = 22;
1010
+ var IW = width - PL - PR;
1011
+ var IH = height - PT - PB;
1012
+ var max = Math.max.apply(Math, _toConsumableArray(allVals).concat([0]));
1013
+ var min = 0;
1014
+ var range = max - min || 1;
1015
+ var xp = function xp(i, n) {
1016
+ return PL + i / Math.max(n - 1, 1) * IW;
1017
+ };
1018
+ var yp = function yp(v) {
1019
+ return PT + IH - (v - min) / range * IH;
1020
+ };
1021
+ var yTicks = [0, 0.25, 0.5, 0.75, 1].map(function (t) {
1022
+ return min + t * range;
1023
+ });
1024
+ var step = Math.max(1, Math.floor(categories.length / 6));
1025
+ var shownCats = categories.filter(function (_, i) {
1026
+ return i % step === 0 || i === categories.length - 1;
1027
+ });
1028
+ return /*#__PURE__*/jsxRuntime.jsxs("svg", {
1029
+ width: width,
1030
+ height: height,
1031
+ style: {
1032
+ display: "block"
1033
+ },
1034
+ children: [yTicks.map(function (v, i) {
1035
+ var y = yp(v);
1036
+ var label = v >= 10000 ? "$".concat((v / 1000).toFixed(0), "K") : v >= 1000 ? "$".concat((v / 1000).toFixed(1), "K") : "$".concat(v.toFixed(0));
1037
+ return /*#__PURE__*/jsxRuntime.jsxs("g", {
1038
+ children: [/*#__PURE__*/jsxRuntime.jsx("line", {
1039
+ x1: PL,
1040
+ y1: y,
1041
+ x2: width - PR,
1042
+ y2: y,
1043
+ stroke: "#F3F4F6",
1044
+ strokeWidth: 1
1045
+ }), /*#__PURE__*/jsxRuntime.jsx("text", {
1046
+ x: PL - 4,
1047
+ y: y + 3.5,
1048
+ textAnchor: "end",
1049
+ fontSize: 9,
1050
+ fill: "#9CA3AF",
1051
+ children: label
1052
+ })]
1053
+ }, i);
1054
+ }), series.map(function (s, si) {
1055
+ var data = s.data || [];
1056
+ if (!data.length) return null;
1057
+ var pathD = data.map(function (v, i) {
1058
+ return "".concat(i === 0 ? "M" : "L").concat(xp(i, data.length).toFixed(1), ",").concat(yp(v).toFixed(1));
1059
+ }).join(" ");
1060
+ return /*#__PURE__*/jsxRuntime.jsx("path", {
1061
+ d: pathD,
1062
+ fill: "none",
1063
+ stroke: COLORS[si % COLORS.length],
1064
+ strokeWidth: 2,
1065
+ strokeLinecap: "round",
1066
+ strokeLinejoin: "round"
1067
+ }, si);
1068
+ }), shownCats.map(function (label, i) {
1069
+ var origIdx = categories.indexOf(label);
1070
+ var x = xp(origIdx < 0 ? i * step : origIdx, categories.length);
1071
+ return /*#__PURE__*/jsxRuntime.jsx("text", {
1072
+ x: x,
1073
+ y: height - 5,
1074
+ textAnchor: "middle",
1075
+ fontSize: 9,
1076
+ fill: "#9CA3AF",
1077
+ children: label
1078
+ }, i);
1079
+ })]
1080
+ });
1081
+ };
1082
+
1083
+ // ─── SVG donut ────────────────────────────────────────────────────────────────
1084
+ var Donut = function Donut(_ref3) {
1085
+ var _ref3$segments = _ref3.segments,
1086
+ segments = _ref3$segments === void 0 ? [] : _ref3$segments,
1087
+ _ref3$size = _ref3.size,
1088
+ size = _ref3$size === void 0 ? 88 : _ref3$size,
1089
+ centerVal = _ref3.centerVal,
1090
+ centerLabel = _ref3.centerLabel;
1091
+ var total = segments.reduce(function (s, g) {
1092
+ return s + (g.value || 0);
1093
+ }, 0) || 1;
1094
+ var r = (size - 18) / 2;
1095
+ var cx = size / 2;
1096
+ var cy = size / 2;
1097
+ var circ = 2 * Math.PI * r;
1098
+ var cumulDash = 0;
1099
+ return /*#__PURE__*/jsxRuntime.jsxs("svg", {
1100
+ width: size,
1101
+ height: size,
1102
+ style: {
1103
+ display: "block"
1104
+ },
1105
+ children: [/*#__PURE__*/jsxRuntime.jsx("circle", {
1106
+ cx: cx,
1107
+ cy: cy,
1108
+ r: r,
1109
+ fill: "none",
1110
+ stroke: "#E5E7EB",
1111
+ strokeWidth: 12
1112
+ }), segments.map(function (seg, i) {
1113
+ var dash = seg.value / total * circ;
1114
+ var el = /*#__PURE__*/jsxRuntime.jsx("circle", {
1115
+ cx: cx,
1116
+ cy: cy,
1117
+ r: r,
1118
+ fill: "none",
1119
+ stroke: seg.color || "#6366F1",
1120
+ strokeWidth: 12,
1121
+ strokeDasharray: "".concat(dash, " ").concat(circ),
1122
+ strokeDashoffset: -cumulDash,
1123
+ strokeLinecap: "butt",
1124
+ transform: "rotate(-90 ".concat(cx, " ").concat(cy, ")")
1125
+ }, i);
1126
+ cumulDash += dash;
1127
+ return el;
1128
+ }), centerVal && /*#__PURE__*/jsxRuntime.jsx("text", {
1129
+ x: cx,
1130
+ y: cy - (centerLabel ? 5 : 0),
1131
+ textAnchor: "middle",
1132
+ fontSize: 14,
1133
+ fontWeight: "bold",
1134
+ fill: "#111827",
1135
+ children: centerVal
1136
+ }), centerLabel && /*#__PURE__*/jsxRuntime.jsx("text", {
1137
+ x: cx,
1138
+ y: cy + 13,
1139
+ textAnchor: "middle",
1140
+ fontSize: 9,
1141
+ fill: "#6B7280",
1142
+ children: centerLabel
1143
+ })]
1144
+ });
1145
+ };
1146
+
1147
+ // ─── Shared primitives ────────────────────────────────────────────────────────
1148
+ var Divider = function Divider(_ref4) {
1149
+ var _ref4$mt = _ref4.mt,
1150
+ mt = _ref4$mt === void 0 ? 0 : _ref4$mt,
1151
+ _ref4$mb = _ref4.mb,
1152
+ mb = _ref4$mb === void 0 ? 0 : _ref4$mb;
1153
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
1154
+ style: {
1155
+ borderTop: "1px solid #E5E7EB",
1156
+ marginTop: mt,
1157
+ marginBottom: mb
1158
+ }
1159
+ });
1160
+ };
1161
+ var Panel = function Panel(_ref5) {
1162
+ var children = _ref5.children,
1163
+ title = _ref5.title,
1164
+ subtitle = _ref5.subtitle,
1165
+ action = _ref5.action,
1166
+ _ref5$style = _ref5.style,
1167
+ style = _ref5$style === void 0 ? {} : _ref5$style;
1168
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1169
+ style: _objectSpread2({
1170
+ border: "1px solid #E5E7EB",
1171
+ borderRadius: 8,
1172
+ background: "#fff",
1173
+ padding: 12,
1174
+ display: "flex",
1175
+ flexDirection: "column",
1176
+ boxSizing: "border-box"
1177
+ }, style),
1178
+ children: [(title || subtitle || action) && /*#__PURE__*/jsxRuntime.jsxs("div", {
1179
+ style: {
1180
+ display: "flex",
1181
+ justifyContent: "space-between",
1182
+ alignItems: "flex-start",
1183
+ marginBottom: 8,
1184
+ flexShrink: 0
1185
+ },
1186
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1187
+ children: [title && /*#__PURE__*/jsxRuntime.jsx("div", {
1188
+ style: {
1189
+ fontSize: 12,
1190
+ fontWeight: 700,
1191
+ color: "#111827",
1192
+ lineHeight: 1.2
1193
+ },
1194
+ children: title
1195
+ }), subtitle && /*#__PURE__*/jsxRuntime.jsx("div", {
1196
+ style: {
1197
+ fontSize: 9.5,
1198
+ color: "#9CA3AF",
1199
+ marginTop: 2
1200
+ },
1201
+ children: subtitle
1202
+ })]
1203
+ }), action && /*#__PURE__*/jsxRuntime.jsx("div", {
1204
+ style: {
1205
+ fontSize: 9.5,
1206
+ color: "#6366F1",
1207
+ fontWeight: 500,
1208
+ flexShrink: 0
1209
+ },
1210
+ children: action
1211
+ })]
1212
+ }), children]
1213
+ });
1214
+ };
1215
+ var MiniTable = function MiniTable(_ref6) {
1216
+ var _ref6$head = _ref6.head,
1217
+ head = _ref6$head === void 0 ? [] : _ref6$head,
1218
+ _ref6$rows = _ref6.rows,
1219
+ rows = _ref6$rows === void 0 ? [] : _ref6$rows;
1220
+ return /*#__PURE__*/jsxRuntime.jsxs("table", {
1221
+ style: {
1222
+ width: "100%",
1223
+ borderCollapse: "collapse",
1224
+ fontSize: 9.5,
1225
+ tableLayout: "fixed"
1226
+ },
1227
+ children: [/*#__PURE__*/jsxRuntime.jsx("thead", {
1228
+ children: /*#__PURE__*/jsxRuntime.jsx("tr", {
1229
+ style: {
1230
+ background: "#F9FAFB"
1231
+ },
1232
+ children: head.map(function (h, i) {
1233
+ return /*#__PURE__*/jsxRuntime.jsx("th", {
1234
+ style: {
1235
+ padding: "4px 6px",
1236
+ textAlign: i === 0 ? "left" : "right",
1237
+ fontWeight: 700,
1238
+ fontSize: 8.5,
1239
+ letterSpacing: "0.3px",
1240
+ color: "#6B7280",
1241
+ borderBottom: "1px solid #E5E7EB"
1242
+ },
1243
+ children: h
1244
+ }, i);
1245
+ })
1246
+ })
1247
+ }), /*#__PURE__*/jsxRuntime.jsx("tbody", {
1248
+ children: rows.map(function (row, ri) {
1249
+ return /*#__PURE__*/jsxRuntime.jsx("tr", {
1250
+ style: {
1251
+ background: ri % 2 === 1 ? "#F9FAFB" : "#fff"
1252
+ },
1253
+ children: row.map(function (cell, ci) {
1254
+ return /*#__PURE__*/jsxRuntime.jsx("td", {
1255
+ style: {
1256
+ padding: "4px 6px",
1257
+ textAlign: ci === 0 ? "left" : "right",
1258
+ color: "#374151",
1259
+ borderBottom: ri < rows.length - 1 ? "1px solid #F3F4F6" : "none"
1260
+ },
1261
+ children: cell
1262
+ }, ci);
1263
+ })
1264
+ }, ri);
1265
+ })
1266
+ })]
1267
+ });
1268
+ };
1269
+ var KpiCard = function KpiCard(_ref7) {
1270
+ var title = _ref7.title,
1271
+ value = _ref7.value,
1272
+ trend = _ref7.trend,
1273
+ detail = _ref7.detail;
1274
+ var neg = "".concat(trend).trim().startsWith("-");
1275
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1276
+ style: {
1277
+ border: "1px solid #E5E7EB",
1278
+ borderRadius: 8,
1279
+ padding: "10px 12px 9px",
1280
+ background: "#fff",
1281
+ width: "100%",
1282
+ minWidth: 0,
1283
+ boxSizing: "border-box",
1284
+ display: "flex",
1285
+ flexDirection: "column",
1286
+ gap: 2
1287
+ },
1288
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1289
+ style: {
1290
+ fontSize: 8,
1291
+ fontWeight: 700,
1292
+ letterSpacing: "0.7px",
1293
+ color: "#6B7280",
1294
+ textTransform: "uppercase"
1295
+ },
1296
+ children: title
1297
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1298
+ style: {
1299
+ fontSize: 17,
1300
+ fontWeight: 800,
1301
+ color: "#111827",
1302
+ lineHeight: 1.1,
1303
+ marginTop: 2
1304
+ },
1305
+ children: value
1306
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1307
+ style: {
1308
+ fontSize: 10.5,
1309
+ fontWeight: 600,
1310
+ color: neg ? "#DC2626" : "#16A34A"
1311
+ },
1312
+ children: trend
1313
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1314
+ style: {
1315
+ fontSize: 8.5,
1316
+ color: "#9CA3AF",
1317
+ lineHeight: 1.4
1318
+ },
1319
+ children: detail
1320
+ })]
1321
+ });
1322
+ };
1323
+ var StatPair = function StatPair(_ref8) {
1324
+ var label = _ref8.label,
1325
+ val = _ref8.val,
1326
+ trend = _ref8.trend;
1327
+ var neg = "".concat(trend).trim().startsWith("-");
1328
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1329
+ style: {
1330
+ marginBottom: 6
1331
+ },
1332
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1333
+ style: {
1334
+ fontSize: 8.5,
1335
+ color: "#9CA3AF",
1336
+ marginBottom: 1
1337
+ },
1338
+ children: label
1339
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1340
+ style: {
1341
+ display: "flex",
1342
+ alignItems: "baseline",
1343
+ gap: 4
1344
+ },
1345
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1346
+ style: {
1347
+ fontSize: 13,
1348
+ fontWeight: 700,
1349
+ color: "#111827"
1350
+ },
1351
+ children: val
1352
+ }), trend && /*#__PURE__*/jsxRuntime.jsx("span", {
1353
+ style: {
1354
+ fontSize: 9.5,
1355
+ fontWeight: 600,
1356
+ color: neg ? "#DC2626" : "#16A34A"
1357
+ },
1358
+ children: trend
1359
+ })]
1360
+ })]
1361
+ });
1362
+ };
1363
+ var PageHeader = function PageHeader(_ref9) {
1364
+ var dateLabel = _ref9.dateLabel,
1365
+ generatedLabel = _ref9.generatedLabel,
1366
+ activeFilters = _ref9.activeFilters,
1367
+ page = _ref9.page;
1368
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1369
+ style: {
1370
+ padding: "22px ".concat(MX, "px 12px"),
1371
+ borderBottom: "1px solid #E5E7EB",
1372
+ flexShrink: 0
1373
+ },
1374
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1375
+ style: {
1376
+ display: "flex",
1377
+ justifyContent: "space-between",
1378
+ alignItems: "center"
1379
+ },
1380
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
1381
+ style: {
1382
+ display: "flex",
1383
+ alignItems: "baseline",
1384
+ gap: 10
1385
+ },
1386
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1387
+ style: {
1388
+ fontSize: 20,
1389
+ fontWeight: 800,
1390
+ color: "#111827",
1391
+ letterSpacing: "-0.5px"
1392
+ },
1393
+ children: "Madinah"
1394
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
1395
+ style: {
1396
+ fontSize: 8.5,
1397
+ fontWeight: 700,
1398
+ letterSpacing: "1.5px",
1399
+ color: "#9CA3AF",
1400
+ textTransform: "uppercase"
1401
+ },
1402
+ children: "PERFORMANCE REPORT"
1403
+ })]
1404
+ })
1405
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1406
+ style: {
1407
+ marginTop: 8,
1408
+ fontSize: 13.5,
1409
+ fontWeight: 700,
1410
+ color: "#111827"
1411
+ },
1412
+ children: "Dashboard overview \u2014 Overall"
1413
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1414
+ style: {
1415
+ display: "flex",
1416
+ justifyContent: "space-between",
1417
+ marginTop: 2
1418
+ },
1419
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1420
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1421
+ style: {
1422
+ fontSize: 10.5,
1423
+ color: "#374151"
1424
+ },
1425
+ children: dateLabel
1426
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1427
+ style: {
1428
+ fontSize: 9.5,
1429
+ color: "#9CA3AF",
1430
+ marginTop: 1
1431
+ },
1432
+ children: ["30-day window \xB7 Generated ", generatedLabel]
1433
+ })]
1434
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1435
+ style: {
1436
+ fontSize: 9,
1437
+ color: "#9CA3AF",
1438
+ textAlign: "right",
1439
+ alignSelf: "flex-end"
1440
+ },
1441
+ children: ["Page ", page, " of 2"]
1442
+ })]
1443
+ }), activeFilters && /*#__PURE__*/jsxRuntime.jsxs("div", {
1444
+ style: {
1445
+ marginTop: 7,
1446
+ display: "inline-flex",
1447
+ gap: 5,
1448
+ background: "#F9FAFB",
1449
+ border: "1px solid #E5E7EB",
1450
+ borderRadius: 4,
1451
+ padding: "3px 9px",
1452
+ fontSize: 8.5
1453
+ },
1454
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1455
+ style: {
1456
+ fontWeight: 700,
1457
+ color: "#374151",
1458
+ letterSpacing: "0.4px"
1459
+ },
1460
+ children: "ACTIVE FILTERS"
1461
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
1462
+ style: {
1463
+ color: "#6B7280"
1464
+ },
1465
+ children: activeFilters
1466
+ })]
1467
+ })]
1468
+ });
1469
+ };
1470
+ var PageFooter = function PageFooter(_ref0) {
1471
+ var generatedLabel = _ref0.generatedLabel,
1472
+ page = _ref0.page;
1473
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
1474
+ style: {
1475
+ padding: "7px ".concat(MX, "px"),
1476
+ borderTop: "1px solid #E5E7EB",
1477
+ marginTop: "auto",
1478
+ flexShrink: 0
1479
+ },
1480
+ children: /*#__PURE__*/jsxRuntime.jsxs("span", {
1481
+ style: {
1482
+ fontSize: 8,
1483
+ color: "#9CA3AF"
1484
+ },
1485
+ children: ["Confidential \xB7 Generated by Dashboard \xB7 ", generatedLabel, " \xA0\xA0 Page ", page, " of 2 \xB7 madinah.com"]
1486
+ })
1487
+ });
1488
+ };
1489
+
1490
+ // ─── Main component ───────────────────────────────────────────────────────────
1491
+ var ExportPdfLayout = /*#__PURE__*/React.forwardRef(function (_ref1, ref) {
1492
+ var _apiData$overviewStat, _apiData$trafficSourc, _apiData$trafficSourc2, _apiData$overviewStat2, _ob$peakDay;
1493
+ var _ref1$apiData = _ref1.apiData,
1494
+ apiData = _ref1$apiData === void 0 ? {} : _ref1$apiData,
1495
+ _ref1$dateName = _ref1.dateName,
1496
+ dateName = _ref1$dateName === void 0 ? "Last Period" : _ref1$dateName;
1497
+ var now = new Date();
1498
+ var generatedLabel = now.toLocaleDateString("en-US", {
1499
+ month: "short",
1500
+ day: "numeric",
1501
+ year: "numeric"
1502
+ }) + " · " + now.toLocaleTimeString("en-US", {
1503
+ hour: "2-digit",
1504
+ minute: "2-digit"
1505
+ }) + " GMT";
1506
+ var dateLabel = dateName;
1507
+ var activeFilters = (apiData === null || apiData === void 0 ? void 0 : apiData.activeFilters) || "";
1508
+
1509
+ // ── data (reference-first defaults, with selective API overrides) ─────────
1510
+ var overview = (apiData === null || apiData === void 0 || (_apiData$overviewStat = apiData.overviewStats) === null || _apiData$overviewStat === void 0 ? void 0 : _apiData$overviewStat.overview) || {};
1511
+ var growth = (overview === null || overview === void 0 ? void 0 : overview.growthPercentage) || {};
1512
+ var sample = {
1513
+ totalRaised: 240938,
1514
+ netRaised: 222300,
1515
+ totalDonors: 215,
1516
+ avgDonation: 130.58,
1517
+ convRate: 1.7,
1518
+ totalVisits: 12438,
1519
+ roas: 3.0,
1520
+ roasGrowth: 0.4,
1521
+ refundRate: 0.84,
1522
+ refundChange: -0.3,
1523
+ refundCount: 2,
1524
+ newDonors: 31,
1525
+ returningDonors: 184,
1526
+ medianGift: 75,
1527
+ topDecileGift: 850,
1528
+ adSpend: 72000,
1529
+ attributedRevenue: 215000
1530
+ };
1531
+ var prefer = function prefer(val, fallback) {
1532
+ var num = Number(val);
1533
+ return Number.isFinite(num) && num !== 0 ? num : fallback;
1534
+ };
1535
+ var totalRaised = prefer(overview === null || overview === void 0 ? void 0 : overview.totalRevenue, sample.totalRaised);
1536
+ var netRaised = prefer(overview === null || overview === void 0 ? void 0 : overview.netRevenue, sample.netRaised);
1537
+ var totalDonors = prefer(overview === null || overview === void 0 ? void 0 : overview.totalDonations, sample.totalDonors);
1538
+ var avgDonation = prefer(overview === null || overview === void 0 ? void 0 : overview.overallAVGDonations, sample.avgDonation);
1539
+ var convRate = prefer(overview === null || overview === void 0 ? void 0 : overview.conversionRate, sample.convRate);
1540
+ var totalVisits = prefer(apiData === null || apiData === void 0 ? void 0 : apiData.totalVisits, sample.totalVisits);
1541
+ var passThrough = totalRaised > 0 ? "".concat((netRaised / totalRaised * 100).toFixed(1), "% pass-through") : "92.3% pass-through";
1542
+ var refundsRaw = (apiData === null || apiData === void 0 ? void 0 : apiData.refundAndChargeBacks) || {};
1543
+ var refundRate = prefer(refundsRaw === null || refundsRaw === void 0 ? void 0 : refundsRaw.refundRate, sample.refundRate);
1544
+ var chargebackRate = prefer(refundsRaw === null || refundsRaw === void 0 ? void 0 : refundsRaw.chargebackRate, 0.1);
1545
+
1546
+ // donor mix
1547
+ var donorMixRaw = apiData === null || apiData === void 0 ? void 0 : apiData.donorPieChartData;
1548
+ var newDonors = sample.newDonors,
1549
+ returningDonors = sample.returningDonors,
1550
+ mixAvgGift = avgDonation;
1551
+ if (Array.isArray(donorMixRaw)) {
1552
+ var nd = donorMixRaw.find(function (d) {
1553
+ return /new/i.test(d.type);
1554
+ }) || {};
1555
+ var rd = donorMixRaw.find(function (d) {
1556
+ return /returning/i.test(d.type);
1557
+ }) || {};
1558
+ newDonors = nd.totalDonations || 0;
1559
+ returningDonors = rd.totalDonations || 0;
1560
+ var totAmt = (nd.totalAmount || 0) + (rd.totalAmount || 0);
1561
+ var totCnt = newDonors + returningDonors;
1562
+ mixAvgGift = totCnt > 0 ? totAmt / totCnt : avgDonation;
1563
+ } else if (donorMixRaw) {
1564
+ newDonors = donorMixRaw.newDonors || 0;
1565
+ returningDonors = donorMixRaw.returningDonors || 0;
1566
+ mixAvgGift = donorMixRaw.avgGift || avgDonation;
1567
+ }
1568
+ var totalMix = newDonors + returningDonors || 1;
1569
+ var newPct = Math.round(newDonors / totalMix * 100);
1570
+ var retPct = 100 - newPct;
1571
+
1572
+ // recurring / one-time
1573
+ var recData = Array.isArray(apiData === null || apiData === void 0 ? void 0 : apiData.recurringBarChartData) ? apiData.recurringBarChartData : [];
1574
+ var recurringTotal = recData.reduce(function (s, i) {
1575
+ return s + Number(i.recurring || i.recurringAmount || 0);
1576
+ }, 0);
1577
+ var oneTimeTotal = recData.reduce(function (s, i) {
1578
+ return s + Number(i.oneTime || i.oneTimeAmount || 0);
1579
+ }, 0);
1580
+
1581
+ // donor geography
1582
+ var geoRaw = apiData === null || apiData === void 0 ? void 0 : apiData.donorGeography;
1583
+ var geoList = Array.isArray(geoRaw) ? geoRaw : Array.isArray(geoRaw === null || geoRaw === void 0 ? void 0 : geoRaw.data) ? geoRaw.data : [];
1584
+
1585
+ // traffic source
1586
+ var trafficItems = Array.isArray(apiData === null || apiData === void 0 || (_apiData$trafficSourc = apiData.trafficSourceData) === null || _apiData$trafficSourc === void 0 ? void 0 : _apiData$trafficSourc.data) ? apiData.trafficSourceData.data : [];
1587
+ var trafficTotal = Number((apiData === null || apiData === void 0 || (_apiData$trafficSourc2 = apiData.trafficSourceData) === null || _apiData$trafficSourc2 === void 0 ? void 0 : _apiData$trafficSourc2.totalRevenue) || 0);
1588
+
1589
+ // revenue trend series
1590
+ var stackedTR = (apiData === null || apiData === void 0 || (_apiData$overviewStat2 = apiData.overviewStats) === null || _apiData$overviewStat2 === void 0 ? void 0 : _apiData$overviewStat2.totalRaised) || {};
1591
+ var revSeries = [{
1592
+ name: "Email",
1593
+ data: ((stackedTR === null || stackedTR === void 0 ? void 0 : stackedTR.email) || []).map(function (i) {
1594
+ return i.value || 0;
1595
+ })
1596
+ }, {
1597
+ name: "Organic",
1598
+ data: ((stackedTR === null || stackedTR === void 0 ? void 0 : stackedTR.organic) || []).map(function (i) {
1599
+ return i.value || 0;
1600
+ })
1601
+ }, {
1602
+ name: "Paid Ads",
1603
+ data: ((stackedTR === null || stackedTR === void 0 ? void 0 : stackedTR.paidAds) || []).map(function (i) {
1604
+ return i.value || 0;
1605
+ })
1606
+ }].filter(function (s) {
1607
+ return s.data.length > 0;
1608
+ });
1609
+ var revCats = ((stackedTR === null || stackedTR === void 0 ? void 0 : stackedTR.organic) || (stackedTR === null || stackedTR === void 0 ? void 0 : stackedTR.paidAds) || (stackedTR === null || stackedTR === void 0 ? void 0 : stackedTR.email) || []).map(function (i) {
1610
+ return i.date || "";
1611
+ });
1612
+
1613
+ // campaigns
1614
+ var campaigns = (apiData === null || apiData === void 0 ? void 0 : apiData.activeCampaigns) || [];
1615
+
1616
+ // order bump
1617
+ var ob = (apiData === null || apiData === void 0 ? void 0 : apiData.orderBumpDetails) || {};
1618
+ var obData = ((ob === null || ob === void 0 ? void 0 : ob.chart) || []).map(function (i) {
1619
+ return Number(i.revenue || 0);
1620
+ });
1621
+
1622
+ // upsell / downsell
1623
+ var up = (apiData === null || apiData === void 0 ? void 0 : apiData.upSellDetails) || {};
1624
+ var dn = (apiData === null || apiData === void 0 ? void 0 : apiData.downSellDetails) || {};
1625
+
1626
+ // referrals
1627
+ var refCard = (apiData === null || apiData === void 0 ? void 0 : apiData.referralDetails) || {};
1628
+ var refData = ((refCard === null || refCard === void 0 ? void 0 : refCard.chartData) || []).map(function (i) {
1629
+ return Number(i.revenue || 0);
1630
+ });
1631
+ var C = {
1632
+ indigo: "#6366F1",
1633
+ emerald: "#10B981",
1634
+ cyan: "#06B6D4"
1635
+ };
1636
+ var headerProps = {
1637
+ dateLabel: dateLabel,
1638
+ generatedLabel: generatedLabel,
1639
+ activeFilters: activeFilters
1640
+ };
1641
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1642
+ ref: ref,
1643
+ style: {
1644
+ display: "inline-flex",
1645
+ flexDirection: "column",
1646
+ gap: 0,
1647
+ background: "#fff"
1648
+ },
1649
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1650
+ "data-export-page": "1",
1651
+ style: {
1652
+ width: W,
1653
+ height: H,
1654
+ background: "#fff",
1655
+ display: "flex",
1656
+ flexDirection: "column",
1657
+ fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
1658
+ boxSizing: "border-box",
1659
+ overflow: "hidden"
1660
+ },
1661
+ children: [/*#__PURE__*/jsxRuntime.jsx(PageHeader, _objectSpread2(_objectSpread2({}, headerProps), {}, {
1662
+ page: 1
1663
+ })), /*#__PURE__*/jsxRuntime.jsxs("div", {
1664
+ style: {
1665
+ flex: 1,
1666
+ padding: "12px ".concat(MX, "px 10px"),
1667
+ display: "flex",
1668
+ flexDirection: "column",
1669
+ gap: 10,
1670
+ overflow: "hidden"
1671
+ },
1672
+ children: [/*#__PURE__*/jsxRuntime.jsx(KpiCard, {
1673
+ title: "Total Raised",
1674
+ value: d$(totalRaised),
1675
+ trend: "".concat(signed((growth === null || growth === void 0 ? void 0 : growth.totalRevenue) || 18), " vs last month"),
1676
+ detail: "".concat(passThrough, " \xB7 ").concat(formatNumber(totalDonors), " donors \xB7 ").concat(d$(avgDonation), " avg \xB7 ").concat(formatNumber(totalVisits), " visits")
1677
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1678
+ style: {
1679
+ display: "grid",
1680
+ gridTemplateColumns: "repeat(3, 1fr)",
1681
+ gap: 7
1682
+ },
1683
+ children: [/*#__PURE__*/jsxRuntime.jsx(KpiCard, {
1684
+ title: "Net Raised",
1685
+ value: d$(netRaised),
1686
+ trend: signed((growth === null || growth === void 0 ? void 0 : growth.netRevenue) || 17.4),
1687
+ detail: passThrough
1688
+ }), /*#__PURE__*/jsxRuntime.jsx(KpiCard, {
1689
+ title: "Total Donors",
1690
+ value: "".concat(formatNumber(totalDonors)),
1691
+ trend: signed((growth === null || growth === void 0 ? void 0 : growth.totalDonations) || 16.8),
1692
+ detail: "".concat(formatNumber(newDonors), " new \xB7 ").concat(formatNumber(returningDonors), " returning")
1693
+ }), /*#__PURE__*/jsxRuntime.jsx(KpiCard, {
1694
+ title: "Avg Donation",
1695
+ value: d$(avgDonation),
1696
+ trend: signed((growth === null || growth === void 0 ? void 0 : growth.overallAVGDonations) || 8.4),
1697
+ detail: "Median ".concat(d$((apiData === null || apiData === void 0 ? void 0 : apiData.medianGift) || sample.medianGift), " \xB7 top decile ").concat(d$((apiData === null || apiData === void 0 ? void 0 : apiData.topDecileGift) || sample.topDecileGift))
1698
+ })]
1699
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1700
+ style: {
1701
+ display: "grid",
1702
+ gridTemplateColumns: "repeat(3, 1fr)",
1703
+ gap: 7
1704
+ },
1705
+ children: [/*#__PURE__*/jsxRuntime.jsx(KpiCard, {
1706
+ title: "ROAS",
1707
+ value: "".concat(formatNumber((apiData === null || apiData === void 0 ? void 0 : apiData.roasCard) || sample.roas), "\xD7"),
1708
+ trend: signed((apiData === null || apiData === void 0 ? void 0 : apiData.roasCardPrev) || sample.roasGrowth, "×"),
1709
+ detail: "".concat(d$((apiData === null || apiData === void 0 ? void 0 : apiData.adSpend) || sample.adSpend), " spend \xB7 ").concat(d$((apiData === null || apiData === void 0 ? void 0 : apiData.attributedRevenue) || sample.attributedRevenue), " attrib.")
1710
+ }), /*#__PURE__*/jsxRuntime.jsx(KpiCard, {
1711
+ title: "Conversion",
1712
+ value: pct(convRate, 1),
1713
+ trend: "".concat(signed((growth === null || growth === void 0 ? void 0 : growth.conversionRate) || 0.21, "pp")),
1714
+ detail: "".concat(formatNumber(totalDonors), " from ").concat(formatNumber(totalVisits), " visits")
1715
+ }), /*#__PURE__*/jsxRuntime.jsx(KpiCard, {
1716
+ title: "Refund Rate",
1717
+ value: pct(refundRate, 2),
1718
+ trend: "".concat(signed((refundsRaw === null || refundsRaw === void 0 ? void 0 : refundsRaw.refundRateChange) || sample.refundChange, "pp")),
1719
+ detail: "".concat(formatNumber((refundsRaw === null || refundsRaw === void 0 ? void 0 : refundsRaw.refundCount) || sample.refundCount), " refunds this period")
1720
+ })]
1721
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1722
+ style: {
1723
+ border: "1px solid #E5E7EB",
1724
+ borderRadius: 8,
1725
+ background: "#fff",
1726
+ padding: "12px 14px 10px",
1727
+ flex: 1
1728
+ },
1729
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1730
+ style: {
1731
+ display: "flex",
1732
+ justifyContent: "space-between",
1733
+ alignItems: "flex-start",
1734
+ marginBottom: 6
1735
+ },
1736
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1737
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1738
+ style: {
1739
+ fontSize: 13,
1740
+ fontWeight: 700,
1741
+ color: "#111827"
1742
+ },
1743
+ children: "Total revenue trend"
1744
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1745
+ style: {
1746
+ fontSize: 9.5,
1747
+ color: "#9CA3AF",
1748
+ marginTop: 1
1749
+ },
1750
+ children: "Last 30 days \xB7 daily aggregation"
1751
+ })]
1752
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1753
+ style: {
1754
+ textAlign: "right"
1755
+ },
1756
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1757
+ style: {
1758
+ fontSize: 15,
1759
+ fontWeight: 800,
1760
+ color: "#111827"
1761
+ },
1762
+ children: d$(totalRaised)
1763
+ }), /*#__PURE__*/jsxRuntime.jsxs("span", {
1764
+ style: {
1765
+ marginLeft: 8,
1766
+ fontSize: 10.5,
1767
+ fontWeight: 600,
1768
+ color: "#16A34A"
1769
+ },
1770
+ children: [signed(growth === null || growth === void 0 ? void 0 : growth.totalRevenue), " vs ", dateLabel]
1771
+ })]
1772
+ })]
1773
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1774
+ style: {
1775
+ display: "flex",
1776
+ gap: 14,
1777
+ marginBottom: 6
1778
+ },
1779
+ children: [["Email", C.indigo], ["Organic", C.emerald], ["Paid Ads", C.cyan]].map(function (_ref10) {
1780
+ var _ref11 = _slicedToArray(_ref10, 2),
1781
+ name = _ref11[0],
1782
+ color = _ref11[1];
1783
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1784
+ style: {
1785
+ display: "flex",
1786
+ alignItems: "center",
1787
+ gap: 5
1788
+ },
1789
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1790
+ style: {
1791
+ width: 20,
1792
+ height: 2.5,
1793
+ background: color,
1794
+ borderRadius: 2
1795
+ }
1796
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
1797
+ style: {
1798
+ fontSize: 9.5,
1799
+ color: "#6B7280"
1800
+ },
1801
+ children: name
1802
+ })]
1803
+ }, name);
1804
+ })
1805
+ }), /*#__PURE__*/jsxRuntime.jsx(LineChart, {
1806
+ series: revSeries,
1807
+ categories: revCats,
1808
+ width: CW - 28,
1809
+ height: 300
1810
+ })]
1811
+ })]
1812
+ }), /*#__PURE__*/jsxRuntime.jsx(PageFooter, {
1813
+ generatedLabel: generatedLabel,
1814
+ page: 1
1815
+ })]
1816
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1817
+ "data-export-page": "2",
1818
+ style: {
1819
+ width: W,
1820
+ height: H,
1821
+ background: "#fff",
1822
+ display: "flex",
1823
+ flexDirection: "column",
1824
+ fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
1825
+ boxSizing: "border-box",
1826
+ overflow: "hidden"
1827
+ },
1828
+ children: [/*#__PURE__*/jsxRuntime.jsx(PageHeader, _objectSpread2(_objectSpread2({}, headerProps), {}, {
1829
+ page: 2
1830
+ })), /*#__PURE__*/jsxRuntime.jsxs("div", {
1831
+ style: {
1832
+ flex: 1,
1833
+ padding: "10px ".concat(MX, "px 8px"),
1834
+ display: "flex",
1835
+ flexDirection: "column",
1836
+ gap: 8,
1837
+ overflow: "hidden"
1838
+ },
1839
+ children: [/*#__PURE__*/jsxRuntime.jsx(Panel, {
1840
+ title: "Active campaigns",
1841
+ subtitle: "Live fundraisers ranked by velocity",
1842
+ action: "View all \u2192",
1843
+ children: /*#__PURE__*/jsxRuntime.jsx(MiniTable, {
1844
+ head: ["CAMPAIGN", "RAISED", "PROGRESS", "DONORS", "AVG GIFT", "STATUS"],
1845
+ rows: campaigns.length ? campaigns.map(function (c) {
1846
+ return [c.title || "Untitled", d$(c.collectedAmount || 0), "".concat(Math.round((c.collectedAmount || 0) / (c.usdTargetAmount || 1) * 100), "%"), "".concat(formatNumber(c.uniqueDonationsCount || 0)), d$(c.avgGift || 0), c.status || "Active"];
1847
+ }) : [["-", "$0", "0%", "0", "$0", "-"]]
1848
+ })
1849
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1850
+ style: {
1851
+ display: "flex",
1852
+ gap: 8,
1853
+ flexShrink: 0
1854
+ },
1855
+ children: [/*#__PURE__*/jsxRuntime.jsx(Panel, {
1856
+ title: "Donor mix",
1857
+ subtitle: "Acquisition vs retention",
1858
+ style: {
1859
+ flex: 1
1860
+ },
1861
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
1862
+ style: {
1863
+ display: "flex",
1864
+ alignItems: "center",
1865
+ gap: 14
1866
+ },
1867
+ children: [/*#__PURE__*/jsxRuntime.jsx(Donut, {
1868
+ segments: [{
1869
+ value: newDonors,
1870
+ color: C.indigo
1871
+ }, {
1872
+ value: returningDonors,
1873
+ color: C.emerald
1874
+ }],
1875
+ size: 88,
1876
+ centerVal: "".concat(formatNumber(totalMix)),
1877
+ centerLabel: "donors"
1878
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1879
+ style: {
1880
+ flex: 1
1881
+ },
1882
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1883
+ style: {
1884
+ display: "flex",
1885
+ alignItems: "center",
1886
+ gap: 6,
1887
+ marginBottom: 5
1888
+ },
1889
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1890
+ style: {
1891
+ width: 9,
1892
+ height: 9,
1893
+ borderRadius: "50%",
1894
+ background: C.indigo,
1895
+ flexShrink: 0
1896
+ }
1897
+ }), /*#__PURE__*/jsxRuntime.jsxs("span", {
1898
+ style: {
1899
+ fontSize: 10,
1900
+ color: "#374151"
1901
+ },
1902
+ children: ["New donors ", formatNumber(newDonors), " \xB7 ", newPct, "%"]
1903
+ })]
1904
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1905
+ style: {
1906
+ display: "flex",
1907
+ alignItems: "center",
1908
+ gap: 6,
1909
+ marginBottom: 9
1910
+ },
1911
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1912
+ style: {
1913
+ width: 9,
1914
+ height: 9,
1915
+ borderRadius: "50%",
1916
+ background: C.emerald,
1917
+ flexShrink: 0
1918
+ }
1919
+ }), /*#__PURE__*/jsxRuntime.jsxs("span", {
1920
+ style: {
1921
+ fontSize: 10,
1922
+ color: "#374151"
1923
+ },
1924
+ children: ["Returning ", formatNumber(returningDonors), " \xB7 ", retPct, "%"]
1925
+ })]
1926
+ }), /*#__PURE__*/jsxRuntime.jsx(Divider, {
1927
+ mb: 7
1928
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1929
+ style: {
1930
+ fontSize: 15,
1931
+ fontWeight: 800,
1932
+ color: "#111827"
1933
+ },
1934
+ children: d$(mixAvgGift)
1935
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1936
+ style: {
1937
+ fontSize: 8.5,
1938
+ color: "#9CA3AF"
1939
+ },
1940
+ children: "Avg gift"
1941
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1942
+ style: {
1943
+ fontSize: 9,
1944
+ color: "#16A34A",
1945
+ marginTop: 1
1946
+ },
1947
+ children: [signed(growth === null || growth === void 0 ? void 0 : growth.overallAVGDonations), " vs ", dateLabel]
1948
+ })]
1949
+ })]
1950
+ })
1951
+ }), /*#__PURE__*/jsxRuntime.jsx(Panel, {
1952
+ title: "Recurring vs one-time",
1953
+ subtitle: "Donation type \xB7 weekly",
1954
+ style: {
1955
+ flex: 1
1956
+ },
1957
+ children: function () {
1958
+ var tot = recurringTotal + oneTimeTotal || 1;
1959
+ var rPct = recurringTotal / tot * 100;
1960
+ var oPct = oneTimeTotal / tot * 100;
1961
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1962
+ style: {
1963
+ display: "flex",
1964
+ flexDirection: "column",
1965
+ gap: 10,
1966
+ marginTop: 4
1967
+ },
1968
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1969
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1970
+ style: {
1971
+ display: "flex",
1972
+ justifyContent: "space-between",
1973
+ marginBottom: 3
1974
+ },
1975
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1976
+ style: {
1977
+ fontSize: 10,
1978
+ color: "#374151"
1979
+ },
1980
+ children: "Recurring"
1981
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
1982
+ style: {
1983
+ fontSize: 10,
1984
+ fontWeight: 700,
1985
+ color: "#111827"
1986
+ },
1987
+ children: d$(recurringTotal)
1988
+ })]
1989
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1990
+ style: {
1991
+ height: 10,
1992
+ background: "#EEF2FF",
1993
+ borderRadius: 3
1994
+ },
1995
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
1996
+ style: {
1997
+ width: "".concat(rPct, "%"),
1998
+ height: "100%",
1999
+ background: C.indigo,
2000
+ borderRadius: 3
2001
+ }
2002
+ })
2003
+ })]
2004
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2005
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2006
+ style: {
2007
+ display: "flex",
2008
+ justifyContent: "space-between",
2009
+ marginBottom: 3
2010
+ },
2011
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
2012
+ style: {
2013
+ fontSize: 10,
2014
+ color: "#374151"
2015
+ },
2016
+ children: "One-time"
2017
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
2018
+ style: {
2019
+ fontSize: 10,
2020
+ fontWeight: 700,
2021
+ color: "#111827"
2022
+ },
2023
+ children: d$(oneTimeTotal)
2024
+ })]
2025
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2026
+ style: {
2027
+ height: 10,
2028
+ background: "#EEF2FF",
2029
+ borderRadius: 3
2030
+ },
2031
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
2032
+ style: {
2033
+ width: "".concat(oPct, "%"),
2034
+ height: "100%",
2035
+ background: "#C7D2FE",
2036
+ borderRadius: 3
2037
+ }
2038
+ })
2039
+ })]
2040
+ })]
2041
+ });
2042
+ }()
2043
+ })]
2044
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2045
+ style: {
2046
+ display: "flex",
2047
+ gap: 8,
2048
+ flexShrink: 0
2049
+ },
2050
+ children: [/*#__PURE__*/jsxRuntime.jsx(Panel, {
2051
+ title: "Donor geography",
2052
+ subtitle: "Top countries \xB7 ".concat(formatNumber(totalDonors), " total"),
2053
+ style: {
2054
+ flex: 1
2055
+ },
2056
+ children: (geoList.length ? geoList.slice(0, 6) : []).map(function (g, i) {
2057
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
2058
+ style: {
2059
+ display: "flex",
2060
+ justifyContent: "space-between",
2061
+ padding: "3.5px 0",
2062
+ borderBottom: i < 5 ? "1px solid #F3F4F6" : "none"
2063
+ },
2064
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
2065
+ style: {
2066
+ fontSize: 9.5,
2067
+ color: "#374151"
2068
+ },
2069
+ children: g.country || g.name || "-"
2070
+ }), /*#__PURE__*/jsxRuntime.jsxs("span", {
2071
+ style: {
2072
+ fontSize: 9.5,
2073
+ color: "#6B7280"
2074
+ },
2075
+ children: [formatNumber(g.totalDonors || g.donors || 0), " \xB7 ", formatNumber(g.percentage || 0), "%"]
2076
+ })]
2077
+ }, i);
2078
+ })
2079
+ }), /*#__PURE__*/jsxRuntime.jsxs(Panel, {
2080
+ title: "Refunds & chargebacks",
2081
+ subtitle: "Trust health \xB7 30-day window",
2082
+ style: {
2083
+ flex: 1
2084
+ },
2085
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2086
+ style: {
2087
+ display: "flex",
2088
+ gap: 18,
2089
+ marginBottom: 8
2090
+ },
2091
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2092
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2093
+ style: {
2094
+ fontSize: 8,
2095
+ fontWeight: 700,
2096
+ letterSpacing: "0.5px",
2097
+ color: "#6B7280",
2098
+ marginBottom: 2
2099
+ },
2100
+ children: "REFUNDS"
2101
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2102
+ style: {
2103
+ fontSize: 18,
2104
+ fontWeight: 800,
2105
+ color: "#111827"
2106
+ },
2107
+ children: pct(refundRate, 1)
2108
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2109
+ style: {
2110
+ fontSize: 9.5,
2111
+ color: "#16A34A",
2112
+ fontWeight: 600
2113
+ },
2114
+ children: signed(refundsRaw === null || refundsRaw === void 0 ? void 0 : refundsRaw.refundRateChange, "pp")
2115
+ })]
2116
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2117
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2118
+ style: {
2119
+ fontSize: 8,
2120
+ fontWeight: 700,
2121
+ letterSpacing: "0.5px",
2122
+ color: "#6B7280",
2123
+ marginBottom: 2
2124
+ },
2125
+ children: "CHARGEBACKS"
2126
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2127
+ style: {
2128
+ fontSize: 18,
2129
+ fontWeight: 800,
2130
+ color: "#111827"
2131
+ },
2132
+ children: pct(chargebackRate, 1)
2133
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2134
+ style: {
2135
+ fontSize: 9.5,
2136
+ color: "#9CA3AF"
2137
+ },
2138
+ children: "stable"
2139
+ })]
2140
+ })]
2141
+ }), /*#__PURE__*/jsxRuntime.jsx(Divider, {
2142
+ mb: 6
2143
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2144
+ style: {
2145
+ fontSize: 8.5,
2146
+ color: "#6B7280",
2147
+ lineHeight: 1.5
2148
+ },
2149
+ children: [d$((refundsRaw === null || refundsRaw === void 0 ? void 0 : refundsRaw.refundAmount) || 0), " refunded \xB7 ", d$((refundsRaw === null || refundsRaw === void 0 ? void 0 : refundsRaw.disputedAmount) || 0), " disputed \xB7 ", formatNumber((refundsRaw === null || refundsRaw === void 0 ? void 0 : refundsRaw.casesLost) || 0), " cases lost"]
2150
+ })]
2151
+ }), /*#__PURE__*/jsxRuntime.jsx(Panel, {
2152
+ title: "Traffic source",
2153
+ subtitle: "Revenue by channel \xB7 30 days",
2154
+ style: {
2155
+ flex: 1
2156
+ },
2157
+ children: /*#__PURE__*/jsxRuntime.jsx(MiniTable, {
2158
+ head: ["SOURCE", "REVENUE", "SHARE"],
2159
+ rows: [].concat(_toConsumableArray(trafficItems.map(function (t) {
2160
+ return [t.source || t.name || "-", d$(t.revenue || t.raised || 0), "".concat(formatNumber(t.share || t.percentage || 0), "%")];
2161
+ })), _toConsumableArray(trafficItems.length ? [["Total", d$(trafficTotal), ""]] : []))
2162
+ })
2163
+ }), /*#__PURE__*/jsxRuntime.jsxs(Panel, {
2164
+ title: "Order Bump",
2165
+ subtitle: "Revenue trend \xB7 last 30 days",
2166
+ style: {
2167
+ flex: 1
2168
+ },
2169
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2170
+ style: {
2171
+ fontSize: 17,
2172
+ fontWeight: 800,
2173
+ color: "#111827"
2174
+ },
2175
+ children: d$((ob === null || ob === void 0 ? void 0 : ob.totalRevenue) || 0)
2176
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2177
+ style: {
2178
+ fontSize: 10,
2179
+ color: "#16A34A",
2180
+ fontWeight: 600,
2181
+ marginBottom: 5
2182
+ },
2183
+ children: [signed(ob === null || ob === void 0 ? void 0 : ob.growthPercentage), " vs ", dateLabel]
2184
+ }), /*#__PURE__*/jsxRuntime.jsx(Sparkline, {
2185
+ data: obData.length ? obData : [0, 1],
2186
+ color: C.indigo,
2187
+ width: 110,
2188
+ height: 34
2189
+ }), /*#__PURE__*/jsxRuntime.jsx(Divider, {
2190
+ mt: 8,
2191
+ mb: 7
2192
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2193
+ style: {
2194
+ display: "flex",
2195
+ gap: 12
2196
+ },
2197
+ children: [["Avg/day", d$((ob === null || ob === void 0 ? void 0 : ob.averagePerDay) || 0)], ["Peak day", d$((ob === null || ob === void 0 || (_ob$peakDay = ob.peakDay) === null || _ob$peakDay === void 0 ? void 0 : _ob$peakDay.amount) || 0)], ["Orders", formatNumber((ob === null || ob === void 0 ? void 0 : ob.totalOrders) || 0)]].map(function (_ref12) {
2198
+ var _ref13 = _slicedToArray(_ref12, 2),
2199
+ l = _ref13[0],
2200
+ v = _ref13[1];
2201
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
2202
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2203
+ style: {
2204
+ fontSize: 8,
2205
+ color: "#9CA3AF"
2206
+ },
2207
+ children: l
2208
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2209
+ style: {
2210
+ fontSize: 11.5,
2211
+ fontWeight: 700,
2212
+ color: "#111827"
2213
+ },
2214
+ children: v
2215
+ })]
2216
+ }, l);
2217
+ })
2218
+ })]
2219
+ })]
2220
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2221
+ style: {
2222
+ display: "flex",
2223
+ gap: 8,
2224
+ flexShrink: 0
2225
+ },
2226
+ children: [/*#__PURE__*/jsxRuntime.jsx(Panel, {
2227
+ title: "Upsell",
2228
+ subtitle: "Acceptance & raised",
2229
+ style: {
2230
+ flex: 1
2231
+ },
2232
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
2233
+ style: {
2234
+ display: "flex",
2235
+ alignItems: "center",
2236
+ gap: 12
2237
+ },
2238
+ children: [/*#__PURE__*/jsxRuntime.jsx(Donut, {
2239
+ segments: [{
2240
+ value: (up === null || up === void 0 ? void 0 : up.acceptanceRate) || 0,
2241
+ color: C.indigo
2242
+ }, {
2243
+ value: Math.max(0, 100 - ((up === null || up === void 0 ? void 0 : up.acceptanceRate) || 0)),
2244
+ color: "#E5E7EB"
2245
+ }],
2246
+ size: 76,
2247
+ centerVal: "".concat(formatNumber((up === null || up === void 0 ? void 0 : up.acceptanceRate) || 0), "%"),
2248
+ centerLabel: "accepted"
2249
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2250
+ style: {
2251
+ flex: 1
2252
+ },
2253
+ children: [/*#__PURE__*/jsxRuntime.jsx(StatPair, {
2254
+ label: "Acceptance",
2255
+ val: pct((up === null || up === void 0 ? void 0 : up.acceptanceRate) || 0, 1),
2256
+ trend: signed(up === null || up === void 0 ? void 0 : up.acceptanceGrowth)
2257
+ }), /*#__PURE__*/jsxRuntime.jsx(StatPair, {
2258
+ label: "Raised",
2259
+ val: d$((up === null || up === void 0 ? void 0 : up.raised) || 0),
2260
+ trend: signed(up === null || up === void 0 ? void 0 : up.raisedGrowth)
2261
+ })]
2262
+ })]
2263
+ })
2264
+ }), /*#__PURE__*/jsxRuntime.jsx(Panel, {
2265
+ title: "Downsell",
2266
+ subtitle: "Acceptance & raised",
2267
+ style: {
2268
+ flex: 1
2269
+ },
2270
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
2271
+ style: {
2272
+ display: "flex",
2273
+ alignItems: "center",
2274
+ gap: 12
2275
+ },
2276
+ children: [/*#__PURE__*/jsxRuntime.jsx(Donut, {
2277
+ segments: [{
2278
+ value: (dn === null || dn === void 0 ? void 0 : dn.acceptanceRate) || 0,
2279
+ color: C.cyan
2280
+ }, {
2281
+ value: Math.max(0, 100 - ((dn === null || dn === void 0 ? void 0 : dn.acceptanceRate) || 0)),
2282
+ color: "#E5E7EB"
2283
+ }],
2284
+ size: 76,
2285
+ centerVal: "".concat(formatNumber((dn === null || dn === void 0 ? void 0 : dn.acceptanceRate) || 0), "%"),
2286
+ centerLabel: "accepted"
2287
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2288
+ style: {
2289
+ flex: 1
2290
+ },
2291
+ children: [/*#__PURE__*/jsxRuntime.jsx(StatPair, {
2292
+ label: "Acceptance",
2293
+ val: pct((dn === null || dn === void 0 ? void 0 : dn.acceptanceRate) || 0, 1),
2294
+ trend: signed(dn === null || dn === void 0 ? void 0 : dn.acceptanceGrowth)
2295
+ }), /*#__PURE__*/jsxRuntime.jsx(StatPair, {
2296
+ label: "Raised",
2297
+ val: d$((dn === null || dn === void 0 ? void 0 : dn.raised) || 0),
2298
+ trend: signed(dn === null || dn === void 0 ? void 0 : dn.raisedGrowth)
2299
+ })]
2300
+ })]
2301
+ })
2302
+ }), /*#__PURE__*/jsxRuntime.jsxs(Panel, {
2303
+ title: "Referrals",
2304
+ subtitle: "Revenue trend \xB7 last 30 days",
2305
+ style: {
2306
+ flex: 1
2307
+ },
2308
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2309
+ style: {
2310
+ fontSize: 17,
2311
+ fontWeight: 800,
2312
+ color: "#111827"
2313
+ },
2314
+ children: d$((refCard === null || refCard === void 0 ? void 0 : refCard.totalRevenue) || 0)
2315
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2316
+ style: {
2317
+ fontSize: 10,
2318
+ color: "#16A34A",
2319
+ fontWeight: 600,
2320
+ marginBottom: 5
2321
+ },
2322
+ children: [signed(refCard === null || refCard === void 0 ? void 0 : refCard.growthPercentage), " vs ", dateLabel]
2323
+ }), /*#__PURE__*/jsxRuntime.jsx(Sparkline, {
2324
+ data: refData.length ? refData : [0, 1],
2325
+ color: C.emerald,
2326
+ width: 110,
2327
+ height: 34
2328
+ }), /*#__PURE__*/jsxRuntime.jsx(Divider, {
2329
+ mt: 8,
2330
+ mb: 7
2331
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2332
+ style: {
2333
+ display: "flex",
2334
+ gap: 12
2335
+ },
2336
+ children: [["Referrers", formatNumber((refCard === null || refCard === void 0 ? void 0 : refCard.totalReferrers) || 0)], ["Avg gift", d$((refCard === null || refCard === void 0 ? void 0 : refCard.averageGift) || 0)], ["Conv. rate", pct((refCard === null || refCard === void 0 ? void 0 : refCard.conversionRate) || 0, 1)]].map(function (_ref14) {
2337
+ var _ref15 = _slicedToArray(_ref14, 2),
2338
+ l = _ref15[0],
2339
+ v = _ref15[1];
2340
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
2341
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2342
+ style: {
2343
+ fontSize: 8,
2344
+ color: "#9CA3AF"
2345
+ },
2346
+ children: l
2347
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2348
+ style: {
2349
+ fontSize: 11.5,
2350
+ fontWeight: 700,
2351
+ color: "#111827"
2352
+ },
2353
+ children: v
2354
+ })]
2355
+ }, l);
2356
+ })
2357
+ })]
2358
+ })]
2359
+ })]
2360
+ }), /*#__PURE__*/jsxRuntime.jsx(PageFooter, {
2361
+ generatedLabel: generatedLabel,
2362
+ page: 2
2363
+ })]
2364
+ })]
2365
+ });
2366
+ });
2367
+ ExportPdfLayout.displayName = "ExportPdfLayout";
2368
+
890
2369
  var OverallSection$2 = /*#__PURE__*/React.lazy(function () {
891
2370
  return Promise.resolve().then(function () { return OverallSection$1; });
892
2371
  });
@@ -919,139 +2398,96 @@ var NewOverview = function NewOverview(_ref) {
919
2398
  _useState4 = _slicedToArray(_useState3, 2),
920
2399
  activeSection = _useState4[0],
921
2400
  setActiveSection = _useState4[1];
922
- var exportCaptureRef = React.useRef(null);
2401
+ var _useState5 = React.useState(false),
2402
+ _useState6 = _slicedToArray(_useState5, 2),
2403
+ showExportLayout = _useState6[0],
2404
+ setShowExportLayout = _useState6[1];
2405
+ var exportLayoutRef = React.useRef(null);
923
2406
  React.useEffect(function () {
924
2407
  if (activeSectionProp) {
925
2408
  var capitalized = activeSectionProp.charAt(0).toUpperCase() + activeSectionProp.slice(1).toLowerCase();
926
2409
  setActiveSection(capitalized);
927
2410
  }
928
2411
  }, [activeSectionProp]);
2412
+
2413
+ // Step 1 – mount the off-screen export layout whenever the trigger fires
929
2414
  React.useEffect(function () {
930
- if (exportTrigger <= 0) return;
931
- var buildAndDownloadPdf = /*#__PURE__*/function () {
2415
+ if (exportTrigger > 0) setShowExportLayout(true);
2416
+ }, [exportTrigger]);
2417
+
2418
+ // Step 2 – once the layout is in the DOM, capture each page and build the PDF
2419
+ React.useEffect(function () {
2420
+ if (!showExportLayout) return;
2421
+ var doPdfExport = /*#__PURE__*/function () {
932
2422
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
933
- var captureNode, _yield$Promise$all, _yield$Promise$all2, jsPDF, html2canvasModule, html2canvas, dateLabel, generatedAt, generatedLabel, canvas, sectionImageWidth, sectionImageHeight, doc, pageWidth, pageHeight, marginX, contentTop, contentBottom, contentWidth, contentHeight, pxPerPt, pageSliceHeightPx, totalPages, addHeader, addFooter, i, startY, sliceHeight, pageCanvas, pageCtx, pageImage, renderHeight, safeDate, _t;
2423
+ var container, pageEls, _yield$Promise$all, _yield$Promise$all2, jsPDF, html2canvasModule, html2canvas, doc, pdfW, pdfH, i, el, cvs, safeDate, _t;
934
2424
  return _regenerator().w(function (_context) {
935
2425
  while (1) switch (_context.p = _context.n) {
936
2426
  case 0:
937
2427
  _context.p = 0;
938
- if (!(activeSection !== "Overall")) {
939
- _context.n = 1;
2428
+ _context.n = 1;
2429
+ return new Promise(function (r) {
2430
+ return requestAnimationFrame(function () {
2431
+ return requestAnimationFrame(r);
2432
+ });
2433
+ });
2434
+ case 1:
2435
+ _context.n = 2;
2436
+ return new Promise(function (r) {
2437
+ return setTimeout(r, 400);
2438
+ });
2439
+ case 2:
2440
+ container = exportLayoutRef.current;
2441
+ if (container) {
2442
+ _context.n = 3;
940
2443
  break;
941
2444
  }
942
2445
  return _context.a(2);
943
- case 1:
944
- captureNode = exportCaptureRef.current;
945
- if (captureNode) {
946
- _context.n = 2;
2446
+ case 3:
2447
+ pageEls = container.querySelectorAll("[data-export-page]");
2448
+ if (pageEls.length) {
2449
+ _context.n = 4;
947
2450
  break;
948
2451
  }
949
2452
  return _context.a(2);
950
- case 2:
951
- _context.n = 3;
2453
+ case 4:
2454
+ _context.n = 5;
952
2455
  return Promise.all([import('jspdf'), Promise.resolve().then(function () { return html2canvas_esm; })]);
953
- case 3:
2456
+ case 5:
954
2457
  _yield$Promise$all = _context.v;
955
2458
  _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
956
2459
  jsPDF = _yield$Promise$all2[0].jsPDF;
957
2460
  html2canvasModule = _yield$Promise$all2[1];
958
2461
  html2canvas = html2canvasModule["default"] || html2canvasModule;
959
- dateLabel = dateName || "Last Period";
960
- generatedAt = new Date();
961
- generatedLabel = "".concat(generatedAt.toLocaleDateString(), " ").concat(generatedAt.toLocaleTimeString(), " GMT");
962
- _context.n = 4;
963
- return new Promise(function (resolve) {
964
- return setTimeout(resolve, 900);
965
- });
966
- case 4:
967
- _context.n = 5;
968
- return html2canvas(captureNode, {
969
- scale: 2,
970
- useCORS: true,
971
- backgroundColor: "#ffffff",
972
- width: captureNode.scrollWidth,
973
- height: captureNode.scrollHeight,
974
- windowWidth: captureNode.scrollWidth,
975
- windowHeight: captureNode.scrollHeight,
976
- scrollX: 0,
977
- scrollY: -window.scrollY
978
- });
979
- case 5:
980
- canvas = _context.v;
981
- sectionImageWidth = canvas.width;
982
- sectionImageHeight = canvas.height;
983
2462
  doc = new jsPDF({
984
2463
  unit: "pt",
985
2464
  format: "a4"
986
2465
  });
987
- pageWidth = doc.internal.pageSize.getWidth();
988
- pageHeight = doc.internal.pageSize.getHeight();
989
- marginX = 40;
990
- contentTop = 112;
991
- contentBottom = 40;
992
- contentWidth = pageWidth - marginX * 2;
993
- contentHeight = pageHeight - contentTop - contentBottom;
994
- pxPerPt = sectionImageWidth / contentWidth;
995
- pageSliceHeightPx = Math.max(1, Math.floor(contentHeight * pxPerPt));
996
- totalPages = Math.max(1, Math.ceil(sectionImageHeight / pageSliceHeightPx));
997
- addHeader = function addHeader() {
998
- doc.setFont("helvetica", "bold");
999
- doc.setTextColor(17, 24, 39);
1000
- doc.setFontSize(17);
1001
- doc.text("Madinah", marginX, 34);
1002
- doc.setFontSize(9.5);
1003
- doc.setTextColor(75, 85, 99);
1004
- doc.text("PERFORMANCE REPORT", marginX, 50);
1005
- doc.setTextColor(17, 24, 39);
1006
- doc.setFontSize(12);
1007
- doc.text("Dashboard overview — Overall", marginX, 72);
1008
- doc.setFont("helvetica", "normal");
1009
- doc.setFontSize(9);
1010
- doc.setTextColor(107, 114, 128);
1011
- doc.text("".concat(dateLabel), marginX, 88);
1012
- doc.text("30-day window \xB7 Generated ".concat(generatedLabel), marginX, 100);
1013
- var activeFilters = (apiData === null || apiData === void 0 ? void 0 : apiData.activeFilters) || "";
1014
- if (activeFilters) {
1015
- doc.setFontSize(8);
1016
- doc.setTextColor(55, 65, 81);
1017
- doc.text("ACTIVE FILTERS ".concat(activeFilters), marginX, 110);
1018
- }
1019
- };
1020
- addFooter = function addFooter(pageNumber, totalPages) {
1021
- doc.setFont("helvetica", "normal");
1022
- doc.setTextColor(107, 114, 128);
1023
- doc.setFontSize(8);
1024
- doc.text("Confidential \xB7 Generated by Dashboard \xB7 ".concat(generatedLabel, " \xB7 Page ").concat(pageNumber, " of ").concat(totalPages, " \xB7 madinah.com"), marginX, pageHeight - 18);
1025
- };
2466
+ pdfW = doc.internal.pageSize.getWidth();
2467
+ pdfH = doc.internal.pageSize.getHeight();
1026
2468
  i = 0;
1027
2469
  case 6:
1028
- if (!(i < totalPages)) {
2470
+ if (!(i < pageEls.length)) {
1029
2471
  _context.n = 9;
1030
2472
  break;
1031
2473
  }
1032
- if (i > 0) doc.addPage();
1033
- addHeader();
1034
- startY = i * pageSliceHeightPx;
1035
- sliceHeight = Math.min(pageSliceHeightPx, sectionImageHeight - startY);
1036
- pageCanvas = document.createElement("canvas");
1037
- pageCanvas.width = sectionImageWidth;
1038
- pageCanvas.height = sliceHeight;
1039
- pageCtx = pageCanvas.getContext("2d");
1040
- if (pageCtx) {
1041
- _context.n = 7;
1042
- break;
1043
- }
1044
- return _context.a(3, 8);
2474
+ el = pageEls[i];
2475
+ _context.n = 7;
2476
+ return html2canvas(el, {
2477
+ scale: 2,
2478
+ useCORS: true,
2479
+ backgroundColor: "#ffffff",
2480
+ width: el.offsetWidth,
2481
+ height: el.offsetHeight,
2482
+ windowWidth: el.offsetWidth,
2483
+ windowHeight: el.offsetHeight
2484
+ });
1045
2485
  case 7:
1046
- pageCtx.fillStyle = "#ffffff";
1047
- pageCtx.fillRect(0, 0, pageCanvas.width, pageCanvas.height);
1048
- pageCtx.drawImage(canvas, 0, startY, sectionImageWidth, sliceHeight, 0, 0, sectionImageWidth, sliceHeight);
1049
- pageImage = pageCanvas.toDataURL("image/png");
1050
- renderHeight = sliceHeight / pxPerPt;
1051
- doc.addImage(pageImage, "PNG", marginX, contentTop, contentWidth, renderHeight, undefined, "FAST");
1052
- addFooter(i + 1, totalPages);
2486
+ cvs = _context.v;
2487
+ if (i > 0) doc.addPage();
2488
+ doc.addImage(cvs.toDataURL("image/png"), "PNG", 0, 0, pdfW, pdfH, undefined, "FAST");
1053
2489
  case 8:
1054
- i += 1;
2490
+ i++;
1055
2491
  _context.n = 6;
1056
2492
  break;
1057
2493
  case 9:
@@ -1062,19 +2498,22 @@ var NewOverview = function NewOverview(_ref) {
1062
2498
  case 10:
1063
2499
  _context.p = 10;
1064
2500
  _t = _context.v;
1065
- // Keep console message for host app debugging when export dependency is missing.
1066
2501
  console.error("Failed to export overall dashboard PDF:", _t);
1067
2502
  case 11:
2503
+ _context.p = 11;
2504
+ setShowExportLayout(false);
2505
+ return _context.f(11);
2506
+ case 12:
1068
2507
  return _context.a(2);
1069
2508
  }
1070
- }, _callee, null, [[0, 10]]);
2509
+ }, _callee, null, [[0, 10, 11, 12]]);
1071
2510
  }));
1072
- return function buildAndDownloadPdf() {
2511
+ return function doPdfExport() {
1073
2512
  return _ref2.apply(this, arguments);
1074
2513
  };
1075
2514
  }();
1076
- buildAndDownloadPdf();
1077
- }, [exportTrigger, activeSection, apiData, dateName]);
2515
+ doPdfExport();
2516
+ }, [showExportLayout]);
1078
2517
  var currentData = metric === "Revenue" ? revenueData : donationsData;
1079
2518
  var oneTimeData = (apiData === null || apiData === void 0 ? void 0 : apiData.oneTimeDonations) || [];
1080
2519
  var oneTimeValues = oneTimeData.length > 0 ? oneTimeData.map(function (item) {
@@ -1234,15 +2673,14 @@ var NewOverview = function NewOverview(_ref) {
1234
2673
  data: [8, 9, 11, 10, 10, 12, 9, 11, 10],
1235
2674
  categories: categories
1236
2675
  }];
1237
- return /*#__PURE__*/jsxRuntime.jsx(material.Box, {
1238
- ref: exportCaptureRef,
2676
+ return /*#__PURE__*/jsxRuntime.jsxs(material.Box, {
1239
2677
  sx: {
1240
2678
  minHeight: "100vh",
1241
2679
  display: "flex",
1242
2680
  flexDirection: "column",
1243
2681
  alignItems: "stretch"
1244
2682
  },
1245
- children: /*#__PURE__*/jsxRuntime.jsxs(React.Suspense, {
2683
+ children: [/*#__PURE__*/jsxRuntime.jsxs(React.Suspense, {
1246
2684
  fallback: /*#__PURE__*/jsxRuntime.jsx(material.Box, {
1247
2685
  sx: {
1248
2686
  display: "flex",
@@ -1272,7 +2710,22 @@ var NewOverview = function NewOverview(_ref) {
1272
2710
  sx: {},
1273
2711
  children: /*#__PURE__*/jsxRuntime.jsx(EmailSection$2, {})
1274
2712
  })]
1275
- })
2713
+ }), showExportLayout && /*#__PURE__*/jsxRuntime.jsx("div", {
2714
+ "aria-hidden": "true",
2715
+ style: {
2716
+ position: "fixed",
2717
+ top: 0,
2718
+ left: "-9999px",
2719
+ zIndex: -1,
2720
+ pointerEvents: "none",
2721
+ opacity: 1
2722
+ },
2723
+ children: /*#__PURE__*/jsxRuntime.jsx(ExportPdfLayout, {
2724
+ ref: exportLayoutRef,
2725
+ apiData: apiData,
2726
+ dateName: dateName
2727
+ })
2728
+ })]
1276
2729
  });
1277
2730
  };
1278
2731
 
@@ -3313,19 +4766,6 @@ var DonorMixCard = function DonorMixCard(_ref) {
3313
4766
  });
3314
4767
  };
3315
4768
 
3316
- function formatNumber(num) {
3317
- if (num >= 1000000000) {
3318
- return (num / 1000000000).toFixed(1).replace(/\.0$/, "") + "B";
3319
- }
3320
- if (num >= 1000000) {
3321
- return (num / 1000000).toFixed(1).replace(/\.0$/, "") + "M";
3322
- }
3323
- if (num >= 1000) {
3324
- return (num / 1000).toFixed(1).replace(/\.0$/, "") + "K";
3325
- }
3326
- return (num !== null && num !== void 0 ? num : 0).toString();
3327
- }
3328
-
3329
4769
  var TrafficSourceCard = function TrafficSourceCard(_ref) {
3330
4770
  var _ref$title = _ref.title,
3331
4771
  title = _ref$title === void 0 ? "Traffic source" : _ref$title,