tickera-angular-components 0.0.1-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/fesm2022/tickera-angular-components.mjs +4586 -0
- package/fesm2022/tickera-angular-components.mjs.map +1 -0
- package/index.d.ts +2250 -0
- package/package.json +45 -0
|
@@ -0,0 +1,4586 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, makeEnvironmentProviders, PLATFORM_ID, Inject, Injectable, signal, LOCALE_ID, computed, inject, EventEmitter, Input, Output, ViewEncapsulation, Component, Self, Optional, Injector, HostListener, forwardRef } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/common/http';
|
|
4
|
+
import { HttpHeaders } from '@angular/common/http';
|
|
5
|
+
import { throwError, BehaviorSubject, Subject, of } from 'rxjs';
|
|
6
|
+
import { catchError, distinctUntilChanged, debounceTime, switchMap, takeUntil, map } from 'rxjs/operators';
|
|
7
|
+
import * as i1$2 from '@angular/common';
|
|
8
|
+
import { isPlatformBrowser, formatDate, CommonModule, DatePipe } from '@angular/common';
|
|
9
|
+
import { toast } from 'ngx-sonner';
|
|
10
|
+
import { toObservable } from '@angular/core/rxjs-interop';
|
|
11
|
+
import * as i2 from '@jsverse/transloco';
|
|
12
|
+
import { TranslocoModule } from '@jsverse/transloco';
|
|
13
|
+
import { RouterLink } from '@angular/router';
|
|
14
|
+
import * as i1$1 from '@angular/forms';
|
|
15
|
+
import { FormsModule, ReactiveFormsModule, Validators, NgControl, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
|
|
16
|
+
import { DEFAULT_TOOLBAR, Editor, toHTML, NgxEditorComponent, NgxEditorMenuComponent } from 'ngx-editor';
|
|
17
|
+
import * as i2$1 from '@ng-select/ng-select';
|
|
18
|
+
import { NgSelectModule } from '@ng-select/ng-select';
|
|
19
|
+
|
|
20
|
+
const TICKERA_COMPONENTS_CONFIG = new InjectionToken('TICKERA_COMPONENTS_CONFIG');
|
|
21
|
+
function provideTickeraComponents(config) {
|
|
22
|
+
return makeEnvironmentProviders([{ provide: TICKERA_COMPONENTS_CONFIG, useValue: config }]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const ALERT_BASE_CLASSES = 'border rounded relative flex items-center gap-2 px-4 py-2';
|
|
26
|
+
const ALERT_COLOR_CLASSES = {
|
|
27
|
+
success: 'bg-green-100 border-green-400 text-green-700',
|
|
28
|
+
error: 'bg-red-100 border-red-400 text-red-700',
|
|
29
|
+
warning: 'bg-yellow-100 border-yellow-400 text-yellow-700',
|
|
30
|
+
info: 'bg-blue-100 border-blue-400 text-blue-700',
|
|
31
|
+
};
|
|
32
|
+
const ALERT_SIZE_CLASSES = {
|
|
33
|
+
xs: 'px-2 py-1 text-xs',
|
|
34
|
+
sm: 'px-4 py-2 text-sm',
|
|
35
|
+
md: 'px-6 py-3 text-base',
|
|
36
|
+
lg: 'px-8 py-4 text-lg',
|
|
37
|
+
};
|
|
38
|
+
const ALERT_ICONS = {
|
|
39
|
+
success: 'ri-check-line',
|
|
40
|
+
error: 'ri-error-warning-line',
|
|
41
|
+
warning: 'ri-alert-line',
|
|
42
|
+
info: 'ri-info-line',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const BUTTON_VARIANT_CLASSES = {
|
|
46
|
+
primary: 'bg-red-600 hover:bg-red-700 focus:ring-red-500 text-white',
|
|
47
|
+
secondary: 'bg-purple-600 hover:bg-purple-700 focus:ring-purple-500 text-white',
|
|
48
|
+
terciary: 'bg-gray-500 hover:bg-gray-600 focus:ring-gray-500 text-white',
|
|
49
|
+
success: 'bg-green-600 hover:bg-green-700 focus:ring-green-500 text-green-900',
|
|
50
|
+
transparent: 'bg-transparent hover:bg-gray-100 focus:ring-gray-500 text-gray-700 ',
|
|
51
|
+
};
|
|
52
|
+
const BASE_BUTTON_CLASSES = [
|
|
53
|
+
'w-full',
|
|
54
|
+
'cursor-pointer',
|
|
55
|
+
'flex',
|
|
56
|
+
'justify-center',
|
|
57
|
+
'gap-2',
|
|
58
|
+
'border',
|
|
59
|
+
'border-transparent',
|
|
60
|
+
'rounded-md',
|
|
61
|
+
'font-medium',
|
|
62
|
+
'focus:outline-none',
|
|
63
|
+
'focus:ring-2',
|
|
64
|
+
'focus:ring-offset-2',
|
|
65
|
+
'disabled:opacity-50',
|
|
66
|
+
'disabled:cursor-not-allowed',
|
|
67
|
+
].join(' ');
|
|
68
|
+
const BUTTON_SIZES_CLASSES = {
|
|
69
|
+
xs: 'text-xs py-1 px-2',
|
|
70
|
+
sm: 'text-sm py-2 px-4',
|
|
71
|
+
md: 'text-base py-3 px-6',
|
|
72
|
+
lg: 'text-lg py-4 px-8',
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const FORM_ERROR_MESSAGES = {
|
|
76
|
+
required: 'Este campo es requerido',
|
|
77
|
+
minlength: 'Debe tener al menos caracteres',
|
|
78
|
+
maxlength: 'Debe tener al menos caracteres',
|
|
79
|
+
pattern: 'El formato no es válido',
|
|
80
|
+
email: 'El formato no es válido',
|
|
81
|
+
mustMatch: 'Las contraseñas no coinciden',
|
|
82
|
+
matDatepickerMin: 'La fecha no puede ser anterior a la fecha mínima permitida',
|
|
83
|
+
matDatepickerMax: 'La fecha no puede ser posterior a la fecha máxima permitida',
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const BASE_INPUT_CLASSES = [
|
|
87
|
+
'block',
|
|
88
|
+
'w-full',
|
|
89
|
+
'rounded-md',
|
|
90
|
+
'px-3',
|
|
91
|
+
'py-1.5',
|
|
92
|
+
'text-base',
|
|
93
|
+
'text-gray-900',
|
|
94
|
+
'outline-1',
|
|
95
|
+
'-outline-offset-1',
|
|
96
|
+
'outline-gray-300',
|
|
97
|
+
'placeholder:text-gray-400',
|
|
98
|
+
'focus:outline-2',
|
|
99
|
+
'focus:-outline-offset-2',
|
|
100
|
+
'focus:outline-indigo-600',
|
|
101
|
+
'sm:text-sm/6',
|
|
102
|
+
].join(' ');
|
|
103
|
+
const ERROR_INPUT_CLASSES = BASE_INPUT_CLASSES + ' outline-red-500 dark:outline-red-500';
|
|
104
|
+
|
|
105
|
+
const ADMIN_API_ROUTES = {
|
|
106
|
+
FIND_ALL: '/admins',
|
|
107
|
+
CREATE: '/admins/auth/register',
|
|
108
|
+
updateOne: (id) => `/admins/${id}`,
|
|
109
|
+
deleteOne: (id) => `/admins/${id}`,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const CITY_API_ENDPOINTS = {
|
|
113
|
+
findAll: '/cities',
|
|
114
|
+
create: '/cities',
|
|
115
|
+
findById: (id) => `/cities/${id}`,
|
|
116
|
+
update: (id) => `/cities/${id}`,
|
|
117
|
+
delete: (id) => `/cities/${id}`,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const COUNTRY_API_ENDPOINTS = {
|
|
121
|
+
findAll: '/countries',
|
|
122
|
+
create: '/countries',
|
|
123
|
+
findById: (id) => `/countries/${id}`,
|
|
124
|
+
update: (id) => `/countries/${id}`,
|
|
125
|
+
delete: (id) => `/countries/${id}`,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const STATE_API_ENDPOINTS = {
|
|
129
|
+
findAll: '/states',
|
|
130
|
+
create: '/states',
|
|
131
|
+
findById: (id) => `/states/${id}`,
|
|
132
|
+
update: (id) => `/states/${id}`,
|
|
133
|
+
delete: (id) => `/states/${id}`,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const PERFORMANCES_API_ROUTES = {
|
|
137
|
+
findAll: '/performances',
|
|
138
|
+
create: '/performances',
|
|
139
|
+
createBulk: '/performances/bulk',
|
|
140
|
+
findOneById: (id) => `/performances/${id}`,
|
|
141
|
+
findOneBookingData: (id) => `/performances/${id}/booking-data`,
|
|
142
|
+
update: (id) => `/performances/${id}`,
|
|
143
|
+
delete: (id) => `/performances/${id}`,
|
|
144
|
+
deleteMany: '/performances/bulk',
|
|
145
|
+
cancel: (id) => `/performances/${id}/cancel`,
|
|
146
|
+
publishInventory: (id) => `/performances/${id}/publish-inventory`,
|
|
147
|
+
reserve: (id) => `/performances/${id}/reserve`,
|
|
148
|
+
ticketQrToken: (uuid) => `/performances/tickets/${uuid}/qr-token`,
|
|
149
|
+
getAvailableDays: '/performances/available-days',
|
|
150
|
+
publicAvailablePerformances: '/public/performances/daily',
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const PRODUCTS_API_ROUTES = {
|
|
154
|
+
FIND_ALL: '/products',
|
|
155
|
+
CREATE: '/products',
|
|
156
|
+
findOneById: (id) => `/products/${id}`,
|
|
157
|
+
update: (id) => `/products/${id}`,
|
|
158
|
+
delete: (id) => `/products/${id}`,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const SHOWS_API_ROUTES = {
|
|
162
|
+
findAll: '/shows',
|
|
163
|
+
create: '/shows',
|
|
164
|
+
findOneById: (id) => `/shows/${id}`,
|
|
165
|
+
update: (id) => `/shows/${id}`,
|
|
166
|
+
delete: (id) => `/shows/${id}`,
|
|
167
|
+
getImages: (id) => `/shows/${id}/images`,
|
|
168
|
+
uploadGallery: (id) => `/shows/${id}/images`,
|
|
169
|
+
deleteOneImage: (showId, imageId) => `/shows/${showId}/images/${imageId}`,
|
|
170
|
+
publicAvailablePerformances: '/public/shows/available',
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const CUSTOMERS_API_ROUTES = {
|
|
174
|
+
findAll: '/customers',
|
|
175
|
+
create: '/customers/auth/register',
|
|
176
|
+
findOne: (id) => `/customers/${id}`,
|
|
177
|
+
update: (id) => `/customers/${id}`,
|
|
178
|
+
delete: (id) => `/customers/${id}`,
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const PRICE_ZONES_API_ROUTES = {
|
|
182
|
+
FIND_ALL: '/price-zones',
|
|
183
|
+
CREATE: '/price-zones',
|
|
184
|
+
findOneById: (id) => `/price-zones/${id}`,
|
|
185
|
+
update: (id) => `/price-zones/${id}`,
|
|
186
|
+
delete: (id) => `/price-zones/${id}`,
|
|
187
|
+
updateElements: (id) => `/price-zones/${id}/elements`,
|
|
188
|
+
duplicate: (id) => `/price-zones/${id}/duplicate`,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const VENUES_API_ROUTES = {
|
|
192
|
+
findAll: '/venues',
|
|
193
|
+
create: '/venues',
|
|
194
|
+
findOneById: (id) => '/venues/' + id,
|
|
195
|
+
update: (id) => '/venues/' + id,
|
|
196
|
+
delete: (id) => '/venues/' + id,
|
|
197
|
+
getGallery: (id) => '/venues/' + id + '/images',
|
|
198
|
+
uploadGallery: (id) => '/venues/' + id + '/images',
|
|
199
|
+
deleteOneImage: (venueId, imageId) => '/venues/' + venueId + '/images/' + imageId,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
var FileType;
|
|
203
|
+
(function (FileType) {
|
|
204
|
+
FileType["IMAGE"] = "image";
|
|
205
|
+
FileType["PDF"] = "pdf";
|
|
206
|
+
FileType["EXCEL"] = "excel";
|
|
207
|
+
FileType["WORD"] = "word";
|
|
208
|
+
FileType["TEXT"] = "text";
|
|
209
|
+
FileType["DEFAULT"] = "default";
|
|
210
|
+
})(FileType || (FileType = {}));
|
|
211
|
+
|
|
212
|
+
var CouponApplicability;
|
|
213
|
+
(function (CouponApplicability) {
|
|
214
|
+
CouponApplicability["GENERAL"] = "GENERAL";
|
|
215
|
+
CouponApplicability["CUSTOMER_EMAIL"] = "CUSTOMER_EMAIL";
|
|
216
|
+
CouponApplicability["MEMBERSHIP_TYPE"] = "MEMBERSHIP_TYPE";
|
|
217
|
+
CouponApplicability["SHOWS"] = "SHOWS";
|
|
218
|
+
CouponApplicability["PERFORMANCES"] = "PERFORMANCES";
|
|
219
|
+
})(CouponApplicability || (CouponApplicability = {}));
|
|
220
|
+
|
|
221
|
+
var CouponDiscountType;
|
|
222
|
+
(function (CouponDiscountType) {
|
|
223
|
+
CouponDiscountType["PERCENTAGE"] = "PERCENTAGE";
|
|
224
|
+
CouponDiscountType["FIXED"] = "FIXED";
|
|
225
|
+
})(CouponDiscountType || (CouponDiscountType = {}));
|
|
226
|
+
|
|
227
|
+
var CorporateBondStatus;
|
|
228
|
+
(function (CorporateBondStatus) {
|
|
229
|
+
CorporateBondStatus["ACTIVE"] = "ACTIVE";
|
|
230
|
+
CorporateBondStatus["INACTIVE"] = "INACTIVE";
|
|
231
|
+
CorporateBondStatus["EXPIRED"] = "EXPIRED";
|
|
232
|
+
})(CorporateBondStatus || (CorporateBondStatus = {}));
|
|
233
|
+
|
|
234
|
+
var PerformanceStatus;
|
|
235
|
+
(function (PerformanceStatus) {
|
|
236
|
+
PerformanceStatus["ACTIVE"] = "active";
|
|
237
|
+
PerformanceStatus["CANCELLED"] = "cancelled";
|
|
238
|
+
PerformanceStatus["FINISHED"] = "finished";
|
|
239
|
+
PerformanceStatus["POSTPONED"] = "postponed";
|
|
240
|
+
})(PerformanceStatus || (PerformanceStatus = {}));
|
|
241
|
+
|
|
242
|
+
var PerformanceTicketStatus;
|
|
243
|
+
(function (PerformanceTicketStatus) {
|
|
244
|
+
PerformanceTicketStatus["AVAILABLE"] = "available";
|
|
245
|
+
PerformanceTicketStatus["RESERVED"] = "reserved";
|
|
246
|
+
PerformanceTicketStatus["SOLD"] = "sold";
|
|
247
|
+
PerformanceTicketStatus["BLOCKED"] = "blocked";
|
|
248
|
+
})(PerformanceTicketStatus || (PerformanceTicketStatus = {}));
|
|
249
|
+
|
|
250
|
+
var RoomMapElementOrientation;
|
|
251
|
+
(function (RoomMapElementOrientation) {
|
|
252
|
+
RoomMapElementOrientation["TOP"] = "top";
|
|
253
|
+
RoomMapElementOrientation["RIGHT"] = "right";
|
|
254
|
+
RoomMapElementOrientation["BOTTOM"] = "bottom";
|
|
255
|
+
RoomMapElementOrientation["LEFT"] = "left";
|
|
256
|
+
RoomMapElementOrientation["CENTER"] = "center";
|
|
257
|
+
})(RoomMapElementOrientation || (RoomMapElementOrientation = {}));
|
|
258
|
+
|
|
259
|
+
var RoomMapElementType;
|
|
260
|
+
(function (RoomMapElementType) {
|
|
261
|
+
RoomMapElementType["SEAT_BLOCK"] = "seat_block";
|
|
262
|
+
RoomMapElementType["TABLE"] = "table";
|
|
263
|
+
RoomMapElementType["ZONE"] = "zone";
|
|
264
|
+
RoomMapElementType["EXIT"] = "exit";
|
|
265
|
+
RoomMapElementType["STAGE"] = "stage";
|
|
266
|
+
RoomMapElementType["PRODUCTION_AREA"] = "production_area";
|
|
267
|
+
RoomMapElementType["UNAVAILABLE_SPACE"] = "unavailable_space";
|
|
268
|
+
RoomMapElementType["STAIR"] = "stair";
|
|
269
|
+
RoomMapElementType["HALLWAY"] = "hallway";
|
|
270
|
+
})(RoomMapElementType || (RoomMapElementType = {}));
|
|
271
|
+
|
|
272
|
+
var OrderItemType;
|
|
273
|
+
(function (OrderItemType) {
|
|
274
|
+
OrderItemType["TICKET"] = "TICKET";
|
|
275
|
+
OrderItemType["PRODUCT"] = "PRODUCT";
|
|
276
|
+
})(OrderItemType || (OrderItemType = {}));
|
|
277
|
+
|
|
278
|
+
var OrderStatus;
|
|
279
|
+
(function (OrderStatus) {
|
|
280
|
+
OrderStatus["PENDING"] = "PENDING";
|
|
281
|
+
OrderStatus["COMPLETED"] = "COMPLETED";
|
|
282
|
+
OrderStatus["FAILED"] = "FAILED";
|
|
283
|
+
OrderStatus["CANCELLED"] = "CANCELLED";
|
|
284
|
+
})(OrderStatus || (OrderStatus = {}));
|
|
285
|
+
|
|
286
|
+
const getCustomerFullname = (customer) => {
|
|
287
|
+
return `${customer.first_name || ''} ${customer.last_name || ''}`.trim();
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
function parseJsonToFormDataAdvanced(imageGallery) {
|
|
291
|
+
const formData = new FormData();
|
|
292
|
+
if (!Array.isArray(imageGallery)) {
|
|
293
|
+
throw new Error('imageGallery debe ser un array');
|
|
294
|
+
}
|
|
295
|
+
if (imageGallery.length === 0) {
|
|
296
|
+
throw new Error('No hay imágenes para procesar');
|
|
297
|
+
}
|
|
298
|
+
if (imageGallery.length > 10) {
|
|
299
|
+
throw new Error('El backend acepta máximo 10 archivos por petición');
|
|
300
|
+
}
|
|
301
|
+
const processedFiles = [];
|
|
302
|
+
imageGallery.forEach((image, index) => {
|
|
303
|
+
try {
|
|
304
|
+
if (!image.name) {
|
|
305
|
+
throw new Error(`La imagen ${index + 1} no tiene nombre`);
|
|
306
|
+
}
|
|
307
|
+
if (!image.type || !image.type.startsWith('image/')) {
|
|
308
|
+
throw new Error(`La imagen ${index + 1} no tiene un tipo MIME válido`);
|
|
309
|
+
}
|
|
310
|
+
if (!image.preview) {
|
|
311
|
+
throw new Error(`La imagen ${index + 1} no tiene datos de preview`);
|
|
312
|
+
}
|
|
313
|
+
if (!image.preview.includes('data:image/') || !image.preview.includes('base64,')) {
|
|
314
|
+
throw new Error(`La imagen ${index + 1} no tiene un formato base64 válido`);
|
|
315
|
+
}
|
|
316
|
+
const base64Data = image.preview.split(',')[1];
|
|
317
|
+
const byteCharacters = atob(base64Data);
|
|
318
|
+
const byteNumbers = new Array(byteCharacters.length);
|
|
319
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
320
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
321
|
+
}
|
|
322
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
323
|
+
const blob = new Blob([byteArray], { type: image.type });
|
|
324
|
+
const file = new File([blob], image.name, {
|
|
325
|
+
type: image.type,
|
|
326
|
+
lastModified: Date.now(),
|
|
327
|
+
});
|
|
328
|
+
if (file.size === 0) {
|
|
329
|
+
throw new Error(`El archivo ${image.name} está vacío`);
|
|
330
|
+
}
|
|
331
|
+
formData.append('files', file);
|
|
332
|
+
processedFiles.push({
|
|
333
|
+
name: image.name,
|
|
334
|
+
size: file.size,
|
|
335
|
+
type: file.type,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
console.error(`Error procesando imagen ${index + 1}:`, error);
|
|
340
|
+
throw new Error(`Error procesando ${image.name || 'imagen ' + (index + 1)}: ${error?.message}`);
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
return formData;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const transformImageToFile = (image) => {
|
|
347
|
+
return {
|
|
348
|
+
preview: image.full_url,
|
|
349
|
+
name: image.original_name,
|
|
350
|
+
size: image.size,
|
|
351
|
+
type: image.mime_type,
|
|
352
|
+
extension: image.extension,
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const formatCitiesResponseToSelect = (res) => {
|
|
357
|
+
if (!res.data.cities || res.data.cities.length < 1) {
|
|
358
|
+
return [];
|
|
359
|
+
}
|
|
360
|
+
return res.data.cities?.map(({ id, name, search_text }) => ({
|
|
361
|
+
value: id,
|
|
362
|
+
label: search_text ?? name,
|
|
363
|
+
}));
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
function MinTodayValidator(controlName) {
|
|
367
|
+
return (formGroup) => {
|
|
368
|
+
const group = formGroup;
|
|
369
|
+
const control = group.get(controlName);
|
|
370
|
+
if (!control || !control.value) {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
const today = new Date();
|
|
374
|
+
today.setHours(0, 0, 0, 0);
|
|
375
|
+
let selectedDate;
|
|
376
|
+
if (control.value instanceof Date) {
|
|
377
|
+
selectedDate = new Date(control.value);
|
|
378
|
+
}
|
|
379
|
+
else if (typeof control.value === 'string') {
|
|
380
|
+
const [year, month, day] = control.value.split('-').map(Number);
|
|
381
|
+
selectedDate = new Date(Date.UTC(year, month - 1, day));
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
selectedDate.setUTCHours(0, 0, 0, 0);
|
|
387
|
+
if (selectedDate < today) {
|
|
388
|
+
control.setErrors({ minToday: true });
|
|
389
|
+
return { minToday: true };
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
const currentErrors = control.errors;
|
|
393
|
+
if (currentErrors) {
|
|
394
|
+
delete currentErrors['minToday'];
|
|
395
|
+
control.setErrors(Object.keys(currentErrors).length > 0 ? currentErrors : null);
|
|
396
|
+
}
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
function EndDateGreaterThanStartValidator(startDateControlName, endDateControlName) {
|
|
402
|
+
return (formGroup) => {
|
|
403
|
+
const group = formGroup;
|
|
404
|
+
const startDateControl = group.get(startDateControlName);
|
|
405
|
+
const endDateControl = group.get(endDateControlName);
|
|
406
|
+
if (!startDateControl || !endDateControl || !startDateControl.value || !endDateControl.value) {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
let startDate;
|
|
410
|
+
let endDate;
|
|
411
|
+
if (startDateControl.value instanceof Date) {
|
|
412
|
+
startDate = new Date(startDateControl.value);
|
|
413
|
+
}
|
|
414
|
+
else if (typeof startDateControl.value === 'string') {
|
|
415
|
+
const [startYear, startMonth, startDay] = startDateControl.value.split('-').map(Number);
|
|
416
|
+
startDate = new Date(Date.UTC(startYear, startMonth - 1, startDay));
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
if (endDateControl.value instanceof Date) {
|
|
422
|
+
endDate = new Date(endDateControl.value);
|
|
423
|
+
}
|
|
424
|
+
else if (typeof endDateControl.value === 'string') {
|
|
425
|
+
const [endYear, endMonth, endDay] = endDateControl.value.split('-').map(Number);
|
|
426
|
+
endDate = new Date(Date.UTC(endYear, endMonth - 1, endDay));
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
startDate.setUTCHours(0, 0, 0, 0);
|
|
432
|
+
endDate.setUTCHours(0, 0, 0, 0);
|
|
433
|
+
if (endDate <= startDate) {
|
|
434
|
+
endDateControl.setErrors({ endDateGreaterThanStart: true });
|
|
435
|
+
return { endDateGreaterThanStart: true };
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
const currentErrors = endDateControl.errors;
|
|
439
|
+
if (currentErrors) {
|
|
440
|
+
delete currentErrors['endDateGreaterThanStart'];
|
|
441
|
+
endDateControl.setErrors(Object.keys(currentErrors).length > 0 ? currentErrors : null);
|
|
442
|
+
}
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function MustMatchValidator(controlName, matchingControlName) {
|
|
449
|
+
return (formGroup) => {
|
|
450
|
+
const group = formGroup;
|
|
451
|
+
const control = group.get(controlName);
|
|
452
|
+
const matchingControl = group.get(matchingControlName);
|
|
453
|
+
if (!control || !matchingControl) {
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
if (control.value !== matchingControl.value) {
|
|
457
|
+
matchingControl.setErrors({ mustMatch: true });
|
|
458
|
+
return { mustMatch: true };
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
matchingControl.setErrors(null);
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
class ApiService {
|
|
468
|
+
http;
|
|
469
|
+
platformId;
|
|
470
|
+
config;
|
|
471
|
+
apiUrl;
|
|
472
|
+
constructor(http, platformId, config) {
|
|
473
|
+
this.http = http;
|
|
474
|
+
this.platformId = platformId;
|
|
475
|
+
this.config = config;
|
|
476
|
+
this.apiUrl = config.apiUrl;
|
|
477
|
+
}
|
|
478
|
+
getHeaders(contentType) {
|
|
479
|
+
let headers = new HttpHeaders();
|
|
480
|
+
if (contentType) {
|
|
481
|
+
headers = headers.set('Content-Type', contentType);
|
|
482
|
+
}
|
|
483
|
+
return headers;
|
|
484
|
+
}
|
|
485
|
+
validateContentType(body) {
|
|
486
|
+
if (body instanceof FormData) {
|
|
487
|
+
return undefined;
|
|
488
|
+
}
|
|
489
|
+
return 'application/json';
|
|
490
|
+
}
|
|
491
|
+
handleError(error) {
|
|
492
|
+
if (error.status === 401 && isPlatformBrowser(this.platformId)) {
|
|
493
|
+
const currentRoute = window.location.pathname;
|
|
494
|
+
if (currentRoute.startsWith('/admin')) {
|
|
495
|
+
localStorage.removeItem('access_token');
|
|
496
|
+
window.location.href = '/';
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return throwError(() => error);
|
|
500
|
+
}
|
|
501
|
+
get(path) {
|
|
502
|
+
const headers = this.getHeaders(this.validateContentType(null));
|
|
503
|
+
return this.http
|
|
504
|
+
.get(`${this.apiUrl}${path}`, { headers })
|
|
505
|
+
.pipe(catchError(this.handleError.bind(this)));
|
|
506
|
+
}
|
|
507
|
+
post(path, body) {
|
|
508
|
+
const headers = this.getHeaders(this.validateContentType(body));
|
|
509
|
+
return this.http
|
|
510
|
+
.post(`${this.apiUrl}${path}`, body, { headers })
|
|
511
|
+
.pipe(catchError(this.handleError.bind(this)));
|
|
512
|
+
}
|
|
513
|
+
patch(path, body) {
|
|
514
|
+
const headers = this.getHeaders(this.validateContentType(body));
|
|
515
|
+
return this.http
|
|
516
|
+
.patch(`${this.apiUrl}${path}`, body, { headers })
|
|
517
|
+
.pipe(catchError(this.handleError.bind(this)));
|
|
518
|
+
}
|
|
519
|
+
put(path, body) {
|
|
520
|
+
const headers = this.getHeaders(this.validateContentType(body));
|
|
521
|
+
return this.http
|
|
522
|
+
.put(`${this.apiUrl}${path}`, body, { headers })
|
|
523
|
+
.pipe(catchError(this.handleError.bind(this)));
|
|
524
|
+
}
|
|
525
|
+
delete(path, body) {
|
|
526
|
+
const headers = this.getHeaders(this.validateContentType(body));
|
|
527
|
+
return this.http
|
|
528
|
+
.request('DELETE', `${this.apiUrl}${path}`, { headers, body })
|
|
529
|
+
.pipe(catchError(this.handleError.bind(this)));
|
|
530
|
+
}
|
|
531
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ApiService, deps: [{ token: i1.HttpClient }, { token: PLATFORM_ID }, { token: TICKERA_COMPONENTS_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
532
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ApiService, providedIn: 'root' });
|
|
533
|
+
}
|
|
534
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ApiService, decorators: [{
|
|
535
|
+
type: Injectable,
|
|
536
|
+
args: [{
|
|
537
|
+
providedIn: 'root',
|
|
538
|
+
}]
|
|
539
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: Object, decorators: [{
|
|
540
|
+
type: Inject,
|
|
541
|
+
args: [PLATFORM_ID]
|
|
542
|
+
}] }, { type: undefined, decorators: [{
|
|
543
|
+
type: Inject,
|
|
544
|
+
args: [TICKERA_COMPONENTS_CONFIG]
|
|
545
|
+
}] }] });
|
|
546
|
+
|
|
547
|
+
class ToastService {
|
|
548
|
+
show(message, type = 'info') {
|
|
549
|
+
toast[type](message);
|
|
550
|
+
}
|
|
551
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
552
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ToastService, providedIn: 'root' });
|
|
553
|
+
}
|
|
554
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ToastService, decorators: [{
|
|
555
|
+
type: Injectable,
|
|
556
|
+
args: [{ providedIn: 'root' }]
|
|
557
|
+
}] });
|
|
558
|
+
|
|
559
|
+
class LoadingModalService {
|
|
560
|
+
title = signal('', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
561
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
562
|
+
get modalIsOpen() {
|
|
563
|
+
return this.isOpen;
|
|
564
|
+
}
|
|
565
|
+
open(title) {
|
|
566
|
+
this.title.set(title ?? 'Cargando...');
|
|
567
|
+
this.isOpen.set(true);
|
|
568
|
+
}
|
|
569
|
+
close() {
|
|
570
|
+
this.isOpen.set(false);
|
|
571
|
+
}
|
|
572
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: LoadingModalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
573
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: LoadingModalService, providedIn: 'root' });
|
|
574
|
+
}
|
|
575
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: LoadingModalService, decorators: [{
|
|
576
|
+
type: Injectable,
|
|
577
|
+
args: [{ providedIn: 'root' }]
|
|
578
|
+
}] });
|
|
579
|
+
|
|
580
|
+
class DeleteConfirmationService {
|
|
581
|
+
title = signal('Confirmar eliminación', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
582
|
+
resourceName = signal('', ...(ngDevMode ? [{ debugName: "resourceName" }] : []));
|
|
583
|
+
confirmationText = signal('', ...(ngDevMode ? [{ debugName: "confirmationText" }] : []));
|
|
584
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
585
|
+
confirmDeleteCallback = null;
|
|
586
|
+
get modalTitle() {
|
|
587
|
+
return this.title;
|
|
588
|
+
}
|
|
589
|
+
get modalResourceName() {
|
|
590
|
+
return this.resourceName;
|
|
591
|
+
}
|
|
592
|
+
get modalConfirmationText() {
|
|
593
|
+
return this.confirmationText;
|
|
594
|
+
}
|
|
595
|
+
get modalIsOpen() {
|
|
596
|
+
return this.isOpen;
|
|
597
|
+
}
|
|
598
|
+
open({ title, resourceName, confirmationText }, confirmCallback) {
|
|
599
|
+
this.title.set(title);
|
|
600
|
+
this.resourceName.set(resourceName);
|
|
601
|
+
this.confirmationText.set(confirmationText);
|
|
602
|
+
this.confirmDeleteCallback = confirmCallback || null;
|
|
603
|
+
this.isOpen.set(true);
|
|
604
|
+
}
|
|
605
|
+
close() {
|
|
606
|
+
this.title.set('Confirmar eliminación');
|
|
607
|
+
this.resourceName.set('');
|
|
608
|
+
this.confirmationText.set('');
|
|
609
|
+
this.confirmDeleteCallback = null;
|
|
610
|
+
this.isOpen.set(false);
|
|
611
|
+
}
|
|
612
|
+
getConfirmDeleteCallback() {
|
|
613
|
+
return this.confirmDeleteCallback;
|
|
614
|
+
}
|
|
615
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DeleteConfirmationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
616
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DeleteConfirmationService, providedIn: 'root' });
|
|
617
|
+
}
|
|
618
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DeleteConfirmationService, decorators: [{
|
|
619
|
+
type: Injectable,
|
|
620
|
+
args: [{ providedIn: 'root' }]
|
|
621
|
+
}] });
|
|
622
|
+
|
|
623
|
+
class ChangePasswordFormService {
|
|
624
|
+
resourceId = signal(0, ...(ngDevMode ? [{ debugName: "resourceId" }] : []));
|
|
625
|
+
isCustomer = signal(false, ...(ngDevMode ? [{ debugName: "isCustomer" }] : []));
|
|
626
|
+
isAdmin = signal(false, ...(ngDevMode ? [{ debugName: "isAdmin" }] : []));
|
|
627
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
628
|
+
get modalIsOpen() {
|
|
629
|
+
return this.isOpen;
|
|
630
|
+
}
|
|
631
|
+
get isCustomerMode() {
|
|
632
|
+
return this.isCustomer;
|
|
633
|
+
}
|
|
634
|
+
get isAdminMode() {
|
|
635
|
+
return this.isAdmin;
|
|
636
|
+
}
|
|
637
|
+
get resourceIdValue() {
|
|
638
|
+
return this.resourceId;
|
|
639
|
+
}
|
|
640
|
+
open(resourceId, isAdmin = false) {
|
|
641
|
+
this.resourceId.set(resourceId);
|
|
642
|
+
this.isCustomer.set(!isAdmin);
|
|
643
|
+
this.isAdmin.set(isAdmin);
|
|
644
|
+
this.isOpen.set(true);
|
|
645
|
+
}
|
|
646
|
+
close() {
|
|
647
|
+
this.isOpen.set(false);
|
|
648
|
+
}
|
|
649
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ChangePasswordFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
650
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ChangePasswordFormService, providedIn: 'root' });
|
|
651
|
+
}
|
|
652
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ChangePasswordFormService, decorators: [{
|
|
653
|
+
type: Injectable,
|
|
654
|
+
args: [{ providedIn: 'root' }]
|
|
655
|
+
}] });
|
|
656
|
+
|
|
657
|
+
class DateService {
|
|
658
|
+
locale;
|
|
659
|
+
constructor(locale) {
|
|
660
|
+
this.locale = locale;
|
|
661
|
+
}
|
|
662
|
+
formatDate(date, format = 'yyyy-MM-dd') {
|
|
663
|
+
const formattedDate = formatDate(date, format, this.locale);
|
|
664
|
+
return formattedDate;
|
|
665
|
+
}
|
|
666
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DateService, deps: [{ token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
667
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DateService, providedIn: 'root' });
|
|
668
|
+
}
|
|
669
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DateService, decorators: [{
|
|
670
|
+
type: Injectable,
|
|
671
|
+
args: [{ providedIn: 'root' }]
|
|
672
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
673
|
+
type: Inject,
|
|
674
|
+
args: [LOCALE_ID]
|
|
675
|
+
}] }] });
|
|
676
|
+
|
|
677
|
+
class AdminService {
|
|
678
|
+
apiService;
|
|
679
|
+
constructor(apiService) {
|
|
680
|
+
this.apiService = apiService;
|
|
681
|
+
}
|
|
682
|
+
fetchAdmins(page = 1, search = '', limit = 20) {
|
|
683
|
+
const queryParams = new URLSearchParams();
|
|
684
|
+
if (page)
|
|
685
|
+
queryParams.append('page', page.toString());
|
|
686
|
+
if (search)
|
|
687
|
+
queryParams.append('search', search);
|
|
688
|
+
if (limit)
|
|
689
|
+
queryParams.append('limit', limit.toString());
|
|
690
|
+
const queryString = queryParams.toString();
|
|
691
|
+
const apiRoute = `${ADMIN_API_ROUTES.FIND_ALL}${queryString ? '?' + queryString : ''}`;
|
|
692
|
+
return this.apiService.get(apiRoute);
|
|
693
|
+
}
|
|
694
|
+
deleteOne(id) {
|
|
695
|
+
return this.apiService.delete(ADMIN_API_ROUTES.deleteOne(id));
|
|
696
|
+
}
|
|
697
|
+
createOne(data) {
|
|
698
|
+
return this.apiService.post(ADMIN_API_ROUTES.CREATE, data);
|
|
699
|
+
}
|
|
700
|
+
updateOne(id, data) {
|
|
701
|
+
return this.apiService.patch(ADMIN_API_ROUTES.updateOne(id), data);
|
|
702
|
+
}
|
|
703
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdminService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
704
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdminService, providedIn: 'root' });
|
|
705
|
+
}
|
|
706
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdminService, decorators: [{
|
|
707
|
+
type: Injectable,
|
|
708
|
+
args: [{ providedIn: 'root' }]
|
|
709
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
710
|
+
|
|
711
|
+
class CitiesService {
|
|
712
|
+
apiService;
|
|
713
|
+
constructor(apiService) {
|
|
714
|
+
this.apiService = apiService;
|
|
715
|
+
}
|
|
716
|
+
fetchCities({ page, search, stateId }) {
|
|
717
|
+
const queryParams = new URLSearchParams();
|
|
718
|
+
if (page)
|
|
719
|
+
queryParams.append('page', page.toString());
|
|
720
|
+
if (search)
|
|
721
|
+
queryParams.append('search', search);
|
|
722
|
+
if (stateId)
|
|
723
|
+
queryParams.append('state_id', stateId.toString());
|
|
724
|
+
const queryString = queryParams.toString();
|
|
725
|
+
const apiRoute = `${CITY_API_ENDPOINTS.findAll}${queryString ? '?' + queryString : ''}`;
|
|
726
|
+
return this.apiService.get(apiRoute);
|
|
727
|
+
}
|
|
728
|
+
createOne(data) {
|
|
729
|
+
return this.apiService.post(CITY_API_ENDPOINTS.create, data);
|
|
730
|
+
}
|
|
731
|
+
updateOne(id, data) {
|
|
732
|
+
return this.apiService.patch(CITY_API_ENDPOINTS.update(id), data);
|
|
733
|
+
}
|
|
734
|
+
deleteOne(id) {
|
|
735
|
+
return this.apiService.delete(CITY_API_ENDPOINTS.delete(id));
|
|
736
|
+
}
|
|
737
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CitiesService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
738
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CitiesService, providedIn: 'root' });
|
|
739
|
+
}
|
|
740
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CitiesService, decorators: [{
|
|
741
|
+
type: Injectable,
|
|
742
|
+
args: [{ providedIn: 'root' }]
|
|
743
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
744
|
+
|
|
745
|
+
class CountryService {
|
|
746
|
+
apiService;
|
|
747
|
+
constructor(apiService) {
|
|
748
|
+
this.apiService = apiService;
|
|
749
|
+
}
|
|
750
|
+
fetchCountries(page, search) {
|
|
751
|
+
const queryParams = new URLSearchParams();
|
|
752
|
+
if (page)
|
|
753
|
+
queryParams.append('page', page.toString());
|
|
754
|
+
if (search)
|
|
755
|
+
queryParams.append('search', search);
|
|
756
|
+
const queryString = queryParams.toString();
|
|
757
|
+
const apiRoute = `${COUNTRY_API_ENDPOINTS.findAll}${queryString ? '?' + queryString : ''}`;
|
|
758
|
+
return this.apiService.get(apiRoute);
|
|
759
|
+
}
|
|
760
|
+
createOne(data) {
|
|
761
|
+
return this.apiService.post(COUNTRY_API_ENDPOINTS.create, data);
|
|
762
|
+
}
|
|
763
|
+
updateOne(id, data) {
|
|
764
|
+
return this.apiService.patch(COUNTRY_API_ENDPOINTS.update(id), data);
|
|
765
|
+
}
|
|
766
|
+
deleteOne(id) {
|
|
767
|
+
return this.apiService.delete(COUNTRY_API_ENDPOINTS.delete(id));
|
|
768
|
+
}
|
|
769
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CountryService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
770
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CountryService, providedIn: 'root' });
|
|
771
|
+
}
|
|
772
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CountryService, decorators: [{
|
|
773
|
+
type: Injectable,
|
|
774
|
+
args: [{ providedIn: 'root' }]
|
|
775
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
776
|
+
|
|
777
|
+
class StatesService {
|
|
778
|
+
apiService;
|
|
779
|
+
constructor(apiService) {
|
|
780
|
+
this.apiService = apiService;
|
|
781
|
+
}
|
|
782
|
+
fetchStates(page, search, countryId) {
|
|
783
|
+
const queryParams = new URLSearchParams();
|
|
784
|
+
if (page)
|
|
785
|
+
queryParams.append('page', page.toString());
|
|
786
|
+
if (search)
|
|
787
|
+
queryParams.append('search', search);
|
|
788
|
+
if (countryId)
|
|
789
|
+
queryParams.append('country_id', countryId.toString());
|
|
790
|
+
const queryString = queryParams.toString();
|
|
791
|
+
const apiRoute = `${STATE_API_ENDPOINTS.findAll}${queryString ? '?' + queryString : ''}`;
|
|
792
|
+
return this.apiService.get(apiRoute);
|
|
793
|
+
}
|
|
794
|
+
fetchStatesByCountryId(countryId) {
|
|
795
|
+
const apiRoute = `${STATE_API_ENDPOINTS.findAll}?country_id=${countryId}`;
|
|
796
|
+
return this.apiService.get(apiRoute);
|
|
797
|
+
}
|
|
798
|
+
createOne(data) {
|
|
799
|
+
return this.apiService.post(STATE_API_ENDPOINTS.create, data);
|
|
800
|
+
}
|
|
801
|
+
updateOne(id, data) {
|
|
802
|
+
return this.apiService.patch(STATE_API_ENDPOINTS.update(id), data);
|
|
803
|
+
}
|
|
804
|
+
deleteOne(id) {
|
|
805
|
+
return this.apiService.delete(STATE_API_ENDPOINTS.delete(id));
|
|
806
|
+
}
|
|
807
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: StatesService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
808
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: StatesService, providedIn: 'root' });
|
|
809
|
+
}
|
|
810
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: StatesService, decorators: [{
|
|
811
|
+
type: Injectable,
|
|
812
|
+
args: [{ providedIn: 'root' }]
|
|
813
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
814
|
+
|
|
815
|
+
class PerformanceService {
|
|
816
|
+
apiService;
|
|
817
|
+
performancesSubject = new BehaviorSubject([]);
|
|
818
|
+
performances$ = this.performancesSubject.asObservable();
|
|
819
|
+
constructor(apiService) {
|
|
820
|
+
this.apiService = apiService;
|
|
821
|
+
}
|
|
822
|
+
fetchPerformances(showId, search) {
|
|
823
|
+
const queryParams = new URLSearchParams();
|
|
824
|
+
if (showId)
|
|
825
|
+
queryParams.append('show_id', showId.toString());
|
|
826
|
+
if (search)
|
|
827
|
+
queryParams.append('search', search);
|
|
828
|
+
queryParams.append('limit', '100');
|
|
829
|
+
const queryString = queryParams.toString();
|
|
830
|
+
const apiRoute = `${PERFORMANCES_API_ROUTES.findAll}${queryString ? '?' + queryString : ''}`;
|
|
831
|
+
return this.apiService.get(apiRoute);
|
|
832
|
+
}
|
|
833
|
+
fetchDailyPerformances({ show_id, search, limit, date, }) {
|
|
834
|
+
const queryParams = new URLSearchParams();
|
|
835
|
+
if (date)
|
|
836
|
+
queryParams.append('date', date.toString());
|
|
837
|
+
if (show_id)
|
|
838
|
+
queryParams.append('show_id', show_id.toString());
|
|
839
|
+
if (search)
|
|
840
|
+
queryParams.append('search', search);
|
|
841
|
+
queryParams.append('limit', limit?.toString() ?? '100');
|
|
842
|
+
const queryString = queryParams.toString();
|
|
843
|
+
const apiRoute = `${PERFORMANCES_API_ROUTES.publicAvailablePerformances}${queryString ? '?' + queryString : ''}`;
|
|
844
|
+
return this.apiService.get(apiRoute);
|
|
845
|
+
}
|
|
846
|
+
loadPerformances({ showId, search } = {}) {
|
|
847
|
+
this.fetchPerformances(showId, search).subscribe({
|
|
848
|
+
next: ({ data }) => {
|
|
849
|
+
this.performancesSubject.next(data?.performances ?? []);
|
|
850
|
+
},
|
|
851
|
+
error: () => {
|
|
852
|
+
this.performancesSubject.next([]);
|
|
853
|
+
},
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
getCurrentPerformances() {
|
|
857
|
+
return this.performancesSubject.value;
|
|
858
|
+
}
|
|
859
|
+
fetchOneById(id) {
|
|
860
|
+
return this.apiService.get(PERFORMANCES_API_ROUTES.findOneById(id));
|
|
861
|
+
}
|
|
862
|
+
fetchOneBookingData(id) {
|
|
863
|
+
const apiRoute = PERFORMANCES_API_ROUTES.findOneBookingData(id);
|
|
864
|
+
return this.apiService.get(apiRoute);
|
|
865
|
+
}
|
|
866
|
+
fetchAvailableDays(params) {
|
|
867
|
+
const queryParams = new URLSearchParams();
|
|
868
|
+
if (params?.show_id)
|
|
869
|
+
queryParams.append('show_id', params.show_id.toString());
|
|
870
|
+
const queryString = queryParams.toString();
|
|
871
|
+
const apiRoute = `${PERFORMANCES_API_ROUTES.getAvailableDays}${queryString ? '?' + queryString : ''}`;
|
|
872
|
+
return this.apiService.get(apiRoute);
|
|
873
|
+
}
|
|
874
|
+
createOne(data) {
|
|
875
|
+
return this.apiService.post(PERFORMANCES_API_ROUTES.create, data);
|
|
876
|
+
}
|
|
877
|
+
createMany(data) {
|
|
878
|
+
return this.apiService.post(PERFORMANCES_API_ROUTES.createBulk, { performances: data });
|
|
879
|
+
}
|
|
880
|
+
updateOne(id, data) {
|
|
881
|
+
return this.apiService.patch(PERFORMANCES_API_ROUTES.update(id), data);
|
|
882
|
+
}
|
|
883
|
+
deleteOne(id) {
|
|
884
|
+
return this.apiService.delete(PERFORMANCES_API_ROUTES.delete(id));
|
|
885
|
+
}
|
|
886
|
+
deleteMany(ids) {
|
|
887
|
+
return this.apiService.delete(PERFORMANCES_API_ROUTES.deleteMany, { ids });
|
|
888
|
+
}
|
|
889
|
+
cancelPerformance(id, notifyUsers) {
|
|
890
|
+
return this.apiService.patch(PERFORMANCES_API_ROUTES.cancel(id), { notify_users: notifyUsers });
|
|
891
|
+
}
|
|
892
|
+
publishInvenotry(id) {
|
|
893
|
+
const apiRoute = PERFORMANCES_API_ROUTES.publishInventory(id);
|
|
894
|
+
return this.apiService.post(apiRoute, {});
|
|
895
|
+
}
|
|
896
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformanceService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
897
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformanceService, providedIn: 'root' });
|
|
898
|
+
}
|
|
899
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformanceService, decorators: [{
|
|
900
|
+
type: Injectable,
|
|
901
|
+
args: [{ providedIn: 'root' }]
|
|
902
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
903
|
+
|
|
904
|
+
class PerformancesListEventsService {
|
|
905
|
+
_selectedDay = signal(null, ...(ngDevMode ? [{ debugName: "_selectedDay" }] : []));
|
|
906
|
+
_selectedPerformance = signal(null, ...(ngDevMode ? [{ debugName: "_selectedPerformance" }] : []));
|
|
907
|
+
_filteredShowId = signal(null, ...(ngDevMode ? [{ debugName: "_filteredShowId" }] : []));
|
|
908
|
+
selectedDay = computed(() => this._selectedDay(), ...(ngDevMode ? [{ debugName: "selectedDay" }] : []));
|
|
909
|
+
selectedDayDate = computed(() => this._selectedDay()?.date, ...(ngDevMode ? [{ debugName: "selectedDayDate" }] : []));
|
|
910
|
+
selectedPerformance = computed(() => this._selectedPerformance(), ...(ngDevMode ? [{ debugName: "selectedPerformance" }] : []));
|
|
911
|
+
filteredShowId = computed(() => this._filteredShowId(), ...(ngDevMode ? [{ debugName: "filteredShowId" }] : []));
|
|
912
|
+
setSelectedDay(day) {
|
|
913
|
+
this._selectedDay.set(day);
|
|
914
|
+
}
|
|
915
|
+
setSelectedPerformance(performance) {
|
|
916
|
+
this._selectedPerformance.set(performance);
|
|
917
|
+
}
|
|
918
|
+
setFilteredShowId(id) {
|
|
919
|
+
this._filteredShowId.set(id);
|
|
920
|
+
}
|
|
921
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformancesListEventsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
922
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformancesListEventsService, providedIn: 'root' });
|
|
923
|
+
}
|
|
924
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformancesListEventsService, decorators: [{
|
|
925
|
+
type: Injectable,
|
|
926
|
+
args: [{ providedIn: 'root' }]
|
|
927
|
+
}] });
|
|
928
|
+
|
|
929
|
+
class ProductService {
|
|
930
|
+
apiService;
|
|
931
|
+
productsSubject = new BehaviorSubject([]);
|
|
932
|
+
products$ = this.productsSubject.asObservable();
|
|
933
|
+
constructor(apiService) {
|
|
934
|
+
this.apiService = apiService;
|
|
935
|
+
}
|
|
936
|
+
fetchProducts(page, search) {
|
|
937
|
+
const queryParams = new URLSearchParams();
|
|
938
|
+
if (page)
|
|
939
|
+
queryParams.append('page', page.toString());
|
|
940
|
+
if (search)
|
|
941
|
+
queryParams.append('search', search);
|
|
942
|
+
const queryString = queryParams.toString();
|
|
943
|
+
const apiRoute = `${PRODUCTS_API_ROUTES.FIND_ALL}${queryString ? '?' + queryString : ''}`;
|
|
944
|
+
return this.apiService.get(apiRoute);
|
|
945
|
+
}
|
|
946
|
+
loadProducts({ page, search } = {}) {
|
|
947
|
+
this.fetchProducts(page ?? 1, search ?? '').subscribe({
|
|
948
|
+
next: ({ data }) => {
|
|
949
|
+
this.productsSubject.next(data?.products ?? []);
|
|
950
|
+
},
|
|
951
|
+
error: () => {
|
|
952
|
+
this.productsSubject.next([]);
|
|
953
|
+
},
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
getCurrentProducts() {
|
|
957
|
+
return this.productsSubject.value;
|
|
958
|
+
}
|
|
959
|
+
fetchOneById(id) {
|
|
960
|
+
return this.apiService.get(PRODUCTS_API_ROUTES.findOneById(id));
|
|
961
|
+
}
|
|
962
|
+
createOne(data) {
|
|
963
|
+
return this.apiService.post(PRODUCTS_API_ROUTES.CREATE, data);
|
|
964
|
+
}
|
|
965
|
+
updateOne(id, data) {
|
|
966
|
+
return this.apiService.patch(PRODUCTS_API_ROUTES.update(id), data);
|
|
967
|
+
}
|
|
968
|
+
deleteOne(id) {
|
|
969
|
+
return this.apiService.delete(PRODUCTS_API_ROUTES.delete(id));
|
|
970
|
+
}
|
|
971
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ProductService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
972
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ProductService, providedIn: 'root' });
|
|
973
|
+
}
|
|
974
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ProductService, decorators: [{
|
|
975
|
+
type: Injectable,
|
|
976
|
+
args: [{ providedIn: 'root' }]
|
|
977
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
978
|
+
|
|
979
|
+
class ShowService {
|
|
980
|
+
apiService;
|
|
981
|
+
showsSubject = new BehaviorSubject([]);
|
|
982
|
+
shows$ = this.showsSubject.asObservable();
|
|
983
|
+
constructor(apiService) {
|
|
984
|
+
this.apiService = apiService;
|
|
985
|
+
}
|
|
986
|
+
loadShows({ page, search } = {}) {
|
|
987
|
+
this.fetchShows({ page, search }).subscribe({
|
|
988
|
+
next: ({ data }) => {
|
|
989
|
+
this.showsSubject.next(data?.shows ?? []);
|
|
990
|
+
},
|
|
991
|
+
error: () => {
|
|
992
|
+
this.showsSubject.next([]);
|
|
993
|
+
},
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
getCurrentShows() {
|
|
997
|
+
return this.showsSubject.value;
|
|
998
|
+
}
|
|
999
|
+
fetchShows({ limit, page, search }) {
|
|
1000
|
+
const queryParams = new URLSearchParams();
|
|
1001
|
+
if (page)
|
|
1002
|
+
queryParams.append('page', page.toString());
|
|
1003
|
+
if (limit)
|
|
1004
|
+
queryParams.append('limit', limit.toString());
|
|
1005
|
+
if (search)
|
|
1006
|
+
queryParams.append('search', search);
|
|
1007
|
+
const queryString = queryParams.toString();
|
|
1008
|
+
const apiRoute = `${SHOWS_API_ROUTES.findAll}${queryString ? '?' + queryString : ''}`;
|
|
1009
|
+
return this.apiService.get(apiRoute);
|
|
1010
|
+
}
|
|
1011
|
+
fetchAvailableShows({ date, limit, page, search, }) {
|
|
1012
|
+
const queryParams = new URLSearchParams();
|
|
1013
|
+
if (date)
|
|
1014
|
+
queryParams.append('date', date);
|
|
1015
|
+
if (page)
|
|
1016
|
+
queryParams.append('page', page.toString());
|
|
1017
|
+
if (search)
|
|
1018
|
+
queryParams.append('search', search);
|
|
1019
|
+
if (limit)
|
|
1020
|
+
queryParams.append('limit', limit.toString());
|
|
1021
|
+
const queryString = queryParams.toString();
|
|
1022
|
+
const apiRoute = `${SHOWS_API_ROUTES.publicAvailablePerformances}${queryString ? '?' + queryString : ''}`;
|
|
1023
|
+
return this.apiService.get(apiRoute);
|
|
1024
|
+
}
|
|
1025
|
+
fetchOneById(id) {
|
|
1026
|
+
return this.apiService.get(SHOWS_API_ROUTES.findOneById(id));
|
|
1027
|
+
}
|
|
1028
|
+
createOne(data) {
|
|
1029
|
+
return this.apiService.post(SHOWS_API_ROUTES.create, data);
|
|
1030
|
+
}
|
|
1031
|
+
updateOne(id, data) {
|
|
1032
|
+
return this.apiService.patch(SHOWS_API_ROUTES.update(id), data);
|
|
1033
|
+
}
|
|
1034
|
+
deleteOne(id) {
|
|
1035
|
+
return this.apiService.delete(SHOWS_API_ROUTES.delete(id));
|
|
1036
|
+
}
|
|
1037
|
+
fetchImages(id) {
|
|
1038
|
+
return this.apiService.get(SHOWS_API_ROUTES.getImages(id));
|
|
1039
|
+
}
|
|
1040
|
+
uploadImages(id, files) {
|
|
1041
|
+
return this.apiService.post(SHOWS_API_ROUTES.uploadGallery(id), files);
|
|
1042
|
+
}
|
|
1043
|
+
deleteOneImage(showId, imageId) {
|
|
1044
|
+
return this.apiService.delete(SHOWS_API_ROUTES.deleteOneImage(showId, imageId));
|
|
1045
|
+
}
|
|
1046
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ShowService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1047
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ShowService, providedIn: 'root' });
|
|
1048
|
+
}
|
|
1049
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ShowService, decorators: [{
|
|
1050
|
+
type: Injectable,
|
|
1051
|
+
args: [{ providedIn: 'root' }]
|
|
1052
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
1053
|
+
|
|
1054
|
+
class CustomerService {
|
|
1055
|
+
apiService;
|
|
1056
|
+
constructor(apiService) {
|
|
1057
|
+
this.apiService = apiService;
|
|
1058
|
+
}
|
|
1059
|
+
createOne(data) {
|
|
1060
|
+
return this.apiService.post(CUSTOMERS_API_ROUTES.create, data);
|
|
1061
|
+
}
|
|
1062
|
+
fetchCustomers(page, search, limit) {
|
|
1063
|
+
const queryParams = new URLSearchParams();
|
|
1064
|
+
if (page)
|
|
1065
|
+
queryParams.append('page', page.toString());
|
|
1066
|
+
if (search)
|
|
1067
|
+
queryParams.append('search', search);
|
|
1068
|
+
if (limit)
|
|
1069
|
+
queryParams.append('limit', limit.toString());
|
|
1070
|
+
const queryString = queryParams.toString();
|
|
1071
|
+
const apiRoute = `${CUSTOMERS_API_ROUTES.findAll}${queryString ? '?' + queryString : ''}`;
|
|
1072
|
+
return this.apiService.get(apiRoute);
|
|
1073
|
+
}
|
|
1074
|
+
fetchOneById(id) {
|
|
1075
|
+
return this.apiService.get(CUSTOMERS_API_ROUTES.findOne(id));
|
|
1076
|
+
}
|
|
1077
|
+
updateOne(id, data) {
|
|
1078
|
+
return this.apiService.patch(CUSTOMERS_API_ROUTES.update(id), data);
|
|
1079
|
+
}
|
|
1080
|
+
deleteOne(id) {
|
|
1081
|
+
return this.apiService.delete(CUSTOMERS_API_ROUTES.delete(id));
|
|
1082
|
+
}
|
|
1083
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CustomerService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1084
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CustomerService, providedIn: 'root' });
|
|
1085
|
+
}
|
|
1086
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CustomerService, decorators: [{
|
|
1087
|
+
type: Injectable,
|
|
1088
|
+
args: [{ providedIn: 'root' }]
|
|
1089
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
1090
|
+
|
|
1091
|
+
class PriceZoneService {
|
|
1092
|
+
apiService;
|
|
1093
|
+
priceZonesSubject = new BehaviorSubject([]);
|
|
1094
|
+
priceZones$ = this.priceZonesSubject.asObservable();
|
|
1095
|
+
constructor(apiService) {
|
|
1096
|
+
this.apiService = apiService;
|
|
1097
|
+
}
|
|
1098
|
+
fetchPriceZones({ roomMapId, page, search, limit, } = {}) {
|
|
1099
|
+
const queryParams = new URLSearchParams();
|
|
1100
|
+
if (roomMapId)
|
|
1101
|
+
queryParams.append('room_map_id', roomMapId.toString());
|
|
1102
|
+
if (page)
|
|
1103
|
+
queryParams.append('page', page.toString());
|
|
1104
|
+
if (search)
|
|
1105
|
+
queryParams.append('search', search);
|
|
1106
|
+
if (limit)
|
|
1107
|
+
queryParams.append('limit', limit.toString());
|
|
1108
|
+
const queryString = queryParams.toString();
|
|
1109
|
+
const apiRoute = `${PRICE_ZONES_API_ROUTES.FIND_ALL}${queryString ? '?' + queryString : ''}`;
|
|
1110
|
+
return this.apiService.get(apiRoute);
|
|
1111
|
+
}
|
|
1112
|
+
loadPriceZones({ roomMapId, page, search, limit } = {}) {
|
|
1113
|
+
this.fetchPriceZones({ roomMapId, page, search, limit }).subscribe({
|
|
1114
|
+
next: ({ data }) => {
|
|
1115
|
+
this.priceZonesSubject.next(data?.price_zones ?? []);
|
|
1116
|
+
},
|
|
1117
|
+
error: () => {
|
|
1118
|
+
this.priceZonesSubject.next([]);
|
|
1119
|
+
},
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
getCurrentPriceZones() {
|
|
1123
|
+
return this.priceZonesSubject.value;
|
|
1124
|
+
}
|
|
1125
|
+
fetchOneById(id) {
|
|
1126
|
+
return this.apiService.get(PRICE_ZONES_API_ROUTES.findOneById(id));
|
|
1127
|
+
}
|
|
1128
|
+
createOne(data) {
|
|
1129
|
+
return this.apiService.post(PRICE_ZONES_API_ROUTES.CREATE, data);
|
|
1130
|
+
}
|
|
1131
|
+
duplicateOne(id, name) {
|
|
1132
|
+
return this.apiService.post(PRICE_ZONES_API_ROUTES.duplicate(id), { name });
|
|
1133
|
+
}
|
|
1134
|
+
updateOne(id, data) {
|
|
1135
|
+
return this.apiService.patch(PRICE_ZONES_API_ROUTES.update(id), data);
|
|
1136
|
+
}
|
|
1137
|
+
deleteOne(id) {
|
|
1138
|
+
return this.apiService.delete(PRICE_ZONES_API_ROUTES.delete(id));
|
|
1139
|
+
}
|
|
1140
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneService, deps: [{ token: ApiService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1141
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneService, providedIn: 'root' });
|
|
1142
|
+
}
|
|
1143
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneService, decorators: [{
|
|
1144
|
+
type: Injectable,
|
|
1145
|
+
args: [{ providedIn: 'root' }]
|
|
1146
|
+
}], ctorParameters: () => [{ type: ApiService }] });
|
|
1147
|
+
|
|
1148
|
+
class PriceZoneEventService {
|
|
1149
|
+
priceZoneDeleted$ = new Subject();
|
|
1150
|
+
priceZoneSaved$ = new Subject();
|
|
1151
|
+
_selectedPriceZone = signal(null, ...(ngDevMode ? [{ debugName: "_selectedPriceZone" }] : []));
|
|
1152
|
+
selectedPriceZone$ = toObservable(this._selectedPriceZone);
|
|
1153
|
+
onPriceZoneDeleted() {
|
|
1154
|
+
this.priceZoneDeleted$.next();
|
|
1155
|
+
}
|
|
1156
|
+
getPriceZoneDeleted() {
|
|
1157
|
+
return this.priceZoneDeleted$.asObservable();
|
|
1158
|
+
}
|
|
1159
|
+
onPriceZoneSaved() {
|
|
1160
|
+
this.priceZoneSaved$.next();
|
|
1161
|
+
}
|
|
1162
|
+
getPriceZoneSaved() {
|
|
1163
|
+
return this.priceZoneSaved$.asObservable();
|
|
1164
|
+
}
|
|
1165
|
+
setSelectedPriceZone(priceZone) {
|
|
1166
|
+
this._selectedPriceZone.set(priceZone);
|
|
1167
|
+
}
|
|
1168
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1169
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneEventService, providedIn: 'root' });
|
|
1170
|
+
}
|
|
1171
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneEventService, decorators: [{
|
|
1172
|
+
type: Injectable,
|
|
1173
|
+
args: [{ providedIn: 'root' }]
|
|
1174
|
+
}] });
|
|
1175
|
+
|
|
1176
|
+
class PriceZoneFormModalService {
|
|
1177
|
+
priceZoneEventService;
|
|
1178
|
+
priceZone = signal(null, ...(ngDevMode ? [{ debugName: "priceZone" }] : []));
|
|
1179
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
1180
|
+
constructor(priceZoneEventService) {
|
|
1181
|
+
this.priceZoneEventService = priceZoneEventService;
|
|
1182
|
+
}
|
|
1183
|
+
get modalIsOpen() {
|
|
1184
|
+
return this.isOpen;
|
|
1185
|
+
}
|
|
1186
|
+
get currentPriceZone() {
|
|
1187
|
+
return this.priceZone;
|
|
1188
|
+
}
|
|
1189
|
+
open(priceZone = null) {
|
|
1190
|
+
this.priceZone.set(priceZone);
|
|
1191
|
+
this.priceZoneEventService.setSelectedPriceZone(priceZone);
|
|
1192
|
+
this.isOpen.set(true);
|
|
1193
|
+
}
|
|
1194
|
+
close() {
|
|
1195
|
+
this.isOpen.set(false);
|
|
1196
|
+
this.priceZone.set(null);
|
|
1197
|
+
}
|
|
1198
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneFormModalService, deps: [{ token: PriceZoneEventService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1199
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneFormModalService, providedIn: 'root' });
|
|
1200
|
+
}
|
|
1201
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneFormModalService, decorators: [{
|
|
1202
|
+
type: Injectable,
|
|
1203
|
+
args: [{ providedIn: 'root' }]
|
|
1204
|
+
}], ctorParameters: () => [{ type: PriceZoneEventService }] });
|
|
1205
|
+
|
|
1206
|
+
const authInterceptor = (req, next) => {
|
|
1207
|
+
const platformId = inject(PLATFORM_ID);
|
|
1208
|
+
const config = inject(TICKERA_COMPONENTS_CONFIG);
|
|
1209
|
+
if (isPlatformBrowser(platformId)) {
|
|
1210
|
+
const key = config.accessTokenKey ?? 'access_token';
|
|
1211
|
+
const token = localStorage.getItem(key);
|
|
1212
|
+
if (token) {
|
|
1213
|
+
req = req.clone({
|
|
1214
|
+
setHeaders: { Authorization: `Bearer ${token}` },
|
|
1215
|
+
});
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
return next(req);
|
|
1219
|
+
};
|
|
1220
|
+
|
|
1221
|
+
class AppButtonComponent {
|
|
1222
|
+
clicked = new EventEmitter();
|
|
1223
|
+
disabled = false;
|
|
1224
|
+
loading = false;
|
|
1225
|
+
type = 'button';
|
|
1226
|
+
variant = 'primary';
|
|
1227
|
+
text = '';
|
|
1228
|
+
size = 'md';
|
|
1229
|
+
loadingText = '';
|
|
1230
|
+
icon = '';
|
|
1231
|
+
handleClick() {
|
|
1232
|
+
this.clicked.emit();
|
|
1233
|
+
}
|
|
1234
|
+
get buttonClasses() {
|
|
1235
|
+
const disabledClasses = this.disabled ? 'opacity-50 cursor-not-allowed' : '';
|
|
1236
|
+
const variantClasses = BUTTON_VARIANT_CLASSES[this.variant];
|
|
1237
|
+
const loadingClasses = this.loading ? 'opacity-50 cursor-not-allowed' : '';
|
|
1238
|
+
const sizeClasses = BUTTON_SIZES_CLASSES[this.size];
|
|
1239
|
+
return `${BASE_BUTTON_CLASSES} ${disabledClasses} ${variantClasses} ${loadingClasses} ${sizeClasses}`;
|
|
1240
|
+
}
|
|
1241
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AppButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1242
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AppButtonComponent, isStandalone: true, selector: "app-button", inputs: { disabled: "disabled", loading: "loading", type: "type", variant: "variant", text: "text", size: "size", loadingText: "loadingText", icon: "icon" }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<button\n [type]=\"type\"\n [disabled]=\"loading || disabled\"\n class=\"{{ buttonClasses }}\"\n (click)=\"handleClick()\"\n>\n @if (icon && !loading) {\n <i class=\"{{ icon }}\"></i>\n }\n\n @if (loading) {\n <i class=\"ri-refresh-line animate-spin\"></i>\n }\n\n {{ loading ? loadingText : text }}\n</button>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }], encapsulation: i0.ViewEncapsulation.None });
|
|
1243
|
+
}
|
|
1244
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AppButtonComponent, decorators: [{
|
|
1245
|
+
type: Component,
|
|
1246
|
+
args: [{ selector: 'app-button', standalone: true, imports: [CommonModule], encapsulation: ViewEncapsulation.None, template: "<button\n [type]=\"type\"\n [disabled]=\"loading || disabled\"\n class=\"{{ buttonClasses }}\"\n (click)=\"handleClick()\"\n>\n @if (icon && !loading) {\n <i class=\"{{ icon }}\"></i>\n }\n\n @if (loading) {\n <i class=\"ri-refresh-line animate-spin\"></i>\n }\n\n {{ loading ? loadingText : text }}\n</button>\n" }]
|
|
1247
|
+
}], propDecorators: { clicked: [{
|
|
1248
|
+
type: Output
|
|
1249
|
+
}], disabled: [{
|
|
1250
|
+
type: Input
|
|
1251
|
+
}], loading: [{
|
|
1252
|
+
type: Input
|
|
1253
|
+
}], type: [{
|
|
1254
|
+
type: Input
|
|
1255
|
+
}], variant: [{
|
|
1256
|
+
type: Input
|
|
1257
|
+
}], text: [{
|
|
1258
|
+
type: Input
|
|
1259
|
+
}], size: [{
|
|
1260
|
+
type: Input
|
|
1261
|
+
}], loadingText: [{
|
|
1262
|
+
type: Input
|
|
1263
|
+
}], icon: [{
|
|
1264
|
+
type: Input
|
|
1265
|
+
}] } });
|
|
1266
|
+
|
|
1267
|
+
class AppLinkButtonComponent {
|
|
1268
|
+
BASE_BUTTON_CLASSES = BASE_BUTTON_CLASSES;
|
|
1269
|
+
disabled = false;
|
|
1270
|
+
loading = false;
|
|
1271
|
+
target = '_self';
|
|
1272
|
+
text = '';
|
|
1273
|
+
icon = '';
|
|
1274
|
+
loadingText = '';
|
|
1275
|
+
route = '';
|
|
1276
|
+
queryParams = {};
|
|
1277
|
+
size = 'md';
|
|
1278
|
+
variant = 'primary';
|
|
1279
|
+
get buttonClasses() {
|
|
1280
|
+
const disabledClasses = this.disabled ? 'opacity-50 cursor-not-allowed' : '';
|
|
1281
|
+
const variantClasses = BUTTON_VARIANT_CLASSES[this.variant];
|
|
1282
|
+
const loadingClasses = this.loading ? 'opacity-50 cursor-not-allowed' : '';
|
|
1283
|
+
const sizeClasses = BUTTON_SIZES_CLASSES[this.size] || 'text-base';
|
|
1284
|
+
return [BASE_BUTTON_CLASSES, disabledClasses, variantClasses, loadingClasses, sizeClasses].join(' ');
|
|
1285
|
+
}
|
|
1286
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AppLinkButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1287
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AppLinkButtonComponent, isStandalone: true, selector: "app-link-button", inputs: { disabled: "disabled", loading: "loading", target: "target", text: "text", icon: "icon", loadingText: "loadingText", route: "route", queryParams: "queryParams", size: "size", variant: "variant" }, ngImport: i0, template: "<a class=\"{{ buttonClasses }}\" [routerLink]=\"!disabled ? route : null\" [queryParams]=\"queryParams\" [target]=\"target\">\n @if (icon) {\n <i [class]=\"icon\"></i>\n }\n\n {{ loading ? loadingText : text }}\n</a>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: TranslocoModule }], encapsulation: i0.ViewEncapsulation.None });
|
|
1288
|
+
}
|
|
1289
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AppLinkButtonComponent, decorators: [{
|
|
1290
|
+
type: Component,
|
|
1291
|
+
args: [{ selector: 'app-link-button', standalone: true, imports: [CommonModule, RouterLink, TranslocoModule], encapsulation: ViewEncapsulation.None, template: "<a class=\"{{ buttonClasses }}\" [routerLink]=\"!disabled ? route : null\" [queryParams]=\"queryParams\" [target]=\"target\">\n @if (icon) {\n <i [class]=\"icon\"></i>\n }\n\n {{ loading ? loadingText : text }}\n</a>\n" }]
|
|
1292
|
+
}], propDecorators: { disabled: [{
|
|
1293
|
+
type: Input
|
|
1294
|
+
}], loading: [{
|
|
1295
|
+
type: Input
|
|
1296
|
+
}], target: [{
|
|
1297
|
+
type: Input
|
|
1298
|
+
}], text: [{
|
|
1299
|
+
type: Input
|
|
1300
|
+
}], icon: [{
|
|
1301
|
+
type: Input
|
|
1302
|
+
}], loadingText: [{
|
|
1303
|
+
type: Input
|
|
1304
|
+
}], route: [{
|
|
1305
|
+
type: Input
|
|
1306
|
+
}], queryParams: [{
|
|
1307
|
+
type: Input
|
|
1308
|
+
}], size: [{
|
|
1309
|
+
type: Input
|
|
1310
|
+
}], variant: [{
|
|
1311
|
+
type: Input
|
|
1312
|
+
}] } });
|
|
1313
|
+
|
|
1314
|
+
class AppAlertComponent {
|
|
1315
|
+
type = 'success';
|
|
1316
|
+
text = '';
|
|
1317
|
+
closeable = false;
|
|
1318
|
+
size = 'md';
|
|
1319
|
+
get alertColorClasses() {
|
|
1320
|
+
return ALERT_COLOR_CLASSES[this.type] ?? ALERT_COLOR_CLASSES.success;
|
|
1321
|
+
}
|
|
1322
|
+
get alertSizeClasses() {
|
|
1323
|
+
return ALERT_SIZE_CLASSES[this.size] ?? ALERT_SIZE_CLASSES.sm;
|
|
1324
|
+
}
|
|
1325
|
+
get alertClasses() {
|
|
1326
|
+
return `${ALERT_BASE_CLASSES} ${this.alertColorClasses} ${this.alertSizeClasses}`;
|
|
1327
|
+
}
|
|
1328
|
+
get alertIcon() {
|
|
1329
|
+
return ALERT_ICONS[this.type] ?? ALERT_ICONS.info;
|
|
1330
|
+
}
|
|
1331
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AppAlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1332
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AppAlertComponent, isStandalone: true, selector: "app-alert", inputs: { type: "type", text: "text", closeable: "closeable", size: "size" }, ngImport: i0, template: "<div class=\"{{ alertClasses }}\" role=\"alert\">\n <div class=\"flex items-center gap-2\">\n <i class=\"{{ alertIcon }}\"></i>\n <span>{{ text }}</span>\n </div>\n\n @if (closeable) {\n <span\n class=\"absolute top-0 bottom-0 right-0 h-full w-8 flex items-center justify-center cursor-pointer\"\n >\n <i class=\"ri-close-line\"></i>\n </span>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }], encapsulation: i0.ViewEncapsulation.None });
|
|
1333
|
+
}
|
|
1334
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AppAlertComponent, decorators: [{
|
|
1335
|
+
type: Component,
|
|
1336
|
+
args: [{ selector: 'app-alert', standalone: true, imports: [CommonModule], encapsulation: ViewEncapsulation.None, template: "<div class=\"{{ alertClasses }}\" role=\"alert\">\n <div class=\"flex items-center gap-2\">\n <i class=\"{{ alertIcon }}\"></i>\n <span>{{ text }}</span>\n </div>\n\n @if (closeable) {\n <span\n class=\"absolute top-0 bottom-0 right-0 h-full w-8 flex items-center justify-center cursor-pointer\"\n >\n <i class=\"ri-close-line\"></i>\n </span>\n }\n</div>\n" }]
|
|
1337
|
+
}], propDecorators: { type: [{
|
|
1338
|
+
type: Input
|
|
1339
|
+
}], text: [{
|
|
1340
|
+
type: Input
|
|
1341
|
+
}], closeable: [{
|
|
1342
|
+
type: Input
|
|
1343
|
+
}], size: [{
|
|
1344
|
+
type: Input
|
|
1345
|
+
}] } });
|
|
1346
|
+
|
|
1347
|
+
class AppModalComponent {
|
|
1348
|
+
title = '';
|
|
1349
|
+
disableClose = false;
|
|
1350
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
1351
|
+
size = 'md';
|
|
1352
|
+
closeModal = new EventEmitter();
|
|
1353
|
+
onCloseModal() {
|
|
1354
|
+
if (this.disableClose)
|
|
1355
|
+
return;
|
|
1356
|
+
this.closeModal.emit();
|
|
1357
|
+
}
|
|
1358
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AppModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1359
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AppModalComponent, isStandalone: true, selector: "app-modal", inputs: { title: "title", disableClose: "disableClose", isOpen: "isOpen", size: "size" }, outputs: { closeModal: "closeModal" }, ngImport: i0, template: "@if (isOpen()) {\n <div class=\"fixed inset-0 flex items-center justify-center z-50\">\n <div class=\"absolute inset-0 bg-black opacity-50\" (click)=\"onCloseModal()\"></div>\n\n <div\n [class]=\"`bg-white rounded-lg max-h-screen overflow-y-auto shadow-xl relative z-10 max-w-${size} w-full`\"\n >\n @if (!disableClose || !!title) {\n <div class=\"flex justify-between items-center p-5 border-b border-gray-200\">\n <h3 class=\"text-lg font-semibold text-gray-800 m-0\">{{ title }}</h3>\n\n @if (!disableClose) {\n <button\n class=\"bg-none border-none text-2xl cursor-pointer text-gray-600 p-0 w-7.5 h-7.5 flex items-center justify-center hover:text-gray-800\"\n (click)=\"onCloseModal()\"\n >\n ×\n </button>\n }\n </div>\n }\n\n <div class=\"p-5\">\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n}\n", styles: [".max-w-xl{max-width:36rem}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], encapsulation: i0.ViewEncapsulation.None });
|
|
1360
|
+
}
|
|
1361
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AppModalComponent, decorators: [{
|
|
1362
|
+
type: Component,
|
|
1363
|
+
args: [{ selector: 'app-modal', standalone: true, imports: [CommonModule], encapsulation: ViewEncapsulation.None, template: "@if (isOpen()) {\n <div class=\"fixed inset-0 flex items-center justify-center z-50\">\n <div class=\"absolute inset-0 bg-black opacity-50\" (click)=\"onCloseModal()\"></div>\n\n <div\n [class]=\"`bg-white rounded-lg max-h-screen overflow-y-auto shadow-xl relative z-10 max-w-${size} w-full`\"\n >\n @if (!disableClose || !!title) {\n <div class=\"flex justify-between items-center p-5 border-b border-gray-200\">\n <h3 class=\"text-lg font-semibold text-gray-800 m-0\">{{ title }}</h3>\n\n @if (!disableClose) {\n <button\n class=\"bg-none border-none text-2xl cursor-pointer text-gray-600 p-0 w-7.5 h-7.5 flex items-center justify-center hover:text-gray-800\"\n (click)=\"onCloseModal()\"\n >\n ×\n </button>\n }\n </div>\n }\n\n <div class=\"p-5\">\n <ng-content></ng-content>\n </div>\n </div>\n </div>\n}\n", styles: [".max-w-xl{max-width:36rem}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}\n"] }]
|
|
1364
|
+
}], propDecorators: { title: [{
|
|
1365
|
+
type: Input
|
|
1366
|
+
}], disableClose: [{
|
|
1367
|
+
type: Input
|
|
1368
|
+
}], isOpen: [{
|
|
1369
|
+
type: Input
|
|
1370
|
+
}], size: [{
|
|
1371
|
+
type: Input
|
|
1372
|
+
}], closeModal: [{
|
|
1373
|
+
type: Output
|
|
1374
|
+
}] } });
|
|
1375
|
+
|
|
1376
|
+
class LoadingmModalComponent {
|
|
1377
|
+
loadingModalService;
|
|
1378
|
+
constructor(loadingModalService) {
|
|
1379
|
+
this.loadingModalService = loadingModalService;
|
|
1380
|
+
}
|
|
1381
|
+
get isOpen() {
|
|
1382
|
+
return this.loadingModalService.modalIsOpen;
|
|
1383
|
+
}
|
|
1384
|
+
get title() {
|
|
1385
|
+
return this.loadingModalService.title;
|
|
1386
|
+
}
|
|
1387
|
+
closeModal() {
|
|
1388
|
+
this.loadingModalService.close();
|
|
1389
|
+
}
|
|
1390
|
+
onCitySaved() {
|
|
1391
|
+
this.loadingModalService.close();
|
|
1392
|
+
}
|
|
1393
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: LoadingmModalComponent, deps: [{ token: LoadingModalService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1394
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: LoadingmModalComponent, isStandalone: true, selector: "loading-modal", ngImport: i0, template: "<app-modal [disableClose]=\"true\" [isOpen]=\"isOpen\" (closeModal)=\"closeModal()\">\n <div class=\"flex flex-col gap-4 py-6 w-full\">\n <div role=\"status\">\n <div class=\"flex items-center justify-center\">\n <div\n class=\"h-14 w-14 animate-spin rounded-full border-8 border-solid border-red-500 border-t-transparent\"\n ></div>\n </div>\n <span class=\"sr-only\">Loading...</span>\n </div>\n\n <p class=\"font-bold text-md text-center\">{{ title() }}</p>\n </div>\n</app-modal>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AppModalComponent, selector: "app-modal", inputs: ["title", "disableClose", "isOpen", "size"], outputs: ["closeModal"] }] });
|
|
1395
|
+
}
|
|
1396
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: LoadingmModalComponent, decorators: [{
|
|
1397
|
+
type: Component,
|
|
1398
|
+
args: [{ selector: 'loading-modal', standalone: true, imports: [CommonModule, AppModalComponent], template: "<app-modal [disableClose]=\"true\" [isOpen]=\"isOpen\" (closeModal)=\"closeModal()\">\n <div class=\"flex flex-col gap-4 py-6 w-full\">\n <div role=\"status\">\n <div class=\"flex items-center justify-center\">\n <div\n class=\"h-14 w-14 animate-spin rounded-full border-8 border-solid border-red-500 border-t-transparent\"\n ></div>\n </div>\n <span class=\"sr-only\">Loading...</span>\n </div>\n\n <p class=\"font-bold text-md text-center\">{{ title() }}</p>\n </div>\n</app-modal>\n" }]
|
|
1399
|
+
}], ctorParameters: () => [{ type: LoadingModalService }] });
|
|
1400
|
+
|
|
1401
|
+
class FormInputComponent {
|
|
1402
|
+
ngControl;
|
|
1403
|
+
transloco;
|
|
1404
|
+
label = '';
|
|
1405
|
+
type = 'text';
|
|
1406
|
+
name = '';
|
|
1407
|
+
id = '';
|
|
1408
|
+
placeholder = '';
|
|
1409
|
+
required = false;
|
|
1410
|
+
readonly = false;
|
|
1411
|
+
minlength = null;
|
|
1412
|
+
min = null;
|
|
1413
|
+
step = 1;
|
|
1414
|
+
pattern = null;
|
|
1415
|
+
fieldGroupClass = '';
|
|
1416
|
+
autocomplete = true;
|
|
1417
|
+
value = '';
|
|
1418
|
+
disabled = false;
|
|
1419
|
+
onChange = () => { };
|
|
1420
|
+
onTouched = () => { };
|
|
1421
|
+
constructor(ngControl, transloco) {
|
|
1422
|
+
this.ngControl = ngControl;
|
|
1423
|
+
this.transloco = transloco;
|
|
1424
|
+
if (this.ngControl) {
|
|
1425
|
+
this.ngControl.valueAccessor = this;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
writeValue(value) {
|
|
1429
|
+
this.value = value;
|
|
1430
|
+
}
|
|
1431
|
+
registerOnChange(fn) {
|
|
1432
|
+
this.onChange = fn;
|
|
1433
|
+
}
|
|
1434
|
+
registerOnTouched(fn) {
|
|
1435
|
+
this.onTouched = fn;
|
|
1436
|
+
}
|
|
1437
|
+
setDisabledState(isDisabled) {
|
|
1438
|
+
this.disabled = isDisabled;
|
|
1439
|
+
}
|
|
1440
|
+
onInput(value) {
|
|
1441
|
+
this.value = value;
|
|
1442
|
+
this.onChange(value);
|
|
1443
|
+
this.onTouched();
|
|
1444
|
+
}
|
|
1445
|
+
get inputId() {
|
|
1446
|
+
return this.id || this.name;
|
|
1447
|
+
}
|
|
1448
|
+
get showError() {
|
|
1449
|
+
if (!this.ngControl || !this.ngControl.control)
|
|
1450
|
+
return false;
|
|
1451
|
+
const control = this.ngControl.control;
|
|
1452
|
+
const dirty = control.dirty;
|
|
1453
|
+
const touched = control.touched;
|
|
1454
|
+
return control.invalid ? dirty || touched : false;
|
|
1455
|
+
}
|
|
1456
|
+
get errorMessage() {
|
|
1457
|
+
if (!this.ngControl?.errors)
|
|
1458
|
+
return '';
|
|
1459
|
+
const errors = this.ngControl.errors;
|
|
1460
|
+
const errorKey = Object.keys(errors)[0];
|
|
1461
|
+
if (errorKey === 'minlength') {
|
|
1462
|
+
return this.transloco.translate('formErrors.minlength', {
|
|
1463
|
+
length: errors[errorKey].requiredLength,
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1466
|
+
if (errorKey === 'maxlength') {
|
|
1467
|
+
return this.transloco.translate('formErrors.maxlength', {
|
|
1468
|
+
length: errors[errorKey].requiredLength,
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
if (errorKey === 'email') {
|
|
1472
|
+
return this.transloco.translate('formErrors.email');
|
|
1473
|
+
}
|
|
1474
|
+
return this.transloco.translate(`formErrors.${errorKey}`);
|
|
1475
|
+
}
|
|
1476
|
+
get inputClasses() {
|
|
1477
|
+
return this.showError ? ERROR_INPUT_CLASSES : BASE_INPUT_CLASSES;
|
|
1478
|
+
}
|
|
1479
|
+
get fieldGroupClasses() {
|
|
1480
|
+
let baseClasses = '';
|
|
1481
|
+
if (this.fieldGroupClass) {
|
|
1482
|
+
baseClasses += ` ${this.fieldGroupClass}`;
|
|
1483
|
+
}
|
|
1484
|
+
else {
|
|
1485
|
+
baseClasses += ' w-full';
|
|
1486
|
+
}
|
|
1487
|
+
return baseClasses;
|
|
1488
|
+
}
|
|
1489
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FormInputComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1490
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: FormInputComponent, isStandalone: true, selector: "form-input", inputs: { label: "label", type: "type", name: "name", id: "id", placeholder: "placeholder", required: "required", readonly: "readonly", minlength: "minlength", min: "min", step: "step", pattern: "pattern", fieldGroupClass: "fieldGroupClass", autocomplete: "autocomplete" }, ngImport: i0, template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <input\n [type]=\"type\"\n [id]=\"inputId\"\n [name]=\"name\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [minlength]=\"minlength\"\n [pattern]=\"pattern || ''\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onInput($event)\"\n (blur)=\"onTouched()\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [class.bg-white]=\"!readonly\"\n [class.bg-gray-200]=\"readonly\"\n [class.cursor-not-allowed]=\"readonly\"\n [class]=\"inputClasses\"\n [autocomplete]=\"autocomplete\"\n [min]=\"min\"\n [step]=\"step\"\n />\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1$1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
1491
|
+
}
|
|
1492
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FormInputComponent, decorators: [{
|
|
1493
|
+
type: Component,
|
|
1494
|
+
args: [{ selector: 'form-input', standalone: true, imports: [FormsModule, CommonModule, ReactiveFormsModule], template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <input\n [type]=\"type\"\n [id]=\"inputId\"\n [name]=\"name\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [minlength]=\"minlength\"\n [pattern]=\"pattern || ''\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onInput($event)\"\n (blur)=\"onTouched()\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [class.bg-white]=\"!readonly\"\n [class.bg-gray-200]=\"readonly\"\n [class.cursor-not-allowed]=\"readonly\"\n [class]=\"inputClasses\"\n [autocomplete]=\"autocomplete\"\n [min]=\"min\"\n [step]=\"step\"\n />\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n" }]
|
|
1495
|
+
}], ctorParameters: () => [{ type: i1$1.NgControl, decorators: [{
|
|
1496
|
+
type: Self
|
|
1497
|
+
}, {
|
|
1498
|
+
type: Optional
|
|
1499
|
+
}] }, { type: i2.TranslocoService }], propDecorators: { label: [{
|
|
1500
|
+
type: Input
|
|
1501
|
+
}], type: [{
|
|
1502
|
+
type: Input
|
|
1503
|
+
}], name: [{
|
|
1504
|
+
type: Input
|
|
1505
|
+
}], id: [{
|
|
1506
|
+
type: Input
|
|
1507
|
+
}], placeholder: [{
|
|
1508
|
+
type: Input
|
|
1509
|
+
}], required: [{
|
|
1510
|
+
type: Input
|
|
1511
|
+
}], readonly: [{
|
|
1512
|
+
type: Input
|
|
1513
|
+
}], minlength: [{
|
|
1514
|
+
type: Input
|
|
1515
|
+
}], min: [{
|
|
1516
|
+
type: Input
|
|
1517
|
+
}], step: [{
|
|
1518
|
+
type: Input
|
|
1519
|
+
}], pattern: [{
|
|
1520
|
+
type: Input
|
|
1521
|
+
}], fieldGroupClass: [{
|
|
1522
|
+
type: Input
|
|
1523
|
+
}], autocomplete: [{
|
|
1524
|
+
type: Input
|
|
1525
|
+
}] } });
|
|
1526
|
+
|
|
1527
|
+
class DeleteConfirmationComponent {
|
|
1528
|
+
fb;
|
|
1529
|
+
deleteConfirmationService;
|
|
1530
|
+
transloco;
|
|
1531
|
+
deleteConfirmationForm;
|
|
1532
|
+
constructor(fb, deleteConfirmationService, transloco) {
|
|
1533
|
+
this.fb = fb;
|
|
1534
|
+
this.deleteConfirmationService = deleteConfirmationService;
|
|
1535
|
+
this.transloco = transloco;
|
|
1536
|
+
this.deleteConfirmationForm = this.fb.group({
|
|
1537
|
+
confirmationText: ['', [Validators.required]],
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1540
|
+
get title() {
|
|
1541
|
+
return this.deleteConfirmationService.modalTitle();
|
|
1542
|
+
}
|
|
1543
|
+
get resourceName() {
|
|
1544
|
+
return this.deleteConfirmationService.modalResourceName();
|
|
1545
|
+
}
|
|
1546
|
+
get confirmationText() {
|
|
1547
|
+
return this.deleteConfirmationService.modalConfirmationText();
|
|
1548
|
+
}
|
|
1549
|
+
get isOpen() {
|
|
1550
|
+
return this.deleteConfirmationService.modalIsOpen;
|
|
1551
|
+
}
|
|
1552
|
+
get isConfirmationValid() {
|
|
1553
|
+
const value = this.deleteConfirmationForm.value.confirmationText?.trim()?.toLowerCase();
|
|
1554
|
+
const confirmation = this.confirmationText?.trim()?.toLowerCase();
|
|
1555
|
+
return value == confirmation;
|
|
1556
|
+
}
|
|
1557
|
+
onCloseModal() {
|
|
1558
|
+
this.deleteConfirmationForm.reset();
|
|
1559
|
+
this.deleteConfirmationService.close();
|
|
1560
|
+
}
|
|
1561
|
+
onConfirmDelete() {
|
|
1562
|
+
const callback = this.deleteConfirmationService.getConfirmDeleteCallback();
|
|
1563
|
+
if (callback) {
|
|
1564
|
+
callback();
|
|
1565
|
+
}
|
|
1566
|
+
this.deleteConfirmationForm.reset();
|
|
1567
|
+
this.deleteConfirmationService.close();
|
|
1568
|
+
}
|
|
1569
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DeleteConfirmationComponent, deps: [{ token: i1$1.FormBuilder }, { token: DeleteConfirmationService }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1570
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: DeleteConfirmationComponent, isStandalone: true, selector: "delete-confirmation", ngImport: i0, template: "@if (isOpen()) {\n <app-modal [title]=\"title\" [isOpen]=\"isOpen\" (closeModal)=\"onCloseModal()\">\n <form\n [formGroup]=\"deleteConfirmationForm\"\n method=\"POST\"\n class=\"flex flex-col gap-4\"\n (ngSubmit)=\"onConfirmDelete()\"\n >\n <app-alert\n type=\"warning\"\n [text]=\"'deleteConfirmation.warning' | transloco\"\n size=\"sm\"\n [closeable]=\"false\"\n />\n\n <p class=\"text-xs text-gray-600\">\n {{ 'deleteConfirmation.instructions' | transloco }}\n\n <span\n class=\"inline-flex bg-gray-200 items-center px-2 py-1 gap-1 text-red-600 font-semibold text-sm rounded mt-1\"\n >\n {{ confirmationText }}\n </span>\n </p>\n\n <form-input\n name=\"confirmationText\"\n type=\"text\"\n class=\"flex-1\"\n [required]=\"true\"\n [autocomplete]=\"false\"\n formControlName=\"confirmationText\"\n [placeholder]=\"\n transloco.translate('deleteConfirmation.placeholder', { text: confirmationText })\n \"\n />\n\n <div class=\"flex space-x-3\">\n <app-button\n variant=\"terciary\"\n [text]=\"'deleteConfirmation.cancel' | transloco\"\n (click)=\"onCloseModal()\"\n size=\"sm\"\n />\n\n <app-button\n type=\"submit\"\n variant=\"primary\"\n [text]=\"'deleteConfirmation.delete' | transloco\"\n [disabled]=\"!isConfirmationValid\"\n size=\"sm\"\n />\n </div>\n </form>\n </app-modal>\n}\n", styles: [".delete-confirmation-modal{animation:fadeIn .3s ease-out}.delete-confirmation-content{animation:slideUp .3s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.confirmation-input{transition:all .2s ease}.confirmation-input:focus{box-shadow:0 0 0 3px #ef44441a}.confirmation-input.invalid{border-color:#dc2626}.confirmation-input.invalid:focus{border-color:#dc2626;box-shadow:0 0 0 3px #dc26261a}.delete-button{transition:all .2s ease}.delete-button:disabled{opacity:.5;cursor:not-allowed}.delete-button:not(:disabled):hover{transform:translateY(-1px);box-shadow:0 4px 12px #dc26264d}.warning-message{border-left:4px solid #f59e0b;background:linear-gradient(135deg,#fef3c7,#fde68a)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: AppButtonComponent, selector: "app-button", inputs: ["disabled", "loading", "type", "variant", "text", "size", "loadingText", "icon"], outputs: ["clicked"] }, { kind: "component", type: FormInputComponent, selector: "form-input", inputs: ["label", "type", "name", "id", "placeholder", "required", "readonly", "minlength", "min", "step", "pattern", "fieldGroupClass", "autocomplete"] }, { kind: "component", type: AppModalComponent, selector: "app-modal", inputs: ["title", "disableClose", "isOpen", "size"], outputs: ["closeModal"] }, { kind: "component", type: AppAlertComponent, selector: "app-alert", inputs: ["type", "text", "closeable", "size"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], encapsulation: i0.ViewEncapsulation.None });
|
|
1571
|
+
}
|
|
1572
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DeleteConfirmationComponent, decorators: [{
|
|
1573
|
+
type: Component,
|
|
1574
|
+
args: [{ selector: 'delete-confirmation', standalone: true, imports: [
|
|
1575
|
+
CommonModule,
|
|
1576
|
+
ReactiveFormsModule,
|
|
1577
|
+
TranslocoModule,
|
|
1578
|
+
AppButtonComponent,
|
|
1579
|
+
FormInputComponent,
|
|
1580
|
+
AppModalComponent,
|
|
1581
|
+
AppAlertComponent,
|
|
1582
|
+
], encapsulation: ViewEncapsulation.None, template: "@if (isOpen()) {\n <app-modal [title]=\"title\" [isOpen]=\"isOpen\" (closeModal)=\"onCloseModal()\">\n <form\n [formGroup]=\"deleteConfirmationForm\"\n method=\"POST\"\n class=\"flex flex-col gap-4\"\n (ngSubmit)=\"onConfirmDelete()\"\n >\n <app-alert\n type=\"warning\"\n [text]=\"'deleteConfirmation.warning' | transloco\"\n size=\"sm\"\n [closeable]=\"false\"\n />\n\n <p class=\"text-xs text-gray-600\">\n {{ 'deleteConfirmation.instructions' | transloco }}\n\n <span\n class=\"inline-flex bg-gray-200 items-center px-2 py-1 gap-1 text-red-600 font-semibold text-sm rounded mt-1\"\n >\n {{ confirmationText }}\n </span>\n </p>\n\n <form-input\n name=\"confirmationText\"\n type=\"text\"\n class=\"flex-1\"\n [required]=\"true\"\n [autocomplete]=\"false\"\n formControlName=\"confirmationText\"\n [placeholder]=\"\n transloco.translate('deleteConfirmation.placeholder', { text: confirmationText })\n \"\n />\n\n <div class=\"flex space-x-3\">\n <app-button\n variant=\"terciary\"\n [text]=\"'deleteConfirmation.cancel' | transloco\"\n (click)=\"onCloseModal()\"\n size=\"sm\"\n />\n\n <app-button\n type=\"submit\"\n variant=\"primary\"\n [text]=\"'deleteConfirmation.delete' | transloco\"\n [disabled]=\"!isConfirmationValid\"\n size=\"sm\"\n />\n </div>\n </form>\n </app-modal>\n}\n", styles: [".delete-confirmation-modal{animation:fadeIn .3s ease-out}.delete-confirmation-content{animation:slideUp .3s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.confirmation-input{transition:all .2s ease}.confirmation-input:focus{box-shadow:0 0 0 3px #ef44441a}.confirmation-input.invalid{border-color:#dc2626}.confirmation-input.invalid:focus{border-color:#dc2626;box-shadow:0 0 0 3px #dc26261a}.delete-button{transition:all .2s ease}.delete-button:disabled{opacity:.5;cursor:not-allowed}.delete-button:not(:disabled):hover{transform:translateY(-1px);box-shadow:0 4px 12px #dc26264d}.warning-message{border-left:4px solid #f59e0b;background:linear-gradient(135deg,#fef3c7,#fde68a)}\n"] }]
|
|
1583
|
+
}], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: DeleteConfirmationService }, { type: i2.TranslocoService }] });
|
|
1584
|
+
|
|
1585
|
+
class AuditInformationComponent {
|
|
1586
|
+
data = null;
|
|
1587
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AuditInformationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1588
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AuditInformationComponent, isStandalone: true, selector: "app-audit-information", inputs: { data: "data" }, ngImport: i0, template: "@if (data) {\n <div class=\"w-full bg-white rounded-lg shadow-lg overflow-hidden\">\n <div class=\"border-b border-gray-200 last:border-b-0\">\n <div class=\"flex items-center justify-between p-4 bg-gray-50 border-b border-gray-200\">\n <p class=\"text-sm font-semibold\">Informaci\u00F3n de auditoria</p>\n </div>\n\n <div class=\"p-4 w-full\">\n <ul class=\"flex flex-col gap-4 list-none p-0 m-0 w-full text-xs\">\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Fecha de creaci\u00F3n:</span>\n <span>{{ data.created_at | date: 'medium' }}</span>\n </li>\n\n @if (data.created_by_admin) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Creado por:</span>\n <span>\n {{ data.created_by_admin.first_name }} - {{ data.created_by_admin.email }}\n </span>\n </li>\n }\n\n @if (data.updated_at) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">\u00DAltima actualizaci\u00F3n:</span>\n <span>{{ data.updated_at | date: 'medium' }}</span>\n </li>\n }\n\n @if (data.updated_by_admin) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Actualizado por:</span>\n <span>\n {{ data.updated_by_admin.first_name }} - {{ data.updated_by_admin.email }}\n </span>\n </li>\n }\n\n @if (data.is_published && data.published_at) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Fecha de publicaci\u00F3n:</span>\n <span>{{ data.published_at | date: 'medium' }}</span>\n </li>\n }\n\n @if (data.is_published && data.published_by_admin) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Publicado por:</span>\n <span>\n {{ data.published_by_admin.first_name }} - {{ data.published_by_admin.email }}\n </span>\n </li>\n }\n </ul>\n </div>\n </div>\n </div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1$2.DatePipe, name: "date" }] });
|
|
1589
|
+
}
|
|
1590
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AuditInformationComponent, decorators: [{
|
|
1591
|
+
type: Component,
|
|
1592
|
+
args: [{ selector: 'app-audit-information', standalone: true, imports: [CommonModule, DatePipe], template: "@if (data) {\n <div class=\"w-full bg-white rounded-lg shadow-lg overflow-hidden\">\n <div class=\"border-b border-gray-200 last:border-b-0\">\n <div class=\"flex items-center justify-between p-4 bg-gray-50 border-b border-gray-200\">\n <p class=\"text-sm font-semibold\">Informaci\u00F3n de auditoria</p>\n </div>\n\n <div class=\"p-4 w-full\">\n <ul class=\"flex flex-col gap-4 list-none p-0 m-0 w-full text-xs\">\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Fecha de creaci\u00F3n:</span>\n <span>{{ data.created_at | date: 'medium' }}</span>\n </li>\n\n @if (data.created_by_admin) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Creado por:</span>\n <span>\n {{ data.created_by_admin.first_name }} - {{ data.created_by_admin.email }}\n </span>\n </li>\n }\n\n @if (data.updated_at) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">\u00DAltima actualizaci\u00F3n:</span>\n <span>{{ data.updated_at | date: 'medium' }}</span>\n </li>\n }\n\n @if (data.updated_by_admin) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Actualizado por:</span>\n <span>\n {{ data.updated_by_admin.first_name }} - {{ data.updated_by_admin.email }}\n </span>\n </li>\n }\n\n @if (data.is_published && data.published_at) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Fecha de publicaci\u00F3n:</span>\n <span>{{ data.published_at | date: 'medium' }}</span>\n </li>\n }\n\n @if (data.is_published && data.published_by_admin) {\n <li class=\"flex flex-col items-start\">\n <span class=\"font-bold\">Publicado por:</span>\n <span>\n {{ data.published_by_admin.first_name }} - {{ data.published_by_admin.email }}\n </span>\n </li>\n }\n </ul>\n </div>\n </div>\n </div>\n}\n" }]
|
|
1593
|
+
}], propDecorators: { data: [{
|
|
1594
|
+
type: Input
|
|
1595
|
+
}] } });
|
|
1596
|
+
|
|
1597
|
+
class DynamicTableComponent {
|
|
1598
|
+
injector;
|
|
1599
|
+
constructor(injector) {
|
|
1600
|
+
this.injector = injector;
|
|
1601
|
+
}
|
|
1602
|
+
title = '';
|
|
1603
|
+
data = [];
|
|
1604
|
+
headers = [];
|
|
1605
|
+
columnComponents = {};
|
|
1606
|
+
// Inputs necesarios para la paginación remota
|
|
1607
|
+
isLoading = true;
|
|
1608
|
+
totalItems = 0;
|
|
1609
|
+
itemsPerPage = 10;
|
|
1610
|
+
currentPage = 1;
|
|
1611
|
+
// Eventos para avisar al Backend
|
|
1612
|
+
pageChange = new EventEmitter();
|
|
1613
|
+
searchChange = new EventEmitter();
|
|
1614
|
+
// Visualización de paginación
|
|
1615
|
+
showPagination = true;
|
|
1616
|
+
// Visualización de búsqueda
|
|
1617
|
+
showSearch = true;
|
|
1618
|
+
// Visualización de título
|
|
1619
|
+
showTitle = true;
|
|
1620
|
+
get totalPages() {
|
|
1621
|
+
return Math.ceil(this.totalItems / this.itemsPerPage) || 1;
|
|
1622
|
+
}
|
|
1623
|
+
onSearch(event) {
|
|
1624
|
+
this.data = [];
|
|
1625
|
+
const value = event.target.value;
|
|
1626
|
+
this.searchChange.emit(value); // El padre recibe el término y hace el fetch
|
|
1627
|
+
}
|
|
1628
|
+
changePage(delta) {
|
|
1629
|
+
const newPage = this.currentPage + delta;
|
|
1630
|
+
if (newPage > 0 && newPage <= this.totalPages) {
|
|
1631
|
+
this.pageChange.emit(newPage); // El padre recibe la nueva página
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
createInjector(row) {
|
|
1635
|
+
return Injector.create({
|
|
1636
|
+
providers: [{ provide: 'ROW_DATA', useValue: row }],
|
|
1637
|
+
parent: this.injector,
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DynamicTableComponent, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
|
|
1641
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: DynamicTableComponent, isStandalone: true, selector: "dynamic-table", inputs: { title: "title", data: "data", headers: "headers", columnComponents: "columnComponents", isLoading: "isLoading", totalItems: "totalItems", itemsPerPage: "itemsPerPage", currentPage: "currentPage", showPagination: "showPagination", showSearch: "showSearch", showTitle: "showTitle" }, outputs: { pageChange: "pageChange", searchChange: "searchChange" }, ngImport: i0, template: "<div\n class=\"bg-white rounded-lg overflow-hidden border border-gray-200 dark:bg-gray-800 dark:border-gray-700\"\n>\n @if (showTitle || showSearch) {\n <div class=\"p-4 border-b border-gray-200 flex items-center justify-start dark:border-gray-700\">\n @if (showTitle) {\n <h2 class=\"text-lg font-semibold dark:text-white\">{{ title }}</h2>\n }\n\n @if (showSearch) {\n <input\n type=\"text\"\n (input)=\"onSearch($event)\"\n placeholder=\"Buscar...\"\n class=\"ml-auto block w-sm rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:placeholder:text-gray-500 dark:focus:outline-indigo-500\"\n />\n }\n </div>\n }\n\n <div class=\"overflow-x-auto\">\n <table class=\"w-full text-left border-collapse\">\n <thead class=\"bg-gray-100 text-gray-600 text-xs dark:bg-gray-700 dark:text-gray-300\">\n <tr>\n @for (header of headers; track header.key) {\n <th class=\"p-3 border-b border-gray-300 whitespace-nowrap dark:border-gray-600\">\n {{ header.label }}\n </th>\n }\n </tr>\n </thead>\n\n <tbody class=\"text-gray-700 text-xs dark:text-gray-200\">\n @if (isLoading) {\n <tr\n class=\"border-b even:bg-gray-100 border-gray-200 last:border-none transition-colors dark:even:bg-gray-700/50 dark:border-gray-700\"\n >\n @for (header of headers; track header.key) {\n <td class=\"p-3\">\n <div class=\"h-5 bg-gray-200 rounded animate-pulse w-full dark:bg-gray-600\"></div>\n </td>\n }\n </tr>\n }\n\n @for (row of data; track row) {\n <tr\n class=\"hover:bg-gray-200 border-b even:bg-gray-100 border-gray-200 last:border-none transition-colors dark:hover:bg-gray-700 dark:even:bg-gray-700/50 dark:border-gray-700\"\n >\n @for (header of headers; track header.key) {\n <td class=\"p-3 whitespace-nowrap\">\n @if (columnComponents[header.key]) {\n <ng-container\n *ngComponentOutlet=\"columnComponents[header.key]; injector: createInjector(row)\"\n ></ng-container>\n } @else {\n {{ row[header.key] || '---' }}\n }\n </td>\n }\n </tr>\n }\n\n @if ((!data || data.length < 1) && !isLoading) {\n <tr>\n <td\n [attr.colspan]=\"headers.length\"\n class=\"p-6 text-center text-gray-400 italic dark:text-gray-500\"\n >\n No se encontraron registros en el servidor.\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n @if (showPagination) {\n <div\n class=\"p-4 flex items-center justify-between bg-gray-50 border-gray-300 border-t dark:bg-gray-800/50 dark:border-gray-700\"\n >\n <div class=\"text-sm text-gray-500 dark:text-gray-400\">\n Mostrando p\u00E1gina\n <span class=\"font-semibold text-gray-800 dark:text-white\">{{ currentPage }}</span> de\n <span class=\"font-semibold text-gray-800 dark:text-white\">{{ totalPages }}</span>\n <span class=\"ml-1\">({{ totalItems }} registros totales)</span>\n </div>\n\n <div class=\"flex gap-2\">\n <button\n (click)=\"changePage(-1)\"\n [disabled]=\"currentPage === 1\"\n class=\"flex items-center px-4 py-2 border rounded-lg bg-white text-sm font-medium hover:bg-gray-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 dark:text-white\"\n >\n Anterior\n </button>\n <button\n (click)=\"changePage(1)\"\n [disabled]=\"currentPage >= totalPages\"\n class=\"flex items-center px-4 py-2 border rounded-lg bg-white text-sm font-medium hover:bg-gray-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 dark:text-white\"\n >\n Siguiente\n </button>\n </div>\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }] });
|
|
1642
|
+
}
|
|
1643
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DynamicTableComponent, decorators: [{
|
|
1644
|
+
type: Component,
|
|
1645
|
+
args: [{ selector: 'dynamic-table', standalone: true, imports: [CommonModule], template: "<div\n class=\"bg-white rounded-lg overflow-hidden border border-gray-200 dark:bg-gray-800 dark:border-gray-700\"\n>\n @if (showTitle || showSearch) {\n <div class=\"p-4 border-b border-gray-200 flex items-center justify-start dark:border-gray-700\">\n @if (showTitle) {\n <h2 class=\"text-lg font-semibold dark:text-white\">{{ title }}</h2>\n }\n\n @if (showSearch) {\n <input\n type=\"text\"\n (input)=\"onSearch($event)\"\n placeholder=\"Buscar...\"\n class=\"ml-auto block w-sm rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:placeholder:text-gray-500 dark:focus:outline-indigo-500\"\n />\n }\n </div>\n }\n\n <div class=\"overflow-x-auto\">\n <table class=\"w-full text-left border-collapse\">\n <thead class=\"bg-gray-100 text-gray-600 text-xs dark:bg-gray-700 dark:text-gray-300\">\n <tr>\n @for (header of headers; track header.key) {\n <th class=\"p-3 border-b border-gray-300 whitespace-nowrap dark:border-gray-600\">\n {{ header.label }}\n </th>\n }\n </tr>\n </thead>\n\n <tbody class=\"text-gray-700 text-xs dark:text-gray-200\">\n @if (isLoading) {\n <tr\n class=\"border-b even:bg-gray-100 border-gray-200 last:border-none transition-colors dark:even:bg-gray-700/50 dark:border-gray-700\"\n >\n @for (header of headers; track header.key) {\n <td class=\"p-3\">\n <div class=\"h-5 bg-gray-200 rounded animate-pulse w-full dark:bg-gray-600\"></div>\n </td>\n }\n </tr>\n }\n\n @for (row of data; track row) {\n <tr\n class=\"hover:bg-gray-200 border-b even:bg-gray-100 border-gray-200 last:border-none transition-colors dark:hover:bg-gray-700 dark:even:bg-gray-700/50 dark:border-gray-700\"\n >\n @for (header of headers; track header.key) {\n <td class=\"p-3 whitespace-nowrap\">\n @if (columnComponents[header.key]) {\n <ng-container\n *ngComponentOutlet=\"columnComponents[header.key]; injector: createInjector(row)\"\n ></ng-container>\n } @else {\n {{ row[header.key] || '---' }}\n }\n </td>\n }\n </tr>\n }\n\n @if ((!data || data.length < 1) && !isLoading) {\n <tr>\n <td\n [attr.colspan]=\"headers.length\"\n class=\"p-6 text-center text-gray-400 italic dark:text-gray-500\"\n >\n No se encontraron registros en el servidor.\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n @if (showPagination) {\n <div\n class=\"p-4 flex items-center justify-between bg-gray-50 border-gray-300 border-t dark:bg-gray-800/50 dark:border-gray-700\"\n >\n <div class=\"text-sm text-gray-500 dark:text-gray-400\">\n Mostrando p\u00E1gina\n <span class=\"font-semibold text-gray-800 dark:text-white\">{{ currentPage }}</span> de\n <span class=\"font-semibold text-gray-800 dark:text-white\">{{ totalPages }}</span>\n <span class=\"ml-1\">({{ totalItems }} registros totales)</span>\n </div>\n\n <div class=\"flex gap-2\">\n <button\n (click)=\"changePage(-1)\"\n [disabled]=\"currentPage === 1\"\n class=\"flex items-center px-4 py-2 border rounded-lg bg-white text-sm font-medium hover:bg-gray-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 dark:text-white\"\n >\n Anterior\n </button>\n <button\n (click)=\"changePage(1)\"\n [disabled]=\"currentPage >= totalPages\"\n class=\"flex items-center px-4 py-2 border rounded-lg bg-white text-sm font-medium hover:bg-gray-100 disabled:opacity-40 disabled:cursor-not-allowed transition-all dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 dark:text-white\"\n >\n Siguiente\n </button>\n </div>\n </div>\n }\n</div>\n" }]
|
|
1646
|
+
}], ctorParameters: () => [{ type: i0.Injector }], propDecorators: { title: [{
|
|
1647
|
+
type: Input
|
|
1648
|
+
}], data: [{
|
|
1649
|
+
type: Input
|
|
1650
|
+
}], headers: [{
|
|
1651
|
+
type: Input
|
|
1652
|
+
}], columnComponents: [{
|
|
1653
|
+
type: Input
|
|
1654
|
+
}], isLoading: [{
|
|
1655
|
+
type: Input
|
|
1656
|
+
}], totalItems: [{
|
|
1657
|
+
type: Input
|
|
1658
|
+
}], itemsPerPage: [{
|
|
1659
|
+
type: Input
|
|
1660
|
+
}], currentPage: [{
|
|
1661
|
+
type: Input
|
|
1662
|
+
}], pageChange: [{
|
|
1663
|
+
type: Output
|
|
1664
|
+
}], searchChange: [{
|
|
1665
|
+
type: Output
|
|
1666
|
+
}], showPagination: [{
|
|
1667
|
+
type: Input
|
|
1668
|
+
}], showSearch: [{
|
|
1669
|
+
type: Input
|
|
1670
|
+
}], showTitle: [{
|
|
1671
|
+
type: Input
|
|
1672
|
+
}] } });
|
|
1673
|
+
|
|
1674
|
+
class LanguageSwitcherComponent {
|
|
1675
|
+
transloco;
|
|
1676
|
+
availableLangs = ['es', 'en'];
|
|
1677
|
+
constructor(transloco) {
|
|
1678
|
+
this.transloco = transloco;
|
|
1679
|
+
}
|
|
1680
|
+
get activeLang() {
|
|
1681
|
+
return this.transloco.getActiveLang();
|
|
1682
|
+
}
|
|
1683
|
+
switchLang(lang) {
|
|
1684
|
+
this.transloco.setActiveLang(lang);
|
|
1685
|
+
}
|
|
1686
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: LanguageSwitcherComponent, deps: [{ token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1687
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: LanguageSwitcherComponent, isStandalone: true, selector: "language-switcher", ngImport: i0, template: `
|
|
1688
|
+
<div class="flex items-center gap-1">
|
|
1689
|
+
@for (lang of availableLangs; track lang) {
|
|
1690
|
+
<button
|
|
1691
|
+
(click)="switchLang(lang)"
|
|
1692
|
+
class="cursor-pointer px-2 py-1 text-xs font-medium rounded transition-colors"
|
|
1693
|
+
[class.bg-gray-800]="activeLang === lang"
|
|
1694
|
+
[class.text-white]="activeLang === lang"
|
|
1695
|
+
[class.text-gray-400]="activeLang !== lang"
|
|
1696
|
+
[class.hover:text-white]="activeLang !== lang"
|
|
1697
|
+
>
|
|
1698
|
+
{{ lang | uppercase }}
|
|
1699
|
+
</button>
|
|
1700
|
+
}
|
|
1701
|
+
</div>
|
|
1702
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i1$2.UpperCasePipe, name: "uppercase" }] });
|
|
1703
|
+
}
|
|
1704
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: LanguageSwitcherComponent, decorators: [{
|
|
1705
|
+
type: Component,
|
|
1706
|
+
args: [{
|
|
1707
|
+
selector: 'language-switcher',
|
|
1708
|
+
standalone: true,
|
|
1709
|
+
imports: [CommonModule, TranslocoModule],
|
|
1710
|
+
template: `
|
|
1711
|
+
<div class="flex items-center gap-1">
|
|
1712
|
+
@for (lang of availableLangs; track lang) {
|
|
1713
|
+
<button
|
|
1714
|
+
(click)="switchLang(lang)"
|
|
1715
|
+
class="cursor-pointer px-2 py-1 text-xs font-medium rounded transition-colors"
|
|
1716
|
+
[class.bg-gray-800]="activeLang === lang"
|
|
1717
|
+
[class.text-white]="activeLang === lang"
|
|
1718
|
+
[class.text-gray-400]="activeLang !== lang"
|
|
1719
|
+
[class.hover:text-white]="activeLang !== lang"
|
|
1720
|
+
>
|
|
1721
|
+
{{ lang | uppercase }}
|
|
1722
|
+
</button>
|
|
1723
|
+
}
|
|
1724
|
+
</div>
|
|
1725
|
+
`,
|
|
1726
|
+
}]
|
|
1727
|
+
}], ctorParameters: () => [{ type: i2.TranslocoService }] });
|
|
1728
|
+
|
|
1729
|
+
class FormSelectComponent {
|
|
1730
|
+
ngControl;
|
|
1731
|
+
transloco;
|
|
1732
|
+
label = '';
|
|
1733
|
+
name = '';
|
|
1734
|
+
id = '';
|
|
1735
|
+
placeholder = 'Seleccione una opción';
|
|
1736
|
+
required = false;
|
|
1737
|
+
disabled = false;
|
|
1738
|
+
readonly = false;
|
|
1739
|
+
options = [];
|
|
1740
|
+
fieldGroupClass = '';
|
|
1741
|
+
showDefaultOption = true;
|
|
1742
|
+
defaultOptionLabel = '';
|
|
1743
|
+
value = '';
|
|
1744
|
+
onChange = () => { };
|
|
1745
|
+
onTouched = () => { };
|
|
1746
|
+
constructor(ngControl, transloco) {
|
|
1747
|
+
this.ngControl = ngControl;
|
|
1748
|
+
this.transloco = transloco;
|
|
1749
|
+
if (this.ngControl) {
|
|
1750
|
+
this.ngControl.valueAccessor = this;
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
writeValue(value) {
|
|
1754
|
+
this.value = value;
|
|
1755
|
+
}
|
|
1756
|
+
registerOnChange(fn) {
|
|
1757
|
+
this.onChange = fn;
|
|
1758
|
+
}
|
|
1759
|
+
registerOnTouched(fn) {
|
|
1760
|
+
this.onTouched = fn;
|
|
1761
|
+
}
|
|
1762
|
+
setDisabledState(isDisabled) {
|
|
1763
|
+
this.disabled = isDisabled;
|
|
1764
|
+
}
|
|
1765
|
+
onSelectChange(value) {
|
|
1766
|
+
this.value = value;
|
|
1767
|
+
this.onChange(value);
|
|
1768
|
+
this.onTouched();
|
|
1769
|
+
}
|
|
1770
|
+
get inputId() {
|
|
1771
|
+
return this.id || this.name;
|
|
1772
|
+
}
|
|
1773
|
+
get showError() {
|
|
1774
|
+
if (!this.ngControl || !this.ngControl.control)
|
|
1775
|
+
return false;
|
|
1776
|
+
const control = this.ngControl.control;
|
|
1777
|
+
const dirty = control.dirty;
|
|
1778
|
+
const touched = control.touched;
|
|
1779
|
+
return control.invalid ? dirty || touched : false;
|
|
1780
|
+
}
|
|
1781
|
+
get errorMessage() {
|
|
1782
|
+
if (!this.ngControl?.errors)
|
|
1783
|
+
return '';
|
|
1784
|
+
const errors = this.ngControl.errors;
|
|
1785
|
+
const errorKey = Object.keys(errors)[0];
|
|
1786
|
+
return this.transloco.translate(`formErrors.${errorKey}`, {}, this.transloco.translate('formErrors.invalidSelection'));
|
|
1787
|
+
}
|
|
1788
|
+
get resolvedDefaultOptionLabel() {
|
|
1789
|
+
return this.defaultOptionLabel || this.transloco.translate('common.selectOption');
|
|
1790
|
+
}
|
|
1791
|
+
get selectClasses() {
|
|
1792
|
+
return this.showError ? ERROR_INPUT_CLASSES : BASE_INPUT_CLASSES;
|
|
1793
|
+
}
|
|
1794
|
+
get fieldGroupClasses() {
|
|
1795
|
+
let baseClasses = '';
|
|
1796
|
+
if (this.fieldGroupClass) {
|
|
1797
|
+
baseClasses += ` ${this.fieldGroupClass}`;
|
|
1798
|
+
}
|
|
1799
|
+
else {
|
|
1800
|
+
baseClasses += ' w-full';
|
|
1801
|
+
}
|
|
1802
|
+
return baseClasses;
|
|
1803
|
+
}
|
|
1804
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FormSelectComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1805
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: FormSelectComponent, isStandalone: true, selector: "form-select", inputs: { label: "label", name: "name", id: "id", placeholder: "placeholder", required: "required", disabled: "disabled", readonly: "readonly", options: "options", fieldGroupClass: "fieldGroupClass", showDefaultOption: "showDefaultOption", defaultOptionLabel: "defaultOptionLabel" }, ngImport: i0, template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <select\n [id]=\"inputId\"\n [name]=\"name\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onSelectChange($event)\"\n (blur)=\"onTouched()\"\n [class]=\"selectClasses\"\n [class.bg-white]=\"!readonly\"\n [class.bg-gray-200]=\"readonly\"\n [class.cursor-not-allowed]=\"readonly\"\n >\n @if (showDefaultOption) {\n <option [value]=\"null\" disabled selected>{{ resolvedDefaultOptionLabel }}</option>\n }\n\n @for (option of options; track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled\">\n {{ option.label }}\n </option>\n }\n </select>\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n", styles: ["select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url(\"data:image/svg+xml;charset=US-ASCII,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right .75rem center;background-size:1em;padding-right:2.5rem}select::-ms-expand{display:none}@-moz-document url-prefix(){select{text-indent:.01px;text-overflow:\"\";padding-right:.75rem}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
1806
|
+
}
|
|
1807
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FormSelectComponent, decorators: [{
|
|
1808
|
+
type: Component,
|
|
1809
|
+
args: [{ selector: 'form-select', standalone: true, imports: [FormsModule, CommonModule, ReactiveFormsModule], template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <select\n [id]=\"inputId\"\n [name]=\"name\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onSelectChange($event)\"\n (blur)=\"onTouched()\"\n [class]=\"selectClasses\"\n [class.bg-white]=\"!readonly\"\n [class.bg-gray-200]=\"readonly\"\n [class.cursor-not-allowed]=\"readonly\"\n >\n @if (showDefaultOption) {\n <option [value]=\"null\" disabled selected>{{ resolvedDefaultOptionLabel }}</option>\n }\n\n @for (option of options; track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled\">\n {{ option.label }}\n </option>\n }\n </select>\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n", styles: ["select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url(\"data:image/svg+xml;charset=US-ASCII,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right .75rem center;background-size:1em;padding-right:2.5rem}select::-ms-expand{display:none}@-moz-document url-prefix(){select{text-indent:.01px;text-overflow:\"\";padding-right:.75rem}}\n"] }]
|
|
1810
|
+
}], ctorParameters: () => [{ type: i1$1.NgControl, decorators: [{
|
|
1811
|
+
type: Self
|
|
1812
|
+
}, {
|
|
1813
|
+
type: Optional
|
|
1814
|
+
}] }, { type: i2.TranslocoService }], propDecorators: { label: [{
|
|
1815
|
+
type: Input
|
|
1816
|
+
}], name: [{
|
|
1817
|
+
type: Input
|
|
1818
|
+
}], id: [{
|
|
1819
|
+
type: Input
|
|
1820
|
+
}], placeholder: [{
|
|
1821
|
+
type: Input
|
|
1822
|
+
}], required: [{
|
|
1823
|
+
type: Input
|
|
1824
|
+
}], disabled: [{
|
|
1825
|
+
type: Input
|
|
1826
|
+
}], readonly: [{
|
|
1827
|
+
type: Input
|
|
1828
|
+
}], options: [{
|
|
1829
|
+
type: Input
|
|
1830
|
+
}], fieldGroupClass: [{
|
|
1831
|
+
type: Input
|
|
1832
|
+
}], showDefaultOption: [{
|
|
1833
|
+
type: Input
|
|
1834
|
+
}], defaultOptionLabel: [{
|
|
1835
|
+
type: Input
|
|
1836
|
+
}] } });
|
|
1837
|
+
|
|
1838
|
+
class FormTextareaComponent {
|
|
1839
|
+
ngControl;
|
|
1840
|
+
transloco;
|
|
1841
|
+
label = '';
|
|
1842
|
+
name = '';
|
|
1843
|
+
id = '';
|
|
1844
|
+
placeholder = '';
|
|
1845
|
+
required = false;
|
|
1846
|
+
readonly = false;
|
|
1847
|
+
minlength = null;
|
|
1848
|
+
maxlength = null;
|
|
1849
|
+
rows = 4;
|
|
1850
|
+
cols = null;
|
|
1851
|
+
fieldGroupClass = '';
|
|
1852
|
+
value = '';
|
|
1853
|
+
disabled = false;
|
|
1854
|
+
onChange = () => { };
|
|
1855
|
+
onTouched = () => { };
|
|
1856
|
+
constructor(ngControl, transloco) {
|
|
1857
|
+
this.ngControl = ngControl;
|
|
1858
|
+
this.transloco = transloco;
|
|
1859
|
+
if (this.ngControl) {
|
|
1860
|
+
this.ngControl.valueAccessor = this;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
writeValue(value) {
|
|
1864
|
+
this.value = value;
|
|
1865
|
+
}
|
|
1866
|
+
registerOnChange(fn) {
|
|
1867
|
+
this.onChange = fn;
|
|
1868
|
+
}
|
|
1869
|
+
registerOnTouched(fn) {
|
|
1870
|
+
this.onTouched = fn;
|
|
1871
|
+
}
|
|
1872
|
+
setDisabledState(isDisabled) {
|
|
1873
|
+
this.disabled = isDisabled;
|
|
1874
|
+
}
|
|
1875
|
+
onInput(value) {
|
|
1876
|
+
this.value = value;
|
|
1877
|
+
this.onChange(value);
|
|
1878
|
+
this.onTouched();
|
|
1879
|
+
}
|
|
1880
|
+
get inputId() {
|
|
1881
|
+
return this.id || this.name;
|
|
1882
|
+
}
|
|
1883
|
+
get showError() {
|
|
1884
|
+
if (!this.ngControl || !this.ngControl.control)
|
|
1885
|
+
return false;
|
|
1886
|
+
const control = this.ngControl.control;
|
|
1887
|
+
const dirty = control.dirty;
|
|
1888
|
+
const touched = control.touched;
|
|
1889
|
+
return control.invalid ? dirty || touched : false;
|
|
1890
|
+
}
|
|
1891
|
+
get errorMessage() {
|
|
1892
|
+
if (!this.ngControl?.errors)
|
|
1893
|
+
return '';
|
|
1894
|
+
const errors = this.ngControl.errors;
|
|
1895
|
+
const errorKey = Object.keys(errors)[0];
|
|
1896
|
+
if (errorKey === 'minlength') {
|
|
1897
|
+
return this.transloco.translate('formErrors.minlength', {
|
|
1898
|
+
length: errors[errorKey].requiredLength,
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
if (errorKey === 'maxlength') {
|
|
1902
|
+
return this.transloco.translate('formErrors.maxlength', {
|
|
1903
|
+
length: errors[errorKey].requiredLength,
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1906
|
+
return this.transloco.translate(`formErrors.${errorKey}`);
|
|
1907
|
+
}
|
|
1908
|
+
get inputClasses() {
|
|
1909
|
+
return this.showError ? ERROR_INPUT_CLASSES : BASE_INPUT_CLASSES;
|
|
1910
|
+
}
|
|
1911
|
+
get fieldGroupClasses() {
|
|
1912
|
+
let baseClasses = '';
|
|
1913
|
+
if (this.fieldGroupClass) {
|
|
1914
|
+
baseClasses += ` ${this.fieldGroupClass}`;
|
|
1915
|
+
}
|
|
1916
|
+
else {
|
|
1917
|
+
baseClasses += ' w-full';
|
|
1918
|
+
}
|
|
1919
|
+
return baseClasses;
|
|
1920
|
+
}
|
|
1921
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FormTextareaComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1922
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: FormTextareaComponent, isStandalone: true, selector: "form-textarea", inputs: { label: "label", name: "name", id: "id", placeholder: "placeholder", required: "required", readonly: "readonly", minlength: "minlength", maxlength: "maxlength", rows: "rows", cols: "cols", fieldGroupClass: "fieldGroupClass" }, ngImport: i0, template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <textarea\n [id]=\"inputId\"\n [name]=\"name\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [minlength]=\"minlength\"\n [maxlength]=\"maxlength\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onInput($event)\"\n (blur)=\"onTouched()\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [class.bg-white]=\"!readonly\"\n [class.bg-gray-200]=\"readonly\"\n [class.cursor-not-allowed]=\"readonly\"\n [class]=\"inputClasses\"\n ></textarea>\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
1923
|
+
}
|
|
1924
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FormTextareaComponent, decorators: [{
|
|
1925
|
+
type: Component,
|
|
1926
|
+
args: [{ selector: 'form-textarea', standalone: true, imports: [FormsModule, CommonModule, ReactiveFormsModule], template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <textarea\n [id]=\"inputId\"\n [name]=\"name\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [minlength]=\"minlength\"\n [maxlength]=\"maxlength\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onInput($event)\"\n (blur)=\"onTouched()\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [class.bg-white]=\"!readonly\"\n [class.bg-gray-200]=\"readonly\"\n [class.cursor-not-allowed]=\"readonly\"\n [class]=\"inputClasses\"\n ></textarea>\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n" }]
|
|
1927
|
+
}], ctorParameters: () => [{ type: i1$1.NgControl, decorators: [{
|
|
1928
|
+
type: Self
|
|
1929
|
+
}, {
|
|
1930
|
+
type: Optional
|
|
1931
|
+
}] }, { type: i2.TranslocoService }], propDecorators: { label: [{
|
|
1932
|
+
type: Input
|
|
1933
|
+
}], name: [{
|
|
1934
|
+
type: Input
|
|
1935
|
+
}], id: [{
|
|
1936
|
+
type: Input
|
|
1937
|
+
}], placeholder: [{
|
|
1938
|
+
type: Input
|
|
1939
|
+
}], required: [{
|
|
1940
|
+
type: Input
|
|
1941
|
+
}], readonly: [{
|
|
1942
|
+
type: Input
|
|
1943
|
+
}], minlength: [{
|
|
1944
|
+
type: Input
|
|
1945
|
+
}], maxlength: [{
|
|
1946
|
+
type: Input
|
|
1947
|
+
}], rows: [{
|
|
1948
|
+
type: Input
|
|
1949
|
+
}], cols: [{
|
|
1950
|
+
type: Input
|
|
1951
|
+
}], fieldGroupClass: [{
|
|
1952
|
+
type: Input
|
|
1953
|
+
}] } });
|
|
1954
|
+
|
|
1955
|
+
class FormEditorComponent {
|
|
1956
|
+
ngControl;
|
|
1957
|
+
transloco;
|
|
1958
|
+
label = '';
|
|
1959
|
+
name = '';
|
|
1960
|
+
id = '';
|
|
1961
|
+
placeholder = '';
|
|
1962
|
+
required = false;
|
|
1963
|
+
readonly = false;
|
|
1964
|
+
toolbar = DEFAULT_TOOLBAR;
|
|
1965
|
+
fieldGroupClass = '';
|
|
1966
|
+
editor;
|
|
1967
|
+
value = '';
|
|
1968
|
+
disabled = false;
|
|
1969
|
+
onChange = () => { };
|
|
1970
|
+
onTouched = () => { };
|
|
1971
|
+
subscription = null;
|
|
1972
|
+
constructor(ngControl, transloco) {
|
|
1973
|
+
this.ngControl = ngControl;
|
|
1974
|
+
this.transloco = transloco;
|
|
1975
|
+
if (this.ngControl) {
|
|
1976
|
+
this.ngControl.valueAccessor = this;
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
ngOnInit() {
|
|
1980
|
+
this.editor = new Editor();
|
|
1981
|
+
if (this.value) {
|
|
1982
|
+
this.editor.setContent(this.value);
|
|
1983
|
+
}
|
|
1984
|
+
this.subscription = this.editor.valueChanges
|
|
1985
|
+
.pipe(distinctUntilChanged())
|
|
1986
|
+
.subscribe((doc) => {
|
|
1987
|
+
this.value = toHTML(doc);
|
|
1988
|
+
this.onChange(this.value);
|
|
1989
|
+
this.onTouched();
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1992
|
+
ngOnDestroy() {
|
|
1993
|
+
this.subscription?.unsubscribe();
|
|
1994
|
+
this.editor?.destroy();
|
|
1995
|
+
}
|
|
1996
|
+
writeValue(value) {
|
|
1997
|
+
this.value = value ?? '';
|
|
1998
|
+
if (this.editor) {
|
|
1999
|
+
this.editor.setContent(value ?? null);
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
registerOnChange(fn) {
|
|
2003
|
+
this.onChange = fn;
|
|
2004
|
+
}
|
|
2005
|
+
registerOnTouched(fn) {
|
|
2006
|
+
this.onTouched = fn;
|
|
2007
|
+
}
|
|
2008
|
+
setDisabledState(isDisabled) {
|
|
2009
|
+
this.disabled = isDisabled;
|
|
2010
|
+
}
|
|
2011
|
+
get inputId() {
|
|
2012
|
+
return this.id || this.name;
|
|
2013
|
+
}
|
|
2014
|
+
get showError() {
|
|
2015
|
+
if (!this.ngControl || !this.ngControl.control)
|
|
2016
|
+
return false;
|
|
2017
|
+
const control = this.ngControl.control;
|
|
2018
|
+
return control.invalid ? control.dirty || control.touched : false;
|
|
2019
|
+
}
|
|
2020
|
+
get errorMessage() {
|
|
2021
|
+
if (!this.ngControl?.errors)
|
|
2022
|
+
return '';
|
|
2023
|
+
const errors = this.ngControl.errors;
|
|
2024
|
+
const errorKey = Object.keys(errors)[0];
|
|
2025
|
+
if (errorKey === 'minlength') {
|
|
2026
|
+
return this.transloco.translate('formErrors.minlength', {
|
|
2027
|
+
length: errors[errorKey].requiredLength,
|
|
2028
|
+
});
|
|
2029
|
+
}
|
|
2030
|
+
if (errorKey === 'maxlength') {
|
|
2031
|
+
return this.transloco.translate('formErrors.maxlength', {
|
|
2032
|
+
length: errors[errorKey].requiredLength,
|
|
2033
|
+
});
|
|
2034
|
+
}
|
|
2035
|
+
return this.transloco.translate(`formErrors.${errorKey}`, {}, this.transloco.translate('formErrors.invalidField'));
|
|
2036
|
+
}
|
|
2037
|
+
get fieldGroupClasses() {
|
|
2038
|
+
let baseClasses = '';
|
|
2039
|
+
if (this.fieldGroupClass) {
|
|
2040
|
+
baseClasses += ` ${this.fieldGroupClass}`;
|
|
2041
|
+
}
|
|
2042
|
+
else {
|
|
2043
|
+
baseClasses += ' w-full';
|
|
2044
|
+
}
|
|
2045
|
+
return baseClasses;
|
|
2046
|
+
}
|
|
2047
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FormEditorComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2048
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: FormEditorComponent, isStandalone: true, selector: "form-editor", inputs: { label: "label", name: "name", id: "id", placeholder: "placeholder", required: "required", readonly: "readonly", toolbar: "toolbar", fieldGroupClass: "fieldGroupClass" }, ngImport: i0, template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div\n class=\"relative\"\n [class.opacity-50]=\"disabled\"\n [class.pointer-events-none]=\"disabled\"\n [class.cursor-not-allowed]=\"disabled\"\n >\n <ngx-editor [editor]=\"editor\" outputFormat=\"html\" [placeholder]=\"placeholder\">\n <ngx-editor-menu\n [editor]=\"editor\"\n [toolbar]=\"toolbar\"\n [disabled]=\"disabled\"\n ></ngx-editor-menu>\n </ngx-editor>\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: NgxEditorComponent, selector: "ngx-editor", inputs: ["editor", "outputFormat", "placeholder"], outputs: ["focusOut", "focusIn"] }, { kind: "component", type: NgxEditorMenuComponent, selector: "ngx-editor-menu", inputs: ["toolbar", "colorPresets", "disabled", "editor", "customMenuRef", "dropdownPlacement"] }] });
|
|
2049
|
+
}
|
|
2050
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FormEditorComponent, decorators: [{
|
|
2051
|
+
type: Component,
|
|
2052
|
+
args: [{ selector: 'form-editor', standalone: true, imports: [
|
|
2053
|
+
FormsModule,
|
|
2054
|
+
CommonModule,
|
|
2055
|
+
ReactiveFormsModule,
|
|
2056
|
+
NgxEditorComponent,
|
|
2057
|
+
NgxEditorMenuComponent,
|
|
2058
|
+
], template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div\n class=\"relative\"\n [class.opacity-50]=\"disabled\"\n [class.pointer-events-none]=\"disabled\"\n [class.cursor-not-allowed]=\"disabled\"\n >\n <ngx-editor [editor]=\"editor\" outputFormat=\"html\" [placeholder]=\"placeholder\">\n <ngx-editor-menu\n [editor]=\"editor\"\n [toolbar]=\"toolbar\"\n [disabled]=\"disabled\"\n ></ngx-editor-menu>\n </ngx-editor>\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n" }]
|
|
2059
|
+
}], ctorParameters: () => [{ type: i1$1.NgControl, decorators: [{
|
|
2060
|
+
type: Self
|
|
2061
|
+
}, {
|
|
2062
|
+
type: Optional
|
|
2063
|
+
}] }, { type: i2.TranslocoService }], propDecorators: { label: [{
|
|
2064
|
+
type: Input
|
|
2065
|
+
}], name: [{
|
|
2066
|
+
type: Input
|
|
2067
|
+
}], id: [{
|
|
2068
|
+
type: Input
|
|
2069
|
+
}], placeholder: [{
|
|
2070
|
+
type: Input
|
|
2071
|
+
}], required: [{
|
|
2072
|
+
type: Input
|
|
2073
|
+
}], readonly: [{
|
|
2074
|
+
type: Input
|
|
2075
|
+
}], toolbar: [{
|
|
2076
|
+
type: Input
|
|
2077
|
+
}], fieldGroupClass: [{
|
|
2078
|
+
type: Input
|
|
2079
|
+
}] } });
|
|
2080
|
+
|
|
2081
|
+
class ColorPickerComponent {
|
|
2082
|
+
ngControl;
|
|
2083
|
+
elementRef;
|
|
2084
|
+
label = '';
|
|
2085
|
+
name = '';
|
|
2086
|
+
id = '';
|
|
2087
|
+
placeholder = '#000000';
|
|
2088
|
+
required = false;
|
|
2089
|
+
readonly = false;
|
|
2090
|
+
fieldGroupClass = '';
|
|
2091
|
+
showPreview = true;
|
|
2092
|
+
presetColors = [
|
|
2093
|
+
'#000000',
|
|
2094
|
+
'#FFFFFF',
|
|
2095
|
+
'#EF4444',
|
|
2096
|
+
'#F97316',
|
|
2097
|
+
'#F59E0B',
|
|
2098
|
+
'#EAB308',
|
|
2099
|
+
'#84CC16',
|
|
2100
|
+
'#22C55E',
|
|
2101
|
+
'#10B981',
|
|
2102
|
+
'#14B8A6',
|
|
2103
|
+
'#06B6D4',
|
|
2104
|
+
'#0EA5E9',
|
|
2105
|
+
'#3B82F6',
|
|
2106
|
+
'#6366F1',
|
|
2107
|
+
'#8B5CF6',
|
|
2108
|
+
'#A855F7',
|
|
2109
|
+
'#D946EF',
|
|
2110
|
+
'#EC4899',
|
|
2111
|
+
'#F43F5E',
|
|
2112
|
+
'#6B7280',
|
|
2113
|
+
];
|
|
2114
|
+
colorChange = new EventEmitter();
|
|
2115
|
+
value = '#000000';
|
|
2116
|
+
disabled = false;
|
|
2117
|
+
isDropdownOpen = false;
|
|
2118
|
+
onChange = () => { };
|
|
2119
|
+
onTouched = () => { };
|
|
2120
|
+
constructor(ngControl, elementRef) {
|
|
2121
|
+
this.ngControl = ngControl;
|
|
2122
|
+
this.elementRef = elementRef;
|
|
2123
|
+
if (this.ngControl) {
|
|
2124
|
+
this.ngControl.valueAccessor = this;
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
onDocumentClick(event) {
|
|
2128
|
+
const clickedInside = this.elementRef.nativeElement.contains(event.target);
|
|
2129
|
+
if (!clickedInside && this.isDropdownOpen) {
|
|
2130
|
+
this.isDropdownOpen = false;
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
// Control value accessor methods
|
|
2134
|
+
writeValue(value) {
|
|
2135
|
+
if (value) {
|
|
2136
|
+
this.value = value;
|
|
2137
|
+
}
|
|
2138
|
+
}
|
|
2139
|
+
registerOnChange(fn) {
|
|
2140
|
+
this.onChange = fn;
|
|
2141
|
+
}
|
|
2142
|
+
registerOnTouched(fn) {
|
|
2143
|
+
this.onTouched = fn;
|
|
2144
|
+
}
|
|
2145
|
+
setDisabledState(isDisabled) {
|
|
2146
|
+
this.disabled = isDisabled;
|
|
2147
|
+
}
|
|
2148
|
+
onColorChange(color) {
|
|
2149
|
+
this.value = color;
|
|
2150
|
+
this.onChange(color);
|
|
2151
|
+
this.onTouched();
|
|
2152
|
+
}
|
|
2153
|
+
onInputColorChange(event) {
|
|
2154
|
+
const input = event.target;
|
|
2155
|
+
this.value = input.value;
|
|
2156
|
+
this.onChange(input.value);
|
|
2157
|
+
this.onTouched();
|
|
2158
|
+
this.colorChange.emit(input.value);
|
|
2159
|
+
}
|
|
2160
|
+
toggleDropdown() {
|
|
2161
|
+
if (this.disabled || this.readonly)
|
|
2162
|
+
return;
|
|
2163
|
+
this.isDropdownOpen = !this.isDropdownOpen;
|
|
2164
|
+
}
|
|
2165
|
+
selectPresetColor(color) {
|
|
2166
|
+
this.onColorChange(color);
|
|
2167
|
+
this.colorChange.emit(color);
|
|
2168
|
+
this.isDropdownOpen = false;
|
|
2169
|
+
}
|
|
2170
|
+
get inputId() {
|
|
2171
|
+
return this.id || this.name;
|
|
2172
|
+
}
|
|
2173
|
+
get showError() {
|
|
2174
|
+
if (!this.ngControl || !this.ngControl.control)
|
|
2175
|
+
return false;
|
|
2176
|
+
const control = this.ngControl.control;
|
|
2177
|
+
const dirty = control.dirty;
|
|
2178
|
+
const touched = control.touched;
|
|
2179
|
+
return control.invalid ? dirty || touched : false;
|
|
2180
|
+
}
|
|
2181
|
+
get inputClasses() {
|
|
2182
|
+
return this.showError ? ERROR_INPUT_CLASSES : BASE_INPUT_CLASSES;
|
|
2183
|
+
}
|
|
2184
|
+
get fieldGroupClasses() {
|
|
2185
|
+
let baseClasses = '';
|
|
2186
|
+
if (this.fieldGroupClass) {
|
|
2187
|
+
baseClasses += ` ${this.fieldGroupClass}`;
|
|
2188
|
+
}
|
|
2189
|
+
else {
|
|
2190
|
+
baseClasses += ' w-full';
|
|
2191
|
+
}
|
|
2192
|
+
return baseClasses;
|
|
2193
|
+
}
|
|
2194
|
+
isValidHexColor(color) {
|
|
2195
|
+
return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
|
|
2196
|
+
}
|
|
2197
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ColorPickerComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
2198
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: ColorPickerComponent, isStandalone: true, selector: "color-picker", inputs: { label: "label", name: "name", id: "id", placeholder: "placeholder", required: "required", readonly: "readonly", fieldGroupClass: "fieldGroupClass", showPreview: "showPreview", presetColors: "presetColors" }, outputs: { colorChange: "colorChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, ngImport: i0, template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div class=\"flex gap-2 items-center\">\n <!-- Color Input -->\n <div class=\"relative flex-1\">\n <input\n type=\"text\"\n [id]=\"inputId\"\n [name]=\"name\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onInputColorChange($event)\"\n (blur)=\"onTouched()\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [class.bg-white]=\"!readonly\"\n [class.bg-gray-200]=\"readonly\"\n [class.cursor-not-allowed]=\"readonly\"\n [class]=\"inputClasses\"\n pattern=\"^#[0-9A-Fa-f]{6}$\"\n />\n\n <!-- Native Color Picker (Hidden) -->\n <input\n type=\"color\"\n class=\"absolute inset-0 opacity-0 cursor-pointer\"\n [disabled]=\"disabled || readonly\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onColorChange($event)\"\n />\n </div>\n\n <!-- Color Preview -->\n @if (showPreview) {\n <div class=\"flex items-center\">\n <div\n class=\"w-[37px] h-[37px] rounded-md border border-gray-300 cursor-pointer transition-all hover:scale-105\"\n [style.background-color]=\"value\"\n (click)=\"toggleDropdown()\"\n [class.cursor-not-allowed]=\"disabled || readonly\"\n [class.opacity-50]=\"disabled\"\n ></div>\n </div>\n }\n </div>\n\n <!-- Color Presets Dropdown -->\n @if (isDropdownOpen && !disabled && !readonly) {\n <div\n class=\"absolute z-50 mt-2 p-3 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg\"\n >\n <div class=\"grid grid-cols-5 gap-2 min-w-[200px]\">\n @for (color of presetColors; track color) {\n <button\n type=\"button\"\n class=\"w-8 h-8 rounded-md border-2 border-gray-300 hover:border-gray-400 transition-all hover:scale-110 focus:outline-none focus:ring-2 focus:ring-indigo-500\"\n [style.background-color]=\"color\"\n (click)=\"selectPresetColor(color)\"\n [attr.aria-label]=\"`Select color ${color}`\"\n ></button>\n }\n </div>\n\n <!-- Custom Color Input -->\n <div class=\"mt-3 pt-3 border-t border-gray-200 dark:border-gray-700\">\n <label class=\"text-xs text-gray-600 dark:text-gray-400 block mb-1\">Custom color:</label>\n <input\n type=\"color\"\n class=\"w-full h-8 rounded cursor-pointer\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onColorChange($event)\"\n />\n </div>\n </div>\n }\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">Please enter a valid hex color (e.g., #FF5733)</div>\n }\n</div>\n", styles: [":host{display:block}.color-picker-dropdown{z-index:9999}.color-preview{transition:all .2s ease-in-out}.color-preset-button{transition:all .15s ease-in-out}.color-preset-button:focus{outline:2px solid #4f46e5;outline-offset:2px}@media(prefers-color-scheme:dark){.color-picker-dropdown{background-color:#1f2937;border-color:#374151}}@keyframes dropdownFadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.color-picker-dropdown{animation:dropdownFadeIn .15s ease-out}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
2199
|
+
}
|
|
2200
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ColorPickerComponent, decorators: [{
|
|
2201
|
+
type: Component,
|
|
2202
|
+
args: [{ selector: 'color-picker', standalone: true, imports: [FormsModule, CommonModule, ReactiveFormsModule], template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <div class=\"flex gap-2 items-center\">\n <!-- Color Input -->\n <div class=\"relative flex-1\">\n <input\n type=\"text\"\n [id]=\"inputId\"\n [name]=\"name\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onInputColorChange($event)\"\n (blur)=\"onTouched()\"\n [readonly]=\"readonly\"\n [disabled]=\"disabled\"\n [class.bg-white]=\"!readonly\"\n [class.bg-gray-200]=\"readonly\"\n [class.cursor-not-allowed]=\"readonly\"\n [class]=\"inputClasses\"\n pattern=\"^#[0-9A-Fa-f]{6}$\"\n />\n\n <!-- Native Color Picker (Hidden) -->\n <input\n type=\"color\"\n class=\"absolute inset-0 opacity-0 cursor-pointer\"\n [disabled]=\"disabled || readonly\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onColorChange($event)\"\n />\n </div>\n\n <!-- Color Preview -->\n @if (showPreview) {\n <div class=\"flex items-center\">\n <div\n class=\"w-[37px] h-[37px] rounded-md border border-gray-300 cursor-pointer transition-all hover:scale-105\"\n [style.background-color]=\"value\"\n (click)=\"toggleDropdown()\"\n [class.cursor-not-allowed]=\"disabled || readonly\"\n [class.opacity-50]=\"disabled\"\n ></div>\n </div>\n }\n </div>\n\n <!-- Color Presets Dropdown -->\n @if (isDropdownOpen && !disabled && !readonly) {\n <div\n class=\"absolute z-50 mt-2 p-3 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg\"\n >\n <div class=\"grid grid-cols-5 gap-2 min-w-[200px]\">\n @for (color of presetColors; track color) {\n <button\n type=\"button\"\n class=\"w-8 h-8 rounded-md border-2 border-gray-300 hover:border-gray-400 transition-all hover:scale-110 focus:outline-none focus:ring-2 focus:ring-indigo-500\"\n [style.background-color]=\"color\"\n (click)=\"selectPresetColor(color)\"\n [attr.aria-label]=\"`Select color ${color}`\"\n ></button>\n }\n </div>\n\n <!-- Custom Color Input -->\n <div class=\"mt-3 pt-3 border-t border-gray-200 dark:border-gray-700\">\n <label class=\"text-xs text-gray-600 dark:text-gray-400 block mb-1\">Custom color:</label>\n <input\n type=\"color\"\n class=\"w-full h-8 rounded cursor-pointer\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onColorChange($event)\"\n />\n </div>\n </div>\n }\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">Please enter a valid hex color (e.g., #FF5733)</div>\n }\n</div>\n", styles: [":host{display:block}.color-picker-dropdown{z-index:9999}.color-preview{transition:all .2s ease-in-out}.color-preset-button{transition:all .15s ease-in-out}.color-preset-button:focus{outline:2px solid #4f46e5;outline-offset:2px}@media(prefers-color-scheme:dark){.color-picker-dropdown{background-color:#1f2937;border-color:#374151}}@keyframes dropdownFadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.color-picker-dropdown{animation:dropdownFadeIn .15s ease-out}\n"] }]
|
|
2203
|
+
}], ctorParameters: () => [{ type: i1$1.NgControl, decorators: [{
|
|
2204
|
+
type: Self
|
|
2205
|
+
}, {
|
|
2206
|
+
type: Optional
|
|
2207
|
+
}] }, { type: i0.ElementRef }], propDecorators: { label: [{
|
|
2208
|
+
type: Input
|
|
2209
|
+
}], name: [{
|
|
2210
|
+
type: Input
|
|
2211
|
+
}], id: [{
|
|
2212
|
+
type: Input
|
|
2213
|
+
}], placeholder: [{
|
|
2214
|
+
type: Input
|
|
2215
|
+
}], required: [{
|
|
2216
|
+
type: Input
|
|
2217
|
+
}], readonly: [{
|
|
2218
|
+
type: Input
|
|
2219
|
+
}], fieldGroupClass: [{
|
|
2220
|
+
type: Input
|
|
2221
|
+
}], showPreview: [{
|
|
2222
|
+
type: Input
|
|
2223
|
+
}], presetColors: [{
|
|
2224
|
+
type: Input
|
|
2225
|
+
}], colorChange: [{
|
|
2226
|
+
type: Output
|
|
2227
|
+
}], onDocumentClick: [{
|
|
2228
|
+
type: HostListener,
|
|
2229
|
+
args: ['document:click', ['$event']]
|
|
2230
|
+
}] } });
|
|
2231
|
+
|
|
2232
|
+
class DateInputComponent {
|
|
2233
|
+
ngControl;
|
|
2234
|
+
transloco;
|
|
2235
|
+
label = '';
|
|
2236
|
+
type = 'date';
|
|
2237
|
+
includeTime = false;
|
|
2238
|
+
name = '';
|
|
2239
|
+
id = '';
|
|
2240
|
+
placeholder = '';
|
|
2241
|
+
required = false;
|
|
2242
|
+
readonly = false;
|
|
2243
|
+
min = null;
|
|
2244
|
+
max = null;
|
|
2245
|
+
fieldGroupClass = '';
|
|
2246
|
+
dateFormat = 'yyyy-MM-dd';
|
|
2247
|
+
value = '';
|
|
2248
|
+
disabled = false;
|
|
2249
|
+
onChange = () => { };
|
|
2250
|
+
onTouched = () => { };
|
|
2251
|
+
constructor(ngControl, transloco) {
|
|
2252
|
+
this.ngControl = ngControl;
|
|
2253
|
+
this.transloco = transloco;
|
|
2254
|
+
if (this.ngControl) {
|
|
2255
|
+
this.ngControl.valueAccessor = this;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
writeValue(value) {
|
|
2259
|
+
if (value) {
|
|
2260
|
+
if (value instanceof Date) {
|
|
2261
|
+
this.value = this.formatDateForInput(value);
|
|
2262
|
+
}
|
|
2263
|
+
else if (typeof value === 'string') {
|
|
2264
|
+
this.value = value;
|
|
2265
|
+
}
|
|
2266
|
+
else {
|
|
2267
|
+
this.value = '';
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
else {
|
|
2271
|
+
this.value = '';
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
registerOnChange(fn) {
|
|
2275
|
+
this.onChange = fn;
|
|
2276
|
+
}
|
|
2277
|
+
registerOnTouched(fn) {
|
|
2278
|
+
this.onTouched = fn;
|
|
2279
|
+
}
|
|
2280
|
+
setDisabledState(isDisabled) {
|
|
2281
|
+
this.disabled = isDisabled;
|
|
2282
|
+
}
|
|
2283
|
+
onInput(value) {
|
|
2284
|
+
this.value = value;
|
|
2285
|
+
const dateValue = value ? new Date(value) : null;
|
|
2286
|
+
this.onChange(dateValue);
|
|
2287
|
+
this.onTouched();
|
|
2288
|
+
}
|
|
2289
|
+
formatDateForInput(date) {
|
|
2290
|
+
const year = date.getFullYear();
|
|
2291
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
2292
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
2293
|
+
if (this.includeTime) {
|
|
2294
|
+
const hours = String(date.getHours()).padStart(2, '0');
|
|
2295
|
+
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
2296
|
+
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
|
2297
|
+
}
|
|
2298
|
+
return `${year}-${month}-${day}`;
|
|
2299
|
+
}
|
|
2300
|
+
parseDateFromString(dateString) {
|
|
2301
|
+
if (!dateString)
|
|
2302
|
+
return null;
|
|
2303
|
+
const date = new Date(dateString);
|
|
2304
|
+
return isNaN(date.getTime()) ? null : date;
|
|
2305
|
+
}
|
|
2306
|
+
get inputId() {
|
|
2307
|
+
return this.id || this.name;
|
|
2308
|
+
}
|
|
2309
|
+
get showError() {
|
|
2310
|
+
if (!this.ngControl || !this.ngControl.control)
|
|
2311
|
+
return false;
|
|
2312
|
+
const control = this.ngControl.control;
|
|
2313
|
+
const dirty = control.dirty;
|
|
2314
|
+
const touched = control.touched;
|
|
2315
|
+
return control.invalid ? dirty || touched : false;
|
|
2316
|
+
}
|
|
2317
|
+
get errorMessage() {
|
|
2318
|
+
if (!this.ngControl?.errors)
|
|
2319
|
+
return '';
|
|
2320
|
+
const errors = this.ngControl.errors;
|
|
2321
|
+
const errorKey = Object.keys(errors)[0];
|
|
2322
|
+
if (errorKey === 'minlength') {
|
|
2323
|
+
return this.transloco.translate('formErrors.minlength', {
|
|
2324
|
+
length: errors[errorKey].requiredLength,
|
|
2325
|
+
});
|
|
2326
|
+
}
|
|
2327
|
+
return this.transloco.translate(`formErrors.${errorKey}`, {}, this.transloco.translate('formErrors.invalidField'));
|
|
2328
|
+
}
|
|
2329
|
+
get inputClasses() {
|
|
2330
|
+
return this.showError ? ERROR_INPUT_CLASSES : BASE_INPUT_CLASSES;
|
|
2331
|
+
}
|
|
2332
|
+
get fieldGroupClasses() {
|
|
2333
|
+
let baseClasses = '';
|
|
2334
|
+
if (this.fieldGroupClass) {
|
|
2335
|
+
baseClasses += ` ${this.fieldGroupClass}`;
|
|
2336
|
+
}
|
|
2337
|
+
else {
|
|
2338
|
+
baseClasses += ' w-full';
|
|
2339
|
+
}
|
|
2340
|
+
return baseClasses;
|
|
2341
|
+
}
|
|
2342
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DateInputComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2343
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: DateInputComponent, isStandalone: true, selector: "date-input", inputs: { label: "label", type: "type", includeTime: "includeTime", name: "name", id: "id", placeholder: "placeholder", required: "required", readonly: "readonly", min: "min", max: "max", fieldGroupClass: "fieldGroupClass", dateFormat: "dateFormat" }, ngImport: i0, template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <input\n [type]=\"includeTime ? 'datetime-local' : type\"\n [id]=\"inputId\"\n [name]=\"name\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [min]=\"min\"\n [max]=\"max\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onInput($event)\"\n (blur)=\"onTouched()\"\n [disabled]=\"disabled\"\n [class]=\"inputClasses\"\n [readonly]=\"readonly\"\n />\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
2344
|
+
}
|
|
2345
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: DateInputComponent, decorators: [{
|
|
2346
|
+
type: Component,
|
|
2347
|
+
args: [{ selector: 'date-input', standalone: true, imports: [FormsModule, CommonModule, ReactiveFormsModule], template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"relative\">\n <input\n [type]=\"includeTime ? 'datetime-local' : type\"\n [id]=\"inputId\"\n [name]=\"name\"\n [placeholder]=\"placeholder\"\n [required]=\"required\"\n [min]=\"min\"\n [max]=\"max\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onInput($event)\"\n (blur)=\"onTouched()\"\n [disabled]=\"disabled\"\n [class]=\"inputClasses\"\n [readonly]=\"readonly\"\n />\n </div>\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n" }]
|
|
2348
|
+
}], ctorParameters: () => [{ type: i1$1.NgControl, decorators: [{
|
|
2349
|
+
type: Self
|
|
2350
|
+
}, {
|
|
2351
|
+
type: Optional
|
|
2352
|
+
}] }, { type: i2.TranslocoService }], propDecorators: { label: [{
|
|
2353
|
+
type: Input
|
|
2354
|
+
}], type: [{
|
|
2355
|
+
type: Input
|
|
2356
|
+
}], includeTime: [{
|
|
2357
|
+
type: Input
|
|
2358
|
+
}], name: [{
|
|
2359
|
+
type: Input
|
|
2360
|
+
}], id: [{
|
|
2361
|
+
type: Input
|
|
2362
|
+
}], placeholder: [{
|
|
2363
|
+
type: Input
|
|
2364
|
+
}], required: [{
|
|
2365
|
+
type: Input
|
|
2366
|
+
}], readonly: [{
|
|
2367
|
+
type: Input
|
|
2368
|
+
}], min: [{
|
|
2369
|
+
type: Input
|
|
2370
|
+
}], max: [{
|
|
2371
|
+
type: Input
|
|
2372
|
+
}], fieldGroupClass: [{
|
|
2373
|
+
type: Input
|
|
2374
|
+
}], dateFormat: [{
|
|
2375
|
+
type: Input
|
|
2376
|
+
}] } });
|
|
2377
|
+
|
|
2378
|
+
class ToggleSwitchComponent {
|
|
2379
|
+
ngControl;
|
|
2380
|
+
label = '';
|
|
2381
|
+
name = '';
|
|
2382
|
+
id = '';
|
|
2383
|
+
required = false;
|
|
2384
|
+
disabled = false;
|
|
2385
|
+
size = 'md';
|
|
2386
|
+
fieldGroupClass = '';
|
|
2387
|
+
description = '';
|
|
2388
|
+
toggleClick = new EventEmitter();
|
|
2389
|
+
value = false;
|
|
2390
|
+
onChange = () => { };
|
|
2391
|
+
onTouched = () => { };
|
|
2392
|
+
constructor(ngControl) {
|
|
2393
|
+
this.ngControl = ngControl;
|
|
2394
|
+
if (this.ngControl) {
|
|
2395
|
+
this.ngControl.valueAccessor = this;
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
// Control value accessor methods
|
|
2399
|
+
writeValue(value) {
|
|
2400
|
+
this.value = value ?? false;
|
|
2401
|
+
}
|
|
2402
|
+
registerOnChange(fn) {
|
|
2403
|
+
this.onChange = fn;
|
|
2404
|
+
}
|
|
2405
|
+
registerOnTouched(fn) {
|
|
2406
|
+
this.onTouched = fn;
|
|
2407
|
+
}
|
|
2408
|
+
setDisabledState(isDisabled) {
|
|
2409
|
+
this.disabled = isDisabled;
|
|
2410
|
+
}
|
|
2411
|
+
onToggle() {
|
|
2412
|
+
this.value = !this.value;
|
|
2413
|
+
this.onChange(this.value);
|
|
2414
|
+
this.onTouched();
|
|
2415
|
+
this.toggleClick.emit(this.value);
|
|
2416
|
+
}
|
|
2417
|
+
get inputId() {
|
|
2418
|
+
return this.id || this.name;
|
|
2419
|
+
}
|
|
2420
|
+
get toggleSizeClasses() {
|
|
2421
|
+
switch (this.size) {
|
|
2422
|
+
case 'sm':
|
|
2423
|
+
return 'h-4 w-7';
|
|
2424
|
+
case 'lg':
|
|
2425
|
+
return 'h-7 w-14';
|
|
2426
|
+
default:
|
|
2427
|
+
return 'h-5 w-9';
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
get toggleThumbSizeClasses() {
|
|
2431
|
+
switch (this.size) {
|
|
2432
|
+
case 'sm':
|
|
2433
|
+
return 'h-3 w-3';
|
|
2434
|
+
case 'lg':
|
|
2435
|
+
return 'h-6 w-6';
|
|
2436
|
+
default:
|
|
2437
|
+
return 'h-4 w-4';
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
get toggleThumbTranslateClasses() {
|
|
2441
|
+
switch (this.size) {
|
|
2442
|
+
case 'sm':
|
|
2443
|
+
return 'translate-x-3';
|
|
2444
|
+
case 'lg':
|
|
2445
|
+
return 'translate-x-7';
|
|
2446
|
+
default:
|
|
2447
|
+
return 'translate-x-5';
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
get fieldGroupClasses() {
|
|
2451
|
+
let baseClasses = '';
|
|
2452
|
+
if (this.fieldGroupClass) {
|
|
2453
|
+
baseClasses += ` ${this.fieldGroupClass}`;
|
|
2454
|
+
}
|
|
2455
|
+
else {
|
|
2456
|
+
baseClasses += ' w-full';
|
|
2457
|
+
}
|
|
2458
|
+
return baseClasses;
|
|
2459
|
+
}
|
|
2460
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ToggleSwitchComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
2461
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: ToggleSwitchComponent, isStandalone: true, selector: "toggle-switch", inputs: { label: "label", name: "name", id: "id", required: "required", disabled: "disabled", size: "size", fieldGroupClass: "fieldGroupClass", description: "description" }, outputs: { toggleClick: "toggleClick" }, ngImport: i0, template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"flex items-center\">\n <button\n type=\"button\"\n role=\"switch\"\n [id]=\"inputId\"\n [name]=\"name\"\n [attr.aria-checked]=\"value\"\n [attr.aria-required]=\"required\"\n [disabled]=\"disabled\"\n [class]=\"\n 'toggle-switch ' +\n size +\n (value ? ' checked' : ' unchecked') +\n (disabled ? ' disabled' : '')\n \"\n (click)=\"onToggle()\"\n >\n <span\n [class]=\"\n 'toggle-thumb ' +\n size +\n (value ? ' checked' : ' unchecked') +\n (disabled ? ' disabled' : '')\n \"\n ></span>\n </button>\n\n @if (description) {\n <span class=\"ml-3 text-sm text-gray-500 dark:text-gray-400\">{{ description }}</span>\n }\n </div>\n\n <!-- Hidden checkbox for form submission and accessibility -->\n <input\n type=\"checkbox\"\n [id]=\"inputId + '-hidden'\"\n [name]=\"name\"\n [checked]=\"value\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n class=\"sr-only\"\n (change)=\"onToggle()\"\n />\n</div>\n", styles: [".toggle-switch{display:inline-flex;flex-shrink:0;position:relative;border:2px solid transparent;border-radius:9999px;cursor:pointer;transition:background-color .2s ease-in-out;outline:none}.toggle-switch:focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #4f46e5}.toggle-switch.checked:not(.disabled){background-color:#4f46e5}.toggle-switch.unchecked:not(.disabled){background-color:#e5e7eb}.toggle-switch.disabled{background-color:#d1d5db;cursor:not-allowed;opacity:.5}.toggle-switch.sm{height:1rem;width:1.75rem;padding:0 2px;box-sizing:border-box}.toggle-switch.sm .toggle-thumb{height:calc(1rem - 6px);width:calc(1rem - 6px)}.toggle-switch.sm .toggle-thumb.checked{transform:translate(calc(.75rem - 2px))}.toggle-switch.md{height:1.25rem;width:2.25rem;padding:0 2px;box-sizing:border-box}.toggle-switch.md .toggle-thumb{height:calc(1.25rem - 6px);width:calc(1.25rem - 6px)}.toggle-switch.md .toggle-thumb.checked{transform:translate(calc(1rem - 2px))}.toggle-switch.lg{height:1.75rem;width:3.5rem;padding:0 2px;box-sizing:border-box}.toggle-switch.lg .toggle-thumb{height:calc(1.75rem - 6px);width:calc(1.75rem - 6px)}.toggle-switch.lg .toggle-thumb.checked{transform:translate(calc(1.75rem - 2px))}.toggle-thumb{pointer-events:none;display:inline-block;border-radius:50%;background-color:#fff;box-shadow:0 10px 15px -3px #0000001a;transition:transform .2s ease-in-out;margin:auto 0}.disabled .toggle-thumb{background-color:#9ca3af}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
2462
|
+
}
|
|
2463
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ToggleSwitchComponent, decorators: [{
|
|
2464
|
+
type: Component,
|
|
2465
|
+
args: [{ selector: 'toggle-switch', standalone: true, imports: [FormsModule, CommonModule, ReactiveFormsModule], template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div class=\"flex items-center\">\n <button\n type=\"button\"\n role=\"switch\"\n [id]=\"inputId\"\n [name]=\"name\"\n [attr.aria-checked]=\"value\"\n [attr.aria-required]=\"required\"\n [disabled]=\"disabled\"\n [class]=\"\n 'toggle-switch ' +\n size +\n (value ? ' checked' : ' unchecked') +\n (disabled ? ' disabled' : '')\n \"\n (click)=\"onToggle()\"\n >\n <span\n [class]=\"\n 'toggle-thumb ' +\n size +\n (value ? ' checked' : ' unchecked') +\n (disabled ? ' disabled' : '')\n \"\n ></span>\n </button>\n\n @if (description) {\n <span class=\"ml-3 text-sm text-gray-500 dark:text-gray-400\">{{ description }}</span>\n }\n </div>\n\n <!-- Hidden checkbox for form submission and accessibility -->\n <input\n type=\"checkbox\"\n [id]=\"inputId + '-hidden'\"\n [name]=\"name\"\n [checked]=\"value\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n class=\"sr-only\"\n (change)=\"onToggle()\"\n />\n</div>\n", styles: [".toggle-switch{display:inline-flex;flex-shrink:0;position:relative;border:2px solid transparent;border-radius:9999px;cursor:pointer;transition:background-color .2s ease-in-out;outline:none}.toggle-switch:focus{box-shadow:0 0 0 2px #fff,0 0 0 4px #4f46e5}.toggle-switch.checked:not(.disabled){background-color:#4f46e5}.toggle-switch.unchecked:not(.disabled){background-color:#e5e7eb}.toggle-switch.disabled{background-color:#d1d5db;cursor:not-allowed;opacity:.5}.toggle-switch.sm{height:1rem;width:1.75rem;padding:0 2px;box-sizing:border-box}.toggle-switch.sm .toggle-thumb{height:calc(1rem - 6px);width:calc(1rem - 6px)}.toggle-switch.sm .toggle-thumb.checked{transform:translate(calc(.75rem - 2px))}.toggle-switch.md{height:1.25rem;width:2.25rem;padding:0 2px;box-sizing:border-box}.toggle-switch.md .toggle-thumb{height:calc(1.25rem - 6px);width:calc(1.25rem - 6px)}.toggle-switch.md .toggle-thumb.checked{transform:translate(calc(1rem - 2px))}.toggle-switch.lg{height:1.75rem;width:3.5rem;padding:0 2px;box-sizing:border-box}.toggle-switch.lg .toggle-thumb{height:calc(1.75rem - 6px);width:calc(1.75rem - 6px)}.toggle-switch.lg .toggle-thumb.checked{transform:translate(calc(1.75rem - 2px))}.toggle-thumb{pointer-events:none;display:inline-block;border-radius:50%;background-color:#fff;box-shadow:0 10px 15px -3px #0000001a;transition:transform .2s ease-in-out;margin:auto 0}.disabled .toggle-thumb{background-color:#9ca3af}\n"] }]
|
|
2466
|
+
}], ctorParameters: () => [{ type: i1$1.NgControl, decorators: [{
|
|
2467
|
+
type: Self
|
|
2468
|
+
}, {
|
|
2469
|
+
type: Optional
|
|
2470
|
+
}] }], propDecorators: { label: [{
|
|
2471
|
+
type: Input
|
|
2472
|
+
}], name: [{
|
|
2473
|
+
type: Input
|
|
2474
|
+
}], id: [{
|
|
2475
|
+
type: Input
|
|
2476
|
+
}], required: [{
|
|
2477
|
+
type: Input
|
|
2478
|
+
}], disabled: [{
|
|
2479
|
+
type: Input
|
|
2480
|
+
}], size: [{
|
|
2481
|
+
type: Input
|
|
2482
|
+
}], fieldGroupClass: [{
|
|
2483
|
+
type: Input
|
|
2484
|
+
}], description: [{
|
|
2485
|
+
type: Input
|
|
2486
|
+
}], toggleClick: [{
|
|
2487
|
+
type: Output
|
|
2488
|
+
}] } });
|
|
2489
|
+
|
|
2490
|
+
class FileUploadPreviewComponent {
|
|
2491
|
+
file = {};
|
|
2492
|
+
remove = new EventEmitter();
|
|
2493
|
+
removeFile() {
|
|
2494
|
+
this.remove.emit(this.file);
|
|
2495
|
+
}
|
|
2496
|
+
getFileType(file) {
|
|
2497
|
+
if (file.type.startsWith('image/'))
|
|
2498
|
+
return FileType.IMAGE;
|
|
2499
|
+
if (file.type === 'application/pdf')
|
|
2500
|
+
return FileType.PDF;
|
|
2501
|
+
if (file.type.includes('spreadsheet') ||
|
|
2502
|
+
file.type.includes('excel') ||
|
|
2503
|
+
file.extension === 'xlsx' ||
|
|
2504
|
+
file.extension === 'xls' ||
|
|
2505
|
+
file.extension === 'csv') {
|
|
2506
|
+
return FileType.EXCEL;
|
|
2507
|
+
}
|
|
2508
|
+
if (file.type.includes('word') ||
|
|
2509
|
+
file.type.includes('document') ||
|
|
2510
|
+
file.extension === 'docx' ||
|
|
2511
|
+
file.extension === 'doc') {
|
|
2512
|
+
return FileType.WORD;
|
|
2513
|
+
}
|
|
2514
|
+
if (file.type.startsWith('text/') || file.extension === 'txt') {
|
|
2515
|
+
return FileType.TEXT;
|
|
2516
|
+
}
|
|
2517
|
+
return FileType.DEFAULT;
|
|
2518
|
+
}
|
|
2519
|
+
getFileIcon(fileType) {
|
|
2520
|
+
switch (fileType) {
|
|
2521
|
+
case FileType.IMAGE:
|
|
2522
|
+
return 'ri-image-line';
|
|
2523
|
+
case FileType.PDF:
|
|
2524
|
+
return 'ri-file-pdf-line';
|
|
2525
|
+
case FileType.EXCEL:
|
|
2526
|
+
return 'ri-file-excel-line';
|
|
2527
|
+
case FileType.WORD:
|
|
2528
|
+
return 'ri-file-word-line';
|
|
2529
|
+
case FileType.TEXT:
|
|
2530
|
+
return 'ri-file-text-line';
|
|
2531
|
+
default:
|
|
2532
|
+
return 'ri-file-line';
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
getFileTypeIcon(file) {
|
|
2536
|
+
return this.getFileIcon(this.getFileType(file));
|
|
2537
|
+
}
|
|
2538
|
+
formatFileSize(bytes) {
|
|
2539
|
+
if (bytes === 0)
|
|
2540
|
+
return '0 Bytes';
|
|
2541
|
+
const k = 1024;
|
|
2542
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
2543
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
2544
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
2545
|
+
}
|
|
2546
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FileUploadPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2547
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: FileUploadPreviewComponent, isStandalone: true, selector: "file-upload-preview", inputs: { file: "file" }, outputs: { remove: "remove" }, ngImport: i0, template: "<div class=\"flex items-center justify-between p-3 bg-gray-50 rounded-lg border border-gray-200\">\n <div class=\"flex items-center space-x-3 flex-1 min-w-0\">\n <!-- File Preview/Icon -->\n <div class=\"flex-shrink-0\">\n @if (file.preview) {\n <img [src]=\"file.preview\" [alt]=\"file.name\" class=\"w-10 h-10 object-cover rounded-md\" />\n } @else {\n <div class=\"w-10 h-10 bg-gray-200 rounded-md flex items-center justify-center\">\n <i [class]=\"getFileTypeIcon(file) + ' text-gray-600 text-lg'\"></i>\n </div>\n }\n </div>\n\n <!-- File Info -->\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-gray-900 truncate\">\n {{ file.name }}\n </p>\n <p class=\"text-xs text-gray-500\">\n @if (!!file.size) {\n {{ formatFileSize(file.size) }}\n }\n @if (file.extension) {\n \u2022 {{ file.extension.toUpperCase() }}\n }\n </p>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"flex items-center space-x-2 ml-4\">\n <app-button\n icon=\"ri-delete-bin-line\"\n (clicked)=\"removeFile()\"\n variant=\"primary\"\n size=\"xs\"\n title=\"Eliminar archivo\"\n />\n </div>\n</div>\n", styles: [".file-upload__drag-over{border-color:#60a5fa;background-color:#eff6ff}.file-upload__disabled{border-color:#e5e7eb;background-color:#f9fafb;cursor:not-allowed}.file-upload__preview{transition:all .2s ease-in-out}.file-upload__preview:hover{transform:scale(1.05)}.file-upload__file-item{transition:all .2s ease-in-out}.file-upload__file-item:hover{background-color:#f3f4f6;border-color:#d1d5db}.file-upload__remove-btn{transition:all .2s ease-in-out}.file-upload__remove-btn:hover{background-color:#fef2f2}.file-upload__remove-btn:active{transform:scale(.95)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.file-upload__drag-active{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.file-upload__file-list{max-height:15rem;overflow-y:auto}.file-upload__file-list::-webkit-scrollbar{width:.5rem}.file-upload__file-list::-webkit-scrollbar-track{background-color:#f3f4f6;border-radius:9999px}.file-upload__file-list::-webkit-scrollbar-thumb{background-color:#d1d5db;border-radius:9999px}.file-upload__file-list::-webkit-scrollbar-thumb:hover{background-color:#9ca3af}.file-type-icon--image{color:#3b82f6}.file-type-icon--pdf{color:#ef4444}.file-type-icon--excel{color:#10b981}.file-type-icon--word{color:#2563eb}.file-type-icon--text{color:#6b7280}.file-type-icon--default{color:#9ca3af}@media(max-width:640px){.file-upload__file-item{padding:.5rem}.file-upload__file-info{font-size:.75rem}.file-upload__preview{width:2rem;height:2rem}}@media(prefers-color-scheme:dark){.file-upload__file-item{background-color:#1f2937;border-color:#374151}.file-upload__file-item:hover{background-color:#111827;border-color:#4b5563}.file-upload__file-info{color:#d1d5db}.file-upload__file-name{color:#f3f4f6}.file-upload__file-size{color:#9ca3af}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: AppButtonComponent, selector: "app-button", inputs: ["disabled", "loading", "type", "variant", "text", "size", "loadingText", "icon"], outputs: ["clicked"] }] });
|
|
2548
|
+
}
|
|
2549
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FileUploadPreviewComponent, decorators: [{
|
|
2550
|
+
type: Component,
|
|
2551
|
+
args: [{ selector: 'file-upload-preview', standalone: true, imports: [FormsModule, CommonModule, ReactiveFormsModule, AppButtonComponent], template: "<div class=\"flex items-center justify-between p-3 bg-gray-50 rounded-lg border border-gray-200\">\n <div class=\"flex items-center space-x-3 flex-1 min-w-0\">\n <!-- File Preview/Icon -->\n <div class=\"flex-shrink-0\">\n @if (file.preview) {\n <img [src]=\"file.preview\" [alt]=\"file.name\" class=\"w-10 h-10 object-cover rounded-md\" />\n } @else {\n <div class=\"w-10 h-10 bg-gray-200 rounded-md flex items-center justify-center\">\n <i [class]=\"getFileTypeIcon(file) + ' text-gray-600 text-lg'\"></i>\n </div>\n }\n </div>\n\n <!-- File Info -->\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-gray-900 truncate\">\n {{ file.name }}\n </p>\n <p class=\"text-xs text-gray-500\">\n @if (!!file.size) {\n {{ formatFileSize(file.size) }}\n }\n @if (file.extension) {\n \u2022 {{ file.extension.toUpperCase() }}\n }\n </p>\n </div>\n </div>\n\n <!-- Actions -->\n <div class=\"flex items-center space-x-2 ml-4\">\n <app-button\n icon=\"ri-delete-bin-line\"\n (clicked)=\"removeFile()\"\n variant=\"primary\"\n size=\"xs\"\n title=\"Eliminar archivo\"\n />\n </div>\n</div>\n", styles: [".file-upload__drag-over{border-color:#60a5fa;background-color:#eff6ff}.file-upload__disabled{border-color:#e5e7eb;background-color:#f9fafb;cursor:not-allowed}.file-upload__preview{transition:all .2s ease-in-out}.file-upload__preview:hover{transform:scale(1.05)}.file-upload__file-item{transition:all .2s ease-in-out}.file-upload__file-item:hover{background-color:#f3f4f6;border-color:#d1d5db}.file-upload__remove-btn{transition:all .2s ease-in-out}.file-upload__remove-btn:hover{background-color:#fef2f2}.file-upload__remove-btn:active{transform:scale(.95)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.file-upload__drag-active{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.file-upload__file-list{max-height:15rem;overflow-y:auto}.file-upload__file-list::-webkit-scrollbar{width:.5rem}.file-upload__file-list::-webkit-scrollbar-track{background-color:#f3f4f6;border-radius:9999px}.file-upload__file-list::-webkit-scrollbar-thumb{background-color:#d1d5db;border-radius:9999px}.file-upload__file-list::-webkit-scrollbar-thumb:hover{background-color:#9ca3af}.file-type-icon--image{color:#3b82f6}.file-type-icon--pdf{color:#ef4444}.file-type-icon--excel{color:#10b981}.file-type-icon--word{color:#2563eb}.file-type-icon--text{color:#6b7280}.file-type-icon--default{color:#9ca3af}@media(max-width:640px){.file-upload__file-item{padding:.5rem}.file-upload__file-info{font-size:.75rem}.file-upload__preview{width:2rem;height:2rem}}@media(prefers-color-scheme:dark){.file-upload__file-item{background-color:#1f2937;border-color:#374151}.file-upload__file-item:hover{background-color:#111827;border-color:#4b5563}.file-upload__file-info{color:#d1d5db}.file-upload__file-name{color:#f3f4f6}.file-upload__file-size{color:#9ca3af}}\n"] }]
|
|
2552
|
+
}], propDecorators: { file: [{
|
|
2553
|
+
type: Input,
|
|
2554
|
+
args: [{ required: true }]
|
|
2555
|
+
}], remove: [{
|
|
2556
|
+
type: Output
|
|
2557
|
+
}] } });
|
|
2558
|
+
|
|
2559
|
+
class FileUploadComponent {
|
|
2560
|
+
ngControl;
|
|
2561
|
+
transloco;
|
|
2562
|
+
label = '';
|
|
2563
|
+
name = '';
|
|
2564
|
+
id = '';
|
|
2565
|
+
required = false;
|
|
2566
|
+
readonly = false;
|
|
2567
|
+
fieldGroupClass = '';
|
|
2568
|
+
config = {};
|
|
2569
|
+
accept = '*/*';
|
|
2570
|
+
fileSelected = new EventEmitter();
|
|
2571
|
+
fileRemoved = new EventEmitter();
|
|
2572
|
+
validationError = new EventEmitter();
|
|
2573
|
+
files = [];
|
|
2574
|
+
disabled = false;
|
|
2575
|
+
onChange = () => { };
|
|
2576
|
+
onTouched = () => { };
|
|
2577
|
+
dragOver = false;
|
|
2578
|
+
constructor(ngControl, transloco) {
|
|
2579
|
+
this.ngControl = ngControl;
|
|
2580
|
+
this.transloco = transloco;
|
|
2581
|
+
if (this.ngControl) {
|
|
2582
|
+
this.ngControl.valueAccessor = this;
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
writeValue(value) {
|
|
2586
|
+
this.files = value || [];
|
|
2587
|
+
}
|
|
2588
|
+
registerOnChange(fn) {
|
|
2589
|
+
this.onChange = fn;
|
|
2590
|
+
}
|
|
2591
|
+
registerOnTouched(fn) {
|
|
2592
|
+
this.onTouched = fn;
|
|
2593
|
+
}
|
|
2594
|
+
setDisabledState(isDisabled) {
|
|
2595
|
+
this.disabled = isDisabled;
|
|
2596
|
+
}
|
|
2597
|
+
onFileSelect(event) {
|
|
2598
|
+
const input = event.target;
|
|
2599
|
+
if (input.files && input.files.length > 0) {
|
|
2600
|
+
this.handleFiles(Array.from(input.files));
|
|
2601
|
+
}
|
|
2602
|
+
input.value = '';
|
|
2603
|
+
}
|
|
2604
|
+
onDrop(event) {
|
|
2605
|
+
event.preventDefault();
|
|
2606
|
+
this.dragOver = false;
|
|
2607
|
+
if (event.dataTransfer?.files && event.dataTransfer.files.length > 0) {
|
|
2608
|
+
this.handleFiles(Array.from(event.dataTransfer.files));
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
onDragOver(event) {
|
|
2612
|
+
event.preventDefault();
|
|
2613
|
+
this.dragOver = true;
|
|
2614
|
+
}
|
|
2615
|
+
onDragLeave(event) {
|
|
2616
|
+
event.preventDefault();
|
|
2617
|
+
this.dragOver = false;
|
|
2618
|
+
}
|
|
2619
|
+
async handleFiles(fileList) {
|
|
2620
|
+
const newFiles = [];
|
|
2621
|
+
for (const file of fileList) {
|
|
2622
|
+
const validationError = this.validateFile(file);
|
|
2623
|
+
if (validationError) {
|
|
2624
|
+
this.validationError.emit(validationError);
|
|
2625
|
+
continue;
|
|
2626
|
+
}
|
|
2627
|
+
const uploadedFile = {
|
|
2628
|
+
file,
|
|
2629
|
+
name: file.name,
|
|
2630
|
+
size: file.size,
|
|
2631
|
+
type: file.type,
|
|
2632
|
+
extension: this.getFileExtension(file.name),
|
|
2633
|
+
};
|
|
2634
|
+
if (this.isImage(file)) {
|
|
2635
|
+
uploadedFile.preview = await this.generateImagePreview(file);
|
|
2636
|
+
}
|
|
2637
|
+
newFiles.push(uploadedFile);
|
|
2638
|
+
}
|
|
2639
|
+
if (this.config.multiple) {
|
|
2640
|
+
const maxFiles = this.config.maxFiles || 10;
|
|
2641
|
+
const totalFiles = [...this.files, ...newFiles].slice(0, maxFiles);
|
|
2642
|
+
this.files = totalFiles;
|
|
2643
|
+
}
|
|
2644
|
+
else {
|
|
2645
|
+
this.files = newFiles.slice(0, 1);
|
|
2646
|
+
}
|
|
2647
|
+
this.onChange(this.files);
|
|
2648
|
+
this.onTouched();
|
|
2649
|
+
this.fileSelected.emit(this.files);
|
|
2650
|
+
}
|
|
2651
|
+
validateFile(file) {
|
|
2652
|
+
if (this.config.maxFileSize && file.size > this.config.maxFileSize) {
|
|
2653
|
+
const maxSizeMB = this.config.maxFileSize / (1024 * 1024);
|
|
2654
|
+
return this.transloco.translate('fileUpload.sizeError', {
|
|
2655
|
+
fileName: file.name,
|
|
2656
|
+
maxSize: maxSizeMB.toFixed(2),
|
|
2657
|
+
});
|
|
2658
|
+
}
|
|
2659
|
+
if (this.config.allowedExtensions && this.config.allowedExtensions.length > 0) {
|
|
2660
|
+
const extension = this.getFileExtension(file.name);
|
|
2661
|
+
if (!this.config.allowedExtensions.includes(extension)) {
|
|
2662
|
+
return this.transloco.translate('fileUpload.extensionError', {
|
|
2663
|
+
fileName: file.name,
|
|
2664
|
+
extensions: this.config.allowedExtensions.join(', '),
|
|
2665
|
+
});
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
return null;
|
|
2669
|
+
}
|
|
2670
|
+
getFileExtension(filename) {
|
|
2671
|
+
return filename.split('.').pop()?.toLowerCase() || '';
|
|
2672
|
+
}
|
|
2673
|
+
isImage(file) {
|
|
2674
|
+
return file.type.startsWith('image/');
|
|
2675
|
+
}
|
|
2676
|
+
async generateImagePreview(file) {
|
|
2677
|
+
return new Promise((resolve) => {
|
|
2678
|
+
const reader = new FileReader();
|
|
2679
|
+
reader.onload = (e) => {
|
|
2680
|
+
resolve(e.target?.result);
|
|
2681
|
+
};
|
|
2682
|
+
reader.readAsDataURL(file);
|
|
2683
|
+
});
|
|
2684
|
+
}
|
|
2685
|
+
removeFile(index) {
|
|
2686
|
+
const removedFile = this.files[index];
|
|
2687
|
+
this.files.splice(index, 1);
|
|
2688
|
+
this.onChange(this.files);
|
|
2689
|
+
this.onTouched();
|
|
2690
|
+
this.fileRemoved.emit(removedFile);
|
|
2691
|
+
}
|
|
2692
|
+
getFileType(file) {
|
|
2693
|
+
if (file.type.startsWith('image/'))
|
|
2694
|
+
return FileType.IMAGE;
|
|
2695
|
+
if (file.type === 'application/pdf')
|
|
2696
|
+
return FileType.PDF;
|
|
2697
|
+
if (file.type.includes('spreadsheet') ||
|
|
2698
|
+
file.type.includes('excel') ||
|
|
2699
|
+
file.extension === 'xlsx' ||
|
|
2700
|
+
file.extension === 'xls' ||
|
|
2701
|
+
file.extension === 'csv') {
|
|
2702
|
+
return FileType.EXCEL;
|
|
2703
|
+
}
|
|
2704
|
+
if (file.type.includes('word') ||
|
|
2705
|
+
file.type.includes('document') ||
|
|
2706
|
+
file.extension === 'docx' ||
|
|
2707
|
+
file.extension === 'doc') {
|
|
2708
|
+
return FileType.WORD;
|
|
2709
|
+
}
|
|
2710
|
+
if (file.type.startsWith('text/') || file.extension === 'txt') {
|
|
2711
|
+
return FileType.TEXT;
|
|
2712
|
+
}
|
|
2713
|
+
return FileType.DEFAULT;
|
|
2714
|
+
}
|
|
2715
|
+
getFileIcon(fileType) {
|
|
2716
|
+
switch (fileType) {
|
|
2717
|
+
case FileType.IMAGE:
|
|
2718
|
+
return 'ri-image-line';
|
|
2719
|
+
case FileType.PDF:
|
|
2720
|
+
return 'ri-file-pdf-line';
|
|
2721
|
+
case FileType.EXCEL:
|
|
2722
|
+
return 'ri-file-excel-line';
|
|
2723
|
+
case FileType.WORD:
|
|
2724
|
+
return 'ri-file-word-line';
|
|
2725
|
+
case FileType.TEXT:
|
|
2726
|
+
return 'ri-file-text-line';
|
|
2727
|
+
default:
|
|
2728
|
+
return 'ri-file-line';
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
getFileTypeIcon(file) {
|
|
2732
|
+
return this.getFileIcon(this.getFileType(file));
|
|
2733
|
+
}
|
|
2734
|
+
triggerFileInput() {
|
|
2735
|
+
const inputElement = document.getElementById(this.inputId);
|
|
2736
|
+
if (inputElement) {
|
|
2737
|
+
inputElement.click();
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
formatFileSize(bytes) {
|
|
2741
|
+
if (bytes === 0)
|
|
2742
|
+
return '0 Bytes';
|
|
2743
|
+
const k = 1024;
|
|
2744
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
2745
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
2746
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
2747
|
+
}
|
|
2748
|
+
get inputId() {
|
|
2749
|
+
return this.id || this.name;
|
|
2750
|
+
}
|
|
2751
|
+
get showError() {
|
|
2752
|
+
if (!this.ngControl || !this.ngControl.control)
|
|
2753
|
+
return false;
|
|
2754
|
+
const control = this.ngControl.control;
|
|
2755
|
+
const dirty = control.dirty;
|
|
2756
|
+
const touched = control.touched;
|
|
2757
|
+
return control.invalid ? dirty || touched : false;
|
|
2758
|
+
}
|
|
2759
|
+
get errorMessage() {
|
|
2760
|
+
if (!this.ngControl?.errors)
|
|
2761
|
+
return '';
|
|
2762
|
+
const errors = this.ngControl.errors;
|
|
2763
|
+
const errorKey = Object.keys(errors)[0];
|
|
2764
|
+
return this.transloco.translate(`formErrors.${errorKey}`, {}, this.transloco.translate('formErrors.invalidField'));
|
|
2765
|
+
}
|
|
2766
|
+
get fieldGroupClasses() {
|
|
2767
|
+
let baseClasses = '';
|
|
2768
|
+
if (this.fieldGroupClass) {
|
|
2769
|
+
baseClasses += ` ${this.fieldGroupClass}`;
|
|
2770
|
+
}
|
|
2771
|
+
else {
|
|
2772
|
+
baseClasses += ' w-full';
|
|
2773
|
+
}
|
|
2774
|
+
return baseClasses;
|
|
2775
|
+
}
|
|
2776
|
+
get uploadAreaClasses() {
|
|
2777
|
+
const baseClasses = 'border-2 border-dashed rounded-lg p-6 text-center transition-colors cursor-pointer';
|
|
2778
|
+
if (this.disabled) {
|
|
2779
|
+
return `${baseClasses} border-gray-200 bg-gray-50 cursor-not-allowed`;
|
|
2780
|
+
}
|
|
2781
|
+
if (this.dragOver) {
|
|
2782
|
+
return `${baseClasses} border-blue-400 bg-blue-50`;
|
|
2783
|
+
}
|
|
2784
|
+
return `${baseClasses} border-gray-300 hover:border-gray-400 hover:bg-gray-50`;
|
|
2785
|
+
}
|
|
2786
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FileUploadComponent, deps: [{ token: i1$1.NgControl, optional: true, self: true }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2787
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: FileUploadComponent, isStandalone: true, selector: "file-upload", inputs: { label: "label", name: "name", id: "id", required: "required", readonly: "readonly", fieldGroupClass: "fieldGroupClass", config: "config", accept: "accept" }, outputs: { fileSelected: "fileSelected", fileRemoved: "fileRemoved", validationError: "validationError" }, ngImport: i0, template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <!-- Upload Area -->\n <div\n class=\"relative\"\n (drop)=\"onDrop($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n >\n <div [class]=\"uploadAreaClasses\" (click)=\"!disabled && triggerFileInput()\">\n <input\n [id]=\"inputId\"\n [name]=\"name\"\n type=\"file\"\n [accept]=\"accept\"\n [multiple]=\"config.multiple\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n (change)=\"onFileSelect($event)\"\n (blur)=\"onTouched()\"\n class=\"hidden\"\n />\n\n <div class=\"flex flex-col items-center space-y-2\">\n <i class=\"ri-upload-cloud-2-line text-3xl text-gray-400\"></i>\n <div class=\"text-sm text-gray-600\">\n <p class=\"font-medium\">\n @if (config.multiple) {\n {{ 'fileUpload.dropMultiple' | transloco }}\n } @else {\n {{ 'fileUpload.dropSingle' | transloco }}\n }\n </p>\n <p class=\"text-xs text-gray-500 mt-1\">\n @if (config.allowedExtensions && config.allowedExtensions.length > 0) {\n {{ 'fileUpload.allowedExtensions' | transloco }}\n {{ config.allowedExtensions.join(', ') }}\n }\n @if (config.maxFileSize) {\n \u2022 {{ 'fileUpload.maxSize' | transloco }} {{ formatFileSize(config.maxFileSize) }}\n }\n </p>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Files Preview -->\n @if (files.length > 0) {\n <div class=\"flex flex-col gap-2 mt-4\">\n @for (file of files; track file; let i = $index) {\n <file-upload-preview [file]=\"file\" (remove)=\"removeFile(i)\" />\n }\n </div>\n }\n\n <!-- Validation Error -->\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n\n <!-- File Type Legend -->\n @if (files.length === 0) {\n <div class=\"mt-3 flex flex-wrap gap-4 text-xs text-gray-500\">\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-image-line text-blue-500\"></i>\n <span>{{ 'fileUpload.fileTypeImages' | transloco }}</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-pdf-line text-red-500\"></i>\n <span>PDF</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-excel-line text-green-500\"></i>\n <span>{{ 'fileUpload.fileTypeExcel' | transloco }}</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-word-line text-blue-600\"></i>\n <span>{{ 'fileUpload.fileTypeWord' | transloco }}</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-text-line text-gray-500\"></i>\n <span>{{ 'fileUpload.fileTypeText' | transloco }}</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-line text-gray-400\"></i>\n <span>{{ 'fileUpload.fileTypeOther' | transloco }}</span>\n </div>\n </div>\n }\n</div>\n", styles: [".file-upload__drag-over{border-color:#60a5fa;background-color:#eff6ff}.file-upload__disabled{border-color:#e5e7eb;background-color:#f9fafb;cursor:not-allowed}.file-upload__preview{transition:all .2s ease-in-out}.file-upload__preview:hover{transform:scale(1.05)}.file-upload__file-item{transition:all .2s ease-in-out}.file-upload__file-item:hover{background-color:#f3f4f6;border-color:#d1d5db}.file-upload__remove-btn{transition:all .2s ease-in-out}.file-upload__remove-btn:hover{background-color:#fef2f2}.file-upload__remove-btn:active{transform:scale(.95)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.file-upload__drag-active{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.file-upload__file-list{max-height:15rem;overflow-y:auto}.file-upload__file-list::-webkit-scrollbar{width:.5rem}.file-upload__file-list::-webkit-scrollbar-track{background-color:#f3f4f6;border-radius:9999px}.file-upload__file-list::-webkit-scrollbar-thumb{background-color:#d1d5db;border-radius:9999px}.file-upload__file-list::-webkit-scrollbar-thumb:hover{background-color:#9ca3af}.file-type-icon--image{color:#3b82f6}.file-type-icon--pdf{color:#ef4444}.file-type-icon--excel{color:#10b981}.file-type-icon--word{color:#2563eb}.file-type-icon--text{color:#6b7280}.file-type-icon--default{color:#9ca3af}@media(max-width:640px){.file-upload__file-item{padding:.5rem}.file-upload__file-info{font-size:.75rem}.file-upload__preview{width:2rem;height:2rem}}@media(prefers-color-scheme:dark){.file-upload__file-item{background-color:#1f2937;border-color:#374151}.file-upload__file-item:hover{background-color:#111827;border-color:#4b5563}.file-upload__file-info{color:#d1d5db}.file-upload__file-name{color:#f3f4f6}.file-upload__file-size{color:#9ca3af}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: FileUploadPreviewComponent, selector: "file-upload-preview", inputs: ["file"], outputs: ["remove"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
|
|
2788
|
+
}
|
|
2789
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FileUploadComponent, decorators: [{
|
|
2790
|
+
type: Component,
|
|
2791
|
+
args: [{ selector: 'file-upload', standalone: true, imports: [
|
|
2792
|
+
FormsModule,
|
|
2793
|
+
CommonModule,
|
|
2794
|
+
ReactiveFormsModule,
|
|
2795
|
+
TranslocoModule,
|
|
2796
|
+
FileUploadPreviewComponent,
|
|
2797
|
+
], template: "<div [class]=\"fieldGroupClasses\">\n @if (label) {\n <label [for]=\"inputId\" class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <!-- Upload Area -->\n <div\n class=\"relative\"\n (drop)=\"onDrop($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n >\n <div [class]=\"uploadAreaClasses\" (click)=\"!disabled && triggerFileInput()\">\n <input\n [id]=\"inputId\"\n [name]=\"name\"\n type=\"file\"\n [accept]=\"accept\"\n [multiple]=\"config.multiple\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n (change)=\"onFileSelect($event)\"\n (blur)=\"onTouched()\"\n class=\"hidden\"\n />\n\n <div class=\"flex flex-col items-center space-y-2\">\n <i class=\"ri-upload-cloud-2-line text-3xl text-gray-400\"></i>\n <div class=\"text-sm text-gray-600\">\n <p class=\"font-medium\">\n @if (config.multiple) {\n {{ 'fileUpload.dropMultiple' | transloco }}\n } @else {\n {{ 'fileUpload.dropSingle' | transloco }}\n }\n </p>\n <p class=\"text-xs text-gray-500 mt-1\">\n @if (config.allowedExtensions && config.allowedExtensions.length > 0) {\n {{ 'fileUpload.allowedExtensions' | transloco }}\n {{ config.allowedExtensions.join(', ') }}\n }\n @if (config.maxFileSize) {\n \u2022 {{ 'fileUpload.maxSize' | transloco }} {{ formatFileSize(config.maxFileSize) }}\n }\n </p>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Files Preview -->\n @if (files.length > 0) {\n <div class=\"flex flex-col gap-2 mt-4\">\n @for (file of files; track file; let i = $index) {\n <file-upload-preview [file]=\"file\" (remove)=\"removeFile(i)\" />\n }\n </div>\n }\n\n <!-- Validation Error -->\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n\n <!-- File Type Legend -->\n @if (files.length === 0) {\n <div class=\"mt-3 flex flex-wrap gap-4 text-xs text-gray-500\">\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-image-line text-blue-500\"></i>\n <span>{{ 'fileUpload.fileTypeImages' | transloco }}</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-pdf-line text-red-500\"></i>\n <span>PDF</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-excel-line text-green-500\"></i>\n <span>{{ 'fileUpload.fileTypeExcel' | transloco }}</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-word-line text-blue-600\"></i>\n <span>{{ 'fileUpload.fileTypeWord' | transloco }}</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-text-line text-gray-500\"></i>\n <span>{{ 'fileUpload.fileTypeText' | transloco }}</span>\n </div>\n <div class=\"flex items-center space-x-1\">\n <i class=\"ri-file-line text-gray-400\"></i>\n <span>{{ 'fileUpload.fileTypeOther' | transloco }}</span>\n </div>\n </div>\n }\n</div>\n", styles: [".file-upload__drag-over{border-color:#60a5fa;background-color:#eff6ff}.file-upload__disabled{border-color:#e5e7eb;background-color:#f9fafb;cursor:not-allowed}.file-upload__preview{transition:all .2s ease-in-out}.file-upload__preview:hover{transform:scale(1.05)}.file-upload__file-item{transition:all .2s ease-in-out}.file-upload__file-item:hover{background-color:#f3f4f6;border-color:#d1d5db}.file-upload__remove-btn{transition:all .2s ease-in-out}.file-upload__remove-btn:hover{background-color:#fef2f2}.file-upload__remove-btn:active{transform:scale(.95)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.file-upload__drag-active{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.file-upload__file-list{max-height:15rem;overflow-y:auto}.file-upload__file-list::-webkit-scrollbar{width:.5rem}.file-upload__file-list::-webkit-scrollbar-track{background-color:#f3f4f6;border-radius:9999px}.file-upload__file-list::-webkit-scrollbar-thumb{background-color:#d1d5db;border-radius:9999px}.file-upload__file-list::-webkit-scrollbar-thumb:hover{background-color:#9ca3af}.file-type-icon--image{color:#3b82f6}.file-type-icon--pdf{color:#ef4444}.file-type-icon--excel{color:#10b981}.file-type-icon--word{color:#2563eb}.file-type-icon--text{color:#6b7280}.file-type-icon--default{color:#9ca3af}@media(max-width:640px){.file-upload__file-item{padding:.5rem}.file-upload__file-info{font-size:.75rem}.file-upload__preview{width:2rem;height:2rem}}@media(prefers-color-scheme:dark){.file-upload__file-item{background-color:#1f2937;border-color:#374151}.file-upload__file-item:hover{background-color:#111827;border-color:#4b5563}.file-upload__file-info{color:#d1d5db}.file-upload__file-name{color:#f3f4f6}.file-upload__file-size{color:#9ca3af}}\n"] }]
|
|
2798
|
+
}], ctorParameters: () => [{ type: i1$1.NgControl, decorators: [{
|
|
2799
|
+
type: Self
|
|
2800
|
+
}, {
|
|
2801
|
+
type: Optional
|
|
2802
|
+
}] }, { type: i2.TranslocoService }], propDecorators: { label: [{
|
|
2803
|
+
type: Input
|
|
2804
|
+
}], name: [{
|
|
2805
|
+
type: Input
|
|
2806
|
+
}], id: [{
|
|
2807
|
+
type: Input
|
|
2808
|
+
}], required: [{
|
|
2809
|
+
type: Input
|
|
2810
|
+
}], readonly: [{
|
|
2811
|
+
type: Input
|
|
2812
|
+
}], fieldGroupClass: [{
|
|
2813
|
+
type: Input
|
|
2814
|
+
}], config: [{
|
|
2815
|
+
type: Input
|
|
2816
|
+
}], accept: [{
|
|
2817
|
+
type: Input
|
|
2818
|
+
}], fileSelected: [{
|
|
2819
|
+
type: Output
|
|
2820
|
+
}], fileRemoved: [{
|
|
2821
|
+
type: Output
|
|
2822
|
+
}], validationError: [{
|
|
2823
|
+
type: Output
|
|
2824
|
+
}] } });
|
|
2825
|
+
|
|
2826
|
+
class AsyncSelectComponent {
|
|
2827
|
+
config;
|
|
2828
|
+
items = [];
|
|
2829
|
+
parentId;
|
|
2830
|
+
label = '';
|
|
2831
|
+
placeholder = 'Seleccione...';
|
|
2832
|
+
name = '';
|
|
2833
|
+
required = false;
|
|
2834
|
+
multiple = false;
|
|
2835
|
+
clearable = true;
|
|
2836
|
+
searchable = true;
|
|
2837
|
+
loading = false;
|
|
2838
|
+
virtualScroll = false;
|
|
2839
|
+
notFoundText = 'No se encontraron resultados';
|
|
2840
|
+
bindLabel = 'label';
|
|
2841
|
+
bindValue = 'value';
|
|
2842
|
+
value = null;
|
|
2843
|
+
onChange = () => { };
|
|
2844
|
+
onTouched = () => { };
|
|
2845
|
+
displayItems = [];
|
|
2846
|
+
loadingSignal = signal(false, ...(ngDevMode ? [{ debugName: "loadingSignal" }] : []));
|
|
2847
|
+
searchTerm$ = new Subject();
|
|
2848
|
+
destroy$ = new Subject();
|
|
2849
|
+
injector = inject(Injector);
|
|
2850
|
+
_ngControl = null;
|
|
2851
|
+
constructor() { }
|
|
2852
|
+
get ngControl() {
|
|
2853
|
+
if (!this._ngControl) {
|
|
2854
|
+
this._ngControl = this.injector.get(NgControl, null);
|
|
2855
|
+
}
|
|
2856
|
+
return this._ngControl;
|
|
2857
|
+
}
|
|
2858
|
+
ngOnInit() {
|
|
2859
|
+
this.setupSearch();
|
|
2860
|
+
if (this.config) {
|
|
2861
|
+
this.loadAndMap();
|
|
2862
|
+
}
|
|
2863
|
+
else {
|
|
2864
|
+
this.displayItems = this.items;
|
|
2865
|
+
this.searchMode();
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
ngOnChanges(changes) {
|
|
2869
|
+
if (changes['parentId'] && !changes['parentId'].firstChange) {
|
|
2870
|
+
this.handleParentIdChange();
|
|
2871
|
+
}
|
|
2872
|
+
if (changes['items'] && !changes['items'].firstChange && !this.config) {
|
|
2873
|
+
this.displayItems = this.items;
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
ngOnDestroy() {
|
|
2877
|
+
this.destroy$.next();
|
|
2878
|
+
this.destroy$.complete();
|
|
2879
|
+
}
|
|
2880
|
+
setupSearch() {
|
|
2881
|
+
this.searchTerm$
|
|
2882
|
+
.pipe(debounceTime(400), distinctUntilChanged(), switchMap((term) => {
|
|
2883
|
+
if (this.config) {
|
|
2884
|
+
this.loadingSignal.set(true);
|
|
2885
|
+
return this.fetchData({ search: term });
|
|
2886
|
+
}
|
|
2887
|
+
return of(this.displayItems);
|
|
2888
|
+
}), takeUntil(this.destroy$))
|
|
2889
|
+
.subscribe((options) => {
|
|
2890
|
+
this.displayItems = options;
|
|
2891
|
+
this.loadingSignal.set(false);
|
|
2892
|
+
});
|
|
2893
|
+
}
|
|
2894
|
+
searchMode() {
|
|
2895
|
+
this.searchTerm$
|
|
2896
|
+
.pipe(debounceTime(400), distinctUntilChanged(), switchMap((term) => {
|
|
2897
|
+
this.loadingSignal.set(true);
|
|
2898
|
+
setTimeout(() => this.loadingSignal.set(false), 150);
|
|
2899
|
+
return of(this.items.filter((item) => item.label.toLowerCase().includes(term.toLowerCase())));
|
|
2900
|
+
}), takeUntil(this.destroy$))
|
|
2901
|
+
.subscribe((options) => {
|
|
2902
|
+
this.displayItems = options;
|
|
2903
|
+
});
|
|
2904
|
+
}
|
|
2905
|
+
loadAndMap(params) {
|
|
2906
|
+
if (!this.config)
|
|
2907
|
+
return;
|
|
2908
|
+
this.loadingSignal.set(true);
|
|
2909
|
+
this.fetchData(params)
|
|
2910
|
+
.pipe(takeUntil(this.destroy$))
|
|
2911
|
+
.subscribe((options) => {
|
|
2912
|
+
this.displayItems = options;
|
|
2913
|
+
this.loadingSignal.set(false);
|
|
2914
|
+
});
|
|
2915
|
+
}
|
|
2916
|
+
fetchData(params) {
|
|
2917
|
+
if (!this.config)
|
|
2918
|
+
return of([]);
|
|
2919
|
+
const mergedParams = { ...params };
|
|
2920
|
+
if (this.parentId != null && mergedParams.parentId == null) {
|
|
2921
|
+
mergedParams.parentId = this.parentId;
|
|
2922
|
+
}
|
|
2923
|
+
return this.config.load(mergedParams).pipe(map((res) => this.config.map(res)), catchError(() => of([])));
|
|
2924
|
+
}
|
|
2925
|
+
handleParentIdChange() {
|
|
2926
|
+
this.value = this.multiple ? [] : null;
|
|
2927
|
+
this.onChange(this.value);
|
|
2928
|
+
if (this.parentId != null && this.config) {
|
|
2929
|
+
this.loadAndMap({ parentId: this.parentId });
|
|
2930
|
+
}
|
|
2931
|
+
else if (this.config) {
|
|
2932
|
+
this.displayItems = [];
|
|
2933
|
+
this.loadingSignal.set(false);
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
onSearch(event) {
|
|
2937
|
+
const term = event?.term || '';
|
|
2938
|
+
this.searchTerm$.next(term);
|
|
2939
|
+
}
|
|
2940
|
+
onSelectChange(value) {
|
|
2941
|
+
this.value = value;
|
|
2942
|
+
this.onChange(value);
|
|
2943
|
+
this.onTouched();
|
|
2944
|
+
}
|
|
2945
|
+
get typeahead$() {
|
|
2946
|
+
return this.searchTerm$;
|
|
2947
|
+
}
|
|
2948
|
+
get showError() {
|
|
2949
|
+
if (!this.ngControl || !this.ngControl.control)
|
|
2950
|
+
return false;
|
|
2951
|
+
const control = this.ngControl.control;
|
|
2952
|
+
return control.invalid ? control.dirty || control.touched : false;
|
|
2953
|
+
}
|
|
2954
|
+
get errorMessage() {
|
|
2955
|
+
if (!this.ngControl?.errors)
|
|
2956
|
+
return '';
|
|
2957
|
+
const errorKey = Object.keys(this.ngControl.errors)[0];
|
|
2958
|
+
return 'Campo inválido';
|
|
2959
|
+
}
|
|
2960
|
+
writeValue(value) {
|
|
2961
|
+
this.value = value;
|
|
2962
|
+
}
|
|
2963
|
+
registerOnChange(fn) {
|
|
2964
|
+
this.onChange = fn;
|
|
2965
|
+
}
|
|
2966
|
+
registerOnTouched(fn) {
|
|
2967
|
+
this.onTouched = fn;
|
|
2968
|
+
}
|
|
2969
|
+
setDisabledState(isDisabled) {
|
|
2970
|
+
this.loading = isDisabled;
|
|
2971
|
+
}
|
|
2972
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AsyncSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2973
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: AsyncSelectComponent, isStandalone: true, selector: "async-select", inputs: { config: "config", items: "items", parentId: "parentId", label: "label", placeholder: "placeholder", name: "name", required: "required", multiple: "multiple", clearable: "clearable", searchable: "searchable", loading: "loading", virtualScroll: "virtualScroll", notFoundText: "notFoundText", bindLabel: "bindLabel", bindValue: "bindValue" }, providers: [
|
|
2974
|
+
{
|
|
2975
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2976
|
+
useExisting: forwardRef(() => AsyncSelectComponent),
|
|
2977
|
+
multi: true,
|
|
2978
|
+
},
|
|
2979
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"w-full\">\n @if (label) {\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <ng-select\n [items]=\"displayItems\"\n [multiple]=\"multiple\"\n [searchable]=\"searchable\"\n [clearable]=\"clearable\"\n [placeholder]=\"placeholder\"\n [loading]=\"loading || loadingSignal()\"\n [virtualScroll]=\"virtualScroll\"\n [notFoundText]=\"notFoundText\"\n [bindLabel]=\"bindLabel\"\n [bindValue]=\"bindValue\"\n [ngModel]=\"value\"\n [typeahead]=\"typeahead$\"\n [closeOnSelect]=\"!multiple\"\n (ngModelChange)=\"onSelectChange($event)\"\n (blur)=\"onTouched()\"\n (search)=\"onSearch($event)\"\n />\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: NgSelectModule }, { kind: "component", type: i2$1.NgSelectComponent, selector: "ng-select", inputs: ["ariaLabelDropdown", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "dropdownPosition", "appendTo", "outsideClickEvent", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "tabFocusOnClearButton", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "deselectOnClick", "clearSearchOnAdd", "compareWith", "keyDownFn", "bindLabel", "bindValue", "appearance", "isOpen", "items"], outputs: ["bindLabelChange", "bindValueChange", "appearanceChange", "isOpenChange", "itemsChange", "blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"], exportAs: ["ngSelect"] }] });
|
|
2980
|
+
}
|
|
2981
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AsyncSelectComponent, decorators: [{
|
|
2982
|
+
type: Component,
|
|
2983
|
+
args: [{ selector: 'async-select', standalone: true, imports: [CommonModule, FormsModule, NgSelectModule], providers: [
|
|
2984
|
+
{
|
|
2985
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2986
|
+
useExisting: forwardRef(() => AsyncSelectComponent),
|
|
2987
|
+
multi: true,
|
|
2988
|
+
},
|
|
2989
|
+
], template: "<div class=\"w-full\">\n @if (label) {\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n @if (required) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <ng-select\n [items]=\"displayItems\"\n [multiple]=\"multiple\"\n [searchable]=\"searchable\"\n [clearable]=\"clearable\"\n [placeholder]=\"placeholder\"\n [loading]=\"loading || loadingSignal()\"\n [virtualScroll]=\"virtualScroll\"\n [notFoundText]=\"notFoundText\"\n [bindLabel]=\"bindLabel\"\n [bindValue]=\"bindValue\"\n [ngModel]=\"value\"\n [typeahead]=\"typeahead$\"\n [closeOnSelect]=\"!multiple\"\n (ngModelChange)=\"onSelectChange($event)\"\n (blur)=\"onTouched()\"\n (search)=\"onSearch($event)\"\n />\n\n @if (showError) {\n <div class=\"text-red-500 text-xs mt-1\">\n {{ errorMessage }}\n </div>\n }\n</div>\n" }]
|
|
2990
|
+
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
2991
|
+
type: Input
|
|
2992
|
+
}], items: [{
|
|
2993
|
+
type: Input
|
|
2994
|
+
}], parentId: [{
|
|
2995
|
+
type: Input
|
|
2996
|
+
}], label: [{
|
|
2997
|
+
type: Input
|
|
2998
|
+
}], placeholder: [{
|
|
2999
|
+
type: Input
|
|
3000
|
+
}], name: [{
|
|
3001
|
+
type: Input
|
|
3002
|
+
}], required: [{
|
|
3003
|
+
type: Input
|
|
3004
|
+
}], multiple: [{
|
|
3005
|
+
type: Input
|
|
3006
|
+
}], clearable: [{
|
|
3007
|
+
type: Input
|
|
3008
|
+
}], searchable: [{
|
|
3009
|
+
type: Input
|
|
3010
|
+
}], loading: [{
|
|
3011
|
+
type: Input
|
|
3012
|
+
}], virtualScroll: [{
|
|
3013
|
+
type: Input
|
|
3014
|
+
}], notFoundText: [{
|
|
3015
|
+
type: Input
|
|
3016
|
+
}], bindLabel: [{
|
|
3017
|
+
type: Input
|
|
3018
|
+
}], bindValue: [{
|
|
3019
|
+
type: Input
|
|
3020
|
+
}] } });
|
|
3021
|
+
|
|
3022
|
+
class ChangePasswordFormComponent {
|
|
3023
|
+
fb;
|
|
3024
|
+
changePasswordFormService;
|
|
3025
|
+
customerService;
|
|
3026
|
+
adminService;
|
|
3027
|
+
toastService;
|
|
3028
|
+
transloco;
|
|
3029
|
+
changePasswordForm;
|
|
3030
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
3031
|
+
constructor(fb, changePasswordFormService, customerService, adminService, toastService, transloco) {
|
|
3032
|
+
this.fb = fb;
|
|
3033
|
+
this.changePasswordFormService = changePasswordFormService;
|
|
3034
|
+
this.customerService = customerService;
|
|
3035
|
+
this.adminService = adminService;
|
|
3036
|
+
this.toastService = toastService;
|
|
3037
|
+
this.transloco = transloco;
|
|
3038
|
+
this.changePasswordForm = this.fb.group({
|
|
3039
|
+
password: ['', [Validators.required, Validators.minLength(6)]],
|
|
3040
|
+
confirm_password: ['', [Validators.required, Validators.minLength(6)]],
|
|
3041
|
+
}, {
|
|
3042
|
+
validators: MustMatchValidator('password', 'confirm_password'),
|
|
3043
|
+
});
|
|
3044
|
+
}
|
|
3045
|
+
get isOpen() {
|
|
3046
|
+
return this.changePasswordFormService.modalIsOpen;
|
|
3047
|
+
}
|
|
3048
|
+
get resourceId() {
|
|
3049
|
+
return this.changePasswordFormService.resourceId;
|
|
3050
|
+
}
|
|
3051
|
+
onCloseModal() {
|
|
3052
|
+
this.changePasswordForm.reset();
|
|
3053
|
+
this.changePasswordFormService.close();
|
|
3054
|
+
}
|
|
3055
|
+
onConfirmDelete() {
|
|
3056
|
+
this.loading.set(true);
|
|
3057
|
+
const service = this.changePasswordFormService.isAdminMode()
|
|
3058
|
+
? this.adminService
|
|
3059
|
+
: this.customerService;
|
|
3060
|
+
const isAdmin = this.changePasswordFormService.isAdminMode();
|
|
3061
|
+
const successKey = isAdmin ? 'changePassword.adminSuccess' : 'changePassword.customerSuccess';
|
|
3062
|
+
const errorKey = isAdmin ? 'changePassword.adminError' : 'changePassword.customerError';
|
|
3063
|
+
service.updateOne(this.resourceId(), this.changePasswordForm.value).subscribe({
|
|
3064
|
+
next: () => {
|
|
3065
|
+
this.toastService.show(this.transloco.translate(successKey), 'success');
|
|
3066
|
+
this.changePasswordForm.reset();
|
|
3067
|
+
this.changePasswordFormService.close();
|
|
3068
|
+
this.loading.set(false);
|
|
3069
|
+
},
|
|
3070
|
+
error: (error) => {
|
|
3071
|
+
console.error('Error al actualizar contraseña:', error);
|
|
3072
|
+
this.toastService.show(this.transloco.translate(errorKey), 'error');
|
|
3073
|
+
this.loading.set(false);
|
|
3074
|
+
},
|
|
3075
|
+
});
|
|
3076
|
+
}
|
|
3077
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ChangePasswordFormComponent, deps: [{ token: i1$1.FormBuilder }, { token: ChangePasswordFormService }, { token: CustomerService }, { token: AdminService }, { token: ToastService }, { token: i2.TranslocoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3078
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: ChangePasswordFormComponent, isStandalone: true, selector: "change-password-form", providers: [AdminService, CustomerService], ngImport: i0, template: "@if (isOpen()) {\n <app-modal\n [title]=\"'changePassword.title' | transloco\"\n [isOpen]=\"isOpen\"\n (closeModal)=\"onCloseModal()\"\n >\n <form\n [formGroup]=\"changePasswordForm\"\n method=\"POST\"\n class=\"flex flex-col gap-4\"\n (ngSubmit)=\"onConfirmDelete()\"\n >\n <form-input\n [label]=\"'changePassword.newPasswordLabel' | transloco\"\n [placeholder]=\"'changePassword.newPasswordPlaceholder' | transloco\"\n name=\"password\"\n type=\"password\"\n class=\"flex-1\"\n [required]=\"true\"\n [autocomplete]=\"false\"\n formControlName=\"password\"\n />\n\n <form-input\n [label]=\"'changePassword.confirmPasswordLabel' | transloco\"\n [placeholder]=\"'changePassword.confirmPasswordPlaceholder' | transloco\"\n name=\"confirm_password\"\n type=\"password\"\n class=\"flex-1\"\n [required]=\"true\"\n [autocomplete]=\"false\"\n formControlName=\"confirm_password\"\n />\n\n <div class=\"flex space-x-3\">\n <app-button\n variant=\"terciary\"\n [text]=\"'changePassword.cancel' | transloco\"\n (click)=\"onCloseModal()\"\n size=\"sm\"\n />\n\n <app-button\n [disabled]=\"loading() || changePasswordForm.invalid || changePasswordForm.pristine\"\n [loading]=\"loading()\"\n type=\"submit\"\n variant=\"primary\"\n [text]=\"'changePassword.save' | transloco\"\n [loadingText]=\"'changePassword.saving' | transloco\"\n size=\"sm\"\n />\n </div>\n </form>\n </app-modal>\n}\n", styles: [".delete-confirmation-modal{animation:fadeIn .3s ease-out}.delete-confirmation-content{animation:slideUp .3s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.confirmation-input{transition:all .2s ease}.confirmation-input:focus{box-shadow:0 0 0 3px #ef44441a}.confirmation-input.invalid{border-color:#dc2626}.confirmation-input.invalid:focus{border-color:#dc2626;box-shadow:0 0 0 3px #dc26261a}.delete-button{transition:all .2s ease}.delete-button:disabled{opacity:.5;cursor:not-allowed}.delete-button:not(:disabled):hover{transform:translateY(-1px);box-shadow:0 4px 12px #dc26264d}.warning-message{border-left:4px solid #f59e0b;background:linear-gradient(135deg,#fef3c7,#fde68a)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: AppButtonComponent, selector: "app-button", inputs: ["disabled", "loading", "type", "variant", "text", "size", "loadingText", "icon"], outputs: ["clicked"] }, { kind: "component", type: FormInputComponent, selector: "form-input", inputs: ["label", "type", "name", "id", "placeholder", "required", "readonly", "minlength", "min", "step", "pattern", "fieldGroupClass", "autocomplete"] }, { kind: "component", type: AppModalComponent, selector: "app-modal", inputs: ["title", "disableClose", "isOpen", "size"], outputs: ["closeModal"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], encapsulation: i0.ViewEncapsulation.None });
|
|
3079
|
+
}
|
|
3080
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ChangePasswordFormComponent, decorators: [{
|
|
3081
|
+
type: Component,
|
|
3082
|
+
args: [{ selector: 'change-password-form', standalone: true, imports: [
|
|
3083
|
+
CommonModule,
|
|
3084
|
+
ReactiveFormsModule,
|
|
3085
|
+
TranslocoModule,
|
|
3086
|
+
AppButtonComponent,
|
|
3087
|
+
FormInputComponent,
|
|
3088
|
+
AppModalComponent,
|
|
3089
|
+
], providers: [AdminService, CustomerService], encapsulation: ViewEncapsulation.None, template: "@if (isOpen()) {\n <app-modal\n [title]=\"'changePassword.title' | transloco\"\n [isOpen]=\"isOpen\"\n (closeModal)=\"onCloseModal()\"\n >\n <form\n [formGroup]=\"changePasswordForm\"\n method=\"POST\"\n class=\"flex flex-col gap-4\"\n (ngSubmit)=\"onConfirmDelete()\"\n >\n <form-input\n [label]=\"'changePassword.newPasswordLabel' | transloco\"\n [placeholder]=\"'changePassword.newPasswordPlaceholder' | transloco\"\n name=\"password\"\n type=\"password\"\n class=\"flex-1\"\n [required]=\"true\"\n [autocomplete]=\"false\"\n formControlName=\"password\"\n />\n\n <form-input\n [label]=\"'changePassword.confirmPasswordLabel' | transloco\"\n [placeholder]=\"'changePassword.confirmPasswordPlaceholder' | transloco\"\n name=\"confirm_password\"\n type=\"password\"\n class=\"flex-1\"\n [required]=\"true\"\n [autocomplete]=\"false\"\n formControlName=\"confirm_password\"\n />\n\n <div class=\"flex space-x-3\">\n <app-button\n variant=\"terciary\"\n [text]=\"'changePassword.cancel' | transloco\"\n (click)=\"onCloseModal()\"\n size=\"sm\"\n />\n\n <app-button\n [disabled]=\"loading() || changePasswordForm.invalid || changePasswordForm.pristine\"\n [loading]=\"loading()\"\n type=\"submit\"\n variant=\"primary\"\n [text]=\"'changePassword.save' | transloco\"\n [loadingText]=\"'changePassword.saving' | transloco\"\n size=\"sm\"\n />\n </div>\n </form>\n </app-modal>\n}\n", styles: [".delete-confirmation-modal{animation:fadeIn .3s ease-out}.delete-confirmation-content{animation:slideUp .3s ease-out}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.confirmation-input{transition:all .2s ease}.confirmation-input:focus{box-shadow:0 0 0 3px #ef44441a}.confirmation-input.invalid{border-color:#dc2626}.confirmation-input.invalid:focus{border-color:#dc2626;box-shadow:0 0 0 3px #dc26261a}.delete-button{transition:all .2s ease}.delete-button:disabled{opacity:.5;cursor:not-allowed}.delete-button:not(:disabled):hover{transform:translateY(-1px);box-shadow:0 4px 12px #dc26264d}.warning-message{border-left:4px solid #f59e0b;background:linear-gradient(135deg,#fef3c7,#fde68a)}\n"] }]
|
|
3090
|
+
}], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: ChangePasswordFormService }, { type: CustomerService }, { type: AdminService }, { type: ToastService }, { type: i2.TranslocoService }] });
|
|
3091
|
+
|
|
3092
|
+
class AdminSelectComponent {
|
|
3093
|
+
platformId;
|
|
3094
|
+
adminService;
|
|
3095
|
+
label = 'Equipo de trabajo';
|
|
3096
|
+
placeholder = 'Selecciona un equipo de trabajo';
|
|
3097
|
+
name = 'admin_id';
|
|
3098
|
+
required = false;
|
|
3099
|
+
readonly = false;
|
|
3100
|
+
showError = true;
|
|
3101
|
+
customClass = '';
|
|
3102
|
+
control = null;
|
|
3103
|
+
adminChange = new EventEmitter();
|
|
3104
|
+
admins = signal([], ...(ngDevMode ? [{ debugName: "admins" }] : []));
|
|
3105
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
3106
|
+
destroy$ = new Subject();
|
|
3107
|
+
// ControlValueAccessor properties
|
|
3108
|
+
value = null;
|
|
3109
|
+
onChange = () => { };
|
|
3110
|
+
onTouched = () => { };
|
|
3111
|
+
constructor(platformId, adminService) {
|
|
3112
|
+
this.platformId = platformId;
|
|
3113
|
+
this.adminService = adminService;
|
|
3114
|
+
}
|
|
3115
|
+
ngOnInit() {
|
|
3116
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
3117
|
+
this.loadAdmins();
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
// Update the formControl getter to handle the AbstractControl
|
|
3121
|
+
get formControl() {
|
|
3122
|
+
return this.control;
|
|
3123
|
+
}
|
|
3124
|
+
ngOnDestroy() {
|
|
3125
|
+
this.destroy$.next();
|
|
3126
|
+
this.destroy$.complete();
|
|
3127
|
+
}
|
|
3128
|
+
loadAdmins() {
|
|
3129
|
+
this.loading.set(true);
|
|
3130
|
+
this.adminService
|
|
3131
|
+
.fetchAdmins()
|
|
3132
|
+
.pipe(takeUntil(this.destroy$))
|
|
3133
|
+
.subscribe({
|
|
3134
|
+
next: ({ data: { admins } }) => {
|
|
3135
|
+
this.admins.set(admins?.map((admin) => ({
|
|
3136
|
+
value: admin.id,
|
|
3137
|
+
label: `${admin.first_name} ${admin.last_name} - ${admin.email}`,
|
|
3138
|
+
})) || []);
|
|
3139
|
+
this.loading.set(false);
|
|
3140
|
+
},
|
|
3141
|
+
error: () => {
|
|
3142
|
+
this.admins.set([]);
|
|
3143
|
+
this.loading.set(false);
|
|
3144
|
+
},
|
|
3145
|
+
});
|
|
3146
|
+
}
|
|
3147
|
+
// In admin-select.component.ts
|
|
3148
|
+
onAdminSelected(event) {
|
|
3149
|
+
const select = event.target;
|
|
3150
|
+
const value = select.value ? Number(select.value) : null;
|
|
3151
|
+
// Update the local value
|
|
3152
|
+
this.value = value;
|
|
3153
|
+
// Update the form control if it exists
|
|
3154
|
+
if (this.control) {
|
|
3155
|
+
this.control.setValue(value);
|
|
3156
|
+
this.control.markAsTouched();
|
|
3157
|
+
}
|
|
3158
|
+
// Emit the change event
|
|
3159
|
+
this.adminChange.emit(value);
|
|
3160
|
+
}
|
|
3161
|
+
// ControlValueAccessor methods
|
|
3162
|
+
writeValue(value) {
|
|
3163
|
+
this.value = value;
|
|
3164
|
+
}
|
|
3165
|
+
registerOnChange(fn) {
|
|
3166
|
+
this.onChange = fn;
|
|
3167
|
+
}
|
|
3168
|
+
registerOnTouched(fn) {
|
|
3169
|
+
this.onTouched = fn;
|
|
3170
|
+
}
|
|
3171
|
+
// Validator method
|
|
3172
|
+
validate(control) {
|
|
3173
|
+
if (this.required && !control.value) {
|
|
3174
|
+
return { required: true };
|
|
3175
|
+
}
|
|
3176
|
+
return null;
|
|
3177
|
+
}
|
|
3178
|
+
// Helper method to check if control is invalid
|
|
3179
|
+
get isInvalid() {
|
|
3180
|
+
return false;
|
|
3181
|
+
}
|
|
3182
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdminSelectComponent, deps: [{ token: PLATFORM_ID }, { token: AdminService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3183
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: AdminSelectComponent, isStandalone: true, selector: "admin-select", inputs: { label: "label", placeholder: "placeholder", name: "name", required: "required", readonly: "readonly", showError: "showError", customClass: "customClass", control: "control" }, outputs: { adminChange: "adminChange" }, ngImport: i0, template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'country_id'\"\n [class]=\"customClass\"\n [options]=\"admins()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onAdminSelected($event)\"\n/>\n", styles: [":host{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FormSelectComponent, selector: "form-select", inputs: ["label", "name", "id", "placeholder", "required", "disabled", "readonly", "options", "fieldGroupClass", "showDefaultOption", "defaultOptionLabel"] }] });
|
|
3184
|
+
}
|
|
3185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: AdminSelectComponent, decorators: [{
|
|
3186
|
+
type: Component,
|
|
3187
|
+
args: [{ selector: 'admin-select', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormSelectComponent], template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'country_id'\"\n [class]=\"customClass\"\n [options]=\"admins()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onAdminSelected($event)\"\n/>\n", styles: [":host{display:block;width:100%}\n"] }]
|
|
3188
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
3189
|
+
type: Inject,
|
|
3190
|
+
args: [PLATFORM_ID]
|
|
3191
|
+
}] }, { type: AdminService }], propDecorators: { label: [{
|
|
3192
|
+
type: Input
|
|
3193
|
+
}], placeholder: [{
|
|
3194
|
+
type: Input
|
|
3195
|
+
}], name: [{
|
|
3196
|
+
type: Input
|
|
3197
|
+
}], required: [{
|
|
3198
|
+
type: Input
|
|
3199
|
+
}], readonly: [{
|
|
3200
|
+
type: Input
|
|
3201
|
+
}], showError: [{
|
|
3202
|
+
type: Input
|
|
3203
|
+
}], customClass: [{
|
|
3204
|
+
type: Input
|
|
3205
|
+
}], control: [{
|
|
3206
|
+
type: Input
|
|
3207
|
+
}], adminChange: [{
|
|
3208
|
+
type: Output
|
|
3209
|
+
}] } });
|
|
3210
|
+
|
|
3211
|
+
class CitySelectComponent {
|
|
3212
|
+
citiesService;
|
|
3213
|
+
label = 'Ciudad';
|
|
3214
|
+
name = 'city_id';
|
|
3215
|
+
placeholder = 'Selecciona una ciudad';
|
|
3216
|
+
required = false;
|
|
3217
|
+
disabled = false;
|
|
3218
|
+
readonly = false;
|
|
3219
|
+
stateId = null;
|
|
3220
|
+
showError = true;
|
|
3221
|
+
customClass = '';
|
|
3222
|
+
control = null;
|
|
3223
|
+
cityChange = new EventEmitter();
|
|
3224
|
+
cities = signal([], ...(ngDevMode ? [{ debugName: "cities" }] : []));
|
|
3225
|
+
loading = false;
|
|
3226
|
+
destroy$ = new Subject();
|
|
3227
|
+
// ControlValueAccessor properties
|
|
3228
|
+
value = null;
|
|
3229
|
+
onChange = () => { };
|
|
3230
|
+
onTouched = () => { };
|
|
3231
|
+
constructor(citiesService) {
|
|
3232
|
+
this.citiesService = citiesService;
|
|
3233
|
+
}
|
|
3234
|
+
// Update the formControl getter to handle the AbstractControl
|
|
3235
|
+
get formControl() {
|
|
3236
|
+
return this.control;
|
|
3237
|
+
}
|
|
3238
|
+
ngOnInit() {
|
|
3239
|
+
this.loadCities();
|
|
3240
|
+
}
|
|
3241
|
+
ngOnChanges(changes) {
|
|
3242
|
+
if (changes['stateId'] && !changes['stateId'].firstChange) {
|
|
3243
|
+
this.value = null;
|
|
3244
|
+
this.onChange(null);
|
|
3245
|
+
this.cityChange.emit(null);
|
|
3246
|
+
if (this.stateId) {
|
|
3247
|
+
this.loadCities();
|
|
3248
|
+
}
|
|
3249
|
+
else {
|
|
3250
|
+
this.cities.set([]);
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
}
|
|
3254
|
+
ngOnDestroy() {
|
|
3255
|
+
this.destroy$.next();
|
|
3256
|
+
this.destroy$.complete();
|
|
3257
|
+
}
|
|
3258
|
+
loadCities() {
|
|
3259
|
+
this.loading = true;
|
|
3260
|
+
this.citiesService
|
|
3261
|
+
.fetchCities({ stateId: this.stateId ?? undefined })
|
|
3262
|
+
.pipe(takeUntil(this.destroy$))
|
|
3263
|
+
.subscribe({
|
|
3264
|
+
next: (response) => {
|
|
3265
|
+
this.cities.set(formatCitiesResponseToSelect(response));
|
|
3266
|
+
this.loading = false;
|
|
3267
|
+
},
|
|
3268
|
+
error: () => {
|
|
3269
|
+
this.cities.set([]);
|
|
3270
|
+
this.loading = false;
|
|
3271
|
+
},
|
|
3272
|
+
});
|
|
3273
|
+
}
|
|
3274
|
+
onCitySelected(event) {
|
|
3275
|
+
const select = event.target;
|
|
3276
|
+
const value = select.value ? Number(select.value) : null;
|
|
3277
|
+
this.value = value;
|
|
3278
|
+
this.onChange(value);
|
|
3279
|
+
this.onTouched();
|
|
3280
|
+
this.cityChange.emit(value);
|
|
3281
|
+
}
|
|
3282
|
+
// ControlValueAccessor methods
|
|
3283
|
+
writeValue(value) {
|
|
3284
|
+
this.value = value;
|
|
3285
|
+
}
|
|
3286
|
+
registerOnChange(fn) {
|
|
3287
|
+
this.onChange = fn;
|
|
3288
|
+
}
|
|
3289
|
+
registerOnTouched(fn) {
|
|
3290
|
+
this.onTouched = fn;
|
|
3291
|
+
}
|
|
3292
|
+
setDisabledState(isDisabled) {
|
|
3293
|
+
this.disabled = isDisabled;
|
|
3294
|
+
}
|
|
3295
|
+
// Validator method
|
|
3296
|
+
validate(control) {
|
|
3297
|
+
if (this.required && !control.value) {
|
|
3298
|
+
return { required: true };
|
|
3299
|
+
}
|
|
3300
|
+
return null;
|
|
3301
|
+
}
|
|
3302
|
+
get isInvalid() {
|
|
3303
|
+
return false;
|
|
3304
|
+
}
|
|
3305
|
+
get isDisabled() {
|
|
3306
|
+
return this.disabled || this.readonly || !this.stateId || this.loading;
|
|
3307
|
+
}
|
|
3308
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CitySelectComponent, deps: [{ token: CitiesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3309
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: CitySelectComponent, isStandalone: true, selector: "city-select", inputs: { label: "label", name: "name", placeholder: "placeholder", required: "required", disabled: "disabled", readonly: "readonly", stateId: "stateId", showError: "showError", customClass: "customClass", control: "control" }, outputs: { cityChange: "cityChange" }, providers: [
|
|
3310
|
+
{
|
|
3311
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3312
|
+
useExisting: forwardRef(() => CitySelectComponent),
|
|
3313
|
+
multi: true,
|
|
3314
|
+
},
|
|
3315
|
+
{
|
|
3316
|
+
provide: NG_VALIDATORS,
|
|
3317
|
+
useExisting: forwardRef(() => CitySelectComponent),
|
|
3318
|
+
multi: true,
|
|
3319
|
+
},
|
|
3320
|
+
], usesOnChanges: true, ngImport: i0, template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name\"\n [class]=\"customClass\"\n [required]=\"required\"\n [options]=\"cities()\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onCitySelected($event)\"\n/>\n", styles: [":host{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FormSelectComponent, selector: "form-select", inputs: ["label", "name", "id", "placeholder", "required", "disabled", "readonly", "options", "fieldGroupClass", "showDefaultOption", "defaultOptionLabel"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
3321
|
+
}
|
|
3322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CitySelectComponent, decorators: [{
|
|
3323
|
+
type: Component,
|
|
3324
|
+
args: [{ selector: 'city-select', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormSelectComponent], encapsulation: ViewEncapsulation.None, providers: [
|
|
3325
|
+
{
|
|
3326
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3327
|
+
useExisting: forwardRef(() => CitySelectComponent),
|
|
3328
|
+
multi: true,
|
|
3329
|
+
},
|
|
3330
|
+
{
|
|
3331
|
+
provide: NG_VALIDATORS,
|
|
3332
|
+
useExisting: forwardRef(() => CitySelectComponent),
|
|
3333
|
+
multi: true,
|
|
3334
|
+
},
|
|
3335
|
+
], template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name\"\n [class]=\"customClass\"\n [required]=\"required\"\n [options]=\"cities()\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onCitySelected($event)\"\n/>\n", styles: [":host{display:block;width:100%}\n"] }]
|
|
3336
|
+
}], ctorParameters: () => [{ type: CitiesService }], propDecorators: { label: [{
|
|
3337
|
+
type: Input
|
|
3338
|
+
}], name: [{
|
|
3339
|
+
type: Input
|
|
3340
|
+
}], placeholder: [{
|
|
3341
|
+
type: Input
|
|
3342
|
+
}], required: [{
|
|
3343
|
+
type: Input
|
|
3344
|
+
}], disabled: [{
|
|
3345
|
+
type: Input
|
|
3346
|
+
}], readonly: [{
|
|
3347
|
+
type: Input
|
|
3348
|
+
}], stateId: [{
|
|
3349
|
+
type: Input
|
|
3350
|
+
}], showError: [{
|
|
3351
|
+
type: Input
|
|
3352
|
+
}], customClass: [{
|
|
3353
|
+
type: Input
|
|
3354
|
+
}], control: [{
|
|
3355
|
+
type: Input
|
|
3356
|
+
}], cityChange: [{
|
|
3357
|
+
type: Output
|
|
3358
|
+
}] } });
|
|
3359
|
+
|
|
3360
|
+
class CountrySelectComponent {
|
|
3361
|
+
platformId;
|
|
3362
|
+
countryService;
|
|
3363
|
+
label = 'País';
|
|
3364
|
+
placeholder = 'Selecciona un país';
|
|
3365
|
+
name = 'country_id';
|
|
3366
|
+
required = false;
|
|
3367
|
+
readonly = false;
|
|
3368
|
+
showError = true;
|
|
3369
|
+
customClass = '';
|
|
3370
|
+
control = null;
|
|
3371
|
+
countryChange = new EventEmitter();
|
|
3372
|
+
countries = signal([], ...(ngDevMode ? [{ debugName: "countries" }] : []));
|
|
3373
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
3374
|
+
destroy$ = new Subject();
|
|
3375
|
+
// ControlValueAccessor properties
|
|
3376
|
+
value = null;
|
|
3377
|
+
onChange = () => { };
|
|
3378
|
+
onTouched = () => { };
|
|
3379
|
+
constructor(platformId, countryService) {
|
|
3380
|
+
this.platformId = platformId;
|
|
3381
|
+
this.countryService = countryService;
|
|
3382
|
+
}
|
|
3383
|
+
ngOnInit() {
|
|
3384
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
3385
|
+
this.loadCountries();
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
// Update the formControl getter to handle the AbstractControl
|
|
3389
|
+
get formControl() {
|
|
3390
|
+
return this.control;
|
|
3391
|
+
}
|
|
3392
|
+
ngOnDestroy() {
|
|
3393
|
+
this.destroy$.next();
|
|
3394
|
+
this.destroy$.complete();
|
|
3395
|
+
}
|
|
3396
|
+
loadCountries() {
|
|
3397
|
+
this.loading.set(true);
|
|
3398
|
+
this.countryService
|
|
3399
|
+
.fetchCountries()
|
|
3400
|
+
.pipe(takeUntil(this.destroy$))
|
|
3401
|
+
.subscribe({
|
|
3402
|
+
next: ({ data: { countries } }) => {
|
|
3403
|
+
this.countries.set(countries?.map((country) => ({
|
|
3404
|
+
value: country.id,
|
|
3405
|
+
label: country.name,
|
|
3406
|
+
})) || []);
|
|
3407
|
+
this.loading.set(false);
|
|
3408
|
+
},
|
|
3409
|
+
error: () => {
|
|
3410
|
+
this.countries.set([]);
|
|
3411
|
+
this.loading.set(false);
|
|
3412
|
+
},
|
|
3413
|
+
});
|
|
3414
|
+
}
|
|
3415
|
+
// In country-select.component.ts
|
|
3416
|
+
onCountrySelected(event) {
|
|
3417
|
+
const select = event.target;
|
|
3418
|
+
const value = select.value ? Number(select.value) : null;
|
|
3419
|
+
// Update the local value
|
|
3420
|
+
this.value = value;
|
|
3421
|
+
// Update the form control if it exists
|
|
3422
|
+
if (this.control) {
|
|
3423
|
+
this.control.setValue(value);
|
|
3424
|
+
this.control.markAsTouched();
|
|
3425
|
+
}
|
|
3426
|
+
// Emit the change event
|
|
3427
|
+
this.countryChange.emit(value);
|
|
3428
|
+
}
|
|
3429
|
+
// ControlValueAccessor methods
|
|
3430
|
+
writeValue(value) {
|
|
3431
|
+
this.value = value;
|
|
3432
|
+
}
|
|
3433
|
+
registerOnChange(fn) {
|
|
3434
|
+
this.onChange = fn;
|
|
3435
|
+
}
|
|
3436
|
+
registerOnTouched(fn) {
|
|
3437
|
+
this.onTouched = fn;
|
|
3438
|
+
}
|
|
3439
|
+
// Validator method
|
|
3440
|
+
validate(control) {
|
|
3441
|
+
if (this.required && !control.value) {
|
|
3442
|
+
return { required: true };
|
|
3443
|
+
}
|
|
3444
|
+
return null;
|
|
3445
|
+
}
|
|
3446
|
+
// Helper method to check if control is invalid
|
|
3447
|
+
get isInvalid() {
|
|
3448
|
+
return false;
|
|
3449
|
+
}
|
|
3450
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CountrySelectComponent, deps: [{ token: PLATFORM_ID }, { token: CountryService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3451
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: CountrySelectComponent, isStandalone: true, selector: "country-select", inputs: { label: "label", placeholder: "placeholder", name: "name", required: "required", readonly: "readonly", showError: "showError", customClass: "customClass", control: "control" }, outputs: { countryChange: "countryChange" }, ngImport: i0, template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'country_id'\"\n [class]=\"customClass\"\n [options]=\"countries()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onCountrySelected($event)\"\n></form-select>\n", styles: [":host{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FormSelectComponent, selector: "form-select", inputs: ["label", "name", "id", "placeholder", "required", "disabled", "readonly", "options", "fieldGroupClass", "showDefaultOption", "defaultOptionLabel"] }] });
|
|
3452
|
+
}
|
|
3453
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CountrySelectComponent, decorators: [{
|
|
3454
|
+
type: Component,
|
|
3455
|
+
args: [{ selector: 'country-select', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormSelectComponent], template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'country_id'\"\n [class]=\"customClass\"\n [options]=\"countries()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onCountrySelected($event)\"\n></form-select>\n", styles: [":host{display:block;width:100%}\n"] }]
|
|
3456
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
3457
|
+
type: Inject,
|
|
3458
|
+
args: [PLATFORM_ID]
|
|
3459
|
+
}] }, { type: CountryService }], propDecorators: { label: [{
|
|
3460
|
+
type: Input
|
|
3461
|
+
}], placeholder: [{
|
|
3462
|
+
type: Input
|
|
3463
|
+
}], name: [{
|
|
3464
|
+
type: Input
|
|
3465
|
+
}], required: [{
|
|
3466
|
+
type: Input
|
|
3467
|
+
}], readonly: [{
|
|
3468
|
+
type: Input
|
|
3469
|
+
}], showError: [{
|
|
3470
|
+
type: Input
|
|
3471
|
+
}], customClass: [{
|
|
3472
|
+
type: Input
|
|
3473
|
+
}], control: [{
|
|
3474
|
+
type: Input
|
|
3475
|
+
}], countryChange: [{
|
|
3476
|
+
type: Output
|
|
3477
|
+
}] } });
|
|
3478
|
+
|
|
3479
|
+
class StateSelectComponent {
|
|
3480
|
+
statesService;
|
|
3481
|
+
label = 'Departamento';
|
|
3482
|
+
name = 'state_id';
|
|
3483
|
+
placeholder = 'Selecciona un departamento';
|
|
3484
|
+
required = false;
|
|
3485
|
+
readonly = false;
|
|
3486
|
+
countryId = null;
|
|
3487
|
+
showError = true;
|
|
3488
|
+
customClass = '';
|
|
3489
|
+
control = null;
|
|
3490
|
+
stateChange = new EventEmitter();
|
|
3491
|
+
states = signal([], ...(ngDevMode ? [{ debugName: "states" }] : []));
|
|
3492
|
+
loading = false;
|
|
3493
|
+
destroy$ = new Subject();
|
|
3494
|
+
// ControlValueAccessor properties
|
|
3495
|
+
value = null;
|
|
3496
|
+
onChange = () => { };
|
|
3497
|
+
onTouched = () => { };
|
|
3498
|
+
constructor(statesService) {
|
|
3499
|
+
this.statesService = statesService;
|
|
3500
|
+
}
|
|
3501
|
+
ngOnInit() {
|
|
3502
|
+
this.loadStates();
|
|
3503
|
+
}
|
|
3504
|
+
// Update the formControl getter to handle the AbstractControl
|
|
3505
|
+
get formControl() {
|
|
3506
|
+
return this.control;
|
|
3507
|
+
}
|
|
3508
|
+
ngOnChanges(changes) {
|
|
3509
|
+
if (changes['countryId'] && !changes['countryId'].firstChange) {
|
|
3510
|
+
this.value = null;
|
|
3511
|
+
this.onChange(null);
|
|
3512
|
+
this.stateChange.emit(null);
|
|
3513
|
+
if (this.countryId) {
|
|
3514
|
+
this.loadStates();
|
|
3515
|
+
}
|
|
3516
|
+
else {
|
|
3517
|
+
this.states.set([]);
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3521
|
+
ngOnDestroy() {
|
|
3522
|
+
this.destroy$.next();
|
|
3523
|
+
this.destroy$.complete();
|
|
3524
|
+
}
|
|
3525
|
+
loadStates() {
|
|
3526
|
+
this.loading = true;
|
|
3527
|
+
this.statesService
|
|
3528
|
+
.fetchStates(1, undefined, this.countryId)
|
|
3529
|
+
.pipe(takeUntil(this.destroy$))
|
|
3530
|
+
.subscribe({
|
|
3531
|
+
next: ({ data: { states } }) => {
|
|
3532
|
+
this.states.set(states?.map(({ id, name }) => ({ value: id, label: name })) || []);
|
|
3533
|
+
this.loading = false;
|
|
3534
|
+
},
|
|
3535
|
+
error: () => {
|
|
3536
|
+
this.states.set([]);
|
|
3537
|
+
this.loading = false;
|
|
3538
|
+
},
|
|
3539
|
+
});
|
|
3540
|
+
}
|
|
3541
|
+
onStateSelected(event) {
|
|
3542
|
+
const select = event.target;
|
|
3543
|
+
const value = select.value ? Number(select.value) : null;
|
|
3544
|
+
this.value = value;
|
|
3545
|
+
this.onChange(value);
|
|
3546
|
+
this.onTouched();
|
|
3547
|
+
this.stateChange.emit(value);
|
|
3548
|
+
}
|
|
3549
|
+
writeValue(value) {
|
|
3550
|
+
this.value = value;
|
|
3551
|
+
}
|
|
3552
|
+
registerOnChange(fn) {
|
|
3553
|
+
this.onChange = fn;
|
|
3554
|
+
}
|
|
3555
|
+
registerOnTouched(fn) {
|
|
3556
|
+
this.onTouched = fn;
|
|
3557
|
+
}
|
|
3558
|
+
validate(control) {
|
|
3559
|
+
if (this.required && !control.value) {
|
|
3560
|
+
return { required: true };
|
|
3561
|
+
}
|
|
3562
|
+
return null;
|
|
3563
|
+
}
|
|
3564
|
+
get isInvalid() {
|
|
3565
|
+
return false;
|
|
3566
|
+
}
|
|
3567
|
+
get isDisabled() {
|
|
3568
|
+
return this.readonly || !this.countryId || this.loading;
|
|
3569
|
+
}
|
|
3570
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: StateSelectComponent, deps: [{ token: StatesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3571
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: StateSelectComponent, isStandalone: true, selector: "state-select", inputs: { label: "label", name: "name", placeholder: "placeholder", required: "required", readonly: "readonly", countryId: "countryId", showError: "showError", customClass: "customClass", control: "control" }, outputs: { stateChange: "stateChange" }, providers: [
|
|
3572
|
+
{
|
|
3573
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3574
|
+
useExisting: forwardRef(() => StateSelectComponent),
|
|
3575
|
+
multi: true,
|
|
3576
|
+
},
|
|
3577
|
+
{
|
|
3578
|
+
provide: NG_VALIDATORS,
|
|
3579
|
+
useExisting: forwardRef(() => StateSelectComponent),
|
|
3580
|
+
multi: true,
|
|
3581
|
+
},
|
|
3582
|
+
], usesOnChanges: true, ngImport: i0, template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'state_id'\"\n [class]=\"customClass\"\n [options]=\"states()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onStateSelected($event)\"\n></form-select>\n", styles: [":host{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FormSelectComponent, selector: "form-select", inputs: ["label", "name", "id", "placeholder", "required", "disabled", "readonly", "options", "fieldGroupClass", "showDefaultOption", "defaultOptionLabel"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
3583
|
+
}
|
|
3584
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: StateSelectComponent, decorators: [{
|
|
3585
|
+
type: Component,
|
|
3586
|
+
args: [{ selector: 'state-select', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormSelectComponent], encapsulation: ViewEncapsulation.None, providers: [
|
|
3587
|
+
{
|
|
3588
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3589
|
+
useExisting: forwardRef(() => StateSelectComponent),
|
|
3590
|
+
multi: true,
|
|
3591
|
+
},
|
|
3592
|
+
{
|
|
3593
|
+
provide: NG_VALIDATORS,
|
|
3594
|
+
useExisting: forwardRef(() => StateSelectComponent),
|
|
3595
|
+
multi: true,
|
|
3596
|
+
},
|
|
3597
|
+
], template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'state_id'\"\n [class]=\"customClass\"\n [options]=\"states()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onStateSelected($event)\"\n></form-select>\n", styles: [":host{display:block;width:100%}\n"] }]
|
|
3598
|
+
}], ctorParameters: () => [{ type: StatesService }], propDecorators: { label: [{
|
|
3599
|
+
type: Input
|
|
3600
|
+
}], name: [{
|
|
3601
|
+
type: Input
|
|
3602
|
+
}], placeholder: [{
|
|
3603
|
+
type: Input
|
|
3604
|
+
}], required: [{
|
|
3605
|
+
type: Input
|
|
3606
|
+
}], readonly: [{
|
|
3607
|
+
type: Input
|
|
3608
|
+
}], countryId: [{
|
|
3609
|
+
type: Input
|
|
3610
|
+
}], showError: [{
|
|
3611
|
+
type: Input
|
|
3612
|
+
}], customClass: [{
|
|
3613
|
+
type: Input
|
|
3614
|
+
}], control: [{
|
|
3615
|
+
type: Input
|
|
3616
|
+
}], stateChange: [{
|
|
3617
|
+
type: Output
|
|
3618
|
+
}] } });
|
|
3619
|
+
|
|
3620
|
+
class CustomerSelectComponent {
|
|
3621
|
+
customerService;
|
|
3622
|
+
label = 'Cliente';
|
|
3623
|
+
placeholder = 'Selecciona un cliente';
|
|
3624
|
+
name = 'customer_id';
|
|
3625
|
+
required = false;
|
|
3626
|
+
readonly = false;
|
|
3627
|
+
multiple = false;
|
|
3628
|
+
customerChange = new EventEmitter();
|
|
3629
|
+
value = null;
|
|
3630
|
+
onChange = () => { };
|
|
3631
|
+
onTouched = () => { };
|
|
3632
|
+
config = {
|
|
3633
|
+
load: (params) => this.customerService.fetchCustomers(1, params?.search || '', 50),
|
|
3634
|
+
map: (res) => res.data.customers?.map((customer) => ({
|
|
3635
|
+
value: customer.id,
|
|
3636
|
+
label: `${getCustomerFullname(customer)} - ${customer.email}`.trim(),
|
|
3637
|
+
})) || [],
|
|
3638
|
+
};
|
|
3639
|
+
constructor(customerService) {
|
|
3640
|
+
this.customerService = customerService;
|
|
3641
|
+
}
|
|
3642
|
+
onInternalChange(value) {
|
|
3643
|
+
this.value = value;
|
|
3644
|
+
this.onChange(value);
|
|
3645
|
+
this.onTouched();
|
|
3646
|
+
this.customerChange.emit(value);
|
|
3647
|
+
}
|
|
3648
|
+
writeValue(value) {
|
|
3649
|
+
this.value = value;
|
|
3650
|
+
}
|
|
3651
|
+
registerOnChange(fn) {
|
|
3652
|
+
this.onChange = fn;
|
|
3653
|
+
}
|
|
3654
|
+
registerOnTouched(fn) {
|
|
3655
|
+
this.onTouched = fn;
|
|
3656
|
+
}
|
|
3657
|
+
validate(control) {
|
|
3658
|
+
if (this.required && !control.value) {
|
|
3659
|
+
return { required: true };
|
|
3660
|
+
}
|
|
3661
|
+
return null;
|
|
3662
|
+
}
|
|
3663
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CustomerSelectComponent, deps: [{ token: CustomerService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3664
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: CustomerSelectComponent, isStandalone: true, selector: "customer-select", inputs: { label: "label", placeholder: "placeholder", name: "name", required: "required", readonly: "readonly", multiple: "multiple" }, outputs: { customerChange: "customerChange" }, providers: [
|
|
3665
|
+
{
|
|
3666
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3667
|
+
useExisting: forwardRef(() => CustomerSelectComponent),
|
|
3668
|
+
multi: true,
|
|
3669
|
+
},
|
|
3670
|
+
{
|
|
3671
|
+
provide: NG_VALIDATORS,
|
|
3672
|
+
useExisting: forwardRef(() => CustomerSelectComponent),
|
|
3673
|
+
multi: true,
|
|
3674
|
+
},
|
|
3675
|
+
], ngImport: i0, template: "<async-select\n [config]=\"config\"\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'customer_id'\"\n [required]=\"required\"\n [multiple]=\"multiple\"\n [clearable]=\"true\"\n bindLabel=\"label\"\n bindValue=\"value\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onInternalChange($event)\"\n/>\n", dependencies: [{ kind: "component", type: AsyncSelectComponent, selector: "async-select", inputs: ["config", "items", "parentId", "label", "placeholder", "name", "required", "multiple", "clearable", "searchable", "loading", "virtualScroll", "notFoundText", "bindLabel", "bindValue"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
3676
|
+
}
|
|
3677
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: CustomerSelectComponent, decorators: [{
|
|
3678
|
+
type: Component,
|
|
3679
|
+
args: [{ selector: 'customer-select', standalone: true, imports: [AsyncSelectComponent, FormsModule], providers: [
|
|
3680
|
+
{
|
|
3681
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3682
|
+
useExisting: forwardRef(() => CustomerSelectComponent),
|
|
3683
|
+
multi: true,
|
|
3684
|
+
},
|
|
3685
|
+
{
|
|
3686
|
+
provide: NG_VALIDATORS,
|
|
3687
|
+
useExisting: forwardRef(() => CustomerSelectComponent),
|
|
3688
|
+
multi: true,
|
|
3689
|
+
},
|
|
3690
|
+
], template: "<async-select\n [config]=\"config\"\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'customer_id'\"\n [required]=\"required\"\n [multiple]=\"multiple\"\n [clearable]=\"true\"\n bindLabel=\"label\"\n bindValue=\"value\"\n [ngModel]=\"value\"\n (ngModelChange)=\"onInternalChange($event)\"\n/>\n" }]
|
|
3691
|
+
}], ctorParameters: () => [{ type: CustomerService }], propDecorators: { label: [{
|
|
3692
|
+
type: Input
|
|
3693
|
+
}], placeholder: [{
|
|
3694
|
+
type: Input
|
|
3695
|
+
}], name: [{
|
|
3696
|
+
type: Input
|
|
3697
|
+
}], required: [{
|
|
3698
|
+
type: Input
|
|
3699
|
+
}], readonly: [{
|
|
3700
|
+
type: Input
|
|
3701
|
+
}], multiple: [{
|
|
3702
|
+
type: Input
|
|
3703
|
+
}], customerChange: [{
|
|
3704
|
+
type: Output
|
|
3705
|
+
}] } });
|
|
3706
|
+
|
|
3707
|
+
class PerformanceSelectComponent {
|
|
3708
|
+
platformId;
|
|
3709
|
+
performanceService;
|
|
3710
|
+
label = 'Función';
|
|
3711
|
+
placeholder = 'Selecciona una función';
|
|
3712
|
+
name = 'performance_id';
|
|
3713
|
+
required = false;
|
|
3714
|
+
readonly = false;
|
|
3715
|
+
showError = true;
|
|
3716
|
+
customClass = '';
|
|
3717
|
+
control = null;
|
|
3718
|
+
performanceChange = new EventEmitter();
|
|
3719
|
+
performances = signal([], ...(ngDevMode ? [{ debugName: "performances" }] : []));
|
|
3720
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
3721
|
+
searchTerm = '';
|
|
3722
|
+
searchSubject = new Subject();
|
|
3723
|
+
destroy$ = new Subject();
|
|
3724
|
+
value = null;
|
|
3725
|
+
onChange = () => { };
|
|
3726
|
+
onTouched = () => { };
|
|
3727
|
+
constructor(platformId, performanceService) {
|
|
3728
|
+
this.platformId = platformId;
|
|
3729
|
+
this.performanceService = performanceService;
|
|
3730
|
+
}
|
|
3731
|
+
ngOnInit() {
|
|
3732
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
3733
|
+
this.performanceService.loadPerformances({ search: this.searchTerm });
|
|
3734
|
+
this.performanceService.performances$
|
|
3735
|
+
.pipe(takeUntil(this.destroy$))
|
|
3736
|
+
.subscribe((performances) => {
|
|
3737
|
+
this.performances.set(performances?.map((p) => ({
|
|
3738
|
+
value: p.id,
|
|
3739
|
+
label: `${p.show?.title || `Show #${p.show_id}`} - ${new Date(p.start_time).toLocaleDateString()}`,
|
|
3740
|
+
})) || []);
|
|
3741
|
+
this.loading.set(false);
|
|
3742
|
+
});
|
|
3743
|
+
this.searchSubject
|
|
3744
|
+
.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
3745
|
+
.subscribe((search) => {
|
|
3746
|
+
this.searchTerm = search;
|
|
3747
|
+
this.performanceService.loadPerformances({ search: this.searchTerm });
|
|
3748
|
+
});
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
get formControl() {
|
|
3752
|
+
return this.control;
|
|
3753
|
+
}
|
|
3754
|
+
ngOnDestroy() {
|
|
3755
|
+
this.destroy$.next();
|
|
3756
|
+
this.destroy$.complete();
|
|
3757
|
+
}
|
|
3758
|
+
onSearchChange(search) {
|
|
3759
|
+
this.searchSubject.next(search);
|
|
3760
|
+
}
|
|
3761
|
+
onPerformanceSelected(event) {
|
|
3762
|
+
const select = event.target;
|
|
3763
|
+
const value = select.value ? Number(select.value) : null;
|
|
3764
|
+
this.value = value;
|
|
3765
|
+
if (this.control) {
|
|
3766
|
+
this.control.setValue(value);
|
|
3767
|
+
this.control.markAsTouched();
|
|
3768
|
+
}
|
|
3769
|
+
this.performanceChange.emit(value);
|
|
3770
|
+
}
|
|
3771
|
+
writeValue(value) {
|
|
3772
|
+
this.value = value;
|
|
3773
|
+
}
|
|
3774
|
+
registerOnChange(fn) {
|
|
3775
|
+
this.onChange = fn;
|
|
3776
|
+
}
|
|
3777
|
+
registerOnTouched(fn) {
|
|
3778
|
+
this.onTouched = fn;
|
|
3779
|
+
}
|
|
3780
|
+
validate(control) {
|
|
3781
|
+
if (this.required && !control.value) {
|
|
3782
|
+
return { required: true };
|
|
3783
|
+
}
|
|
3784
|
+
return null;
|
|
3785
|
+
}
|
|
3786
|
+
get isInvalid() {
|
|
3787
|
+
return false;
|
|
3788
|
+
}
|
|
3789
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformanceSelectComponent, deps: [{ token: PLATFORM_ID }, { token: PerformanceService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3790
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: PerformanceSelectComponent, isStandalone: true, selector: "performance-select", inputs: { label: "label", placeholder: "placeholder", name: "name", required: "required", readonly: "readonly", showError: "showError", customClass: "customClass", control: "control" }, outputs: { performanceChange: "performanceChange" }, providers: [
|
|
3791
|
+
{
|
|
3792
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3793
|
+
useExisting: forwardRef(() => PerformanceSelectComponent),
|
|
3794
|
+
multi: true,
|
|
3795
|
+
},
|
|
3796
|
+
{
|
|
3797
|
+
provide: NG_VALIDATORS,
|
|
3798
|
+
useExisting: forwardRef(() => PerformanceSelectComponent),
|
|
3799
|
+
multi: true,
|
|
3800
|
+
},
|
|
3801
|
+
], ngImport: i0, template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'performance_id'\"\n [class]=\"customClass\"\n [options]=\"performances()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onPerformanceSelected($event)\"\n></form-select>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FormSelectComponent, selector: "form-select", inputs: ["label", "name", "id", "placeholder", "required", "disabled", "readonly", "options", "fieldGroupClass", "showDefaultOption", "defaultOptionLabel"] }] });
|
|
3802
|
+
}
|
|
3803
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformanceSelectComponent, decorators: [{
|
|
3804
|
+
type: Component,
|
|
3805
|
+
args: [{ selector: 'performance-select', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormSelectComponent], providers: [
|
|
3806
|
+
{
|
|
3807
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3808
|
+
useExisting: forwardRef(() => PerformanceSelectComponent),
|
|
3809
|
+
multi: true,
|
|
3810
|
+
},
|
|
3811
|
+
{
|
|
3812
|
+
provide: NG_VALIDATORS,
|
|
3813
|
+
useExisting: forwardRef(() => PerformanceSelectComponent),
|
|
3814
|
+
multi: true,
|
|
3815
|
+
},
|
|
3816
|
+
], template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'performance_id'\"\n [class]=\"customClass\"\n [options]=\"performances()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onPerformanceSelected($event)\"\n></form-select>\n" }]
|
|
3817
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
3818
|
+
type: Inject,
|
|
3819
|
+
args: [PLATFORM_ID]
|
|
3820
|
+
}] }, { type: PerformanceService }], propDecorators: { label: [{
|
|
3821
|
+
type: Input
|
|
3822
|
+
}], placeholder: [{
|
|
3823
|
+
type: Input
|
|
3824
|
+
}], name: [{
|
|
3825
|
+
type: Input
|
|
3826
|
+
}], required: [{
|
|
3827
|
+
type: Input
|
|
3828
|
+
}], readonly: [{
|
|
3829
|
+
type: Input
|
|
3830
|
+
}], showError: [{
|
|
3831
|
+
type: Input
|
|
3832
|
+
}], customClass: [{
|
|
3833
|
+
type: Input
|
|
3834
|
+
}], control: [{
|
|
3835
|
+
type: Input
|
|
3836
|
+
}], performanceChange: [{
|
|
3837
|
+
type: Output
|
|
3838
|
+
}] } });
|
|
3839
|
+
|
|
3840
|
+
class PerformanceMultiSelectComponent {
|
|
3841
|
+
platformId;
|
|
3842
|
+
performanceService;
|
|
3843
|
+
label = 'Funciones';
|
|
3844
|
+
placeholder = 'Buscar funciones...';
|
|
3845
|
+
allPerformances = signal([], ...(ngDevMode ? [{ debugName: "allPerformances" }] : []));
|
|
3846
|
+
filteredPerformances = signal([], ...(ngDevMode ? [{ debugName: "filteredPerformances" }] : []));
|
|
3847
|
+
loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
3848
|
+
selectedIds = [];
|
|
3849
|
+
searchTerm = '';
|
|
3850
|
+
searchSubject = new Subject();
|
|
3851
|
+
destroy$ = new Subject();
|
|
3852
|
+
onChange = () => { };
|
|
3853
|
+
onTouched = () => { };
|
|
3854
|
+
constructor(platformId, performanceService) {
|
|
3855
|
+
this.platformId = platformId;
|
|
3856
|
+
this.performanceService = performanceService;
|
|
3857
|
+
}
|
|
3858
|
+
ngOnInit() {
|
|
3859
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
3860
|
+
this.performanceService.loadPerformances({});
|
|
3861
|
+
this.performanceService.performances$
|
|
3862
|
+
.pipe(takeUntil(this.destroy$))
|
|
3863
|
+
.subscribe((performances) => {
|
|
3864
|
+
this.allPerformances.set(performances?.map((p) => ({
|
|
3865
|
+
value: p.id,
|
|
3866
|
+
label: `${p.show?.title || `Show #${p.show_id}`} - ${new Date(p.start_time).toLocaleString()}`,
|
|
3867
|
+
})) || []);
|
|
3868
|
+
this.applyFilter();
|
|
3869
|
+
this.loading.set(false);
|
|
3870
|
+
});
|
|
3871
|
+
this.searchSubject
|
|
3872
|
+
.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
3873
|
+
.subscribe((search) => {
|
|
3874
|
+
this.searchTerm = search;
|
|
3875
|
+
this.performanceService.loadPerformances({ search: this.searchTerm });
|
|
3876
|
+
});
|
|
3877
|
+
}
|
|
3878
|
+
}
|
|
3879
|
+
ngOnDestroy() {
|
|
3880
|
+
this.destroy$.next();
|
|
3881
|
+
this.destroy$.complete();
|
|
3882
|
+
}
|
|
3883
|
+
applyFilter() {
|
|
3884
|
+
if (this.searchTerm) {
|
|
3885
|
+
const term = this.searchTerm.toLowerCase();
|
|
3886
|
+
this.filteredPerformances.set(this.allPerformances().filter((p) => p.label.toLowerCase().includes(term)));
|
|
3887
|
+
}
|
|
3888
|
+
else {
|
|
3889
|
+
this.filteredPerformances.set([...this.allPerformances()]);
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
onSearchChange(event) {
|
|
3893
|
+
const value = event.target.value;
|
|
3894
|
+
this.searchSubject.next(value);
|
|
3895
|
+
}
|
|
3896
|
+
isSelected(id) {
|
|
3897
|
+
return this.selectedIds.includes(id);
|
|
3898
|
+
}
|
|
3899
|
+
togglePerformance(id) {
|
|
3900
|
+
const index = this.selectedIds.indexOf(id);
|
|
3901
|
+
if (index > -1) {
|
|
3902
|
+
this.selectedIds = this.selectedIds.filter((v) => v !== id);
|
|
3903
|
+
}
|
|
3904
|
+
else {
|
|
3905
|
+
this.selectedIds = [...this.selectedIds, id];
|
|
3906
|
+
}
|
|
3907
|
+
this.onChange(this.selectedIds);
|
|
3908
|
+
this.onTouched();
|
|
3909
|
+
}
|
|
3910
|
+
removePerformance(id) {
|
|
3911
|
+
this.togglePerformance(id);
|
|
3912
|
+
}
|
|
3913
|
+
getPerformanceLabel(id) {
|
|
3914
|
+
return this.allPerformances().find((p) => p.value === id)?.label || '';
|
|
3915
|
+
}
|
|
3916
|
+
writeValue(value) {
|
|
3917
|
+
this.selectedIds = value || [];
|
|
3918
|
+
}
|
|
3919
|
+
registerOnChange(fn) {
|
|
3920
|
+
this.onChange = fn;
|
|
3921
|
+
}
|
|
3922
|
+
registerOnTouched(fn) {
|
|
3923
|
+
this.onTouched = fn;
|
|
3924
|
+
}
|
|
3925
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformanceMultiSelectComponent, deps: [{ token: PLATFORM_ID }, { token: PerformanceService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3926
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: PerformanceMultiSelectComponent, isStandalone: true, selector: "performance-multi-select", inputs: { label: "label", placeholder: "placeholder" }, providers: [
|
|
3927
|
+
{
|
|
3928
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3929
|
+
useExisting: forwardRef(() => PerformanceMultiSelectComponent),
|
|
3930
|
+
multi: true,
|
|
3931
|
+
},
|
|
3932
|
+
], ngImport: i0, template: "<div class=\"w-full\">\n @if (label) {\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n </label>\n }\n\n @if (selectedIds.length > 0) {\n <div class=\"flex flex-wrap gap-1 mb-2\">\n @for (id of selectedIds; track id) {\n <span\n class=\"inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800\"\n >\n {{ getPerformanceLabel(id) }}\n <button\n type=\"button\"\n class=\"ml-1 hover:text-green-600 leading-none\"\n (click)=\"removePerformance(id)\"\n >\n ×\n </button>\n </span>\n }\n </div>\n }\n\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n class=\"w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent\"\n (input)=\"onSearchChange($event)\"\n />\n\n @if (loading()) {\n <div class=\"flex items-center gap-2 mt-2 text-sm text-gray-500\">\n <div\n class=\"w-4 h-4 border-2 border-gray-200 border-t-green-500 rounded-full animate-spin\"\n ></div>\n Cargando funciones...\n </div>\n }\n\n @if (!loading() && filteredPerformances().length > 0) {\n <div\n class=\"mt-1 max-h-48 overflow-y-auto border border-gray-200 rounded-md divide-y divide-gray-100\"\n >\n @for (p of filteredPerformances(); track p.value) {\n <label class=\"flex items-center gap-2 px-3 py-2 hover:bg-gray-50 cursor-pointer text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(p.value)\"\n (change)=\"togglePerformance(p.value)\"\n class=\"w-4 h-4 accent-green-500 cursor-pointer\"\n />\n <span class=\"text-gray-700 select-none\">{{ p.label }}</span>\n </label>\n }\n </div>\n }\n\n @if (!loading() && filteredPerformances().length === 0) {\n <p class=\"text-sm text-gray-500 mt-1\">No se encontraron funciones</p>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
3933
|
+
}
|
|
3934
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PerformanceMultiSelectComponent, decorators: [{
|
|
3935
|
+
type: Component,
|
|
3936
|
+
args: [{ selector: 'performance-multi-select', standalone: true, imports: [CommonModule], providers: [
|
|
3937
|
+
{
|
|
3938
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3939
|
+
useExisting: forwardRef(() => PerformanceMultiSelectComponent),
|
|
3940
|
+
multi: true,
|
|
3941
|
+
},
|
|
3942
|
+
], template: "<div class=\"w-full\">\n @if (label) {\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n </label>\n }\n\n @if (selectedIds.length > 0) {\n <div class=\"flex flex-wrap gap-1 mb-2\">\n @for (id of selectedIds; track id) {\n <span\n class=\"inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800\"\n >\n {{ getPerformanceLabel(id) }}\n <button\n type=\"button\"\n class=\"ml-1 hover:text-green-600 leading-none\"\n (click)=\"removePerformance(id)\"\n >\n ×\n </button>\n </span>\n }\n </div>\n }\n\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n class=\"w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent\"\n (input)=\"onSearchChange($event)\"\n />\n\n @if (loading()) {\n <div class=\"flex items-center gap-2 mt-2 text-sm text-gray-500\">\n <div\n class=\"w-4 h-4 border-2 border-gray-200 border-t-green-500 rounded-full animate-spin\"\n ></div>\n Cargando funciones...\n </div>\n }\n\n @if (!loading() && filteredPerformances().length > 0) {\n <div\n class=\"mt-1 max-h-48 overflow-y-auto border border-gray-200 rounded-md divide-y divide-gray-100\"\n >\n @for (p of filteredPerformances(); track p.value) {\n <label class=\"flex items-center gap-2 px-3 py-2 hover:bg-gray-50 cursor-pointer text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(p.value)\"\n (change)=\"togglePerformance(p.value)\"\n class=\"w-4 h-4 accent-green-500 cursor-pointer\"\n />\n <span class=\"text-gray-700 select-none\">{{ p.label }}</span>\n </label>\n }\n </div>\n }\n\n @if (!loading() && filteredPerformances().length === 0) {\n <p class=\"text-sm text-gray-500 mt-1\">No se encontraron funciones</p>\n }\n</div>\n" }]
|
|
3943
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
3944
|
+
type: Inject,
|
|
3945
|
+
args: [PLATFORM_ID]
|
|
3946
|
+
}] }, { type: PerformanceService }], propDecorators: { label: [{
|
|
3947
|
+
type: Input
|
|
3948
|
+
}], placeholder: [{
|
|
3949
|
+
type: Input
|
|
3950
|
+
}] } });
|
|
3951
|
+
|
|
3952
|
+
class ProductSelectComponent {
|
|
3953
|
+
platformId;
|
|
3954
|
+
productService;
|
|
3955
|
+
label = 'Producto';
|
|
3956
|
+
placeholder = 'Selecciona un producto';
|
|
3957
|
+
name = 'product_id';
|
|
3958
|
+
required = false;
|
|
3959
|
+
readonly = false;
|
|
3960
|
+
showError = true;
|
|
3961
|
+
customClass = '';
|
|
3962
|
+
control = null;
|
|
3963
|
+
productChange = new EventEmitter();
|
|
3964
|
+
products = signal([], ...(ngDevMode ? [{ debugName: "products" }] : []));
|
|
3965
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
3966
|
+
searchTerm = '';
|
|
3967
|
+
searchSubject = new Subject();
|
|
3968
|
+
destroy$ = new Subject();
|
|
3969
|
+
value = null;
|
|
3970
|
+
onChange = () => { };
|
|
3971
|
+
onTouched = () => { };
|
|
3972
|
+
constructor(platformId, productService) {
|
|
3973
|
+
this.platformId = platformId;
|
|
3974
|
+
this.productService = productService;
|
|
3975
|
+
}
|
|
3976
|
+
ngOnInit() {
|
|
3977
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
3978
|
+
this.productService.loadProducts({ search: this.searchTerm });
|
|
3979
|
+
this.productService.products$
|
|
3980
|
+
.pipe(takeUntil(this.destroy$))
|
|
3981
|
+
.subscribe((products) => {
|
|
3982
|
+
this.products.set(products?.map((product) => ({
|
|
3983
|
+
value: product.id,
|
|
3984
|
+
label: product.name,
|
|
3985
|
+
})) || []);
|
|
3986
|
+
this.loading.set(false);
|
|
3987
|
+
});
|
|
3988
|
+
this.searchSubject
|
|
3989
|
+
.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
3990
|
+
.subscribe((search) => {
|
|
3991
|
+
this.searchTerm = search;
|
|
3992
|
+
this.productService.loadProducts({ search: this.searchTerm });
|
|
3993
|
+
});
|
|
3994
|
+
}
|
|
3995
|
+
}
|
|
3996
|
+
get formControl() {
|
|
3997
|
+
return this.control;
|
|
3998
|
+
}
|
|
3999
|
+
ngOnDestroy() {
|
|
4000
|
+
this.destroy$.next();
|
|
4001
|
+
this.destroy$.complete();
|
|
4002
|
+
}
|
|
4003
|
+
onSearchChange(search) {
|
|
4004
|
+
this.searchSubject.next(search);
|
|
4005
|
+
}
|
|
4006
|
+
onProductSelected(event) {
|
|
4007
|
+
const select = event.target;
|
|
4008
|
+
const value = select.value ? Number(select.value) : null;
|
|
4009
|
+
this.value = value;
|
|
4010
|
+
if (this.control) {
|
|
4011
|
+
this.control.setValue(value);
|
|
4012
|
+
this.control.markAsTouched();
|
|
4013
|
+
}
|
|
4014
|
+
this.productChange.emit(value);
|
|
4015
|
+
}
|
|
4016
|
+
writeValue(value) {
|
|
4017
|
+
this.value = value;
|
|
4018
|
+
}
|
|
4019
|
+
registerOnChange(fn) {
|
|
4020
|
+
this.onChange = fn;
|
|
4021
|
+
}
|
|
4022
|
+
registerOnTouched(fn) {
|
|
4023
|
+
this.onTouched = fn;
|
|
4024
|
+
}
|
|
4025
|
+
validate(control) {
|
|
4026
|
+
if (this.required && !control.value) {
|
|
4027
|
+
return { required: true };
|
|
4028
|
+
}
|
|
4029
|
+
return null;
|
|
4030
|
+
}
|
|
4031
|
+
get isInvalid() {
|
|
4032
|
+
return false;
|
|
4033
|
+
}
|
|
4034
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ProductSelectComponent, deps: [{ token: PLATFORM_ID }, { token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4035
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: ProductSelectComponent, isStandalone: true, selector: "product-select", inputs: { label: "label", placeholder: "placeholder", name: "name", required: "required", readonly: "readonly", showError: "showError", customClass: "customClass", control: "control" }, outputs: { productChange: "productChange" }, providers: [
|
|
4036
|
+
{
|
|
4037
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4038
|
+
useExisting: forwardRef(() => ProductSelectComponent),
|
|
4039
|
+
multi: true,
|
|
4040
|
+
},
|
|
4041
|
+
{
|
|
4042
|
+
provide: NG_VALIDATORS,
|
|
4043
|
+
useExisting: forwardRef(() => ProductSelectComponent),
|
|
4044
|
+
multi: true,
|
|
4045
|
+
},
|
|
4046
|
+
], ngImport: i0, template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'product_id'\"\n [class]=\"customClass\"\n [options]=\"products()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onProductSelected($event)\"\n></form-select>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FormSelectComponent, selector: "form-select", inputs: ["label", "name", "id", "placeholder", "required", "disabled", "readonly", "options", "fieldGroupClass", "showDefaultOption", "defaultOptionLabel"] }] });
|
|
4047
|
+
}
|
|
4048
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ProductSelectComponent, decorators: [{
|
|
4049
|
+
type: Component,
|
|
4050
|
+
args: [{ selector: 'product-select', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormSelectComponent], providers: [
|
|
4051
|
+
{
|
|
4052
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4053
|
+
useExisting: forwardRef(() => ProductSelectComponent),
|
|
4054
|
+
multi: true,
|
|
4055
|
+
},
|
|
4056
|
+
{
|
|
4057
|
+
provide: NG_VALIDATORS,
|
|
4058
|
+
useExisting: forwardRef(() => ProductSelectComponent),
|
|
4059
|
+
multi: true,
|
|
4060
|
+
},
|
|
4061
|
+
], template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'product_id'\"\n [class]=\"customClass\"\n [options]=\"products()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onProductSelected($event)\"\n></form-select>\n" }]
|
|
4062
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
4063
|
+
type: Inject,
|
|
4064
|
+
args: [PLATFORM_ID]
|
|
4065
|
+
}] }, { type: ProductService }], propDecorators: { label: [{
|
|
4066
|
+
type: Input
|
|
4067
|
+
}], placeholder: [{
|
|
4068
|
+
type: Input
|
|
4069
|
+
}], name: [{
|
|
4070
|
+
type: Input
|
|
4071
|
+
}], required: [{
|
|
4072
|
+
type: Input
|
|
4073
|
+
}], readonly: [{
|
|
4074
|
+
type: Input
|
|
4075
|
+
}], showError: [{
|
|
4076
|
+
type: Input
|
|
4077
|
+
}], customClass: [{
|
|
4078
|
+
type: Input
|
|
4079
|
+
}], control: [{
|
|
4080
|
+
type: Input
|
|
4081
|
+
}], productChange: [{
|
|
4082
|
+
type: Output
|
|
4083
|
+
}] } });
|
|
4084
|
+
|
|
4085
|
+
class ProductMultiSelectComponent {
|
|
4086
|
+
platformId;
|
|
4087
|
+
productService;
|
|
4088
|
+
label = 'Productos';
|
|
4089
|
+
placeholder = 'Buscar productos...';
|
|
4090
|
+
set initialSelection(ids) {
|
|
4091
|
+
this.selectedIds = ids ?? [];
|
|
4092
|
+
}
|
|
4093
|
+
selectionChange = new EventEmitter();
|
|
4094
|
+
allProducts = signal([], ...(ngDevMode ? [{ debugName: "allProducts" }] : []));
|
|
4095
|
+
filteredProducts = signal([], ...(ngDevMode ? [{ debugName: "filteredProducts" }] : []));
|
|
4096
|
+
loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
4097
|
+
selectedIds = [];
|
|
4098
|
+
searchTerm = '';
|
|
4099
|
+
searchSubject = new Subject();
|
|
4100
|
+
destroy$ = new Subject();
|
|
4101
|
+
onChange = () => { };
|
|
4102
|
+
onTouched = () => { };
|
|
4103
|
+
constructor(platformId, productService) {
|
|
4104
|
+
this.platformId = platformId;
|
|
4105
|
+
this.productService = productService;
|
|
4106
|
+
}
|
|
4107
|
+
ngOnInit() {
|
|
4108
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
4109
|
+
this.productService.loadProducts({ search: this.searchTerm });
|
|
4110
|
+
this.productService.products$
|
|
4111
|
+
.pipe(takeUntil(this.destroy$))
|
|
4112
|
+
.subscribe((products) => {
|
|
4113
|
+
this.allProducts.set(products?.map((p) => ({
|
|
4114
|
+
value: p.id,
|
|
4115
|
+
label: p.name,
|
|
4116
|
+
imageUrl: p.images?.[0]?.full_url ?? null,
|
|
4117
|
+
})) || []);
|
|
4118
|
+
this.applyFilter();
|
|
4119
|
+
this.loading.set(false);
|
|
4120
|
+
});
|
|
4121
|
+
this.searchSubject
|
|
4122
|
+
.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
4123
|
+
.subscribe((search) => {
|
|
4124
|
+
this.searchTerm = search;
|
|
4125
|
+
this.productService.loadProducts({ search: this.searchTerm });
|
|
4126
|
+
});
|
|
4127
|
+
}
|
|
4128
|
+
}
|
|
4129
|
+
ngOnDestroy() {
|
|
4130
|
+
this.destroy$.next();
|
|
4131
|
+
this.destroy$.complete();
|
|
4132
|
+
}
|
|
4133
|
+
applyFilter() {
|
|
4134
|
+
if (this.searchTerm) {
|
|
4135
|
+
const term = this.searchTerm.toLowerCase();
|
|
4136
|
+
this.filteredProducts.set(this.allProducts().filter((p) => p.label.toLowerCase().includes(term)));
|
|
4137
|
+
}
|
|
4138
|
+
else {
|
|
4139
|
+
this.filteredProducts.set([...this.allProducts()]);
|
|
4140
|
+
}
|
|
4141
|
+
}
|
|
4142
|
+
onSearchChange(event) {
|
|
4143
|
+
const value = event.target.value;
|
|
4144
|
+
this.searchSubject.next(value);
|
|
4145
|
+
}
|
|
4146
|
+
isSelected(id) {
|
|
4147
|
+
return this.selectedIds.includes(id);
|
|
4148
|
+
}
|
|
4149
|
+
toggleProduct(id) {
|
|
4150
|
+
const index = this.selectedIds.indexOf(id);
|
|
4151
|
+
if (index > -1) {
|
|
4152
|
+
this.selectedIds = this.selectedIds.filter((v) => v !== id);
|
|
4153
|
+
}
|
|
4154
|
+
else {
|
|
4155
|
+
this.selectedIds = [...this.selectedIds, id];
|
|
4156
|
+
}
|
|
4157
|
+
this.onChange(this.selectedIds);
|
|
4158
|
+
this.onTouched();
|
|
4159
|
+
this.selectionChange.emit(this.selectedIds);
|
|
4160
|
+
}
|
|
4161
|
+
removeProduct(id) {
|
|
4162
|
+
this.toggleProduct(id);
|
|
4163
|
+
}
|
|
4164
|
+
getProductOption(id) {
|
|
4165
|
+
return this.allProducts().find((p) => p.value === id);
|
|
4166
|
+
}
|
|
4167
|
+
writeValue(value) {
|
|
4168
|
+
this.selectedIds = value || [];
|
|
4169
|
+
}
|
|
4170
|
+
registerOnChange(fn) {
|
|
4171
|
+
this.onChange = fn;
|
|
4172
|
+
}
|
|
4173
|
+
registerOnTouched(fn) {
|
|
4174
|
+
this.onTouched = fn;
|
|
4175
|
+
}
|
|
4176
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ProductMultiSelectComponent, deps: [{ token: PLATFORM_ID }, { token: ProductService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4177
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: ProductMultiSelectComponent, isStandalone: true, selector: "product-multi-select", inputs: { label: "label", placeholder: "placeholder", initialSelection: "initialSelection" }, outputs: { selectionChange: "selectionChange" }, providers: [
|
|
4178
|
+
{
|
|
4179
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4180
|
+
useExisting: forwardRef(() => ProductMultiSelectComponent),
|
|
4181
|
+
multi: true,
|
|
4182
|
+
},
|
|
4183
|
+
], ngImport: i0, template: "<div class=\"w-full\">\n @if (label) {\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n </label>\n }\n\n @if (selectedIds.length > 0) {\n <div class=\"flex flex-wrap gap-1 mb-2\">\n @for (id of selectedIds; track id) {\n @let product = getProductOption(id);\n <span\n class=\"inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800\"\n >\n @if (product?.imageUrl) {\n <img [src]=\"product!.imageUrl\" alt=\"\" class=\"w-4 h-4 rounded-full object-cover\" />\n }\n {{ product?.label ?? id }}\n <button\n type=\"button\"\n class=\"ml-1 hover:text-green-600 leading-none\"\n (click)=\"removeProduct(id)\"\n >\n ×\n </button>\n </span>\n }\n </div>\n }\n\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n class=\"w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent\"\n (input)=\"onSearchChange($event)\"\n />\n\n @if (loading()) {\n <div class=\"flex items-center gap-2 mt-2 text-sm text-gray-500\">\n <div\n class=\"w-4 h-4 border-2 border-gray-200 border-t-green-500 rounded-full animate-spin\"\n ></div>\n Cargando productos...\n </div>\n }\n\n @if (!loading() && filteredProducts().length > 0) {\n <div\n class=\"mt-1 max-h-48 overflow-y-auto border border-gray-200 rounded-md divide-y divide-gray-100\"\n >\n @for (p of filteredProducts(); track p.value) {\n <label class=\"flex items-center gap-2 px-3 py-2 hover:bg-gray-50 cursor-pointer text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(p.value)\"\n (change)=\"toggleProduct(p.value)\"\n class=\"w-4 h-4 accent-green-500 cursor-pointer\"\n />\n @if (p.imageUrl) {\n <img [src]=\"p.imageUrl\" alt=\"\" class=\"w-6 h-6 rounded object-cover\" />\n } @else {\n <div class=\"w-6 h-6 rounded bg-gray-200 flex items-center justify-center\">\n <i class=\"ri-image-line text-gray-400 text-xs\"></i>\n </div>\n }\n <span class=\"text-gray-700 select-none\">{{ p.label }}</span>\n </label>\n }\n </div>\n }\n\n @if (!loading() && filteredProducts().length === 0) {\n <p class=\"text-sm text-gray-500 mt-1\">No se encontraron productos</p>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
4184
|
+
}
|
|
4185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ProductMultiSelectComponent, decorators: [{
|
|
4186
|
+
type: Component,
|
|
4187
|
+
args: [{ selector: 'product-multi-select', standalone: true, imports: [CommonModule], providers: [
|
|
4188
|
+
{
|
|
4189
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4190
|
+
useExisting: forwardRef(() => ProductMultiSelectComponent),
|
|
4191
|
+
multi: true,
|
|
4192
|
+
},
|
|
4193
|
+
], template: "<div class=\"w-full\">\n @if (label) {\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n </label>\n }\n\n @if (selectedIds.length > 0) {\n <div class=\"flex flex-wrap gap-1 mb-2\">\n @for (id of selectedIds; track id) {\n @let product = getProductOption(id);\n <span\n class=\"inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium bg-green-100 text-green-800\"\n >\n @if (product?.imageUrl) {\n <img [src]=\"product!.imageUrl\" alt=\"\" class=\"w-4 h-4 rounded-full object-cover\" />\n }\n {{ product?.label ?? id }}\n <button\n type=\"button\"\n class=\"ml-1 hover:text-green-600 leading-none\"\n (click)=\"removeProduct(id)\"\n >\n ×\n </button>\n </span>\n }\n </div>\n }\n\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n class=\"w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent\"\n (input)=\"onSearchChange($event)\"\n />\n\n @if (loading()) {\n <div class=\"flex items-center gap-2 mt-2 text-sm text-gray-500\">\n <div\n class=\"w-4 h-4 border-2 border-gray-200 border-t-green-500 rounded-full animate-spin\"\n ></div>\n Cargando productos...\n </div>\n }\n\n @if (!loading() && filteredProducts().length > 0) {\n <div\n class=\"mt-1 max-h-48 overflow-y-auto border border-gray-200 rounded-md divide-y divide-gray-100\"\n >\n @for (p of filteredProducts(); track p.value) {\n <label class=\"flex items-center gap-2 px-3 py-2 hover:bg-gray-50 cursor-pointer text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(p.value)\"\n (change)=\"toggleProduct(p.value)\"\n class=\"w-4 h-4 accent-green-500 cursor-pointer\"\n />\n @if (p.imageUrl) {\n <img [src]=\"p.imageUrl\" alt=\"\" class=\"w-6 h-6 rounded object-cover\" />\n } @else {\n <div class=\"w-6 h-6 rounded bg-gray-200 flex items-center justify-center\">\n <i class=\"ri-image-line text-gray-400 text-xs\"></i>\n </div>\n }\n <span class=\"text-gray-700 select-none\">{{ p.label }}</span>\n </label>\n }\n </div>\n }\n\n @if (!loading() && filteredProducts().length === 0) {\n <p class=\"text-sm text-gray-500 mt-1\">No se encontraron productos</p>\n }\n</div>\n" }]
|
|
4194
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
4195
|
+
type: Inject,
|
|
4196
|
+
args: [PLATFORM_ID]
|
|
4197
|
+
}] }, { type: ProductService }], propDecorators: { label: [{
|
|
4198
|
+
type: Input
|
|
4199
|
+
}], placeholder: [{
|
|
4200
|
+
type: Input
|
|
4201
|
+
}], initialSelection: [{
|
|
4202
|
+
type: Input
|
|
4203
|
+
}], selectionChange: [{
|
|
4204
|
+
type: Output
|
|
4205
|
+
}] } });
|
|
4206
|
+
|
|
4207
|
+
class ShowSelectComponent {
|
|
4208
|
+
platformId;
|
|
4209
|
+
showService;
|
|
4210
|
+
label = 'Función';
|
|
4211
|
+
placeholder = 'Selecciona una función';
|
|
4212
|
+
name = 'show_id';
|
|
4213
|
+
required = false;
|
|
4214
|
+
readonly = false;
|
|
4215
|
+
showError = true;
|
|
4216
|
+
customClass = '';
|
|
4217
|
+
control = null;
|
|
4218
|
+
showChange = new EventEmitter();
|
|
4219
|
+
shows = signal([], ...(ngDevMode ? [{ debugName: "shows" }] : []));
|
|
4220
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
4221
|
+
searchTerm = '';
|
|
4222
|
+
searchSubject = new Subject();
|
|
4223
|
+
destroy$ = new Subject();
|
|
4224
|
+
value = null;
|
|
4225
|
+
onChange = () => { };
|
|
4226
|
+
onTouched = () => { };
|
|
4227
|
+
constructor(platformId, showService) {
|
|
4228
|
+
this.platformId = platformId;
|
|
4229
|
+
this.showService = showService;
|
|
4230
|
+
}
|
|
4231
|
+
ngOnInit() {
|
|
4232
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
4233
|
+
this.showService.loadShows({ search: this.searchTerm });
|
|
4234
|
+
this.showService.shows$.pipe(takeUntil(this.destroy$)).subscribe((shows) => {
|
|
4235
|
+
const formatted = shows?.map((show) => ({ value: show.id, label: show.title })) || [];
|
|
4236
|
+
this.shows.set(formatted);
|
|
4237
|
+
this.loading.set(false);
|
|
4238
|
+
});
|
|
4239
|
+
this.searchSubject
|
|
4240
|
+
.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
4241
|
+
.subscribe((search) => {
|
|
4242
|
+
this.searchTerm = search;
|
|
4243
|
+
this.showService.loadShows({ search: this.searchTerm });
|
|
4244
|
+
});
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
get formControl() {
|
|
4248
|
+
return this.control;
|
|
4249
|
+
}
|
|
4250
|
+
ngOnDestroy() {
|
|
4251
|
+
this.destroy$.next();
|
|
4252
|
+
this.destroy$.complete();
|
|
4253
|
+
}
|
|
4254
|
+
onSearchChange(search) {
|
|
4255
|
+
this.searchSubject.next(search);
|
|
4256
|
+
}
|
|
4257
|
+
onShowSelected(event) {
|
|
4258
|
+
const select = event.target;
|
|
4259
|
+
const value = select.value ? Number(select.value) : null;
|
|
4260
|
+
this.value = value;
|
|
4261
|
+
if (this.control) {
|
|
4262
|
+
this.control.setValue(value);
|
|
4263
|
+
this.control.markAsTouched();
|
|
4264
|
+
}
|
|
4265
|
+
this.showChange.emit(value);
|
|
4266
|
+
}
|
|
4267
|
+
writeValue(value) {
|
|
4268
|
+
this.value = value;
|
|
4269
|
+
}
|
|
4270
|
+
registerOnChange(fn) {
|
|
4271
|
+
this.onChange = fn;
|
|
4272
|
+
}
|
|
4273
|
+
registerOnTouched(fn) {
|
|
4274
|
+
this.onTouched = fn;
|
|
4275
|
+
}
|
|
4276
|
+
validate(control) {
|
|
4277
|
+
if (this.required && !control.value) {
|
|
4278
|
+
return { required: true };
|
|
4279
|
+
}
|
|
4280
|
+
return null;
|
|
4281
|
+
}
|
|
4282
|
+
get isInvalid() {
|
|
4283
|
+
return false;
|
|
4284
|
+
}
|
|
4285
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ShowSelectComponent, deps: [{ token: PLATFORM_ID }, { token: ShowService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4286
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: ShowSelectComponent, isStandalone: true, selector: "show-select", inputs: { label: "label", placeholder: "placeholder", name: "name", required: "required", readonly: "readonly", showError: "showError", customClass: "customClass", control: "control" }, outputs: { showChange: "showChange" }, providers: [
|
|
4287
|
+
{
|
|
4288
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4289
|
+
useExisting: forwardRef(() => ShowSelectComponent),
|
|
4290
|
+
multi: true,
|
|
4291
|
+
},
|
|
4292
|
+
{
|
|
4293
|
+
provide: NG_VALIDATORS,
|
|
4294
|
+
useExisting: forwardRef(() => ShowSelectComponent),
|
|
4295
|
+
multi: true,
|
|
4296
|
+
},
|
|
4297
|
+
], ngImport: i0, template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'show_id'\"\n [class]=\"customClass\"\n [options]=\"shows()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onShowSelected($event)\"\n></form-select>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FormSelectComponent, selector: "form-select", inputs: ["label", "name", "id", "placeholder", "required", "disabled", "readonly", "options", "fieldGroupClass", "showDefaultOption", "defaultOptionLabel"] }] });
|
|
4298
|
+
}
|
|
4299
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ShowSelectComponent, decorators: [{
|
|
4300
|
+
type: Component,
|
|
4301
|
+
args: [{ selector: 'show-select', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormSelectComponent], providers: [
|
|
4302
|
+
{
|
|
4303
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4304
|
+
useExisting: forwardRef(() => ShowSelectComponent),
|
|
4305
|
+
multi: true,
|
|
4306
|
+
},
|
|
4307
|
+
{
|
|
4308
|
+
provide: NG_VALIDATORS,
|
|
4309
|
+
useExisting: forwardRef(() => ShowSelectComponent),
|
|
4310
|
+
multi: true,
|
|
4311
|
+
},
|
|
4312
|
+
], template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'show_id'\"\n [class]=\"customClass\"\n [options]=\"shows()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onShowSelected($event)\"\n></form-select>\n" }]
|
|
4313
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
4314
|
+
type: Inject,
|
|
4315
|
+
args: [PLATFORM_ID]
|
|
4316
|
+
}] }, { type: ShowService }], propDecorators: { label: [{
|
|
4317
|
+
type: Input
|
|
4318
|
+
}], placeholder: [{
|
|
4319
|
+
type: Input
|
|
4320
|
+
}], name: [{
|
|
4321
|
+
type: Input
|
|
4322
|
+
}], required: [{
|
|
4323
|
+
type: Input
|
|
4324
|
+
}], readonly: [{
|
|
4325
|
+
type: Input
|
|
4326
|
+
}], showError: [{
|
|
4327
|
+
type: Input
|
|
4328
|
+
}], customClass: [{
|
|
4329
|
+
type: Input
|
|
4330
|
+
}], control: [{
|
|
4331
|
+
type: Input
|
|
4332
|
+
}], showChange: [{
|
|
4333
|
+
type: Output
|
|
4334
|
+
}] } });
|
|
4335
|
+
|
|
4336
|
+
class ShowMultiSelectComponent {
|
|
4337
|
+
platformId;
|
|
4338
|
+
showService;
|
|
4339
|
+
label = 'Funciones';
|
|
4340
|
+
placeholder = 'Buscar funciones...';
|
|
4341
|
+
allShows = signal([], ...(ngDevMode ? [{ debugName: "allShows" }] : []));
|
|
4342
|
+
filteredShows = signal([], ...(ngDevMode ? [{ debugName: "filteredShows" }] : []));
|
|
4343
|
+
loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
4344
|
+
selectedIds = [];
|
|
4345
|
+
searchTerm = '';
|
|
4346
|
+
searchSubject = new Subject();
|
|
4347
|
+
destroy$ = new Subject();
|
|
4348
|
+
onChange = () => { };
|
|
4349
|
+
onTouched = () => { };
|
|
4350
|
+
constructor(platformId, showService) {
|
|
4351
|
+
this.platformId = platformId;
|
|
4352
|
+
this.showService = showService;
|
|
4353
|
+
}
|
|
4354
|
+
ngOnInit() {
|
|
4355
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
4356
|
+
this.showService.loadShows({});
|
|
4357
|
+
this.showService.shows$.pipe(takeUntil(this.destroy$)).subscribe((shows) => {
|
|
4358
|
+
this.allShows.set(shows?.map((show) => ({
|
|
4359
|
+
value: show.id,
|
|
4360
|
+
label: show.title,
|
|
4361
|
+
})) || []);
|
|
4362
|
+
this.applyFilter();
|
|
4363
|
+
this.loading.set(false);
|
|
4364
|
+
});
|
|
4365
|
+
this.searchSubject
|
|
4366
|
+
.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
4367
|
+
.subscribe((search) => {
|
|
4368
|
+
this.searchTerm = search;
|
|
4369
|
+
this.showService.loadShows({ search: this.searchTerm });
|
|
4370
|
+
});
|
|
4371
|
+
}
|
|
4372
|
+
}
|
|
4373
|
+
ngOnDestroy() {
|
|
4374
|
+
this.destroy$.next();
|
|
4375
|
+
this.destroy$.complete();
|
|
4376
|
+
}
|
|
4377
|
+
applyFilter() {
|
|
4378
|
+
if (this.searchTerm) {
|
|
4379
|
+
const term = this.searchTerm.toLowerCase();
|
|
4380
|
+
this.filteredShows.set(this.allShows().filter((s) => s.label.toLowerCase().includes(term)));
|
|
4381
|
+
}
|
|
4382
|
+
else {
|
|
4383
|
+
this.filteredShows.set([...this.allShows()]);
|
|
4384
|
+
}
|
|
4385
|
+
}
|
|
4386
|
+
onSearchChange(event) {
|
|
4387
|
+
const value = event.target.value;
|
|
4388
|
+
this.searchSubject.next(value);
|
|
4389
|
+
}
|
|
4390
|
+
isSelected(id) {
|
|
4391
|
+
return this.selectedIds.includes(id);
|
|
4392
|
+
}
|
|
4393
|
+
toggleShow(id) {
|
|
4394
|
+
const index = this.selectedIds.indexOf(id);
|
|
4395
|
+
if (index > -1) {
|
|
4396
|
+
this.selectedIds = this.selectedIds.filter((v) => v !== id);
|
|
4397
|
+
}
|
|
4398
|
+
else {
|
|
4399
|
+
this.selectedIds = [...this.selectedIds, id];
|
|
4400
|
+
}
|
|
4401
|
+
this.onChange(this.selectedIds);
|
|
4402
|
+
this.onTouched();
|
|
4403
|
+
}
|
|
4404
|
+
removeShow(id) {
|
|
4405
|
+
this.toggleShow(id);
|
|
4406
|
+
}
|
|
4407
|
+
getShowLabel(id) {
|
|
4408
|
+
return this.allShows().find((s) => s.value === id)?.label || '';
|
|
4409
|
+
}
|
|
4410
|
+
writeValue(value) {
|
|
4411
|
+
this.selectedIds = value || [];
|
|
4412
|
+
}
|
|
4413
|
+
registerOnChange(fn) {
|
|
4414
|
+
this.onChange = fn;
|
|
4415
|
+
}
|
|
4416
|
+
registerOnTouched(fn) {
|
|
4417
|
+
this.onTouched = fn;
|
|
4418
|
+
}
|
|
4419
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ShowMultiSelectComponent, deps: [{ token: PLATFORM_ID }, { token: ShowService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4420
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: ShowMultiSelectComponent, isStandalone: true, selector: "show-multi-select", inputs: { label: "label", placeholder: "placeholder" }, providers: [
|
|
4421
|
+
{
|
|
4422
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4423
|
+
useExisting: forwardRef(() => ShowMultiSelectComponent),
|
|
4424
|
+
multi: true,
|
|
4425
|
+
},
|
|
4426
|
+
], ngImport: i0, template: "<div class=\"w-full\">\n @if (label) {\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n </label>\n }\n\n @if (selectedIds.length > 0) {\n <div class=\"flex flex-wrap gap-1 mb-2\">\n @for (id of selectedIds; track id) {\n <span\n class=\"inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800\"\n >\n {{ getShowLabel(id) }}\n <button\n type=\"button\"\n class=\"ml-1 hover:text-blue-600 leading-none\"\n (click)=\"removeShow(id)\"\n >\n ×\n </button>\n </span>\n }\n </div>\n }\n\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n class=\"w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n (input)=\"onSearchChange($event)\"\n />\n\n @if (loading()) {\n <div class=\"flex items-center gap-2 mt-2 text-sm text-gray-500\">\n <div\n class=\"w-4 h-4 border-2 border-gray-200 border-t-blue-500 rounded-full animate-spin\"\n ></div>\n Cargando funciones...\n </div>\n }\n\n @if (!loading() && filteredShows().length > 0) {\n <div\n class=\"mt-1 max-h-48 overflow-y-auto border border-gray-200 rounded-md divide-y divide-gray-100\"\n >\n @for (show of filteredShows(); track show.value) {\n <label class=\"flex items-center gap-2 px-3 py-2 hover:bg-gray-50 cursor-pointer text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(show.value)\"\n (change)=\"toggleShow(show.value)\"\n class=\"w-4 h-4 accent-blue-500 cursor-pointer\"\n />\n <span class=\"text-gray-700 select-none\">{{ show.label }}</span>\n </label>\n }\n </div>\n }\n\n @if (!loading() && filteredShows().length === 0) {\n <p class=\"text-sm text-gray-500 mt-1\">No se encontraron funciones</p>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
4427
|
+
}
|
|
4428
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: ShowMultiSelectComponent, decorators: [{
|
|
4429
|
+
type: Component,
|
|
4430
|
+
args: [{ selector: 'show-multi-select', standalone: true, imports: [CommonModule], providers: [
|
|
4431
|
+
{
|
|
4432
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4433
|
+
useExisting: forwardRef(() => ShowMultiSelectComponent),
|
|
4434
|
+
multi: true,
|
|
4435
|
+
},
|
|
4436
|
+
], template: "<div class=\"w-full\">\n @if (label) {\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\">\n {{ label }}\n </label>\n }\n\n @if (selectedIds.length > 0) {\n <div class=\"flex flex-wrap gap-1 mb-2\">\n @for (id of selectedIds; track id) {\n <span\n class=\"inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800\"\n >\n {{ getShowLabel(id) }}\n <button\n type=\"button\"\n class=\"ml-1 hover:text-blue-600 leading-none\"\n (click)=\"removeShow(id)\"\n >\n ×\n </button>\n </span>\n }\n </div>\n }\n\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n class=\"w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n (input)=\"onSearchChange($event)\"\n />\n\n @if (loading()) {\n <div class=\"flex items-center gap-2 mt-2 text-sm text-gray-500\">\n <div\n class=\"w-4 h-4 border-2 border-gray-200 border-t-blue-500 rounded-full animate-spin\"\n ></div>\n Cargando funciones...\n </div>\n }\n\n @if (!loading() && filteredShows().length > 0) {\n <div\n class=\"mt-1 max-h-48 overflow-y-auto border border-gray-200 rounded-md divide-y divide-gray-100\"\n >\n @for (show of filteredShows(); track show.value) {\n <label class=\"flex items-center gap-2 px-3 py-2 hover:bg-gray-50 cursor-pointer text-sm\">\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(show.value)\"\n (change)=\"toggleShow(show.value)\"\n class=\"w-4 h-4 accent-blue-500 cursor-pointer\"\n />\n <span class=\"text-gray-700 select-none\">{{ show.label }}</span>\n </label>\n }\n </div>\n }\n\n @if (!loading() && filteredShows().length === 0) {\n <p class=\"text-sm text-gray-500 mt-1\">No se encontraron funciones</p>\n }\n</div>\n" }]
|
|
4437
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
4438
|
+
type: Inject,
|
|
4439
|
+
args: [PLATFORM_ID]
|
|
4440
|
+
}] }, { type: ShowService }], propDecorators: { label: [{
|
|
4441
|
+
type: Input
|
|
4442
|
+
}], placeholder: [{
|
|
4443
|
+
type: Input
|
|
4444
|
+
}] } });
|
|
4445
|
+
|
|
4446
|
+
class PriceZoneSelectComponent {
|
|
4447
|
+
platformId;
|
|
4448
|
+
priceZoneService;
|
|
4449
|
+
label = 'Categoría';
|
|
4450
|
+
placeholder = 'Selecciona una categoría';
|
|
4451
|
+
name = 'price_zone_id';
|
|
4452
|
+
required = false;
|
|
4453
|
+
readonly = false;
|
|
4454
|
+
showError = true;
|
|
4455
|
+
customClass = '';
|
|
4456
|
+
control = null;
|
|
4457
|
+
priceZoneChange = new EventEmitter();
|
|
4458
|
+
priceZones = signal([], ...(ngDevMode ? [{ debugName: "priceZones" }] : []));
|
|
4459
|
+
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
4460
|
+
searchTerm = '';
|
|
4461
|
+
searchSubject = new Subject();
|
|
4462
|
+
destroy$ = new Subject();
|
|
4463
|
+
value = null;
|
|
4464
|
+
onChange = () => { };
|
|
4465
|
+
onTouched = () => { };
|
|
4466
|
+
constructor(platformId, priceZoneService) {
|
|
4467
|
+
this.platformId = platformId;
|
|
4468
|
+
this.priceZoneService = priceZoneService;
|
|
4469
|
+
}
|
|
4470
|
+
ngOnInit() {
|
|
4471
|
+
if (isPlatformBrowser(this.platformId)) {
|
|
4472
|
+
this.priceZoneService.loadPriceZones({ search: this.searchTerm });
|
|
4473
|
+
this.priceZoneService.priceZones$
|
|
4474
|
+
.pipe(takeUntil(this.destroy$))
|
|
4475
|
+
.subscribe((priceZones) => {
|
|
4476
|
+
this.priceZones.set(priceZones?.map((pz) => ({
|
|
4477
|
+
value: pz.id,
|
|
4478
|
+
label: pz.name,
|
|
4479
|
+
})) || []);
|
|
4480
|
+
this.loading.set(false);
|
|
4481
|
+
});
|
|
4482
|
+
this.searchSubject
|
|
4483
|
+
.pipe(debounceTime(400), distinctUntilChanged(), takeUntil(this.destroy$))
|
|
4484
|
+
.subscribe((search) => {
|
|
4485
|
+
this.searchTerm = search;
|
|
4486
|
+
this.priceZoneService.loadPriceZones({ search: this.searchTerm });
|
|
4487
|
+
});
|
|
4488
|
+
}
|
|
4489
|
+
}
|
|
4490
|
+
get formControl() {
|
|
4491
|
+
return this.control;
|
|
4492
|
+
}
|
|
4493
|
+
ngOnDestroy() {
|
|
4494
|
+
this.destroy$.next();
|
|
4495
|
+
this.destroy$.complete();
|
|
4496
|
+
}
|
|
4497
|
+
onSearchChange(search) {
|
|
4498
|
+
this.searchSubject.next(search);
|
|
4499
|
+
}
|
|
4500
|
+
onPriceZoneSelected(event) {
|
|
4501
|
+
const select = event.target;
|
|
4502
|
+
const value = select.value ? Number(select.value) : null;
|
|
4503
|
+
this.value = value;
|
|
4504
|
+
if (this.control) {
|
|
4505
|
+
this.control.setValue(value);
|
|
4506
|
+
this.control.markAsTouched();
|
|
4507
|
+
}
|
|
4508
|
+
this.priceZoneChange.emit(value);
|
|
4509
|
+
}
|
|
4510
|
+
writeValue(value) {
|
|
4511
|
+
this.value = value;
|
|
4512
|
+
}
|
|
4513
|
+
registerOnChange(fn) {
|
|
4514
|
+
this.onChange = fn;
|
|
4515
|
+
}
|
|
4516
|
+
registerOnTouched(fn) {
|
|
4517
|
+
this.onTouched = fn;
|
|
4518
|
+
}
|
|
4519
|
+
validate(control) {
|
|
4520
|
+
if (this.required && !control.value) {
|
|
4521
|
+
return { required: true };
|
|
4522
|
+
}
|
|
4523
|
+
return null;
|
|
4524
|
+
}
|
|
4525
|
+
get isInvalid() {
|
|
4526
|
+
return false;
|
|
4527
|
+
}
|
|
4528
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneSelectComponent, deps: [{ token: PLATFORM_ID }, { token: PriceZoneService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4529
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.25", type: PriceZoneSelectComponent, isStandalone: true, selector: "price-zone-select", inputs: { label: "label", placeholder: "placeholder", name: "name", required: "required", readonly: "readonly", showError: "showError", customClass: "customClass", control: "control" }, outputs: { priceZoneChange: "priceZoneChange" }, providers: [
|
|
4530
|
+
{
|
|
4531
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4532
|
+
useExisting: forwardRef(() => PriceZoneSelectComponent),
|
|
4533
|
+
multi: true,
|
|
4534
|
+
},
|
|
4535
|
+
{
|
|
4536
|
+
provide: NG_VALIDATORS,
|
|
4537
|
+
useExisting: forwardRef(() => PriceZoneSelectComponent),
|
|
4538
|
+
multi: true,
|
|
4539
|
+
},
|
|
4540
|
+
], ngImport: i0, template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'price_zone_id'\"\n [class]=\"customClass\"\n [options]=\"priceZones()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onPriceZoneSelected($event)\"\n></form-select>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FormSelectComponent, selector: "form-select", inputs: ["label", "name", "id", "placeholder", "required", "disabled", "readonly", "options", "fieldGroupClass", "showDefaultOption", "defaultOptionLabel"] }] });
|
|
4541
|
+
}
|
|
4542
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: PriceZoneSelectComponent, decorators: [{
|
|
4543
|
+
type: Component,
|
|
4544
|
+
args: [{ selector: 'price-zone-select', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormSelectComponent], providers: [
|
|
4545
|
+
{
|
|
4546
|
+
provide: NG_VALUE_ACCESSOR,
|
|
4547
|
+
useExisting: forwardRef(() => PriceZoneSelectComponent),
|
|
4548
|
+
multi: true,
|
|
4549
|
+
},
|
|
4550
|
+
{
|
|
4551
|
+
provide: NG_VALIDATORS,
|
|
4552
|
+
useExisting: forwardRef(() => PriceZoneSelectComponent),
|
|
4553
|
+
multi: true,
|
|
4554
|
+
},
|
|
4555
|
+
], template: "<form-select\n [label]=\"label\"\n [placeholder]=\"placeholder\"\n [name]=\"name || 'price_zone_id'\"\n [class]=\"customClass\"\n [options]=\"priceZones()\"\n [required]=\"required\"\n [readonly]=\"readonly\"\n [formControl]=\"formControl\"\n (change)=\"onPriceZoneSelected($event)\"\n></form-select>\n" }]
|
|
4556
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
4557
|
+
type: Inject,
|
|
4558
|
+
args: [PLATFORM_ID]
|
|
4559
|
+
}] }, { type: PriceZoneService }], propDecorators: { label: [{
|
|
4560
|
+
type: Input
|
|
4561
|
+
}], placeholder: [{
|
|
4562
|
+
type: Input
|
|
4563
|
+
}], name: [{
|
|
4564
|
+
type: Input
|
|
4565
|
+
}], required: [{
|
|
4566
|
+
type: Input
|
|
4567
|
+
}], readonly: [{
|
|
4568
|
+
type: Input
|
|
4569
|
+
}], showError: [{
|
|
4570
|
+
type: Input
|
|
4571
|
+
}], customClass: [{
|
|
4572
|
+
type: Input
|
|
4573
|
+
}], control: [{
|
|
4574
|
+
type: Input
|
|
4575
|
+
}], priceZoneChange: [{
|
|
4576
|
+
type: Output
|
|
4577
|
+
}] } });
|
|
4578
|
+
|
|
4579
|
+
// Config
|
|
4580
|
+
|
|
4581
|
+
/**
|
|
4582
|
+
* Generated bundle index. Do not edit.
|
|
4583
|
+
*/
|
|
4584
|
+
|
|
4585
|
+
export { ADMIN_API_ROUTES, ALERT_BASE_CLASSES, ALERT_COLOR_CLASSES, ALERT_ICONS, ALERT_SIZE_CLASSES, AdminSelectComponent, AdminService, ApiService, AppAlertComponent, AppButtonComponent, AppLinkButtonComponent, AppModalComponent, AsyncSelectComponent, AuditInformationComponent, BASE_BUTTON_CLASSES, BASE_INPUT_CLASSES, BUTTON_SIZES_CLASSES, BUTTON_VARIANT_CLASSES, CITY_API_ENDPOINTS, COUNTRY_API_ENDPOINTS, CUSTOMERS_API_ROUTES, ChangePasswordFormComponent, ChangePasswordFormService, CitiesService, CitySelectComponent, ColorPickerComponent, CorporateBondStatus, CountrySelectComponent, CountryService, CouponApplicability, CouponDiscountType, CustomerSelectComponent, CustomerService, DateInputComponent, DateService, DeleteConfirmationComponent, DeleteConfirmationService, DynamicTableComponent, ERROR_INPUT_CLASSES, EndDateGreaterThanStartValidator, FORM_ERROR_MESSAGES, FileType, FileUploadComponent, FileUploadPreviewComponent, FormEditorComponent, FormInputComponent, FormSelectComponent, FormTextareaComponent, LanguageSwitcherComponent, LoadingModalService, LoadingmModalComponent, MinTodayValidator, MustMatchValidator, OrderItemType, OrderStatus, PERFORMANCES_API_ROUTES, PRICE_ZONES_API_ROUTES, PRODUCTS_API_ROUTES, PerformanceMultiSelectComponent, PerformanceSelectComponent, PerformanceService, PerformanceStatus, PerformanceTicketStatus, PerformancesListEventsService, PriceZoneEventService, PriceZoneFormModalService, PriceZoneSelectComponent, PriceZoneService, ProductMultiSelectComponent, ProductSelectComponent, ProductService, RoomMapElementOrientation, RoomMapElementType, SHOWS_API_ROUTES, STATE_API_ENDPOINTS, ShowMultiSelectComponent, ShowSelectComponent, ShowService, StateSelectComponent, StatesService, TICKERA_COMPONENTS_CONFIG, ToastService, ToggleSwitchComponent, VENUES_API_ROUTES, authInterceptor, formatCitiesResponseToSelect, getCustomerFullname, parseJsonToFormDataAdvanced, provideTickeraComponents, transformImageToFile };
|
|
4586
|
+
//# sourceMappingURL=tickera-angular-components.mjs.map
|