1+ < div class ="user-create-container ">
2+ < mat-card class ="create-user-card ">
3+ < mat-card-header class ="card-header ">
4+ < div mat-card-avatar class ="header-avatar ">
5+ < mat-icon > person_add</ mat-icon >
6+ </ div >
7+ < mat-card-title class ="header-title "> Crear Nuevo Usuario</ mat-card-title >
8+ < mat-card-subtitle class ="header-subtitle "> Complete la información del nuevo usuario</ mat-card-subtitle >
9+ </ mat-card-header >
10+
11+ < mat-divider > </ mat-divider >
12+
13+ < mat-card-content class ="card-content ">
14+ < form [formGroup] ="userForm " (ngSubmit) ="onSave() " class ="user-form " autocomplete ="off ">
15+
16+ < div class ="form-section ">
17+ < h3 class ="section-title ">
18+ Tipo de Usuario
19+ </ h3 >
20+
21+ < div class ="form-row ">
22+ < mat-form-field appearance ="outline " class ="full-width ">
23+ < mat-label > Roles</ mat-label >
24+ < mat-icon matPrefix > admin_panel_settings</ mat-icon >
25+ < mat-select formControlName ="roles " multiple (selectionChange) ="onRoleSelectionChange($event) ">
26+ < mat-option *ngFor ="let role of getAvailableRoleOptions() " [value] ="role.role "
27+ [disabled] ="isRoleDisabled(role) " (click) ="onRoleOptionClick($event, role) ">
28+ < div class ="role-option ">
29+ < span class ="role-indicator " [style.background-color] ="role.color "> </ span >
30+ < span > {{ role.displayName || role.name || role.role }}</ span >
31+ </ div >
32+ </ mat-option >
33+ </ mat-select >
34+ < mat-hint > Seleccione el tipo de usuario primero</ mat-hint >
35+ < mat-error *ngIf ="isFieldInvalid('roles') ">
36+ {{ getFieldError('roles') }}
37+ </ mat-error >
38+ </ mat-form-field >
39+ </ div >
40+ </ div >
41+
42+ < div class ="form-section " *ngIf ="hasSelectedRoles() ">
43+ <!-- Campo Username para profesionales -->
44+ < div class ="form-row " *ngIf ="hasProfessionalRole() ">
45+ < mat-form-field appearance ="outline " class ="full-width ">
46+ < mat-label > Documento (Username)</ mat-label >
47+ < mat-icon matPrefix > badge</ mat-icon >
48+ < input matInput formControlName ="username " placeholder ="Ingrese el número de documento "
49+ (input) ="onUsernameChange($event) ">
50+ < mat-icon matSuffix *ngIf ="isValidatingUsername " class ="validation-icon ">
51+ < mat-spinner diameter ="20 "> </ mat-spinner >
52+ </ mat-icon >
53+ < mat-icon matSuffix *ngIf ="!isValidatingUsername && isUsernameValid "
54+ class ="validation-icon success "> check_circle</ mat-icon >
55+ < mat-icon matSuffix *ngIf ="!isValidatingUsername && !isUsernameValid && usernameValidationMessage "
56+ class ="validation-icon error "> error</ mat-icon >
57+ < mat-hint *ngIf ="usernameValidationMessage " [class.success-hint] ="isUsernameValid "
58+ [class.error-hint] ="!isUsernameValid ">
59+ {{ usernameValidationMessage }}
60+ </ mat-hint >
61+ < mat-error *ngIf ="isFieldInvalid('username') ">
62+ {{ getFieldError('username') }}
63+ </ mat-error >
64+ </ mat-form-field >
65+ </ div >
66+
67+ <!-- Campo CUIL para farmacias -->
68+ < div class ="form-row " *ngIf ="hasPharmacyRole() ">
69+ < mat-form-field appearance ="outline " class ="full-width ">
70+ < mat-label > CUIL</ mat-label >
71+ < mat-icon matPrefix > fingerprint</ mat-icon >
72+ < input matInput formControlName ="cuil " placeholder ="12345678901 " maxlength ="11 "
73+ (input) ="onCuilChange($event) ">
74+ < mat-icon matSuffix *ngIf ="isValidatingCuil " class ="validation-icon ">
75+ < mat-spinner diameter ="20 "> </ mat-spinner >
76+ </ mat-icon >
77+ < mat-icon matSuffix *ngIf ="!isValidatingCuil && isCuilValid "
78+ class ="validation-icon success "> check_circle</ mat-icon >
79+ < mat-icon matSuffix *ngIf ="!isValidatingCuil && !isCuilValid && cuilValidationMessage "
80+ class ="validation-icon error "> error</ mat-icon >
81+ < mat-hint *ngIf ="cuilValidationMessage " [class.success-hint] ="isCuilValid "
82+ [class.error-hint] ="!isCuilValid ">
83+ {{ cuilValidationMessage }}
84+ </ mat-hint >
85+ < mat-error *ngIf ="isFieldInvalid('cuil') ">
86+ {{ getFieldError('cuil') }}
87+ </ mat-error >
88+ </ mat-form-field >
89+ </ div >
90+ </ div >
91+
92+ <!-- Información del profesional encontrado -->
93+ < div class ="form-section " *ngIf ="hasProfessionalData() ">
94+ < h3 class ="section-title ">
95+ < mat-icon > person_search</ mat-icon >
96+ Profesional Encontrado en Andes
97+ </ h3 >
98+
99+ < div class ="found-data-card ">
100+ < div class ="professional-info ">
101+ < div class ="info-row ">
102+ < strong > Nombre:</ strong > {{ foundProfessionalData.nombre }} {{ foundProfessionalData.apellido }}
103+ </ div >
104+ < div class ="info-row " *ngIf ="foundProfessionalData.cuit ">
105+ < strong > CUIL:</ strong > {{ foundProfessionalData.cuit }}
106+ </ div >
107+ < div class ="info-row " *ngIf ="foundProfessionalData.documento ">
108+ < strong > Documento:</ strong > {{ foundProfessionalData.documento }}
109+ </ div >
110+ < div class ="info-row " *ngIf ="foundProfessionalData.sexo ">
111+ < strong > Sexo:</ strong > {{ foundProfessionalData.sexo }}
112+ </ div >
113+ < div class ="info-row " *ngIf ="foundProfessionalData.profesiones && foundProfessionalData.profesiones.length ">
114+ < strong > Profesiones:</ strong >
115+ < span >
116+ < ng-container *ngFor ="let profession of foundProfessionalData.profesiones; let last = last ">
117+ {{ profession.profesion?.nombre }} (Mat. {{ getProfessionMatricula(profession) }})< span *ngIf ="!last "> , </ span >
118+ </ ng-container >
119+ </ span >
120+ </ div >
121+ </ div >
122+
123+ < button mat-icon-button type ="button " (click) ="clearFoundData() " class ="clear-data-button "
124+ aria-label ="Buscar otro profesional ">
125+ < mat-icon > clear</ mat-icon >
126+ </ button >
127+ </ div >
128+ </ div >
129+
130+ <!-- Información de farmacia encontrada -->
131+ < div class ="form-section " *ngIf ="hasPharmacyData() ">
132+ < h3 class ="section-title ">
133+ < mat-icon > local_pharmacy</ mat-icon >
134+ Farmacia Encontrada en Andes
135+ </ h3 >
136+
137+ < div class ="found-data-card ">
138+ < div class ="pharmacy-info ">
139+ < div class ="info-row ">
140+ < strong > Denominación:</ strong > {{ foundPharmacyData.denominacion || foundPharmacyData.razonSocial }}
141+ </ div >
142+ < div class ="info-row " *ngIf ="foundPharmacyData.cuit ">
143+ < strong > CUIT:</ strong > {{ foundPharmacyData.cuit }}
144+ </ div >
145+ < div class ="info-row " *ngIf ="foundPharmacyData.DTResponsable ">
146+ < strong > Responsable:</ strong > {{ foundPharmacyData.DTResponsable }}
147+ </ div >
148+ < div class ="info-row " *ngIf ="foundPharmacyData.matriculaDTResponsable ">
149+ < strong > Matrícula:</ strong > {{ foundPharmacyData.matriculaDTResponsable }}
150+ </ div >
151+ < div class ="info-row " *ngIf ="foundPharmacyData.domicilio ">
152+ < strong > Dirección:</ strong >
153+ {{ foundPharmacyData.domicilio.valor }}
154+ < span *ngIf ="foundPharmacyData.domicilio.ubicacion ">
155+ , {{ foundPharmacyData.domicilio.ubicacion.localidad.nombre }}
156+ < span *ngIf ="foundPharmacyData.domicilio.ubicacion.provincia ">
157+ , {{ foundPharmacyData.domicilio.ubicacion.provincia.nombre }}
158+ </ span >
159+ </ span >
160+ </ div >
161+ < div class ="info-row ">
162+ < strong > Estado:</ strong >
163+ < span [class.activo] ="foundPharmacyData.activo " [class.inactivo] ="!foundPharmacyData.activo ">
164+ {{ foundPharmacyData.activo ? 'Activa' : 'Inactiva' }}
165+ </ span >
166+ </ div >
167+ < div class ="info-row " *ngIf ="foundPharmacyData.telefono ">
168+ < strong > Teléfono:</ strong > {{ foundPharmacyData.telefono }}
169+ </ div >
170+ < div class ="info-row " *ngIf ="foundPharmacyData.email ">
171+ < strong > Email:</ strong > {{ foundPharmacyData.email }}
172+ </ div >
173+ </ div >
174+
175+ < button mat-icon-button type ="button " (click) ="clearFoundData() " class ="clear-data-button "
176+ aria-label ="Buscar otra farmacia ">
177+ < mat-icon > clear</ mat-icon >
178+ </ button >
179+ </ div >
180+ </ div >
181+
182+ < div class ="form-section ">
183+ < div class ="form-row " *ngIf ="!hasProfessionalRole() && !hasPharmacyRole() ">
184+ < mat-form-field appearance ="outline " class ="full-width ">
185+ < mat-label > Nombre</ mat-label >
186+ < mat-icon matPrefix > store</ mat-icon >
187+ < input matInput formControlName ="businessName " placeholder ="Ingrese el nombre del negocio ">
188+ < mat-error *ngIf ="isFieldInvalid('businessName') ">
189+ {{ getFieldError('businessName') }}
190+ </ mat-error >
191+ </ mat-form-field >
192+ </ div >
193+ </ div >
194+ < div class ="form-section ">
195+ < h3 class ="section-title ">
196+ Información del usuario
197+ </ h3 >
198+ <!-- Select de profesiones para profesionales -->
199+ < div class ="professions-section "
200+ *ngIf ="foundProfessionalData && foundProfessionalData.profesiones && foundProfessionalData.profesiones.length > 0 ">
201+ < div class ="form-row ">
202+ < mat-form-field appearance ="outline " class ="full-width ">
203+ < mat-label > Profesiones</ mat-label >
204+ < mat-icon matPrefix > work</ mat-icon >
205+ < mat-select [value] ="selectedProfession " (selectionChange) ="onProfessionSelect($event.value) "
206+ placeholder ="Seleccione una profesión ">
207+ < mat-option *ngFor ="let profession of foundProfessionalData.profesiones " [value] ="profession ">
208+ < span class ="profession-name "> {{ profession.profesion.nombre }}</ span >
209+ < span class ="matricula "> - Matricula {{ getProfessionMatricula(profession) }}</ span >
210+ < span class ="status "
211+ [class.vigente] ="getProfessionStatus(profession) === 'Vigente' "
212+ [class.vencida] ="getProfessionStatus(profession) === 'Vencida' "
213+ [style.color] ="getProfessionStatus(profession) === 'Vigente' ? '#4caf50' : '#f44336' ">
214+ ({{ getProfessionStatus(profession) }})
215+ </ span >
216+ </ mat-option >
217+ </ mat-select >
218+ < mat-error *ngIf ="isProfessionSelectionMissing() ">
219+ Debe seleccionar una profesión
220+ </ mat-error >
221+ < mat-hint *ngIf ="!selectedProfession ">
222+ Seleccione una profesión para continuar
223+ </ mat-hint >
224+ </ mat-form-field >
225+ </ div >
226+ </ div >
227+
228+ < div class ="form-row ">
229+ < mat-form-field appearance ="outline " class ="full-width ">
230+ < mat-label > Email</ mat-label >
231+ < mat-icon matPrefix > email</ mat-icon >
232+ < input matInput type ="email " formControlName ="email " placeholder ="usuario@ejemplo.com " autocomplete ="off "
233+ autocapitalize ="none " spellcheck ="false " name ="no-autocomplete-email ">
234+ < mat-error *ngIf ="isFieldInvalid('email') ">
235+ {{ getFieldError('email') }}
236+ </ mat-error >
237+ </ mat-form-field >
238+ </ div >
239+
240+ < div class ="form-row ">
241+ < mat-form-field appearance ="outline " class ="full-width ">
242+ < mat-label > Contraseña</ mat-label >
243+ < mat-icon matPrefix > lock</ mat-icon >
244+ < input matInput type ="password " formControlName ="password " placeholder ="Ingrese la contraseña "
245+ autocomplete ="new-password " name ="no-autocomplete-password ">
246+ < mat-hint > Mínimo 6 caracteres</ mat-hint >
247+ < mat-error *ngIf ="isFieldInvalid('password') ">
248+ {{ getFieldError('password') }}
249+ </ mat-error >
250+ </ mat-form-field >
251+ </ div >
252+ </ div >
253+
254+
255+
256+ </ form >
257+ </ mat-card-content >
258+
259+ < mat-divider > </ mat-divider >
260+
261+ < mat-card-actions class ="card-actions ">
262+ < div class ="actions-container ">
263+ < button mat-stroked-button type ="button " (click) ="onCancel() " [disabled] ="isLoading " class ="cancel-button ">
264+ < mat-icon > close</ mat-icon >
265+ Cancelar
266+ </ button >
267+
268+ < button mat-icon-button type ="button " (click) ="onSave() " [disabled] ="isLoading || userForm.invalid || isProfessionSelectionMissing() "
269+ class ="save-button " [style.background-color] ="(isLoading || userForm.invalid || isProfessionSelectionMissing()) ? '#969696' : '#3f51b5' "
270+ [style.color] ="'white' ">
271+ < div class ="button ">
272+ < mat-icon *ngIf ="!isLoading "> save</ mat-icon >
273+ < mat-spinner *ngIf ="isLoading " diameter ="20 "> </ mat-spinner >
274+ {{ isLoading ? 'Guardando...' : 'Crear Usuario' }}
275+ </ div >
276+ </ button >
277+ </ div >
278+ </ mat-card-actions >
279+ </ mat-card >
280+ </ div >
0 commit comments