frontend-plus-react 0.1.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.js ADDED
@@ -0,0 +1,3393 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // node_modules/json4all/json4all.js
28
+ var require_json4all = __commonJS({
29
+ "node_modules/json4all/json4all.js"(exports, module) {
30
+ "use strict";
31
+ (function codenautasModuleDefinition(root, name, factory) {
32
+ if (typeof root.globalModuleName !== "string") {
33
+ root.globalModuleName = name;
34
+ }
35
+ if (typeof exports === "object" && typeof module === "object") {
36
+ module.exports = factory();
37
+ } else if (typeof define === "function" && define.amd) {
38
+ define(factory);
39
+ } else if (typeof exports === "object") {
40
+ exports[root.globalModuleName] = factory();
41
+ } else {
42
+ root[root.globalModuleName] = factory();
43
+ }
44
+ root.globalModuleName = null;
45
+ })(
46
+ /*jshint -W040 */
47
+ exports,
48
+ "json4all",
49
+ function() {
50
+ var json4all = {};
51
+ json4all.PretendedClass = Symbol("Pretended Class");
52
+ function functionName(fun) {
53
+ if ("name" in fun) {
54
+ return fun.name;
55
+ } else {
56
+ return fun.toString().replace(/^\s*function\s*([^(]*)\((.|\s)*$/i, "$1");
57
+ }
58
+ }
59
+ function constructorName(obj) {
60
+ return functionName(obj[json4all.PretendedClass] || obj.constructor);
61
+ }
62
+ var root;
63
+ if (typeof window !== "undefined") {
64
+ root = window;
65
+ } else {
66
+ root = global;
67
+ }
68
+ root.json4allRegisteredTypes = root.json4allRegisteredTypes || {};
69
+ var types = root.json4allRegisteredTypes;
70
+ var thisPlatformSkipsUndefinedInArrays = true;
71
+ JSON.stringify([void 0], function(key, value) {
72
+ if (key === "0" || key === 0) {
73
+ thisPlatformSkipsUndefinedInArrays = false;
74
+ }
75
+ return value;
76
+ });
77
+ var thisPlatformHasReplacerBug = false;
78
+ JSON.parse('{"3":"33"}', function(key, value) {
79
+ if (value === void 0) {
80
+ thisPlatformHasReplacerBug = true;
81
+ }
82
+ return value;
83
+ });
84
+ function InternalValueForUndefined() {
85
+ throw new Error("this is not a function");
86
+ }
87
+ function InternalValueForUnset() {
88
+ throw new Error("this is not a function");
89
+ }
90
+ json4all.directTypes = {
91
+ "Object": true,
92
+ "Array": true,
93
+ "anonymous": true,
94
+ "": true
95
+ };
96
+ json4all.anonymizate = function(classedObject) {
97
+ var plainObject = {};
98
+ for (var attr in classedObject) {
99
+ plainObject[attr] = classedObject[attr];
100
+ }
101
+ return plainObject;
102
+ };
103
+ json4all.nonymizate = function(plainValue, Constructor) {
104
+ var typedValue = new Constructor();
105
+ for (var attr in plainValue) {
106
+ typedValue[attr] = plainValue[attr];
107
+ }
108
+ return typedValue;
109
+ };
110
+ json4all.replacer = function replacer(key, value) {
111
+ var realValue = this[key];
112
+ if (realValue === InternalValueForUndefined) {
113
+ this[key] = void 0;
114
+ return { $special: "undefined" };
115
+ }
116
+ if (key !== "" && (!(key in this) || realValue !== null && realValue instanceof Function)) {
117
+ return { $special: "unset" };
118
+ }
119
+ if (realValue === void 0 || typeof realValue === "undefined" || realValue !== null && realValue instanceof Function) {
120
+ return { $special: "undefined" };
121
+ }
122
+ if (realValue === null || typeof realValue !== "object" || key === "$escape") {
123
+ return value;
124
+ }
125
+ if ("$special" in realValue || "$escape" in realValue) {
126
+ return { $escape: realValue };
127
+ }
128
+ if (thisPlatformSkipsUndefinedInArrays && realValue instanceof Array) {
129
+ for (var i = 0; i < realValue.length; i++) {
130
+ if (typeof realValue[i] === "undefined") {
131
+ realValue[i] = InternalValueForUndefined;
132
+ }
133
+ }
134
+ return realValue;
135
+ }
136
+ var typeName = constructorName(realValue);
137
+ if (json4all.directTypes[typeName]) {
138
+ return value;
139
+ } else {
140
+ var typeDef = types[typeName];
141
+ if (typeDef) {
142
+ var replaced = { $special: typeDef.specialTag(realValue), $value: typeDef.deconstruct(realValue) };
143
+ var ref = realValue[RefKey];
144
+ if (ref !== void 0) {
145
+ replaced.$ref = ref;
146
+ if (json4all.$RefStoreSpace == null) {
147
+ delete replaced.$value;
148
+ }
149
+ }
150
+ return replaced;
151
+ } else {
152
+ console.log("JSON4all.stringify unregistered object type", typeName);
153
+ throw new Error("JSON4all.stringify unregistered object type");
154
+ }
155
+ }
156
+ };
157
+ json4all.reviver = function reviver(key, plainValue) {
158
+ var log = false;
159
+ var result;
160
+ if (key === "$escape") {
161
+ return plainValue;
162
+ } else if (plainValue !== null && plainValue.$ref && json4all.$RefStoreSpace) {
163
+ var collection = json4all.$RefStoreSpace[plainValue.$ref[0][0]];
164
+ if (!collection) {
165
+ throw new Error("json4all ref collection invalid");
166
+ }
167
+ var object2 = collection[plainValue.$ref[1]];
168
+ if (!object2) {
169
+ throw new Error("json4all ref key invalid");
170
+ }
171
+ return object2;
172
+ } else if (plainValue !== null && plainValue.$special) {
173
+ if (plainValue.$special === "undefined") {
174
+ if (key === "") {
175
+ return void 0;
176
+ }
177
+ return InternalValueForUndefined;
178
+ } else if (plainValue.$special === "unset") {
179
+ return void 0;
180
+ } else {
181
+ var typeDef = types[plainValue.$special];
182
+ if (typeDef) {
183
+ result = new typeDef.construct(plainValue.$value, typeDef.constructor);
184
+ } else {
185
+ console.log("JSON4all.parse invalid $special", plainValue.$special);
186
+ throw new Error("JSON4all.parse invalid $special");
187
+ }
188
+ }
189
+ } else if (plainValue !== null && plainValue.$escape) {
190
+ return plainValue.$escape;
191
+ } else {
192
+ result = plainValue;
193
+ if (plainValue instanceof Object) {
194
+ for (var k in plainValue) {
195
+ if (plainValue[k] === InternalValueForUndefined) {
196
+ plainValue[k] = void 0;
197
+ }
198
+ }
199
+ }
200
+ }
201
+ if (plainValue != null && plainValue.$ref) {
202
+ result[RefKey] = plainValue.$ref;
203
+ }
204
+ return result;
205
+ };
206
+ var directRegExp = /^((null|true|false)$|[-\]\[{}".0-9])/;
207
+ var directStringRegExp = /^[a-zA-ZÑñáéíóúüÁÉÍÓÚÜ_@-][0-9a-zA-ZÑñáéíóúüÁÉÍÓÚÜ_@-]{0,32}$/;
208
+ var AttributeNameRegExp = /^[a-zA-ZÑñáéíóúüÁÉÍÓÚÜ_@-][0-9a-zA-ZÑñáéíóúüÁÉÍÓÚÜ_@-]*($|,)/;
209
+ json4all.stringifyAnyPlace = function stringifyAnyPlace(value) {
210
+ return JSON.stringify(value, json4all.replacer);
211
+ };
212
+ var CHANNEL = {
213
+ object: { separator: ",", pairSeparator: ":", empty: function() {
214
+ return {};
215
+ } },
216
+ array: { separator: ";", pairSeparator: null, empty: function() {
217
+ return [];
218
+ } }
219
+ };
220
+ var SEPARATOR = { ",": "object", ";": "array" };
221
+ function maxConsumer() {
222
+ var fun = function(node) {
223
+ for (var channel2 in CHANNEL) {
224
+ if (node[channel2] > fun[channel2]) fun[channel2] = node[channel2];
225
+ }
226
+ return node.value;
227
+ };
228
+ for (var channel in CHANNEL) {
229
+ fun[channel] = null;
230
+ }
231
+ return fun;
232
+ }
233
+ function simpleValue(value) {
234
+ return { value, object: 0, array: 0 };
235
+ }
236
+ json4all.maxConsumer = maxConsumer;
237
+ json4all.mesureString = function mesureString(value) {
238
+ var currentSeparator = null;
239
+ var currentLength = 0;
240
+ var result = simpleValue(value);
241
+ for (var char of value) {
242
+ var channel = SEPARATOR[char];
243
+ if (channel) {
244
+ if (currentSeparator != char) {
245
+ currentLength = 0;
246
+ currentSeparator = char;
247
+ }
248
+ currentLength++;
249
+ if (currentLength > result[channel]) result[channel] = currentLength;
250
+ } else {
251
+ currentSeparator = null;
252
+ }
253
+ }
254
+ return result;
255
+ };
256
+ json4all.quoteString = function quoteString(text, escapeColon) {
257
+ var value = directStringRegExp.test(text) && !directRegExp.test(text) ? text : JSON.stringify(text);
258
+ if (escapeColon) value = value.replace(/:/g, "\\u003a");
259
+ return json4all.mesureString(value);
260
+ };
261
+ var STAR = "*";
262
+ var BANG = "!";
263
+ json4all.toUrl = function toUrl(value) {
264
+ return json4all.toUrlConstruct(value).value;
265
+ };
266
+ json4all.toUrlLines = function toUrlLines(value, eol) {
267
+ return json4all.toUrlConstruct(value, eol ? eol : "\n").value;
268
+ };
269
+ var repeat = (str, count) => Array.prototype.concat(new Array(count + 1)).join(str);
270
+ json4all.toUrlConstruct = function toUrlConstruct(value, addEol) {
271
+ if (value === null) return simpleValue("null");
272
+ if (value === void 0) return simpleValue("!undefined");
273
+ if (value instanceof Function) return simpleValue("!unset");
274
+ var typeName = constructorName(value);
275
+ if (typeof value === "string") {
276
+ return json4all.quoteString(value);
277
+ } else if (value && typeof value === "object" && !value[RefKey]) {
278
+ if (!json4all.directTypes[typeName]) {
279
+ var typeDef = types[typeName];
280
+ if (typeDef) {
281
+ var serializedValue = typeDef.serialize(value);
282
+ if (typeof serializedValue === "string") return json4all.mesureString(serializedValue);
283
+ return serializedValue;
284
+ } else {
285
+ console.log("JSON4all.stringify unregistered object type", typeName);
286
+ throw new Error("JSON4all.stringify unregistered object type");
287
+ }
288
+ } else {
289
+ var thisChannel = value instanceof Array ? "array" : "object";
290
+ var parts = [];
291
+ var result = simpleValue(null);
292
+ var cantSimplify = false;
293
+ var max = maxConsumer();
294
+ if (thisChannel == "array") {
295
+ for (var i = 0; i < value.length; i++) {
296
+ var pair = [max(json4all.toUrlConstruct(value[i]))];
297
+ parts.push(pair);
298
+ }
299
+ } else {
300
+ for (var attr in value) {
301
+ var pair = [max(json4all.quoteString(attr, true)), max(json4all.toUrlConstruct(value[attr]))];
302
+ parts.push(pair);
303
+ }
304
+ }
305
+ for (var channel in CHANNEL) {
306
+ result[channel] = (max[channel] || 0) + (channel == thisChannel ? 1 : 0);
307
+ }
308
+ var PairSep = ":";
309
+ var lengthSep = result[thisChannel];
310
+ var ListSep = addEol ? addEol : repeat(CHANNEL[thisChannel].separator, lengthSep);
311
+ result.value = (addEol ? "!json4all" + CHANNEL[thisChannel].separator : "") + ListSep + parts.map((pair2) => pair2.join(PairSep)).join(ListSep);
312
+ if (!cantSimplify && parts.length) {
313
+ return result;
314
+ }
315
+ }
316
+ }
317
+ return json4all.mesureString(JSON.stringify(value, json4all.replacer));
318
+ };
319
+ json4all.stringify = json4all.stringifyAnyPlace;
320
+ json4all.convertPlain2$special = function convertPlain2$special(o, internally) {
321
+ if (o != null && o instanceof Object) {
322
+ for (var key in o) {
323
+ var realKey = o[key] === void 0 && !isNaN(key) ? Number(key) : key;
324
+ json4all.convertPlain2$special(o[key], true);
325
+ var newValue = json4all.reviver(key, o[key]);
326
+ if (newValue === void 0 && !(o instanceof Array)) {
327
+ delete o[key];
328
+ } else {
329
+ o[key] = newValue;
330
+ }
331
+ }
332
+ }
333
+ if (!internally) {
334
+ return json4all.reviver("", o);
335
+ }
336
+ };
337
+ json4all.isTesting = true;
338
+ json4all.getPlainObject = function getPlainObject(payload, separator, initial, PairSep) {
339
+ var i = 0;
340
+ if (separator instanceof RegExp) {
341
+ var ListSep = separator;
342
+ } else {
343
+ var ListSep = "";
344
+ while (i < payload.length && payload[i] === separator) {
345
+ i++;
346
+ ListSep += separator;
347
+ }
348
+ }
349
+ var result = initial;
350
+ var parts = payload.split(ListSep).slice(1);
351
+ var index = -1;
352
+ for (var part of parts) {
353
+ if (PairSep) {
354
+ var pos = part.indexOf(PairSep);
355
+ if (pos < 0) {
356
+ throw new Error('JSON4all.parse error. Lack of colon "' + PairSep + '" in object');
357
+ }
358
+ var value = part.substr(pos + PairSep.length);
359
+ var index = json4all.parse(part.substr(0, pos));
360
+ } else {
361
+ var value = part;
362
+ index++;
363
+ }
364
+ var value = json4all.parse(value, true);
365
+ if (value !== InternalValueForUnset) {
366
+ result[index] = value;
367
+ }
368
+ }
369
+ return result;
370
+ };
371
+ json4all.parse = function parse2(text, inner) {
372
+ var payload = text[0] === STAR ? text.substr(1) : text;
373
+ if (payload[0] === BANG) {
374
+ payload = payload.substr(1);
375
+ if (payload === "undefined") return void 0;
376
+ if (payload === "unset") {
377
+ return inner ? InternalValueForUnset : void 0;
378
+ }
379
+ if (payload[0] == "@") {
380
+ var commaPosition = payload.indexOf(",");
381
+ var className = payload.substr(1, commaPosition - 1);
382
+ var typeDef = types[className];
383
+ if (!typeDef) {
384
+ throw new Error("JSON4all.parse unrecognize className " + className);
385
+ }
386
+ return typeDef.deserialize(payload).value;
387
+ }
388
+ if (payload[0] == "/") {
389
+ var typeDef = types.RegExp;
390
+ return typeDef.deserialize(payload).value;
391
+ }
392
+ if (payload.substr(0, 8) == "json4all") {
393
+ var iSeparator = SEPARATOR[payload[8]];
394
+ if (iSeparator) {
395
+ var channel = CHANNEL[iSeparator];
396
+ if (channel) {
397
+ var eol = payload[9] == "\r" && payload[10] == "\n" ? "\r\n" : payload[9] == "\n" ? "\n" : null;
398
+ if (eol) {
399
+ return json4all.getPlainObject(payload.substr(8 + eol.length), /\r?\n/, channel.empty(), channel.pairSeparator);
400
+ }
401
+ }
402
+ }
403
+ }
404
+ throw new Error("JSON4all.parse unrecognize ! token");
405
+ }
406
+ if (SEPARATOR[payload[0]]) {
407
+ var channel = CHANNEL[SEPARATOR[payload[0]]];
408
+ return json4all.getPlainObject(payload, channel.separator, channel.empty(), channel.pairSeparator);
409
+ }
410
+ for (var typeName in types) {
411
+ var typeDef = types[typeName];
412
+ var okDetected = null;
413
+ if (!typeDef.deserialize) {
414
+ throw new Error("JSON4all.parse type without deserialize: " + typeName);
415
+ }
416
+ var valueOk = null;
417
+ var { ok, value } = typeDef.deserialize(payload);
418
+ if (ok) {
419
+ valueOk = value;
420
+ if (json4all.isTesting) {
421
+ if (okDetected) {
422
+ console.log("More than one way", typeName, okDetected, text, value, valueOk);
423
+ throw Error("");
424
+ }
425
+ okDetected = typeName;
426
+ }
427
+ break;
428
+ }
429
+ }
430
+ if (okDetected) return valueOk;
431
+ if (typeof text === "string" && !directRegExp.test(text)) {
432
+ return text;
433
+ }
434
+ if (thisPlatformHasReplacerBug) {
435
+ var parsed = JSON.parse(text);
436
+ return json4all.convertPlain2$special(parsed);
437
+ } else {
438
+ return JSON.parse(text, json4all.reviver);
439
+ }
440
+ };
441
+ json4all.addType = function addType(typeConstructor, functions, skipIfExists) {
442
+ functions = functions || {};
443
+ var constructorName2 = typeof typeConstructor === "string" ? typeConstructor : functionName(typeConstructor);
444
+ if (skipIfExists && types[constructorName2]) {
445
+ return;
446
+ }
447
+ var prefix = "@" + constructorName2;
448
+ types[constructorName2] = {
449
+ construct: functions.construct || function construct(plainValue, constructor2) {
450
+ return typeConstructor.JSON4reviver(plainValue, constructor2);
451
+ },
452
+ deconstruct: functions.deconstruct || function deconstruct(o) {
453
+ return o.JSON4replacer();
454
+ },
455
+ specialTag: functions.specialTag || function specialTag(value) {
456
+ return constructorName2;
457
+ },
458
+ serialize: functions.serialize || function serialize(o) {
459
+ var plainObject = "JSON4replacer" in typeConstructor.prototype ? o.JSON4replacer() : functions.deconstruct(o);
460
+ var result = json4all.toUrlConstruct(plainObject);
461
+ result.value = BANG + prefix + result.value;
462
+ return result;
463
+ },
464
+ deserialize: functions.deserialize || function deserialize(plainValue) {
465
+ if (plainValue.startsWith(prefix + ",")) {
466
+ var plainObject = json4all.parse(STAR + plainValue.substr(prefix.length), constructor);
467
+ return {
468
+ ok: true,
469
+ value: "JSON4replacer" in typeConstructor.prototype ? typeConstructor.JSON4reviver(plainObject, typeConstructor) : functions.construct(plainObject, typeConstructor)
470
+ };
471
+ }
472
+ return { ok: false };
473
+ },
474
+ valueLike: functions.valueLike || typeConstructor.JSON4valueLike
475
+ };
476
+ if (typeof typeConstructor === "function") {
477
+ types[constructorName2].constructor = typeConstructor;
478
+ }
479
+ };
480
+ var NativeDateRegExp = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d*)?Z$/;
481
+ json4all.DateFunctions = {
482
+ construct: function construct(plainValue) {
483
+ return new Date(plainValue);
484
+ },
485
+ deconstruct: function deconstruct(o) {
486
+ return o.getTime();
487
+ },
488
+ serialize: function serialize(o) {
489
+ return o.toISOString();
490
+ },
491
+ deserialize: function deserialize(plainValue) {
492
+ var ok = NativeDateRegExp.test(plainValue);
493
+ var value = ok && new Date(plainValue) || null;
494
+ return { ok, value };
495
+ },
496
+ valueLike: true
497
+ };
498
+ json4all.addType(Date, json4all.DateFunctions, true);
499
+ json4all.addType(RegExp, {
500
+ construct: function construct(plainValue) {
501
+ return new RegExp(plainValue.source, plainValue.flags);
502
+ },
503
+ deconstruct: function deconstruct(o) {
504
+ return { source: o.source, flags: o.toString().substr(o.toString().lastIndexOf("/") + 1) };
505
+ },
506
+ serialize: function serialize(o) {
507
+ return BANG + "/" + o.source + "/" + o.flags;
508
+ },
509
+ deserialize: function deserialize(plainValue) {
510
+ var ok = false;
511
+ var value = null;
512
+ plainValue.replace(/^\/(.+)\/(\w*)$/, function(_, pattern, flags) {
513
+ value = new RegExp(pattern, flags);
514
+ ok = true;
515
+ });
516
+ return { ok, value };
517
+ },
518
+ valueLike: true
519
+ });
520
+ json4all._types = types;
521
+ const RefKey = Symbol("RefKey for RefMap");
522
+ json4all.RefKey = RefKey;
523
+ json4all.RefStoreSpace = (myCollection) => {
524
+ json4all.$RefStoreSpace = myCollection;
525
+ };
526
+ json4all.RefStore = (path) => {
527
+ var myCollection = json4all.$RefStoreSpace;
528
+ var o = {};
529
+ var p = new Proxy(o, {
530
+ /*
531
+ get:function(target, prop, _receiver) {
532
+ return target[prop];
533
+ },
534
+ */
535
+ /** @param {Partial<{[key in K]:V}>} target */
536
+ /** @param {K} prop */
537
+ /** @param {V} value */
538
+ set: function(target, prop, value) {
539
+ if (
540
+ // @ts-expect-error RefKey no está en el tipo original
541
+ value[RefKey] == null
542
+ ) {
543
+ value[RefKey] = [path, prop];
544
+ } else if (
545
+ // @ts-expect-error RefKey no está en el tipo original
546
+ value[RefKey][1] != prop
547
+ ) {
548
+ console.log("This value was stored in another place", path, prop);
549
+ throw new Error("This value was stored in another place");
550
+ }
551
+ return Reflect.set(target, prop, value);
552
+ }
553
+ });
554
+ myCollection[path[0]] = p;
555
+ return p;
556
+ };
557
+ json4all.$props2serialize = Symbol("props2serialize");
558
+ json4all.addProperty = function(constructorPosition) {
559
+ var innerFunction = (classPrototype, prop, index) => {
560
+ if (!(json4all.$props2serialize in classPrototype)) {
561
+ classPrototype[json4all.$props2serialize] = [];
562
+ }
563
+ var info = { name: prop };
564
+ if (typeof constructorPosition === "number") info.construct = constructorPosition;
565
+ classPrototype[json4all.$props2serialize].push(info);
566
+ };
567
+ if (typeof constructorPosition === "number") {
568
+ return innerFunction;
569
+ } else {
570
+ return innerFunction.apply(null, arguments);
571
+ }
572
+ };
573
+ json4all.pretendClass = function(object2, Constructor) {
574
+ object2[json4all.PretendedClass] = Constructor;
575
+ object2.JSON4replacer = Constructor.prototype.JSON4replacer;
576
+ };
577
+ json4all.addClass = (constructor2) => {
578
+ if (!(json4all.$props2serialize in constructor2.prototype)) {
579
+ throw new Error("must add parameters or properties");
580
+ }
581
+ var propList = constructor2.prototype[json4all.$props2serialize];
582
+ constructor2.prototype.JSON4replacer = function() {
583
+ var o = {};
584
+ for (var prop of propList) {
585
+ o[prop.name] = this[prop.name];
586
+ }
587
+ return o;
588
+ };
589
+ constructor2.JSON4reviver = function(value, constructor3) {
590
+ var constructParams = propList.filter((p2) => p2.construct != null).map((p2) => value[p2.name]);
591
+ var o = new constructor3(...constructParams);
592
+ for (var p of propList) {
593
+ if (!p.construct) {
594
+ o[p.name] = value[p.name];
595
+ }
596
+ }
597
+ return o;
598
+ };
599
+ json4all.addType(constructor2);
600
+ };
601
+ return json4all;
602
+ }
603
+ );
604
+ }
605
+ });
606
+
607
+ // src/components/grid/GenericDataGrid.tsx
608
+ import { useState as useState4, useEffect, useCallback as useCallback4, useMemo as useMemo2, useRef } from "react";
609
+ import { DataGrid } from "react-data-grid";
610
+ import "react-data-grid/lib/styles.css";
611
+
612
+ // src/hooks/useApiCall.ts
613
+ import { useState as useState2, useCallback as useCallback2 } from "react";
614
+
615
+ // src/contexts/SnackbarContext.tsx
616
+ import React, { createContext, useContext, useState, useCallback } from "react";
617
+ import MuiAlert from "@mui/material/Alert";
618
+ import Snackbar from "@mui/material/Snackbar";
619
+ import { jsx, jsxs } from "react/jsx-runtime";
620
+ var SnackbarAlert = React.forwardRef(function SnackbarAlert2(props, ref) {
621
+ return /* @__PURE__ */ jsx(MuiAlert, { elevation: 6, ref, variant: "filled", ...props });
622
+ });
623
+ var SnackbarContext = createContext(void 0);
624
+ var DEFAULT_SUCCESS_DURATION = 3e3;
625
+ var DEFAULT_ERROR_DURATION = 5e3;
626
+ var SnackbarProvider = ({ children }) => {
627
+ const [snackbar, setSnackbar] = useState({
628
+ open: false,
629
+ message: "",
630
+ severity: "info",
631
+ duration: DEFAULT_SUCCESS_DURATION
632
+ // Valor inicial
633
+ });
634
+ const showSnackbar = useCallback((message, severity, duration) => {
635
+ const finalDuration = duration !== void 0 && duration !== null ? duration : severity === "error" ? DEFAULT_ERROR_DURATION : DEFAULT_SUCCESS_DURATION;
636
+ setSnackbar({
637
+ open: true,
638
+ message,
639
+ severity,
640
+ duration: finalDuration
641
+ });
642
+ }, []);
643
+ const showSuccess = useCallback((message, duration) => showSnackbar(message, "success", duration), [showSnackbar]);
644
+ const showError = useCallback((message, duration) => showSnackbar(message, "error", duration), [showSnackbar]);
645
+ const showWarning = useCallback((message, duration) => showSnackbar(message, "warning", duration), [showSnackbar]);
646
+ const showInfo = useCallback((message, duration) => showSnackbar(message, "info", duration), [showSnackbar]);
647
+ const handleCloseSnackbar = (event, reason) => {
648
+ if (reason === "clickaway") {
649
+ return;
650
+ }
651
+ setSnackbar((prev) => ({ ...prev, open: false }));
652
+ };
653
+ return /* @__PURE__ */ jsxs(SnackbarContext.Provider, { value: { showSnackbar, showSuccess, showError, showWarning, showInfo }, children: [
654
+ children,
655
+ /* @__PURE__ */ jsx(
656
+ Snackbar,
657
+ {
658
+ open: snackbar.open,
659
+ autoHideDuration: snackbar.duration,
660
+ onClose: handleCloseSnackbar,
661
+ anchorOrigin: { vertical: "top", horizontal: "center" },
662
+ children: /* @__PURE__ */ jsx(SnackbarAlert, { onClose: handleCloseSnackbar, severity: snackbar.severity, children: snackbar.message })
663
+ }
664
+ )
665
+ ] });
666
+ };
667
+ var useSnackbar = () => {
668
+ const context = useContext(SnackbarContext);
669
+ if (context === void 0) {
670
+ throw new Error("useSnackbar must be used within a SnackbarProvider");
671
+ }
672
+ return context;
673
+ };
674
+
675
+ // src/env.ts
676
+ var getEnvVar = (key) => {
677
+ if (typeof import.meta !== "undefined" && import.meta.env) {
678
+ const viteKey = `VITE_${key}`;
679
+ if (import.meta.env[viteKey]) {
680
+ return import.meta.env[viteKey];
681
+ }
682
+ }
683
+ if (typeof process !== "undefined" && process.env) {
684
+ const craKey = `REACT_APP_${key}`;
685
+ if (process.env[craKey]) {
686
+ return process.env[craKey];
687
+ }
688
+ if (process.env[key]) {
689
+ return process.env[key];
690
+ }
691
+ }
692
+ console.warn(`Variable de entorno "${key}" no encontrada. Aseg\xFArate de definirla con el prefijo correcto (VITE_ o REACT_APP_).`);
693
+ return "";
694
+ };
695
+ var envConfig = {
696
+ backendUrl: getEnvVar("BACKEND_URL")
697
+ // Agrega aquí las demás variables siguiendo el mismo patrón
698
+ };
699
+
700
+ // src/utils/fetchApi.ts
701
+ async function fetchApi(endPoint, options) {
702
+ const BACKEND_URL = envConfig.backendUrl;
703
+ const defaultHeaders = {
704
+ "Content-Type": "application/x-www-form-urlencoded"
705
+ };
706
+ const config = {
707
+ ...options,
708
+ headers: {
709
+ ...defaultHeaders,
710
+ ...options?.headers
711
+ },
712
+ credentials: "include"
713
+ };
714
+ if (config.method === "GET" || config.method === "HEAD") {
715
+ delete config.body;
716
+ }
717
+ return await fetch(BACKEND_URL + endPoint, config);
718
+ }
719
+ var executeBackendProcedure = async (procedureName, params) => {
720
+ function stringifyObjectsAndArraysInParams(params2) {
721
+ const newParams = {};
722
+ for (const key in params2) {
723
+ if (Object.prototype.hasOwnProperty.call(params2, key)) {
724
+ const value = params2[key];
725
+ if (typeof value === "object" && value !== null) {
726
+ try {
727
+ newParams[key] = JSON.stringify(value);
728
+ } catch (e) {
729
+ console.warn(`Warning: Could not stringify value for key '${key}'. Keeping original value. Error:`, e);
730
+ newParams[key] = value;
731
+ }
732
+ } else {
733
+ newParams[key] = value;
734
+ }
735
+ }
736
+ }
737
+ return newParams;
738
+ }
739
+ const body = new URLSearchParams(stringifyObjectsAndArraysInParams(params));
740
+ const response = await fetchApi(`/${procedureName}`, { body, method: "POST" });
741
+ if (response.ok) {
742
+ const rawResponseTextDefinition = await response.text();
743
+ const result = JSON.parse(rawResponseTextDefinition.replace(/^--\n/, ""));
744
+ if (result.error) {
745
+ throw new Error(result.error.message);
746
+ } else {
747
+ return result;
748
+ }
749
+ } else {
750
+ const errorTextDefinition = await response.text();
751
+ throw new Error(`Error al ejecutar procedure '${procedureName}': ${response.status} - ${errorTextDefinition}`);
752
+ }
753
+ };
754
+
755
+ // src/hooks/useApiCall.ts
756
+ var useApiCall = () => {
757
+ const { showSnackbar } = useSnackbar();
758
+ const [loading, setLoading] = useState2(false);
759
+ const [error, setError] = useState2(null);
760
+ const callApi = useCallback2(async (procedureName, params) => {
761
+ setLoading(true);
762
+ setError(null);
763
+ try {
764
+ const result = await executeBackendProcedure(procedureName, params);
765
+ return result === null ? void 0 : result;
766
+ } catch (err) {
767
+ setError(err);
768
+ let snackbarMessage = `Error inesperado al ejecutar '${procedureName}'.`;
769
+ if (err instanceof TypeError) {
770
+ snackbarMessage = `Problema de conexi\xF3n: ${err.message}. Por favor, revisa tu internet o intenta de nuevo.`;
771
+ } else if (err instanceof Error) {
772
+ snackbarMessage = err.message;
773
+ }
774
+ showSnackbar(snackbarMessage, "error");
775
+ throw err;
776
+ } finally {
777
+ setLoading(false);
778
+ }
779
+ }, [showSnackbar]);
780
+ return { callApi, loading, error };
781
+ };
782
+
783
+ // src/components/grid/GenericDataGrid.tsx
784
+ import {
785
+ CircularProgress,
786
+ Typography as Typography5,
787
+ Box as Box4,
788
+ Alert,
789
+ useTheme,
790
+ Button as Button2,
791
+ IconButton
792
+ } from "@mui/material";
793
+
794
+ // src/utils/functions.tsx
795
+ var JSON4all = __toESM(require_json4all(), 1);
796
+
797
+ // src/store/index.ts
798
+ import { configureStore, combineReducers } from "@reduxjs/toolkit";
799
+ import {
800
+ persistStore,
801
+ persistReducer,
802
+ FLUSH,
803
+ REHYDRATE,
804
+ PAUSE,
805
+ PERSIST,
806
+ PURGE,
807
+ REGISTER
808
+ } from "redux-persist";
809
+ import storage from "redux-persist/lib/storage";
810
+
811
+ // src/store/clientContextSlice.ts
812
+ import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
813
+ var initialState = {
814
+ menu: [],
815
+ procedure: {},
816
+ procedures: [],
817
+ config: {},
818
+ // Inicializa con un objeto vacío o valores por defecto adecuados
819
+ useragent: {},
820
+ // Igual aquí
821
+ username: "",
822
+ status: "idle",
823
+ // Por defecto, sin carga
824
+ error: null
825
+ // Sin error
826
+ };
827
+ var fetchClientContext = createAsyncThunk(
828
+ "clientContext/fetchClientContext",
829
+ async (_, { rejectWithValue }) => {
830
+ try {
831
+ const setupResponse = await fetchApi("/client-setup", { method: "GET" });
832
+ if (!setupResponse.ok) {
833
+ const errorData = await setupResponse.text();
834
+ throw new Error(errorData || "Error al obtener configuraci\xF3n del cliente");
835
+ }
836
+ const clientSetup = await setupResponse.json();
837
+ return clientSetup;
838
+ } catch (error) {
839
+ return rejectWithValue(error.message || "Error desconocido al cargar el contexto");
840
+ }
841
+ }
842
+ );
843
+ var clientContextSlice = createSlice({
844
+ name: "clientContext",
845
+ initialState,
846
+ reducers: {
847
+ // Un reducer para limpiar el contexto del cliente (ej. al cerrar sesión)
848
+ clearClientContext: (state) => {
849
+ Object.assign(state, initialState);
850
+ }
851
+ // Puedes añadir otros reducers aquí si necesitas modificar partes del clientContext directamente
852
+ // pero el thunk es la forma preferida para la carga inicial.
853
+ },
854
+ // **extraReducers maneja las acciones del thunk asíncrono**
855
+ extraReducers: (builder) => {
856
+ builder.addCase(fetchClientContext.pending, (state) => {
857
+ state.status = "loading";
858
+ state.error = null;
859
+ }).addCase(fetchClientContext.fulfilled, (state, action) => {
860
+ state.status = "succeeded";
861
+ state.menu = action.payload.menu;
862
+ state.procedure = action.payload.procedure;
863
+ state.procedures = action.payload.procedures;
864
+ state.config = action.payload.config;
865
+ state.useragent = action.payload.useragent;
866
+ state.username = action.payload.username;
867
+ state.error = null;
868
+ }).addCase(fetchClientContext.rejected, (state, action) => {
869
+ state.status = "failed";
870
+ state.error = action.payload || "Fallo al cargar el contexto del cliente";
871
+ });
872
+ }
873
+ });
874
+ var { clearClientContext } = clientContextSlice.actions;
875
+ var clientContextSlice_default = clientContextSlice.reducer;
876
+
877
+ // src/store/routerSlice.ts
878
+ import { createSlice as createSlice2 } from "@reduxjs/toolkit";
879
+ var initialState2 = {
880
+ currentPath: "/",
881
+ previousPath: null,
882
+ redirectPath: null
883
+ // <--- Inicializamos en null
884
+ };
885
+ var routerSlice = createSlice2({
886
+ name: "router",
887
+ initialState: initialState2,
888
+ reducers: {
889
+ setCurrentPath: (state, action) => {
890
+ state.previousPath = state.currentPath;
891
+ state.currentPath = action.payload;
892
+ },
893
+ setRedirectPath: (state, action) => {
894
+ state.redirectPath = action.payload;
895
+ },
896
+ resetRouterState: (state) => {
897
+ state.currentPath = "/";
898
+ state.previousPath = null;
899
+ state.redirectPath = null;
900
+ }
901
+ }
902
+ });
903
+ var { setCurrentPath, setRedirectPath, resetRouterState } = routerSlice.actions;
904
+ var routerSlice_default = routerSlice.reducer;
905
+
906
+ // src/store/menuUiSlice.ts
907
+ import { createSlice as createSlice3 } from "@reduxjs/toolkit";
908
+ var initialState3 = {
909
+ isDrawerOpen: false,
910
+ subMenuOpenStates: {}
911
+ };
912
+ var menuUiSlice = createSlice3({
913
+ name: "menuUi",
914
+ initialState: initialState3,
915
+ reducers: {
916
+ setDrawerOpen: (state, action) => {
917
+ state.isDrawerOpen = action.payload;
918
+ },
919
+ toggleDrawer: (state) => {
920
+ state.isDrawerOpen = !state.isDrawerOpen;
921
+ },
922
+ setSubMenuOpen: (state, action) => {
923
+ state.subMenuOpenStates[action.payload.menuName] = action.payload.isOpen;
924
+ },
925
+ toggleSubMenu: (state, action) => {
926
+ state.subMenuOpenStates[action.payload] = !state.subMenuOpenStates[action.payload];
927
+ },
928
+ // --- NUEVO REDUCER: Establecer el estado de todos los submenús ---
929
+ setAllSubMenusOpen: (state, action) => {
930
+ for (const menuName in state.subMenuOpenStates) {
931
+ if (Object.prototype.hasOwnProperty.call(state.subMenuOpenStates, menuName)) {
932
+ state.subMenuOpenStates[menuName] = action.payload;
933
+ }
934
+ }
935
+ },
936
+ resetMenuUiState: (state) => {
937
+ Object.assign(state, initialState3);
938
+ }
939
+ }
940
+ });
941
+ var {
942
+ setDrawerOpen,
943
+ toggleDrawer,
944
+ setSubMenuOpen,
945
+ toggleSubMenu,
946
+ setAllSubMenusOpen,
947
+ // ¡Exportamos la nueva acción!
948
+ resetMenuUiState
949
+ } = menuUiSlice.actions;
950
+ var menuUiSlice_default = menuUiSlice.reducer;
951
+
952
+ // src/store/index.ts
953
+ import { useDispatch, useSelector } from "react-redux";
954
+ var rootReducer = combineReducers({
955
+ clientContext: clientContextSlice_default,
956
+ router: routerSlice_default,
957
+ menuUi: menuUiSlice_default
958
+ // ...otros slices
959
+ });
960
+ var persistConfig = {
961
+ key: "root",
962
+ storage,
963
+ whitelist: ["clientContext", "router", "menuUi"]
964
+ };
965
+ var persistedReducer = persistReducer(persistConfig, rootReducer);
966
+ var store = configureStore({
967
+ reducer: persistedReducer,
968
+ middleware: (getDefaultMiddleware) => getDefaultMiddleware({
969
+ serializableCheck: {
970
+ ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER]
971
+ }
972
+ })
973
+ });
974
+ var persistor = persistStore(store);
975
+ var useAppDispatch = useDispatch;
976
+ var useAppSelector = useSelector;
977
+ var useClientContextStatus = () => {
978
+ return useAppSelector((state) => state.clientContext.status);
979
+ };
980
+ var useIsDrawerOpen = () => {
981
+ return useAppSelector((state) => state.menuUi.isDrawerOpen);
982
+ };
983
+ var useSubMenuOpenState = (menuName) => {
984
+ return useAppSelector((state) => state.menuUi.subMenuOpenStates[menuName] || false);
985
+ };
986
+ var useRedirectPath = () => {
987
+ return useAppSelector((state) => state.router.redirectPath);
988
+ };
989
+
990
+ // src/utils/functions.tsx
991
+ var cambiarGuionesBajosPorEspacios = (texto) => texto.replace(/_/g, " ");
992
+
993
+ // src/components/grid/GenericDataGrid.tsx
994
+ import SearchIcon from "@mui/icons-material/Search";
995
+ import SearchOffIcon from "@mui/icons-material/SearchOff";
996
+ import AddIcon from "@mui/icons-material/Add";
997
+ import DeleteIcon from "@mui/icons-material/Delete";
998
+
999
+ // src/components/grid/PkHeaderRenderer.tsx
1000
+ import { Box, Typography } from "@mui/material";
1001
+ import { jsx as jsx2 } from "react/jsx-runtime";
1002
+ function PkHeaderRenderer(props) {
1003
+ const { column } = props;
1004
+ const isPrimaryKey = column.isPK;
1005
+ return /* @__PURE__ */ jsx2(
1006
+ Box,
1007
+ {
1008
+ sx: {
1009
+ display: "flex",
1010
+ flexDirection: "column",
1011
+ justifyContent: "center",
1012
+ alignItems: "flex-start",
1013
+ padding: "4px",
1014
+ boxSizing: "border-box",
1015
+ height: "100%"
1016
+ },
1017
+ children: /* @__PURE__ */ jsx2(
1018
+ Typography,
1019
+ {
1020
+ variant: "body2",
1021
+ sx: {
1022
+ fontWeight: "bold",
1023
+ textDecoration: isPrimaryKey ? "underline" : "none",
1024
+ fontSize: "0.875rem"
1025
+ // Puedes ajustar el tamaño si es necesario
1026
+ },
1027
+ children: column.name
1028
+ }
1029
+ )
1030
+ }
1031
+ );
1032
+ }
1033
+ var PkHeaderRenderer_default = PkHeaderRenderer;
1034
+
1035
+ // src/components/grid/PkCellRenderer.tsx
1036
+ import { Typography as Typography2 } from "@mui/material";
1037
+ import { jsx as jsx3 } from "react/jsx-runtime";
1038
+ function PkCellRenderer(props) {
1039
+ const { column, row } = props;
1040
+ const isPrimaryKey = column.isPK;
1041
+ const rowAsRecord = row;
1042
+ const value = rowAsRecord[column.key];
1043
+ return /* @__PURE__ */ jsx3(
1044
+ Typography2,
1045
+ {
1046
+ variant: "body2",
1047
+ sx: {
1048
+ //fontWeight: isPrimaryKey ? 'bold' : 'normal',
1049
+ fontSize: "0.875rem",
1050
+ // Ajusta el tamaño si es necesario
1051
+ whiteSpace: "nowrap",
1052
+ overflow: "hidden",
1053
+ textOverflow: "ellipsis",
1054
+ width: "100%"
1055
+ },
1056
+ children: value === null || value === void 0 ? "" : String(value)
1057
+ }
1058
+ );
1059
+ }
1060
+ var PkCellRenderer_default = PkCellRenderer;
1061
+
1062
+ // src/components/ConfirmDialog.tsx
1063
+ import Dialog from "@mui/material/Dialog";
1064
+ import DialogTitle from "@mui/material/DialogTitle";
1065
+ import DialogContent from "@mui/material/DialogContent";
1066
+ import DialogContentText from "@mui/material/DialogContentText";
1067
+ import DialogActions from "@mui/material/DialogActions";
1068
+ import Button from "@mui/material/Button";
1069
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
1070
+ var ConfirmDialog = ({ open, onClose, title, message }) => {
1071
+ return /* @__PURE__ */ jsxs2(
1072
+ Dialog,
1073
+ {
1074
+ open,
1075
+ onClose: () => onClose(false),
1076
+ "aria-labelledby": "confirm-dialog-title",
1077
+ "aria-describedby": "confirm-dialog-description",
1078
+ children: [
1079
+ /* @__PURE__ */ jsx4(DialogTitle, { id: "confirm-dialog-title", children: title }),
1080
+ /* @__PURE__ */ jsx4(DialogContent, { children: /* @__PURE__ */ jsx4(DialogContentText, { id: "confirm-dialog-description", children: message }) }),
1081
+ /* @__PURE__ */ jsxs2(DialogActions, { children: [
1082
+ /* @__PURE__ */ jsx4(Button, { onClick: () => onClose(false), color: "primary", children: "Cancelar" }),
1083
+ /* @__PURE__ */ jsx4(Button, { onClick: () => onClose(true), color: "error", autoFocus: true, children: "Confirmar" })
1084
+ ] })
1085
+ ]
1086
+ }
1087
+ );
1088
+ };
1089
+
1090
+ // src/components/grid/FilterInputRender.tsx
1091
+ import { InputBase } from "@mui/material";
1092
+ import { jsx as jsx5 } from "react/jsx-runtime";
1093
+ function FilterInputRenderer({
1094
+ column,
1095
+ filters,
1096
+ setFilters
1097
+ }) {
1098
+ return /* @__PURE__ */ jsx5(
1099
+ InputBase,
1100
+ {
1101
+ value: filters[column.key] || "",
1102
+ onChange: (e) => setFilters({
1103
+ ...filters,
1104
+ [column.key]: e.target.value
1105
+ }),
1106
+ sx: {
1107
+ width: "100%",
1108
+ margin: "0",
1109
+ border: "1px solid #ccc",
1110
+ borderRadius: "4px",
1111
+ padding: "2px 4px",
1112
+ fontSize: "0.8rem",
1113
+ boxSizing: "border-box"
1114
+ },
1115
+ onClick: (e) => e.stopPropagation()
1116
+ }
1117
+ );
1118
+ }
1119
+ var FilterInputRender_default = FilterInputRenderer;
1120
+
1121
+ // src/components/grid/InputRendered.tsx
1122
+ import { useCallback as useCallback3, useMemo, useState as useState3 } from "react";
1123
+ import InputBase2 from "@mui/material/InputBase";
1124
+ import { jsx as jsx6 } from "react/jsx-runtime";
1125
+ function InputRenderer({
1126
+ column,
1127
+ row,
1128
+ rowIdx,
1129
+ tableDefinition,
1130
+ onRowChange,
1131
+ onClose,
1132
+ setCellFeedback,
1133
+ onEnterPress,
1134
+ setTableData,
1135
+ setLocalCellChanges,
1136
+ localCellChanges,
1137
+ primaryKey
1138
+ }) {
1139
+ const tableName = tableDefinition.tableName;
1140
+ const [editingValue, setEditingValue] = useState3(row[column.key]);
1141
+ const { showSuccess, showError } = useSnackbar();
1142
+ const initialRowId = useMemo(() => getPrimaryKeyValues(row, primaryKey), [row, primaryKey]);
1143
+ const { callApi, loading, error } = useApiCall();
1144
+ const handleCommit = useCallback3(async (currentValue, closeEditor, focusNextCell) => {
1145
+ const processedNewValue = typeof currentValue === "string" ? currentValue.trim() === "" ? null : currentValue.trim() : currentValue;
1146
+ const potentialUpdatedRow = { ...row, [column.key]: processedNewValue };
1147
+ const arePKValuesFilled = tableDefinition.primaryKey.every(
1148
+ (key) => potentialUpdatedRow[key] !== void 0 && potentialUpdatedRow[key] !== null && String(potentialUpdatedRow[key]).trim() !== ""
1149
+ );
1150
+ const isNewRow = !arePKValuesFilled || potentialUpdatedRow[NEW_ROW_INDICATOR];
1151
+ const isMandatoryField = tableDefinition.primaryKey.includes(column.key) || tableDefinition.fields.find((f) => f.name === column.key)?.nullable === false;
1152
+ const isMandatoryFieldEmpty = isNewRow && isMandatoryField && (processedNewValue === null || processedNewValue === void 0 || String(processedNewValue).trim() === "");
1153
+ if (processedNewValue === row[column.key] && !isNewRow && !isMandatoryFieldEmpty) {
1154
+ console.log("No se guard\xF3: el valor no cambi\xF3 (y no es una nueva fila o campo obligatorio vac\xEDo que se est\xE1 iniciando).");
1155
+ onClose(false, focusNextCell);
1156
+ setLocalCellChanges((prev) => {
1157
+ const newMap = new Map(prev);
1158
+ const columnKeys = newMap.get(initialRowId);
1159
+ if (columnKeys) {
1160
+ columnKeys.delete(column.key);
1161
+ if (columnKeys.size === 0) {
1162
+ newMap.delete(initialRowId);
1163
+ } else {
1164
+ newMap.set(initialRowId, columnKeys);
1165
+ }
1166
+ }
1167
+ return newMap;
1168
+ });
1169
+ return;
1170
+ }
1171
+ const oldRowData = { ...row };
1172
+ const primaryKeyValuesForBackend = tableDefinition.primaryKey.map((key) => potentialUpdatedRow[key]);
1173
+ const currentRowIdBeforeUpdate = getPrimaryKeyValues(oldRowData, tableDefinition.primaryKey);
1174
+ onRowChange({ ...row, [column.key]: processedNewValue }, true);
1175
+ onClose(true, focusNextCell);
1176
+ if (isNewRow) {
1177
+ const areAllMandatoryFieldsFilled = tableDefinition.fields.every((fieldDef) => {
1178
+ const isMandatory = fieldDef.nullable === false || fieldDef.isPk;
1179
+ const fieldValue = potentialUpdatedRow[fieldDef.name];
1180
+ return !isMandatory || fieldValue !== null && fieldValue !== void 0 && String(fieldValue).trim() !== "";
1181
+ });
1182
+ if (!areAllMandatoryFieldsFilled) {
1183
+ console.log("Nueva fila: Faltan campos obligatorios. No se guarda en el backend todav\xEDa.");
1184
+ setLocalCellChanges((prev) => {
1185
+ const newMap = new Map(prev);
1186
+ const currentColumnsInRow = newMap.get(initialRowId) || /* @__PURE__ */ new Set();
1187
+ tableDefinition.fields.forEach((fieldDef) => {
1188
+ const isMandatory = fieldDef.nullable === false || fieldDef.isPk;
1189
+ const isEditable = fieldDef.editable !== false;
1190
+ const fieldValue = potentialUpdatedRow[fieldDef.name];
1191
+ if (isMandatory && isEditable && (fieldValue === null || fieldValue === void 0 || String(fieldValue).trim() === "")) {
1192
+ currentColumnsInRow.add(fieldDef.name);
1193
+ } else {
1194
+ currentColumnsInRow.delete(fieldDef.name);
1195
+ }
1196
+ });
1197
+ newMap.set(initialRowId, currentColumnsInRow);
1198
+ return newMap;
1199
+ });
1200
+ return;
1201
+ } else {
1202
+ console.log("Nueva fila: Todos los campos obligatorios est\xE1n llenos. Procediendo a guardar.");
1203
+ setLocalCellChanges((prev) => {
1204
+ const newMap = new Map(prev);
1205
+ newMap.delete(initialRowId);
1206
+ return newMap;
1207
+ });
1208
+ }
1209
+ }
1210
+ const status = isNewRow ? "new" : "update";
1211
+ let rowToSend = {};
1212
+ if (isNewRow) {
1213
+ tableDefinition.fields.forEach((fieldDef) => {
1214
+ const fieldValue = potentialUpdatedRow[fieldDef.name];
1215
+ if (fieldValue !== void 0 && fieldValue !== null && String(fieldValue).trim() !== "") {
1216
+ rowToSend[fieldDef.name] = fieldValue;
1217
+ } else if (tableDefinition.primaryKey.includes(fieldDef.name) && (fieldValue === null || fieldValue === void 0 || String(fieldValue).trim() === "")) {
1218
+ rowToSend[fieldDef.name] = fieldValue;
1219
+ }
1220
+ });
1221
+ if (localCellChanges.has(initialRowId)) {
1222
+ localCellChanges.get(initialRowId)?.forEach((colKey) => {
1223
+ if (!rowToSend.hasOwnProperty(colKey)) {
1224
+ rowToSend[colKey] = potentialUpdatedRow[colKey];
1225
+ }
1226
+ });
1227
+ }
1228
+ delete rowToSend[NEW_ROW_INDICATOR];
1229
+ } else {
1230
+ rowToSend[column.key] = processedNewValue;
1231
+ tableDefinition.primaryKey.forEach((pkField) => {
1232
+ rowToSend[pkField] = potentialUpdatedRow[pkField];
1233
+ });
1234
+ }
1235
+ try {
1236
+ const response = await callApi("table_record_save", {
1237
+ table: tableName,
1238
+ primaryKeyValues: primaryKeyValuesForBackend,
1239
+ newRow: rowToSend,
1240
+ oldRow: oldRowData,
1241
+ status
1242
+ });
1243
+ setLocalCellChanges((prev) => {
1244
+ const newMap = new Map(prev);
1245
+ const columnKeys = newMap.get(initialRowId);
1246
+ if (columnKeys) {
1247
+ columnKeys.delete(column.key);
1248
+ if (columnKeys.size === 0) {
1249
+ newMap.delete(initialRowId);
1250
+ } else {
1251
+ newMap.set(initialRowId, columnKeys);
1252
+ }
1253
+ }
1254
+ return newMap;
1255
+ });
1256
+ showSuccess("Registro guardado exitosamente!");
1257
+ let finalRowIdForFeedback;
1258
+ let persistedRowData;
1259
+ if (response.row && isNewRow) {
1260
+ persistedRowData = { ...response.row };
1261
+ setTableData((prevData) => {
1262
+ const newData = [...prevData];
1263
+ const originalRowId = getPrimaryKeyValues(oldRowData, tableDefinition.primaryKey);
1264
+ const rowIndex = newData.findIndex((r) => getPrimaryKeyValues(r, tableDefinition.primaryKey) === originalRowId);
1265
+ if (rowIndex !== -1) {
1266
+ newData[rowIndex] = persistedRowData;
1267
+ } else {
1268
+ console.warn("Fila no encontrada para actualizar despu\xE9s de la inserci\xF3n. Podr\xEDa haber un problema de sincronizaci\xF3n.");
1269
+ const newPrimaryKeyId = getPrimaryKeyValues(persistedRowData, tableDefinition.primaryKey);
1270
+ const newRowIndex = newData.findIndex((r) => getPrimaryKeyValues(r, tableDefinition.primaryKey) === newPrimaryKeyId);
1271
+ if (newRowIndex !== -1) {
1272
+ newData[newRowIndex] = persistedRowData;
1273
+ }
1274
+ }
1275
+ return newData;
1276
+ });
1277
+ finalRowIdForFeedback = getPrimaryKeyValues(persistedRowData, tableDefinition.primaryKey);
1278
+ } else {
1279
+ persistedRowData = potentialUpdatedRow;
1280
+ const isPrimaryKeyColumn = tableDefinition.primaryKey.includes(column.key);
1281
+ finalRowIdForFeedback = isPrimaryKeyColumn ? getPrimaryKeyValues(potentialUpdatedRow, tableDefinition.primaryKey) : currentRowIdBeforeUpdate;
1282
+ }
1283
+ setCellFeedback({ rowId: finalRowIdForFeedback, columnKey: column.key, type: "success" });
1284
+ } catch (err) {
1285
+ console.error("Error al guardar el registro:", err);
1286
+ setCellFeedback({ rowId: currentRowIdBeforeUpdate, columnKey: column.key, type: "error" });
1287
+ onRowChange(oldRowData, true);
1288
+ }
1289
+ }, [
1290
+ column,
1291
+ row,
1292
+ onRowChange,
1293
+ tableName,
1294
+ tableDefinition.primaryKey,
1295
+ tableDefinition.fields,
1296
+ showSuccess,
1297
+ showError,
1298
+ setCellFeedback,
1299
+ onClose,
1300
+ setTableData,
1301
+ setLocalCellChanges,
1302
+ localCellChanges,
1303
+ initialRowId
1304
+ ]);
1305
+ const handleKeyDown = useCallback3((event) => {
1306
+ if (event.key === "Enter") {
1307
+ handleCommit(editingValue, true, true);
1308
+ event.preventDefault();
1309
+ if (onEnterPress) {
1310
+ onEnterPress(rowIdx, column.key);
1311
+ }
1312
+ } else if (event.key === "Tab") {
1313
+ handleCommit(editingValue, true, true);
1314
+ }
1315
+ }, [handleCommit, editingValue, column.key, rowIdx, onEnterPress]);
1316
+ const handleBlur = useCallback3(() => {
1317
+ handleCommit(editingValue, true, false);
1318
+ }, [handleCommit, editingValue]);
1319
+ const fieldDefinition = tableDefinition.fields.find((f) => f.name === column.key);
1320
+ const isFieldEditable = fieldDefinition?.editable !== false;
1321
+ return /* @__PURE__ */ jsx6(
1322
+ InputBase2,
1323
+ {
1324
+ value: editingValue === null ? "" : editingValue,
1325
+ onChange: (e) => setEditingValue(e.target.value),
1326
+ onKeyDown: handleKeyDown,
1327
+ onBlur: handleBlur,
1328
+ placeholder: "",
1329
+ sx: {
1330
+ width: "100%",
1331
+ margin: "0",
1332
+ border: "1px solid #ccc",
1333
+ borderRadius: "4px",
1334
+ padding: "2px 4px",
1335
+ fontSize: "0.8rem",
1336
+ boxSizing: "border-box"
1337
+ },
1338
+ onClick: (e) => e.stopPropagation(),
1339
+ autoFocus: true,
1340
+ disabled: !isFieldEditable
1341
+ }
1342
+ );
1343
+ }
1344
+ var InputRendered_default = InputRenderer;
1345
+
1346
+ // src/components/grid/ExampleClientSideComponent.tsx
1347
+ import { Box as Box2, Typography as Typography3 } from "@mui/material";
1348
+ import { jsx as jsx7 } from "react/jsx-runtime";
1349
+ var ExampleClientSideComponent = ({ row, column, fieldDefinition }) => {
1350
+ const value = row[column.key];
1351
+ return /* @__PURE__ */ jsx7(Box2, { sx: {
1352
+ padding: 0.5,
1353
+ width: "100%",
1354
+ height: "100%",
1355
+ display: "flex",
1356
+ alignItems: "center",
1357
+ backgroundColor: value === "Special" ? "lightblue" : "transparent"
1358
+ }, children: /* @__PURE__ */ jsx7(Typography3, { variant: "body2", sx: { fontWeight: "bold" }, children: value ? `CS: ${value}` : "N/A" }) });
1359
+ };
1360
+ var ExampleClientSideComponent_default = ExampleClientSideComponent;
1361
+
1362
+ // src/components/grid/FallbackClientSideRenderer.tsx
1363
+ import { Box as Box3, Typography as Typography4, Tooltip } from "@mui/material";
1364
+ import WarningAmberIcon from "@mui/icons-material/WarningAmber";
1365
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
1366
+ var FallbackClientSideRenderer = ({ column, row, fieldDefinition }) => {
1367
+ const value = row[column.key];
1368
+ const clientSideName = fieldDefinition?.clientSide || "Desconocido";
1369
+ return /* @__PURE__ */ jsx8(Tooltip, { title: `Componente clientSide '${clientSideName}' no implementado. Mostrando valor por defecto.`, children: /* @__PURE__ */ jsxs3(
1370
+ Box3,
1371
+ {
1372
+ sx: {
1373
+ display: "flex",
1374
+ alignItems: "center",
1375
+ justifyContent: "space-between",
1376
+ // Para espaciar el valor y el icono
1377
+ gap: 1,
1378
+ // Espacio entre elementos
1379
+ width: "100%",
1380
+ height: "100%",
1381
+ paddingLeft: "8px",
1382
+ backgroundColor: "rgba(255, 193, 7, 0.1)",
1383
+ // Amarillo claro para advertencia
1384
+ border: "1px dashed rgba(255, 193, 7, 0.5)",
1385
+ boxSizing: "border-box",
1386
+ overflow: "hidden"
1387
+ // Evita que el contenido se desborde
1388
+ },
1389
+ children: [
1390
+ /* @__PURE__ */ jsx8(Typography4, { variant: "body2", noWrap: true, sx: { flexGrow: 1 }, children: value !== null && value !== void 0 ? String(value) : "*Vac\xEDo*" }),
1391
+ /* @__PURE__ */ jsx8(
1392
+ WarningAmberIcon,
1393
+ {
1394
+ sx: {
1395
+ fontSize: 18,
1396
+ color: "warning.main",
1397
+ marginRight: "4px"
1398
+ // Pequeño margen a la derecha del icono
1399
+ }
1400
+ }
1401
+ )
1402
+ ]
1403
+ }
1404
+ ) });
1405
+ };
1406
+ var FallbackClientSideRenderer_default = FallbackClientSideRenderer;
1407
+
1408
+ // src/components/grid/clientSides.ts
1409
+ var clientSides = {
1410
+ "ExampleClientSideComponent": ExampleClientSideComponent_default,
1411
+ // Aseguramos el tipo aquí también
1412
+ "FallbackClientSideRenderer": FallbackClientSideRenderer_default
1413
+ // Y aquí
1414
+ };
1415
+ var extendClientSides = (newRenderers) => {
1416
+ clientSides = { ...clientSides, ...newRenderers };
1417
+ console.log("clientSides extendidos:", clientSides);
1418
+ };
1419
+
1420
+ // src/components/grid/GenericDataGrid.tsx
1421
+ import { Fragment, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1422
+ var getPrimaryKeyValues = (row, primaryKey) => {
1423
+ return primaryKey.map((key) => {
1424
+ return row[key] !== void 0 && row[key] !== null ? String(row[key]) : "NULL_OR_UNDEFINED";
1425
+ }).join("|");
1426
+ };
1427
+ var NEW_ROW_INDICATOR = ".$new";
1428
+ var GenericDataGrid = ({
1429
+ tableName,
1430
+ fixedFields
1431
+ }) => {
1432
+ const [tableDefinition, setTableDefinition] = useState4(null);
1433
+ const [tableData, setTableData] = useState4([]);
1434
+ const [isFilterRowVisible, setIsFilterRowVisible] = useState4(false);
1435
+ const [filters, setFilters] = useState4({});
1436
+ const [selectedRows, setSelectedRows] = useState4(() => /* @__PURE__ */ new Set());
1437
+ const [cellFeedback, setCellFeedback] = useState4(null);
1438
+ const [localCellChanges, setLocalCellChanges] = useState4(/* @__PURE__ */ new Map());
1439
+ const theme = useTheme();
1440
+ const [openConfirmDialog, setOpenConfirmDialog] = useState4(false);
1441
+ const [rowToDelete, setRowToDelete] = useState4(null);
1442
+ const [exitingRowIds, setExitingRowIds] = useState4(/* @__PURE__ */ new Set());
1443
+ const { showSuccess, showError, showWarning, showInfo } = useSnackbar();
1444
+ const feedbackTimerRef = useRef(null);
1445
+ const dataGridRef = useRef(null);
1446
+ const { callApi, loading, error } = useApiCall();
1447
+ useEffect(() => {
1448
+ setFilters({});
1449
+ setIsFilterRowVisible(false);
1450
+ setSelectedRows(/* @__PURE__ */ new Set());
1451
+ setTableDefinition(null);
1452
+ setTableData([]);
1453
+ setCellFeedback(null);
1454
+ setLocalCellChanges(/* @__PURE__ */ new Map());
1455
+ setOpenConfirmDialog(false);
1456
+ setRowToDelete(null);
1457
+ setExitingRowIds(/* @__PURE__ */ new Set());
1458
+ if (feedbackTimerRef.current) {
1459
+ clearTimeout(feedbackTimerRef.current);
1460
+ }
1461
+ }, [tableName]);
1462
+ useEffect(() => {
1463
+ const fetchDataAndDefinition = async () => {
1464
+ try {
1465
+ const definition = await callApi("table_structure", { table: tableName });
1466
+ setTableDefinition(definition);
1467
+ const data = await callApi("table_data", {
1468
+ table: tableName,
1469
+ fixedFields
1470
+ // Envía el array fixedFields directamente a la API
1471
+ });
1472
+ setTableData(data);
1473
+ } catch (err) {
1474
+ setTableDefinition(null);
1475
+ setTableData([]);
1476
+ showError(`Error al cargar datos para la tabla '${tableName}': ${err.message || "Error desconocido"}`);
1477
+ } finally {
1478
+ }
1479
+ };
1480
+ fetchDataAndDefinition();
1481
+ }, [tableName, fixedFields, showError]);
1482
+ useEffect(() => {
1483
+ if (cellFeedback) {
1484
+ if (feedbackTimerRef.current) {
1485
+ clearTimeout(feedbackTimerRef.current);
1486
+ }
1487
+ const timerDuration = cellFeedback.type === "success" ? 4e3 : 3e3;
1488
+ feedbackTimerRef.current = setTimeout(() => {
1489
+ setCellFeedback(null);
1490
+ }, timerDuration);
1491
+ }
1492
+ return () => {
1493
+ if (feedbackTimerRef.current) {
1494
+ clearTimeout(feedbackTimerRef.current);
1495
+ }
1496
+ };
1497
+ }, [cellFeedback]);
1498
+ const primaryKey = useMemo2(() => {
1499
+ if (!tableDefinition) return ["id"];
1500
+ return tableDefinition.primaryKey && tableDefinition.primaryKey.length > 0 ? tableDefinition.primaryKey : ["id"];
1501
+ }, [tableDefinition]);
1502
+ const toggleFilterVisibility = useCallback4(() => {
1503
+ setIsFilterRowVisible((prev) => {
1504
+ if (prev) {
1505
+ setFilters({});
1506
+ }
1507
+ return !prev;
1508
+ });
1509
+ }, []);
1510
+ const handleAddRow = useCallback4(() => {
1511
+ if (!tableDefinition) {
1512
+ showWarning("No se puede agregar una fila sin la definici\xF3n de la tabla.");
1513
+ return;
1514
+ }
1515
+ const newRow = {};
1516
+ tableDefinition.fields.forEach((field) => {
1517
+ newRow[field.name] = null;
1518
+ });
1519
+ newRow[NEW_ROW_INDICATOR] = true;
1520
+ if (fixedFields) {
1521
+ fixedFields.forEach((fixedField) => {
1522
+ newRow[fixedField.fieldName] = fixedField.value;
1523
+ });
1524
+ }
1525
+ setTableData((prevData) => [newRow, ...prevData]);
1526
+ setSelectedRows(/* @__PURE__ */ new Set());
1527
+ const tempRowId = getPrimaryKeyValues(newRow, primaryKey);
1528
+ setLocalCellChanges((prev) => {
1529
+ const newMap = new Map(prev);
1530
+ const mandatoryEditableColumns = /* @__PURE__ */ new Set();
1531
+ tableDefinition.fields.forEach((field) => {
1532
+ const isMandatory = field.nullable === false || field.isPk;
1533
+ const isEditable = field.editable !== false;
1534
+ if (isMandatory && isEditable) {
1535
+ mandatoryEditableColumns.add(field.name);
1536
+ }
1537
+ });
1538
+ newMap.set(tempRowId, mandatoryEditableColumns);
1539
+ return newMap;
1540
+ });
1541
+ }, [tableDefinition, showWarning, primaryKey, fixedFields]);
1542
+ const handleDeleteRow = useCallback4(async (row) => {
1543
+ setRowToDelete(row);
1544
+ setOpenConfirmDialog(true);
1545
+ }, []);
1546
+ const handleConfirmDelete = useCallback4(async (confirm) => {
1547
+ setOpenConfirmDialog(false);
1548
+ if (!confirm || !rowToDelete) {
1549
+ showWarning("Eliminaci\xF3n cancelada por el usuario.");
1550
+ setRowToDelete(null);
1551
+ return;
1552
+ }
1553
+ if (!tableDefinition || !tableName) {
1554
+ showError("No se puede eliminar la fila sin la definici\xF3n de la tabla o el nombre de la tabla.");
1555
+ setRowToDelete(null);
1556
+ return;
1557
+ }
1558
+ const rowId = getPrimaryKeyValues(rowToDelete, primaryKey);
1559
+ setExitingRowIds((prev) => new Set(prev).add(rowId));
1560
+ setTimeout(async () => {
1561
+ if (rowToDelete[NEW_ROW_INDICATOR]) {
1562
+ setTimeout(() => {
1563
+ setTableData((prevData) => prevData.filter((row) => getPrimaryKeyValues(row, primaryKey) !== rowId));
1564
+ setLocalCellChanges((prev) => {
1565
+ const newMap = new Map(prev);
1566
+ newMap.delete(rowId);
1567
+ return newMap;
1568
+ });
1569
+ setSelectedRows((prev) => {
1570
+ const newSet = new Set(prev);
1571
+ newSet.delete(rowId);
1572
+ return newSet;
1573
+ });
1574
+ setExitingRowIds((prev) => {
1575
+ const newSet = new Set(prev);
1576
+ newSet.delete(rowId);
1577
+ return newSet;
1578
+ });
1579
+ showInfo(`Fila no guardada '${rowId}' eliminada localmente.`);
1580
+ setRowToDelete(null);
1581
+ }, 500);
1582
+ return;
1583
+ }
1584
+ try {
1585
+ const primaryKeyValues = tableDefinition.primaryKey.map((key) => rowToDelete[key]);
1586
+ await callApi("table_record_delete", {
1587
+ table: tableName,
1588
+ primaryKeyValues
1589
+ });
1590
+ console.log(`Fila con ID ${rowId} eliminada exitosamente del backend.`);
1591
+ setTimeout(() => {
1592
+ setTableData((prevData) => prevData.filter((row) => getPrimaryKeyValues(row, primaryKey) !== rowId));
1593
+ setLocalCellChanges((prev) => {
1594
+ const newMap = new Map(prev);
1595
+ newMap.delete(rowId);
1596
+ return newMap;
1597
+ });
1598
+ setSelectedRows((prev) => {
1599
+ const newSet = new Set(prev);
1600
+ newSet.delete(rowId);
1601
+ return newSet;
1602
+ });
1603
+ setExitingRowIds((prev) => {
1604
+ const newSet = new Set(prev);
1605
+ newSet.delete(rowId);
1606
+ return newSet;
1607
+ });
1608
+ showSuccess(`Fila '${rowId}' eliminada exitosamente.`);
1609
+ setRowToDelete(null);
1610
+ }, 500);
1611
+ } catch (err) {
1612
+ console.error(`Error al eliminar la fila '${rowId}':`, err);
1613
+ showError(`Error al eliminar la fila '${rowId}': ${err.message || "Error desconocido"}`);
1614
+ setExitingRowIds((prev) => {
1615
+ const newSet = new Set(prev);
1616
+ newSet.delete(rowId);
1617
+ return newSet;
1618
+ });
1619
+ setRowToDelete(null);
1620
+ }
1621
+ }, 10);
1622
+ }, [rowToDelete, tableDefinition, tableName, primaryKey, showInfo, showSuccess, showError, showWarning, setTableData, setLocalCellChanges, setSelectedRows]);
1623
+ const filteredRows = useMemo2(() => {
1624
+ let rows = tableData;
1625
+ if (isFilterRowVisible) {
1626
+ Object.keys(filters).forEach((key) => {
1627
+ const filterValue = filters[key].toLowerCase();
1628
+ if (filterValue) {
1629
+ rows = rows.filter((row) => {
1630
+ const cellValue = String(row[key] || "").toLowerCase();
1631
+ return cellValue.includes(filterValue);
1632
+ });
1633
+ }
1634
+ });
1635
+ }
1636
+ return rows;
1637
+ }, [tableData, filters, isFilterRowVisible]);
1638
+ const handleEnterKeyPressInEditor = useCallback4((rowIndex, columnKey, currentColumns) => {
1639
+ if (dataGridRef.current && tableDefinition) {
1640
+ const currentColumnIndex = currentColumns.findIndex((col) => col.key === columnKey);
1641
+ if (currentColumnIndex !== -1) {
1642
+ let nextColumnIndex = currentColumnIndex + 1;
1643
+ let nextRowIndex = rowIndex;
1644
+ let foundNextTarget = false;
1645
+ while (!foundNextTarget) {
1646
+ if (nextColumnIndex >= currentColumns.length) {
1647
+ nextColumnIndex = 0;
1648
+ nextRowIndex++;
1649
+ if (nextRowIndex >= filteredRows.length) {
1650
+ nextRowIndex = 0;
1651
+ nextColumnIndex = 0;
1652
+ if (filteredRows.length === 0 || rowIndex === filteredRows.length - 1 && currentColumnIndex === currentColumns.length - 1) {
1653
+ foundNextTarget = true;
1654
+ break;
1655
+ }
1656
+ }
1657
+ }
1658
+ const nextColumn = currentColumns[nextColumnIndex];
1659
+ if (nextColumn) {
1660
+ const fieldDefinition = tableDefinition.fields.find((f) => f.name === nextColumn.key);
1661
+ const isEditableField = fieldDefinition?.editable !== false;
1662
+ if (nextColumn.key !== "filterToggle" && nextColumn.key !== "deleteAction" && isEditableField) {
1663
+ foundNextTarget = true;
1664
+ } else {
1665
+ nextColumnIndex++;
1666
+ }
1667
+ } else {
1668
+ nextColumnIndex++;
1669
+ }
1670
+ }
1671
+ if (foundNextTarget) {
1672
+ dataGridRef.current.selectCell({ rowIdx: nextRowIndex, idx: nextColumnIndex }, { enableEditor: false, scrollIntoView: true });
1673
+ }
1674
+ }
1675
+ }
1676
+ }, [filteredRows, tableDefinition]);
1677
+ const columns = useMemo2(() => {
1678
+ if (!tableDefinition) return [];
1679
+ const fieldsToShow = tableDefinition.fields.filter((field) => {
1680
+ const fixedFieldEntry = fixedFields?.find((f) => f.fieldName === field.name);
1681
+ return !(fixedFieldEntry && fixedFieldEntry.until === void 0);
1682
+ });
1683
+ const defaultColumns = fieldsToShow.map((field) => {
1684
+ const isFixedField = fixedFields?.some((f) => f.fieldName === field.name);
1685
+ const isFieldEditable = field.editable !== false && !isFixedField;
1686
+ return {
1687
+ key: field.name,
1688
+ name: field.label || cambiarGuionesBajosPorEspacios(field.name),
1689
+ resizable: true,
1690
+ sortable: true,
1691
+ editable: isFieldEditable,
1692
+ // Usar la nueva bandera de editable
1693
+ flexGrow: 1,
1694
+ minWidth: 60,
1695
+ isPK: field.isPk,
1696
+ renderHeaderCell: (props) => /* @__PURE__ */ jsx9(PkHeaderRenderer_default, { ...props }),
1697
+ renderSummaryCell: ({ column }) => {
1698
+ const fixedFieldEntry = fixedFields?.find((f) => f.fieldName === column.key);
1699
+ if (fixedFieldEntry && fixedFieldEntry.until === void 0) return null;
1700
+ return isFilterRowVisible ? /* @__PURE__ */ jsx9(
1701
+ FilterInputRender_default,
1702
+ {
1703
+ column,
1704
+ filters,
1705
+ setFilters
1706
+ }
1707
+ ) : null;
1708
+ },
1709
+ renderCell: (props) => {
1710
+ const rowId = getPrimaryKeyValues(props.row, primaryKey);
1711
+ const fieldDefinition = tableDefinition.fields.find((f) => f.name === props.column.key);
1712
+ if (fieldDefinition?.clientSide) {
1713
+ const ClientSideComponent = clientSides[fieldDefinition.clientSide];
1714
+ if (ClientSideComponent) {
1715
+ return /* @__PURE__ */ jsx9(
1716
+ ClientSideComponent,
1717
+ {
1718
+ ...props,
1719
+ fieldDefinition,
1720
+ tableDefinition,
1721
+ primaryKey
1722
+ }
1723
+ );
1724
+ } else {
1725
+ return /* @__PURE__ */ jsx9(
1726
+ FallbackClientSideRenderer_default,
1727
+ {
1728
+ ...props,
1729
+ fieldDefinition,
1730
+ tableDefinition,
1731
+ primaryKey
1732
+ }
1733
+ );
1734
+ }
1735
+ }
1736
+ let cellBackgroundColor = "transparent";
1737
+ if (cellFeedback && cellFeedback.rowId === rowId && cellFeedback.columnKey === props.column.key) {
1738
+ cellBackgroundColor = cellFeedback.type === "error" ? theme.palette.error.light : theme.palette.success.light;
1739
+ } else {
1740
+ const isNewRowLocalCheck = props.row[NEW_ROW_INDICATOR];
1741
+ const isMandatory = tableDefinition.primaryKey.includes(props.column.key) || tableDefinition.fields.find((f) => f.name === props.column.key)?.nullable === false;
1742
+ const hasValue = props.row[props.column.key] !== null && props.row[props.column.key] !== void 0 && String(props.row[props.column.key]).trim() !== "";
1743
+ const isFixedFieldCurrent = fixedFields?.some((f) => f.fieldName === props.column.key);
1744
+ if (isFixedFieldCurrent) {
1745
+ cellBackgroundColor = theme.palette.action.selected;
1746
+ } else if (isNewRowLocalCheck && isMandatory && !hasValue || localCellChanges.has(rowId) && localCellChanges.get(rowId)?.has(props.column.key)) {
1747
+ cellBackgroundColor = theme.palette.info.light;
1748
+ }
1749
+ }
1750
+ return /* @__PURE__ */ jsx9(
1751
+ Box4,
1752
+ {
1753
+ sx: {
1754
+ position: "absolute",
1755
+ top: 0,
1756
+ left: 0,
1757
+ width: "100%",
1758
+ height: "100%",
1759
+ backgroundColor: cellBackgroundColor,
1760
+ transition: "background-color 0.3s ease-in-out",
1761
+ display: "flex",
1762
+ alignItems: "center",
1763
+ paddingLeft: "8px",
1764
+ boxSizing: "border-box"
1765
+ },
1766
+ children: /* @__PURE__ */ jsx9(
1767
+ PkCellRenderer_default,
1768
+ {
1769
+ ...props,
1770
+ column: { ...props.column, isPK: !!field.isPk }
1771
+ }
1772
+ )
1773
+ }
1774
+ );
1775
+ }
1776
+ };
1777
+ });
1778
+ const filterToggleColumn = {
1779
+ key: "filterToggle",
1780
+ name: "",
1781
+ width: 50,
1782
+ resizable: false,
1783
+ sortable: false,
1784
+ frozen: true,
1785
+ renderHeaderCell: () => /* @__PURE__ */ jsx9(
1786
+ IconButton,
1787
+ {
1788
+ color: "inherit",
1789
+ onClick: toggleFilterVisibility,
1790
+ size: "small",
1791
+ title: isFilterRowVisible ? "Ocultar filtros" : "Mostrar filtros",
1792
+ sx: { p: 0.5 },
1793
+ children: isFilterRowVisible ? /* @__PURE__ */ jsx9(SearchOffIcon, { sx: { fontSize: 20 } }) : /* @__PURE__ */ jsx9(SearchIcon, { sx: { fontSize: 20 } })
1794
+ }
1795
+ ),
1796
+ renderSummaryCell: () => null
1797
+ };
1798
+ const deleteActionColumn = {
1799
+ key: "deleteAction",
1800
+ name: "",
1801
+ width: 50,
1802
+ resizable: false,
1803
+ sortable: false,
1804
+ frozen: true,
1805
+ renderHeaderCell: () => null,
1806
+ renderSummaryCell: () => null,
1807
+ renderCell: ({ row }) => {
1808
+ if (!tableDefinition.allow?.delete) {
1809
+ return null;
1810
+ }
1811
+ return /* @__PURE__ */ jsx9(Box4, { sx: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%" }, children: /* @__PURE__ */ jsx9(
1812
+ Button2,
1813
+ {
1814
+ variant: "outlined",
1815
+ color: "error",
1816
+ size: "small",
1817
+ onClick: () => handleDeleteRow(row),
1818
+ title: "Eliminar fila",
1819
+ sx: {
1820
+ minWidth: 35,
1821
+ height: 30,
1822
+ p: 0.5,
1823
+ "& .MuiButton-startIcon": { m: 0 }
1824
+ },
1825
+ children: /* @__PURE__ */ jsx9(DeleteIcon, { sx: { fontSize: 18 } })
1826
+ }
1827
+ ) });
1828
+ }
1829
+ };
1830
+ const allColumns = [filterToggleColumn, deleteActionColumn, ...defaultColumns];
1831
+ return allColumns.map((col) => {
1832
+ if (col.editable) {
1833
+ const fieldDefinition = tableDefinition.fields.find((f) => f.name === col.key);
1834
+ const isFixedField = fixedFields?.some((f) => f.fieldName === col.key);
1835
+ const isFieldEditableByUI = fieldDefinition?.editable !== false && !isFixedField;
1836
+ if (!isFieldEditableByUI) {
1837
+ return { ...col, renderEditCell: void 0 };
1838
+ }
1839
+ return {
1840
+ ...col,
1841
+ renderEditCell: (props) => {
1842
+ return /* @__PURE__ */ jsx9(
1843
+ InputRendered_default,
1844
+ {
1845
+ ...props,
1846
+ tableDefinition,
1847
+ setCellFeedback,
1848
+ onEnterPress: (rowIndex, columnKey) => handleEnterKeyPressInEditor(rowIndex, columnKey, allColumns),
1849
+ setTableData,
1850
+ setLocalCellChanges,
1851
+ localCellChanges,
1852
+ primaryKey
1853
+ }
1854
+ );
1855
+ }
1856
+ };
1857
+ }
1858
+ return col;
1859
+ });
1860
+ }, [
1861
+ tableDefinition,
1862
+ isFilterRowVisible,
1863
+ filters,
1864
+ toggleFilterVisibility,
1865
+ cellFeedback,
1866
+ primaryKey,
1867
+ theme.palette.success.light,
1868
+ theme.palette.error.light,
1869
+ theme.palette.info.light,
1870
+ theme.palette.action.selected,
1871
+ // Añade el color de campos fijos
1872
+ handleEnterKeyPressInEditor,
1873
+ setTableData,
1874
+ localCellChanges,
1875
+ handleDeleteRow,
1876
+ fixedFields
1877
+ // Añade fixedFields como dependencia
1878
+ ]);
1879
+ const showNoRowsMessage = filteredRows.length === 0 && !loading && !error;
1880
+ const handleRowsChange = useCallback4((updatedRows) => {
1881
+ setTableData(updatedRows);
1882
+ }, []);
1883
+ const handleCellClick = useCallback4((args) => {
1884
+ const fieldDefinition = tableDefinition?.fields.find((f) => f.name === args.column.key);
1885
+ const isFixedField = fixedFields?.some((f) => f.fieldName === args.column.key);
1886
+ const isEditable = fieldDefinition?.editable !== false && !isFixedField;
1887
+ console.log("Clicked column index:", args.column.idx);
1888
+ console.log("Clicked row index:", args.rowIdx);
1889
+ console.log("Is editable:", isEditable);
1890
+ }, [tableDefinition, fixedFields]);
1891
+ if (loading) {
1892
+ return /* @__PURE__ */ jsxs4(Box4, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: [
1893
+ /* @__PURE__ */ jsx9(CircularProgress, {}),
1894
+ /* @__PURE__ */ jsx9(Typography5, { variant: "h6", sx: { ml: 2 }, children: "Cargando tabla..." })
1895
+ ] });
1896
+ }
1897
+ if (error) {
1898
+ return /* @__PURE__ */ jsx9(Box4, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsx9(Alert, { severity: "error", children: error.message }) });
1899
+ }
1900
+ if (!tableDefinition) {
1901
+ return /* @__PURE__ */ jsx9(Box4, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsx9(Alert, { severity: "warning", children: "No se pudo cargar la definici\xF3n de la tabla." }) });
1902
+ }
1903
+ return /* @__PURE__ */ jsxs4(Box4, { sx: { p: 0, display: "flex", flexDirection: "column", height: "100%", boxSizing: "border-box" }, children: [
1904
+ /* @__PURE__ */ jsx9(Box4, { sx: { display: "flex", justifyContent: "space-between", alignItems: "center", px: 2, pt: 2, pb: 1 }, children: /* @__PURE__ */ jsx9(Typography5, { variant: "h4", gutterBottom: true, sx: { m: 0 }, children: cambiarGuionesBajosPorEspacios(tableDefinition.title || tableDefinition.name) }) }),
1905
+ tableDefinition.allow?.insert && /* @__PURE__ */ jsx9(Box4, { sx: { display: "flex", px: 2 }, children: /* @__PURE__ */ jsx9(
1906
+ Button2,
1907
+ {
1908
+ variant: "contained",
1909
+ onClick: handleAddRow,
1910
+ startIcon: /* @__PURE__ */ jsx9(AddIcon, {}),
1911
+ children: "Nuevo Registro"
1912
+ }
1913
+ ) }),
1914
+ /* @__PURE__ */ jsx9(Box4, { sx: { px: 2, pt: 2, pb: 1, fontSize: "0.9rem" }, children: filteredRows.length === tableData.length ? /* @__PURE__ */ jsxs4(Box4, { children: [
1915
+ "mostrando ",
1916
+ `${tableData.length} registros`
1917
+ ] }) : /* @__PURE__ */ jsx9(Fragment, { children: /* @__PURE__ */ jsxs4(Box4, { children: [
1918
+ "mostrando ",
1919
+ `${filteredRows.length} registros filtrados`
1920
+ ] }) }) }),
1921
+ /* @__PURE__ */ jsxs4(
1922
+ Box4,
1923
+ {
1924
+ sx: {
1925
+ flexGrow: showNoRowsMessage ? 0 : 1,
1926
+ height: showNoRowsMessage ? "150px" : "100%",
1927
+ boxSizing: "border-box",
1928
+ position: "relative",
1929
+ overflowX: "auto",
1930
+ overflowY: "auto",
1931
+ px: 2,
1932
+ pb: 2
1933
+ },
1934
+ children: [
1935
+ /* @__PURE__ */ jsx9(
1936
+ DataGrid,
1937
+ {
1938
+ ref: dataGridRef,
1939
+ columns,
1940
+ rows: filteredRows.map((row) => ({
1941
+ ...row,
1942
+ style: exitingRowIds.has(getPrimaryKeyValues(row, primaryKey)) ? { maxHeight: 0, opacity: 0, overflow: "hidden" } : { maxHeight: "35px", opacity: 1 }
1943
+ })),
1944
+ enableVirtualization: true,
1945
+ rowKeyGetter: (row) => getPrimaryKeyValues(row, primaryKey),
1946
+ onSelectedRowsChange: setSelectedRows,
1947
+ onRowsChange: handleRowsChange,
1948
+ selectedRows,
1949
+ rowHeight: (row) => exitingRowIds.has(getPrimaryKeyValues(row, primaryKey)) ? 0 : 35,
1950
+ style: { height: "100%", width: "100%", boxSizing: "border-box" },
1951
+ headerRowHeight: 35,
1952
+ topSummaryRows: isFilterRowVisible ? [{ id: "filterRow" }] : void 0,
1953
+ summaryRowHeight: isFilterRowVisible ? 35 : 0,
1954
+ onCellClick: handleCellClick
1955
+ }
1956
+ ),
1957
+ showNoRowsMessage && /* @__PURE__ */ jsx9(
1958
+ Box4,
1959
+ {
1960
+ sx: {
1961
+ position: "absolute",
1962
+ top: isFilterRowVisible ? "70px" : "36px",
1963
+ left: (theme2) => theme2.spacing(2),
1964
+ right: (theme2) => theme2.spacing(2),
1965
+ bottom: (theme2) => theme2.spacing(2),
1966
+ display: "flex",
1967
+ justifyContent: "center",
1968
+ alignItems: "center",
1969
+ backgroundColor: "rgba(255, 255, 255, 0.9)",
1970
+ color: (theme2) => theme2.palette.text.secondary,
1971
+ border: (theme2) => `1px solid ${theme2.palette.divider}`,
1972
+ borderRadius: "4px",
1973
+ zIndex: 1
1974
+ },
1975
+ children: /* @__PURE__ */ jsx9(Typography5, { variant: "h6", children: "No hay filas para mostrar." })
1976
+ }
1977
+ )
1978
+ ]
1979
+ }
1980
+ ),
1981
+ /* @__PURE__ */ jsx9(
1982
+ ConfirmDialog,
1983
+ {
1984
+ open: openConfirmDialog,
1985
+ onClose: handleConfirmDelete,
1986
+ title: "Confirmar Eliminaci\xF3n",
1987
+ message: rowToDelete && rowToDelete[NEW_ROW_INDICATOR] ? `\xBFEst\xE1s seguro de que quieres eliminar esta nueva fila (ID: ${getPrimaryKeyValues(rowToDelete, primaryKey)}) localmente?` : rowToDelete ? `\xBFEst\xE1s seguro de que quieres eliminar la fila con ID: ${getPrimaryKeyValues(rowToDelete, primaryKey)} de la base de datos? Esta acci\xF3n es irreversible.` : "\xBFEst\xE1s seguro de que quieres eliminar este registro? Esta acci\xF3n es irreversible."
1988
+ }
1989
+ )
1990
+ ] });
1991
+ };
1992
+ var GenericDataGrid_default = GenericDataGrid;
1993
+
1994
+ // src/App.tsx
1995
+ import React11, { useEffect as useEffect7 } from "react";
1996
+ import { BrowserRouter, Routes, Route, useLocation as useLocation4, Navigate as Navigate2 } from "react-router-dom";
1997
+
1998
+ // src/components/MainLayout.tsx
1999
+ import { useEffect as useEffect3 } from "react";
2000
+ import { Outlet } from "react-router-dom";
2001
+ import {
2002
+ Box as Box7,
2003
+ AppBar,
2004
+ Toolbar,
2005
+ Typography as Typography8,
2006
+ Button as Button3,
2007
+ Drawer,
2008
+ CssBaseline,
2009
+ IconButton as IconButton2,
2010
+ useTheme as useTheme2,
2011
+ useMediaQuery
2012
+ } from "@mui/material";
2013
+
2014
+ // src/contexts/AppContext.tsx
2015
+ import { createContext as createContext2, useContext as useContext2, useState as useState5, useEffect as useEffect2, useCallback as useCallback5, useMemo as useMemo3 } from "react";
2016
+ import { useNavigate } from "react-router-dom";
2017
+ import { useSelector as useSelector2, useDispatch as useDispatch2 } from "react-redux";
2018
+ import { jsx as jsx10 } from "react/jsx-runtime";
2019
+ var AuthContext = createContext2(void 0);
2020
+ var useApp = () => {
2021
+ const context = useContext2(AuthContext);
2022
+ if (!context) {
2023
+ throw new Error("useApp must be used within an AppProvider");
2024
+ }
2025
+ const clientContext = useSelector2((state) => state.clientContext);
2026
+ return { ...context, clientContext };
2027
+ };
2028
+ var AppProvider = ({ children }) => {
2029
+ console.log("AppProvider rendered/re-rendered");
2030
+ const [isLoggedIn, setIsLoggedIn] = useState5(false);
2031
+ const [showSessionExpiredMessage, setShowSessionExpiredMessage] = useState5(false);
2032
+ const dispatch = useDispatch2();
2033
+ const clientContext = useSelector2((state) => state.clientContext);
2034
+ const navigate = useNavigate();
2035
+ const checkSession = useCallback5(async () => {
2036
+ try {
2037
+ const response = await fetchApi("/keep-alive.json", { method: "GET" });
2038
+ if (response.ok) {
2039
+ setIsLoggedIn(true);
2040
+ setShowSessionExpiredMessage(false);
2041
+ if (clientContext.status === "idle" || clientContext.status === "failed") {
2042
+ console.log("Client context needs loading/reloading, dispatching fetchClientContext thunk...");
2043
+ try {
2044
+ await dispatch(fetchClientContext()).unwrap();
2045
+ console.log("Client context data loaded successfully by Redux.");
2046
+ } catch (loadError) {
2047
+ console.error("Error loading client context data during session check:", loadError);
2048
+ }
2049
+ }
2050
+ } else {
2051
+ setIsLoggedIn(false);
2052
+ dispatch(clearClientContext());
2053
+ if (!showSessionExpiredMessage && window.location.pathname !== "/login") {
2054
+ setShowSessionExpiredMessage(true);
2055
+ }
2056
+ }
2057
+ } catch (error) {
2058
+ console.error("Error checking session:", error);
2059
+ setIsLoggedIn(false);
2060
+ dispatch(clearClientContext());
2061
+ if (!showSessionExpiredMessage && window.location.pathname !== "/login") {
2062
+ setShowSessionExpiredMessage(true);
2063
+ }
2064
+ }
2065
+ }, [dispatch, clientContext.status, showSessionExpiredMessage]);
2066
+ useEffect2(() => {
2067
+ checkSession();
2068
+ const intervalId = setInterval(checkSession, 15 * 1e3);
2069
+ return () => {
2070
+ clearInterval(intervalId);
2071
+ };
2072
+ }, [checkSession]);
2073
+ const authContextValue = useMemo3(() => ({
2074
+ isLoggedIn,
2075
+ setIsLoggedIn,
2076
+ checkSession,
2077
+ showSessionExpiredMessage,
2078
+ setShowSessionExpiredMessage
2079
+ }), [
2080
+ isLoggedIn,
2081
+ setIsLoggedIn,
2082
+ checkSession,
2083
+ showSessionExpiredMessage,
2084
+ setShowSessionExpiredMessage
2085
+ ]);
2086
+ return /* @__PURE__ */ jsx10(AuthContext.Provider, { value: authContextValue, children });
2087
+ };
2088
+
2089
+ // src/components/MainLayout.tsx
2090
+ import LogoutIcon from "@mui/icons-material/Logout";
2091
+ import MenuIcon from "@mui/icons-material/Menu";
2092
+ import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
2093
+
2094
+ // src/components/SideMenu.tsx
2095
+ import { List, ListItem, ListItemButton, ListItemIcon, ListItemText, Divider, Box as Box6, Typography as Typography7, Collapse } from "@mui/material";
2096
+ import ExpandLess from "@mui/icons-material/ExpandLess";
2097
+ import ExpandMore from "@mui/icons-material/ExpandMore";
2098
+ import TableChartIcon from "@mui/icons-material/TableChart";
2099
+ import FolderIcon from "@mui/icons-material/Folder";
2100
+ import DnsIcon from "@mui/icons-material/Dns";
2101
+ import HomeIcon from "@mui/icons-material/Home";
2102
+ import WarningAmberIcon3 from "@mui/icons-material/WarningAmber";
2103
+ import DesktopWindowsIcon from "@mui/icons-material/DesktopWindows";
2104
+ import UnfoldMoreIcon from "@mui/icons-material/UnfoldMore";
2105
+ import UnfoldLessIcon from "@mui/icons-material/UnfoldLess";
2106
+ import { useNavigate as useNavigate2, useLocation } from "react-router-dom";
2107
+ import { blue, orange, teal, red, grey } from "@mui/material/colors";
2108
+
2109
+ // src/pages/WScreens.tsx
2110
+ import { Box as Box5, Typography as Typography6, Paper } from "@mui/material";
2111
+ import ConstructionIcon from "@mui/icons-material/Construction";
2112
+ import WarningAmberIcon2 from "@mui/icons-material/WarningAmber";
2113
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
2114
+ var MyCustomDashboard = ({ screenName }) => {
2115
+ return /* @__PURE__ */ jsx11(Box5, { sx: { p: 4, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100%" }, children: /* @__PURE__ */ jsxs5(Paper, { elevation: 3, sx: { p: 4, textAlign: "center", maxWidth: 600 }, children: [
2116
+ /* @__PURE__ */ jsxs5(Typography6, { variant: "h5", component: "h1", gutterBottom: true, children: [
2117
+ "\xA1Bienvenido a tu WScreen: ",
2118
+ screenName,
2119
+ "!"
2120
+ ] }),
2121
+ /* @__PURE__ */ jsx11(Typography6, { variant: "body1", color: "text.secondary", children: "Esta es una pantalla de interfaz de usuario personalizada." }),
2122
+ /* @__PURE__ */ jsx11(Box5, { sx: { mt: 3 }, children: /* @__PURE__ */ jsx11(ConstructionIcon, { sx: { fontSize: 80, color: "primary.main" } }) })
2123
+ ] }) });
2124
+ };
2125
+ var FallbackWScreen = ({ screenName }) => {
2126
+ return /* @__PURE__ */ jsx11(Box5, { sx: { p: 4, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100%" }, children: /* @__PURE__ */ jsxs5(Paper, { elevation: 3, sx: { p: 4, textAlign: "center", maxWidth: 600, backgroundColor: "warning.light", border: "1px solid orange" }, children: [
2127
+ /* @__PURE__ */ jsx11(Typography6, { variant: "h5", component: "h1", gutterBottom: true, color: "warning.dark", children: "WScreen No Implementada" }),
2128
+ /* @__PURE__ */ jsxs5(Typography6, { variant: "body1", color: "warning.dark", children: [
2129
+ 'No se encontr\xF3 un componente implementado para la **WScreen**: **`"$',
2130
+ screenName,
2131
+ '"`**. Por favor, verifica el `menuType` en la definici\xF3n del men\xFA o aseg\xFArate de que el componente est\xE9 correctamente importado y mapeado en el frontend.'
2132
+ ] }),
2133
+ /* @__PURE__ */ jsx11(Box5, { sx: { mt: 3 }, children: /* @__PURE__ */ jsx11(WarningAmberIcon2, { sx: { fontSize: 80, color: "warning.dark" } }) })
2134
+ ] }) });
2135
+ };
2136
+ var wScreens = {
2137
+ "MyCustomDashboard": MyCustomDashboard
2138
+ // Agrega más componentes de wScreen aquí:
2139
+ // 'AnotherWScreen': AnotherWScreenComponent,
2140
+ };
2141
+ var WScreens_default = FallbackWScreen;
2142
+
2143
+ // src/components/SideMenu.tsx
2144
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
2145
+ var MenuListItem = ({ item, level, onMenuItemClick }) => {
2146
+ const navigate = useNavigate2();
2147
+ const location = useLocation();
2148
+ const open = useSubMenuOpenState(item.name);
2149
+ const dispatch = useAppDispatch();
2150
+ const handleClick = () => {
2151
+ if (item.menuType === "menu") {
2152
+ dispatch(toggleSubMenu(item.name));
2153
+ } else {
2154
+ let path = "";
2155
+ const queryParams = new URLSearchParams();
2156
+ if (item.menuType === "table") {
2157
+ path = `/menu/${item.name}`;
2158
+ if (item.td) queryParams.append("td", JSON.stringify(item.td));
2159
+ if (item.fc) queryParams.append("fc", JSON.stringify(item.fc));
2160
+ if (queryParams.toString()) {
2161
+ path = `${path}?${queryParams.toString()}`;
2162
+ }
2163
+ } else if (item.menuType === "proc") {
2164
+ path = `/procedures/${item.name}`;
2165
+ } else {
2166
+ const WScreenComponent = wScreens[item.menuType];
2167
+ if (WScreenComponent !== void 0) {
2168
+ path = `/wScreens/${item.menuType}`;
2169
+ } else {
2170
+ path = `/wScreens-fallback/${item.menuType}`;
2171
+ console.warn(`Menu type '${item.menuType}' no reconocido o WScreen no mapeada.`);
2172
+ }
2173
+ }
2174
+ if (path) {
2175
+ navigate(path);
2176
+ }
2177
+ if (onMenuItemClick) {
2178
+ onMenuItemClick();
2179
+ }
2180
+ }
2181
+ };
2182
+ const getIcon = (item2) => {
2183
+ switch (item2.menuType) {
2184
+ case "table":
2185
+ return /* @__PURE__ */ jsx12(TableChartIcon, { sx: { color: blue[700] } });
2186
+ case "proc":
2187
+ return /* @__PURE__ */ jsx12(DnsIcon, { sx: { color: teal[700] } });
2188
+ case "menu":
2189
+ return /* @__PURE__ */ jsx12(FolderIcon, { sx: { color: orange[800] } });
2190
+ default:
2191
+ const WScreenComponent = wScreens[item2.menuType];
2192
+ if (WScreenComponent !== void 0) {
2193
+ return /* @__PURE__ */ jsx12(DesktopWindowsIcon, { sx: { color: grey[700] } });
2194
+ }
2195
+ return /* @__PURE__ */ jsx12(WarningAmberIcon3, { sx: { color: red[500] } });
2196
+ }
2197
+ };
2198
+ const currentPath = location.pathname;
2199
+ let isSelected = false;
2200
+ if (item.menuType === "table") {
2201
+ isSelected = currentPath === `/menu/table/${item.name}`;
2202
+ } else if (item.menuType === "proc") {
2203
+ isSelected = currentPath === `/procedures/${item.name}`;
2204
+ } else {
2205
+ isSelected = currentPath.startsWith(`/wScreens/${item.menuType}`) || currentPath.startsWith(`/wScreens-fallback/${item.menuType}`);
2206
+ }
2207
+ return /* @__PURE__ */ jsxs6(Fragment2, { children: [
2208
+ /* @__PURE__ */ jsxs6(
2209
+ ListItemButton,
2210
+ {
2211
+ onClick: handleClick,
2212
+ sx: { pl: level * 2 },
2213
+ selected: isSelected,
2214
+ children: [
2215
+ /* @__PURE__ */ jsx12(ListItemIcon, { sx: { minWidth: "38px" }, children: getIcon(item) }),
2216
+ /* @__PURE__ */ jsx12(ListItemText, { primary: item.label || item.name }),
2217
+ item.menuType === "menu" ? open ? /* @__PURE__ */ jsx12(ExpandLess, {}) : /* @__PURE__ */ jsx12(ExpandMore, {}) : null
2218
+ ]
2219
+ }
2220
+ ),
2221
+ item.menuType === "menu" && /* @__PURE__ */ jsx12(Collapse, { in: open, timeout: "auto", unmountOnExit: true, children: /* @__PURE__ */ jsx12(List, { component: "div", disablePadding: true, children: item.menuContent.map((subItem) => /* @__PURE__ */ jsx12(
2222
+ MenuListItem,
2223
+ {
2224
+ item: subItem,
2225
+ level: level + 1,
2226
+ onMenuItemClick
2227
+ },
2228
+ subItem.name
2229
+ )) }) })
2230
+ ] });
2231
+ };
2232
+ var SideMenu = ({ onMenuItemClick }) => {
2233
+ const { clientContext } = useApp();
2234
+ const navigate = useNavigate2();
2235
+ const location = useLocation();
2236
+ const dispatch = useAppDispatch();
2237
+ const subMenuOpenStates = useAppSelector((state) => state.menuUi.subMenuOpenStates);
2238
+ const allSubMenusKeys = Object.keys(subMenuOpenStates);
2239
+ const openSubMenusCount = allSubMenusKeys.filter((key) => subMenuOpenStates[key]).length;
2240
+ const isMostlyOpen = allSubMenusKeys.length > 0 && openSubMenusCount / allSubMenusKeys.length > 0.5;
2241
+ const handleHomeClick = () => {
2242
+ navigate("/home");
2243
+ if (onMenuItemClick) {
2244
+ onMenuItemClick();
2245
+ }
2246
+ };
2247
+ const handleToggleAllSubMenus = () => {
2248
+ dispatch(setAllSubMenusOpen(!isMostlyOpen));
2249
+ };
2250
+ if (!clientContext || !clientContext.menu) {
2251
+ return /* @__PURE__ */ jsx12(Box6, { sx: { p: 2, textAlign: "center" }, children: /* @__PURE__ */ jsx12(Typography7, { variant: "body2", color: "text.secondary", children: "Cargando men\xFA..." }) });
2252
+ }
2253
+ const isHomeSelected = location.pathname === "/home";
2254
+ return /* @__PURE__ */ jsxs6(Box6, { sx: { width: "100%", flexShrink: 0 }, children: [
2255
+ clientContext.menu.some((item) => item.menuType === "menu") && /* @__PURE__ */ jsx12(ListItem, { disablePadding: true, children: /* @__PURE__ */ jsxs6(ListItemButton, { onClick: handleToggleAllSubMenus, children: [
2256
+ /* @__PURE__ */ jsx12(ListItemIcon, { sx: { minWidth: "38px" }, children: isMostlyOpen ? /* @__PURE__ */ jsx12(UnfoldLessIcon, {}) : /* @__PURE__ */ jsx12(UnfoldMoreIcon, {}) }),
2257
+ /* @__PURE__ */ jsx12(ListItemText, { primary: isMostlyOpen ? "colapsar " : "expandir" })
2258
+ ] }) }),
2259
+ /* @__PURE__ */ jsx12(Divider, {}),
2260
+ /* @__PURE__ */ jsxs6(List, { children: [
2261
+ /* @__PURE__ */ jsx12(ListItem, { disablePadding: true, children: /* @__PURE__ */ jsxs6(ListItemButton, { onClick: handleHomeClick, selected: isHomeSelected, children: [
2262
+ /* @__PURE__ */ jsx12(ListItemIcon, { sx: { minWidth: "38px" }, children: /* @__PURE__ */ jsx12(HomeIcon, {}) }),
2263
+ /* @__PURE__ */ jsx12(ListItemText, { primary: "Inicio" })
2264
+ ] }) }),
2265
+ /* @__PURE__ */ jsx12(Divider, {}),
2266
+ clientContext.menu.map((menuItem) => /* @__PURE__ */ jsx12(
2267
+ MenuListItem,
2268
+ {
2269
+ item: menuItem,
2270
+ level: 1,
2271
+ onMenuItemClick
2272
+ },
2273
+ menuItem.name
2274
+ ))
2275
+ ] })
2276
+ ] });
2277
+ };
2278
+ var SideMenu_default = SideMenu;
2279
+
2280
+ // src/hooks/useLogout.tsx
2281
+ import { useCallback as useCallback6 } from "react";
2282
+ import { useNavigate as useNavigate3 } from "react-router-dom";
2283
+ import { useDispatch as useDispatch3 } from "react-redux";
2284
+ var useLogout = () => {
2285
+ const { setIsLoggedIn } = useApp();
2286
+ const dispatch = useDispatch3();
2287
+ const navigate = useNavigate3();
2288
+ const logout = useCallback6(async () => {
2289
+ try {
2290
+ const response = await fetchApi("/logout", { method: "GET" });
2291
+ if (response.status === 401 || response.ok) {
2292
+ console.log("Sesi\xF3n cerrada correctamente o ya deslogueado");
2293
+ } else {
2294
+ console.error("Error al cerrar sesi\xF3n:", await response.text());
2295
+ }
2296
+ } catch (error) {
2297
+ console.error("Error de red al intentar cerrar sesi\xF3n:", error);
2298
+ } finally {
2299
+ setIsLoggedIn(false);
2300
+ dispatch(clearClientContext());
2301
+ navigate("/login", { replace: true });
2302
+ }
2303
+ }, [setIsLoggedIn, dispatch, navigate]);
2304
+ return logout;
2305
+ };
2306
+ var useLogout_default = useLogout;
2307
+
2308
+ // src/components/MainLayout.tsx
2309
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
2310
+ var drawerWidth = 240;
2311
+ var MainLayout = () => {
2312
+ const { clientContext } = useApp();
2313
+ const logout = useLogout_default();
2314
+ const isDrawerOpen = useIsDrawerOpen();
2315
+ const dispatch = useAppDispatch();
2316
+ const theme = useTheme2();
2317
+ const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
2318
+ useEffect3(() => {
2319
+ if (isMobile && isDrawerOpen) {
2320
+ dispatch(setDrawerOpen(false));
2321
+ }
2322
+ }, [isMobile, isDrawerOpen, dispatch]);
2323
+ const handleToggleDrawer = () => {
2324
+ dispatch(toggleDrawer());
2325
+ };
2326
+ const handleDrawerCloseMobile = () => {
2327
+ if (isMobile && isDrawerOpen) {
2328
+ dispatch(setDrawerOpen(false));
2329
+ }
2330
+ };
2331
+ if (!clientContext) {
2332
+ return /* @__PURE__ */ jsx13(Box7, { sx: { display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }, children: /* @__PURE__ */ jsx13(Typography8, { children: "Cargando dise\xF1o de la aplicaci\xF3n..." }) });
2333
+ }
2334
+ const appBarOffset = theme.mixins.toolbar;
2335
+ return /* @__PURE__ */ jsxs7(Box7, { sx: { display: "flex", height: "100vh" }, children: [
2336
+ /* @__PURE__ */ jsx13(CssBaseline, {}),
2337
+ /* @__PURE__ */ jsx13(
2338
+ AppBar,
2339
+ {
2340
+ position: "fixed",
2341
+ sx: {
2342
+ zIndex: (theme2) => theme2.zIndex.drawer + 1,
2343
+ transition: (theme2) => theme2.transitions.create(["width", "margin"], {
2344
+ easing: theme2.transitions.easing.sharp,
2345
+ duration: theme2.transitions.duration.leavingScreen
2346
+ }),
2347
+ ...isDrawerOpen && {
2348
+ width: `calc(100% - ${drawerWidth}px)`,
2349
+ marginLeft: `${drawerWidth}px`,
2350
+ transition: (theme2) => theme2.transitions.create(["width", "margin"], {
2351
+ easing: theme2.transitions.easing.easeOut,
2352
+ duration: theme2.transitions.duration.enteringScreen
2353
+ })
2354
+ }
2355
+ },
2356
+ children: /* @__PURE__ */ jsxs7(Toolbar, { children: [
2357
+ /* @__PURE__ */ jsx13(
2358
+ IconButton2,
2359
+ {
2360
+ color: "inherit",
2361
+ "aria-label": "open drawer",
2362
+ onClick: handleToggleDrawer,
2363
+ edge: "start",
2364
+ sx: {
2365
+ marginRight: 2.2
2366
+ },
2367
+ children: isDrawerOpen ? /* @__PURE__ */ jsx13(ChevronLeftIcon, {}) : /* @__PURE__ */ jsx13(MenuIcon, {})
2368
+ }
2369
+ ),
2370
+ /* @__PURE__ */ jsx13(Typography8, { variant: "h6", noWrap: true, component: "div", sx: { flexGrow: 1 }, children: isDrawerOpen ? "" : clientContext.config.title }),
2371
+ /* @__PURE__ */ jsx13(Typography8, { variant: "subtitle1", component: "div", sx: { mr: 2 }, children: clientContext.username }),
2372
+ /* @__PURE__ */ jsx13(
2373
+ Button3,
2374
+ {
2375
+ color: "inherit",
2376
+ onClick: logout,
2377
+ startIcon: /* @__PURE__ */ jsx13(LogoutIcon, {}),
2378
+ children: "Salir"
2379
+ }
2380
+ )
2381
+ ] })
2382
+ }
2383
+ ),
2384
+ /* @__PURE__ */ jsxs7(
2385
+ Drawer,
2386
+ {
2387
+ variant: "persistent",
2388
+ anchor: "left",
2389
+ open: isDrawerOpen,
2390
+ sx: {
2391
+ width: drawerWidth,
2392
+ flexShrink: 0,
2393
+ "& .MuiDrawer-paper": {
2394
+ width: drawerWidth,
2395
+ boxSizing: "border-box",
2396
+ overflowX: "hidden",
2397
+ overflowY: "auto"
2398
+ }
2399
+ },
2400
+ children: [
2401
+ /* @__PURE__ */ jsx13(
2402
+ Toolbar,
2403
+ {
2404
+ sx: {
2405
+ display: "flex",
2406
+ alignItems: "center",
2407
+ justifyContent: "flex-end",
2408
+ px: 1,
2409
+ fontSize: "1.3rem",
2410
+ minHeight: theme.mixins.toolbar.minHeight
2411
+ },
2412
+ children: isDrawerOpen ? clientContext.config.title : ""
2413
+ }
2414
+ ),
2415
+ /* @__PURE__ */ jsx13(SideMenu_default, { onMenuItemClick: handleDrawerCloseMobile })
2416
+ ]
2417
+ }
2418
+ ),
2419
+ /* @__PURE__ */ jsx13(
2420
+ Box7,
2421
+ {
2422
+ component: "main",
2423
+ sx: {
2424
+ flexGrow: 1,
2425
+ transition: (theme2) => theme2.transitions.create("margin", {
2426
+ easing: theme2.transitions.easing.sharp,
2427
+ duration: theme2.transitions.duration.leavingScreen
2428
+ }),
2429
+ marginLeft: `-${drawerWidth}px`,
2430
+ ...isDrawerOpen && {
2431
+ transition: (theme2) => theme2.transitions.create("margin", {
2432
+ easing: theme2.transitions.easing.easeOut,
2433
+ duration: theme2.transitions.duration.enteringScreen
2434
+ }),
2435
+ marginLeft: 0
2436
+ },
2437
+ minWidth: 0,
2438
+ flexShrink: 0,
2439
+ // Asegúrate de que el paddingTop sea suficiente para la AppBar
2440
+ paddingTop: `${appBarOffset.minHeight}px`,
2441
+ height: "100%",
2442
+ boxSizing: "border-box",
2443
+ display: "flex",
2444
+ flexDirection: "column",
2445
+ width: isDrawerOpen ? `calc(100% - ${drawerWidth}px)` : "100%"
2446
+ },
2447
+ children: /* @__PURE__ */ jsx13(Outlet, {})
2448
+ }
2449
+ )
2450
+ ] });
2451
+ };
2452
+ var MainLayout_default = MainLayout;
2453
+
2454
+ // src/components/SessionExpiredMessage.tsx
2455
+ import { Box as Box8, Typography as Typography9, Button as Button4, Modal } from "@mui/material";
2456
+ import { useNavigate as useNavigate4 } from "react-router-dom";
2457
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
2458
+ var style = {
2459
+ position: "absolute",
2460
+ top: "50%",
2461
+ left: "50%",
2462
+ transform: "translate(-50%, -50%)",
2463
+ width: 400,
2464
+ bgcolor: "background.paper",
2465
+ border: "2px solid #000",
2466
+ boxShadow: 24,
2467
+ p: 4,
2468
+ textAlign: "center",
2469
+ borderRadius: 2
2470
+ };
2471
+ var SessionExpiredMessage = () => {
2472
+ const { showSessionExpiredMessage, setShowSessionExpiredMessage, setIsLoggedIn } = useApp();
2473
+ const navigate = useNavigate4();
2474
+ const handleClose = () => {
2475
+ setShowSessionExpiredMessage(false);
2476
+ setIsLoggedIn(false);
2477
+ navigate("/login", { replace: true });
2478
+ };
2479
+ return /* @__PURE__ */ jsx14(
2480
+ Modal,
2481
+ {
2482
+ open: showSessionExpiredMessage,
2483
+ onClose: () => {
2484
+ },
2485
+ "aria-labelledby": "session-expired-modal-title",
2486
+ "aria-describedby": "session-expired-modal-description",
2487
+ disableEscapeKeyDown: true,
2488
+ slotProps: {
2489
+ backdrop: {
2490
+ // Esto es crucial en MUI v5: detiene la propagación del evento de clic en el backdrop,
2491
+ // impidiendo que el modal se cierre al hacer clic fuera.
2492
+ onClick: (event) => event.stopPropagation(),
2493
+ sx: {
2494
+ backgroundColor: "rgba(100, 100, 100, 0.95)"
2495
+ // Ajusta el color y la opacidad para un fondo más oscuro
2496
+ }
2497
+ }
2498
+ },
2499
+ children: /* @__PURE__ */ jsxs8(Box8, { sx: style, children: [
2500
+ /* @__PURE__ */ jsx14(Typography9, { id: "session-expired-modal-title", variant: "h6", component: "h2", gutterBottom: true, children: "\xA1Sesi\xF3n Expirada!" }),
2501
+ /* @__PURE__ */ jsx14(Typography9, { id: "session-expired-modal-description", sx: { mt: 2, mb: 3 }, children: "Tu sesi\xF3n ha expirado por inactividad o por seguridad. Por favor, inicia sesi\xF3n de nuevo." }),
2502
+ /* @__PURE__ */ jsx14(Button4, { variant: "contained", color: "primary", onClick: handleClose, children: "Ir al Login" })
2503
+ ] })
2504
+ }
2505
+ );
2506
+ };
2507
+ var SessionExpiredMessage_default = SessionExpiredMessage;
2508
+
2509
+ // src/pages/HomePage.tsx
2510
+ import { Box as Box9, Typography as Typography10 } from "@mui/material";
2511
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
2512
+ var HomePage = () => {
2513
+ const { clientContext } = useApp();
2514
+ return /* @__PURE__ */ jsxs9(Box9, { sx: { p: 3 }, children: [
2515
+ /* @__PURE__ */ jsx15(Typography10, { variant: "h4", component: "h1", gutterBottom: true, children: `Bienvenido/a ${clientContext?.username}` }),
2516
+ /* @__PURE__ */ jsx15(Typography10, { variant: "body1", children: "Usa el men\xFA lateral para navegar por las diferentes secciones." })
2517
+ ] });
2518
+ };
2519
+ var HomePage_default = HomePage;
2520
+
2521
+ // src/pages/LogoutPage.tsx
2522
+ import { useEffect as useEffect4 } from "react";
2523
+ import { Box as Box10, Typography as Typography11, CircularProgress as CircularProgress2 } from "@mui/material";
2524
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
2525
+ var LogoutPage = () => {
2526
+ const logout = useLogout_default();
2527
+ useEffect4(() => {
2528
+ logout();
2529
+ }, [logout]);
2530
+ return /* @__PURE__ */ jsxs10(Box10, { sx: {
2531
+ display: "flex",
2532
+ flexDirection: "column",
2533
+ justifyContent: "center",
2534
+ alignItems: "center",
2535
+ height: "100vh",
2536
+ textAlign: "center"
2537
+ }, children: [
2538
+ /* @__PURE__ */ jsx16(CircularProgress2, { size: 60 }),
2539
+ /* @__PURE__ */ jsx16(Typography11, { variant: "h6", sx: { mt: 2 }, children: "Cerrando sesi\xF3n..." })
2540
+ ] });
2541
+ };
2542
+ var LogoutPage_default = LogoutPage;
2543
+
2544
+ // src/pages/LoginPage.tsx
2545
+ import { useState as useState6 } from "react";
2546
+ import { Button as Button5, TextField, Typography as Typography12, Alert as Alert2, AlertTitle, Box as Box11, CircularProgress as CircularProgress3 } from "@mui/material";
2547
+ import { useForm, Controller } from "react-hook-form";
2548
+ import { zodResolver } from "@hookform/resolvers/zod";
2549
+ import * as z from "zod";
2550
+ import { useNavigate as useNavigate5 } from "react-router-dom";
2551
+ import { useDispatch as useDispatch4 } from "react-redux";
2552
+ import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2553
+ var loginSchema = z.object({
2554
+ username: z.string().min(1, "El usuario es requerido"),
2555
+ // Añadir validación básica
2556
+ password: z.string().min(1, "La contrase\xF1a es requerida")
2557
+ // Añadir validación básica
2558
+ });
2559
+ var LoginPage = () => {
2560
+ const navigate = useNavigate5();
2561
+ const [loginError, setLoginError] = useState6(null);
2562
+ const [isSubmitting, setIsSubmitting] = useState6(false);
2563
+ const { setIsLoggedIn, checkSession } = useApp();
2564
+ const dispatch = useDispatch4();
2565
+ const {
2566
+ control,
2567
+ handleSubmit,
2568
+ formState: { errors },
2569
+ reset
2570
+ } = useForm({
2571
+ resolver: zodResolver(loginSchema),
2572
+ defaultValues: {
2573
+ username: "",
2574
+ password: ""
2575
+ }
2576
+ });
2577
+ const onSubmit = async (data) => {
2578
+ setIsSubmitting(true);
2579
+ setLoginError(null);
2580
+ try {
2581
+ const body = new URLSearchParams({
2582
+ username: data.username,
2583
+ password: data.password
2584
+ });
2585
+ const loginResponse = await fetchApi("/login", {
2586
+ method: "POST",
2587
+ body
2588
+ // URLSearchParams se envía directamente como body para form-urlencoded
2589
+ // Asegúrate de que el Content-Type en el backend maneje 'application/x-www-form-urlencoded'
2590
+ });
2591
+ if (!loginResponse.ok || !loginResponse.url.endsWith("/menu")) {
2592
+ const errorText = "Credenciales incorrectas o error al iniciar sesi\xF3n";
2593
+ throw new Error(errorText);
2594
+ }
2595
+ setIsLoggedIn(true);
2596
+ await dispatch(fetchClientContext()).unwrap();
2597
+ console.log("Login exitoso y clientContext cargado.");
2598
+ navigate("/home");
2599
+ reset();
2600
+ } catch (error) {
2601
+ console.error("Error al iniciar sesi\xF3n:", error);
2602
+ setIsLoggedIn(false);
2603
+ setLoginError(error.message || "Ocurri\xF3 un error al iniciar sesi\xF3n. Int\xE9ntalo de nuevo.");
2604
+ } finally {
2605
+ setIsSubmitting(false);
2606
+ }
2607
+ };
2608
+ return /* @__PURE__ */ jsx17(
2609
+ Box11,
2610
+ {
2611
+ display: "flex",
2612
+ alignItems: "center",
2613
+ justifyContent: "center",
2614
+ minHeight: "100vh",
2615
+ bgcolor: "#f5f5f5",
2616
+ children: /* @__PURE__ */ jsxs11(
2617
+ Box11,
2618
+ {
2619
+ width: "100%",
2620
+ maxWidth: "400px",
2621
+ padding: 4,
2622
+ bgcolor: "white",
2623
+ borderRadius: 8,
2624
+ boxShadow: 3,
2625
+ children: [
2626
+ /* @__PURE__ */ jsx17(Typography12, { variant: "h5", align: "center", gutterBottom: true, children: "Iniciar Sesi\xF3n" }),
2627
+ /* @__PURE__ */ jsxs11("form", { onSubmit: handleSubmit(onSubmit), className: "space-y-4", children: [
2628
+ /* @__PURE__ */ jsxs11("div", { children: [
2629
+ /* @__PURE__ */ jsx17("label", { htmlFor: "username", children: /* @__PURE__ */ jsx17(Typography12, { variant: "subtitle1", component: "div", sx: { fontWeight: "medium" }, children: "Usuario" }) }),
2630
+ /* @__PURE__ */ jsx17(
2631
+ Controller,
2632
+ {
2633
+ name: "username",
2634
+ control,
2635
+ render: ({ field }) => /* @__PURE__ */ jsx17(
2636
+ TextField,
2637
+ {
2638
+ ...field,
2639
+ type: "text",
2640
+ placeholder: "Ingresa tu usuario",
2641
+ fullWidth: true,
2642
+ margin: "normal",
2643
+ error: !!errors.username,
2644
+ helperText: errors.username?.message,
2645
+ disabled: isSubmitting
2646
+ }
2647
+ )
2648
+ }
2649
+ )
2650
+ ] }),
2651
+ /* @__PURE__ */ jsxs11("div", { children: [
2652
+ /* @__PURE__ */ jsx17("label", { htmlFor: "password", children: /* @__PURE__ */ jsx17(Typography12, { variant: "subtitle1", component: "div", sx: { fontWeight: "medium" }, children: "Contrase\xF1a" }) }),
2653
+ /* @__PURE__ */ jsx17(
2654
+ Controller,
2655
+ {
2656
+ name: "password",
2657
+ control,
2658
+ render: ({ field }) => /* @__PURE__ */ jsx17(
2659
+ TextField,
2660
+ {
2661
+ ...field,
2662
+ type: "password",
2663
+ placeholder: "Ingresa tu contrase\xF1a",
2664
+ fullWidth: true,
2665
+ margin: "normal",
2666
+ error: !!errors.password,
2667
+ helperText: errors.password?.message,
2668
+ disabled: isSubmitting
2669
+ }
2670
+ )
2671
+ }
2672
+ )
2673
+ ] }),
2674
+ /* @__PURE__ */ jsx17(Button5, { type: "submit", fullWidth: true, variant: "contained", color: "primary", disabled: isSubmitting, sx: { mt: 2 }, children: isSubmitting ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
2675
+ /* @__PURE__ */ jsx17(CircularProgress3, { size: 20, sx: { mr: 1 } }),
2676
+ "Iniciando sesi\xF3n..."
2677
+ ] }) : "Iniciar Sesi\xF3n" })
2678
+ ] }),
2679
+ loginError && /* @__PURE__ */ jsxs11(Alert2, { severity: "error", sx: { mt: 2, maxHeight: "200px" }, children: [
2680
+ " ",
2681
+ /* @__PURE__ */ jsx17(AlertTitle, { children: "Error" }),
2682
+ loginError
2683
+ ] })
2684
+ ]
2685
+ }
2686
+ )
2687
+ }
2688
+ );
2689
+ };
2690
+ var LoginPage_default = LoginPage;
2691
+
2692
+ // src/components/ProcedureForm.tsx
2693
+ import React7, { useState as useState7, useCallback as useCallback7, useMemo as useMemo4 } from "react";
2694
+ import { useParams } from "react-router-dom";
2695
+ import {
2696
+ TextField as TextField2,
2697
+ Button as Button6,
2698
+ FormControl,
2699
+ InputLabel,
2700
+ Select,
2701
+ MenuItem,
2702
+ Checkbox,
2703
+ FormControlLabel,
2704
+ FormHelperText,
2705
+ Typography as Typography14,
2706
+ Box as Box13,
2707
+ CircularProgress as CircularProgress4,
2708
+ Alert as Alert3,
2709
+ Divider as Divider2,
2710
+ Paper as Paper3
2711
+ } from "@mui/material";
2712
+
2713
+ // src/pages/procedure-results/SuccessDisplay.tsx
2714
+ import { Box as Box12, Typography as Typography13, Paper as Paper2 } from "@mui/material";
2715
+ import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
2716
+ var SuccessDisplay = ({ data }) => {
2717
+ return /* @__PURE__ */ jsxs12(Paper2, { elevation: 2, sx: { p: 2, mt: 2, bgcolor: "success.light", color: "success.contrastText" }, children: [
2718
+ /* @__PURE__ */ jsx18(Typography13, { variant: "h6", sx: { fontSize: "1rem", mb: 1 }, children: "\xA1Operaci\xF3n Exitosa!" }),
2719
+ /* @__PURE__ */ jsx18(Typography13, { variant: "body2", sx: { fontSize: "0.85rem" }, children: "Detalles del resultado:" }),
2720
+ /* @__PURE__ */ jsx18(Box12, { sx: { bgcolor: "success.dark", p: 1, borderRadius: 1, mt: 1, overflowX: "auto" }, children: /* @__PURE__ */ jsx18("pre", { style: { margin: 0, fontSize: "0.75rem", color: "white" }, children: JSON.stringify(data, null, 2) }) }),
2721
+ /* @__PURE__ */ jsx18(Typography13, { variant: "body2", sx: { fontSize: "0.8rem", mt: 1 }, children: "Puedes revisar los detalles anteriores o cerrar este mensaje." })
2722
+ ] });
2723
+ };
2724
+ var SuccessDisplay_default = SuccessDisplay;
2725
+
2726
+ // src/pages/procedure-results/resultsOk.ts
2727
+ var resultsOk = {
2728
+ "successful_operation": SuccessDisplay_default
2729
+ };
2730
+ var extendResultsOk = (newComponents) => {
2731
+ resultsOk = { ...resultsOk, ...newComponents };
2732
+ };
2733
+
2734
+ // src/components/ProcedureForm.tsx
2735
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
2736
+ var ProcedureForm = () => {
2737
+ const { procedureName } = useParams();
2738
+ const { clientContext } = useApp();
2739
+ const { callApi, loading: apiLoading, error: apiError } = useApiCall();
2740
+ const [validationErrors, setValidationErrors] = useState7({});
2741
+ const [successMessage, setSuccessMessage] = useState7(null);
2742
+ const [executionLog, setExecutionLog] = useState7([]);
2743
+ const [procedureResultData, setProcedureResultData] = useState7(null);
2744
+ const procedure = useMemo4(() => {
2745
+ if (procedureName && clientContext?.procedure) {
2746
+ return clientContext.procedure[procedureName];
2747
+ }
2748
+ return void 0;
2749
+ }, [procedureName, clientContext]);
2750
+ const [formValues, setFormValues] = useState7(() => {
2751
+ if (!procedure) return {};
2752
+ const initialValues = {};
2753
+ procedure.parameters.forEach((param) => {
2754
+ if (param.defaultValue !== void 0) {
2755
+ initialValues[param.name] = param.defaultValue;
2756
+ } else if (param.specialDefaultValue) {
2757
+ switch (param.specialDefaultValue) {
2758
+ case "current_date":
2759
+ initialValues[param.name] = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2760
+ break;
2761
+ case "current_datetime":
2762
+ const now = /* @__PURE__ */ new Date();
2763
+ initialValues[param.name] = now.toISOString().substring(0, 16);
2764
+ break;
2765
+ default:
2766
+ initialValues[param.name] = param.specialDefaultValue;
2767
+ break;
2768
+ }
2769
+ } else {
2770
+ initialValues[param.name] = "";
2771
+ }
2772
+ });
2773
+ return initialValues;
2774
+ });
2775
+ React7.useEffect(() => {
2776
+ if (procedure) {
2777
+ setValidationErrors({});
2778
+ setSuccessMessage(null);
2779
+ setProcedureResultData(null);
2780
+ const newInitialValues = {};
2781
+ procedure.parameters.forEach((param) => {
2782
+ if (param.defaultValue !== void 0) {
2783
+ newInitialValues[param.name] = param.defaultValue;
2784
+ } else if (param.specialDefaultValue) {
2785
+ switch (param.specialDefaultValue) {
2786
+ case "current_date":
2787
+ newInitialValues[param.name] = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2788
+ break;
2789
+ case "current_datetime":
2790
+ const now = /* @__PURE__ */ new Date();
2791
+ newInitialValues[param.name] = now.toISOString().substring(0, 16);
2792
+ break;
2793
+ default:
2794
+ newInitialValues[param.name] = param.specialDefaultValue;
2795
+ break;
2796
+ }
2797
+ } else {
2798
+ newInitialValues[param.name] = "";
2799
+ }
2800
+ });
2801
+ setFormValues(newInitialValues);
2802
+ setExecutionLog([]);
2803
+ }
2804
+ }, [procedure]);
2805
+ const addLogMessage = useCallback7((message, isError = false) => {
2806
+ const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString("es-AR");
2807
+ setExecutionLog((prev) => [...prev, `[${timestamp}] ${isError ? "ERROR: " : ""}${message}`]);
2808
+ }, []);
2809
+ const handleChange = useCallback7((e, child) => {
2810
+ const { name, value } = e.target;
2811
+ let newValue = value;
2812
+ if (e.target.type === "checkbox") {
2813
+ newValue = e.target.checked;
2814
+ }
2815
+ setFormValues((prevValues) => ({
2816
+ ...prevValues,
2817
+ [name]: newValue
2818
+ }));
2819
+ setValidationErrors((prev) => ({ ...prev, [name]: null }));
2820
+ setSuccessMessage(null);
2821
+ setProcedureResultData(null);
2822
+ }, []);
2823
+ const handleSubmit = async (e) => {
2824
+ e.preventDefault();
2825
+ setValidationErrors({});
2826
+ setSuccessMessage(null);
2827
+ setExecutionLog([]);
2828
+ setProcedureResultData(null);
2829
+ if (!procedure) {
2830
+ addLogMessage("Error: La definici\xF3n del procedimiento no est\xE1 disponible.", true);
2831
+ return;
2832
+ }
2833
+ addLogMessage(`Iniciando ejecuci\xF3n del procedimiento: ${procedure.action}...`);
2834
+ const paramsToSend = {};
2835
+ let currentValidationErrors = {};
2836
+ let hasOverallError = false;
2837
+ for (const param of procedure.parameters) {
2838
+ let value = formValues[param.name];
2839
+ let processedValue = value;
2840
+ let paramError = null;
2841
+ switch (param.typeName) {
2842
+ case "decimal":
2843
+ case "double":
2844
+ if (value === "" || value === null) {
2845
+ processedValue = null;
2846
+ } else {
2847
+ processedValue = parseFloat(value);
2848
+ if (isNaN(processedValue)) {
2849
+ paramError = `El valor para "${param.label || param.name}" no es un n\xFAmero v\xE1lido.`;
2850
+ }
2851
+ }
2852
+ break;
2853
+ case "integer":
2854
+ case "bigint":
2855
+ if (value === "" || value === null) {
2856
+ processedValue = null;
2857
+ } else {
2858
+ processedValue = parseInt(value, 10);
2859
+ if (isNaN(processedValue)) {
2860
+ paramError = `El valor para "${param.label || param.name}" no es un entero v\xE1lido.`;
2861
+ }
2862
+ }
2863
+ break;
2864
+ case "boolean":
2865
+ processedValue = !!value;
2866
+ break;
2867
+ case "jsonb":
2868
+ case "jsona":
2869
+ if (value === "" || value === null) {
2870
+ processedValue = null;
2871
+ } else {
2872
+ try {
2873
+ processedValue = JSON.parse(value);
2874
+ } catch (jsonError) {
2875
+ paramError = `Error en el formato JSON para "${param.label || param.name}": ${jsonError.message}`;
2876
+ }
2877
+ }
2878
+ break;
2879
+ case "bytea":
2880
+ processedValue = value instanceof File ? value : value === "" ? null : value;
2881
+ break;
2882
+ case "text":
2883
+ case "date":
2884
+ case "timestamp":
2885
+ case "time":
2886
+ case "interval":
2887
+ case "tsrange":
2888
+ case "time_range":
2889
+ case "daterange":
2890
+ default:
2891
+ processedValue = value === "" ? null : value;
2892
+ break;
2893
+ }
2894
+ const hasDefaultValue = param.defaultValue !== void 0 || param.specialDefaultValue !== void 0;
2895
+ const isEmpty = processedValue === null || processedValue === void 0 || typeof processedValue === "string" && processedValue.trim() === "";
2896
+ if (!hasDefaultValue && isEmpty) {
2897
+ paramError = `El campo "${param.label || param.name}" es obligatorio y no puede estar vac\xEDo.`;
2898
+ }
2899
+ if (paramError) {
2900
+ currentValidationErrors[param.name] = paramError;
2901
+ hasOverallError = true;
2902
+ addLogMessage(`Error de validaci\xF3n para "${param.label || param.name}": ${paramError}`, true);
2903
+ }
2904
+ paramsToSend[param.name] = processedValue;
2905
+ }
2906
+ if (hasOverallError) {
2907
+ setValidationErrors(currentValidationErrors);
2908
+ addLogMessage("No se puede ejecutar el procedimiento debido a errores de validaci\xF3n en el formulario.", true);
2909
+ return;
2910
+ }
2911
+ addLogMessage(`Par\xE1metros a enviar: ${JSON.stringify(paramsToSend, null, 2)}`);
2912
+ try {
2913
+ addLogMessage("Invocando procedimiento a trav\xE9s de useApiCall...");
2914
+ const result = await callApi(procedure.action, paramsToSend);
2915
+ if (result !== void 0) {
2916
+ setSuccessMessage(procedure.resultOk || "Procedimiento ejecutado con \xE9xito.");
2917
+ addLogMessage("Procedimiento ejecutado con \xE9xito.");
2918
+ addLogMessage(`Resultado: ${JSON.stringify(result, null, 2)}`);
2919
+ setProcedureResultData(result);
2920
+ console.log("Resultado del procedimiento:", result);
2921
+ } else {
2922
+ addLogMessage("Procedimiento finalizado con errores.", true);
2923
+ }
2924
+ } catch (err) {
2925
+ console.error("Error al ejecutar el procedimiento (capturado en ProcedureForm):", err);
2926
+ addLogMessage(`Error en la ejecuci\xF3n: ${err.message || "Error desconocido."}`, true);
2927
+ } finally {
2928
+ addLogMessage("Ejecuci\xF3n finalizada.");
2929
+ }
2930
+ };
2931
+ const renderInputField = useCallback7((param) => {
2932
+ const hasError = !!validationErrors[param.name];
2933
+ const errorMessage = validationErrors[param.name];
2934
+ const commonProps = {
2935
+ id: param.name,
2936
+ name: param.name,
2937
+ label: param.label || param.name,
2938
+ variant: "outlined",
2939
+ fullWidth: true,
2940
+ margin: "dense",
2941
+ required: !(param.defaultValue !== void 0 || param.specialDefaultValue !== void 0),
2942
+ size: "small",
2943
+ helperText: errorMessage || param.description,
2944
+ error: hasError,
2945
+ disabled: apiLoading,
2946
+ onChange: handleChange,
2947
+ sx: { fontSize: "0.8rem" }
2948
+ };
2949
+ if (param.options && param.options.length > 0) {
2950
+ return /* @__PURE__ */ jsxs13(FormControl, { fullWidth: true, margin: "dense", size: "small", error: hasError, required: commonProps.required, children: [
2951
+ /* @__PURE__ */ jsx19(InputLabel, { id: `${param.name}-label`, sx: { fontSize: "0.8rem" }, children: param.label || param.name }),
2952
+ /* @__PURE__ */ jsxs13(
2953
+ Select,
2954
+ {
2955
+ labelId: `${param.name}-label`,
2956
+ value: formValues[param.name] === void 0 ? "" : formValues[param.name],
2957
+ onChange: handleChange,
2958
+ name: param.name,
2959
+ id: param.name,
2960
+ label: param.label || param.name,
2961
+ disabled: apiLoading,
2962
+ sx: { fontSize: "0.8rem" },
2963
+ renderValue: (selected) => /* @__PURE__ */ jsx19(Typography14, { sx: { fontSize: "0.8rem" }, children: selected }),
2964
+ children: [
2965
+ (!commonProps.required || formValues[param.name] === "") && /* @__PURE__ */ jsx19(MenuItem, { value: "", sx: { fontSize: "0.8rem" }, children: /* @__PURE__ */ jsx19("em", { children: "Seleccione..." }) }),
2966
+ param.options.map((option) => /* @__PURE__ */ jsx19(MenuItem, { value: option, sx: { fontSize: "0.8rem" }, children: option }, option))
2967
+ ]
2968
+ }
2969
+ ),
2970
+ (param.description || errorMessage) && /* @__PURE__ */ jsx19(FormHelperText, { sx: { fontSize: "0.7rem" }, children: errorMessage || param.description })
2971
+ ] });
2972
+ }
2973
+ switch (param.typeName) {
2974
+ case "text":
2975
+ case "interval":
2976
+ case "tsrange":
2977
+ case "time_range":
2978
+ case "daterange":
2979
+ return /* @__PURE__ */ jsx19(TextField2, { type: "text", value: formValues[param.name] || "", ...commonProps });
2980
+ case "decimal":
2981
+ case "double":
2982
+ return /* @__PURE__ */ jsx19(TextField2, { type: "number", inputProps: { step: "any", style: { fontSize: "0.8rem" } }, value: formValues[param.name] || "", ...commonProps });
2983
+ case "integer":
2984
+ case "bigint":
2985
+ return /* @__PURE__ */ jsx19(TextField2, { type: "number", inputProps: { step: "1", style: { fontSize: "0.8rem" } }, value: formValues[param.name] || "", ...commonProps });
2986
+ case "boolean":
2987
+ return /* @__PURE__ */ jsx19(
2988
+ FormControlLabel,
2989
+ {
2990
+ control: /* @__PURE__ */ jsx19(
2991
+ Checkbox,
2992
+ {
2993
+ checked: !!formValues[param.name],
2994
+ onChange: handleChange,
2995
+ name: param.name,
2996
+ id: param.name,
2997
+ disabled: apiLoading,
2998
+ size: "small"
2999
+ }
3000
+ ),
3001
+ label: /* @__PURE__ */ jsx19(Typography14, { sx: { fontSize: "0.8rem", color: hasError ? "error.main" : "inherit" }, children: param.label || param.name }),
3002
+ sx: { mt: 1, mb: 0 }
3003
+ }
3004
+ );
3005
+ case "date":
3006
+ case "timestamp":
3007
+ case "time":
3008
+ return /* @__PURE__ */ jsx19(TextField2, { type: param.typeName === "date" ? "date" : param.typeName === "timestamp" ? "datetime-local" : "time", value: formValues[param.name] || "", ...commonProps, InputLabelProps: { shrink: true, sx: { fontSize: "0.8rem" } } });
3009
+ case "jsonb":
3010
+ case "jsona":
3011
+ return /* @__PURE__ */ jsx19(TextField2, { multiline: true, rows: 5, value: formValues[param.name] || "", ...commonProps, InputProps: { sx: { fontSize: "0.8rem" } } });
3012
+ case "bytea":
3013
+ return /* @__PURE__ */ jsxs13(FormControl, { fullWidth: true, margin: "dense", error: hasError, required: commonProps.required, children: [
3014
+ /* @__PURE__ */ jsx19(Typography14, { variant: "body2", color: "textSecondary", component: "label", htmlFor: param.name, sx: { fontSize: "0.8rem", color: hasError ? "error.main" : "text.secondary" }, children: param.label || param.name }),
3015
+ /* @__PURE__ */ jsx19(
3016
+ "input",
3017
+ {
3018
+ type: "file",
3019
+ id: param.name,
3020
+ name: param.name,
3021
+ onChange: (e) => {
3022
+ const files = e.target.files;
3023
+ setFormValues((prev) => ({ ...prev, [param.name]: files && files.length > 0 ? files[0] : void 0 }));
3024
+ },
3025
+ disabled: apiLoading,
3026
+ style: { padding: "6px 0", fontSize: "0.8rem" }
3027
+ }
3028
+ ),
3029
+ (param.description || errorMessage) && /* @__PURE__ */ jsx19(FormHelperText, { sx: { fontSize: "0.7rem" }, children: errorMessage || param.description })
3030
+ ] });
3031
+ default:
3032
+ return /* @__PURE__ */ jsx19(TextField2, { type: "text", value: formValues[param.name] || "", ...commonProps });
3033
+ }
3034
+ }, [formValues, handleChange, apiLoading, validationErrors]);
3035
+ const ResultDisplayContent = useMemo4(() => {
3036
+ if (!procedureResultData || !procedure?.resultOk) return null;
3037
+ const ComponentToRender = resultsOk[procedure.resultOk];
3038
+ if (ComponentToRender) {
3039
+ return /* @__PURE__ */ jsx19(ComponentToRender, { data: procedureResultData });
3040
+ } else {
3041
+ return /* @__PURE__ */ jsxs13(Paper3, { elevation: 2, sx: { p: 2, mt: 0, bgcolor: "warning.light" }, children: [
3042
+ /* @__PURE__ */ jsxs13(Typography14, { variant: "h6", sx: { fontSize: "1rem", mb: 1 }, children: [
3043
+ "el componente para resolver el resultOk: '",
3044
+ procedure.resultOk,
3045
+ "' definido en el procedure no existe o no est\xE1 mapeado."
3046
+ ] }),
3047
+ /* @__PURE__ */ jsx19(Box13, { sx: {
3048
+ bgcolor: "warning.dark",
3049
+ p: 1,
3050
+ borderRadius: 1
3051
+ }, children: /* @__PURE__ */ jsx19("pre", { style: { margin: 0, fontSize: "0.75rem", color: "white" }, children: JSON.stringify(procedureResultData, null, 2) }) })
3052
+ ] });
3053
+ }
3054
+ }, [procedureResultData, procedure]);
3055
+ if (!procedure) {
3056
+ return /* @__PURE__ */ jsxs13(Box13, { sx: {
3057
+ p: 2,
3058
+ width: "100%",
3059
+ boxSizing: "border-box",
3060
+ mt: 0,
3061
+ bgcolor: "background.paper",
3062
+ borderRadius: 2,
3063
+ boxShadow: 3,
3064
+ textAlign: "center"
3065
+ }, children: [
3066
+ /* @__PURE__ */ jsx19(CircularProgress4, { sx: { mb: 2 } }),
3067
+ /* @__PURE__ */ jsx19(Typography14, { variant: "h6", color: "text.secondary", children: "Cargando procedimiento o no encontrado..." })
3068
+ ] });
3069
+ }
3070
+ return (
3071
+ // Esta es la Box más externa que ahora controlará el scroll
3072
+ /* @__PURE__ */ jsxs13(Box13, { sx: {
3073
+ p: 2,
3074
+ ml: 1,
3075
+ mt: 2,
3076
+ mr: 1,
3077
+ boxSizing: "border-box",
3078
+ bgcolor: "background.paper",
3079
+ borderRadius: 2,
3080
+ boxShadow: 3,
3081
+ fontSize: "0.8rem",
3082
+ maxHeight: "calc(100vh - 100px)",
3083
+ // Ajusta esta altura máxima según el espacio disponible en tu layout
3084
+ overflowY: "auto",
3085
+ // Habilita el scroll vertical para todo el contenido de esta Box
3086
+ overflowX: "hidden"
3087
+ // Oculta el scroll horizontal si no es necesario para el contenedor principal
3088
+ }, children: [
3089
+ /* @__PURE__ */ jsx19(Typography14, { variant: "h5", component: "h2", gutterBottom: true, align: "left", children: cambiarGuionesBajosPorEspacios(procedure.proceedLabel || procedure.action) }),
3090
+ Object.values(validationErrors).some((err) => err !== null) && /* @__PURE__ */ jsxs13(Alert3, { severity: "error", sx: { mb: 2, fontSize: "0.8rem" }, children: [
3091
+ "Por favor, corrige los errores en el formulario antes de enviar.",
3092
+ /* @__PURE__ */ jsx19("ul", { children: Object.values(validationErrors).map((err, idx) => err && /* @__PURE__ */ jsx19("li", { children: err }, idx)) })
3093
+ ] }),
3094
+ !Object.values(validationErrors).some((err) => err !== null) && apiError && /* @__PURE__ */ jsx19(Alert3, { severity: "error", sx: { mb: 2, fontSize: "0.8rem" }, children: apiError.message }),
3095
+ !Object.values(validationErrors).some((err) => err !== null) && !apiError && successMessage && /* @__PURE__ */ jsx19(Alert3, { severity: "success", sx: { mb: 2, fontSize: "0.8rem" }, children: successMessage }),
3096
+ /* @__PURE__ */ jsxs13("form", { onSubmit: handleSubmit, children: [
3097
+ procedure.parameters.map((param) => /* @__PURE__ */ jsx19("div", { children: renderInputField(param) }, param.name)),
3098
+ /* @__PURE__ */ jsx19(
3099
+ Button6,
3100
+ {
3101
+ type: "submit",
3102
+ variant: "contained",
3103
+ color: "primary",
3104
+ disabled: apiLoading || Object.values(validationErrors).some((err) => err !== null),
3105
+ sx: { mt: 2 },
3106
+ size: "medium",
3107
+ startIcon: apiLoading ? /* @__PURE__ */ jsx19(CircularProgress4, { size: 20, color: "inherit" }) : null,
3108
+ children: apiLoading ? "Ejecutando..." : procedure.proceedLabel || "Ejecutar"
3109
+ }
3110
+ )
3111
+ ] }),
3112
+ ResultDisplayContent && /* @__PURE__ */ jsxs13(Box13, { sx: { mt: 2 }, children: [
3113
+ " ",
3114
+ ResultDisplayContent
3115
+ ] }),
3116
+ executionLog.length > 0 && /* @__PURE__ */ jsxs13(Box13, { sx: { mt: 3 }, children: [
3117
+ /* @__PURE__ */ jsx19(Divider2, { sx: { mb: 2 } }),
3118
+ /* @__PURE__ */ jsx19(Typography14, { variant: "h6", gutterBottom: true, sx: { fontSize: "0.9rem" }, children: "Registro de Ejecuci\xF3n" }),
3119
+ /* @__PURE__ */ jsx19(
3120
+ Box13,
3121
+ {
3122
+ sx: {
3123
+ bgcolor: "grey.100",
3124
+ p: 2,
3125
+ borderRadius: 1,
3126
+ maxHeight: "200px",
3127
+ // Este log puede tener su propio scroll interno si es muy largo
3128
+ overflowY: "auto",
3129
+ fontFamily: "monospace",
3130
+ fontSize: "0.75rem",
3131
+ whiteSpace: "pre-wrap"
3132
+ },
3133
+ children: executionLog.map((log, index) => /* @__PURE__ */ jsx19(
3134
+ Typography14,
3135
+ {
3136
+ component: "pre",
3137
+ sx: {
3138
+ margin: 0,
3139
+ color: log.includes("ERROR:") ? "error.main" : "text.primary",
3140
+ fontSize: "inherit"
3141
+ },
3142
+ children: log
3143
+ },
3144
+ index
3145
+ ))
3146
+ }
3147
+ )
3148
+ ] })
3149
+ ] })
3150
+ );
3151
+ };
3152
+ var ProcedureForm_default = ProcedureForm;
3153
+
3154
+ // src/App.tsx
3155
+ import { Provider } from "react-redux";
3156
+ import { PersistGate } from "redux-persist/integration/react";
3157
+
3158
+ // src/components/PrivateRoute.tsx
3159
+ import { useEffect as useEffect5 } from "react";
3160
+ import { Navigate, useLocation as useLocation2 } from "react-router-dom";
3161
+ import { Fragment as Fragment4, jsx as jsx20 } from "react/jsx-runtime";
3162
+ var PrivateRoute = ({ children }) => {
3163
+ const location = useLocation2();
3164
+ const dispatch = useAppDispatch();
3165
+ const clientContextStatus = useClientContextStatus();
3166
+ const isAuthenticated = clientContextStatus === "succeeded";
3167
+ const isLoadingAuth = clientContextStatus === "loading";
3168
+ console.log(`[PrivateRoute] Render: Path=${location.pathname}, AuthStatus=${clientContextStatus}, IsAuthenticated=${isAuthenticated}, IsLoadingAuth=${isLoadingAuth}`);
3169
+ useEffect5(() => {
3170
+ console.log(`[PrivateRoute] Effect: Path=${location.pathname}, AuthStatus=${clientContextStatus}, IsAuthenticated=${isAuthenticated}, IsLoadingAuth=${isLoadingAuth}`);
3171
+ if (!isAuthenticated && !isLoadingAuth && location.pathname !== "/login") {
3172
+ const path = location.pathname + location.search;
3173
+ console.log(`[PrivateRoute] ACTION: Dispatching setRedirectPath(${path})`);
3174
+ dispatch(setRedirectPath(path));
3175
+ } else if (isAuthenticated) {
3176
+ console.log(`[PrivateRoute] User is authenticated, no redirectPath set.`);
3177
+ } else if (isLoadingAuth) {
3178
+ console.log(`[PrivateRoute] Still loading authentication.`);
3179
+ } else if (location.pathname === "/login") {
3180
+ console.log(`[PrivateRoute] Currently on /login, not setting redirectPath.`);
3181
+ }
3182
+ }, [isAuthenticated, isLoadingAuth, location, dispatch, clientContextStatus]);
3183
+ if (isLoadingAuth) {
3184
+ console.log(`[PrivateRoute] Returning loading state...`);
3185
+ return /* @__PURE__ */ jsx20("p", { children: "Verificando autenticaci\xF3n..." });
3186
+ }
3187
+ if (!isAuthenticated) {
3188
+ console.log(`[PrivateRoute] User not authenticated, navigating to /login`);
3189
+ return /* @__PURE__ */ jsx20(Navigate, { to: "/login", replace: true });
3190
+ }
3191
+ console.log(`[PrivateRoute] User authenticated, rendering children.`);
3192
+ return /* @__PURE__ */ jsx20(Fragment4, { children });
3193
+ };
3194
+ var PrivateRoute_default = PrivateRoute;
3195
+
3196
+ // src/components/InitialRedirectHandler.tsx
3197
+ import { useEffect as useEffect6 } from "react";
3198
+ import { useLocation as useLocation3, useNavigate as useNavigate6 } from "react-router-dom";
3199
+ var InitialRedirectHandler = () => {
3200
+ const location = useLocation3();
3201
+ const navigate = useNavigate6();
3202
+ const dispatch = useAppDispatch();
3203
+ const redirectPath = useRedirectPath();
3204
+ const clientContextStatus = useClientContextStatus();
3205
+ useEffect6(() => {
3206
+ dispatch(setCurrentPath(location.pathname + location.search));
3207
+ }, [location, dispatch]);
3208
+ useEffect6(() => {
3209
+ if (clientContextStatus === "succeeded") {
3210
+ if (redirectPath && redirectPath !== "/login") {
3211
+ console.log("Redirigiendo a la ruta guardada:", redirectPath);
3212
+ navigate(redirectPath);
3213
+ dispatch(setRedirectPath(null));
3214
+ } else if (location.pathname === "/login" || location.pathname === "/") {
3215
+ console.log("Usuario autenticado, redirigiendo a /home por defecto.");
3216
+ navigate("/home");
3217
+ }
3218
+ }
3219
+ }, [clientContextStatus, redirectPath, location.pathname, navigate, dispatch]);
3220
+ return null;
3221
+ };
3222
+ var InitialRedirectHandler_default = InitialRedirectHandler;
3223
+
3224
+ // src/pages/GenericDataGridPage.tsx
3225
+ import { useParams as useParams2 } from "react-router-dom";
3226
+ import { Box as Box14, Alert as Alert4, Typography as Typography15 } from "@mui/material";
3227
+ import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
3228
+ var GenericDataGridPage = () => {
3229
+ const { tableName } = useParams2();
3230
+ if (!tableName) {
3231
+ return /* @__PURE__ */ jsx21(Box14, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsxs14(Alert4, { severity: "error", children: [
3232
+ /* @__PURE__ */ jsx21(Typography15, { variant: "h6", children: "Error: Nombre de tabla no especificado en la URL." }),
3233
+ /* @__PURE__ */ jsx21(Typography15, { variant: "body1", children: "Por favor, aseg\xFArate de que la URL contenga el nombre de la tabla (ej. `/data/users`)." })
3234
+ ] }) });
3235
+ }
3236
+ return /* @__PURE__ */ jsx21(GenericDataGrid_default, { tableName, fixedFields: [] });
3237
+ };
3238
+ var GenericDataGridPage_default = GenericDataGridPage;
3239
+
3240
+ // src/pages/MenuTablePage.tsx
3241
+ import { useMemo as useMemo5 } from "react";
3242
+ import { useParams as useParams3 } from "react-router-dom";
3243
+ import { Box as Box15, Alert as Alert5, Typography as Typography16 } from "@mui/material";
3244
+ import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
3245
+ var MenuTablePage = () => {
3246
+ const { menuName } = useParams3();
3247
+ const { clientContext } = useApp();
3248
+ const findMenuItem = (items, nameToFind) => {
3249
+ for (const item of items) {
3250
+ if (item.name === nameToFind && item.menuType === "table") {
3251
+ return item;
3252
+ }
3253
+ if (item.menuType === "menu" && item.menuContent) {
3254
+ const found = findMenuItem(item.menuContent, nameToFind);
3255
+ if (found) return found;
3256
+ }
3257
+ }
3258
+ return void 0;
3259
+ };
3260
+ const { currentTableName, currentFixedFields } = useMemo5(() => {
3261
+ let tableName = void 0;
3262
+ let fixedFields = [];
3263
+ if (menuName && clientContext && clientContext.menu) {
3264
+ const menuItem = findMenuItem(clientContext.menu, menuName);
3265
+ if (menuItem) {
3266
+ tableName = menuItem.table || menuItem.name;
3267
+ if (menuItem.ff) {
3268
+ Object.keys(menuItem.ff || []).forEach((fixedFieldKey) => {
3269
+ fixedFields.push({
3270
+ fieldName: fixedFieldKey,
3271
+ //@ts-ignore
3272
+ value: menuItem.ff[fixedFieldKey]
3273
+ });
3274
+ });
3275
+ }
3276
+ } else {
3277
+ console.warn(`[${menuName}] \xCDtem de men\xFA '${menuName}' no encontrado o no es de tipo 'table' en clientContext.menu.`);
3278
+ }
3279
+ }
3280
+ return {
3281
+ currentTableName: tableName,
3282
+ currentFixedFields: fixedFields
3283
+ };
3284
+ }, [menuName, clientContext]);
3285
+ if (!currentTableName) {
3286
+ return /* @__PURE__ */ jsx22(Box15, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "200px", children: /* @__PURE__ */ jsxs15(Alert5, { severity: "error", children: [
3287
+ /* @__PURE__ */ jsx22(Typography16, { variant: "h6", children: "Error: No se pudo cargar la informaci\xF3n de la tabla." }),
3288
+ /* @__PURE__ */ jsx22(Typography16, { variant: "body1", children: "Verifique la configuraci\xF3n del men\xFA o el nombre de la tabla en la URL." })
3289
+ ] }) });
3290
+ }
3291
+ return /* @__PURE__ */ jsx22(
3292
+ GenericDataGrid_default,
3293
+ {
3294
+ tableName: currentTableName,
3295
+ fixedFields: currentFixedFields
3296
+ }
3297
+ );
3298
+ };
3299
+ var MenuTablePage_default = MenuTablePage;
3300
+
3301
+ // src/App.tsx
3302
+ import { jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
3303
+ var LocationTracker = () => {
3304
+ const location = useLocation4();
3305
+ const dispatch = useAppDispatch();
3306
+ useEffect7(() => {
3307
+ dispatch(setCurrentPath(location.pathname + location.search));
3308
+ }, [location, dispatch]);
3309
+ return null;
3310
+ };
3311
+ function FrontendPlusReactRoutes({ myRoutes, myWScreens }) {
3312
+ const allWScreens = { ...wScreens, ...myWScreens || {} };
3313
+ return /* @__PURE__ */ jsxs16(Routes, { children: [
3314
+ /* @__PURE__ */ jsx23(Route, { path: "/login", element: /* @__PURE__ */ jsx23(LoginPage_default, {}) }),
3315
+ /* @__PURE__ */ jsx23(Route, { path: "/logout", element: /* @__PURE__ */ jsx23(LogoutPage_default, {}) }),
3316
+ /* @__PURE__ */ jsxs16(Route, { element: /* @__PURE__ */ jsxs16(PrivateRoute_default, { children: [
3317
+ /* @__PURE__ */ jsx23(InitialRedirectHandler_default, {}),
3318
+ /* @__PURE__ */ jsx23(MainLayout_default, {})
3319
+ ] }), children: [
3320
+ /* @__PURE__ */ jsx23(Route, { path: "/", element: /* @__PURE__ */ jsx23(HomePage_default, {}) }),
3321
+ /* @__PURE__ */ jsx23(Route, { path: "/home", element: /* @__PURE__ */ jsx23(HomePage_default, {}) }),
3322
+ /* @__PURE__ */ jsx23(Route, { path: "/table/:tableName", element: /* @__PURE__ */ jsx23(GenericDataGridPage_default, {}) }),
3323
+ /* @__PURE__ */ jsx23(Route, { path: "/menu/:menuName", element: /* @__PURE__ */ jsx23(MenuTablePage_default, {}) }),
3324
+ /* @__PURE__ */ jsx23(Route, { path: "/procedures/:procedureName", element: /* @__PURE__ */ jsx23(ProcedureForm_default, {}) }),
3325
+ Object.keys(allWScreens).map((screenName) => /* @__PURE__ */ jsx23(
3326
+ Route,
3327
+ {
3328
+ path: `/wScreens/${screenName}`,
3329
+ element: React11.createElement(wScreens[screenName], { screenName })
3330
+ },
3331
+ screenName
3332
+ )),
3333
+ /* @__PURE__ */ jsx23(
3334
+ Route,
3335
+ {
3336
+ path: "/wScreens-fallback/:screenName",
3337
+ element: /* @__PURE__ */ jsx23(WScreens_default, { screenName: ":screenName" })
3338
+ }
3339
+ ),
3340
+ /* @__PURE__ */ jsx23(Route, { path: "*", element: /* @__PURE__ */ jsx23("div", { style: { marginTop: "20px", marginLeft: "10px" }, children: "404 - Recurso No Encontrado" }) })
3341
+ ] }),
3342
+ myRoutes,
3343
+ /* @__PURE__ */ jsx23(Route, { path: "*", element: /* @__PURE__ */ jsx23(Navigate2, { to: "/", replace: true }) })
3344
+ ] });
3345
+ }
3346
+ var App = ({
3347
+ myRoutes,
3348
+ myWScreens,
3349
+ myClientSides,
3350
+ myResultsOk
3351
+ }) => {
3352
+ useEffect7(() => {
3353
+ if (myClientSides) {
3354
+ extendClientSides(myClientSides);
3355
+ }
3356
+ if (myResultsOk) {
3357
+ extendResultsOk(myResultsOk);
3358
+ }
3359
+ }, [myClientSides, myResultsOk]);
3360
+ return /* @__PURE__ */ jsx23(Provider, { store, children: /* @__PURE__ */ jsx23(PersistGate, { loading: null, persistor, children: /* @__PURE__ */ jsxs16(BrowserRouter, { children: [
3361
+ /* @__PURE__ */ jsx23(LocationTracker, {}),
3362
+ /* @__PURE__ */ jsx23(AppProvider, { children: /* @__PURE__ */ jsxs16(SnackbarProvider, { children: [
3363
+ /* @__PURE__ */ jsx23(
3364
+ FrontendPlusReactRoutes,
3365
+ {
3366
+ myRoutes,
3367
+ myWScreens
3368
+ }
3369
+ ),
3370
+ /* @__PURE__ */ jsx23(SessionExpiredMessage_default, {})
3371
+ ] }) })
3372
+ ] }) }) });
3373
+ };
3374
+ var App_default = App;
3375
+ export {
3376
+ App_default as App,
3377
+ AppProvider,
3378
+ ConfirmDialog,
3379
+ FrontendPlusReactRoutes,
3380
+ GenericDataGrid_default as GenericDataGrid,
3381
+ MainLayout_default as MainLayout,
3382
+ SnackbarProvider,
3383
+ cambiarGuionesBajosPorEspacios,
3384
+ clientSides,
3385
+ extendClientSides,
3386
+ resultsOk as resultComponents,
3387
+ useApiCall,
3388
+ useApp,
3389
+ useLogout_default as useLogout,
3390
+ useSnackbar,
3391
+ wScreens
3392
+ };
3393
+ //# sourceMappingURL=index.js.map