@roax/ui 0.2.0 → 0.3.0

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.mjs CHANGED
@@ -2,19 +2,7 @@
2
2
  import { CLoadingButton } from "@coreui/react-pro";
3
3
  import CIcon from "@coreui/icons-react";
4
4
  import "./SolidButton.scss";
5
- function SolidButton({
6
- title = "Button",
7
- onClick,
8
- color = "custom-primary",
9
- textColor = "custom-white",
10
- className = "",
11
- loading = false,
12
- icon,
13
- svgComponent: SvgComponent,
14
- type = "submit",
15
- badge,
16
- disabled
17
- }) {
5
+ function SolidButton({ title = "Button", onClick, color = "custom-primary", textColor = "custom-white", className = "", loading = false, icon, svgComponent: SvgComponent, type = "submit", badge, disabled }) {
18
6
  return /* @__PURE__ */ React.createElement(
19
7
  CLoadingButton,
20
8
  {
@@ -24,12 +12,7 @@ function SolidButton({
24
12
  loading,
25
13
  disabledOnLoading: true,
26
14
  disabled,
27
- style: {
28
- minHeight: "44px",
29
- minWidth: "fit-content",
30
- fontSize: "0.95rem",
31
- letterSpacing: "0.3px"
32
- }
15
+ style: { minHeight: "44px", minWidth: "fit-content", fontSize: "0.95rem", letterSpacing: "0.3px" }
33
16
  },
34
17
  icon && /* @__PURE__ */ React.createElement(CIcon, { icon, className: "btn-icon" }),
35
18
  SvgComponent && !icon && /* @__PURE__ */ React.createElement(SvgComponent, null),
@@ -42,16 +25,7 @@ function SolidButton({
42
25
  import { CLoadingButton as CLoadingButton2 } from "@coreui/react-pro";
43
26
  import CIcon2 from "@coreui/icons-react";
44
27
  import "./OutlineButton.scss";
45
- function OutlineButton({
46
- title = "Button",
47
- onClick,
48
- color = "custom-primary",
49
- className = "",
50
- loading = false,
51
- icon,
52
- type = "submit",
53
- disabled
54
- }) {
28
+ function OutlineButton({ title = "Button", onClick, color = "custom-primary", className = "", loading = false, icon, type = "submit", disabled }) {
55
29
  return /* @__PURE__ */ React.createElement(
56
30
  CLoadingButton2,
57
31
  {
@@ -62,10 +36,7 @@ function OutlineButton({
62
36
  disabledOnLoading: true,
63
37
  disabled,
64
38
  variant: "outline",
65
- style: {
66
- maxHeight: "40px",
67
- minWidth: "fit-content"
68
- }
39
+ style: { maxHeight: "40px", minWidth: "fit-content" }
69
40
  },
70
41
  icon && /* @__PURE__ */ React.createElement(CIcon2, { icon }),
71
42
  /* @__PURE__ */ React.createElement("span", null, title)
@@ -75,17 +46,7 @@ function OutlineButton({
75
46
  // src/components/buttons/TextButton.jsx
76
47
  import { CLoadingButton as CLoadingButton3 } from "@coreui/react-pro";
77
48
  import CIcon3 from "@coreui/icons-react";
78
- function TextButton({
79
- disabled,
80
- title,
81
- onClick,
82
- color = "dark",
83
- className = "",
84
- loading = false,
85
- icon,
86
- children
87
- }) {
88
- const buttonClasses = `rounded-3 px-2 d-flex justify-content-center gap-2 fw-medium ${className}`;
49
+ function TextButton({ disabled, title, onClick, color = "dark", className = "", loading = false, icon, children }) {
89
50
  return /* @__PURE__ */ React.createElement("span", { className: "d-inline-block", tabIndex: 0 }, /* @__PURE__ */ React.createElement(
90
51
  CLoadingButton3,
91
52
  {
@@ -94,7 +55,7 @@ function TextButton({
94
55
  variant: "ghost",
95
56
  type: "button",
96
57
  color,
97
- className: buttonClasses,
58
+ className: `rounded-3 px-2 d-flex justify-content-center gap-2 fw-medium ${className}`,
98
59
  loading
99
60
  },
100
61
  icon && /* @__PURE__ */ React.createElement(CIcon3, { size: "xl", icon }),
@@ -109,37 +70,12 @@ import CIcon4 from "@coreui/icons-react";
109
70
  // src/components/custom-tooltip/CustomTooltip.jsx
110
71
  import Tippy from "@tippyjs/react";
111
72
  import "tippy.js/dist/tippy.css";
112
- function CustomTooltip({
113
- content,
114
- placement = "bottom",
115
- delay = 0,
116
- className = "",
117
- children
118
- }) {
119
- return /* @__PURE__ */ React.createElement(
120
- Tippy,
121
- {
122
- content,
123
- placement,
124
- className,
125
- delay
126
- },
127
- children
128
- );
73
+ function CustomTooltip({ content, placement = "bottom", delay = 0, className = "", children }) {
74
+ return /* @__PURE__ */ React.createElement(Tippy, { content, placement, className, delay }, children);
129
75
  }
130
76
 
131
77
  // src/components/buttons/IconButton.jsx
132
- function IconButton({
133
- title,
134
- onClick,
135
- color = "dark",
136
- className = "",
137
- loading = false,
138
- icon,
139
- tooltip = "",
140
- disabled
141
- }) {
142
- const buttonClasses = `d-flex justify-content-center align-items-center gap-1 m-0 p-1 ${className}`;
78
+ function IconButton({ title, onClick, color = "dark", className = "", loading = false, icon, tooltip = "", disabled }) {
143
79
  return /* @__PURE__ */ React.createElement(CustomTooltip, { content: tooltip, placement: "bottom" }, /* @__PURE__ */ React.createElement(
144
80
  CLoadingButton4,
145
81
  {
@@ -147,7 +83,7 @@ function IconButton({
147
83
  variant: "ghost",
148
84
  type: "button",
149
85
  color,
150
- className: buttonClasses,
86
+ className: `d-flex justify-content-center align-items-center gap-1 m-0 p-1 ${className}`,
151
87
  loading,
152
88
  disabled
153
89
  },
@@ -159,61 +95,25 @@ function IconButton({
159
95
  // src/components/modal/Modal.jsx
160
96
  import CIcon5 from "@coreui/icons-react";
161
97
  import { CModal, CModalBody, CModalHeader, CModalTitle } from "@coreui/react-pro";
162
-
163
- // ../../node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js
164
- var cilArrowBottom = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='367.997 338.75 271.999 434.747 271.999 17.503 239.999 17.503 239.999 434.745 144.003 338.75 121.376 361.377 256 496 390.624 361.377 367.997 338.75' class='ci-primary'/>"];
165
-
166
- // ../../node_modules/@coreui/icons/dist/esm/free/cil-arrow-left.js
167
- var cilArrowLeft = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='497.333 239.999 80.092 239.999 176.087 144.004 153.46 121.377 18.837 256 153.46 390.623 176.087 367.996 80.09 271.999 497.333 271.999 497.333 239.999' class='ci-primary'/>"];
168
-
169
- // ../../node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js
170
- var cilArrowTop = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='390.624 150.625 256 16 121.376 150.625 144.004 173.252 240.001 77.254 240.001 495.236 272.001 495.236 272.001 77.257 367.996 173.252 390.624 150.625' class='ci-primary'/>"];
171
-
172
- // ../../node_modules/@coreui/icons/dist/esm/free/cil-info.js
173
- var cilInfo = ["512 512", "<rect width='34.924' height='34.924' x='256' y='95.998' fill='var(--ci-primary-color, currentColor)' class='ci-primary'/><path fill='var(--ci-primary-color, currentColor)' d='M16,496H496V16H16ZM48,48H464V464H48Z' class='ci-primary'/><path fill='var(--ci-primary-color, currentColor)' d='M285.313,359.032a18.123,18.123,0,0,1-15.6,8.966,18.061,18.061,0,0,1-17.327-23.157l35.67-121.277A49.577,49.577,0,0,0,194.7,190.572l-11.718,28.234,29.557,12.266,11.718-28.235a17.577,17.577,0,0,1,33.1,11.7l-35.67,121.277A50.061,50.061,0,0,0,269.709,400a50.227,50.227,0,0,0,43.25-24.853l15.1-25.913-27.646-16.115Z' class='ci-primary'/>"];
174
-
175
- // ../../node_modules/@coreui/icons/dist/esm/free/cil-x.js
176
- var cilX = ["512 512", "<polygon fill='var(--ci-primary-color, currentColor)' points='427.314 107.313 404.686 84.687 256 233.373 107.314 84.687 84.686 107.313 233.373 256 84.686 404.687 107.314 427.313 256 278.627 404.686 427.313 427.314 404.687 278.627 256 427.314 107.313' class='ci-primary'/>"];
177
-
178
- // src/components/modal/Modal.jsx
179
- function Modal({
180
- title,
181
- titleIcon,
182
- visible,
183
- setVisible,
184
- alignment = "center",
185
- size,
186
- children
187
- }) {
188
- return /* @__PURE__ */ React.createElement(
189
- CModal,
98
+ import { cilX } from "@coreui/icons";
99
+ function Modal({ title, titleIcon, visible, setVisible, alignment = "center", size, children }) {
100
+ return /* @__PURE__ */ React.createElement(CModal, { alignment, visible, onClose: () => setVisible(false), size, focus: true, keyboard: true, "aria-labelledby": "roax-modal-title" }, /* @__PURE__ */ React.createElement(CModalHeader, { className: "position-relative" }, /* @__PURE__ */ React.createElement(CModalTitle, { id: "roax-modal-title", className: "d-flex align-items-center gap-2" }, titleIcon && /* @__PURE__ */ React.createElement(CIcon5, { icon: titleIcon, size: "lg", className: "text-muted" }), title), /* @__PURE__ */ React.createElement(
101
+ "button",
190
102
  {
191
- alignment,
192
- visible,
193
- onClose: () => setVisible(false),
194
- size,
195
- focus: true,
196
- keyboard: true,
197
- "aria-labelledby": "roax-modal-title"
103
+ onClick: () => setVisible(false),
104
+ type: "button",
105
+ className: "position-absolute end-0 top-0 mt-3 me-3 p-0 bg-transparent border-0",
106
+ style: { fontSize: "1.25rem", color: "var(--cui-body-color)", zIndex: 10 },
107
+ "aria-label": "Cerrar"
198
108
  },
199
- /* @__PURE__ */ React.createElement(CModalHeader, { className: "position-relative" }, /* @__PURE__ */ React.createElement(CModalTitle, { id: "roax-modal-title", className: "d-flex align-items-center gap-2" }, titleIcon && /* @__PURE__ */ React.createElement(CIcon5, { icon: titleIcon, size: "lg", className: "text-muted" }), title), /* @__PURE__ */ React.createElement(
200
- "button",
201
- {
202
- onClick: () => setVisible(false),
203
- type: "button",
204
- className: "position-absolute end-0 top-0 mt-3 me-3 p-0 bg-transparent border-0",
205
- style: { fontSize: "1.25rem", color: "var(--cui-body-color)", zIndex: 10 },
206
- "aria-label": "Cerrar"
207
- },
208
- /* @__PURE__ */ React.createElement(CIcon5, { icon: cilX, size: "lg" })
209
- )),
210
- /* @__PURE__ */ React.createElement(CModalBody, null, children)
211
- );
109
+ /* @__PURE__ */ React.createElement(CIcon5, { icon: cilX, size: "lg" })
110
+ )), /* @__PURE__ */ React.createElement(CModalBody, null, children));
212
111
  }
213
112
 
214
113
  // src/components/card/MetricCard.jsx
215
114
  import { CCard, CCardBody } from "@coreui/react-pro";
216
115
  import CIcon6 from "@coreui/icons-react";
116
+ import { cilArrowTop, cilArrowBottom, cilInfo } from "@coreui/icons";
217
117
 
218
118
  // src/components/card/card-utils.js
219
119
  var formatValue = (val, unit = "", title = "") => {
@@ -240,8 +140,8 @@ function formatDateRange(previousDateRange) {
240
140
  if (!previousDateRange) return { formattedRange: "" };
241
141
  const parts = previousDateRange.split(" - ");
242
142
  const parseDate = (str) => {
243
- const [year, month, day] = str.split("-").map(Number);
244
- return new Date(year, month - 1, day);
143
+ const [y, m, d] = str.split("-").map(Number);
144
+ return new Date(y, m - 1, d);
245
145
  };
246
146
  const format = (date) => {
247
147
  const day = String(date.getDate()).padStart(2, "0");
@@ -251,13 +151,33 @@ function formatDateRange(previousDateRange) {
251
151
  };
252
152
  const since = parseDate(parts[0]);
253
153
  const until = parts[1] ? parseDate(parts[1]) : null;
254
- const formattedRange = until ? `${format(since)} - ${format(until)}` : format(since);
255
- return { formattedRange };
154
+ return { formattedRange: until ? `${format(since)} - ${format(until)}` : format(since) };
256
155
  }
257
156
 
258
157
  // src/components/card/MetricCard.jsx
259
158
  import "./MetricCard.scss";
260
- function MetricCard({
159
+ function MetricCard({ title, current, previous, change, isPositive, unit = "", previousDateRange = "", tooltipText = "", backgroundColor }) {
160
+ const isColored = !!backgroundColor;
161
+ return /* @__PURE__ */ React.createElement(
162
+ CCard,
163
+ {
164
+ className: `metric-card w-100 h-100 d-flex flex-column border-0${isColored ? " metric-card--colored" : ""}`,
165
+ style: isColored ? { background: backgroundColor } : void 0
166
+ },
167
+ /* @__PURE__ */ React.createElement(CCardBody, { className: "d-flex flex-column justify-content-between h-100 p-4 position-relative" }, tooltipText && /* @__PURE__ */ React.createElement("div", { className: "position-absolute top-0 end-0 m-2" }, /* @__PURE__ */ React.createElement(CustomTooltip, { content: tooltipText, placement: "top" }, /* @__PURE__ */ React.createElement(CIcon6, { icon: cilInfo, style: { cursor: "pointer", opacity: 0.5, width: 16, height: 16 } }))), /* @__PURE__ */ React.createElement("p", { className: "metric-card__title m-0" }, title), /* @__PURE__ */ React.createElement("div", { className: "d-flex align-items-center gap-2 mt-1" }, /* @__PURE__ */ React.createElement("span", { className: "metric-card__value" }, formatValue(current, unit, title)), typeof change === "number" && isFinite(change) && current > 0 && /* @__PURE__ */ React.createElement("div", { style: getBadgeStyles(isPositive) }, /* @__PURE__ */ React.createElement(CIcon6, { icon: isPositive ? cilArrowTop : cilArrowBottom, size: "sm" }), Math.abs(change), "%")), /* @__PURE__ */ React.createElement("hr", { className: "metric-card__divider" }), (() => {
168
+ const { formattedRange } = formatDateRange(previousDateRange);
169
+ return /* @__PURE__ */ React.createElement("div", { className: "d-flex justify-content-between align-items-center metric-card__footer" }, /* @__PURE__ */ React.createElement("strong", null, formatValue(previous, unit, title)), /* @__PURE__ */ React.createElement("span", null, formattedRange));
170
+ })())
171
+ );
172
+ }
173
+
174
+ // src/components/card/GeneralCard.jsx
175
+ import { CCard as CCard2, CCardBody as CCardBody2 } from "@coreui/react-pro";
176
+ import CIcon7 from "@coreui/icons-react";
177
+ import { cilArrowTop as cilArrowTop2, cilArrowBottom as cilArrowBottom2 } from "@coreui/icons";
178
+ import { Info } from "lucide-react";
179
+ import "./general-card.scss";
180
+ function GeneralCard({
261
181
  title,
262
182
  current,
263
183
  previous,
@@ -269,195 +189,513 @@ function MetricCard({
269
189
  backgroundColor
270
190
  }) {
271
191
  const isColored = !!backgroundColor;
272
- const cardClass = `metric-card w-100 h-100 d-flex flex-column border-0${isColored ? " metric-card--colored" : ""}`;
192
+ const cardClass = `general-card w-100 h-100 d-flex flex-column border-0${isColored ? " general-card--colored" : ""}`;
273
193
  return /* @__PURE__ */ React.createElement(
274
- CCard,
194
+ CCard2,
275
195
  {
276
196
  className: cardClass,
277
197
  style: isColored ? { background: backgroundColor } : void 0
278
198
  },
279
- /* @__PURE__ */ React.createElement(CCardBody, { className: "d-flex flex-column justify-content-between h-100 p-4 position-relative" }, tooltipText && /* @__PURE__ */ React.createElement("div", { className: "position-absolute top-0 end-0 m-2" }, /* @__PURE__ */ React.createElement(CustomTooltip, { content: tooltipText, placement: "top" }, /* @__PURE__ */ React.createElement(
280
- CIcon6,
199
+ /* @__PURE__ */ React.createElement(CCardBody2, { className: "d-flex flex-column justify-content-between h-100 p-4 position-relative" }, tooltipText && /* @__PURE__ */ React.createElement("div", { className: "position-absolute top-0 end-0 m-2" }, /* @__PURE__ */ React.createElement(CustomTooltip, { content: tooltipText, placement: "top" }, /* @__PURE__ */ React.createElement(
200
+ Info,
281
201
  {
282
- icon: cilInfo,
283
- style: { cursor: "pointer", opacity: 0.5, width: 16, height: 16 }
202
+ size: 16,
203
+ strokeWidth: 2,
204
+ style: { cursor: "pointer", opacity: 0.5 }
284
205
  }
285
- ))), /* @__PURE__ */ React.createElement("p", { className: "metric-card__title m-0" }, title), /* @__PURE__ */ React.createElement("div", { className: "d-flex align-items-center gap-2 mt-1" }, /* @__PURE__ */ React.createElement("span", { className: "metric-card__value" }, formatValue(current, unit, title)), typeof change === "number" && isFinite(change) && current > 0 && /* @__PURE__ */ React.createElement("div", { style: getBadgeStyles(isPositive) }, /* @__PURE__ */ React.createElement(CIcon6, { icon: isPositive ? cilArrowTop : cilArrowBottom, size: "sm" }), Math.abs(change), "%")), /* @__PURE__ */ React.createElement("hr", { className: "metric-card__divider" }), (() => {
206
+ ))), /* @__PURE__ */ React.createElement("p", { className: "general-card__title m-0" }, title), /* @__PURE__ */ React.createElement("div", { className: "d-flex align-items-center gap-2 mt-1" }, /* @__PURE__ */ React.createElement("span", { className: "general-card__value" }, formatValue(current, unit, title)), typeof change === "number" && isFinite(change) && current > 0 && /* @__PURE__ */ React.createElement("div", { style: getBadgeStyles(isPositive) }, /* @__PURE__ */ React.createElement(CIcon7, { icon: isPositive ? cilArrowTop2 : cilArrowBottom2, size: "sm" }), Math.abs(change), "%")), /* @__PURE__ */ React.createElement("hr", { className: "general-card__divider" }), (() => {
286
207
  const { formattedRange } = formatDateRange(previousDateRange);
287
- return /* @__PURE__ */ React.createElement("div", { className: "d-flex justify-content-between align-items-center metric-card__footer" }, /* @__PURE__ */ React.createElement("strong", null, formatValue(previous, unit, title)), /* @__PURE__ */ React.createElement("span", null, formattedRange));
208
+ return /* @__PURE__ */ React.createElement("div", { className: "d-flex justify-content-between align-items-center general-card__footer" }, /* @__PURE__ */ React.createElement("strong", null, formatValue(previous, unit, title)), /* @__PURE__ */ React.createElement("span", null, formattedRange));
288
209
  })())
289
210
  );
290
211
  }
291
212
 
292
- // src/components/pagination/PaginatedTable.jsx
213
+ // src/components/charts/FunnelChart.jsx
293
214
  import {
294
- CTable,
295
- CTableHead,
296
- CTableBody,
297
- CTableRow,
298
- CTableHeaderCell,
299
- CSpinner
300
- } from "@coreui/react-pro";
301
- function PaginatedTable({
215
+ ResponsiveContainer,
216
+ BarChart,
217
+ Bar,
218
+ XAxis,
219
+ YAxis,
220
+ Tooltip,
221
+ Cell,
222
+ LabelList
223
+ } from "recharts";
224
+ import { CCard as CCard3, CCardBody as CCardBody3, CRow, CCol } from "@coreui/react-pro";
225
+ function FunnelChart({ data = [] }) {
226
+ return /* @__PURE__ */ React.createElement(CCard3, { className: "mt-4 rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(CCardBody3, null, /* @__PURE__ */ React.createElement(ResponsiveContainer, { width: "100%", height: data.length * 45 + 50 }, /* @__PURE__ */ React.createElement(
227
+ BarChart,
228
+ {
229
+ data,
230
+ layout: "vertical",
231
+ margin: { top: 10, right: 60, left: 20, bottom: 0 },
232
+ barCategoryGap: 15
233
+ },
234
+ /* @__PURE__ */ React.createElement("defs", null, /* @__PURE__ */ React.createElement("linearGradient", { id: "funnelGradient", x1: "0", y1: "0", x2: "1", y2: "0" }, /* @__PURE__ */ React.createElement("stop", { offset: "0%", stopColor: "#FF8AAE" }), /* @__PURE__ */ React.createElement("stop", { offset: "100%", stopColor: "#FF1F3D" }))),
235
+ /* @__PURE__ */ React.createElement(XAxis, { type: "number", hide: true, domain: [0, "dataMax"] }),
236
+ /* @__PURE__ */ React.createElement(
237
+ YAxis,
238
+ {
239
+ dataKey: "title",
240
+ type: "category",
241
+ width: 130,
242
+ axisLine: false,
243
+ tickLine: false,
244
+ style: { fontWeight: 600, fill: "#333", fontSize: 13 }
245
+ }
246
+ ),
247
+ /* @__PURE__ */ React.createElement(
248
+ Tooltip,
249
+ {
250
+ content: ({ active, payload }) => {
251
+ if (active && payload && payload.length > 0) {
252
+ const { value, payload: item } = payload[0];
253
+ return /* @__PURE__ */ React.createElement("div", { className: "bg-white shadow-sm p-2 rounded" }, /* @__PURE__ */ React.createElement("strong", null, item.title), ":", " ", /* @__PURE__ */ React.createElement("span", null, formatValue(value, item.unit, item.title)));
254
+ }
255
+ return null;
256
+ }
257
+ }
258
+ ),
259
+ /* @__PURE__ */ React.createElement(Bar, { dataKey: "value", fill: "url(#funnelGradient)", radius: [0, 10, 10, 0] }, /* @__PURE__ */ React.createElement(
260
+ LabelList,
261
+ {
262
+ dataKey: "value",
263
+ position: "right",
264
+ formatter: (val) => formatValue(val),
265
+ style: { fill: "#333", fontWeight: 500, fontSize: 12 }
266
+ }
267
+ ), data.map((entry, index) => /* @__PURE__ */ React.createElement(
268
+ Cell,
269
+ {
270
+ key: `cell-${entry.title || index}`,
271
+ fill: entry.color || "url(#funnelGradient)"
272
+ }
273
+ )))
274
+ )), /* @__PURE__ */ React.createElement(CRow, { className: "pt-4 g-3" }, data.slice(0, 3).map((item, index) => /* @__PURE__ */ React.createElement(CCol, { xs: 12, md: 4, key: `card-top-${index}` }, /* @__PURE__ */ React.createElement(
275
+ GeneralCard,
276
+ {
277
+ title: item.title,
278
+ current: item.value,
279
+ previous: item.previous,
280
+ change: item.percentageChange,
281
+ isPositive: item.isPositive,
282
+ unit: item.unit,
283
+ previousDateRange: item.previousDateRange,
284
+ tooltipText: item.title
285
+ }
286
+ )))), data.length > 3 && /* @__PURE__ */ React.createElement(CRow, { className: "pt-3 g-3" }, data.slice(3).map((item, index) => /* @__PURE__ */ React.createElement(CCol, { xs: 12, md: 5, lg: 4, key: `card-bottom-${index}` }, /* @__PURE__ */ React.createElement(
287
+ GeneralCard,
288
+ {
289
+ title: item.title,
290
+ current: item.value,
291
+ previous: item.previous,
292
+ change: item.percentageChange,
293
+ isPositive: item.isPositive,
294
+ unit: item.unit,
295
+ previousDateRange: item.previousDateRange,
296
+ tooltipText: item.title
297
+ }
298
+ ))))));
299
+ }
300
+
301
+ // src/components/charts/TimeSeriesComparisonChart.jsx
302
+ import {
303
+ ResponsiveContainer as ResponsiveContainer2,
304
+ LineChart,
305
+ Line,
306
+ XAxis as XAxis2,
307
+ YAxis as YAxis2,
308
+ Tooltip as Tooltip2,
309
+ Legend,
310
+ CartesianGrid
311
+ } from "recharts";
312
+ import { CCard as CCard4, CCardBody as CCardBody4, CRow as CRow2, CCol as CCol2 } from "@coreui/react-pro";
313
+ function TimeSeriesComparisonChart({
302
314
  data = [],
303
- itemsPerPage = 10,
304
- currentPage = 1,
305
- setCurrentPage = () => {
306
- },
307
- columns = [],
308
- renderRow = () => null,
309
- loading = false,
310
- emptyMessage = "No hay datos disponibles."
315
+ lines = [],
316
+ colors = {},
317
+ cards = [],
318
+ currency = "",
319
+ yAxisLabel = "",
320
+ displayNames = {}
311
321
  }) {
312
- const totalPages = Math.ceil(data.length / itemsPerPage);
313
- const paginatedData = data.slice(
314
- (currentPage - 1) * itemsPerPage,
315
- currentPage * itemsPerPage
316
- );
317
- if (loading) {
318
- return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5" }, /* @__PURE__ */ React.createElement(CSpinner, { color: "secondary" }));
322
+ const detectUnit = (name = "") => {
323
+ const lower = name.toLowerCase();
324
+ if (lower.includes("%")) return "%";
325
+ if (lower.includes("venta") || lower.includes("inversi\xF3n")) return currency || "";
326
+ return "";
327
+ };
328
+ const maxY = data.length ? Math.ceil(
329
+ Math.max(
330
+ ...lines.map((lineName) => Math.max(...data.map((d) => d[lineName] || 0)))
331
+ ) * 1.1
332
+ ) : 100;
333
+ return /* @__PURE__ */ React.createElement(CCard4, { className: "mt-4 rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(CCardBody4, null, cards.length > 0 && /* @__PURE__ */ React.createElement(CRow2, { className: "pt-4 g-3 justify-content-center text-center mb-4" }, cards.map((card, index) => /* @__PURE__ */ React.createElement(CCol2, { xs: 12, md: 4, lg: 5, key: index }, /* @__PURE__ */ React.createElement(
334
+ GeneralCard,
335
+ {
336
+ title: card.title,
337
+ current: card.value,
338
+ previous: card.previous,
339
+ change: card.percentageChange,
340
+ isPositive: card.isPositive,
341
+ unit: card.unit,
342
+ previousDateRange: card.previousDateRange,
343
+ tooltipText: card.title
344
+ }
345
+ )))), /* @__PURE__ */ React.createElement(ResponsiveContainer2, { width: "100%", height: 340 }, /* @__PURE__ */ React.createElement(LineChart, { data, margin: { top: 20, right: 30, left: 10, bottom: 10 } }, /* @__PURE__ */ React.createElement(CartesianGrid, { strokeDasharray: "3 3", stroke: "#e5e5e5" }), /* @__PURE__ */ React.createElement(XAxis2, { dataKey: "date", stroke: "#333", tick: { fontSize: 12 } }), /* @__PURE__ */ React.createElement(
346
+ YAxis2,
347
+ {
348
+ yAxisId: "left",
349
+ stroke: "#333",
350
+ tickFormatter: (val) => `${currency ? currency + " " : ""}${val >= 1e6 ? (val / 1e6).toFixed(1) + "M" : val.toLocaleString("es-CO")}`,
351
+ tick: { fontSize: 12 },
352
+ width: 100,
353
+ domain: [0, maxY],
354
+ allowDecimals: false,
355
+ label: yAxisLabel ? {
356
+ value: yAxisLabel,
357
+ angle: -90,
358
+ position: "insideLeft",
359
+ style: { textAnchor: "middle", fill: "#333", fontSize: 13 }
360
+ } : void 0
361
+ }
362
+ ), /* @__PURE__ */ React.createElement(
363
+ Tooltip2,
364
+ {
365
+ formatter: (val, name) => {
366
+ const unit = detectUnit(name);
367
+ return [formatValue(val, unit), displayNames[name] || name];
368
+ },
369
+ labelClassName: "fw-bold",
370
+ wrapperStyle: { zIndex: 1e3 }
371
+ }
372
+ ), /* @__PURE__ */ React.createElement(
373
+ Legend,
374
+ {
375
+ verticalAlign: "bottom",
376
+ height: 36,
377
+ wrapperStyle: { marginTop: 20 },
378
+ iconType: "circle",
379
+ formatter: (value) => displayNames[value] || value
380
+ }
381
+ ), lines.map((lineName) => /* @__PURE__ */ React.createElement(
382
+ Line,
383
+ {
384
+ key: lineName,
385
+ yAxisId: "left",
386
+ type: "monotone",
387
+ dataKey: lineName,
388
+ stroke: colors[lineName] || "#000",
389
+ strokeWidth: 2.5,
390
+ dot: { r: 4 },
391
+ activeDot: { r: 6 }
392
+ }
393
+ ))))));
394
+ }
395
+
396
+ // src/components/charts/TopProductsChart.jsx
397
+ import {
398
+ BarChart as BarChart2,
399
+ Bar as Bar2,
400
+ XAxis as XAxis3,
401
+ YAxis as YAxis3,
402
+ Tooltip as Tooltip3,
403
+ ResponsiveContainer as ResponsiveContainer3,
404
+ LabelList as LabelList2,
405
+ Cell as Cell2
406
+ } from "recharts";
407
+ import { CCard as CCard5, CCardBody as CCardBody5 } from "@coreui/react-pro";
408
+ var COLORS = ["#FF6A8D", "#FF8AAE", "#FFA3BC", "#FFC3D0", "#FFE0E7"];
409
+ var ChartTooltip = ({ active, payload }) => {
410
+ if (active && payload && payload.length) {
411
+ return /* @__PURE__ */ React.createElement("div", { className: "bg-white p-2 shadow rounded border border-light" }, /* @__PURE__ */ React.createElement("p", { className: "mb-1 fw-semibold" }, payload[0].payload.name), /* @__PURE__ */ React.createElement("p", { className: "mb-0 text-muted" }, "Cantidad: ", payload[0].value.toLocaleString()));
319
412
  }
320
- if (!data.length) {
321
- return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5 text-muted" }, emptyMessage);
413
+ return null;
414
+ };
415
+ function TopProductsChart({
416
+ data = [],
417
+ title = "Productos M\xE1s Vendidos",
418
+ emptyText = "No se registraron productos vendidos en este rango de fechas.",
419
+ maxItems = 5
420
+ }) {
421
+ const processedData = (data || []).filter((item) => {
422
+ var _a;
423
+ return item.quantity > 0 && ((_a = item.name) == null ? void 0 : _a.trim());
424
+ }).sort((a, b) => b.quantity - a.quantity).slice(0, maxItems).map((item) => ({ name: item.name, quantity: item.quantity }));
425
+ if (!processedData.length) {
426
+ return /* @__PURE__ */ React.createElement(CCard5, { className: "mt-4 rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(CCardBody5, { className: "text-center py-5" }, /* @__PURE__ */ React.createElement("p", { className: "text-muted mb-2" }, /* @__PURE__ */ React.createElement("i", { className: "bi bi-box-seam fs-4 d-block mb-2" }), emptyText)));
322
427
  }
323
- const renderPagination = () => {
324
- const pages = [];
325
- for (let i = 1; i <= totalPages; i++) {
326
- pages.push(
327
- /* @__PURE__ */ React.createElement(
328
- "button",
329
- {
330
- key: i,
331
- onClick: () => setCurrentPage(i),
332
- className: `px-3 py-1 rounded-pill border ${i === currentPage ? "bg-dark text-white" : "bg-white text-dark"}`
333
- },
334
- i
335
- )
336
- );
337
- }
338
- return /* @__PURE__ */ React.createElement("div", { className: "d-flex justify-content-center align-items-center gap-2 mt-3 flex-wrap" }, currentPage > 1 && /* @__PURE__ */ React.createElement(
339
- "button",
428
+ return /* @__PURE__ */ React.createElement(CCard5, { className: "mt-4 rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(CCardBody5, null, /* @__PURE__ */ React.createElement("h5", { className: "fw-semibold text-center fs-5 mb-4" }, title), /* @__PURE__ */ React.createElement("div", { style: { height: `${Math.max(processedData.length * 50, 80)}px` } }, /* @__PURE__ */ React.createElement(ResponsiveContainer3, { width: "100%", height: "100%" }, /* @__PURE__ */ React.createElement(
429
+ BarChart2,
430
+ {
431
+ layout: "vertical",
432
+ data: processedData,
433
+ margin: { top: 10, right: 40, left: 20, bottom: 10 }
434
+ },
435
+ /* @__PURE__ */ React.createElement("defs", null, /* @__PURE__ */ React.createElement("linearGradient", { id: "barGradient", x1: "0", y1: "0", x2: "1", y2: "0" }, /* @__PURE__ */ React.createElement("stop", { offset: "0%", stopColor: "#FF8AAE" }), /* @__PURE__ */ React.createElement("stop", { offset: "100%", stopColor: "#FF1F3D" }))),
436
+ /* @__PURE__ */ React.createElement(
437
+ XAxis3,
340
438
  {
341
- onClick: () => setCurrentPage(currentPage - 1),
342
- className: "px-3 py-1 rounded-pill border bg-white text-dark",
343
- style: { minWidth: "80px", fontWeight: 500 }
344
- },
345
- "Anterior"
346
- ), pages, currentPage < totalPages && /* @__PURE__ */ React.createElement(
347
- "button",
439
+ type: "number",
440
+ tickFormatter: (value) => value.toLocaleString(),
441
+ axisLine: false,
442
+ tick: { fontSize: 12 }
443
+ }
444
+ ),
445
+ /* @__PURE__ */ React.createElement(
446
+ YAxis3,
348
447
  {
349
- onClick: () => setCurrentPage(currentPage + 1),
350
- className: "px-3 py-1 rounded-pill border bg-white text-dark",
351
- style: { minWidth: "80px", fontWeight: 500 }
352
- },
353
- "Siguiente"
354
- ));
448
+ type: "category",
449
+ dataKey: "name",
450
+ width: 150,
451
+ tick: { fontSize: 13 },
452
+ tickFormatter: (value) => value.length > 30 ? value.substring(0, 30) + "..." : value
453
+ }
454
+ ),
455
+ /* @__PURE__ */ React.createElement(Tooltip3, { content: /* @__PURE__ */ React.createElement(ChartTooltip, null) }),
456
+ /* @__PURE__ */ React.createElement(Bar2, { dataKey: "quantity", fill: "url(#barGradient)", radius: [0, 8, 8, 0] }, /* @__PURE__ */ React.createElement(
457
+ LabelList2,
458
+ {
459
+ dataKey: "quantity",
460
+ position: "right",
461
+ formatter: (value) => value.toLocaleString(),
462
+ style: { fill: "#333", fontWeight: 500, fontSize: 12 }
463
+ }
464
+ ), processedData.map((_, index) => /* @__PURE__ */ React.createElement(Cell2, { key: `cell-${index}`, fill: COLORS[index % COLORS.length] })))
465
+ )))));
466
+ }
467
+
468
+ // src/components/charts/SalesByChannelChart.jsx
469
+ import {
470
+ ResponsiveContainer as ResponsiveContainer4,
471
+ BarChart as BarChart3,
472
+ Bar as Bar3,
473
+ XAxis as XAxis4,
474
+ YAxis as YAxis4,
475
+ Tooltip as Tooltip4,
476
+ Legend as Legend2,
477
+ CartesianGrid as CartesianGrid2
478
+ } from "recharts";
479
+ import { CCard as CCard6, CCardBody as CCardBody6 } from "@coreui/react-pro";
480
+ function SalesByChannelChart({
481
+ data = [],
482
+ title = "Ventas por canal",
483
+ emptyText = "Sin datos para este per\xEDodo",
484
+ channels = ["Meta", "TikTok", "Google"],
485
+ channelColors = { Meta: "#FF2F86", TikTok: "#C0C0C0", Google: "#333333" }
486
+ }) {
487
+ const hasData = data.length > 0;
488
+ return /* @__PURE__ */ React.createElement(CCard6, { className: "rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(CCardBody6, null, /* @__PURE__ */ React.createElement("h5", { className: "fw-bold text-center" }, title), !hasData ? /* @__PURE__ */ React.createElement("p", { className: "text-center text-muted" }, emptyText) : /* @__PURE__ */ React.createElement(ResponsiveContainer4, { width: "100%", height: 300 }, /* @__PURE__ */ React.createElement(BarChart3, { data, margin: { top: 20, right: 30, left: 10, bottom: 10 } }, /* @__PURE__ */ React.createElement(CartesianGrid2, { strokeDasharray: "3 3", stroke: "#e5e5e5" }), /* @__PURE__ */ React.createElement(
489
+ XAxis4,
490
+ {
491
+ dataKey: "fecha",
492
+ tick: { fontSize: 12 },
493
+ angle: -45,
494
+ textAnchor: "end",
495
+ interval: Math.ceil(data.length / 10)
496
+ }
497
+ ), /* @__PURE__ */ React.createElement(YAxis4, { tick: { fontSize: 12 } }), /* @__PURE__ */ React.createElement(Tooltip4, null), /* @__PURE__ */ React.createElement(Legend2, { verticalAlign: "top", height: 36, iconType: "circle" }), channels.map((channel) => /* @__PURE__ */ React.createElement(
498
+ Bar3,
499
+ {
500
+ key: channel,
501
+ dataKey: channel,
502
+ stackId: "ventas",
503
+ fill: channelColors[channel] || "#888"
504
+ }
505
+ ))))));
506
+ }
507
+
508
+ // src/components/charts/InvestmentByPlatformChart.jsx
509
+ import {
510
+ PieChart,
511
+ Pie,
512
+ Cell as Cell3,
513
+ Legend as Legend3,
514
+ Tooltip as Tooltip5,
515
+ ResponsiveContainer as ResponsiveContainer5
516
+ } from "recharts";
517
+ import { CCard as CCard7, CCardBody as CCardBody7 } from "@coreui/react-pro";
518
+ var DEFAULT_COLORS = ["#FF2F86", "#D9D9D9", "#333333"];
519
+ function InvestmentByPlatformChart({
520
+ data = [],
521
+ title = "Inversi\xF3n por plataforma",
522
+ colors = DEFAULT_COLORS,
523
+ currencySymbol = "COP",
524
+ locale = "es-CO"
525
+ }) {
526
+ return /* @__PURE__ */ React.createElement(CCard7, { className: "rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(CCardBody7, null, /* @__PURE__ */ React.createElement("h5", { className: "text-center fw-bold" }, title), /* @__PURE__ */ React.createElement(ResponsiveContainer5, { width: "100%", height: 280 }, /* @__PURE__ */ React.createElement(PieChart, null, /* @__PURE__ */ React.createElement(
527
+ Pie,
528
+ {
529
+ data,
530
+ dataKey: "value",
531
+ nameKey: "name",
532
+ cx: "50%",
533
+ cy: "50%",
534
+ innerRadius: 60,
535
+ outerRadius: 100,
536
+ paddingAngle: 5,
537
+ label: ({ name, percent }) => `${name} ${(percent * 100).toFixed(1)}%`
538
+ },
539
+ data.map((_, index) => /* @__PURE__ */ React.createElement(Cell3, { key: `cell-${index}`, fill: colors[index % colors.length] }))
540
+ ), /* @__PURE__ */ React.createElement(
541
+ Tooltip5,
542
+ {
543
+ formatter: (value) => `${currencySymbol} ${value.toLocaleString(locale)}`
544
+ }
545
+ ), /* @__PURE__ */ React.createElement(Legend3, { verticalAlign: "bottom", height: 36 })))));
546
+ }
547
+
548
+ // src/components/pagination/PaginatedTable.jsx
549
+ import { CTable, CTableHead, CTableBody, CTableRow, CTableHeaderCell, CSpinner } from "@coreui/react-pro";
550
+ function PaginatedTable({ data = [], itemsPerPage = 10, currentPage = 1, setCurrentPage = () => {
551
+ }, columns = [], renderRow = () => null, loading = false, emptyMessage = "No hay datos disponibles." }) {
552
+ const totalPages = Math.ceil(data.length / itemsPerPage);
553
+ const paginatedData = data.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
554
+ if (loading) return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5" }, /* @__PURE__ */ React.createElement(CSpinner, { color: "secondary" }));
555
+ if (!data.length) return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5 text-muted" }, emptyMessage);
556
+ const renderPagination = () => {
557
+ const pages = Array.from({ length: totalPages }, (_, i) => i + 1);
558
+ return /* @__PURE__ */ React.createElement("div", { className: "d-flex justify-content-center align-items-center gap-2 mt-3 flex-wrap" }, currentPage > 1 && /* @__PURE__ */ React.createElement("button", { onClick: () => setCurrentPage(currentPage - 1), className: "px-3 py-1 rounded-pill border bg-white text-dark", style: { minWidth: 80, fontWeight: 500 } }, "Anterior"), pages.map((i) => /* @__PURE__ */ React.createElement("button", { key: i, onClick: () => setCurrentPage(i), className: `px-3 py-1 rounded-pill border ${i === currentPage ? "bg-dark text-white" : "bg-white text-dark"}` }, i)), currentPage < totalPages && /* @__PURE__ */ React.createElement("button", { onClick: () => setCurrentPage(currentPage + 1), className: "px-3 py-1 rounded-pill border bg-white text-dark", style: { minWidth: 80, fontWeight: 500 } }, "Siguiente"));
355
559
  };
356
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(CTable, { hover: true, responsive: true }, /* @__PURE__ */ React.createElement(CTableHead, { className: "bg-dark text-white" }, /* @__PURE__ */ React.createElement(CTableRow, null, columns.map((col, idx) => /* @__PURE__ */ React.createElement(CTableHeaderCell, { key: idx }, col)))), /* @__PURE__ */ React.createElement(CTableBody, null, paginatedData.map(renderRow))), totalPages > 1 && renderPagination());
560
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(CTable, { hover: true, responsive: true }, /* @__PURE__ */ React.createElement(CTableHead, { className: "bg-dark text-white" }, /* @__PURE__ */ React.createElement(CTableRow, null, columns.map((col, i) => /* @__PURE__ */ React.createElement(CTableHeaderCell, { key: i }, col)))), /* @__PURE__ */ React.createElement(CTableBody, null, paginatedData.map(renderRow))), totalPages > 1 && renderPagination());
357
561
  }
358
562
 
359
563
  // src/components/pagination/PaginatedGrid.jsx
360
564
  import { CSpinner as CSpinner2 } from "@coreui/react-pro";
361
- function PaginatedGrid({
362
- data = [],
363
- itemsPerPage = 6,
364
- currentPage = 1,
365
- setCurrentPage = () => {
366
- },
367
- renderItem = () => null,
368
- loading = false,
369
- emptyMessage = "No hay elementos."
370
- }) {
565
+ function PaginatedGrid({ data = [], itemsPerPage = 6, currentPage = 1, setCurrentPage = () => {
566
+ }, renderItem = () => null, loading = false, emptyMessage = "No hay elementos." }) {
371
567
  const totalPages = Math.ceil(data.length / itemsPerPage);
372
- const paginatedData = data.slice(
373
- (currentPage - 1) * itemsPerPage,
374
- currentPage * itemsPerPage
375
- );
376
- if (loading) {
377
- return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5" }, /* @__PURE__ */ React.createElement(CSpinner2, { color: "secondary" }));
378
- }
379
- if (!data.length) {
380
- return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5 text-muted" }, emptyMessage);
381
- }
568
+ const paginatedData = data.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
569
+ if (loading) return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5" }, /* @__PURE__ */ React.createElement(CSpinner2, { color: "secondary" }));
570
+ if (!data.length) return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5 text-muted" }, emptyMessage);
382
571
  const renderPagination = () => {
383
- const pages = [];
384
- for (let i = 1; i <= totalPages; i++) {
385
- pages.push(
386
- /* @__PURE__ */ React.createElement(
387
- "button",
388
- {
389
- key: i,
390
- onClick: () => setCurrentPage(i),
391
- className: `px-3 py-1 rounded-pill border ${i === currentPage ? "bg-dark text-white" : "bg-white text-dark"}`
392
- },
393
- i
394
- )
395
- );
396
- }
397
- return /* @__PURE__ */ React.createElement("div", { className: "d-flex justify-content-center gap-2 mt-4 flex-wrap" }, currentPage > 1 && /* @__PURE__ */ React.createElement(
398
- "button",
399
- {
400
- onClick: () => setCurrentPage(currentPage - 1),
401
- className: "px-3 py-1 rounded-pill border bg-white text-dark"
402
- },
403
- "Anterior"
404
- ), pages, currentPage < totalPages && /* @__PURE__ */ React.createElement(
405
- "button",
406
- {
407
- onClick: () => setCurrentPage(currentPage + 1),
408
- className: "px-3 py-1 rounded-pill border bg-white text-dark"
409
- },
410
- "Siguiente"
411
- ));
572
+ const pages = Array.from({ length: totalPages }, (_, i) => i + 1);
573
+ return /* @__PURE__ */ React.createElement("div", { className: "d-flex justify-content-center gap-2 mt-4 flex-wrap" }, currentPage > 1 && /* @__PURE__ */ React.createElement("button", { onClick: () => setCurrentPage(currentPage - 1), className: "px-3 py-1 rounded-pill border bg-white text-dark" }, "Anterior"), pages.map((i) => /* @__PURE__ */ React.createElement("button", { key: i, onClick: () => setCurrentPage(i), className: `px-3 py-1 rounded-pill border ${i === currentPage ? "bg-dark text-white" : "bg-white text-dark"}` }, i)), currentPage < totalPages && /* @__PURE__ */ React.createElement("button", { onClick: () => setCurrentPage(currentPage + 1), className: "px-3 py-1 rounded-pill border bg-white text-dark" }, "Siguiente"));
412
574
  };
413
575
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "row g-4" }, paginatedData.map(renderItem)), totalPages > 1 && renderPagination());
414
576
  }
415
577
 
416
578
  // src/components/skeletons/CardSkeleton.jsx
417
- import { CCard as CCard2, CPlaceholder } from "@coreui/react-pro";
579
+ import { CCard as CCard8, CPlaceholder } from "@coreui/react-pro";
418
580
  function CardSkeleton() {
419
- return /* @__PURE__ */ React.createElement(CCard2, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(CPlaceholder, { component: "div", animation: "glow", className: "d-flex flex-column gap-2 bg-transparent" }, /* @__PURE__ */ React.createElement(CPlaceholder, { className: "p-4 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" })));
581
+ return /* @__PURE__ */ React.createElement(CCard8, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(CPlaceholder, { component: "div", animation: "glow", className: "d-flex flex-column gap-2 bg-transparent" }, /* @__PURE__ */ React.createElement(CPlaceholder, { className: "p-4 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" })));
420
582
  }
421
583
 
422
584
  // src/components/skeletons/TextSkeleton.jsx
423
- import { CCard as CCard3, CPlaceholder as CPlaceholder2 } from "@coreui/react-pro";
585
+ import { CCard as CCard9, CPlaceholder as CPlaceholder2 } from "@coreui/react-pro";
424
586
  function TextSkeleton() {
425
- return /* @__PURE__ */ React.createElement(CCard3, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(CPlaceholder2, { component: "div", animation: "glow", className: "d-flex flex-column gap-2 bg-transparent" }, /* @__PURE__ */ React.createElement(CPlaceholder2, { className: "p-0 my-2 rounded-1", size: "lg", xs: 8, color: "skeleton" })));
587
+ return /* @__PURE__ */ React.createElement(CCard9, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(CPlaceholder2, { component: "div", animation: "glow", className: "d-flex flex-column gap-2 bg-transparent" }, /* @__PURE__ */ React.createElement(CPlaceholder2, { className: "p-0 my-2 rounded-1", size: "lg", xs: 8, color: "skeleton" })));
426
588
  }
427
589
 
428
590
  // src/components/skeletons/MetricsSkeleton.jsx
429
- import { CCard as CCard4, CPlaceholder as CPlaceholder3 } from "@coreui/react-pro";
591
+ import { CCard as CCard10, CPlaceholder as CPlaceholder3 } from "@coreui/react-pro";
430
592
  function MetricsSkeleton() {
431
- return /* @__PURE__ */ React.createElement(CCard4, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(CPlaceholder3, { component: "div", animation: "glow", className: "d-flex flex-column gap-2 bg-transparent" }, /* @__PURE__ */ React.createElement(CPlaceholder3, { className: "p-5 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" }), /* @__PURE__ */ React.createElement(CPlaceholder3, { className: "p-3 mt-2 rounded-1", size: "xs", xs: 12, color: "skeleton" })));
593
+ return /* @__PURE__ */ React.createElement(CCard10, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(CPlaceholder3, { component: "div", animation: "glow", className: "d-flex flex-column gap-2 bg-transparent" }, /* @__PURE__ */ React.createElement(CPlaceholder3, { className: "p-5 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" }), /* @__PURE__ */ React.createElement(CPlaceholder3, { className: "p-3 mt-2 rounded-1", size: "xs", xs: 12, color: "skeleton" })));
594
+ }
595
+
596
+ // src/components/skeletons/ReportTableSkeleton.jsx
597
+ import { CCard as CCard11, CPlaceholder as CPlaceholder4 } from "@coreui/react-pro";
598
+ function ReportTableSkeleton() {
599
+ return /* @__PURE__ */ React.createElement(CCard11, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(
600
+ CPlaceholder4,
601
+ {
602
+ component: "div",
603
+ animation: "glow",
604
+ className: "d-flex flex-column gap-2 bg-transparent"
605
+ },
606
+ /* @__PURE__ */ React.createElement(CPlaceholder4, { className: "p-4 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" }),
607
+ /* @__PURE__ */ React.createElement(CPlaceholder4, { className: "p-5 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" })
608
+ ));
609
+ }
610
+
611
+ // src/components/skeletons/SummaryReportSkeleton.jsx
612
+ import { CCard as CCard12, CCol as CCol3, CPlaceholder as CPlaceholder5, CRow as CRow3 } from "@coreui/react-pro";
613
+ var CardPlaceholder = ({ className = "" }) => /* @__PURE__ */ React.createElement(CCard12, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(
614
+ CPlaceholder5,
615
+ {
616
+ component: "div",
617
+ animation: "glow",
618
+ className: `d-flex flex-column gap-2 bg-transparent ${className}`
619
+ },
620
+ /* @__PURE__ */ React.createElement(CPlaceholder5, { className: "p-4 mt-2 rounded-2", size: "lg", xs: 12, color: "skeleton" })
621
+ ));
622
+ function SummaryReportSkeleton({
623
+ layout = [
624
+ { sm: 6, md: 6 },
625
+ { sm: 6, md: 6 },
626
+ { sm: 6, md: 4 },
627
+ { sm: 6, md: 4 },
628
+ { sm: 6, md: 4 },
629
+ { sm: 6, md: 6 },
630
+ { sm: 6, md: 4 },
631
+ { sm: 6, md: 2 }
632
+ ]
633
+ }) {
634
+ return /* @__PURE__ */ React.createElement(CRow3, { className: "g-md-3 px-4 px-sm-2 g-sm-2 pt-2 pb-4" }, layout.map((col, index) => /* @__PURE__ */ React.createElement(CCol3, { sm: col.sm, md: col.md, key: index }, /* @__PURE__ */ React.createElement(CardPlaceholder, null))));
635
+ }
636
+
637
+ // ../../node_modules/@coreui/icons-pro/dist/esm/duotone/cid-exclamation-circle.js
638
+ var cidExclamationCircle = ["512 512", "<path fill='var(--ci-secondary-color, currentColor)' d='M256,16C123.452,16,16,123.452,16,256S123.452,496,256,496a238.867,238.867,0,0,0,132.685-40q1.668-1.108,3.315-2.246A239.721,239.721,0,0,0,496,256C496,123.452,388.548,16,256,16Z' class='ci-secondary' opacity='var(--ci-secondary-opacity, 0.25)'/><polygon fill='var(--ci-primary-color, currentColor)' points='224 232 238 304 274 304 288 232 288 120 224 120 224 232' class='ci-primary'/><rect width='40' height='40' x='236' y='344' fill='var(--ci-primary-color, currentColor)' class='ci-primary'/>"];
639
+
640
+ // src/components/feedback/NoDataMessage.jsx
641
+ import CIcon8 from "@coreui/icons-react";
642
+ function NoDataMessage({
643
+ message = "No se obtuvieron datos. Revisa el rango de fechas y la integraci\xF3n."
644
+ }) {
645
+ return /* @__PURE__ */ React.createElement(
646
+ "div",
647
+ {
648
+ className: "d-flex align-items-center gap-2 rounded-3 px-3 py-3 mt-3 mb-3",
649
+ style: {
650
+ backgroundColor: "var(--cui-warning-bg-subtle)",
651
+ border: "1px solid var(--cui-warning)",
652
+ color: "var(--cui-body-color)"
653
+ }
654
+ },
655
+ /* @__PURE__ */ React.createElement(
656
+ CIcon8,
657
+ {
658
+ icon: cidExclamationCircle,
659
+ className: "flex-shrink-0 me-2 text-warning",
660
+ size: "xxl"
661
+ }
662
+ ),
663
+ message
664
+ );
432
665
  }
433
666
 
434
667
  // src/components/back-button/BackButton.jsx
435
668
  import { useRouter } from "next/navigation";
436
669
  import { CButton } from "@coreui/react-pro";
437
- import CIcon7 from "@coreui/icons-react";
670
+ import { cilArrowLeft } from "@coreui/icons";
671
+ import CIcon9 from "@coreui/icons-react";
438
672
  function BackButton({ title, color = "dark", className = "", path }) {
439
673
  const { back, push } = useRouter();
440
- const buttonClasses = `back-button d-flex align-items-center px-0 ${className}`;
441
- function handleBack() {
442
- if (path) push(path);
443
- else back();
444
- }
445
- return /* @__PURE__ */ React.createElement(CustomTooltip, { content: "Volver atr\xE1s", placement: "bottom" }, /* @__PURE__ */ React.createElement(CButton, { color, variant: "ghost", className: buttonClasses, onClick: handleBack }, /* @__PURE__ */ React.createElement(CIcon7, { icon: cilArrowLeft, size: "lg", className: "mx-1" }), title && /* @__PURE__ */ React.createElement("span", { className: "px-2" }, title)));
674
+ return /* @__PURE__ */ React.createElement(CustomTooltip, { content: "Volver atr\xE1s", placement: "bottom" }, /* @__PURE__ */ React.createElement(CButton, { color, variant: "ghost", className: `back-button d-flex align-items-center px-0 ${className}`, onClick: () => path ? push(path) : back() }, /* @__PURE__ */ React.createElement(CIcon9, { icon: cilArrowLeft, size: "lg", className: "mx-1" }), title && /* @__PURE__ */ React.createElement("span", { className: "px-2" }, title)));
446
675
  }
447
676
  export {
448
677
  BackButton,
449
678
  CardSkeleton,
450
679
  CustomTooltip,
680
+ FunnelChart,
681
+ GeneralCard,
451
682
  IconButton,
683
+ InvestmentByPlatformChart,
452
684
  MetricCard,
453
685
  MetricsSkeleton,
454
686
  Modal,
687
+ NoDataMessage,
455
688
  OutlineButton,
456
689
  PaginatedGrid,
457
690
  PaginatedTable,
691
+ ReportTableSkeleton,
692
+ SalesByChannelChart,
458
693
  SolidButton,
694
+ SummaryReportSkeleton,
459
695
  TextButton,
460
696
  TextSkeleton,
697
+ TimeSeriesComparisonChart,
698
+ TopProductsChart,
461
699
  formatDateRange,
462
700
  formatValue,
463
701
  getBadgeStyles