@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/README.md +186 -170
- package/dist/index.js +461 -250
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +492 -254
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -5
- package/src/styles/_roax-colors.scss +107 -8
- package/src/styles/index.scss +3 -8
package/dist/index.js
CHANGED
|
@@ -32,16 +32,25 @@ __export(index_exports, {
|
|
|
32
32
|
BackButton: () => BackButton,
|
|
33
33
|
CardSkeleton: () => CardSkeleton,
|
|
34
34
|
CustomTooltip: () => CustomTooltip,
|
|
35
|
+
FunnelChart: () => FunnelChart,
|
|
36
|
+
GeneralCard: () => GeneralCard,
|
|
35
37
|
IconButton: () => IconButton,
|
|
38
|
+
InvestmentByPlatformChart: () => InvestmentByPlatformChart,
|
|
36
39
|
MetricCard: () => MetricCard,
|
|
37
40
|
MetricsSkeleton: () => MetricsSkeleton,
|
|
38
41
|
Modal: () => Modal,
|
|
42
|
+
NoDataMessage: () => NoDataMessage,
|
|
39
43
|
OutlineButton: () => OutlineButton,
|
|
40
44
|
PaginatedGrid: () => PaginatedGrid,
|
|
41
45
|
PaginatedTable: () => PaginatedTable,
|
|
46
|
+
ReportTableSkeleton: () => ReportTableSkeleton,
|
|
47
|
+
SalesByChannelChart: () => SalesByChannelChart,
|
|
42
48
|
SolidButton: () => SolidButton,
|
|
49
|
+
SummaryReportSkeleton: () => SummaryReportSkeleton,
|
|
43
50
|
TextButton: () => TextButton,
|
|
44
51
|
TextSkeleton: () => TextSkeleton,
|
|
52
|
+
TimeSeriesComparisonChart: () => TimeSeriesComparisonChart,
|
|
53
|
+
TopProductsChart: () => TopProductsChart,
|
|
45
54
|
formatDateRange: () => formatDateRange,
|
|
46
55
|
formatValue: () => formatValue,
|
|
47
56
|
getBadgeStyles: () => getBadgeStyles
|
|
@@ -52,19 +61,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
52
61
|
var import_react_pro = require("@coreui/react-pro");
|
|
53
62
|
var import_icons_react = __toESM(require("@coreui/icons-react"));
|
|
54
63
|
var import_SolidButton = require("./SolidButton.scss");
|
|
55
|
-
function SolidButton({
|
|
56
|
-
title = "Button",
|
|
57
|
-
onClick,
|
|
58
|
-
color = "custom-primary",
|
|
59
|
-
textColor = "custom-white",
|
|
60
|
-
className = "",
|
|
61
|
-
loading = false,
|
|
62
|
-
icon,
|
|
63
|
-
svgComponent: SvgComponent,
|
|
64
|
-
type = "submit",
|
|
65
|
-
badge,
|
|
66
|
-
disabled
|
|
67
|
-
}) {
|
|
64
|
+
function SolidButton({ title = "Button", onClick, color = "custom-primary", textColor = "custom-white", className = "", loading = false, icon, svgComponent: SvgComponent, type = "submit", badge, disabled }) {
|
|
68
65
|
return /* @__PURE__ */ React.createElement(
|
|
69
66
|
import_react_pro.CLoadingButton,
|
|
70
67
|
{
|
|
@@ -74,12 +71,7 @@ function SolidButton({
|
|
|
74
71
|
loading,
|
|
75
72
|
disabledOnLoading: true,
|
|
76
73
|
disabled,
|
|
77
|
-
style: {
|
|
78
|
-
minHeight: "44px",
|
|
79
|
-
minWidth: "fit-content",
|
|
80
|
-
fontSize: "0.95rem",
|
|
81
|
-
letterSpacing: "0.3px"
|
|
82
|
-
}
|
|
74
|
+
style: { minHeight: "44px", minWidth: "fit-content", fontSize: "0.95rem", letterSpacing: "0.3px" }
|
|
83
75
|
},
|
|
84
76
|
icon && /* @__PURE__ */ React.createElement(import_icons_react.default, { icon, className: "btn-icon" }),
|
|
85
77
|
SvgComponent && !icon && /* @__PURE__ */ React.createElement(SvgComponent, null),
|
|
@@ -92,16 +84,7 @@ function SolidButton({
|
|
|
92
84
|
var import_react_pro2 = require("@coreui/react-pro");
|
|
93
85
|
var import_icons_react2 = __toESM(require("@coreui/icons-react"));
|
|
94
86
|
var import_OutlineButton = require("./OutlineButton.scss");
|
|
95
|
-
function OutlineButton({
|
|
96
|
-
title = "Button",
|
|
97
|
-
onClick,
|
|
98
|
-
color = "custom-primary",
|
|
99
|
-
className = "",
|
|
100
|
-
loading = false,
|
|
101
|
-
icon,
|
|
102
|
-
type = "submit",
|
|
103
|
-
disabled
|
|
104
|
-
}) {
|
|
87
|
+
function OutlineButton({ title = "Button", onClick, color = "custom-primary", className = "", loading = false, icon, type = "submit", disabled }) {
|
|
105
88
|
return /* @__PURE__ */ React.createElement(
|
|
106
89
|
import_react_pro2.CLoadingButton,
|
|
107
90
|
{
|
|
@@ -112,10 +95,7 @@ function OutlineButton({
|
|
|
112
95
|
disabledOnLoading: true,
|
|
113
96
|
disabled,
|
|
114
97
|
variant: "outline",
|
|
115
|
-
style: {
|
|
116
|
-
maxHeight: "40px",
|
|
117
|
-
minWidth: "fit-content"
|
|
118
|
-
}
|
|
98
|
+
style: { maxHeight: "40px", minWidth: "fit-content" }
|
|
119
99
|
},
|
|
120
100
|
icon && /* @__PURE__ */ React.createElement(import_icons_react2.default, { icon }),
|
|
121
101
|
/* @__PURE__ */ React.createElement("span", null, title)
|
|
@@ -125,17 +105,7 @@ function OutlineButton({
|
|
|
125
105
|
// src/components/buttons/TextButton.jsx
|
|
126
106
|
var import_react_pro3 = require("@coreui/react-pro");
|
|
127
107
|
var import_icons_react3 = __toESM(require("@coreui/icons-react"));
|
|
128
|
-
function TextButton({
|
|
129
|
-
disabled,
|
|
130
|
-
title,
|
|
131
|
-
onClick,
|
|
132
|
-
color = "dark",
|
|
133
|
-
className = "",
|
|
134
|
-
loading = false,
|
|
135
|
-
icon,
|
|
136
|
-
children
|
|
137
|
-
}) {
|
|
138
|
-
const buttonClasses = `rounded-3 px-2 d-flex justify-content-center gap-2 fw-medium ${className}`;
|
|
108
|
+
function TextButton({ disabled, title, onClick, color = "dark", className = "", loading = false, icon, children }) {
|
|
139
109
|
return /* @__PURE__ */ React.createElement("span", { className: "d-inline-block", tabIndex: 0 }, /* @__PURE__ */ React.createElement(
|
|
140
110
|
import_react_pro3.CLoadingButton,
|
|
141
111
|
{
|
|
@@ -144,7 +114,7 @@ function TextButton({
|
|
|
144
114
|
variant: "ghost",
|
|
145
115
|
type: "button",
|
|
146
116
|
color,
|
|
147
|
-
className:
|
|
117
|
+
className: `rounded-3 px-2 d-flex justify-content-center gap-2 fw-medium ${className}`,
|
|
148
118
|
loading
|
|
149
119
|
},
|
|
150
120
|
icon && /* @__PURE__ */ React.createElement(import_icons_react3.default, { size: "xl", icon }),
|
|
@@ -159,37 +129,12 @@ var import_icons_react4 = __toESM(require("@coreui/icons-react"));
|
|
|
159
129
|
// src/components/custom-tooltip/CustomTooltip.jsx
|
|
160
130
|
var import_react = __toESM(require("@tippyjs/react"));
|
|
161
131
|
var import_tippy = require("tippy.js/dist/tippy.css");
|
|
162
|
-
function CustomTooltip({
|
|
163
|
-
content,
|
|
164
|
-
placement = "bottom",
|
|
165
|
-
delay = 0,
|
|
166
|
-
className = "",
|
|
167
|
-
children
|
|
168
|
-
}) {
|
|
169
|
-
return /* @__PURE__ */ React.createElement(
|
|
170
|
-
import_react.default,
|
|
171
|
-
{
|
|
172
|
-
content,
|
|
173
|
-
placement,
|
|
174
|
-
className,
|
|
175
|
-
delay
|
|
176
|
-
},
|
|
177
|
-
children
|
|
178
|
-
);
|
|
132
|
+
function CustomTooltip({ content, placement = "bottom", delay = 0, className = "", children }) {
|
|
133
|
+
return /* @__PURE__ */ React.createElement(import_react.default, { content, placement, className, delay }, children);
|
|
179
134
|
}
|
|
180
135
|
|
|
181
136
|
// src/components/buttons/IconButton.jsx
|
|
182
|
-
function IconButton({
|
|
183
|
-
title,
|
|
184
|
-
onClick,
|
|
185
|
-
color = "dark",
|
|
186
|
-
className = "",
|
|
187
|
-
loading = false,
|
|
188
|
-
icon,
|
|
189
|
-
tooltip = "",
|
|
190
|
-
disabled
|
|
191
|
-
}) {
|
|
192
|
-
const buttonClasses = `d-flex justify-content-center align-items-center gap-1 m-0 p-1 ${className}`;
|
|
137
|
+
function IconButton({ title, onClick, color = "dark", className = "", loading = false, icon, tooltip = "", disabled }) {
|
|
193
138
|
return /* @__PURE__ */ React.createElement(CustomTooltip, { content: tooltip, placement: "bottom" }, /* @__PURE__ */ React.createElement(
|
|
194
139
|
import_react_pro4.CLoadingButton,
|
|
195
140
|
{
|
|
@@ -197,7 +142,7 @@ function IconButton({
|
|
|
197
142
|
variant: "ghost",
|
|
198
143
|
type: "button",
|
|
199
144
|
color,
|
|
200
|
-
className:
|
|
145
|
+
className: `d-flex justify-content-center align-items-center gap-1 m-0 p-1 ${className}`,
|
|
201
146
|
loading,
|
|
202
147
|
disabled
|
|
203
148
|
},
|
|
@@ -209,61 +154,25 @@ function IconButton({
|
|
|
209
154
|
// src/components/modal/Modal.jsx
|
|
210
155
|
var import_icons_react5 = __toESM(require("@coreui/icons-react"));
|
|
211
156
|
var import_react_pro5 = require("@coreui/react-pro");
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// ../../node_modules/@coreui/icons/dist/esm/free/cil-arrow-left.js
|
|
217
|
-
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'/>"];
|
|
218
|
-
|
|
219
|
-
// ../../node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js
|
|
220
|
-
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'/>"];
|
|
221
|
-
|
|
222
|
-
// ../../node_modules/@coreui/icons/dist/esm/free/cil-info.js
|
|
223
|
-
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'/>"];
|
|
224
|
-
|
|
225
|
-
// ../../node_modules/@coreui/icons/dist/esm/free/cil-x.js
|
|
226
|
-
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'/>"];
|
|
227
|
-
|
|
228
|
-
// src/components/modal/Modal.jsx
|
|
229
|
-
function Modal({
|
|
230
|
-
title,
|
|
231
|
-
titleIcon,
|
|
232
|
-
visible,
|
|
233
|
-
setVisible,
|
|
234
|
-
alignment = "center",
|
|
235
|
-
size,
|
|
236
|
-
children
|
|
237
|
-
}) {
|
|
238
|
-
return /* @__PURE__ */ React.createElement(
|
|
239
|
-
import_react_pro5.CModal,
|
|
157
|
+
var import_icons = require("@coreui/icons");
|
|
158
|
+
function Modal({ title, titleIcon, visible, setVisible, alignment = "center", size, children }) {
|
|
159
|
+
return /* @__PURE__ */ React.createElement(import_react_pro5.CModal, { alignment, visible, onClose: () => setVisible(false), size, focus: true, keyboard: true, "aria-labelledby": "roax-modal-title" }, /* @__PURE__ */ React.createElement(import_react_pro5.CModalHeader, { className: "position-relative" }, /* @__PURE__ */ React.createElement(import_react_pro5.CModalTitle, { id: "roax-modal-title", className: "d-flex align-items-center gap-2" }, titleIcon && /* @__PURE__ */ React.createElement(import_icons_react5.default, { icon: titleIcon, size: "lg", className: "text-muted" }), title), /* @__PURE__ */ React.createElement(
|
|
160
|
+
"button",
|
|
240
161
|
{
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
keyboard: true,
|
|
247
|
-
"aria-labelledby": "roax-modal-title"
|
|
162
|
+
onClick: () => setVisible(false),
|
|
163
|
+
type: "button",
|
|
164
|
+
className: "position-absolute end-0 top-0 mt-3 me-3 p-0 bg-transparent border-0",
|
|
165
|
+
style: { fontSize: "1.25rem", color: "var(--cui-body-color)", zIndex: 10 },
|
|
166
|
+
"aria-label": "Cerrar"
|
|
248
167
|
},
|
|
249
|
-
/* @__PURE__ */ React.createElement(
|
|
250
|
-
|
|
251
|
-
{
|
|
252
|
-
onClick: () => setVisible(false),
|
|
253
|
-
type: "button",
|
|
254
|
-
className: "position-absolute end-0 top-0 mt-3 me-3 p-0 bg-transparent border-0",
|
|
255
|
-
style: { fontSize: "1.25rem", color: "var(--cui-body-color)", zIndex: 10 },
|
|
256
|
-
"aria-label": "Cerrar"
|
|
257
|
-
},
|
|
258
|
-
/* @__PURE__ */ React.createElement(import_icons_react5.default, { icon: cilX, size: "lg" })
|
|
259
|
-
)),
|
|
260
|
-
/* @__PURE__ */ React.createElement(import_react_pro5.CModalBody, null, children)
|
|
261
|
-
);
|
|
168
|
+
/* @__PURE__ */ React.createElement(import_icons_react5.default, { icon: import_icons.cilX, size: "lg" })
|
|
169
|
+
)), /* @__PURE__ */ React.createElement(import_react_pro5.CModalBody, null, children));
|
|
262
170
|
}
|
|
263
171
|
|
|
264
172
|
// src/components/card/MetricCard.jsx
|
|
265
173
|
var import_react_pro6 = require("@coreui/react-pro");
|
|
266
174
|
var import_icons_react6 = __toESM(require("@coreui/icons-react"));
|
|
175
|
+
var import_icons2 = require("@coreui/icons");
|
|
267
176
|
|
|
268
177
|
// src/components/card/card-utils.js
|
|
269
178
|
var formatValue = (val, unit = "", title = "") => {
|
|
@@ -290,8 +199,8 @@ function formatDateRange(previousDateRange) {
|
|
|
290
199
|
if (!previousDateRange) return { formattedRange: "" };
|
|
291
200
|
const parts = previousDateRange.split(" - ");
|
|
292
201
|
const parseDate = (str) => {
|
|
293
|
-
const [
|
|
294
|
-
return new Date(
|
|
202
|
+
const [y, m, d] = str.split("-").map(Number);
|
|
203
|
+
return new Date(y, m - 1, d);
|
|
295
204
|
};
|
|
296
205
|
const format = (date) => {
|
|
297
206
|
const day = String(date.getDate()).padStart(2, "0");
|
|
@@ -301,13 +210,33 @@ function formatDateRange(previousDateRange) {
|
|
|
301
210
|
};
|
|
302
211
|
const since = parseDate(parts[0]);
|
|
303
212
|
const until = parts[1] ? parseDate(parts[1]) : null;
|
|
304
|
-
|
|
305
|
-
return { formattedRange };
|
|
213
|
+
return { formattedRange: until ? `${format(since)} - ${format(until)}` : format(since) };
|
|
306
214
|
}
|
|
307
215
|
|
|
308
216
|
// src/components/card/MetricCard.jsx
|
|
309
217
|
var import_MetricCard = require("./MetricCard.scss");
|
|
310
|
-
function MetricCard({
|
|
218
|
+
function MetricCard({ title, current, previous, change, isPositive, unit = "", previousDateRange = "", tooltipText = "", backgroundColor }) {
|
|
219
|
+
const isColored = !!backgroundColor;
|
|
220
|
+
return /* @__PURE__ */ React.createElement(
|
|
221
|
+
import_react_pro6.CCard,
|
|
222
|
+
{
|
|
223
|
+
className: `metric-card w-100 h-100 d-flex flex-column border-0${isColored ? " metric-card--colored" : ""}`,
|
|
224
|
+
style: isColored ? { background: backgroundColor } : void 0
|
|
225
|
+
},
|
|
226
|
+
/* @__PURE__ */ React.createElement(import_react_pro6.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(import_icons_react6.default, { icon: import_icons2.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(import_icons_react6.default, { icon: isPositive ? import_icons2.cilArrowTop : import_icons2.cilArrowBottom, size: "sm" }), Math.abs(change), "%")), /* @__PURE__ */ React.createElement("hr", { className: "metric-card__divider" }), (() => {
|
|
227
|
+
const { formattedRange } = formatDateRange(previousDateRange);
|
|
228
|
+
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));
|
|
229
|
+
})())
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// src/components/card/GeneralCard.jsx
|
|
234
|
+
var import_react_pro7 = require("@coreui/react-pro");
|
|
235
|
+
var import_icons_react7 = __toESM(require("@coreui/icons-react"));
|
|
236
|
+
var import_icons3 = require("@coreui/icons");
|
|
237
|
+
var import_lucide_react = require("lucide-react");
|
|
238
|
+
var import_general_card = require("./general-card.scss");
|
|
239
|
+
function GeneralCard({
|
|
311
240
|
title,
|
|
312
241
|
current,
|
|
313
242
|
previous,
|
|
@@ -319,189 +248,471 @@ function MetricCard({
|
|
|
319
248
|
backgroundColor
|
|
320
249
|
}) {
|
|
321
250
|
const isColored = !!backgroundColor;
|
|
322
|
-
const cardClass = `
|
|
251
|
+
const cardClass = `general-card w-100 h-100 d-flex flex-column border-0${isColored ? " general-card--colored" : ""}`;
|
|
323
252
|
return /* @__PURE__ */ React.createElement(
|
|
324
|
-
|
|
253
|
+
import_react_pro7.CCard,
|
|
325
254
|
{
|
|
326
255
|
className: cardClass,
|
|
327
256
|
style: isColored ? { background: backgroundColor } : void 0
|
|
328
257
|
},
|
|
329
|
-
/* @__PURE__ */ React.createElement(
|
|
330
|
-
|
|
258
|
+
/* @__PURE__ */ React.createElement(import_react_pro7.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(
|
|
259
|
+
import_lucide_react.Info,
|
|
331
260
|
{
|
|
332
|
-
|
|
333
|
-
|
|
261
|
+
size: 16,
|
|
262
|
+
strokeWidth: 2,
|
|
263
|
+
style: { cursor: "pointer", opacity: 0.5 }
|
|
334
264
|
}
|
|
335
|
-
))), /* @__PURE__ */ React.createElement("p", { className: "
|
|
265
|
+
))), /* @__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(import_icons_react7.default, { icon: isPositive ? import_icons3.cilArrowTop : import_icons3.cilArrowBottom, size: "sm" }), Math.abs(change), "%")), /* @__PURE__ */ React.createElement("hr", { className: "general-card__divider" }), (() => {
|
|
336
266
|
const { formattedRange } = formatDateRange(previousDateRange);
|
|
337
|
-
return /* @__PURE__ */ React.createElement("div", { className: "d-flex justify-content-between align-items-center
|
|
267
|
+
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));
|
|
338
268
|
})())
|
|
339
269
|
);
|
|
340
270
|
}
|
|
341
271
|
|
|
342
|
-
// src/components/
|
|
343
|
-
var
|
|
344
|
-
|
|
272
|
+
// src/components/charts/FunnelChart.jsx
|
|
273
|
+
var import_recharts = require("recharts");
|
|
274
|
+
var import_react_pro8 = require("@coreui/react-pro");
|
|
275
|
+
function FunnelChart({ data = [] }) {
|
|
276
|
+
return /* @__PURE__ */ React.createElement(import_react_pro8.CCard, { className: "mt-4 rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(import_react_pro8.CCardBody, null, /* @__PURE__ */ React.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: data.length * 45 + 50 }, /* @__PURE__ */ React.createElement(
|
|
277
|
+
import_recharts.BarChart,
|
|
278
|
+
{
|
|
279
|
+
data,
|
|
280
|
+
layout: "vertical",
|
|
281
|
+
margin: { top: 10, right: 60, left: 20, bottom: 0 },
|
|
282
|
+
barCategoryGap: 15
|
|
283
|
+
},
|
|
284
|
+
/* @__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" }))),
|
|
285
|
+
/* @__PURE__ */ React.createElement(import_recharts.XAxis, { type: "number", hide: true, domain: [0, "dataMax"] }),
|
|
286
|
+
/* @__PURE__ */ React.createElement(
|
|
287
|
+
import_recharts.YAxis,
|
|
288
|
+
{
|
|
289
|
+
dataKey: "title",
|
|
290
|
+
type: "category",
|
|
291
|
+
width: 130,
|
|
292
|
+
axisLine: false,
|
|
293
|
+
tickLine: false,
|
|
294
|
+
style: { fontWeight: 600, fill: "#333", fontSize: 13 }
|
|
295
|
+
}
|
|
296
|
+
),
|
|
297
|
+
/* @__PURE__ */ React.createElement(
|
|
298
|
+
import_recharts.Tooltip,
|
|
299
|
+
{
|
|
300
|
+
content: ({ active, payload }) => {
|
|
301
|
+
if (active && payload && payload.length > 0) {
|
|
302
|
+
const { value, payload: item } = payload[0];
|
|
303
|
+
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)));
|
|
304
|
+
}
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
),
|
|
309
|
+
/* @__PURE__ */ React.createElement(import_recharts.Bar, { dataKey: "value", fill: "url(#funnelGradient)", radius: [0, 10, 10, 0] }, /* @__PURE__ */ React.createElement(
|
|
310
|
+
import_recharts.LabelList,
|
|
311
|
+
{
|
|
312
|
+
dataKey: "value",
|
|
313
|
+
position: "right",
|
|
314
|
+
formatter: (val) => formatValue(val),
|
|
315
|
+
style: { fill: "#333", fontWeight: 500, fontSize: 12 }
|
|
316
|
+
}
|
|
317
|
+
), data.map((entry, index) => /* @__PURE__ */ React.createElement(
|
|
318
|
+
import_recharts.Cell,
|
|
319
|
+
{
|
|
320
|
+
key: `cell-${entry.title || index}`,
|
|
321
|
+
fill: entry.color || "url(#funnelGradient)"
|
|
322
|
+
}
|
|
323
|
+
)))
|
|
324
|
+
)), /* @__PURE__ */ React.createElement(import_react_pro8.CRow, { className: "pt-4 g-3" }, data.slice(0, 3).map((item, index) => /* @__PURE__ */ React.createElement(import_react_pro8.CCol, { xs: 12, md: 4, key: `card-top-${index}` }, /* @__PURE__ */ React.createElement(
|
|
325
|
+
GeneralCard,
|
|
326
|
+
{
|
|
327
|
+
title: item.title,
|
|
328
|
+
current: item.value,
|
|
329
|
+
previous: item.previous,
|
|
330
|
+
change: item.percentageChange,
|
|
331
|
+
isPositive: item.isPositive,
|
|
332
|
+
unit: item.unit,
|
|
333
|
+
previousDateRange: item.previousDateRange,
|
|
334
|
+
tooltipText: item.title
|
|
335
|
+
}
|
|
336
|
+
)))), data.length > 3 && /* @__PURE__ */ React.createElement(import_react_pro8.CRow, { className: "pt-3 g-3" }, data.slice(3).map((item, index) => /* @__PURE__ */ React.createElement(import_react_pro8.CCol, { xs: 12, md: 5, lg: 4, key: `card-bottom-${index}` }, /* @__PURE__ */ React.createElement(
|
|
337
|
+
GeneralCard,
|
|
338
|
+
{
|
|
339
|
+
title: item.title,
|
|
340
|
+
current: item.value,
|
|
341
|
+
previous: item.previous,
|
|
342
|
+
change: item.percentageChange,
|
|
343
|
+
isPositive: item.isPositive,
|
|
344
|
+
unit: item.unit,
|
|
345
|
+
previousDateRange: item.previousDateRange,
|
|
346
|
+
tooltipText: item.title
|
|
347
|
+
}
|
|
348
|
+
))))));
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// src/components/charts/TimeSeriesComparisonChart.jsx
|
|
352
|
+
var import_recharts2 = require("recharts");
|
|
353
|
+
var import_react_pro9 = require("@coreui/react-pro");
|
|
354
|
+
function TimeSeriesComparisonChart({
|
|
345
355
|
data = [],
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
loading = false,
|
|
353
|
-
emptyMessage = "No hay datos disponibles."
|
|
356
|
+
lines = [],
|
|
357
|
+
colors = {},
|
|
358
|
+
cards = [],
|
|
359
|
+
currency = "",
|
|
360
|
+
yAxisLabel = "",
|
|
361
|
+
displayNames = {}
|
|
354
362
|
}) {
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
(
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
363
|
+
const detectUnit = (name = "") => {
|
|
364
|
+
const lower = name.toLowerCase();
|
|
365
|
+
if (lower.includes("%")) return "%";
|
|
366
|
+
if (lower.includes("venta") || lower.includes("inversi\xF3n")) return currency || "";
|
|
367
|
+
return "";
|
|
368
|
+
};
|
|
369
|
+
const maxY = data.length ? Math.ceil(
|
|
370
|
+
Math.max(
|
|
371
|
+
...lines.map((lineName) => Math.max(...data.map((d) => d[lineName] || 0)))
|
|
372
|
+
) * 1.1
|
|
373
|
+
) : 100;
|
|
374
|
+
return /* @__PURE__ */ React.createElement(import_react_pro9.CCard, { className: "mt-4 rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(import_react_pro9.CCardBody, null, cards.length > 0 && /* @__PURE__ */ React.createElement(import_react_pro9.CRow, { className: "pt-4 g-3 justify-content-center text-center mb-4" }, cards.map((card, index) => /* @__PURE__ */ React.createElement(import_react_pro9.CCol, { xs: 12, md: 4, lg: 5, key: index }, /* @__PURE__ */ React.createElement(
|
|
375
|
+
GeneralCard,
|
|
376
|
+
{
|
|
377
|
+
title: card.title,
|
|
378
|
+
current: card.value,
|
|
379
|
+
previous: card.previous,
|
|
380
|
+
change: card.percentageChange,
|
|
381
|
+
isPositive: card.isPositive,
|
|
382
|
+
unit: card.unit,
|
|
383
|
+
previousDateRange: card.previousDateRange,
|
|
384
|
+
tooltipText: card.title
|
|
385
|
+
}
|
|
386
|
+
)))), /* @__PURE__ */ React.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 340 }, /* @__PURE__ */ React.createElement(import_recharts2.LineChart, { data, margin: { top: 20, right: 30, left: 10, bottom: 10 } }, /* @__PURE__ */ React.createElement(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", stroke: "#e5e5e5" }), /* @__PURE__ */ React.createElement(import_recharts2.XAxis, { dataKey: "date", stroke: "#333", tick: { fontSize: 12 } }), /* @__PURE__ */ React.createElement(
|
|
387
|
+
import_recharts2.YAxis,
|
|
388
|
+
{
|
|
389
|
+
yAxisId: "left",
|
|
390
|
+
stroke: "#333",
|
|
391
|
+
tickFormatter: (val) => `${currency ? currency + " " : ""}${val >= 1e6 ? (val / 1e6).toFixed(1) + "M" : val.toLocaleString("es-CO")}`,
|
|
392
|
+
tick: { fontSize: 12 },
|
|
393
|
+
width: 100,
|
|
394
|
+
domain: [0, maxY],
|
|
395
|
+
allowDecimals: false,
|
|
396
|
+
label: yAxisLabel ? {
|
|
397
|
+
value: yAxisLabel,
|
|
398
|
+
angle: -90,
|
|
399
|
+
position: "insideLeft",
|
|
400
|
+
style: { textAnchor: "middle", fill: "#333", fontSize: 13 }
|
|
401
|
+
} : void 0
|
|
402
|
+
}
|
|
403
|
+
), /* @__PURE__ */ React.createElement(
|
|
404
|
+
import_recharts2.Tooltip,
|
|
405
|
+
{
|
|
406
|
+
formatter: (val, name) => {
|
|
407
|
+
const unit = detectUnit(name);
|
|
408
|
+
return [formatValue(val, unit), displayNames[name] || name];
|
|
409
|
+
},
|
|
410
|
+
labelClassName: "fw-bold",
|
|
411
|
+
wrapperStyle: { zIndex: 1e3 }
|
|
412
|
+
}
|
|
413
|
+
), /* @__PURE__ */ React.createElement(
|
|
414
|
+
import_recharts2.Legend,
|
|
415
|
+
{
|
|
416
|
+
verticalAlign: "bottom",
|
|
417
|
+
height: 36,
|
|
418
|
+
wrapperStyle: { marginTop: 20 },
|
|
419
|
+
iconType: "circle",
|
|
420
|
+
formatter: (value) => displayNames[value] || value
|
|
421
|
+
}
|
|
422
|
+
), lines.map((lineName) => /* @__PURE__ */ React.createElement(
|
|
423
|
+
import_recharts2.Line,
|
|
424
|
+
{
|
|
425
|
+
key: lineName,
|
|
426
|
+
yAxisId: "left",
|
|
427
|
+
type: "monotone",
|
|
428
|
+
dataKey: lineName,
|
|
429
|
+
stroke: colors[lineName] || "#000",
|
|
430
|
+
strokeWidth: 2.5,
|
|
431
|
+
dot: { r: 4 },
|
|
432
|
+
activeDot: { r: 6 }
|
|
433
|
+
}
|
|
434
|
+
))))));
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/components/charts/TopProductsChart.jsx
|
|
438
|
+
var import_recharts3 = require("recharts");
|
|
439
|
+
var import_react_pro10 = require("@coreui/react-pro");
|
|
440
|
+
var COLORS = ["#FF6A8D", "#FF8AAE", "#FFA3BC", "#FFC3D0", "#FFE0E7"];
|
|
441
|
+
var ChartTooltip = ({ active, payload }) => {
|
|
442
|
+
if (active && payload && payload.length) {
|
|
443
|
+
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()));
|
|
362
444
|
}
|
|
363
|
-
|
|
364
|
-
|
|
445
|
+
return null;
|
|
446
|
+
};
|
|
447
|
+
function TopProductsChart({
|
|
448
|
+
data = [],
|
|
449
|
+
title = "Productos M\xE1s Vendidos",
|
|
450
|
+
emptyText = "No se registraron productos vendidos en este rango de fechas.",
|
|
451
|
+
maxItems = 5
|
|
452
|
+
}) {
|
|
453
|
+
const processedData = (data || []).filter((item) => {
|
|
454
|
+
var _a;
|
|
455
|
+
return item.quantity > 0 && ((_a = item.name) == null ? void 0 : _a.trim());
|
|
456
|
+
}).sort((a, b) => b.quantity - a.quantity).slice(0, maxItems).map((item) => ({ name: item.name, quantity: item.quantity }));
|
|
457
|
+
if (!processedData.length) {
|
|
458
|
+
return /* @__PURE__ */ React.createElement(import_react_pro10.CCard, { className: "mt-4 rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(import_react_pro10.CCardBody, { 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)));
|
|
365
459
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
},
|
|
377
|
-
i
|
|
378
|
-
)
|
|
379
|
-
);
|
|
380
|
-
}
|
|
381
|
-
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(
|
|
382
|
-
"button",
|
|
460
|
+
return /* @__PURE__ */ React.createElement(import_react_pro10.CCard, { className: "mt-4 rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(import_react_pro10.CCardBody, 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(import_recharts3.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ React.createElement(
|
|
461
|
+
import_recharts3.BarChart,
|
|
462
|
+
{
|
|
463
|
+
layout: "vertical",
|
|
464
|
+
data: processedData,
|
|
465
|
+
margin: { top: 10, right: 40, left: 20, bottom: 10 }
|
|
466
|
+
},
|
|
467
|
+
/* @__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" }))),
|
|
468
|
+
/* @__PURE__ */ React.createElement(
|
|
469
|
+
import_recharts3.XAxis,
|
|
383
470
|
{
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
),
|
|
390
|
-
|
|
471
|
+
type: "number",
|
|
472
|
+
tickFormatter: (value) => value.toLocaleString(),
|
|
473
|
+
axisLine: false,
|
|
474
|
+
tick: { fontSize: 12 }
|
|
475
|
+
}
|
|
476
|
+
),
|
|
477
|
+
/* @__PURE__ */ React.createElement(
|
|
478
|
+
import_recharts3.YAxis,
|
|
391
479
|
{
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
480
|
+
type: "category",
|
|
481
|
+
dataKey: "name",
|
|
482
|
+
width: 150,
|
|
483
|
+
tick: { fontSize: 13 },
|
|
484
|
+
tickFormatter: (value) => value.length > 30 ? value.substring(0, 30) + "..." : value
|
|
485
|
+
}
|
|
486
|
+
),
|
|
487
|
+
/* @__PURE__ */ React.createElement(import_recharts3.Tooltip, { content: /* @__PURE__ */ React.createElement(ChartTooltip, null) }),
|
|
488
|
+
/* @__PURE__ */ React.createElement(import_recharts3.Bar, { dataKey: "quantity", fill: "url(#barGradient)", radius: [0, 8, 8, 0] }, /* @__PURE__ */ React.createElement(
|
|
489
|
+
import_recharts3.LabelList,
|
|
490
|
+
{
|
|
491
|
+
dataKey: "quantity",
|
|
492
|
+
position: "right",
|
|
493
|
+
formatter: (value) => value.toLocaleString(),
|
|
494
|
+
style: { fill: "#333", fontWeight: 500, fontSize: 12 }
|
|
495
|
+
}
|
|
496
|
+
), processedData.map((_, index) => /* @__PURE__ */ React.createElement(import_recharts3.Cell, { key: `cell-${index}`, fill: COLORS[index % COLORS.length] })))
|
|
497
|
+
)))));
|
|
400
498
|
}
|
|
401
499
|
|
|
402
|
-
// src/components/
|
|
403
|
-
var
|
|
404
|
-
|
|
500
|
+
// src/components/charts/SalesByChannelChart.jsx
|
|
501
|
+
var import_recharts4 = require("recharts");
|
|
502
|
+
var import_react_pro11 = require("@coreui/react-pro");
|
|
503
|
+
function SalesByChannelChart({
|
|
405
504
|
data = [],
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
505
|
+
title = "Ventas por canal",
|
|
506
|
+
emptyText = "Sin datos para este per\xEDodo",
|
|
507
|
+
channels = ["Meta", "TikTok", "Google"],
|
|
508
|
+
channelColors = { Meta: "#FF2F86", TikTok: "#C0C0C0", Google: "#333333" }
|
|
509
|
+
}) {
|
|
510
|
+
const hasData = data.length > 0;
|
|
511
|
+
return /* @__PURE__ */ React.createElement(import_react_pro11.CCard, { className: "rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(import_react_pro11.CCardBody, 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(import_recharts4.ResponsiveContainer, { width: "100%", height: 300 }, /* @__PURE__ */ React.createElement(import_recharts4.BarChart, { data, margin: { top: 20, right: 30, left: 10, bottom: 10 } }, /* @__PURE__ */ React.createElement(import_recharts4.CartesianGrid, { strokeDasharray: "3 3", stroke: "#e5e5e5" }), /* @__PURE__ */ React.createElement(
|
|
512
|
+
import_recharts4.XAxis,
|
|
513
|
+
{
|
|
514
|
+
dataKey: "fecha",
|
|
515
|
+
tick: { fontSize: 12 },
|
|
516
|
+
angle: -45,
|
|
517
|
+
textAnchor: "end",
|
|
518
|
+
interval: Math.ceil(data.length / 10)
|
|
519
|
+
}
|
|
520
|
+
), /* @__PURE__ */ React.createElement(import_recharts4.YAxis, { tick: { fontSize: 12 } }), /* @__PURE__ */ React.createElement(import_recharts4.Tooltip, null), /* @__PURE__ */ React.createElement(import_recharts4.Legend, { verticalAlign: "top", height: 36, iconType: "circle" }), channels.map((channel) => /* @__PURE__ */ React.createElement(
|
|
521
|
+
import_recharts4.Bar,
|
|
522
|
+
{
|
|
523
|
+
key: channel,
|
|
524
|
+
dataKey: channel,
|
|
525
|
+
stackId: "ventas",
|
|
526
|
+
fill: channelColors[channel] || "#888"
|
|
527
|
+
}
|
|
528
|
+
))))));
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// src/components/charts/InvestmentByPlatformChart.jsx
|
|
532
|
+
var import_recharts5 = require("recharts");
|
|
533
|
+
var import_react_pro12 = require("@coreui/react-pro");
|
|
534
|
+
var DEFAULT_COLORS = ["#FF2F86", "#D9D9D9", "#333333"];
|
|
535
|
+
function InvestmentByPlatformChart({
|
|
536
|
+
data = [],
|
|
537
|
+
title = "Inversi\xF3n por plataforma",
|
|
538
|
+
colors = DEFAULT_COLORS,
|
|
539
|
+
currencySymbol = "COP",
|
|
540
|
+
locale = "es-CO"
|
|
413
541
|
}) {
|
|
542
|
+
return /* @__PURE__ */ React.createElement(import_react_pro12.CCard, { className: "rounded-4 shadow-sm p-3" }, /* @__PURE__ */ React.createElement(import_react_pro12.CCardBody, null, /* @__PURE__ */ React.createElement("h5", { className: "text-center fw-bold" }, title), /* @__PURE__ */ React.createElement(import_recharts5.ResponsiveContainer, { width: "100%", height: 280 }, /* @__PURE__ */ React.createElement(import_recharts5.PieChart, null, /* @__PURE__ */ React.createElement(
|
|
543
|
+
import_recharts5.Pie,
|
|
544
|
+
{
|
|
545
|
+
data,
|
|
546
|
+
dataKey: "value",
|
|
547
|
+
nameKey: "name",
|
|
548
|
+
cx: "50%",
|
|
549
|
+
cy: "50%",
|
|
550
|
+
innerRadius: 60,
|
|
551
|
+
outerRadius: 100,
|
|
552
|
+
paddingAngle: 5,
|
|
553
|
+
label: ({ name, percent }) => `${name} ${(percent * 100).toFixed(1)}%`
|
|
554
|
+
},
|
|
555
|
+
data.map((_, index) => /* @__PURE__ */ React.createElement(import_recharts5.Cell, { key: `cell-${index}`, fill: colors[index % colors.length] }))
|
|
556
|
+
), /* @__PURE__ */ React.createElement(
|
|
557
|
+
import_recharts5.Tooltip,
|
|
558
|
+
{
|
|
559
|
+
formatter: (value) => `${currencySymbol} ${value.toLocaleString(locale)}`
|
|
560
|
+
}
|
|
561
|
+
), /* @__PURE__ */ React.createElement(import_recharts5.Legend, { verticalAlign: "bottom", height: 36 })))));
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// src/components/pagination/PaginatedTable.jsx
|
|
565
|
+
var import_react_pro13 = require("@coreui/react-pro");
|
|
566
|
+
function PaginatedTable({ data = [], itemsPerPage = 10, currentPage = 1, setCurrentPage = () => {
|
|
567
|
+
}, columns = [], renderRow = () => null, loading = false, emptyMessage = "No hay datos disponibles." }) {
|
|
414
568
|
const totalPages = Math.ceil(data.length / itemsPerPage);
|
|
415
|
-
const paginatedData = data.slice(
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
);
|
|
419
|
-
if (loading) {
|
|
420
|
-
return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5" }, /* @__PURE__ */ React.createElement(import_react_pro8.CSpinner, { color: "secondary" }));
|
|
421
|
-
}
|
|
422
|
-
if (!data.length) {
|
|
423
|
-
return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5 text-muted" }, emptyMessage);
|
|
424
|
-
}
|
|
569
|
+
const paginatedData = data.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
|
|
570
|
+
if (loading) return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5" }, /* @__PURE__ */ React.createElement(import_react_pro13.CSpinner, { color: "secondary" }));
|
|
571
|
+
if (!data.length) return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5 text-muted" }, emptyMessage);
|
|
425
572
|
const renderPagination = () => {
|
|
426
|
-
const pages =
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
onClick: () => setCurrentPage(currentPage - 1),
|
|
444
|
-
className: "px-3 py-1 rounded-pill border bg-white text-dark"
|
|
445
|
-
},
|
|
446
|
-
"Anterior"
|
|
447
|
-
), pages, currentPage < totalPages && /* @__PURE__ */ React.createElement(
|
|
448
|
-
"button",
|
|
449
|
-
{
|
|
450
|
-
onClick: () => setCurrentPage(currentPage + 1),
|
|
451
|
-
className: "px-3 py-1 rounded-pill border bg-white text-dark"
|
|
452
|
-
},
|
|
453
|
-
"Siguiente"
|
|
454
|
-
));
|
|
573
|
+
const pages = Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
574
|
+
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"));
|
|
575
|
+
};
|
|
576
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(import_react_pro13.CTable, { hover: true, responsive: true }, /* @__PURE__ */ React.createElement(import_react_pro13.CTableHead, { className: "bg-dark text-white" }, /* @__PURE__ */ React.createElement(import_react_pro13.CTableRow, null, columns.map((col, i) => /* @__PURE__ */ React.createElement(import_react_pro13.CTableHeaderCell, { key: i }, col)))), /* @__PURE__ */ React.createElement(import_react_pro13.CTableBody, null, paginatedData.map(renderRow))), totalPages > 1 && renderPagination());
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// src/components/pagination/PaginatedGrid.jsx
|
|
580
|
+
var import_react_pro14 = require("@coreui/react-pro");
|
|
581
|
+
function PaginatedGrid({ data = [], itemsPerPage = 6, currentPage = 1, setCurrentPage = () => {
|
|
582
|
+
}, renderItem = () => null, loading = false, emptyMessage = "No hay elementos." }) {
|
|
583
|
+
const totalPages = Math.ceil(data.length / itemsPerPage);
|
|
584
|
+
const paginatedData = data.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
|
|
585
|
+
if (loading) return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5" }, /* @__PURE__ */ React.createElement(import_react_pro14.CSpinner, { color: "secondary" }));
|
|
586
|
+
if (!data.length) return /* @__PURE__ */ React.createElement("div", { className: "text-center py-5 text-muted" }, emptyMessage);
|
|
587
|
+
const renderPagination = () => {
|
|
588
|
+
const pages = Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
589
|
+
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"));
|
|
455
590
|
};
|
|
456
591
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "row g-4" }, paginatedData.map(renderItem)), totalPages > 1 && renderPagination());
|
|
457
592
|
}
|
|
458
593
|
|
|
459
594
|
// src/components/skeletons/CardSkeleton.jsx
|
|
460
|
-
var
|
|
595
|
+
var import_react_pro15 = require("@coreui/react-pro");
|
|
461
596
|
function CardSkeleton() {
|
|
462
|
-
return /* @__PURE__ */ React.createElement(
|
|
597
|
+
return /* @__PURE__ */ React.createElement(import_react_pro15.CCard, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(import_react_pro15.CPlaceholder, { component: "div", animation: "glow", className: "d-flex flex-column gap-2 bg-transparent" }, /* @__PURE__ */ React.createElement(import_react_pro15.CPlaceholder, { className: "p-4 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" })));
|
|
463
598
|
}
|
|
464
599
|
|
|
465
600
|
// src/components/skeletons/TextSkeleton.jsx
|
|
466
|
-
var
|
|
601
|
+
var import_react_pro16 = require("@coreui/react-pro");
|
|
467
602
|
function TextSkeleton() {
|
|
468
|
-
return /* @__PURE__ */ React.createElement(
|
|
603
|
+
return /* @__PURE__ */ React.createElement(import_react_pro16.CCard, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(import_react_pro16.CPlaceholder, { component: "div", animation: "glow", className: "d-flex flex-column gap-2 bg-transparent" }, /* @__PURE__ */ React.createElement(import_react_pro16.CPlaceholder, { className: "p-0 my-2 rounded-1", size: "lg", xs: 8, color: "skeleton" })));
|
|
469
604
|
}
|
|
470
605
|
|
|
471
606
|
// src/components/skeletons/MetricsSkeleton.jsx
|
|
472
|
-
var
|
|
607
|
+
var import_react_pro17 = require("@coreui/react-pro");
|
|
473
608
|
function MetricsSkeleton() {
|
|
474
|
-
return /* @__PURE__ */ React.createElement(
|
|
609
|
+
return /* @__PURE__ */ React.createElement(import_react_pro17.CCard, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(import_react_pro17.CPlaceholder, { component: "div", animation: "glow", className: "d-flex flex-column gap-2 bg-transparent" }, /* @__PURE__ */ React.createElement(import_react_pro17.CPlaceholder, { className: "p-5 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" }), /* @__PURE__ */ React.createElement(import_react_pro17.CPlaceholder, { className: "p-3 mt-2 rounded-1", size: "xs", xs: 12, color: "skeleton" })));
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// src/components/skeletons/ReportTableSkeleton.jsx
|
|
613
|
+
var import_react_pro18 = require("@coreui/react-pro");
|
|
614
|
+
function ReportTableSkeleton() {
|
|
615
|
+
return /* @__PURE__ */ React.createElement(import_react_pro18.CCard, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(
|
|
616
|
+
import_react_pro18.CPlaceholder,
|
|
617
|
+
{
|
|
618
|
+
component: "div",
|
|
619
|
+
animation: "glow",
|
|
620
|
+
className: "d-flex flex-column gap-2 bg-transparent"
|
|
621
|
+
},
|
|
622
|
+
/* @__PURE__ */ React.createElement(import_react_pro18.CPlaceholder, { className: "p-4 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" }),
|
|
623
|
+
/* @__PURE__ */ React.createElement(import_react_pro18.CPlaceholder, { className: "p-5 mt-2 rounded-1", size: "lg", xs: 12, color: "skeleton" })
|
|
624
|
+
));
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// src/components/skeletons/SummaryReportSkeleton.jsx
|
|
628
|
+
var import_react_pro19 = require("@coreui/react-pro");
|
|
629
|
+
var CardPlaceholder = ({ className = "" }) => /* @__PURE__ */ React.createElement(import_react_pro19.CCard, { className: "shadow-none p-0 m-0 bg-transparent border-0" }, /* @__PURE__ */ React.createElement(
|
|
630
|
+
import_react_pro19.CPlaceholder,
|
|
631
|
+
{
|
|
632
|
+
component: "div",
|
|
633
|
+
animation: "glow",
|
|
634
|
+
className: `d-flex flex-column gap-2 bg-transparent ${className}`
|
|
635
|
+
},
|
|
636
|
+
/* @__PURE__ */ React.createElement(import_react_pro19.CPlaceholder, { className: "p-4 mt-2 rounded-2", size: "lg", xs: 12, color: "skeleton" })
|
|
637
|
+
));
|
|
638
|
+
function SummaryReportSkeleton({
|
|
639
|
+
layout = [
|
|
640
|
+
{ sm: 6, md: 6 },
|
|
641
|
+
{ sm: 6, md: 6 },
|
|
642
|
+
{ sm: 6, md: 4 },
|
|
643
|
+
{ sm: 6, md: 4 },
|
|
644
|
+
{ sm: 6, md: 4 },
|
|
645
|
+
{ sm: 6, md: 6 },
|
|
646
|
+
{ sm: 6, md: 4 },
|
|
647
|
+
{ sm: 6, md: 2 }
|
|
648
|
+
]
|
|
649
|
+
}) {
|
|
650
|
+
return /* @__PURE__ */ React.createElement(import_react_pro19.CRow, { className: "g-md-3 px-4 px-sm-2 g-sm-2 pt-2 pb-4" }, layout.map((col, index) => /* @__PURE__ */ React.createElement(import_react_pro19.CCol, { sm: col.sm, md: col.md, key: index }, /* @__PURE__ */ React.createElement(CardPlaceholder, null))));
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// ../../node_modules/@coreui/icons-pro/dist/esm/duotone/cid-exclamation-circle.js
|
|
654
|
+
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'/>"];
|
|
655
|
+
|
|
656
|
+
// src/components/feedback/NoDataMessage.jsx
|
|
657
|
+
var import_icons_react8 = __toESM(require("@coreui/icons-react"));
|
|
658
|
+
function NoDataMessage({
|
|
659
|
+
message = "No se obtuvieron datos. Revisa el rango de fechas y la integraci\xF3n."
|
|
660
|
+
}) {
|
|
661
|
+
return /* @__PURE__ */ React.createElement(
|
|
662
|
+
"div",
|
|
663
|
+
{
|
|
664
|
+
className: "d-flex align-items-center gap-2 rounded-3 px-3 py-3 mt-3 mb-3",
|
|
665
|
+
style: {
|
|
666
|
+
backgroundColor: "var(--cui-warning-bg-subtle)",
|
|
667
|
+
border: "1px solid var(--cui-warning)",
|
|
668
|
+
color: "var(--cui-body-color)"
|
|
669
|
+
}
|
|
670
|
+
},
|
|
671
|
+
/* @__PURE__ */ React.createElement(
|
|
672
|
+
import_icons_react8.default,
|
|
673
|
+
{
|
|
674
|
+
icon: cidExclamationCircle,
|
|
675
|
+
className: "flex-shrink-0 me-2 text-warning",
|
|
676
|
+
size: "xxl"
|
|
677
|
+
}
|
|
678
|
+
),
|
|
679
|
+
message
|
|
680
|
+
);
|
|
475
681
|
}
|
|
476
682
|
|
|
477
683
|
// src/components/back-button/BackButton.jsx
|
|
478
684
|
var import_navigation = require("next/navigation");
|
|
479
|
-
var
|
|
480
|
-
var
|
|
685
|
+
var import_react_pro20 = require("@coreui/react-pro");
|
|
686
|
+
var import_icons4 = require("@coreui/icons");
|
|
687
|
+
var import_icons_react9 = __toESM(require("@coreui/icons-react"));
|
|
481
688
|
function BackButton({ title, color = "dark", className = "", path }) {
|
|
482
689
|
const { back, push } = (0, import_navigation.useRouter)();
|
|
483
|
-
|
|
484
|
-
function handleBack() {
|
|
485
|
-
if (path) push(path);
|
|
486
|
-
else back();
|
|
487
|
-
}
|
|
488
|
-
return /* @__PURE__ */ React.createElement(CustomTooltip, { content: "Volver atr\xE1s", placement: "bottom" }, /* @__PURE__ */ React.createElement(import_react_pro12.CButton, { color, variant: "ghost", className: buttonClasses, onClick: handleBack }, /* @__PURE__ */ React.createElement(import_icons_react7.default, { icon: cilArrowLeft, size: "lg", className: "mx-1" }), title && /* @__PURE__ */ React.createElement("span", { className: "px-2" }, title)));
|
|
690
|
+
return /* @__PURE__ */ React.createElement(CustomTooltip, { content: "Volver atr\xE1s", placement: "bottom" }, /* @__PURE__ */ React.createElement(import_react_pro20.CButton, { color, variant: "ghost", className: `back-button d-flex align-items-center px-0 ${className}`, onClick: () => path ? push(path) : back() }, /* @__PURE__ */ React.createElement(import_icons_react9.default, { icon: import_icons4.cilArrowLeft, size: "lg", className: "mx-1" }), title && /* @__PURE__ */ React.createElement("span", { className: "px-2" }, title)));
|
|
489
691
|
}
|
|
490
692
|
// Annotate the CommonJS export names for ESM import in node:
|
|
491
693
|
0 && (module.exports = {
|
|
492
694
|
BackButton,
|
|
493
695
|
CardSkeleton,
|
|
494
696
|
CustomTooltip,
|
|
697
|
+
FunnelChart,
|
|
698
|
+
GeneralCard,
|
|
495
699
|
IconButton,
|
|
700
|
+
InvestmentByPlatformChart,
|
|
496
701
|
MetricCard,
|
|
497
702
|
MetricsSkeleton,
|
|
498
703
|
Modal,
|
|
704
|
+
NoDataMessage,
|
|
499
705
|
OutlineButton,
|
|
500
706
|
PaginatedGrid,
|
|
501
707
|
PaginatedTable,
|
|
708
|
+
ReportTableSkeleton,
|
|
709
|
+
SalesByChannelChart,
|
|
502
710
|
SolidButton,
|
|
711
|
+
SummaryReportSkeleton,
|
|
503
712
|
TextButton,
|
|
504
713
|
TextSkeleton,
|
|
714
|
+
TimeSeriesComparisonChart,
|
|
715
|
+
TopProductsChart,
|
|
505
716
|
formatDateRange,
|
|
506
717
|
formatValue,
|
|
507
718
|
getBadgeStyles
|