diff --git a/src/app/core/models/preparer/contact-login.ts b/src/app/core/models/preparer/contact-login.ts new file mode 100644 index 0000000..14517b5 --- /dev/null +++ b/src/app/core/models/preparer/contact-login.ts @@ -0,0 +1,4 @@ +export interface ContactLogin { + clientContactId: number; + password: string; +} diff --git a/src/app/core/models/preparer/contact.ts b/src/app/core/models/preparer/contact.ts index 3c69a96..f40d6fc 100644 --- a/src/app/core/models/preparer/contact.ts +++ b/src/app/core/models/preparer/contact.ts @@ -15,6 +15,7 @@ export interface Contact { createdBy?: string | null; lastUpdatedBy?: string | null; lastUpdatedDate?: Date | null; - isInactive?: boolean | null; // TODO - inactivatedDate?: Date | null; // TODO + isInactive?: boolean | null; + inactivatedDate?: Date | null; + hasLogin?: boolean; // Indicates if the contact has a login } diff --git a/src/app/core/models/preparer/location.ts b/src/app/core/models/preparer/location.ts index 3ab7ef4..dea8473 100644 --- a/src/app/core/models/preparer/location.ts +++ b/src/app/core/models/preparer/location.ts @@ -12,6 +12,6 @@ export interface Location { createdBy?: string | null; lastUpdatedBy?: string | null; lastUpdatedDate?: Date | null; - isInactive?: boolean | null; // TODO - inactivatedDate?: Date | null; // TODO + isInactive?: boolean | null; + inactivatedDate?: Date | null; } diff --git a/src/app/core/services/preparer/contact.service.ts b/src/app/core/services/preparer/contact.service.ts index 70bdc74..cea3253 100644 --- a/src/app/core/services/preparer/contact.service.ts +++ b/src/app/core/services/preparer/contact.service.ts @@ -4,6 +4,7 @@ import { HttpClient } from '@angular/common/http'; import { environment } from '../../../../environments/environment'; import { map, Observable, of } from 'rxjs'; import { Contact } from '../../models/preparer/contact'; +import { ContactLogin } from '../../models/preparer/contact-login'; @Injectable({ providedIn: 'root' @@ -38,7 +39,8 @@ export class ContactService { lastUpdatedBy: contact.LASTUPDATEDBY || null, lastUpdatedDate: contact.LASTUPDATEDDATE || null, isInactive: contact.INACTIVEFLAG === 'Y' || false, - inactivatedDate: contact.INACTIVEDATE || null + inactivatedDate: contact.INACTIVEDATE || null, + hasLogin: contact.LOGINFLAG === 'Y' || false })); } @@ -81,7 +83,23 @@ export class ContactService { return this.http.put(`${this.apiUrl}/${this.apiDb}/UpdateClientContacts`, contact); } - // deleteContact(clientContactId: string): Observable { - // return this.http.post(`${this.apiUrl}/${this.apiDb}/InactivateSPContact?p_clientcontactid=${clientContactId}`, null); - // } + createContactLogin(data: ContactLogin): Observable { + const contact = { + P_SPID: this.userService.getUserSpid(), + P_CLIENTCONTACTID: data.clientContactId, + P_ENABLEPASSWORDPOLICY: 'Y', + P_PASSWORD: data.password, + P_USERID: this.userService.getUser() + } + + return this.http.post(`${this.apiUrl}/${this.apiDb}/CreateClientLogins`, contact); + } + + inactivateContact(clientContactId: string): Observable { + return this.http.patch(`${this.apiUrl}/${this.apiDb}/InactivateClientContacts/${this.userService.getUserSpid()}/${clientContactId}/${this.userService.getUser()}`, null); + } + + reactivateContact(clientContactId: string): Observable { + return this.http.patch(`${this.apiUrl}/${this.apiDb}/ReactivateClientContacts/${this.userService.getUserSpid()}/${clientContactId}/${this.userService.getUser()}`, null); + } } diff --git a/src/app/core/services/preparer/location.service.ts b/src/app/core/services/preparer/location.service.ts index 76944b2..b586fd3 100644 --- a/src/app/core/services/preparer/location.service.ts +++ b/src/app/core/services/preparer/location.service.ts @@ -75,8 +75,4 @@ export class LocationService { return this.http.put(`${this.apiUrl}/${this.apiDb}/UpdateClientLocations`, location); } - - // deleteLocation(clientContactId: string): Observable { - // return this.http.post(`${this.apiUrl}/${this.apiDb}/InactivateSPContact?p_clientcontactid=${clientContactId}`, null); - // } } diff --git a/src/app/preparer/add/add-preparer.component.html b/src/app/preparer/add/add-preparer.component.html index 6f8c2e9..f5242f0 100644 --- a/src/app/preparer/add/add-preparer.component.html +++ b/src/app/preparer/add/add-preparer.component.html @@ -6,7 +6,8 @@ Basic Details - + @@ -20,7 +21,7 @@ - + Locations + +
+ + Do you have more branch offices? + +
+
- - -
+
@@ -260,4 +262,45 @@
+ + +
+
+
+

Create Login

+
+ +
+
+
+ +
+ +
+ {{contactLoginReadOnlyFields.email}} +
+
+
+
+
+ +
+ + Password + + lock + + Password is required + + +
+ +
+ + +
+
+
\ No newline at end of file diff --git a/src/app/preparer/contacts/contacts.component.scss b/src/app/preparer/contacts/contacts.component.scss index 7e4d2f2..03674f5 100644 --- a/src/app/preparer/contacts/contacts.component.scss +++ b/src/app/preparer/contacts/contacts.component.scss @@ -120,9 +120,17 @@ margin-top: 16px; } - .readonly-section { + .top-divider { padding-top: 0.5rem; border-top: 1px solid #eee; + } + + .bottom-divider { + padding-bottom: 0.5rem; + border-bottom: 1px solid #eee; + } + + .readonly-section { .readonly-fields { display: flex; diff --git a/src/app/preparer/contacts/contacts.component.ts b/src/app/preparer/contacts/contacts.component.ts index 74aabbc..c1ee8c0 100644 --- a/src/app/preparer/contacts/contacts.component.ts +++ b/src/app/preparer/contacts/contacts.component.ts @@ -14,6 +14,7 @@ import { MatDialog } from '@angular/material/dialog'; import { ApiErrorHandlerService } from '../../core/services/common/api-error-handler.service'; import { Contact } from '../../core/models/preparer/contact'; import { ConfirmDialogComponent } from '../../shared/components/confirm-dialog/confirm-dialog.component'; +import { ContactLogin } from '../../core/models/preparer/contact-login'; @Component({ selector: 'app-contacts', @@ -29,10 +30,12 @@ export class ContactsComponent { displayedColumns: string[] = ['firstName', 'lastName', 'title', 'phone', 'mobile', 'email', 'defaultContact', 'actions']; dataSource = new MatTableDataSource(); contactForm: FormGroup; + contactLoginForm: FormGroup; isEditing = false; currentContactId: number | null = null; isLoading = false; showForm = false; + showLoginForm = false showInactiveContacts = false; contacts: Contact[] = []; contactReadOnlyFields: any = { @@ -42,6 +45,10 @@ export class ContactsComponent { inactivatedDate: null }; + contactLoginReadOnlyFields: any = { + email: null + }; + @Input() clientid: number = 0; @Input() userPreferences: UserPreferences = {}; @Output() hasContacts = new EventEmitter(); @@ -64,6 +71,10 @@ export class ContactsComponent { email: ['', [Validators.required, Validators.email, Validators.maxLength(100)]], defaultContact: [false] }); + + this.contactLoginForm = this.fb.group({ + password: ['', [Validators.required]] + }); } ngOnInit(): void { @@ -95,6 +106,7 @@ export class ContactsComponent { addNewContact(): void { this.showForm = true; + this.showLoginForm = false; this.isEditing = false; this.currentContactId = null; this.contactForm.reset(); @@ -103,6 +115,7 @@ export class ContactsComponent { editContact(contact: Contact): void { this.showForm = true; + this.showLoginForm = false; this.isEditing = true; this.currentContactId = contact.clientContactId; this.contactForm.patchValue({ @@ -165,42 +178,103 @@ export class ContactsComponent { } } - deleteContact(contactId: string): void { - // const dialogRef = this.dialog.open(ConfirmDialogComponent, { - // width: '350px', - // data: { - // title: 'Confirm Delete', - // message: 'Are you sure you want to delete this contact?', - // confirmText: 'Delete', - // cancelText: 'Cancel' - // } - // }); + inactivateContact(contactId: string): void { + const dialogRef = this.dialog.open(ConfirmDialogComponent, { + width: '350px', + data: { + title: 'Confirm Inactivation', + message: 'Are you sure you want to inactivate this contact?', + confirmText: 'Yes', + cancelText: 'Cancel' + } + }); - // dialogRef.afterClosed().subscribe(result => { - // if (result) { - // this.contactService.deleteContact(contactId).subscribe({ - // next: () => { - // this.notificationService.showSuccess('Contact deleted successfully'); - // this.loadContacts(); - // }, - // error: (error) => { - // let errorMessage = this.errorHandler.handleApiError(error, 'Failed to delete contact'); - // this.notificationService.showError(errorMessage); - // console.error('Error deleting contact:', error); - // } - // }); - // } - // }); + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.contactService.inactivateContact(contactId).subscribe({ + next: () => { + this.notificationService.showSuccess('Contact inactivated successfully'); + this.loadContacts(); + }, + error: (error) => { + let errorMessage = this.errorHandler.handleApiError(error, 'Failed to inactivate contact'); + this.notificationService.showError(errorMessage); + console.error('Error inactivating contact:', error); + } + }); + } + }); } - createLogin(): void { + reactivateContact(contactId: string): void { + const dialogRef = this.dialog.open(ConfirmDialogComponent, { + width: '350px', + data: { + title: 'Confirm Reactivation', + message: 'Are you sure you want to reactivate this contact?', + confirmText: 'Yes', + cancelText: 'Cancel' + } + }); + + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.contactService.reactivateContact(contactId).subscribe({ + next: () => { + this.notificationService.showSuccess('Contact reactivated successfully'); + this.loadContacts(); + }, + error: (error) => { + let errorMessage = this.errorHandler.handleApiError(error, 'Failed to reactivate contact'); + this.notificationService.showError(errorMessage); + console.error('Error reactivating contact:', error); + } + }); + } + }); + } + + createLogin(contact: Contact): void { + this.showForm = false; + this.showLoginForm = true; + this.isEditing = true; + this.currentContactId = contact.clientContactId; + + this.contactLoginReadOnlyFields.email = contact.email; + } + + saveLogin(): void { + if (this.contactLoginForm.invalid) { + this.contactLoginForm.markAllAsTouched(); + return; + } + + const contactLoginData: ContactLogin = { + clientContactId: this.currentContactId!, + password: this.contactLoginForm.value.password + }; + + this.contactService.createContactLogin(contactLoginData).subscribe({ + next: () => { + this.notificationService.showSuccess(`Login created successfully`); + this.loadContacts(); + this.cancelEdit(); + }, + error: (error) => { + let errorMessage = this.errorHandler.handleApiError(error, `Failed to create login`); + this.notificationService.showError(errorMessage); + console.error('Error saving login:', error); + } + }); } cancelEdit(): void { this.showForm = false; + this.showLoginForm = false; this.isEditing = false; this.currentContactId = null; this.contactForm.reset(); + this.contactLoginForm.reset(); } // setDefaultContact(contactId: string): void { diff --git a/src/app/preparer/manage/manage-preparer.component.html b/src/app/preparer/manage/manage-preparer.component.html index 71a01e2..69a5487 100644 --- a/src/app/preparer/manage/manage-preparer.component.html +++ b/src/app/preparer/manage/manage-preparer.component.html @@ -72,7 +72,7 @@ Address - {{ getAddressLabel(client.address1, client.address2, client.zip)}} + {{ getAddressLabel(client.address1, client.address2)}} diff --git a/src/app/preparer/manage/manage-preparer.component.ts b/src/app/preparer/manage/manage-preparer.component.ts index 8e890f1..5f1197b 100644 --- a/src/app/preparer/manage/manage-preparer.component.ts +++ b/src/app/preparer/manage/manage-preparer.component.ts @@ -162,14 +162,11 @@ export class ManagePreparerComponent implements OnInit, OnDestroy, AfterViewInit }); } - getAddressLabel(address1: string, address2?: string, zip?: string): string { + getAddressLabel(address1: string, address2?: string): string { let addressLabel = address1; if (address2) { addressLabel += `, ${address2}`; } - if (zip) { - addressLabel += `, ${zip}`; - } return addressLabel; }