@idsoftsource/initial-process 3.3.4 → 3.3.5
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.
|
@@ -3366,14 +3366,21 @@ class PreviewComponent {
|
|
|
3366
3366
|
customProfessionName = '';
|
|
3367
3367
|
customProfessionGroup = null;
|
|
3368
3368
|
customProfessionType = null;
|
|
3369
|
+
customProfessionStars = 0;
|
|
3370
|
+
customProfessionYear = null;
|
|
3369
3371
|
isSavingCustomProfession = false;
|
|
3370
3372
|
openCustomProfessionForm(context) {
|
|
3371
3373
|
this.customProfessionContext = context;
|
|
3372
3374
|
this.customProfessionName = '';
|
|
3373
3375
|
this.customProfessionGroup = null;
|
|
3374
3376
|
this.customProfessionType = null;
|
|
3377
|
+
this.customProfessionStars = 0;
|
|
3378
|
+
this.customProfessionYear = null;
|
|
3375
3379
|
this.showCustomProfessionForm = true;
|
|
3376
3380
|
}
|
|
3381
|
+
setTempCustomProfessionStars(stars) {
|
|
3382
|
+
this.customProfessionStars = stars;
|
|
3383
|
+
}
|
|
3377
3384
|
cancelCustomProfessionForm() {
|
|
3378
3385
|
this.showCustomProfessionForm = false;
|
|
3379
3386
|
this.customProfessionContext = null;
|
|
@@ -3393,8 +3400,8 @@ class PreviewComponent {
|
|
|
3393
3400
|
targetProviderId: this.effectiveTargetProviderId,
|
|
3394
3401
|
professionName: name,
|
|
3395
3402
|
notes: '',
|
|
3396
|
-
year: 0,
|
|
3397
|
-
starRating:
|
|
3403
|
+
year: this.customProfessionYear ?? 0,
|
|
3404
|
+
starRating: (this.customProfessionStars || 0) * 2,
|
|
3398
3405
|
profileVisibility: false,
|
|
3399
3406
|
status: RequestedStatus.InReview,
|
|
3400
3407
|
professionGroup: this.customProfessionGroup,
|
|
@@ -3545,6 +3552,9 @@ class PreviewComponent {
|
|
|
3545
3552
|
get hasNoProfessionMatches() {
|
|
3546
3553
|
return !!(this.professionSearchQry || '').trim() && this.filteredProfessionTypes.length === 0;
|
|
3547
3554
|
}
|
|
3555
|
+
trackByProfessionId(_index, p) {
|
|
3556
|
+
return p.id;
|
|
3557
|
+
}
|
|
3548
3558
|
professionGroupOptions = [];
|
|
3549
3559
|
professionTypeOptions = [];
|
|
3550
3560
|
recomputeProfessionGroupAndTypeOptions() {
|
|
@@ -3601,6 +3611,19 @@ class PreviewComponent {
|
|
|
3601
3611
|
const checked = event.target.checked;
|
|
3602
3612
|
this.getProfessionSelection(profession.id).selected = checked;
|
|
3603
3613
|
}
|
|
3614
|
+
toggleProfessionRow(profession, event) {
|
|
3615
|
+
if (event) {
|
|
3616
|
+
const target = event.target;
|
|
3617
|
+
// Ignore clicks that originate from an interactive control inside the header
|
|
3618
|
+
// (Group/Type ng-select, checkbox, etc.) — expanding/collapsing the row underneath
|
|
3619
|
+
// them reflows the layout and makes an open ng-select panel auto-close.
|
|
3620
|
+
if (target.closest('.ng-select, select, input, textarea, button, a')) {
|
|
3621
|
+
return;
|
|
3622
|
+
}
|
|
3623
|
+
}
|
|
3624
|
+
const sel = this.getProfessionSelection(profession.id);
|
|
3625
|
+
sel.selected = !sel.selected;
|
|
3626
|
+
}
|
|
3604
3627
|
setProfessionRowStars(profession, stars) {
|
|
3605
3628
|
this.getProfessionSelection(profession.id).starRating = stars * 2;
|
|
3606
3629
|
}
|
|
@@ -3635,8 +3658,8 @@ class PreviewComponent {
|
|
|
3635
3658
|
professionGroup: profType.professionGroup ?? '',
|
|
3636
3659
|
residentialCommercial: profType.residentialCommercial ?? '',
|
|
3637
3660
|
notes: sel.notes ?? '',
|
|
3638
|
-
year: sel.year ??
|
|
3639
|
-
starRating: sel.starRating ??
|
|
3661
|
+
year: sel.year ?? 0,
|
|
3662
|
+
starRating: sel.starRating ?? 0,
|
|
3640
3663
|
profileVisibility: sel.profileVisibility ?? false,
|
|
3641
3664
|
status: RequestedStatus.InReview,
|
|
3642
3665
|
emailId,
|
|
@@ -3653,8 +3676,8 @@ class PreviewComponent {
|
|
|
3653
3676
|
targetProviderId: this.effectiveTargetProviderId,
|
|
3654
3677
|
professionName: profType.professionName,
|
|
3655
3678
|
notes: sel.notes ?? '',
|
|
3656
|
-
year: sel.year ??
|
|
3657
|
-
starRating: sel.starRating ??
|
|
3679
|
+
year: sel.year ?? 0,
|
|
3680
|
+
starRating: sel.starRating ?? 0,
|
|
3658
3681
|
profileVisibility: sel.profileVisibility ?? false,
|
|
3659
3682
|
status: RequestedStatus.InReview,
|
|
3660
3683
|
professionGroup: profType.professionGroup ?? '',
|
|
@@ -3921,28 +3944,16 @@ class PreviewComponent {
|
|
|
3921
3944
|
}
|
|
3922
3945
|
return issues;
|
|
3923
3946
|
}
|
|
3924
|
-
skillItemIssues(name
|
|
3947
|
+
skillItemIssues(name) {
|
|
3925
3948
|
const issues = [];
|
|
3926
3949
|
if (this.isBlank(name))
|
|
3927
3950
|
issues.push('Skill name is required');
|
|
3928
|
-
const meta = this.store.resumeSkillMeta()?.[index] ?? {};
|
|
3929
|
-
const stars = Math.round((meta.starRating ?? 0) / 2);
|
|
3930
|
-
if (!stars || stars <= 0)
|
|
3931
|
-
issues.push('Star rating is required');
|
|
3932
|
-
if (meta.year === null || meta.year === undefined)
|
|
3933
|
-
issues.push('Years of experience is required');
|
|
3934
3951
|
return issues;
|
|
3935
3952
|
}
|
|
3936
|
-
toolItemIssues(name
|
|
3953
|
+
toolItemIssues(name) {
|
|
3937
3954
|
const issues = [];
|
|
3938
3955
|
if (this.isBlank(name))
|
|
3939
3956
|
issues.push('Tool name is required');
|
|
3940
|
-
const meta = this.store.resumeToolMeta()?.[index] ?? {};
|
|
3941
|
-
const stars = Math.round((meta.starRating ?? 0) / 2);
|
|
3942
|
-
if (!stars || stars <= 0)
|
|
3943
|
-
issues.push('Star rating is required');
|
|
3944
|
-
if (meta.year === null || meta.year === undefined)
|
|
3945
|
-
issues.push('Years of experience is required');
|
|
3946
3957
|
return issues;
|
|
3947
3958
|
}
|
|
3948
3959
|
professionItemIssues(name, index) {
|
|
@@ -3952,11 +3963,6 @@ class PreviewComponent {
|
|
|
3952
3963
|
const meta = this.store.resumeProfessionMeta()?.[index] ?? {};
|
|
3953
3964
|
if (this.isBlankOrNull(meta.professionId))
|
|
3954
3965
|
issues.push('Profession type is required');
|
|
3955
|
-
const stars = Math.round((meta.starRating ?? 0) / 2);
|
|
3956
|
-
if (!stars || stars <= 0)
|
|
3957
|
-
issues.push('Star rating is required');
|
|
3958
|
-
if (meta.year === null || meta.year === undefined)
|
|
3959
|
-
issues.push('Years of experience is required');
|
|
3960
3966
|
return issues;
|
|
3961
3967
|
}
|
|
3962
3968
|
basicIssues = computed(() => this.basicDetailsIssues(this.details()), ...(ngDevMode ? [{ debugName: "basicIssues" }] : []));
|
|
@@ -3965,8 +3971,8 @@ class PreviewComponent {
|
|
|
3965
3971
|
educationIssuesByIndex = computed(() => this.educationList().map((e) => this.educationItemIssues(e)), ...(ngDevMode ? [{ debugName: "educationIssuesByIndex" }] : []));
|
|
3966
3972
|
certIssuesByIndex = computed(() => this.certs().map((c) => this.certificationItemIssues(c)), ...(ngDevMode ? [{ debugName: "certIssuesByIndex" }] : []));
|
|
3967
3973
|
licenseIssuesByIndex = computed(() => this.licenses().map((l) => this.licenseItemIssues(l)), ...(ngDevMode ? [{ debugName: "licenseIssuesByIndex" }] : []));
|
|
3968
|
-
skillIssuesByIndex = computed(() => this.skills().map((s
|
|
3969
|
-
toolIssuesByIndex = computed(() => this.tools().map((t
|
|
3974
|
+
skillIssuesByIndex = computed(() => this.skills().map((s) => this.skillItemIssues(s)), ...(ngDevMode ? [{ debugName: "skillIssuesByIndex" }] : []));
|
|
3975
|
+
toolIssuesByIndex = computed(() => this.tools().map((t) => this.toolItemIssues(t)), ...(ngDevMode ? [{ debugName: "toolIssuesByIndex" }] : []));
|
|
3970
3976
|
professionIssuesByIndex = computed(() => this.professions().map((p, i) => this.professionItemIssues(p, i)), ...(ngDevMode ? [{ debugName: "professionIssuesByIndex" }] : []));
|
|
3971
3977
|
// Editor overlay validation based on temporary editor values (so it shows immediately on "Edit")
|
|
3972
3978
|
skillFormIssues = computed(() => {
|
|
@@ -3976,10 +3982,6 @@ class PreviewComponent {
|
|
|
3976
3982
|
const issues = [];
|
|
3977
3983
|
if (this.isBlank(form.name))
|
|
3978
3984
|
issues.push('Skillset name is required');
|
|
3979
|
-
if (!form.stars || form.stars <= 0)
|
|
3980
|
-
issues.push('Star rating is required');
|
|
3981
|
-
if (form.year === null || form.year === undefined)
|
|
3982
|
-
issues.push('Years of experience is required');
|
|
3983
3985
|
return issues;
|
|
3984
3986
|
}, ...(ngDevMode ? [{ debugName: "skillFormIssues" }] : []));
|
|
3985
3987
|
toolFormIssues = computed(() => {
|
|
@@ -3989,10 +3991,6 @@ class PreviewComponent {
|
|
|
3989
3991
|
const issues = [];
|
|
3990
3992
|
if (this.isBlank(form.name))
|
|
3991
3993
|
issues.push('Tool name is required');
|
|
3992
|
-
if (!form.stars || form.stars <= 0)
|
|
3993
|
-
issues.push('Star rating is required');
|
|
3994
|
-
if (form.year === null || form.year === undefined)
|
|
3995
|
-
issues.push('Years of experience is required');
|
|
3996
3994
|
return issues;
|
|
3997
3995
|
}, ...(ngDevMode ? [{ debugName: "toolFormIssues" }] : []));
|
|
3998
3996
|
professionFormIssues = computed(() => {
|
|
@@ -4004,10 +4002,6 @@ class PreviewComponent {
|
|
|
4004
4002
|
issues.push('Profession name is required');
|
|
4005
4003
|
if (this.isBlankOrNull(form.professionId))
|
|
4006
4004
|
issues.push('Profession type is required');
|
|
4007
|
-
if (!form.stars || form.stars <= 0)
|
|
4008
|
-
issues.push('Star rating is required');
|
|
4009
|
-
if (form.year === null || form.year === undefined)
|
|
4010
|
-
issues.push('Years of experience is required');
|
|
4011
4005
|
return issues;
|
|
4012
4006
|
}, ...(ngDevMode ? [{ debugName: "professionFormIssues" }] : []));
|
|
4013
4007
|
workSectionHasIssues = computed(() => {
|
|
@@ -5195,10 +5189,6 @@ class PreviewComponent {
|
|
|
5195
5189
|
const nextName = (form.name || '').trim();
|
|
5196
5190
|
if (!nextName)
|
|
5197
5191
|
return;
|
|
5198
|
-
if (!form.stars || form.stars <= 0)
|
|
5199
|
-
return;
|
|
5200
|
-
if (form.year === null || form.year === undefined)
|
|
5201
|
-
return;
|
|
5202
5192
|
this.isSavingSkill = true;
|
|
5203
5193
|
try {
|
|
5204
5194
|
const nextSkills = [...(current.skills ?? [])];
|
|
@@ -5224,7 +5214,7 @@ class PreviewComponent {
|
|
|
5224
5214
|
professionId: form.professionId ?? null,
|
|
5225
5215
|
professionName: form.professionName ?? '',
|
|
5226
5216
|
starRating: (form.stars || 0) * 2,
|
|
5227
|
-
year: form.year,
|
|
5217
|
+
year: form.year ?? 0,
|
|
5228
5218
|
profileVisibility: form.profileVisibility,
|
|
5229
5219
|
notes: form.notes,
|
|
5230
5220
|
});
|
|
@@ -5391,10 +5381,6 @@ class PreviewComponent {
|
|
|
5391
5381
|
return;
|
|
5392
5382
|
if (this.isBlankOrNull(form.professionId))
|
|
5393
5383
|
return;
|
|
5394
|
-
if (!form.stars || form.stars <= 0)
|
|
5395
|
-
return;
|
|
5396
|
-
if (form.year === null || form.year === undefined)
|
|
5397
|
-
return;
|
|
5398
5384
|
this.isSavingProfession = true;
|
|
5399
5385
|
try {
|
|
5400
5386
|
const nextProfessions = [...(current.professions ?? [])];
|
|
@@ -5420,7 +5406,7 @@ class PreviewComponent {
|
|
|
5420
5406
|
professionGroup: form.professionGroup,
|
|
5421
5407
|
residentialCommercial: form.residentialCommercial,
|
|
5422
5408
|
starRating: (form.stars || 0) * 2,
|
|
5423
|
-
year: form.year,
|
|
5409
|
+
year: form.year ?? 0,
|
|
5424
5410
|
notes: form.notes,
|
|
5425
5411
|
});
|
|
5426
5412
|
await this.persistProfession(metaIndex, !this.isAddingProfession());
|
|
@@ -5607,10 +5593,6 @@ class PreviewComponent {
|
|
|
5607
5593
|
const nextName = (form.name || '').trim();
|
|
5608
5594
|
if (!nextName)
|
|
5609
5595
|
return;
|
|
5610
|
-
if (!form.stars || form.stars <= 0)
|
|
5611
|
-
return;
|
|
5612
|
-
if (form.year === null || form.year === undefined)
|
|
5613
|
-
return;
|
|
5614
5596
|
this.isSavingTool = true;
|
|
5615
5597
|
try {
|
|
5616
5598
|
const nextTools = [...(current.tools ?? [])];
|
|
@@ -5636,7 +5618,7 @@ class PreviewComponent {
|
|
|
5636
5618
|
professionId: form.professionId ?? null,
|
|
5637
5619
|
professionName: form.professionName ?? '',
|
|
5638
5620
|
starRating: (form.stars || 0) * 2,
|
|
5639
|
-
year: form.year,
|
|
5621
|
+
year: form.year ?? 0,
|
|
5640
5622
|
profileVisibility: form.profileVisibility,
|
|
5641
5623
|
notes: form.notes,
|
|
5642
5624
|
});
|
|
@@ -6883,7 +6865,7 @@ class PreviewComponent {
|
|
|
6883
6865
|
number: exp.credentialId ?? null,
|
|
6884
6866
|
issuedBy: exp.issuingOrganization,
|
|
6885
6867
|
documentTypeName: exp.name,
|
|
6886
|
-
|
|
6868
|
+
userProfessionId: exp.professionId ?? null,
|
|
6887
6869
|
professionName: exp.professionName ?? '',
|
|
6888
6870
|
issueDate: this.formatDate(exp.issueDate),
|
|
6889
6871
|
expiryDate: this.formatDate(exp.expiryDate),
|
|
@@ -6944,7 +6926,7 @@ class PreviewComponent {
|
|
|
6944
6926
|
userName: this.payloadUserName,
|
|
6945
6927
|
skillSetId: null,
|
|
6946
6928
|
skillSetName: exp,
|
|
6947
|
-
|
|
6929
|
+
userProfessionId: m.professionId ?? null,
|
|
6948
6930
|
professionName: m.professionName ?? '',
|
|
6949
6931
|
notes: m.notes ?? "",
|
|
6950
6932
|
year: m.year ?? null,
|
|
@@ -6970,7 +6952,7 @@ class PreviewComponent {
|
|
|
6970
6952
|
userName: this.payloadUserName,
|
|
6971
6953
|
toolId: null,
|
|
6972
6954
|
toolName: exp,
|
|
6973
|
-
|
|
6955
|
+
userProfessionId: m.professionId ?? null,
|
|
6974
6956
|
professionName: m.professionName ?? '',
|
|
6975
6957
|
starRating: m.starRating ?? null,
|
|
6976
6958
|
year: m.year ?? null,
|
|
@@ -7400,7 +7382,7 @@ class PreviewComponent {
|
|
|
7400
7382
|
}
|
|
7401
7383
|
}
|
|
7402
7384
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PreviewComponent, deps: [{ token: CredentialingStore }, { token: FileService }, { token: UserSkillSetService }, { token: UserToolService }, { token: ProfessionService }, { token: UserProfessionService }, { token: UserDocumentService }, { token: UserEducationService }, { token: UserDetailService }, { token: UserExperienceService }, { token: i1$4.TokenService }, { token: i1$4.RoleContextService }, { token: ProvidersService }, { token: FrontEndProvidersService }, { token: i0.ChangeDetectorRef }, { token: LIBRARY_CONFIG }], target: i0.ɵɵFactoryTarget.Component });
|
|
7403
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: PreviewComponent, isStandalone: true, selector: "app-preview", inputs: { providerId: "providerId", isResume: "isResume", resumeModel: "resumeModel", providerName: "providerName", roleData: "roleData", cloudfrontUrl: "cloudfrontUrl", signatureFileId: "signatureFileId", signatureUrl: "signatureUrl" }, outputs: { backToParent: "backToParent" }, viewQueries: [{ propertyName: "companyForm", first: true, predicate: ["companyForm"], descendants: true }], ngImport: i0, template: "<div class=\"preview-page-header\" *ngIf=\"!isResume\">\r\n <div class=\"d-flex align-items-center gap-2 mb-1\">\r\n <h2 class=\"preview-title mb-0\">Review Extracted Information</h2>\r\n </div>\r\n <p class=\"preview-subtitle text-muted\">We\u2019ve automatically extracted details from your uploaded resume. Please review and confirm accuracy before proceeding.</p>\r\n</div>\r\n\r\n\r\n<div [ngClass]=\"isResume ? '' : 'container py-4'\" [class.provider-layout]=\"roleData?.role?.name === 'Provider'\">\r\n\r\n <!-- Provider initial setup: combined company + personal form (shown until both APIs succeed) -->\r\n <div class=\"section mb-5\" *ngIf=\"roleData?.role?.name === 'Provider' && !hasUserDetailData && !isResume\">\r\n <div class=\"d-flex align-items-center gap-2 mb-3 section-header-title\">\r\n <img src=\"/assets/images/icons/building.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Company & Personal Details</h5>\r\n <span class=\"badge border section-flag bg-warning-subtle text-warning\">Required to continue</span>\r\n </div>\r\n <div class=\"card shadow-sm border-0\">\r\n <div class=\"card-header bg-white fw-semibold\">Company Information</div>\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-3\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': (!tempCompanyDetails.companyName?.trim() && companyFormSubmitted) || companyNameError}\"\r\n [(ngModel)]=\"tempCompanyDetails.companyName\" name=\"setupCompanyName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyName?.trim() && companyFormSubmitted\">Company name is required</div>\r\n <div class=\"invalid-feedback\" *ngIf=\"companyNameError\">{{ companyNameError }}</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" maxlength=\"14\" inputmode=\"numeric\"\r\n (input)=\"phoneMask($event, 'company')\" (keypress)=\"allowOnlyNumbers($event)\"\r\n [ngClass]=\"{'is-invalid': companyFormSubmitted && (!tempCompanyDetails.companyPhoneNumber?.trim() || getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10)}\"\r\n [(ngModel)]=\"tempCompanyDetails.companyPhoneNumber\" name=\"setupCompanyPhone\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyPhoneNumber?.trim() && companyFormSubmitted\">Company phone is required</div>\r\n <div class=\"invalid-feedback\" *ngIf=\"tempCompanyDetails.companyPhoneNumber?.trim() && getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10 && companyFormSubmitted\">Company phone must be 10 digits</div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Company Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempCompanyDetails.address1\" name=\"setupCompanyAddress\"\r\n [options]=\"options\" inputClass=\"form-control form-control-sm\"\r\n [invalid]=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempCompanyDetails.latitude\" [initialLng]=\"tempCompanyDetails.longitude\"\r\n (addressResolved)=\"onCompanyAddressResolved($event)\"\r\n (manualEdit)=\"onCompanyAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\">Address is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.city?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.city\" name=\"setupCompanyCity\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.city?.trim() && companyFormSubmitted\">City is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.state?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.state\" name=\"setupCompanyState\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.state?.trim() && companyFormSubmitted\">State is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.zipcode?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.zipcode\" name=\"setupCompanyZip\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.zipcode?.trim() && companyFormSubmitted\">Zip code is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.country?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.country\" name=\"setupCompanyCountry\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.country?.trim() && companyFormSubmitted\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <input type=\"file\" accept=\".png,.jpg,.jpeg\" class=\"form-control form-control-sm\" (change)=\"uploadCompanyImage($event)\" name=\"setupCompanyLogo\" />\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"tempCompanyLogoUrl\">\r\n <label class=\"small text-muted d-block\">Logo Preview</label>\r\n <img [src]=\"tempCompanyLogoUrl\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-header bg-white fw-semibold border-top\">Personal Information</div>\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-3\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">First Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.firstName?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.firstName\" name=\"setupFirstName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.firstName?.trim() && companyFormSubmitted\">First name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Last Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.lastName?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.lastName\" name=\"setupLastName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.lastName?.trim() && companyFormSubmitted\">Last name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Email <span class=\"text-danger\">*</span></label>\r\n <input type=\"email\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.email?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.email\" name=\"setupEmail\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.email?.trim() && companyFormSubmitted\">Email is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Phone Number <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" maxlength=\"14\" inputmode=\"numeric\"\r\n (input)=\"phoneMask($event, 'profile')\" (keypress)=\"allowOnlyNumbers($event)\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.phone?.trim() && companyFormSubmitted}\"\r\n [ngModel]=\"tempProfile?.phone\" name=\"setupPhone\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.phone?.trim() && companyFormSubmitted\">Phone number is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Home Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempProfile.address\" name=\"setupAddress\" [options]=\"options\"\r\n inputClass=\"form-control form-control-sm\" [invalid]=\"!tempProfile?.address?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempProfile.latitude\" [initialLng]=\"tempProfile.longitude\"\r\n (addressResolved)=\"onUserAddressResolved($event)\"\r\n (manualEdit)=\"onUserAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.address?.trim() && companyFormSubmitted\">Home address is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.city?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.city\" name=\"setupUserCity\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.city?.trim() && companyFormSubmitted\">City is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.state?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.state\" name=\"setupUserState\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.state?.trim() && companyFormSubmitted\">State is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.zipCode?.trim() && companyFormSubmitted}\"\r\n [ngModel]=\"tempProfile?.zipCode\" (ngModelChange)=\"tempProfile.zipCode = sanitizeZipCode($event)\"\r\n name=\"setupUserZip\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.zipCode?.trim() && companyFormSubmitted\">Zip code is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.country?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.country\" name=\"setupUserCountry\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.country?.trim() && companyFormSubmitted\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [(ngModel)]=\"tempProfile.jobTitle\" name=\"setupJobTitle\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control form-control-sm\" [(ngModel)]=\"tempProfile.yearsOfExperience\"\r\n [ngClass]=\"{'is-invalid': !(tempProfile?.yearsOfExperience > 0) && companyFormSubmitted}\"\r\n name=\"setupYearsOfExp\" min=\"1\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!(tempProfile?.yearsOfExperience > 0) && companyFormSubmitted\">Years of experience is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Profile Picture</label>\r\n <input #setupHeadshotFile type=\"file\" accept=\".png,.jpg,.jpeg\" class=\"d-none\" (change)=\"uploadHeadshotImage($event)\" name=\"setupHeadshotFile\" />\r\n <div class=\"position-relative\">\r\n <input type=\"text\" class=\"form-control form-control-sm pe-5\" [value]=\"headshotFileName\" readonly\r\n placeholder=\"Upload Profile Picture\" (click)=\"setupHeadshotFile.click()\" />\r\n <img *ngIf=\"!isHeadshotLoading\" src=\"assets/images/icons/upload.svg\" alt=\"Upload\" class=\"upload-icon\" style=\"position:absolute;right:12px;top:50%;transform:translateY(-50%);cursor:pointer;width:18px;\" (click)=\"setupHeadshotFile.click()\" />\r\n <div *ngIf=\"isHeadshotLoading\" style=\"position:absolute;right:12px;top:50%;transform:translateY(-50%);\">\r\n <span class=\"spinner-border spinner-border-sm text-primary\"></span>\r\n </div>\r\n </div>\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"headshotPreviewUrl\">\r\n <label class=\"small text-muted d-block\">Preview</label>\r\n <img [src]=\"headshotPreviewUrl\" class=\"img-thumbnail rounded-circle\" style=\"width:64px;height:64px;object-fit:cover;\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-footer d-flex align-items-center justify-content-end gap-2\">\r\n <span *ngIf=\"providerSetupError\" class=\"small text-danger me-auto\">{{ providerSetupError }}</span>\r\n <button class=\"btn btn-success px-5 \"\r\n [disabled]=\"isSavingProviderSetup || !isProviderSetupFormComplete\"\r\n (click)=\"saveProviderSetup()\">\r\n <span *ngIf=\"isSavingProviderSetup\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingProviderSetup ? 'Saving...' : 'Save & Continue' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\" *ngIf=\"roleData?.role?.name !== 'Provider' || hasUserDetailData\">\r\n <div *ngIf=\"details() as data; else loading\">\r\n <div class=\"card profile-header-card shadow-sm border-0 rounded-3 overflow-hidden\" *ngIf=\"!isEditMode()\">\r\n <div class=\"card-body p-0\">\r\n <div class=\"preview-card-gradient\">\r\n <div class=\"d-flex justify-content-between align-items-start mb-4\">\r\n <div class=\"d-flex align-items-start gap-3\">\r\n <div class=\"profile-avatar-circle\" *ngIf=\"!headshotPreviewUrl\">\r\n {{ (data.firstName?.[0] || '') }}{{ (data.lastName?.[0] || '') }}\r\n </div>\r\n <img *ngIf=\"headshotPreviewUrl\" [src]=\"headshotPreviewUrl\"\r\n class=\"rounded-circle\" style=\"width:56px;height:56px;object-fit:cover;\" alt=\"Profile\" />\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h2 class=\"fw-bold mb-1\">{{ data.firstName }} {{ data.lastName }}</h2>\r\n <span *ngIf=\"basicSectionHasIssues()\" class=\"badge bg-warning-subtle text-warning border section-flag\">\r\n Missing info\r\n </span>\r\n <span class=\"badge border section-flag\"\r\n [ngClass]=\"basicDetailsSaved ? 'bg-success-subtle text-success' : 'bg-warning-subtle text-warning'\">\r\n {{ basicDetailsSaved ? 'Saved' : 'Not saved yet' }}\r\n </span>\r\n </div>\r\n <p class=\"text-muted\">{{ data.jobTitle }} \u2022 {{ data.yearsOfExperience }} Years Exp.</p>\r\n <div *ngIf=\"basicIssues().length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ basicIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <span class=\"badge bg-primary-subtle text-primary border p-2\">Email Verified</span>\r\n </div>\r\n\r\n </div>\r\n <div class=\"px-4 py-3\">\r\n <div class=\"row g-4\">\r\n <div class=\"col-12 border-bottom pb-2\">\r\n <h6 class=\"text-uppercase small fw-bold text-muted\">Summary</h6>\r\n <p class=\"text-secondary small mb-0\">{{ data.summary }}</p>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/envelope.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Email</span>\r\n <span class=\"field-value-sm d-block\">{{ data.email }}</span>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/telephone.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Phone</span>\r\n <span class=\"field-value-sm d-block\">{{ data.phone }}</span>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/geo-alt.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Location</span>\r\n <span class=\"field-value-sm d-block\">{{ data.address }}, {{ data.city }}, {{ data.state }}, {{ data.zipCode }}, {{ data.country }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer d-flex align-items-center justify-content-between\">\r\n <span *ngIf=\"!basicDetailsSaved\" class=\"small text-warning fw-semibold\">\r\n <img src=\"/assets/images/icons/exclamation-circle.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" /> Click \"Edit\" to review and save your basic info.\r\n </span>\r\n <span *ngIf=\"basicDetailsSaved\" class=\"small text-success fw-semibold\">\r\n <img src=\"/assets/images/icons/check-circle.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" /> Basic details saved.\r\n </span>\r\n <button class=\"btn btn-sm btn-primary px-4 ms-auto\" (click)=\"toggleEdit()\">Edit</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"isEditMode()\">\r\n <div class=\"card-header bg-white fw-bold\">Update Profile</div>\r\n <div class=\"card-body p-4\">\r\n <form class=\"row g-3\" #basicForm=\"ngForm\" novalidate>\r\n <div *ngIf=\"basicIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ basicIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">First Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.firstName\" name=\"fName\"\r\n placeholder=\"First Name\" required #fName=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"fName.invalid && (fName.dirty || fName.touched)\">First name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Last Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.lastName\" name=\"lName\"\r\n placeholder=\"Last Name\" required #lName=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"lName.invalid && (lName.dirty || lName.touched)\">Last name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Email <span class=\"text-danger\">*</span></label>\r\n <input type=\"email\" class=\"form-control\" [(ngModel)]=\"tempProfile.email\" name=\"email\" placeholder=\"Email\"\r\n required email #email=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"email.invalid && (email.dirty || email.touched)\">\r\n <span *ngIf=\"email.errors?.['required']\">Email is required</span>\r\n <span *ngIf=\"email.errors?.['email']\">Email format is invalid</span>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Phone Number <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"tempProfile.phone\" (input)=\"phoneMask($event, 'profile')\"\r\n name=\"phone\" placeholder=\"Phone (10 digits)\" (keypress)=\"allowOnlyNumbers($event)\"\r\n required pattern=\"^\\(\\d{3}\\) \\d{3}-\\d{4}$\" maxlength=\"14\" inputmode=\"numeric\" #phone=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"phone.invalid && (phone.dirty || phone.touched)\">\r\n <span *ngIf=\"phone.errors?.['required']\">Phone number is required</span>\r\n <span *ngIf=\"phone.errors?.['pattern']\">Phone number must be 10 digits</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\"></span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.jobTitle\" name=\"jobTitle\"\r\n placeholder=\"Job Title\" #jobTitle=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"jobTitle.invalid && (jobTitle.dirty || jobTitle.touched)\">Job\r\n title is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [ngClass]=\"{'is-invalid': !(tempProfile?.yearsOfExperience > 0)}\"\r\n [(ngModel)]=\"tempProfile.yearsOfExperience\"\r\n name=\"yearsOfExperience\" placeholder=\"Years of Experience\" required min=\"1\"\r\n #yearsOfExperience=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!(tempProfile?.yearsOfExperience > 0)\">\r\n Years of experience is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Home Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempProfile.address\" name=\"address\" [options]=\"options\"\r\n placeholder=\"Home Address\" required #address=\"ngModel\"\r\n [invalid]=\"address.invalid && (address.dirty || address.touched)\"\r\n [initialLat]=\"tempProfile.latitude\" [initialLng]=\"tempProfile.longitude\"\r\n (addressResolved)=\"onUserAddressResolved($event)\"\r\n (manualEdit)=\"onUserAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"address.invalid && (address.dirty || address.touched)\">Home\r\n address is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.city\" name=\"city\" placeholder=\"City\"\r\n required #city=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"city.invalid && (city.dirty || city.touched)\">City is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.state\" name=\"state\" placeholder=\"State\"\r\n required #state=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"state.invalid && (state.dirty || state.touched)\">State is\r\n required</div>\r\n </div>\r\n\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"tempProfile.zipCode\"\r\n (ngModelChange)=\"tempProfile.zipCode = sanitizeZipCode($event)\" name=\"zipCode\" placeholder=\"Zip Code\"\r\n required pattern=\"^\\d{1,6}$\" maxlength=\"6\" inputmode=\"numeric\" #zipCode=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"zipCode.invalid && (zipCode.dirty || zipCode.touched)\">Zip code\r\n is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"zipCode.errors?.['pattern'] && (zipCode.dirty || zipCode.touched)\">\r\n Zip code must be up to 6 digits\r\n </div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.country\" name=\"country\"\r\n placeholder=\"Country\" required #country=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"country.invalid && (country.dirty || country.touched)\">Country\r\n is required</div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Summary</label>\r\n <textarea class=\"form-control\" rows=\"3\" [(ngModel)]=\"tempProfile.summary\" name=\"sum\"\r\n placeholder=\"Summary\"></textarea>\r\n </div>\r\n\r\n\r\n </form>\r\n </div>\r\n <div class=\"card-footer text-end gap-2 d-flex justify-content-end\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancel()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingBasic || !isBasicFormValid\" (click)=\"save()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Saving...' : 'Save Changes' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5 provider-company-first\" *ngIf=\"roleData?.role?.name === 'Provider' && hasUserDetailData && !isResume\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/building.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Company Details</h5>\r\n <span *ngIf=\"companyDetailsSaved\"\r\n class=\"badge border section-flag bg-success-subtle text-success\">\r\n Saved\r\n </span>\r\n <span *ngIf=\"!companyDetailsSaved\"\r\n class=\"badge border section-flag bg-warning-subtle text-warning\">\r\n Not saved yet\r\n </span>\r\n </div>\r\n <button class=\"btn btn-sm btn-primary px-4\" (click)=\"toggleCompanyEdit()\">Edit</button>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"!isCompanyEditMode()\">\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-4\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name</label>\r\n <span class=\"fw-bold small\">{{ companyDetails()?.companyName}}</span>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone</label>\r\n <span class=\"fw-bold small\">{{ companyDetails()?.companyPhoneNumber}}</span>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Company Address</label>\r\n <span class=\"small\">{{ companyDetails()?.address1}}, {{ companyDetails()?.city}}, {{ companyDetails()?.state}}, {{ companyDetails()?.zipcode}}, {{ companyDetails()?.country}}</span>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"companyLogoUrl()\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <img [src]=\"companyLogoUrl()\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"isCompanyEditMode()\">\r\n <div class=\"card-header bg-white fw-bold\">Update Company Details</div>\r\n <div class=\"card-body p-4\">\r\n <form class=\"row g-3\" #companyForm=\"ngForm\" novalidate>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': (!tempCompanyDetails.companyName?.trim() && companyFormSubmitted) || companyNameError }\"\r\n [(ngModel)]=\"tempCompanyDetails.companyName\" name=\"companyName\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyName?.trim() && companyFormSubmitted\">\r\n Company name is required\r\n </div>\r\n <div class=\"invalid-feedback\" *ngIf=\"companyNameError\">\r\n {{ companyNameError }}\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone <span class=\"text-danger\">*</span></label>\r\n <input (input)=\"phoneMask($event, 'company')\" type=\"text\" maxlength=\"14\" (keypress)=\"allowOnlyNumbers($event)\" inputmode=\"numeric\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{ 'is-invalid': companyFormSubmitted && (!tempCompanyDetails.companyPhoneNumber?.trim() || getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10) }\"\r\n [(ngModel)]=\"tempCompanyDetails.companyPhoneNumber\" name=\"companyPhoneNumber\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyPhoneNumber?.trim() && companyFormSubmitted\">\r\n Company phone is required\r\n </div>\r\n <div class=\"invalid-feedback\" *ngIf=\"tempCompanyDetails.companyPhoneNumber?.trim() && getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10 && companyFormSubmitted\">\r\n Company phone must be 10 digits\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempCompanyDetails.address1\" name=\"address1\" [options]=\"options\"\r\n required [invalid]=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempCompanyDetails.latitude\" [initialLng]=\"tempCompanyDetails.longitude\"\r\n (addressResolved)=\"onCompanyAddressResolved($event)\"\r\n (manualEdit)=\"onCompanyAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\">\r\n Address is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.city?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.city\" name=\"city\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.city?.trim() && companyFormSubmitted\">\r\n City is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.state?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.state\" name=\"state\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.state?.trim() && companyFormSubmitted\">\r\n State is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.zipcode?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.zipcode\" name=\"zipcode\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.zipcode?.trim() && companyFormSubmitted\">\r\n Zip code is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.country?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.country\" name=\"country\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.country?.trim() && companyFormSubmitted\">\r\n Country is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <input #uploadCompanyFile type=\"file\" accept=\".png,.jpg,.jpeg\" (change)=\"uploadCompanyImage($event)\" class=\"form-control\" />\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"tempCompanyLogoUrl\">\r\n <label class=\"small text-muted d-block\">Logo Preview</label>\r\n <img [src]=\"tempCompanyLogoUrl\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"card-footer text-end gap-2 d-flex justify-content-end\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelCompanyEdit()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingCompany\" \r\n (click)=\"saveCompanyDetails()\">\r\n <span *ngIf=\"isSavingCompany\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCompany ? 'Saving...' : 'Save Changes' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div [class.section-locked]=\"roleData?.role?.name === 'Provider' && !hasUserDetailData\">\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/briefcase-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Profession</h5>\r\n <span *ngIf=\"selectedProfessionCount > 0\" class=\"badge border section-flag bg-warning-subtle text-warning\">\r\n {{ selectedProfessionCount }} selected\r\n </span>\r\n </div>\r\n <button type=\"button\" class=\"btn btn-sm btn-primary px-4\"\r\n [disabled]=\"selectedProfessionCount === 0 || isSavingProfessionsTable\"\r\n (click)=\"submitProfessions()\">\r\n <span *ngIf=\"isSavingProfessionsTable\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingProfessionsTable ? 'Saving...' : professionSubmitLabel }}\r\n </button>\r\n </div>\r\n\r\n <div class=\"mb-3\">\r\n <input type=\"text\" class=\"form-control profession-search-input\" placeholder=\"Search or Add Profession\"\r\n [(ngModel)]=\"professionSearchQry\" name=\"professionSearchQry\"\r\n (keydown.enter)=\"createManualProfessionRow()\" />\r\n </div>\r\n\r\n <div class=\"table-responsive bg-white border rounded shadow-sm\">\r\n <table class=\"table align-middle mb-0 profession-table\">\r\n <thead>\r\n <tr>\r\n <th style=\"width: 36px;\"></th>\r\n <th>Profession Name</th>\r\n <th>Group</th>\r\n <th>Type</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <ng-container *ngFor=\"let p of filteredProfessionTypes\">\r\n <tr [class.profession-row-selected]=\"getProfessionSelection(p.id).selected\">\r\n <td style=\"text-align: center;\">\r\n <input type=\"checkbox\" class=\"form-check-input\" [checked]=\"getProfessionSelection(p.id).selected\"\r\n (change)=\"onProfessionRowCheck(p, $event)\" />\r\n </td>\r\n <td>\r\n {{ p.professionName }}\r\n <span *ngIf=\"isProfessionSaved(p.id)\" class=\"badge border bg-success-subtle text-success ms-1\">Saved</span>\r\n </td>\r\n <td>\r\n <ng-container *ngIf=\"p.isManual; else groupText\">\r\n <select class=\"form-select form-select-sm profession-inline-select\" [ngModel]=\"p.professionGroup\"\r\n (ngModelChange)=\"setManualProfessionGroup(p, $event)\" [name]=\"'manualGroup-' + p.id\">\r\n <option [ngValue]=\"null\" disabled>Select group</option>\r\n <option *ngFor=\"let g of professionGroupOptions\" [ngValue]=\"g\">{{ g }}</option>\r\n </select>\r\n </ng-container>\r\n <ng-template #groupText>{{ p.professionGroup || '\u2013' }}</ng-template>\r\n </td>\r\n <td>\r\n <ng-container *ngIf=\"p.isManual; else typeText\">\r\n <select class=\"form-select form-select-sm profession-inline-select\" [ngModel]=\"p.residentialCommercial\"\r\n (ngModelChange)=\"setManualProfessionType(p, $event)\" [name]=\"'manualType-' + p.id\">\r\n <option [ngValue]=\"null\" disabled>Select type</option>\r\n <option *ngFor=\"let t of professionTypeOptions\" [ngValue]=\"t\">{{ t }}</option>\r\n </select>\r\n </ng-container>\r\n <ng-template #typeText>{{ p.residentialCommercial || '\u2013' }}</ng-template>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"getProfessionSelection(p.id).selected\" class=\"profession-row-selected\">\r\n <td></td>\r\n <td colspan=\"3\">\r\n <div *ngIf=\"p.isManual && !isManualRowReady(p.id)\" class=\"small text-danger mb-2\">\r\n Select a Group and Type above to enable saving this profession.\r\n </div>\r\n <div class=\"d-flex flex-wrap align-items-start gap-4 py-2\">\r\n <div class=\"flex-shrink-0\" style=\"white-space: nowrap;\">\r\n <label class=\"small text-muted d-block mb-1\">Self Ability Rating</label>\r\n <span *ngFor=\"let s of [1,2,3,4,5]\" class=\"fs-5\" style=\"cursor: pointer;\"\r\n (click)=\"setProfessionRowStars(p, s)\"\r\n [class.text-warning]=\"(getProfessionSelection(p.id).starRating || 0) / 2 >= s\"\r\n [class.text-muted]=\"(getProfessionSelection(p.id).starRating || 0) / 2 < s\">\u2605</span>\r\n </div>\r\n <div class=\"flex-shrink-0\" style=\"white-space: nowrap;\">\r\n <label class=\"small text-muted d-block mb-1\">Experience</label>\r\n <div class=\"d-flex align-items-center gap-1\">\r\n <input type=\"number\" class=\"form-control form-control-sm\" style=\"width: 70px;\" min=\"0\" max=\"30\"\r\n [(ngModel)]=\"getProfessionSelection(p.id).year\" [name]=\"'profYear-' + p.id\" />\r\n <span class=\"small text-muted\">Yrs</span>\r\n </div>\r\n </div>\r\n <div class=\"d-flex flex-column align-items-center flex-shrink-0\" style=\"min-width: 80px; white-space: nowrap;\">\r\n <label class=\"small text-muted d-block mb-1\">Visibility</label>\r\n <input type=\"checkbox\" class=\"profession-visibility-checkbox\" [(ngModel)]=\"getProfessionSelection(p.id).profileVisibility\"\r\n [name]=\"'profVis-' + p.id\" />\r\n </div>\r\n <div class=\"flex-grow-1\" style=\"min-width: 200px;\">\r\n <label class=\"small text-muted d-block mb-1\">Notes</label>\r\n <textarea rows=\"3\" class=\"form-control form-control-sm profession-notes-input\" [(ngModel)]=\"getProfessionSelection(p.id).notes\"\r\n [name]=\"'profNotes-' + p.id\" placeholder=\"Notes\"></textarea>\r\n </div>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-container>\r\n <tr *ngIf=\"hasNoProfessionMatches\">\r\n <td colspan=\"4\" class=\"text-center small py-3\">\r\n <span class=\"text-muted\">No professions found for \"{{ professionSearchQry?.trim() }}\".</span>\r\n <button type=\"button\" class=\"btn btn-sm btn-primary ms-2\" (click)=\"createManualProfessionRow()\">\r\n Add \"{{ professionSearchQry?.trim() }}\"\r\n </button>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"!professionSearchQry?.trim() && filteredProfessionTypes.length === 0\">\r\n <td colspan=\"4\" class=\"text-center text-muted small py-3\">No professions found.</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/briefcase-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Work Experience</h5>\r\n <span *ngIf=\"experience().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"workSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ workSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"experience().length === 0 || !workSectionHasUnsavedItems() || isSavingWork || isAddingJob() || editingJobIndex() !== null\"\r\n (click)=\"confirmAllWork()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add work experience\" (click)=\"addJob()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"experience().length === 0 && !isAddingJob()\" class=\"empty-state-wrap mb-3\" role=\"button\"\r\n (click)=\"addJob()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/briefcase.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No work experience added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3\">\r\n <div *ngIf=\"isAddingJob() && tempJob()\" class=\"list-group-item p-0 border-0\">\r\n <div class=\"form-panel mb-2\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.jobTitle\"\r\n (ngModelChange)=\"patchTempJob({ jobTitle: $event })\" name=\"newJobTitle\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.company\"\r\n (ngModelChange)=\"patchTempJob({ company: $event })\" name=\"newCompany\" />\r\n </div>\r\n <div class=\"align-items-end col-md-12 d-flex justify-content-end pe-3\">\r\n <div class=\"form-check\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"tempJob()?.isCurrent\"\r\n (ngModelChange)=\"setTempJobIsCurrent($event)\" name=\"newIsCurrent\" id=\"newIsCurrent\" />\r\n <label class=\"form-check-label\" for=\"newIsCurrent\">Current</label>\r\n </div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.country\"\r\n (ngModelChange)=\"patchTempJob({ country: $event })\" name=\"newCountry\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.state\"\r\n (ngModelChange)=\"patchTempJob({ state: $event })\" name=\"newState\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.city\"\r\n (ngModelChange)=\"patchTempJob({ city: $event })\" name=\"newCity\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempJob()?.startDate)\"\r\n (bsValueChange)=\"setTempJobMonth('startDate', $event)\" name=\"newStartDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.startDate)\">Start date is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [disabled]=\"tempJob()?.isCurrent\"\r\n [ngModel]=\"monthInputToDate(tempJob()?.endDate)\" (bsValueChange)=\"setTempJobMonth('endDate', $event)\"\r\n name=\"newEndDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!tempJob()?.isCurrent && isBlank(tempJob()?.endDate)\">End date is\r\n required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"!tempJob()?.isCurrent && isMonthRangeInvalid(tempJob()?.startDate, tempJob()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Responsibilities (one per line)</label>\r\n <textarea rows=\"4\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"(tempJob()?.responsibilities || []).join('\\n')\"\r\n (ngModelChange)=\"updateTempResponsibilities($event)\" name=\"newResponsibilities\"></textarea>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onWorkExperienceFileSelected($event)\" name=\"newWorkAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempJob()?.fileName\">\r\n <span>{{ tempJob()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempJob())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n <div class=\"d-flex justify-content-end gap-2 mt-3\">\r\n <button class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditJob(); $event.stopPropagation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingWork\"\r\n (click)=\"saveEditJob(); $event.stopPropagation()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Uploading...' : workActionLabel(editingJobIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <div *ngFor=\"let job of experience(); let i = index\" class=\"list-group-item p-0 border-0 mb-2\">\r\n\r\n <div class=\"work-accent-item p-3 rounded-3 bg-white border\">\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n <div class=\"d-flex align-items-center cursor-pointer flex-grow-1\" (click)=\"toggleJob(i)\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h6 class=\"mb-0 fw-bold item-title-sm\">{{ job.jobTitle }}</h6>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedWorkItem(i) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedWorkItem(i) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ job.company || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ formatMonthYear(job.startDate) }} - {{ job.isCurrent ? 'Present' :\r\n formatMonthYear(job.endDate) }}</span>\r\n <span class=\"item-meta-line\">{{ job.city }}<span *ngIf=\"job.city && job.state\">, </span>{{ job.state }}<ng-container *ngIf=\"!job.city && !job.state\">\u2014</ng-container></span>\r\n <div *ngIf=\"editingJobIndex() !== i && (workIssuesByIndex()[i] || []).length > 0\"\r\n class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (workIssuesByIndex()[i] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex align-items-center gap-2\">\r\n\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\" (click)=\"startEditJob(i)\"\r\n title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteJob(i);\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n \r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <div class=\"mt-3 p-3 rounded small\" *ngIf=\"expandedIndex() === i\">\r\n <ng-container *ngIf=\"editingJobIndex() !== i; else editJobForm\">\r\n <ul class=\"mb-0\">\r\n <li *ngFor=\"let res of job.responsibilities\">{{ res }}</li>\r\n </ul>\r\n </ng-container>\r\n\r\n <ng-template #editJobForm>\r\n <div *ngIf=\"(workIssuesByIndex()[i] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (workIssuesByIndex()[i] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.jobTitle\"\r\n (ngModelChange)=\"patchTempJob({ jobTitle: $event })\" name=\"jobTitle{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.jobTitle)\">Job title is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.company\"\r\n (ngModelChange)=\"patchTempJob({ company: $event })\" name=\"company{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.company)\">Company name is required</div>\r\n </div>\r\n\r\n <div class=\"align-items-end col-md-12 d-flex justify-content-end pe-3\">\r\n <div class=\"form-check\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"tempJob()?.isCurrent\"\r\n (ngModelChange)=\"setTempJobIsCurrent($event)\" name=\"isCurrent{{ i }}\" id=\"isCurrent{{ i }}\" />\r\n <label class=\"form-check-label\" for=\"isCurrent{{ i }}\">Current</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.country\"\r\n (ngModelChange)=\"patchTempJob({ country: $event })\" name=\"country{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.state\"\r\n (ngModelChange)=\"patchTempJob({ state: $event })\" name=\"state{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.city\"\r\n (ngModelChange)=\"patchTempJob({ city: $event })\" name=\"city{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.city)\">City is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempJob()?.startDate)\"\r\n (bsValueChange)=\"setTempJobMonth('startDate', $event)\" name=\"startDate{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.startDate)\">Start date is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [disabled]=\"tempJob()?.isCurrent\"\r\n [ngModel]=\"monthInputToDate(tempJob()?.endDate)\" (bsValueChange)=\"setTempJobMonth('endDate', $event)\"\r\n name=\"endDate{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!tempJob()?.isCurrent && isBlank(tempJob()?.endDate)\">\r\n End date is required\r\n </div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"!tempJob()?.isCurrent && isMonthRangeInvalid(tempJob()?.startDate, tempJob()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Responsibilities (one per line)</label>\r\n <textarea rows=\"4\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"(tempJob()?.responsibilities || []).join('\\n')\"\r\n (ngModelChange)=\"updateTempResponsibilities($event)\" name=\"responsibilities{{ i }}\"></textarea>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onWorkExperienceFileSelected($event)\" name=\"workAttachment{{ i }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempJob()?.fileName\">\r\n <span>{{ tempJob()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempJob())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n </ng-template>\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-3\" *ngIf=\"editingJobIndex() === i\">\r\n <button class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditJob(); $event.stopPropagation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4 \" [disabled]=\"isSavingWork\"\r\n (click)=\"saveEditJob(); $event.stopPropagation()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Uploading...' : workActionLabel(editingJobIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/patch-check-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Certifications</h5>\r\n <span *ngIf=\"certs().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"certificationSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ certificationSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"certs().length === 0 || !certificationSectionHasUnsavedItems() || isSavingCertification || isAddingCertification() || editingCertificationIndex() !== null\"\r\n (click)=\"confirmAllCertifications()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add certification\" (click)=\"addCertification()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"certs().length === 0 && !isAddingCertification() && editingCertificationIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addCertification()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/patch-check.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No certifications added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3 border\">\r\n <div *ngIf=\"isAddingCertification() && tempCertification()\" class=\"list-group-item py-3 px-3\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"tempCertification()?.professionId\" (change)=\"onCertificationProfessionChange($event)\"\r\n name=\"newCertProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('certificate')\">+</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.name\"\r\n (ngModelChange)=\"patchTempCertification({ name: $event })\" name=\"newCertName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempCertification()?.name)\">Certificate name is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.issuingOrganization || ''\"\r\n (ngModelChange)=\"patchTempCertification({ issuingOrganization: $event || null })\" name=\"newCertOrg\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.state || ''\"\r\n (ngModelChange)=\"patchTempCertification({ state: $event || null })\" name=\"newCertState\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certification Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.credentialId || ''\"\r\n (ngModelChange)=\"patchTempCertification({ credentialId: $event || null })\" name=\"newCertCredentialId\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('issueDate', $event)\" name=\"newCertIssueDate\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('expiryDate', $event)\" name=\"newCertExpiryDate\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempCertification()?.issueDate || null, tempCertification()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onCertificationFileSelected($event)\" name=\"newCertAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempCertification()?.fileName\">\r\n <span>{{ tempCertification()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempCertification())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditCertification()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\"\r\n [disabled]=\"isSavingCertification\"\r\n (click)=\"saveCertificationEditor()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Uploading...' : certificationActionLabel(editingCertificationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let cert of certs(); let ci = index\" class=\"list-group-item py-3 cert-accent-item\">\r\n <ng-container *ngIf=\"editingCertificationIndex() !== ci; else editCert\">\r\n <div class=\"d-flex justify-content-between align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <div class=\"fw-semibold item-title-sm\">{{ cert.name }}</div>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedCertificationItem(ci) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedCertificationItem(ci) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ cert.issuingOrganization || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.credentialId || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.issueDate ? formatMonthYear(cert.issueDate) : '\u2014' }} - {{ cert.expiryDate ? formatMonthYear(cert.expiryDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.state || '\u2014' }}</span>\r\n <div *ngIf=\"(certIssuesByIndex()[ci] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (certIssuesByIndex()[ci] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditCertification(ci)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\"\r\n (click)=\"deleteCertification(ci)\" title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #editCert>\r\n <div *ngIf=\"(certIssuesByIndex()[ci] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (certIssuesByIndex()[ci] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"tempCertification()?.professionId\" (change)=\"onCertificationProfessionChange($event)\"\r\n name=\"certProfessionType{{ ci }}\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('certificate')\">+</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.name\"\r\n (ngModelChange)=\"patchTempCertification({ name: $event })\" name=\"certName{{ ci }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempCertification()?.name)\">Certificate name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.issuingOrganization || ''\"\r\n (ngModelChange)=\"patchTempCertification({ issuingOrganization: $event || null })\"\r\n name=\"certOrg{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.state || ''\"\r\n (ngModelChange)=\"patchTempCertification({ state: $event || null })\" name=\"certState{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certification Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.credentialId || ''\"\r\n (ngModelChange)=\"patchTempCertification({ credentialId: $event || null })\"\r\n name=\"certCredentialId{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('issueDate', $event)\" name=\"certIssue{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('expiryDate', $event)\" name=\"certExpiry{{ ci }}\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempCertification()?.issueDate || null, tempCertification()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onCertificationFileSelected($event)\" name=\"certAttachment{{ ci }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempCertification()?.fileName\">\r\n <span>{{ tempCertification()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempCertification())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditCertification()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingCertification\"\r\n (click)=\"saveCertificationEditor()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Uploading...' : certificationActionLabel(editingCertificationIndex()) }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/card-checklist-warning.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Licenses</h5>\r\n <span *ngIf=\"licenses().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"licenseSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ licenseSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"licenses().length === 0 || !licenseSectionHasUnsavedItems() || isSavingLicense || isAddingLicense() || editingLicenseIndex() !== null\"\r\n (click)=\"confirmAllLicenses()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add license\" (click)=\"addLicense()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"licenses().length === 0 && !isAddingLicense() && editingLicenseIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addLicense()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/card-checklist.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No licenses added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3 border\">\r\n <div *ngIf=\"isAddingLicense() && tempLicense()\" class=\"list-group-item py-3 px-3\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.name\"\r\n (ngModelChange)=\"patchTempLicense({ name: $event })\" name=\"newLicName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempLicense()?.name)\">License name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.issuingAuthority || ''\"\r\n (ngModelChange)=\"patchTempLicense({ issuingAuthority: $event || null })\" name=\"newLicAuthority\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.licenseNumber || ''\"\r\n (ngModelChange)=\"patchTempLicense({ licenseNumber: $event || null })\" name=\"newLicNumber\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.state || ''\"\r\n (ngModelChange)=\"patchTempLicense({ state: $event || null })\" name=\"newLicState\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('issueDate', $event)\" name=\"newLicIssueDate\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('expiryDate', $event)\" name=\"newLicExpiryDate\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempLicense()?.issueDate || null, tempLicense()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">License File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onLicenseFileSelected($event)\" name=\"newLicenseAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempLicense()?.fileName\">\r\n <span>{{ tempLicense()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempLicense())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelEditLicense()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingLicense\"\r\n (click)=\"saveLicenseEditor()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Uploading...' : licenseActionLabel(editingLicenseIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let lic of licenses(); let li = index\" class=\"list-group-item py-3 lic-accent-item\">\r\n <ng-container *ngIf=\"editingLicenseIndex() !== li; else editLic\">\r\n <div class=\"d-flex justify-content-between align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <div class=\"fw-semibold item-title-sm\">{{ lic.name }}</div>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedLicenseItem(li) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedLicenseItem(li) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ lic.issuingAuthority || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.licenseNumber || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.issueDate ? formatMonthYear(lic.issueDate) : '\u2014' }} - {{ lic.expiryDate ? formatMonthYear(lic.expiryDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.state || '\u2014' }}</span>\r\n <div *ngIf=\"(licenseIssuesByIndex()[li] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (licenseIssuesByIndex()[li] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditLicense(li)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteLicense(li)\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #editLic>\r\n <div *ngIf=\"(licenseIssuesByIndex()[li] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (licenseIssuesByIndex()[li] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.name\"\r\n (ngModelChange)=\"patchTempLicense({ name: $event })\" name=\"licName{{ li }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempLicense()?.name)\">License name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.issuingAuthority || ''\"\r\n (ngModelChange)=\"patchTempLicense({ issuingAuthority: $event || null })\" name=\"licAuthority{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.licenseNumber || ''\"\r\n (ngModelChange)=\"patchTempLicense({ licenseNumber: $event || null })\" name=\"licNumber{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.state || ''\"\r\n (ngModelChange)=\"patchTempLicense({ state: $event || null })\" name=\"licState{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('issueDate', $event)\" name=\"licIssue{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('expiryDate', $event)\" name=\"licExpiry{{ li }}\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempLicense()?.issueDate || null, tempLicense()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">License File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onLicenseFileSelected($event)\" name=\"licenseAttachment{{ li }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempLicense()?.fileName\">\r\n <span>{{ tempLicense()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempLicense())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditLicense()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingLicense\"\r\n (click)=\"saveLicenseEditor()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Uploading...' : licenseActionLabel(editingLicenseIndex()) }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/tools.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Tools</h5>\r\n <span *ngIf=\"tools().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"toolsSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ toolsSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"tools().length === 0 || !toolsSectionHasUnsavedItems() || isSavingTool || isToolEditorOpen()\" (click)=\"confirmAllTools()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add tool\" (click)=\"addTool()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex flex-wrap gap-2 p-3 bg-white border rounded shadow-sm\">\r\n <div *ngFor=\"let tool of tools(); let ti = index\" class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\"\r\n class=\"btn btn-light border res-flex d-inline-flex align-items-center gap-2 px-3 py-2\"\r\n (click)=\"openToolEditor(ti)\" title=\"Edit\">\r\n <span class=\"fw-normal item-name-text\">{{ tool }}</span>\r\n <span class=\"badge border ms-1\"\r\n [ngClass]=\"hasUnsavedToolItem(ti) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedToolItem(ti) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n <span *ngIf=\"(toolIssuesByIndex()[ti] || []).length > 0\"\r\n class=\"badge bg-warning-subtle text-warning border ms-1\">\r\n Missing info\r\n </span>\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-danger rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Delete tool\" (click)=\"deleteTool(ti)\">\r\n <span class=\"fw-bold\">\u00D7</span>\r\n </button>\r\n </div>\r\n\r\n <span *ngIf=\"tools().length === 0\" class=\"text-muted small\">No tools added.</span>\r\n </div>\r\n\r\n <div *ngIf=\"isToolEditorOpen()\" class=\"position-fixed top-0 start-0 w-100 h-100\"\r\n style=\"background: rgba(0,0,0,0.35); z-index: 9999999;\" (click)=\"closeToolEditor()\">\r\n <div class=\"container h-100 d-flex align-items-start justify-content-center pt-4\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"card shadow border-0 w-100\" style=\"max-width: 900px;\">\r\n <div class=\"card-header bg-white d-flex align-items-center gap-3\">\r\n <button type=\"button\" class=\"btn btn-link p-0 text-decoration-none\" (click)=\"closeToolEditor()\">\r\n <img src=\"/assets/images/icons/arrow-left-blue.svg\" width=\"20\" height=\"20\" alt=\"\" />\r\n </button>\r\n <div class=\"fw-bold\">{{ isAddingTool() ? 'Add Tool' : ('Edit ' + (toolForm()?.name || '') + ' Tool') }}\r\n </div>\r\n </div>\r\n <div class=\"card-body p-4\">\r\n <div *ngIf=\"toolFormIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ toolFormIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"row g-3\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"toolForm()?.professionId\" (change)=\"onToolProfessionChange($event)\"\r\n name=\"toolProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('tool')\">+</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Tool Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"toolForm()?.name\"\r\n (ngModelChange)=\"patchToolForm({ name: $event })\" name=\"toolName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(toolForm()?.name)\">Tool name is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span\r\n class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempToolStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"(toolForm()?.stars || 0) >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ (toolForm()?.stars || 0) >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ toolForm()?.stars || 0 }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"(toolForm()?.stars || 0) <= 0\">Star rating is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [ngModel]=\"toolForm()?.year\"\r\n (ngModelChange)=\"patchToolForm({ year: $event === '' ? null : +$event })\" name=\"toolYear\" min=\"1\"\r\n max=\"30\" placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"toolForm()?.year === null || toolForm()?.year === undefined\">\r\n Years of experience is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4 text-center\">\r\n <label class=\"small text-muted d-block\">Profile Visibility</label>\r\n <div class=\"form-checks form-switch mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"toolForm()?.profileVisibility\"\r\n (ngModelChange)=\"patchToolForm({ profileVisibility: $event })\" name=\"toolVisible\" id=\"toolVisible\"\r\n style=\"width: 55px;height: 25px;margin-left: -57px;\" />\r\n <label class=\"form-check-label ps-2 pt-1\" for=\"toolVisible\">Visible</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Comment</label>\r\n <textarea rows=\"4\" class=\"form-control\" [ngModel]=\"toolForm()?.notes\"\r\n (ngModelChange)=\"patchToolForm({ notes: $event })\" name=\"toolNotes\"\r\n placeholder=\"Enter additional details (optional)\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer bg-white d-flex justify-content-end gap-2\">\r\n <button *ngIf=\"!isAddingTool() && editingToolIndex() !== null\" type=\"button\"\r\n class=\"btn btn-link text-danger me-auto\" (click)=\"deleteTool(editingToolIndex()!)\">\r\n Delete\r\n </button>\r\n <button type=\"button\" class=\"btn btn-link text-secondary\" (click)=\"closeToolEditor()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary px-4\" [disabled]=\"isSavingTool\" (click)=\"saveToolEditor()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Saving...' : toolActionLabel(editingToolIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row g-4 mb-5\">\r\n <div class=\"col-md-12\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/stars.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Skills</h5>\r\n <span *ngIf=\"skills().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"skillsSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ skillsSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"skills().length === 0 || !skillsSectionHasUnsavedItems() || isSavingSkill || isSkillEditorOpen()\" (click)=\"confirmAllSkills()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add skill\" (click)=\"addSkill()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex flex-wrap gap-2 p-3 bg-white border rounded shadow-sm\">\r\n <div *ngFor=\"let skill of skills(); let si = index\" class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\"\r\n class=\"btn btn-light border res-flex d-inline-flex align-items-center gap-2 px-3 py-2\"\r\n (click)=\"openSkillEditor(si)\" title=\"Edit\">\r\n <span class=\"fw-normal item-name-text\">{{ skill }}</span>\r\n <span class=\"badge border ms-1\"\r\n [ngClass]=\"hasUnsavedSkillItem(si) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedSkillItem(si) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n <span *ngIf=\"(skillIssuesByIndex()[si] || []).length > 0\"\r\n class=\"badge bg-warning-subtle text-warning border ms-1\">\r\n Missing info\r\n </span>\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-danger rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Delete skill\"\r\n (click)=\"deleteSkill(si); $event.stopPropagation()\">\r\n <span class=\"fw-bold\">\u00D7</span>\r\n </button>\r\n </div>\r\n\r\n <span *ngIf=\"skills().length === 0\" class=\"text-muted small\">No skills added.</span>\r\n </div>\r\n <div *ngIf=\"isSkillEditorOpen()\" class=\"position-fixed top-0 start-0 w-100 h-100\"\r\n style=\"background: rgba(0,0,0,0.35); z-index: 9999999;\" (click)=\"closeSkillEditor()\">\r\n <div class=\"container h-100 d-flex align-items-start justify-content-center pt-4\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"card shadow border-0 w-100\" style=\"max-width: 900px;\">\r\n <div class=\"card-header bg-white d-flex align-items-center gap-3\">\r\n <button type=\"button\" class=\"btn btn-link p-0 text-decoration-none\" (click)=\"closeSkillEditor()\">\r\n <img src=\"/assets/images/icons/arrow-left-blue.svg\" width=\"20\" height=\"20\" alt=\"\" />\r\n </button>\r\n <div class=\"fw-bold\">{{ isAddingSkill() ? 'Add Skill' : ('Edit ' + (skillForm()?.name || '') + ' Skill')\r\n }}</div>\r\n </div>\r\n <div class=\"card-body p-4\">\r\n <div *ngIf=\"skillFormIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ skillFormIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"row g-3\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"skillForm()?.professionId\" (change)=\"onSkillProfessionChange($event)\"\r\n name=\"skillProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('skill')\">+</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Skills Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"skillForm()?.name\"\r\n (ngModelChange)=\"patchSkillForm({ name: $event })\" name=\"skillName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(skillForm()?.name)\">Skillset name is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span\r\n class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempSkillStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"(skillForm()?.stars || 0) >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ (skillForm()?.stars || 0) >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ skillForm()?.stars || 0 }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"(skillForm()?.stars || 0) <= 0\">Star rating is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [ngModel]=\"skillForm()?.year\"\r\n (ngModelChange)=\"patchSkillForm({ year: $event === '' ? null : +$event })\" name=\"skillYear\" min=\"1\"\r\n max=\"30\" placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"skillForm()?.year === null || skillForm()?.year === undefined\">Years of experience is\r\n required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4 text-center\">\r\n <label class=\"small text-muted d-block\">Profile Visibility</label>\r\n <div class=\"form-checks form-switch mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"skillForm()?.profileVisibility\"\r\n (ngModelChange)=\"patchSkillForm({ profileVisibility: $event })\" name=\"skillVisible\"\r\n id=\"skillVisible\" style=\"width: 55px;height: 25px;margin-left: -57px;\" />\r\n <label class=\"form-check-label ps-2 pt-1\" for=\"skillVisible\">Visible</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Comment</label>\r\n <textarea rows=\"4\" class=\"form-control\" [ngModel]=\"skillForm()?.notes\"\r\n (ngModelChange)=\"patchSkillForm({ notes: $event })\" name=\"skillNotes\"\r\n placeholder=\"Enter additional details (optional)\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer bg-white d-flex justify-content-end gap-2\">\r\n <button *ngIf=\"!isAddingSkill() && editingSkillIndex() !== null\" type=\"button\"\r\n class=\"btn btn-link text-danger me-auto\" (click)=\"deleteSkill(editingSkillIndex()!)\">\r\n Delete\r\n </button>\r\n <button type=\"button\" class=\"btn btn-link text-secondary\" (click)=\"closeSkillEditor()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary px-4\" [disabled]=\"isSavingSkill\" (click)=\"saveSkillEditor()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Saving...' : skillActionLabel(editingSkillIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row g-4 mb-5\">\r\n <div class=\"col-md-12\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/mortarboard-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Education</h5>\r\n <span *ngIf=\"educationList().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"educationSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ educationSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"educationList().length === 0 || !educationSectionHasUnsavedItems() || isSavingEducation || isAddingEducation() || editingEducationIndex() !== null\"\r\n (click)=\"confirmAllEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add education\" (click)=\"addEducation()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"educationList().length === 0 && !isAddingEducation() && editingEducationIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addEducation()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/mortarboard.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No education added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div *ngIf=\"isAddingEducation() && tempEducation()\" class=\"mb-2\">\r\n <div class=\"form-panel\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.degree\"\r\n (ngModelChange)=\"patchTempEducation({ degree: $event })\" name=\"newEduDegree\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degree)\">Degree / Course name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Institution <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.institution\"\r\n (ngModelChange)=\"patchTempEducation({ institution: $event })\" name=\"newEduInstitution\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree / Course Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"ng-select-sm\" [items]=\"educationDegreeTypeOptions\" [clearable]=\"false\"\r\n placeholder=\"Select degree / course type\" [ngModel]=\"tempEducation()?.degreeType\"\r\n (ngModelChange)=\"patchTempEducation({ degreeType: $event })\" name=\"newEduDegreeType\">\r\n </ng-select>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degreeType)\">Degree / Course type is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.country\"\r\n (ngModelChange)=\"patchTempEducation({ country: $event })\" name=\"newEduCountry\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.state\"\r\n (ngModelChange)=\"patchTempEducation({ state: $event })\" name=\"newEduState\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.city\"\r\n (ngModelChange)=\"patchTempEducation({ city: $event })\" name=\"newEduCity\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.startDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('startDate', $event)\" name=\"newEduStartDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.startDate)\">Start date is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.endDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('endDate', $event)\" name=\"newEduEndDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.endDate)\">End date is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempEducation()?.startDate, tempEducation()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Education File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onEducationFileSelected($event)\" name=\"newEducationAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempEducation()?.fileName\">\r\n <span>{{ tempEducation()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempEducation())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditEducation()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingEducation\"\r\n (click)=\"saveEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Uploading...' : educationActionLabel(editingEducationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let edu of educationList(); let ei = index\" class=\"edu-accent-item p-3 bg-white border rounded-3 shadow-sm mb-2\">\r\n <div class=\"d-flex justify-content-between align-items-start\">\r\n <div class=\"d-flex align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h6 class=\"fw-bold mb-0 item-title-sm\">{{ edu.degree }}</h6>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedEducationItem(ei) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedEducationItem(ei) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ edu.institution || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.degreeType || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.startDate ? formatMonthYear(edu.startDate) : '\u2014' }} - {{ edu.endDate ? formatMonthYear(edu.endDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.city }}<span *ngIf=\"edu.city && edu.state\">, </span>{{ edu.state }}<ng-container *ngIf=\"!edu.city && !edu.state\">\u2014</ng-container></span>\r\n <div *ngIf=\"(educationIssuesByIndex()[ei] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (educationIssuesByIndex()[ei] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\" *ngIf=\"editingEducationIndex() !== ei\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditEducation(ei)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteEducation(ei)\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"editingEducationIndex() === ei\" class=\"mt-3\">\r\n <div *ngIf=\"(educationIssuesByIndex()[ei] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (educationIssuesByIndex()[ei] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.degree\"\r\n (ngModelChange)=\"patchTempEducation({ degree: $event })\" name=\"eduDegree{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degree)\">Degree / Course name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Institution <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.institution\"\r\n (ngModelChange)=\"patchTempEducation({ institution: $event })\" name=\"eduInstitution{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.institution)\">Institution name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree / Course Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"ng-select-sm\" [items]=\"educationDegreeTypeOptions\" [clearable]=\"false\"\r\n placeholder=\"Select degree / course type\" [ngModel]=\"tempEducation()?.degreeType\"\r\n (ngModelChange)=\"patchTempEducation({ degreeType: $event })\" name=\"eduDegreeType{{ ei }}\">\r\n </ng-select>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degreeType)\">Degree / Course type is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.country\"\r\n (ngModelChange)=\"patchTempEducation({ country: $event })\" name=\"eduCountry{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.state\"\r\n (ngModelChange)=\"patchTempEducation({ state: $event })\" name=\"eduState{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.city\"\r\n (ngModelChange)=\"patchTempEducation({ city: $event })\" name=\"eduCity{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.startDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('startDate', $event)\" name=\"eduStartDate{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.startDate)\">Start date is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.endDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('endDate', $event)\" name=\"eduEndDate{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.endDate)\">End date is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempEducation()?.startDate, tempEducation()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Education File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onEducationFileSelected($event)\" name=\"educationAttachment{{ ei }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempEducation()?.fileName\">\r\n <span>{{ tempEducation()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempEducation())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelEditEducation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingEducation\" (click)=\"saveEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Uploading...' : educationActionLabel(editingEducationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n </div>\r\n <div class=\"d-flex gap-3 justify-content-center mt-5 pt-2\" *ngIf=\"!isResume\">\r\n <button class=\"btn btn-outline-secondary preview-back-btn px-5 h-auto\" style=\"border-radius: 5px !important;\" (click)=\"onBackClick()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"me-1\" style=\"vertical-align:-0.1em\">\r\n <path d=\"M11 3 5 8l6 5\" />\r\n </svg> Back\r\n </button>\r\n <button class=\"btn btn-primary preview-dashboard-btn px-5 h-auto\" style=\"border-radius: 5px !important;\" [disabled]=\"!canConfirmAndContinue() || isSavingBasic\"\r\n (click)=\"onGoToDashboardClick()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Saving...' : 'Go to Dashboard' }}\r\n <img *ngIf=\"!isSavingBasic\" src=\"/assets/images/icons/arrow-right-white.svg\" width=\"14\" height=\"14\" class=\"ms-1\" style=\"vertical-align:-0.1em\" alt=\"\" />\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<ng-template #loading>\r\n <div class=\"text-center p-5\">\r\n <div class=\"spinner-border text-primary\"></div>\r\n <p class=\"text-muted mt-2\">Loading data...</p>\r\n </div>\r\n</ng-template>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showCustomProfessionForm\" style=\"z-index: 9999999;\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 420px;\">\r\n <h4 class=\"mb-1\">Add New Profession</h4>\r\n <p class=\"text-muted small mb-4\">This profession isn't in the list yet. Add it here so you can link it to this\r\n {{ customProfessionContext }}.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"customProfessionName\" name=\"customProfessionName\"\r\n placeholder=\"Enter profession name\" />\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Group <span class=\"text-danger\">*</span></label>\r\n <select class=\"form-select\" [(ngModel)]=\"customProfessionGroup\" name=\"customProfessionGroup\">\r\n <option [ngValue]=\"null\" disabled>Select group</option>\r\n <option *ngFor=\"let g of professionGroupOptions\" [ngValue]=\"g\">{{ g }}</option>\r\n </select>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Type <span class=\"text-danger\">*</span></label>\r\n <select class=\"form-select\" [(ngModel)]=\"customProfessionType\" name=\"customProfessionType\">\r\n <option [ngValue]=\"null\" disabled>Select type</option>\r\n <option *ngFor=\"let t of professionTypeOptions\" [ngValue]=\"t\">{{ t }}</option>\r\n </select>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelCustomProfessionForm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\" [disabled]=\"!canSaveCustomProfession || isSavingCustomProfession\"\r\n (click)=\"saveCustomProfession()\">\r\n <span *ngIf=\"isSavingCustomProfession\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCustomProfession ? 'Saving...' : 'Add Profession' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBulkSkillConfirm\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 480px;\">\r\n <h4 class=\"mb-1\">Set Rating for All Skills</h4>\r\n <p class=\"text-muted small mb-4\">Enter a star rating and years of experience (and optionally a profession type) to apply to all skills that are missing these values.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Type</label>\r\n <ng-select [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"bulkSkillProfessionId\" (change)=\"onBulkSkillProfessionChange($event)\"\r\n name=\"bulkSkillProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"bulkSkillStars = s\">\r\n <span [class]=\"bulkSkillStars >= s ? 'text-warning fs-4' : 'text-muted fs-4'\">\r\n {{ bulkSkillStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ bulkSkillStars }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkSkillStars <= 0\">Star rating is required</div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"bulkSkillYear\" min=\"1\" max=\"30\"\r\n placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkSkillYear === null || bulkSkillYear === undefined\">Years of experience is required</div>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelBulkSkillConfirm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\"\r\n [disabled]=\"isSavingSkill || bulkSkillStars <= 0 || bulkSkillYear === null\"\r\n (click)=\"applyBulkSkillConfirm()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Saving...' : 'Apply to All & Save' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBulkToolConfirm\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 480px;\">\r\n <h4 class=\"mb-1\">Set Rating for All Tools</h4>\r\n <p class=\"text-muted small mb-4\">Enter a star rating and years of experience (and optionally a profession type) to apply to all tools that are missing these values.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Type</label>\r\n <ng-select [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"bulkToolProfessionId\" (change)=\"onBulkToolProfessionChange($event)\"\r\n name=\"bulkToolProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"bulkToolStars = s\">\r\n <span [class]=\"bulkToolStars >= s ? 'text-warning fs-4' : 'text-muted fs-4'\">\r\n {{ bulkToolStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ bulkToolStars }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkToolStars <= 0\">Star rating is required</div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"bulkToolYear\" min=\"1\" max=\"30\"\r\n placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkToolYear === null || bulkToolYear === undefined\">Years of experience is required</div>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelBulkToolConfirm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\"\r\n [disabled]=\"isSavingTool || bulkToolStars <= 0 || bulkToolYear === null\"\r\n (click)=\"applyBulkToolConfirm()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Saving...' : 'Apply to All & Save' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBackConfirmPopup\">\r\n <div class=\"confirm-modal-card\">\r\n <h4 class=\"mb-2\">Leave this page?</h4>\r\n <p class=\"text-muted mb-4\">If you go back, only saved data will be retained.</p>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"stayOnPreview()\">Stay</button>\r\n <button type=\"button\" class=\"btn btn-danger h-auto\" (click)=\"proceedBack()\">Proceed Back</button>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showDashboardConfirmPopup\">\r\n <div class=\"confirm-modal-card\">\r\n <h4 class=\"mb-2\">Finish Setup and Continue</h4>\r\n <p class=\"text-muted mb-4\">Save your information and go to your dashboard</p>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" [disabled]=\"isSavingBasic\"\r\n (click)=\"cancelDashboardRedirect()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\" [disabled]=\"isSavingBasic\" (click)=\"goToDashboard()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Proceeding...' : 'Proceed' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{color:#69707d}.res-flex:hover,.res-flex:focus,.res-flex:active{transform:none!important;box-shadow:none!important}::ng-deep .form-check-input{margin-left:unset!important}.profession-search-input{font-size:11px}.profession-search-input::placeholder{font-size:11px}.profession-row-selected{background-color:#f2f4fa!important}.profession-row-selected>td{background-color:#f2f4fa!important}.profession-visibility-checkbox{all:revert;width:16px!important;height:16px!important;min-width:16px!important;max-width:16px!important;margin:7px 0 0!important;padding:0!important;position:static!important;float:none!important;vertical-align:middle!important;background-image:none!important;transform:none!important}.profession-table{font-size:12px;color:#69707d}.profession-table th{font-size:13px;font-weight:600;color:#69707d;text-transform:uppercase;letter-spacing:.03em}.profession-table td{font-size:12px;color:#69707d;font-weight:600;padding-left:0}.profession-table label.small{font-size:12px;color:#69707d}.profession-inline-select{min-width:160px;font-size:12px}.profession-notes-input{min-height:76px;resize:vertical}.container{max-width:900px;margin:30px auto;font-family:Arial,sans-serif;color:#69707d}.preview-page-header{max-width:900px;margin:50px auto 10px;padding:0 12px}.preview-title{font-size:18px;font-weight:700;color:#69707d;margin:0}.preview-subtitle{margin-top:7px;font-size:14px;color:#69707d}.preview-card-gradient h2,.section h5.fw-bold{font-size:18px}.section{margin-bottom:25px}.section-title{font-weight:600;display:block;margin-bottom:8px}.section-title .sub{font-weight:400;color:#777;font-size:13px}.dropdown-box{border:1px solid #ddd;border-radius:8px;padding:12px 15px;display:flex;justify-content:space-between;align-items:center}.icons{display:flex;gap:10px}.icon{cursor:pointer;font-size:14px;color:#777}.card{border:1px solid #ddd;border-radius:5px;padding:20px;background:#fff}.category{border-bottom:1px solid #eee;padding:15px 0}.category:last-child{border-bottom:none}.category-header{display:flex;justify-content:space-between;font-weight:600;margin-bottom:10px}.tags{display:flex;flex-wrap:wrap;gap:10px}.tag{background:#f2f4f7;padding:6px 12px;border-radius:6px;font-size:13px}.footer{text-align:center;margin-top:15px;color:#777;cursor:pointer}.actions{display:flex;justify-content:space-between;margin:50px 0 27px}.text-secondary{white-space:pre-line;font-size:12px;color:#69707d}.extra-small{font-size:.8rem}.card{transition:box-shadow .2s ease}.achievement-section .badge{font-size:.75rem;white-space:normal;text-align:left}.skill-tag .badge{font-weight:500;font-size:.9rem;transition:all .2s ease;cursor:default}.skill-tag .badge:hover{transform:translateY(-2px)}.skill-tag .btn-close{opacity:.5}.skill-tag .btn-close:hover{opacity:1}.bg-light.text-dark.border{background-color:#f8f9fa!important;border-color:#dee2e6!important}.card{transition:all .3s cubic-bezier(.25,.8,.25,1)}.card:hover .bg-light{background-color:#e8f5e9!important}.position-fixed .card:hover{transform:none!important}code{background-color:#f8f9fa;padding:2px 6px;border-radius:4px}.list-group-item{transition:background-color .2s ease-in-out}.list-group-item:hover{background-color:#fcfcfc}.border-dashed{border-style:dashed!important}.tool-card{transition:all .2s ease-in-out;border-radius:12px}.tool-card:hover{transform:translateY(-5px);border-color:var(--bs-primary)!important}.tool-card:hover .icon-box{background-color:var(--bs-primary-subtle)!important}.tool-card .icon-box{width:60px;height:60px;transition:background-color .2s ease}.border-dashed{border:2px dashed #dee2e6!important}.border-dashed:hover{border-color:var(--bs-primary)!important;background-color:#fff!important}.popup{position:fixed;top:20%;right:20px;width:320px;max-width:calc(100vw - 32px);background:#fff;border-radius:10px;padding:16px}.status-row{display:flex;justify-content:space-between;margin:10px 0}.success{color:#2e7d32;font-weight:700}.error{color:#d32f2f}.pending{color:#f9a825}.section-flag{font-weight:600}button.btn.btn-sm.btn-outline-primary{background-color:#4077ad;border-color:#4077ad;color:#fff;border-radius:5px!important}button.btn.btn-sm.btn-outline-primary:hover{background-color:#356895;border-color:#356895;color:#fff}button.btn.btn-sm.btn-outline-danger{border:1px solid #dc3545;color:#dc3545;border-radius:5px!important}button.btn.btn-sm.btn-outline-primary.rounded-circle{background-color:#4077ad;border-color:#4077ad;color:#fff;border-radius:5px!important}button.action-icon-btn{min-width:22px;width:22px;height:22px;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:5px!important;background:transparent!important;border:none!important;line-height:1}button.action-icon-btn.btn-outline-primary{color:#4077ad!important;border-color:#4077ad!important}button.action-icon-btn.btn-outline-danger{color:#dc3545!important}.action-icon-image{width:20px;height:20px;object-fit:contain;display:inline-block}.action-icon-image.edit-icon{filter:brightness(0) saturate(100%) invert(41%) sepia(39%) saturate(774%) hue-rotate(170deg) brightness(91%) contrast(89%)}.action-icon-image.delete-icon{filter:brightness(0) saturate(100%) invert(24%) sepia(79%) saturate(4008%) hue-rotate(344deg) brightness(91%) contrast(90%)}.modal-overlay{position:fixed;inset:0;background:#11182773;display:flex;align-items:center;justify-content:center;z-index:2500;padding:20px}.status-modal-card{width:min(760px,96vw);max-height:85vh;overflow:auto;background:#fff;border-radius:16px;border:1px solid #e5e7eb}.status-modal-header{padding:20px 24px 14px;border-bottom:1px solid #eef2f7}.status-modal-body{padding:12px 20px 20px}.status-modal-footer{padding:12px 20px 20px;border-top:1px solid #eef2f7;display:flex;justify-content:end;align-items:center;gap:12px}.status-modal-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px 10px;border-bottom:1px solid #f1f5f9}.status-modal-row:last-child{border-bottom:0}.status-modal-name{font-size:14px;font-weight:600;color:#69707d}.status-modal-state{font-size:.92rem;font-weight:600}.status-modal-state.pending{color:#a16207}.status-modal-state.success{color:#166534}.status-modal-state.partial{color:#b45309}.status-modal-state.error{color:#b91c1c}.confirm-modal-card{width:min(520px,96vw);background:#fff;border-radius:5px;border:1px solid #e5e7eb;padding:24px}.year-experience-select{max-height:150px}@media screen and (max-width: 768px){.res-flex{flex-wrap:wrap!important;justify-content:center!important}.res-flex .fw-normal{width:100%;text-align:center;font-size:14px!important}.d-flex.flex-wrap.gap-2.p-3.bg-white.border.rounded.shadow-sm{justify-content:center}.preview-page-header{margin:20px auto 8px;padding:0 4px}.container{padding-left:4px;padding-right:4px}.preview-title{font-size:16px}.preview-subtitle{font-size:14px}.actions{margin:24px 0 16px}.section-header-title{flex-wrap:wrap}.section-header-title>.section-flag{flex-basis:53%}.section-header-row{align-items:flex-start}.preview-card-gradient{padding:14px 14px 12px}.preview-card-gradient h2{font-size:18px}.popup{width:calc(100vw - 40px);right:16px;top:12%}.card{padding:0}.card-body.p-4,.px-4.py-3{padding:12px!important}.row.g-4,.row.g-3{--bs-gutter-x: .75rem}.d-flex.gap-4{gap:10px!important}.preview-card-gradient>.d-flex.justify-content-between.align-items-start{flex-wrap:wrap;row-gap:8px}.preview-card-gradient>.d-flex.justify-content-between.align-items-start>.badge.bg-primary-subtle{margin-left:auto}}@media screen and (max-width: 575px){.preview-title{font-size:16px}.preview-subtitle{font-size:14px}.section>.d-flex{flex-wrap:wrap;row-gap:8px}.section>.d-flex>.d-flex:last-child{width:100%;justify-content:flex-end}}::ng-deep .bs-datepicker-head{background-color:#4077ad!important}::ng-deep .bs-datepicker-body table td span.selected,.bs-datepicker-body table td.selected span{background-color:#4077ad!important}.profile-avatar-circle{width:58px;height:58px;border-radius:5px;background:#4077ad;display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:700;color:#fff;letter-spacing:1px;flex-shrink:0}.section-header-icon{font-size:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;opacity:.9;filter:invert(47%) sepia(8%) saturate(483%) hue-rotate(176deg) brightness(91%) contrast(87%)}.section-header-title h5.fw-bold{color:#69707d}.text-muted{color:#69707d!important}h6.text-uppercase.fw-bold.text-muted{font-size:14px;color:#69707d!important}.work-accent-item{border-radius:5px!important;transition:background-color .18s ease,box-shadow .18s ease}.work-accent-item:hover{background-color:#f5f8ff!important;box-shadow:0 4px 14px #4077ad17!important}.edu-accent-item{border-radius:5px!important;transition:background-color .18s ease,box-shadow .18s ease}.edu-accent-item:hover{background-color:#f8f8ff!important;box-shadow:0 4px 14px #6366f117!important}.cert-accent-item{border-radius:5px!important;transition:background-color .18s ease}.cert-accent-item:hover{background-color:#f0fdf4!important}.lic-accent-item{border-radius:5px!important;transition:background-color .18s ease}.lic-accent-item:hover{background-color:#fffbeb!important}.field-label-sm{font-size:14px;font-weight:700;letter-spacing:.08em;color:#69707d;margin-bottom:3px;display:block}.item-name-text{color:#69707d}.field-value-sm{font-weight:600;font-size:12px;color:#69707d}.item-title-sm{font-size:14px;color:#69707d!important}.item-meta-line{display:block;font-size:12px;color:#69707d;margin-top:3px}.empty-state-wrap{text-align:center;padding:32px 20px;background:#fafbfc;border:1.5px dashed #d1d5db;border-radius:5px;cursor:pointer;transition:background-color .18s ease,border-color .18s ease}.empty-state-wrap .empty-icon{font-size:2rem;color:#d1d5db;margin-bottom:8px}.empty-state-wrap p{color:#9ca3af;margin:0;font-size:14px}.empty-state-wrap:hover{background:#f0f6ff;border-color:#4077ad}.form-panel{background:#fff;border:1px solid #e2e8f0;border-radius:5px;padding:20px}.form-panel .form-control,.form-panel .form-select{border-color:#d1d5db;border-radius:8px;font-size:12px}.form-panel .form-control:focus,.form-panel .form-select:focus{border-color:#4077ad;box-shadow:0 0 0 3px #4077ad1f}.section-header-bar{display:flex;align-items:center;justify-content:space-between;padding:10px 0 14px;border-bottom:2px solid #f1f5f9;margin-bottom:16px}.preview-card-gradient{background:linear-gradient(135deg,#fff,#eff6ff);border-bottom:1px solid #e2e8f0;padding:20px 24px 16px;border-radius:5px 5px 0 0}.profile-header-card{border:1px solid #e2e8f0!important}.item-icon-circle{width:40px;height:40px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;color:#fff;flex-shrink:0}.item-avatar--work{background:linear-gradient(135deg,#4077ad,#2d5a8a)}.item-avatar--edu{background:linear-gradient(135deg,#4077ad,#4338ca)}.provider-layout{display:flex;flex-direction:column}.provider-company-first{order:-1}.section-locked{pointer-events:none;opacity:.45;filter:blur(1.5px);-webkit-user-select:none;user-select:none}.btn.btn-primary{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-primary:hover:not(:disabled),.btn.btn-primary:focus:not(:disabled),.btn.btn-primary:active:not(:disabled){background-color:#356895!important;border-color:#356895!important;color:#fff!important}.btn.btn-success,.btn.btn-outline-success{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-success:hover:not(:disabled),.btn.btn-success:focus:not(:disabled),.btn.btn-success:active:not(:disabled),.btn.btn-outline-success:hover:not(:disabled),.btn.btn-outline-success:focus:not(:disabled),.btn.btn-outline-success:active:not(:disabled){background-color:#336843!important;border-color:#336843!important;color:#fff!important}.btn.btn-outline-secondary.rounded-pill{background-color:#69707d!important;border-color:#69707d!important;color:#fff!important;border-radius:5px!important}.btn.btn-outline-secondary.rounded-pill:hover:not(:disabled),.btn.btn-outline-secondary.rounded-pill:focus:not(:disabled),.btn.btn-outline-secondary.rounded-pill:active:not(:disabled){background-color:#565c66!important;border-color:#565c66!important;color:#fff!important}.preview-back-btn{background-color:#426c85!important;border-color:#426c85!important;color:#fff!important}.preview-dashboard-btn{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-outline-success:hover:not(:disabled),.btn.btn-outline-success:focus:not(:disabled),.btn.btn-outline-success:active:not(:disabled){background-color:transparent!important;border-color:#198754!important;color:#198754!important}.btn.btn-outline-secondary:not(.rounded-pill){background-color:#d4dae6!important;border-color:#d4dae6!important;color:#69707d!important}.btn.btn-outline-secondary:not(.rounded-pill):hover:not(:disabled),.btn.btn-outline-secondary:not(.rounded-pill):focus:not(:disabled),.btn.btn-outline-secondary:not(.rounded-pill):active:not(:disabled){background-color:#c2cbde!important;border-color:#c2cbde!important;color:#69707d!important}.btn.btn-danger{background-color:#b43026!important;border-color:#b43026!important;color:#fff!important}.btn.btn-danger:hover:not(:disabled),.btn.btn-danger:focus:not(:disabled),.btn.btn-danger:active:not(:disabled){background-color:#96271f!important;border-color:#96271f!important;color:#fff!important}.btn.btn-outline-danger.rounded-circle{border-color:#b43026!important;color:#b43026!important;border-radius:5px!important}.btn.btn-outline-danger.rounded-circle:hover:not(:disabled),.btn.btn-outline-danger.rounded-circle:focus:not(:disabled),.btn.btn-outline-danger.rounded-circle:active:not(:disabled){border-color:#96271f!important;color:#b43026!important}.btn.btn-link.text-secondary{background-color:#d4dae6!important;border-color:#d4dae6!important;color:#69707d!important;text-decoration:none!important;border-radius:5px}.btn.btn-link.text-secondary:hover:not(:disabled),.btn.btn-link.text-secondary:focus:not(:disabled){background-color:#c2cbde!important;color:#69707d!important}.btn.btn-link.text-danger{background-color:#b43026!important;border-color:#b43026!important;color:#fff!important;text-decoration:none!important;border-radius:5px}.btn.btn-link.text-danger:hover:not(:disabled),.btn.btn-link.text-danger:focus:not(:disabled){background-color:#96271f!important;color:#fff!important}.btn{border-radius:5px!important;box-shadow:none!important}.badge.bg-warning-subtle.text-warning{background-color:#fff3cd!important;color:#664d03!important;border-color:#ffe69c!important}.badge.bg-success-subtle.text-success{background-color:#4077ad!important;color:#fff!important;border-color:#4077ad!important}.badge.bg-primary-subtle.text-primary{background-color:#e0edf2!important;color:#4077ad!important;border-color:#e0edf2!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ModalModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i7.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i7.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i7.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: i7.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i7.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i7.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i7.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i7.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i7.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i7.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i7.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: NgSelectModule }, { kind: "component", type: i12.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "ngmodule", type: NgxStarsModule }, { kind: "ngmodule", type: BsDatepickerModule }, { kind: "directive", type: i13.BsDatepickerDirective, selector: "[bsDatepicker]", inputs: ["placement", "triggers", "outsideClick", "container", "outsideEsc", "isDisabled", "minDate", "maxDate", "ignoreMinMaxErrors", "minMode", "daysDisabled", "datesDisabled", "datesEnabled", "dateCustomClasses", "dateTooltipTexts", "isOpen", "bsValue", "bsConfig"], outputs: ["onShown", "onHidden", "bsValueChange"], exportAs: ["bsDatepicker"] }, { kind: "directive", type: i13.BsDatepickerInputDirective, selector: "input[bsDatepicker]" }, { kind: "ngmodule", type: TextMaskModule }, { kind: "ngmodule", type: AddressVerifyFieldModule }, { kind: "component", type: AddressVerifyFieldComponent, selector: "im-address-verify-field", inputs: ["placeholder", "options", "maxLength", "inputId", "name", "autocompleteAttr", "inputClass", "invalid", "inputStyle", "initialLat", "initialLng"], outputs: ["addressResolved", "manualEdit"] }] });
|
|
7385
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: PreviewComponent, isStandalone: true, selector: "app-preview", inputs: { providerId: "providerId", isResume: "isResume", resumeModel: "resumeModel", providerName: "providerName", roleData: "roleData", cloudfrontUrl: "cloudfrontUrl", signatureFileId: "signatureFileId", signatureUrl: "signatureUrl" }, outputs: { backToParent: "backToParent" }, viewQueries: [{ propertyName: "companyForm", first: true, predicate: ["companyForm"], descendants: true }], ngImport: i0, template: "<div class=\"preview-page-header\" *ngIf=\"!isResume\">\r\n <div class=\"d-flex align-items-center gap-2 mb-1\">\r\n <h2 class=\"preview-title mb-0\">Review Extracted Information</h2>\r\n </div>\r\n <p class=\"preview-subtitle text-muted\">We\u2019ve automatically extracted details from your uploaded resume. Please review and confirm accuracy before proceeding.</p>\r\n</div>\r\n\r\n\r\n<div [ngClass]=\"isResume ? '' : 'container py-4'\" [class.provider-layout]=\"roleData?.role?.name === 'Provider'\">\r\n\r\n <!-- Provider initial setup: combined company + personal form (shown until both APIs succeed) -->\r\n <div class=\"section mb-5\" *ngIf=\"roleData?.role?.name === 'Provider' && !hasUserDetailData && !isResume\">\r\n <div class=\"d-flex align-items-center gap-2 mb-3 section-header-title\">\r\n <img src=\"/assets/images/icons/building.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Company & Personal Details</h5>\r\n <span class=\"badge border section-flag bg-warning-subtle text-warning\">Required to continue</span>\r\n </div>\r\n <div class=\"card shadow-sm border-0\">\r\n <div class=\"card-header bg-white fw-semibold\">Company Information</div>\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-3\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': (!tempCompanyDetails.companyName?.trim() && companyFormSubmitted) || companyNameError}\"\r\n [(ngModel)]=\"tempCompanyDetails.companyName\" name=\"setupCompanyName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyName?.trim() && companyFormSubmitted\">Company name is required</div>\r\n <div class=\"invalid-feedback\" *ngIf=\"companyNameError\">{{ companyNameError }}</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" maxlength=\"14\" inputmode=\"numeric\"\r\n (input)=\"phoneMask($event, 'company')\" (keypress)=\"allowOnlyNumbers($event)\"\r\n [ngClass]=\"{'is-invalid': companyFormSubmitted && (!tempCompanyDetails.companyPhoneNumber?.trim() || getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10)}\"\r\n [(ngModel)]=\"tempCompanyDetails.companyPhoneNumber\" name=\"setupCompanyPhone\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyPhoneNumber?.trim() && companyFormSubmitted\">Company phone is required</div>\r\n <div class=\"invalid-feedback\" *ngIf=\"tempCompanyDetails.companyPhoneNumber?.trim() && getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10 && companyFormSubmitted\">Company phone must be 10 digits</div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Company Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempCompanyDetails.address1\" name=\"setupCompanyAddress\"\r\n [options]=\"options\" inputClass=\"form-control form-control-sm\"\r\n [invalid]=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempCompanyDetails.latitude\" [initialLng]=\"tempCompanyDetails.longitude\"\r\n (addressResolved)=\"onCompanyAddressResolved($event)\"\r\n (manualEdit)=\"onCompanyAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\">Address is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.city?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.city\" name=\"setupCompanyCity\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.city?.trim() && companyFormSubmitted\">City is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.state?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.state\" name=\"setupCompanyState\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.state?.trim() && companyFormSubmitted\">State is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.zipcode?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.zipcode\" name=\"setupCompanyZip\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.zipcode?.trim() && companyFormSubmitted\">Zip code is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.country?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.country\" name=\"setupCompanyCountry\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.country?.trim() && companyFormSubmitted\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <input type=\"file\" accept=\".png,.jpg,.jpeg\" class=\"form-control form-control-sm\" (change)=\"uploadCompanyImage($event)\" name=\"setupCompanyLogo\" />\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"tempCompanyLogoUrl\">\r\n <label class=\"small text-muted d-block\">Logo Preview</label>\r\n <img [src]=\"tempCompanyLogoUrl\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-header bg-white fw-semibold border-top\">Personal Information</div>\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-3\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">First Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.firstName?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.firstName\" name=\"setupFirstName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.firstName?.trim() && companyFormSubmitted\">First name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Last Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.lastName?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.lastName\" name=\"setupLastName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.lastName?.trim() && companyFormSubmitted\">Last name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Email <span class=\"text-danger\">*</span></label>\r\n <input type=\"email\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.email?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.email\" name=\"setupEmail\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.email?.trim() && companyFormSubmitted\">Email is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Phone Number <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" maxlength=\"14\" inputmode=\"numeric\"\r\n (input)=\"phoneMask($event, 'profile')\" (keypress)=\"allowOnlyNumbers($event)\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.phone?.trim() && companyFormSubmitted}\"\r\n [ngModel]=\"tempProfile?.phone\" name=\"setupPhone\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.phone?.trim() && companyFormSubmitted\">Phone number is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Home Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempProfile.address\" name=\"setupAddress\" [options]=\"options\"\r\n inputClass=\"form-control form-control-sm\" [invalid]=\"!tempProfile?.address?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempProfile.latitude\" [initialLng]=\"tempProfile.longitude\"\r\n (addressResolved)=\"onUserAddressResolved($event)\"\r\n (manualEdit)=\"onUserAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.address?.trim() && companyFormSubmitted\">Home address is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.city?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.city\" name=\"setupUserCity\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.city?.trim() && companyFormSubmitted\">City is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.state?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.state\" name=\"setupUserState\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.state?.trim() && companyFormSubmitted\">State is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.zipCode?.trim() && companyFormSubmitted}\"\r\n [ngModel]=\"tempProfile?.zipCode\" (ngModelChange)=\"tempProfile.zipCode = sanitizeZipCode($event)\"\r\n name=\"setupUserZip\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.zipCode?.trim() && companyFormSubmitted\">Zip code is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.country?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.country\" name=\"setupUserCountry\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.country?.trim() && companyFormSubmitted\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [(ngModel)]=\"tempProfile.jobTitle\" name=\"setupJobTitle\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control form-control-sm\" [(ngModel)]=\"tempProfile.yearsOfExperience\"\r\n [ngClass]=\"{'is-invalid': !(tempProfile?.yearsOfExperience > 0) && companyFormSubmitted}\"\r\n name=\"setupYearsOfExp\" min=\"1\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!(tempProfile?.yearsOfExperience > 0) && companyFormSubmitted\">Years of experience is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Profile Picture</label>\r\n <input #setupHeadshotFile type=\"file\" accept=\".png,.jpg,.jpeg\" class=\"d-none\" (change)=\"uploadHeadshotImage($event)\" name=\"setupHeadshotFile\" />\r\n <div class=\"position-relative\">\r\n <input type=\"text\" class=\"form-control form-control-sm pe-5\" [value]=\"headshotFileName\" readonly\r\n placeholder=\"Upload Profile Picture\" (click)=\"setupHeadshotFile.click()\" />\r\n <img *ngIf=\"!isHeadshotLoading\" src=\"assets/images/icons/upload.svg\" alt=\"Upload\" class=\"upload-icon\" style=\"position:absolute;right:12px;top:50%;transform:translateY(-50%);cursor:pointer;width:18px;\" (click)=\"setupHeadshotFile.click()\" />\r\n <div *ngIf=\"isHeadshotLoading\" style=\"position:absolute;right:12px;top:50%;transform:translateY(-50%);\">\r\n <span class=\"spinner-border spinner-border-sm text-primary\"></span>\r\n </div>\r\n </div>\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"headshotPreviewUrl\">\r\n <label class=\"small text-muted d-block\">Preview</label>\r\n <img [src]=\"headshotPreviewUrl\" class=\"img-thumbnail rounded-circle\" style=\"width:64px;height:64px;object-fit:cover;\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-footer d-flex align-items-center justify-content-end gap-2\">\r\n <span *ngIf=\"providerSetupError\" class=\"small text-danger me-auto\">{{ providerSetupError }}</span>\r\n <button class=\"btn btn-success px-5 \"\r\n [disabled]=\"isSavingProviderSetup || !isProviderSetupFormComplete\"\r\n (click)=\"saveProviderSetup()\">\r\n <span *ngIf=\"isSavingProviderSetup\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingProviderSetup ? 'Saving...' : 'Save & Continue' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\" *ngIf=\"roleData?.role?.name !== 'Provider' || hasUserDetailData\">\r\n <div *ngIf=\"details() as data; else loading\">\r\n <div class=\"card profile-header-card shadow-sm border-0 rounded-3 overflow-hidden\" *ngIf=\"!isEditMode()\">\r\n <div class=\"card-body p-0\">\r\n <div class=\"preview-card-gradient\">\r\n <div class=\"d-flex justify-content-between align-items-start mb-4\">\r\n <div class=\"d-flex align-items-start gap-3\">\r\n <div class=\"profile-avatar-circle\" *ngIf=\"!headshotPreviewUrl\">\r\n {{ (data.firstName?.[0] || '') }}{{ (data.lastName?.[0] || '') }}\r\n </div>\r\n <img *ngIf=\"headshotPreviewUrl\" [src]=\"headshotPreviewUrl\"\r\n class=\"rounded-circle\" style=\"width:56px;height:56px;object-fit:cover;\" alt=\"Profile\" />\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h2 class=\"fw-bold mb-1\">{{ data.firstName }} {{ data.lastName }}</h2>\r\n <span *ngIf=\"basicSectionHasIssues()\" class=\"badge bg-warning-subtle text-warning border section-flag\">\r\n Missing info\r\n </span>\r\n <span class=\"badge border section-flag\"\r\n [ngClass]=\"basicDetailsSaved ? 'bg-success-subtle text-success' : 'bg-warning-subtle text-warning'\">\r\n {{ basicDetailsSaved ? 'Saved' : 'Not saved yet' }}\r\n </span>\r\n </div>\r\n <p class=\"text-muted\">{{ data.jobTitle }} \u2022 {{ data.yearsOfExperience }} Years Exp.</p>\r\n <div *ngIf=\"basicIssues().length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ basicIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <span class=\"badge bg-primary-subtle text-primary border p-2\">Email Verified</span>\r\n </div>\r\n\r\n </div>\r\n <div class=\"px-4 py-3\">\r\n <div class=\"row g-4\">\r\n <div class=\"col-12 border-bottom pb-2\">\r\n <h6 class=\"text-uppercase small fw-bold text-muted\">Summary</h6>\r\n <p class=\"text-secondary small mb-0\">{{ data.summary }}</p>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/envelope.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Email</span>\r\n <span class=\"field-value-sm d-block\">{{ data.email }}</span>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/telephone.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Phone</span>\r\n <span class=\"field-value-sm d-block\">{{ data.phone }}</span>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/geo-alt.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Location</span>\r\n <span class=\"field-value-sm d-block\">{{ data.address }}, {{ data.city }}, {{ data.state }}, {{ data.zipCode }}, {{ data.country }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer d-flex align-items-center justify-content-between\">\r\n <span *ngIf=\"!basicDetailsSaved\" class=\"small text-warning fw-semibold\">\r\n <img src=\"/assets/images/icons/exclamation-circle.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" /> Click \"Edit\" to review and save your basic info.\r\n </span>\r\n <span *ngIf=\"basicDetailsSaved\" class=\"small text-success fw-semibold\">\r\n <img src=\"/assets/images/icons/check-circle.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" /> Basic details saved.\r\n </span>\r\n <button class=\"btn btn-sm btn-primary px-4 ms-auto\" (click)=\"toggleEdit()\">Edit</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0 update-profile-card\" *ngIf=\"isEditMode()\">\r\n <div class=\"card-header bg-white fw-bold\">Update Profile</div>\r\n <div class=\"card-body p-4\">\r\n <form class=\"row g-3\" #basicForm=\"ngForm\" novalidate>\r\n <div *ngIf=\"basicIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ basicIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">First Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.firstName\" name=\"fName\"\r\n placeholder=\"First Name\" required #fName=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"fName.invalid && (fName.dirty || fName.touched)\">First name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Last Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.lastName\" name=\"lName\"\r\n placeholder=\"Last Name\" required #lName=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"lName.invalid && (lName.dirty || lName.touched)\">Last name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Email <span class=\"text-danger\">*</span></label>\r\n <input type=\"email\" class=\"form-control\" [(ngModel)]=\"tempProfile.email\" name=\"email\" placeholder=\"Email\"\r\n required email #email=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"email.invalid && (email.dirty || email.touched)\">\r\n <span *ngIf=\"email.errors?.['required']\">Email is required</span>\r\n <span *ngIf=\"email.errors?.['email']\">Email format is invalid</span>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Phone Number <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"tempProfile.phone\" (input)=\"phoneMask($event, 'profile')\"\r\n name=\"phone\" placeholder=\"Phone (10 digits)\" (keypress)=\"allowOnlyNumbers($event)\"\r\n required pattern=\"^\\(\\d{3}\\) \\d{3}-\\d{4}$\" maxlength=\"14\" inputmode=\"numeric\" #phone=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"phone.invalid && (phone.dirty || phone.touched)\">\r\n <span *ngIf=\"phone.errors?.['required']\">Phone number is required</span>\r\n <span *ngIf=\"phone.errors?.['pattern']\">Phone number must be 10 digits</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\"></span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.jobTitle\" name=\"jobTitle\"\r\n placeholder=\"Job Title\" #jobTitle=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"jobTitle.invalid && (jobTitle.dirty || jobTitle.touched)\">Job\r\n title is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [ngClass]=\"{'is-invalid': !(tempProfile?.yearsOfExperience > 0)}\"\r\n [(ngModel)]=\"tempProfile.yearsOfExperience\"\r\n name=\"yearsOfExperience\" placeholder=\"Years of Experience\" required min=\"1\"\r\n #yearsOfExperience=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!(tempProfile?.yearsOfExperience > 0)\">\r\n Years of experience is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Home Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempProfile.address\" name=\"address\" [options]=\"options\"\r\n placeholder=\"Home Address\" required #address=\"ngModel\"\r\n [invalid]=\"address.invalid && (address.dirty || address.touched)\"\r\n [initialLat]=\"tempProfile.latitude\" [initialLng]=\"tempProfile.longitude\"\r\n (addressResolved)=\"onUserAddressResolved($event)\"\r\n (manualEdit)=\"onUserAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"address.invalid && (address.dirty || address.touched)\">Home\r\n address is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.city\" name=\"city\" placeholder=\"City\"\r\n required #city=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"city.invalid && (city.dirty || city.touched)\">City is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.state\" name=\"state\" placeholder=\"State\"\r\n required #state=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"state.invalid && (state.dirty || state.touched)\">State is\r\n required</div>\r\n </div>\r\n\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"tempProfile.zipCode\"\r\n (ngModelChange)=\"tempProfile.zipCode = sanitizeZipCode($event)\" name=\"zipCode\" placeholder=\"Zip Code\"\r\n required pattern=\"^\\d{1,6}$\" maxlength=\"6\" inputmode=\"numeric\" #zipCode=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"zipCode.invalid && (zipCode.dirty || zipCode.touched)\">Zip code\r\n is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"zipCode.errors?.['pattern'] && (zipCode.dirty || zipCode.touched)\">\r\n Zip code must be up to 6 digits\r\n </div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.country\" name=\"country\"\r\n placeholder=\"Country\" required #country=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"country.invalid && (country.dirty || country.touched)\">Country\r\n is required</div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Summary</label>\r\n <textarea class=\"form-control\" rows=\"3\" [(ngModel)]=\"tempProfile.summary\" name=\"sum\"\r\n placeholder=\"Summary\"></textarea>\r\n </div>\r\n\r\n\r\n </form>\r\n </div>\r\n <div class=\"card-footer text-end gap-2 d-flex justify-content-end\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancel()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingBasic || !isBasicFormValid\" (click)=\"save()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Saving...' : 'Save Changes' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5 provider-company-first\" *ngIf=\"roleData?.role?.name === 'Provider' && hasUserDetailData && !isResume\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/building.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Company Details</h5>\r\n <span *ngIf=\"companyDetailsSaved\"\r\n class=\"badge border section-flag bg-success-subtle text-success\">\r\n Saved\r\n </span>\r\n <span *ngIf=\"!companyDetailsSaved\"\r\n class=\"badge border section-flag bg-warning-subtle text-warning\">\r\n Not saved yet\r\n </span>\r\n </div>\r\n <button class=\"btn btn-sm btn-primary px-4\" (click)=\"toggleCompanyEdit()\">Edit</button>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"!isCompanyEditMode()\">\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-4\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name</label>\r\n <span class=\"fw-bold small\">{{ companyDetails()?.companyName}}</span>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone</label>\r\n <span class=\"fw-bold small\">{{ companyDetails()?.companyPhoneNumber}}</span>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Company Address</label>\r\n <span class=\"small\">{{ companyDetails()?.address1}}, {{ companyDetails()?.city}}, {{ companyDetails()?.state}}, {{ companyDetails()?.zipcode}}, {{ companyDetails()?.country}}</span>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"companyLogoUrl()\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <img [src]=\"companyLogoUrl()\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"isCompanyEditMode()\">\r\n <div class=\"card-header bg-white fw-bold\">Update Company Details</div>\r\n <div class=\"card-body p-4\">\r\n <form class=\"row g-3\" #companyForm=\"ngForm\" novalidate>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': (!tempCompanyDetails.companyName?.trim() && companyFormSubmitted) || companyNameError }\"\r\n [(ngModel)]=\"tempCompanyDetails.companyName\" name=\"companyName\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyName?.trim() && companyFormSubmitted\">\r\n Company name is required\r\n </div>\r\n <div class=\"invalid-feedback\" *ngIf=\"companyNameError\">\r\n {{ companyNameError }}\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone <span class=\"text-danger\">*</span></label>\r\n <input (input)=\"phoneMask($event, 'company')\" type=\"text\" maxlength=\"14\" (keypress)=\"allowOnlyNumbers($event)\" inputmode=\"numeric\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{ 'is-invalid': companyFormSubmitted && (!tempCompanyDetails.companyPhoneNumber?.trim() || getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10) }\"\r\n [(ngModel)]=\"tempCompanyDetails.companyPhoneNumber\" name=\"companyPhoneNumber\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyPhoneNumber?.trim() && companyFormSubmitted\">\r\n Company phone is required\r\n </div>\r\n <div class=\"invalid-feedback\" *ngIf=\"tempCompanyDetails.companyPhoneNumber?.trim() && getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10 && companyFormSubmitted\">\r\n Company phone must be 10 digits\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempCompanyDetails.address1\" name=\"address1\" [options]=\"options\"\r\n required [invalid]=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempCompanyDetails.latitude\" [initialLng]=\"tempCompanyDetails.longitude\"\r\n (addressResolved)=\"onCompanyAddressResolved($event)\"\r\n (manualEdit)=\"onCompanyAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\">\r\n Address is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.city?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.city\" name=\"city\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.city?.trim() && companyFormSubmitted\">\r\n City is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.state?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.state\" name=\"state\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.state?.trim() && companyFormSubmitted\">\r\n State is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.zipcode?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.zipcode\" name=\"zipcode\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.zipcode?.trim() && companyFormSubmitted\">\r\n Zip code is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.country?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.country\" name=\"country\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.country?.trim() && companyFormSubmitted\">\r\n Country is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <input #uploadCompanyFile type=\"file\" accept=\".png,.jpg,.jpeg\" (change)=\"uploadCompanyImage($event)\" class=\"form-control\" />\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"tempCompanyLogoUrl\">\r\n <label class=\"small text-muted d-block\">Logo Preview</label>\r\n <img [src]=\"tempCompanyLogoUrl\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"card-footer text-end gap-2 d-flex justify-content-end\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelCompanyEdit()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingCompany\" \r\n (click)=\"saveCompanyDetails()\">\r\n <span *ngIf=\"isSavingCompany\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCompany ? 'Saving...' : 'Save Changes' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div [class.section-locked]=\"roleData?.role?.name === 'Provider' && !hasUserDetailData\">\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/briefcase-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Profession</h5>\r\n <span *ngIf=\"selectedProfessionCount > 0\" class=\"badge border section-flag bg-warning-subtle text-warning\">\r\n {{ selectedProfessionCount }} selected\r\n </span>\r\n </div>\r\n <button type=\"button\" class=\"btn btn-sm btn-primary px-4\"\r\n [disabled]=\"selectedProfessionCount === 0 || isSavingProfessionsTable\"\r\n (click)=\"submitProfessions()\">\r\n <span *ngIf=\"isSavingProfessionsTable\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingProfessionsTable ? 'Saving...' : professionSubmitLabel }}\r\n </button>\r\n </div>\r\n\r\n <div class=\"mb-3\">\r\n <input type=\"text\" class=\"form-control profession-search-input\" placeholder=\"Search or Add Profession\"\r\n [(ngModel)]=\"professionSearchQry\" name=\"professionSearchQry\"\r\n (keydown.enter)=\"createManualProfessionRow()\" />\r\n </div>\r\n\r\n <div class=\"bg-white border rounded shadow-sm profession-accordion\">\r\n <div class=\"profession-acc-columns\">\r\n <span></span>\r\n <span>Profession Name</span>\r\n <span>Group</span>\r\n <span>Type</span>\r\n <span></span>\r\n </div>\r\n\r\n <ng-container *ngFor=\"let p of filteredProfessionTypes; trackBy: trackByProfessionId\">\r\n <div class=\"profession-acc-item\" [class.profession-row-selected]=\"getProfessionSelection(p.id).selected\">\r\n <div class=\"profession-acc-header\" (click)=\"toggleProfessionRow(p, $event)\">\r\n <div class=\"text-center\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" class=\"form-check-input\" [checked]=\"getProfessionSelection(p.id).selected\"\r\n (change)=\"onProfessionRowCheck(p, $event)\" />\r\n </div>\r\n <div class=\"profession-acc-name\">\r\n {{ p.professionName }}\r\n <span *ngIf=\"isProfessionSaved(p.id)\" class=\"badge border bg-success-subtle text-success ms-1\">Saved</span>\r\n </div>\r\n <div (mousedown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\r\n <ng-container *ngIf=\"p.isManual; else groupText\">\r\n <ng-select class=\"profession-inline-select\" [items]=\"professionGroupOptions\" [ngModel]=\"p.professionGroup\"\r\n (ngModelChange)=\"setManualProfessionGroup(p, $event)\" [name]=\"'manualGroup-' + p.id\"\r\n placeholder=\"Select group\" [clearable]=\"false\">\r\n </ng-select>\r\n </ng-container>\r\n <ng-template #groupText>{{ p.professionGroup || '\u2013' }}</ng-template>\r\n </div>\r\n <div (mousedown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\r\n <ng-container *ngIf=\"p.isManual; else typeText\">\r\n <ng-select class=\"profession-inline-select\" [items]=\"professionTypeOptions\" [ngModel]=\"p.residentialCommercial\"\r\n (ngModelChange)=\"setManualProfessionType(p, $event)\" [name]=\"'manualType-' + p.id\"\r\n placeholder=\"Select type\" [clearable]=\"false\">\r\n </ng-select>\r\n </ng-container>\r\n <ng-template #typeText>{{ p.residentialCommercial || '\u2013' }}</ng-template>\r\n </div>\r\n <button type=\"button\" class=\"profession-acc-chevron-btn\"\r\n [attr.aria-label]=\"getProfessionSelection(p.id).selected ? 'Collapse' : 'Expand'\">\r\n <svg class=\"profession-acc-chevron\" [class.profession-acc-chevron--open]=\"getProfessionSelection(p.id).selected\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"profession-acc-body\" *ngIf=\"getProfessionSelection(p.id).selected\">\r\n <div class=\"profession-acc-panel\">\r\n <div *ngIf=\"p.isManual && !isManualRowReady(p.id)\" class=\"small text-danger mb-3\">\r\n Select a Group and Type above to enable saving this profession.\r\n </div>\r\n <div class=\"profession-acc-fields\">\r\n <div class=\"profession-acc-field\">\r\n <label class=\"small text-muted d-block mb-1\">Self Ability Rating</label>\r\n <div class=\"profession-acc-stars\">\r\n <span *ngFor=\"let s of [1,2,3,4,5]\" class=\"fs-5\" style=\"cursor: pointer;\"\r\n (click)=\"setProfessionRowStars(p, s)\"\r\n [class.text-warning]=\"(getProfessionSelection(p.id).starRating || 0) / 2 >= s\"\r\n [class.text-muted]=\"(getProfessionSelection(p.id).starRating || 0) / 2 < s\">\u2605</span>\r\n </div>\r\n </div>\r\n <div class=\"profession-acc-field\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience</label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <input type=\"number\" class=\"form-control form-control-sm profession-acc-year-input\" min=\"0\" max=\"30\"\r\n [(ngModel)]=\"getProfessionSelection(p.id).year\" [name]=\"'profYear-' + p.id\" />\r\n <span class=\"small text-muted\">Yrs</span>\r\n </div>\r\n </div>\r\n <div class=\"profession-acc-field profession-acc-field--visibility\">\r\n <label class=\"small text-muted d-block mb-1\">Visibility</label>\r\n <input type=\"checkbox\" class=\"profession-visibility-checkbox\" [(ngModel)]=\"getProfessionSelection(p.id).profileVisibility\"\r\n [name]=\"'profVis-' + p.id\" />\r\n </div>\r\n <div class=\"profession-acc-field profession-acc-field--notes\">\r\n <label class=\"small text-muted d-block mb-1\">Additional Details</label>\r\n <textarea rows=\"3\" class=\"form-control form-control-sm profession-notes-input\" [(ngModel)]=\"getProfessionSelection(p.id).notes\"\r\n [name]=\"'profNotes-' + p.id\" placeholder=\"Additional Details\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <div *ngIf=\"hasNoProfessionMatches\" class=\"text-center small py-3\">\r\n <span class=\"text-muted\">No professions found for \"{{ professionSearchQry?.trim() }}\".</span>\r\n <button type=\"button\" class=\"btn btn-sm btn-primary ms-2\" (click)=\"createManualProfessionRow()\">\r\n Add \"{{ professionSearchQry?.trim() }}\"\r\n </button>\r\n </div>\r\n <div *ngIf=\"!professionSearchQry?.trim() && filteredProfessionTypes.length === 0\"\r\n class=\"text-center text-muted small py-3\">\r\n No professions found.\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/briefcase-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Work Experience</h5>\r\n <span *ngIf=\"experience().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"workSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ workSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"experience().length === 0 || !workSectionHasUnsavedItems() || isSavingWork || isAddingJob() || editingJobIndex() !== null\"\r\n (click)=\"confirmAllWork()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add work experience\" (click)=\"addJob()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"experience().length === 0 && !isAddingJob()\" class=\"empty-state-wrap mb-3\" role=\"button\"\r\n (click)=\"addJob()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/briefcase.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No work experience added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3\">\r\n <div *ngIf=\"isAddingJob() && tempJob()\" class=\"list-group-item p-0 border-0\">\r\n <div class=\"form-panel mb-2\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.jobTitle\"\r\n (ngModelChange)=\"patchTempJob({ jobTitle: $event })\" name=\"newJobTitle\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.company\"\r\n (ngModelChange)=\"patchTempJob({ company: $event })\" name=\"newCompany\" />\r\n </div>\r\n <div class=\"align-items-end col-md-12 d-flex justify-content-end pe-3\">\r\n <div class=\"form-check\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"tempJob()?.isCurrent\"\r\n (ngModelChange)=\"setTempJobIsCurrent($event)\" name=\"newIsCurrent\" id=\"newIsCurrent\" />\r\n <label class=\"form-check-label\" for=\"newIsCurrent\">Current</label>\r\n </div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.country\"\r\n (ngModelChange)=\"patchTempJob({ country: $event })\" name=\"newCountry\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.state\"\r\n (ngModelChange)=\"patchTempJob({ state: $event })\" name=\"newState\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.city\"\r\n (ngModelChange)=\"patchTempJob({ city: $event })\" name=\"newCity\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempJob()?.startDate)\"\r\n (bsValueChange)=\"setTempJobMonth('startDate', $event)\" name=\"newStartDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.startDate)\">Start date is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [disabled]=\"tempJob()?.isCurrent\"\r\n [ngModel]=\"monthInputToDate(tempJob()?.endDate)\" (bsValueChange)=\"setTempJobMonth('endDate', $event)\"\r\n name=\"newEndDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!tempJob()?.isCurrent && isBlank(tempJob()?.endDate)\">End date is\r\n required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"!tempJob()?.isCurrent && isMonthRangeInvalid(tempJob()?.startDate, tempJob()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Responsibilities (one per line)</label>\r\n <textarea rows=\"4\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"(tempJob()?.responsibilities || []).join('\\n')\"\r\n (ngModelChange)=\"updateTempResponsibilities($event)\" name=\"newResponsibilities\"></textarea>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onWorkExperienceFileSelected($event)\" name=\"newWorkAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempJob()?.fileName\">\r\n <span>{{ tempJob()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempJob())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n <div class=\"d-flex justify-content-end gap-2 mt-3\">\r\n <button class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditJob(); $event.stopPropagation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingWork\"\r\n (click)=\"saveEditJob(); $event.stopPropagation()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Uploading...' : workActionLabel(editingJobIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <div *ngFor=\"let job of experience(); let i = index\" class=\"list-group-item p-0 border-0 mb-2\">\r\n\r\n <div class=\"work-accent-item p-3 rounded-3 bg-white border\">\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n <div class=\"d-flex align-items-center cursor-pointer flex-grow-1\" (click)=\"toggleJob(i)\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h6 class=\"mb-0 fw-bold item-title-sm\">{{ job.jobTitle }}</h6>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedWorkItem(i) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedWorkItem(i) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ job.company || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ formatMonthYear(job.startDate) }} - {{ job.isCurrent ? 'Present' :\r\n formatMonthYear(job.endDate) }}</span>\r\n <span class=\"item-meta-line\">{{ job.city }}<span *ngIf=\"job.city && job.state\">, </span>{{ job.state }}<ng-container *ngIf=\"!job.city && !job.state\">\u2014</ng-container></span>\r\n <div *ngIf=\"editingJobIndex() !== i && (workIssuesByIndex()[i] || []).length > 0\"\r\n class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (workIssuesByIndex()[i] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex align-items-center gap-2\">\r\n\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\" (click)=\"startEditJob(i)\"\r\n title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteJob(i);\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n \r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <div class=\"mt-3 p-3 rounded small\" *ngIf=\"expandedIndex() === i\">\r\n <ng-container *ngIf=\"editingJobIndex() !== i; else editJobForm\">\r\n <ul class=\"mb-0\">\r\n <li *ngFor=\"let res of job.responsibilities\">{{ res }}</li>\r\n </ul>\r\n </ng-container>\r\n\r\n <ng-template #editJobForm>\r\n <div *ngIf=\"(workIssuesByIndex()[i] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (workIssuesByIndex()[i] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.jobTitle\"\r\n (ngModelChange)=\"patchTempJob({ jobTitle: $event })\" name=\"jobTitle{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.jobTitle)\">Job title is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.company\"\r\n (ngModelChange)=\"patchTempJob({ company: $event })\" name=\"company{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.company)\">Company name is required</div>\r\n </div>\r\n\r\n <div class=\"align-items-end col-md-12 d-flex justify-content-end pe-3\">\r\n <div class=\"form-check\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"tempJob()?.isCurrent\"\r\n (ngModelChange)=\"setTempJobIsCurrent($event)\" name=\"isCurrent{{ i }}\" id=\"isCurrent{{ i }}\" />\r\n <label class=\"form-check-label\" for=\"isCurrent{{ i }}\">Current</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.country\"\r\n (ngModelChange)=\"patchTempJob({ country: $event })\" name=\"country{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.state\"\r\n (ngModelChange)=\"patchTempJob({ state: $event })\" name=\"state{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.city\"\r\n (ngModelChange)=\"patchTempJob({ city: $event })\" name=\"city{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.city)\">City is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempJob()?.startDate)\"\r\n (bsValueChange)=\"setTempJobMonth('startDate', $event)\" name=\"startDate{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.startDate)\">Start date is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [disabled]=\"tempJob()?.isCurrent\"\r\n [ngModel]=\"monthInputToDate(tempJob()?.endDate)\" (bsValueChange)=\"setTempJobMonth('endDate', $event)\"\r\n name=\"endDate{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!tempJob()?.isCurrent && isBlank(tempJob()?.endDate)\">\r\n End date is required\r\n </div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"!tempJob()?.isCurrent && isMonthRangeInvalid(tempJob()?.startDate, tempJob()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Responsibilities (one per line)</label>\r\n <textarea rows=\"4\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"(tempJob()?.responsibilities || []).join('\\n')\"\r\n (ngModelChange)=\"updateTempResponsibilities($event)\" name=\"responsibilities{{ i }}\"></textarea>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onWorkExperienceFileSelected($event)\" name=\"workAttachment{{ i }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempJob()?.fileName\">\r\n <span>{{ tempJob()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempJob())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n </ng-template>\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-3\" *ngIf=\"editingJobIndex() === i\">\r\n <button class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditJob(); $event.stopPropagation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4 \" [disabled]=\"isSavingWork\"\r\n (click)=\"saveEditJob(); $event.stopPropagation()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Uploading...' : workActionLabel(editingJobIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/patch-check-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Certifications</h5>\r\n <span *ngIf=\"certs().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"certificationSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ certificationSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"certs().length === 0 || !certificationSectionHasUnsavedItems() || isSavingCertification || isAddingCertification() || editingCertificationIndex() !== null\"\r\n (click)=\"confirmAllCertifications()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add certification\" (click)=\"addCertification()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"certs().length === 0 && !isAddingCertification() && editingCertificationIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addCertification()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/patch-check.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No certifications added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3 border\">\r\n <div *ngIf=\"isAddingCertification() && tempCertification()\" class=\"list-group-item py-3 px-3\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"tempCertification()?.professionId\" (change)=\"onCertificationProfessionChange($event)\"\r\n name=\"newCertProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('certificate')\">+</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.name\"\r\n (ngModelChange)=\"patchTempCertification({ name: $event })\" name=\"newCertName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempCertification()?.name)\">Certificate name is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.issuingOrganization || ''\"\r\n (ngModelChange)=\"patchTempCertification({ issuingOrganization: $event || null })\" name=\"newCertOrg\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.state || ''\"\r\n (ngModelChange)=\"patchTempCertification({ state: $event || null })\" name=\"newCertState\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certification Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.credentialId || ''\"\r\n (ngModelChange)=\"patchTempCertification({ credentialId: $event || null })\" name=\"newCertCredentialId\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('issueDate', $event)\" name=\"newCertIssueDate\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('expiryDate', $event)\" name=\"newCertExpiryDate\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempCertification()?.issueDate || null, tempCertification()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onCertificationFileSelected($event)\" name=\"newCertAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempCertification()?.fileName\">\r\n <span>{{ tempCertification()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempCertification())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditCertification()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\"\r\n [disabled]=\"isSavingCertification\"\r\n (click)=\"saveCertificationEditor()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Uploading...' : certificationActionLabel(editingCertificationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let cert of certs(); let ci = index\" class=\"list-group-item py-3 cert-accent-item\">\r\n <ng-container *ngIf=\"editingCertificationIndex() !== ci; else editCert\">\r\n <div class=\"d-flex justify-content-between align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <div class=\"fw-semibold item-title-sm\">{{ cert.name }}</div>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedCertificationItem(ci) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedCertificationItem(ci) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ cert.issuingOrganization || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.credentialId || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.issueDate ? formatMonthYear(cert.issueDate) : '\u2014' }} - {{ cert.expiryDate ? formatMonthYear(cert.expiryDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.state || '\u2014' }}</span>\r\n <div *ngIf=\"(certIssuesByIndex()[ci] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (certIssuesByIndex()[ci] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditCertification(ci)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\"\r\n (click)=\"deleteCertification(ci)\" title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #editCert>\r\n <div *ngIf=\"(certIssuesByIndex()[ci] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (certIssuesByIndex()[ci] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"tempCertification()?.professionId\" (change)=\"onCertificationProfessionChange($event)\"\r\n name=\"certProfessionType{{ ci }}\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('certificate')\">+</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.name\"\r\n (ngModelChange)=\"patchTempCertification({ name: $event })\" name=\"certName{{ ci }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempCertification()?.name)\">Certificate name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.issuingOrganization || ''\"\r\n (ngModelChange)=\"patchTempCertification({ issuingOrganization: $event || null })\"\r\n name=\"certOrg{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.state || ''\"\r\n (ngModelChange)=\"patchTempCertification({ state: $event || null })\" name=\"certState{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certification Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.credentialId || ''\"\r\n (ngModelChange)=\"patchTempCertification({ credentialId: $event || null })\"\r\n name=\"certCredentialId{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('issueDate', $event)\" name=\"certIssue{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('expiryDate', $event)\" name=\"certExpiry{{ ci }}\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempCertification()?.issueDate || null, tempCertification()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onCertificationFileSelected($event)\" name=\"certAttachment{{ ci }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempCertification()?.fileName\">\r\n <span>{{ tempCertification()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempCertification())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditCertification()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingCertification\"\r\n (click)=\"saveCertificationEditor()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Uploading...' : certificationActionLabel(editingCertificationIndex()) }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/card-checklist-warning.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Licenses</h5>\r\n <span *ngIf=\"licenses().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"licenseSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ licenseSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"licenses().length === 0 || !licenseSectionHasUnsavedItems() || isSavingLicense || isAddingLicense() || editingLicenseIndex() !== null\"\r\n (click)=\"confirmAllLicenses()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add license\" (click)=\"addLicense()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"licenses().length === 0 && !isAddingLicense() && editingLicenseIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addLicense()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/card-checklist.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No licenses added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3 border\">\r\n <div *ngIf=\"isAddingLicense() && tempLicense()\" class=\"list-group-item py-3 px-3\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.name\"\r\n (ngModelChange)=\"patchTempLicense({ name: $event })\" name=\"newLicName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempLicense()?.name)\">License name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.issuingAuthority || ''\"\r\n (ngModelChange)=\"patchTempLicense({ issuingAuthority: $event || null })\" name=\"newLicAuthority\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.licenseNumber || ''\"\r\n (ngModelChange)=\"patchTempLicense({ licenseNumber: $event || null })\" name=\"newLicNumber\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.state || ''\"\r\n (ngModelChange)=\"patchTempLicense({ state: $event || null })\" name=\"newLicState\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('issueDate', $event)\" name=\"newLicIssueDate\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('expiryDate', $event)\" name=\"newLicExpiryDate\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempLicense()?.issueDate || null, tempLicense()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">License File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onLicenseFileSelected($event)\" name=\"newLicenseAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempLicense()?.fileName\">\r\n <span>{{ tempLicense()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempLicense())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelEditLicense()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingLicense\"\r\n (click)=\"saveLicenseEditor()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Uploading...' : licenseActionLabel(editingLicenseIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let lic of licenses(); let li = index\" class=\"list-group-item py-3 lic-accent-item\">\r\n <ng-container *ngIf=\"editingLicenseIndex() !== li; else editLic\">\r\n <div class=\"d-flex justify-content-between align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <div class=\"fw-semibold item-title-sm\">{{ lic.name }}</div>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedLicenseItem(li) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedLicenseItem(li) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ lic.issuingAuthority || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.licenseNumber || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.issueDate ? formatMonthYear(lic.issueDate) : '\u2014' }} - {{ lic.expiryDate ? formatMonthYear(lic.expiryDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.state || '\u2014' }}</span>\r\n <div *ngIf=\"(licenseIssuesByIndex()[li] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (licenseIssuesByIndex()[li] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditLicense(li)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteLicense(li)\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #editLic>\r\n <div *ngIf=\"(licenseIssuesByIndex()[li] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (licenseIssuesByIndex()[li] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.name\"\r\n (ngModelChange)=\"patchTempLicense({ name: $event })\" name=\"licName{{ li }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempLicense()?.name)\">License name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.issuingAuthority || ''\"\r\n (ngModelChange)=\"patchTempLicense({ issuingAuthority: $event || null })\" name=\"licAuthority{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.licenseNumber || ''\"\r\n (ngModelChange)=\"patchTempLicense({ licenseNumber: $event || null })\" name=\"licNumber{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.state || ''\"\r\n (ngModelChange)=\"patchTempLicense({ state: $event || null })\" name=\"licState{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('issueDate', $event)\" name=\"licIssue{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('expiryDate', $event)\" name=\"licExpiry{{ li }}\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempLicense()?.issueDate || null, tempLicense()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">License File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onLicenseFileSelected($event)\" name=\"licenseAttachment{{ li }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempLicense()?.fileName\">\r\n <span>{{ tempLicense()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempLicense())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditLicense()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingLicense\"\r\n (click)=\"saveLicenseEditor()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Uploading...' : licenseActionLabel(editingLicenseIndex()) }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/tools.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Tools</h5>\r\n <span *ngIf=\"tools().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"toolsSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ toolsSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"tools().length === 0 || !toolsSectionHasUnsavedItems() || isSavingTool || isToolEditorOpen()\" (click)=\"confirmAllTools()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add tool\" (click)=\"addTool()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex flex-wrap gap-2 p-3 bg-white border rounded shadow-sm\">\r\n <div *ngFor=\"let tool of tools(); let ti = index\" class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\"\r\n class=\"btn btn-light border res-flex d-inline-flex align-items-center gap-2 px-3 py-2\"\r\n (click)=\"openToolEditor(ti)\" title=\"Edit\">\r\n <span class=\"fw-normal item-name-text\">{{ tool }}</span>\r\n <span class=\"badge border ms-1\"\r\n [ngClass]=\"hasUnsavedToolItem(ti) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedToolItem(ti) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n <span *ngIf=\"(toolIssuesByIndex()[ti] || []).length > 0\"\r\n class=\"badge bg-warning-subtle text-warning border ms-1\">\r\n Missing info\r\n </span>\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-danger rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Delete tool\" (click)=\"deleteTool(ti)\">\r\n <span class=\"fw-bold\">\u00D7</span>\r\n </button>\r\n </div>\r\n\r\n <span *ngIf=\"tools().length === 0\" class=\"text-muted small\">No tools added.</span>\r\n </div>\r\n\r\n <div *ngIf=\"isToolEditorOpen()\" class=\"position-fixed top-0 start-0 w-100 h-100\"\r\n style=\"background: rgba(0,0,0,0.35); z-index: 9999999;\" (click)=\"closeToolEditor()\">\r\n <div class=\"container h-100 d-flex align-items-start justify-content-center pt-4\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"card shadow border-0 w-100\" style=\"max-width: 900px;\">\r\n <div class=\"card-header bg-white d-flex align-items-center gap-3\">\r\n <button type=\"button\" class=\"btn btn-link p-0 text-decoration-none\" (click)=\"closeToolEditor()\">\r\n <img src=\"/assets/images/icons/arrow-left-blue.svg\" width=\"20\" height=\"20\" alt=\"\" />\r\n </button>\r\n <div class=\"fw-bold\">{{ isAddingTool() ? 'Add Tool' : ('Edit ' + (toolForm()?.name || '') + ' Tool') }}\r\n </div>\r\n </div>\r\n <div class=\"card-body p-4\">\r\n <div *ngIf=\"toolFormIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ toolFormIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"row g-3\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"toolForm()?.professionId\" (change)=\"onToolProfessionChange($event)\"\r\n name=\"toolProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('tool')\">+</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Tool Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"toolForm()?.name\"\r\n (ngModelChange)=\"patchToolForm({ name: $event })\" name=\"toolName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(toolForm()?.name)\">Tool name is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating</label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempToolStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"(toolForm()?.stars || 0) >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ (toolForm()?.stars || 0) >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ toolForm()?.stars || 0 }}/5</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Years of Experience</label>\r\n <input type=\"number\" class=\"form-control\" [ngModel]=\"toolForm()?.year\"\r\n (ngModelChange)=\"patchToolForm({ year: $event === '' ? 0 : +$event })\" name=\"toolYear\" min=\"0\"\r\n max=\"30\" placeholder=\"Years of Experience\" />\r\n </div>\r\n\r\n <div class=\"col-md-4 text-center\">\r\n <label class=\"small text-muted d-block\">Profile Visibility</label>\r\n <div class=\"form-checks form-switch mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"toolForm()?.profileVisibility\"\r\n (ngModelChange)=\"patchToolForm({ profileVisibility: $event })\" name=\"toolVisible\" id=\"toolVisible\"\r\n style=\"width: 55px;height: 25px;margin-left: -57px;\" />\r\n <label class=\"form-check-label ps-2 pt-1\" for=\"toolVisible\">Visible</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Comment</label>\r\n <textarea rows=\"4\" class=\"form-control\" [ngModel]=\"toolForm()?.notes\"\r\n (ngModelChange)=\"patchToolForm({ notes: $event })\" name=\"toolNotes\"\r\n placeholder=\"Enter additional details (optional)\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer bg-white d-flex justify-content-end gap-2\">\r\n <button *ngIf=\"!isAddingTool() && editingToolIndex() !== null\" type=\"button\"\r\n class=\"btn btn-link text-danger me-auto\" (click)=\"deleteTool(editingToolIndex()!)\">\r\n Delete\r\n </button>\r\n <button type=\"button\" class=\"btn btn-link text-secondary\" (click)=\"closeToolEditor()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary px-4\" [disabled]=\"isSavingTool\" (click)=\"saveToolEditor()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Saving...' : toolActionLabel(editingToolIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row g-4 mb-5\">\r\n <div class=\"col-md-12\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/stars.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Skills</h5>\r\n <span *ngIf=\"skills().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"skillsSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ skillsSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"skills().length === 0 || !skillsSectionHasUnsavedItems() || isSavingSkill || isSkillEditorOpen()\" (click)=\"confirmAllSkills()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add skill\" (click)=\"addSkill()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex flex-wrap gap-2 p-3 bg-white border rounded shadow-sm\">\r\n <div *ngFor=\"let skill of skills(); let si = index\" class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\"\r\n class=\"btn btn-light border res-flex d-inline-flex align-items-center gap-2 px-3 py-2\"\r\n (click)=\"openSkillEditor(si)\" title=\"Edit\">\r\n <span class=\"fw-normal item-name-text\">{{ skill }}</span>\r\n <span class=\"badge border ms-1\"\r\n [ngClass]=\"hasUnsavedSkillItem(si) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedSkillItem(si) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n <span *ngIf=\"(skillIssuesByIndex()[si] || []).length > 0\"\r\n class=\"badge bg-warning-subtle text-warning border ms-1\">\r\n Missing info\r\n </span>\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-danger rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Delete skill\"\r\n (click)=\"deleteSkill(si); $event.stopPropagation()\">\r\n <span class=\"fw-bold\">\u00D7</span>\r\n </button>\r\n </div>\r\n\r\n <span *ngIf=\"skills().length === 0\" class=\"text-muted small\">No skills added.</span>\r\n </div>\r\n <div *ngIf=\"isSkillEditorOpen()\" class=\"position-fixed top-0 start-0 w-100 h-100\"\r\n style=\"background: rgba(0,0,0,0.35); z-index: 9999999;\" (click)=\"closeSkillEditor()\">\r\n <div class=\"container h-100 d-flex align-items-start justify-content-center pt-4\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"card shadow border-0 w-100\" style=\"max-width: 900px;\">\r\n <div class=\"card-header bg-white d-flex align-items-center gap-3\">\r\n <button type=\"button\" class=\"btn btn-link p-0 text-decoration-none\" (click)=\"closeSkillEditor()\">\r\n <img src=\"/assets/images/icons/arrow-left-blue.svg\" width=\"20\" height=\"20\" alt=\"\" />\r\n </button>\r\n <div class=\"fw-bold\">{{ isAddingSkill() ? 'Add Skill' : ('Edit ' + (skillForm()?.name || '') + ' Skill')\r\n }}</div>\r\n </div>\r\n <div class=\"card-body p-4\">\r\n <div *ngIf=\"skillFormIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ skillFormIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"row g-3\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"skillForm()?.professionId\" (change)=\"onSkillProfessionChange($event)\"\r\n name=\"skillProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('skill')\">+</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Skills Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"skillForm()?.name\"\r\n (ngModelChange)=\"patchSkillForm({ name: $event })\" name=\"skillName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(skillForm()?.name)\">Skillset name is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating</label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempSkillStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"(skillForm()?.stars || 0) >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ (skillForm()?.stars || 0) >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ skillForm()?.stars || 0 }}/5</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Years of Experience</label>\r\n <input type=\"number\" class=\"form-control\" [ngModel]=\"skillForm()?.year\"\r\n (ngModelChange)=\"patchSkillForm({ year: $event === '' ? 0 : +$event })\" name=\"skillYear\" min=\"0\"\r\n max=\"30\" placeholder=\"Years of Experience\" />\r\n </div>\r\n\r\n <div class=\"col-md-4 text-center\">\r\n <label class=\"small text-muted d-block\">Profile Visibility</label>\r\n <div class=\"form-checks form-switch mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"skillForm()?.profileVisibility\"\r\n (ngModelChange)=\"patchSkillForm({ profileVisibility: $event })\" name=\"skillVisible\"\r\n id=\"skillVisible\" style=\"width: 55px;height: 25px;margin-left: -57px;\" />\r\n <label class=\"form-check-label ps-2 pt-1\" for=\"skillVisible\">Visible</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Comment</label>\r\n <textarea rows=\"4\" class=\"form-control\" [ngModel]=\"skillForm()?.notes\"\r\n (ngModelChange)=\"patchSkillForm({ notes: $event })\" name=\"skillNotes\"\r\n placeholder=\"Enter additional details (optional)\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer bg-white d-flex justify-content-end gap-2\">\r\n <button *ngIf=\"!isAddingSkill() && editingSkillIndex() !== null\" type=\"button\"\r\n class=\"btn btn-link text-danger me-auto\" (click)=\"deleteSkill(editingSkillIndex()!)\">\r\n Delete\r\n </button>\r\n <button type=\"button\" class=\"btn btn-link text-secondary\" (click)=\"closeSkillEditor()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary px-4\" [disabled]=\"isSavingSkill\" (click)=\"saveSkillEditor()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Saving...' : skillActionLabel(editingSkillIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row g-4 mb-5\">\r\n <div class=\"col-md-12\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/mortarboard-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Education</h5>\r\n <span *ngIf=\"educationList().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"educationSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ educationSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"educationList().length === 0 || !educationSectionHasUnsavedItems() || isSavingEducation || isAddingEducation() || editingEducationIndex() !== null\"\r\n (click)=\"confirmAllEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add education\" (click)=\"addEducation()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"educationList().length === 0 && !isAddingEducation() && editingEducationIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addEducation()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/mortarboard.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No education added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div *ngIf=\"isAddingEducation() && tempEducation()\" class=\"mb-2\">\r\n <div class=\"form-panel\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.degree\"\r\n (ngModelChange)=\"patchTempEducation({ degree: $event })\" name=\"newEduDegree\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degree)\">Degree / Course name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Institution <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.institution\"\r\n (ngModelChange)=\"patchTempEducation({ institution: $event })\" name=\"newEduInstitution\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree / Course Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"ng-select-sm\" [items]=\"educationDegreeTypeOptions\" [clearable]=\"false\"\r\n placeholder=\"Select degree / course type\" [ngModel]=\"tempEducation()?.degreeType\"\r\n (ngModelChange)=\"patchTempEducation({ degreeType: $event })\" name=\"newEduDegreeType\">\r\n </ng-select>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degreeType)\">Degree / Course type is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.country\"\r\n (ngModelChange)=\"patchTempEducation({ country: $event })\" name=\"newEduCountry\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.state\"\r\n (ngModelChange)=\"patchTempEducation({ state: $event })\" name=\"newEduState\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.city\"\r\n (ngModelChange)=\"patchTempEducation({ city: $event })\" name=\"newEduCity\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.startDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('startDate', $event)\" name=\"newEduStartDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.startDate)\">Start date is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.endDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('endDate', $event)\" name=\"newEduEndDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.endDate)\">End date is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempEducation()?.startDate, tempEducation()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Education File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onEducationFileSelected($event)\" name=\"newEducationAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempEducation()?.fileName\">\r\n <span>{{ tempEducation()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempEducation())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditEducation()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingEducation\"\r\n (click)=\"saveEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Uploading...' : educationActionLabel(editingEducationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let edu of educationList(); let ei = index\" class=\"edu-accent-item p-3 bg-white border rounded-3 shadow-sm mb-2\">\r\n <div class=\"d-flex justify-content-between align-items-start\">\r\n <div class=\"d-flex align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h6 class=\"fw-bold mb-0 item-title-sm\">{{ edu.degree }}</h6>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedEducationItem(ei) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedEducationItem(ei) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ edu.institution || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.degreeType || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.startDate ? formatMonthYear(edu.startDate) : '\u2014' }} - {{ edu.endDate ? formatMonthYear(edu.endDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.city }}<span *ngIf=\"edu.city && edu.state\">, </span>{{ edu.state }}<ng-container *ngIf=\"!edu.city && !edu.state\">\u2014</ng-container></span>\r\n <div *ngIf=\"(educationIssuesByIndex()[ei] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (educationIssuesByIndex()[ei] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\" *ngIf=\"editingEducationIndex() !== ei\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditEducation(ei)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteEducation(ei)\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"editingEducationIndex() === ei\" class=\"mt-3\">\r\n <div *ngIf=\"(educationIssuesByIndex()[ei] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (educationIssuesByIndex()[ei] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.degree\"\r\n (ngModelChange)=\"patchTempEducation({ degree: $event })\" name=\"eduDegree{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degree)\">Degree / Course name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Institution <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.institution\"\r\n (ngModelChange)=\"patchTempEducation({ institution: $event })\" name=\"eduInstitution{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.institution)\">Institution name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree / Course Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"ng-select-sm\" [items]=\"educationDegreeTypeOptions\" [clearable]=\"false\"\r\n placeholder=\"Select degree / course type\" [ngModel]=\"tempEducation()?.degreeType\"\r\n (ngModelChange)=\"patchTempEducation({ degreeType: $event })\" name=\"eduDegreeType{{ ei }}\">\r\n </ng-select>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degreeType)\">Degree / Course type is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.country\"\r\n (ngModelChange)=\"patchTempEducation({ country: $event })\" name=\"eduCountry{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.state\"\r\n (ngModelChange)=\"patchTempEducation({ state: $event })\" name=\"eduState{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.city\"\r\n (ngModelChange)=\"patchTempEducation({ city: $event })\" name=\"eduCity{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.startDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('startDate', $event)\" name=\"eduStartDate{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.startDate)\">Start date is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.endDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('endDate', $event)\" name=\"eduEndDate{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.endDate)\">End date is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempEducation()?.startDate, tempEducation()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Education File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onEducationFileSelected($event)\" name=\"educationAttachment{{ ei }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempEducation()?.fileName\">\r\n <span>{{ tempEducation()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempEducation())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelEditEducation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingEducation\" (click)=\"saveEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Uploading...' : educationActionLabel(editingEducationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n </div>\r\n <div class=\"d-flex gap-3 justify-content-center mt-5 pt-2\" *ngIf=\"!isResume\">\r\n <button class=\"btn btn-outline-secondary preview-back-btn px-5 h-auto\" style=\"border-radius: 5px !important;\" (click)=\"onBackClick()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"me-1\" style=\"vertical-align:-0.1em\">\r\n <path d=\"M11 3 5 8l6 5\" />\r\n </svg> Back\r\n </button>\r\n <button class=\"btn btn-primary preview-dashboard-btn px-5 h-auto\" style=\"border-radius: 5px !important;\" [disabled]=\"!canConfirmAndContinue() || isSavingBasic\"\r\n (click)=\"onGoToDashboardClick()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Saving...' : 'Go to Dashboard' }}\r\n <img *ngIf=\"!isSavingBasic\" src=\"/assets/images/icons/arrow-right-white.svg\" width=\"14\" height=\"14\" class=\"ms-1\" style=\"vertical-align:-0.1em\" alt=\"\" />\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<ng-template #loading>\r\n <div class=\"text-center p-5\">\r\n <div class=\"spinner-border text-primary\"></div>\r\n <p class=\"text-muted mt-2\">Loading data...</p>\r\n </div>\r\n</ng-template>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showCustomProfessionForm\" style=\"z-index: 9999999;\">\r\n <div class=\"confirm-modal-card add-profession-card\" style=\"max-width: 420px;\">\r\n <h4 class=\"mb-1\">Add New Profession</h4>\r\n <p class=\"text-muted small mb-4\">This profession isn't in the list yet. Add it here so you can link it to this\r\n {{ customProfessionContext }}.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"customProfessionName\" name=\"customProfessionName\"\r\n placeholder=\"Enter profession name\" />\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Group <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"add-profession-select\" [items]=\"professionGroupOptions\" [(ngModel)]=\"customProfessionGroup\" name=\"customProfessionGroup\"\r\n placeholder=\"Select group\" [clearable]=\"false\" [appendTo]=\"'body'\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"add-profession-select\" [items]=\"professionTypeOptions\" [(ngModel)]=\"customProfessionType\" name=\"customProfessionType\"\r\n placeholder=\"Select type\" [clearable]=\"false\" [appendTo]=\"'body'\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating</label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempCustomProfessionStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"customProfessionStars >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ customProfessionStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ customProfessionStars }}/5</span>\r\n </div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience</label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"customProfessionYear\" name=\"customProfessionYear\"\r\n min=\"0\" max=\"30\" placeholder=\"Years of Experience\" />\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelCustomProfessionForm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\" [disabled]=\"!canSaveCustomProfession || isSavingCustomProfession\"\r\n (click)=\"saveCustomProfession()\">\r\n <span *ngIf=\"isSavingCustomProfession\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCustomProfession ? 'Saving...' : 'Add Profession' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBulkSkillConfirm\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 480px;\">\r\n <h4 class=\"mb-1\">Set Rating for All Skills</h4>\r\n <p class=\"text-muted small mb-4\">Enter a star rating and years of experience (and optionally a profession type) to apply to all skills that are missing these values.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Type</label>\r\n <ng-select [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"bulkSkillProfessionId\" (change)=\"onBulkSkillProfessionChange($event)\"\r\n name=\"bulkSkillProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"bulkSkillStars = s\">\r\n <span [class]=\"bulkSkillStars >= s ? 'text-warning fs-4' : 'text-muted fs-4'\">\r\n {{ bulkSkillStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ bulkSkillStars }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkSkillStars <= 0\">Star rating is required</div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"bulkSkillYear\" min=\"1\" max=\"30\"\r\n placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkSkillYear === null || bulkSkillYear === undefined\">Years of experience is required</div>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelBulkSkillConfirm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\"\r\n [disabled]=\"isSavingSkill || bulkSkillStars <= 0 || bulkSkillYear === null\"\r\n (click)=\"applyBulkSkillConfirm()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Saving...' : 'Apply to All & Save' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBulkToolConfirm\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 480px;\">\r\n <h4 class=\"mb-1\">Set Rating for All Tools</h4>\r\n <p class=\"text-muted small mb-4\">Enter a star rating and years of experience (and optionally a profession type) to apply to all tools that are missing these values.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Type</label>\r\n <ng-select [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"bulkToolProfessionId\" (change)=\"onBulkToolProfessionChange($event)\"\r\n name=\"bulkToolProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"bulkToolStars = s\">\r\n <span [class]=\"bulkToolStars >= s ? 'text-warning fs-4' : 'text-muted fs-4'\">\r\n {{ bulkToolStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ bulkToolStars }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkToolStars <= 0\">Star rating is required</div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"bulkToolYear\" min=\"1\" max=\"30\"\r\n placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkToolYear === null || bulkToolYear === undefined\">Years of experience is required</div>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelBulkToolConfirm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\"\r\n [disabled]=\"isSavingTool || bulkToolStars <= 0 || bulkToolYear === null\"\r\n (click)=\"applyBulkToolConfirm()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Saving...' : 'Apply to All & Save' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBackConfirmPopup\">\r\n <div class=\"confirm-modal-card\">\r\n <h4 class=\"mb-2\">Leave this page?</h4>\r\n <p class=\"text-muted mb-4\">If you go back, only saved data will be retained.</p>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"stayOnPreview()\">Stay</button>\r\n <button type=\"button\" class=\"btn btn-danger h-auto\" (click)=\"proceedBack()\">Proceed Back</button>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showDashboardConfirmPopup\">\r\n <div class=\"confirm-modal-card\">\r\n <h4 class=\"mb-2\">Finish Setup and Continue</h4>\r\n <p class=\"text-muted mb-4\">Save your information and go to your dashboard</p>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" [disabled]=\"isSavingBasic\"\r\n (click)=\"cancelDashboardRedirect()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\" [disabled]=\"isSavingBasic\" (click)=\"goToDashboard()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Proceeding...' : 'Proceed' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{color:#69707d}.res-flex:hover,.res-flex:focus,.res-flex:active{transform:none!important;box-shadow:none!important}::ng-deep .form-check-input{margin-left:unset!important}.profession-search-input{font-size:12px}.profession-search-input::placeholder{font-size:12px}.profession-row-selected{background-color:#f2f4fa}.profession-row-selected .profession-acc-header:hover{background-color:#eceffa}.profession-visibility-checkbox{all:revert;width:16px!important;height:16px!important;min-width:16px!important;max-width:16px!important;margin:4px auto 0!important;padding:0!important;position:static!important;float:none!important;vertical-align:middle!important;background-image:none!important;transform:none!important}.profession-accordion,.profession-accordion label.small{font-size:12px;color:#69707d}.profession-acc-columns,.profession-acc-header{display:grid;grid-template-columns:36px 2fr 1fr 1fr 32px;align-items:center;gap:12px}.profession-acc-columns{padding:12px 16px;border-bottom:1px solid #e9ecef;font-size:13px;font-weight:600;color:#69707d;text-transform:uppercase}@media (max-width: 767.98px){.profession-acc-columns{display:none}}.profession-acc-item{border-bottom:1px solid #f1f3f5}.profession-acc-item:last-child{border-bottom:none}.profession-acc-header{padding:12px 16px;cursor:pointer;transition:background-color .15s ease}.profession-acc-header:hover{background-color:#f8f9fb}.profession-acc-name{color:#69707d}.profession-acc-chevron-btn{background:transparent;border:none;padding:4px;display:inline-flex;align-items:center;justify-content:center;color:#69707d}.profession-acc-chevron{transition:transform .2s ease}.profession-acc-chevron--open{transform:rotate(180deg)}.profession-acc-body{padding:0 16px 16px}.profession-acc-panel{background-color:#fff;border:1px solid #e9ecef;border-radius:8px;padding:16px 20px}.profession-acc-fields{display:flex;flex-wrap:wrap;align-items:flex-start;gap:32px}.profession-acc-field{min-width:100px}.profession-acc-field--visibility{display:flex;flex-direction:column;align-items:center;width:90px;flex-shrink:0}.profession-acc-field--visibility label{text-align:center;width:100%}.profession-acc-field--notes{flex:1 1 220px;margin:0}.profession-acc-stars{font-size:1.05rem;letter-spacing:2px}.profession-acc-year-input{width:72px}.profession-inline-select{min-width:160px;font-size:12px}.profession-inline-select ::ng-deep .ng-select-container{min-height:32px!important;height:32px!important}::ng-deep .profession-inline-select .ng-option,::ng-deep .profession-inline-select .ng-placeholder{font-size:12px}.profession-notes-input{min-height:76px;resize:vertical}.container{max-width:900px;margin:30px auto;font-family:Arial,sans-serif;color:#69707d}.preview-page-header{max-width:900px;margin:50px auto 10px;padding:0 12px}.preview-title{font-size:18px;font-weight:700;color:#69707d;margin:0}.preview-subtitle{margin-top:7px;font-size:14px;color:#69707d}.preview-card-gradient h2,.section h5.fw-bold{font-size:18px}.section{margin-bottom:25px}.section-title{font-weight:600;display:block;margin-bottom:8px}.section-title .sub{font-weight:400;color:#777;font-size:13px}.dropdown-box{border:1px solid #ddd;border-radius:8px;padding:12px 15px;display:flex;justify-content:space-between;align-items:center}.icons{display:flex;gap:10px}.icon{cursor:pointer;font-size:14px;color:#777}.card{border:1px solid #ddd;border-radius:5px;padding:20px;background:#fff}.category{border-bottom:1px solid #eee;padding:15px 0}.category:last-child{border-bottom:none}.category-header{display:flex;justify-content:space-between;font-weight:600;margin-bottom:10px}.tags{display:flex;flex-wrap:wrap;gap:10px}.tag{background:#f2f4f7;padding:6px 12px;border-radius:6px;font-size:13px}.footer{text-align:center;margin-top:15px;color:#777;cursor:pointer}.actions{display:flex;justify-content:space-between;margin:50px 0 27px}.text-secondary{white-space:pre-line;font-size:12px;color:#69707d}.extra-small{font-size:.8rem}.card{transition:box-shadow .2s ease}.achievement-section .badge{font-size:.75rem;white-space:normal;text-align:left}.skill-tag .badge{font-weight:500;font-size:.9rem;transition:all .2s ease;cursor:default}.skill-tag .badge:hover{transform:translateY(-2px)}.skill-tag .btn-close{opacity:.5}.skill-tag .btn-close:hover{opacity:1}.bg-light.text-dark.border{background-color:#f8f9fa!important;border-color:#dee2e6!important}.card{transition:all .3s cubic-bezier(.25,.8,.25,1)}.card:hover .bg-light{background-color:#e8f5e9!important}.position-fixed .card:hover{transform:none!important}code{background-color:#f8f9fa;padding:2px 6px;border-radius:4px}.list-group-item{transition:background-color .2s ease-in-out}.list-group-item:hover{background-color:#fcfcfc}.border-dashed{border-style:dashed!important}.tool-card{transition:all .2s ease-in-out;border-radius:12px}.tool-card:hover{transform:translateY(-5px);border-color:var(--bs-primary)!important}.tool-card:hover .icon-box{background-color:var(--bs-primary-subtle)!important}.tool-card .icon-box{width:60px;height:60px;transition:background-color .2s ease}.border-dashed{border:2px dashed #dee2e6!important}.border-dashed:hover{border-color:var(--bs-primary)!important;background-color:#fff!important}.popup{position:fixed;top:20%;right:20px;width:320px;max-width:calc(100vw - 32px);background:#fff;border-radius:10px;padding:16px}.status-row{display:flex;justify-content:space-between;margin:10px 0}.success{color:#2e7d32;font-weight:700}.error{color:#d32f2f}.pending{color:#f9a825}.section-flag{font-weight:600}button.btn.btn-sm.btn-outline-primary{background-color:#4077ad;border-color:#4077ad;color:#fff;border-radius:5px!important}button.btn.btn-sm.btn-outline-primary:hover{background-color:#356895;border-color:#356895;color:#fff}button.btn.btn-sm.btn-outline-danger{border:1px solid #dc3545;color:#dc3545;border-radius:5px!important}button.btn.btn-sm.btn-outline-primary.rounded-circle{background-color:#4077ad;border-color:#4077ad;color:#fff;border-radius:5px!important}button.action-icon-btn{min-width:22px;width:22px;height:22px;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:5px!important;background:transparent!important;border:none!important;line-height:1}button.action-icon-btn.btn-outline-primary{color:#4077ad!important;border-color:#4077ad!important}button.action-icon-btn.btn-outline-danger{color:#dc3545!important}.action-icon-image{width:20px;height:20px;object-fit:contain;display:inline-block}.action-icon-image.edit-icon{filter:brightness(0) saturate(100%) invert(41%) sepia(39%) saturate(774%) hue-rotate(170deg) brightness(91%) contrast(89%)}.action-icon-image.delete-icon{filter:brightness(0) saturate(100%) invert(24%) sepia(79%) saturate(4008%) hue-rotate(344deg) brightness(91%) contrast(90%)}.modal-overlay{position:fixed;inset:0;background:#11182773;display:flex;align-items:center;justify-content:center;z-index:2500;padding:20px}.status-modal-card{width:min(760px,96vw);max-height:85vh;overflow:auto;background:#fff;border-radius:16px;border:1px solid #e5e7eb}.status-modal-header{padding:20px 24px 14px;border-bottom:1px solid #eef2f7}.status-modal-body{padding:12px 20px 20px}.status-modal-footer{padding:12px 20px 20px;border-top:1px solid #eef2f7;display:flex;justify-content:end;align-items:center;gap:12px}.status-modal-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px 10px;border-bottom:1px solid #f1f5f9}.status-modal-row:last-child{border-bottom:0}.status-modal-name{font-size:14px;font-weight:600;color:#69707d}.status-modal-state{font-size:.92rem;font-weight:600}.status-modal-state.pending{color:#a16207}.status-modal-state.success{color:#166534}.status-modal-state.partial{color:#b45309}.status-modal-state.error{color:#b91c1c}.confirm-modal-card{width:min(520px,96vw);max-height:85vh;overflow-y:auto;background:#fff;border-radius:5px;border:1px solid #e5e7eb;padding:24px}.year-experience-select{max-height:150px}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:220px;overflow-y:auto}@media screen and (max-width: 768px){.res-flex{flex-wrap:wrap!important;justify-content:center!important}.res-flex .fw-normal{width:100%;text-align:center;font-size:14px!important}.d-flex.flex-wrap.gap-2.p-3.bg-white.border.rounded.shadow-sm{justify-content:center}.preview-page-header{margin:20px auto 8px;padding:0 4px}.container{padding-left:4px;padding-right:4px}.preview-title{font-size:16px}.preview-subtitle{font-size:14px}.actions{margin:24px 0 16px}.section-header-title{flex-wrap:wrap}.section-header-title>.section-flag{flex-basis:53%}.section-header-row{align-items:flex-start}.preview-card-gradient{padding:14px 14px 12px}.preview-card-gradient h2{font-size:18px}.popup{width:calc(100vw - 40px);right:16px;top:12%}.card{padding:0}.card-body.p-4,.px-4.py-3{padding:12px!important}.row.g-4,.row.g-3{--bs-gutter-x: .75rem}.d-flex.gap-4{gap:10px!important}.preview-card-gradient>.d-flex.justify-content-between.align-items-start{flex-wrap:wrap;row-gap:8px}.preview-card-gradient>.d-flex.justify-content-between.align-items-start>.badge.bg-primary-subtle{margin-left:auto}}@media screen and (max-width: 575px){.preview-title{font-size:16px}.preview-subtitle{font-size:14px}.section>.d-flex{flex-wrap:wrap;row-gap:8px}.section>.d-flex>.d-flex:last-child{width:100%;justify-content:flex-end}}::ng-deep .bs-datepicker-head{background-color:#4077ad!important}::ng-deep .bs-datepicker-body table td span.selected,.bs-datepicker-body table td.selected span{background-color:#4077ad!important}.profile-avatar-circle{width:58px;height:58px;border-radius:5px;background:#4077ad;display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:700;color:#fff;letter-spacing:1px;flex-shrink:0}.section-header-icon{font-size:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;opacity:.9;filter:invert(47%) sepia(8%) saturate(483%) hue-rotate(176deg) brightness(91%) contrast(87%)}.section-header-title h5.fw-bold{color:#69707d}.text-muted{color:#69707d!important}h6.text-uppercase.fw-bold.text-muted{font-size:14px;color:#69707d!important}.work-accent-item{border-radius:5px!important;transition:background-color .18s ease,box-shadow .18s ease}.work-accent-item:hover{background-color:#f5f8ff!important;box-shadow:0 4px 14px #4077ad17!important}.edu-accent-item{border-radius:5px!important;transition:background-color .18s ease,box-shadow .18s ease}.edu-accent-item:hover{background-color:#f8f8ff!important;box-shadow:0 4px 14px #6366f117!important}.cert-accent-item{border-radius:5px!important;transition:background-color .18s ease}.cert-accent-item:hover{background-color:#f0fdf4!important}.lic-accent-item{border-radius:5px!important;transition:background-color .18s ease}.lic-accent-item:hover{background-color:#fffbeb!important}.field-label-sm{font-size:14px;font-weight:700;color:#69707d;margin-bottom:3px;display:block}.item-name-text,.field-value-sm{font-size:12px;color:#69707d}.item-title-sm{font-size:14px;color:#69707d!important}.item-meta-line{display:block;font-size:12px;color:#69707d;margin-top:3px}.empty-state-wrap{text-align:center;padding:32px 20px;background:#fafbfc;border:1.5px dashed #d1d5db;border-radius:5px;cursor:pointer;transition:background-color .18s ease,border-color .18s ease}.empty-state-wrap .empty-icon{font-size:2rem;color:#d1d5db;margin-bottom:8px}.empty-state-wrap p{color:#9ca3af;margin:0;font-size:14px}.empty-state-wrap:hover{background:#f0f6ff;border-color:#4077ad}.form-panel{background:#fff;border:1px solid #e2e8f0;border-radius:5px;padding:20px}.form-panel .form-control,.form-panel .form-select{border-color:#d1d5db;border-radius:8px;font-size:12px}.form-panel .form-control:focus,.form-panel .form-select:focus{border-color:#4077ad;box-shadow:0 0 0 3px #4077ad1f}.section-header-bar{display:flex;align-items:center;justify-content:space-between;padding:10px 0 14px;border-bottom:2px solid #f1f5f9;margin-bottom:16px}.preview-card-gradient{background:linear-gradient(135deg,#fff,#eff6ff);border-bottom:1px solid #e2e8f0;padding:20px 24px 16px;border-radius:5px 5px 0 0}.profile-header-card{border:1px solid #e2e8f0!important}.item-icon-circle{width:40px;height:40px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;color:#fff;flex-shrink:0}.item-avatar--work{background:linear-gradient(135deg,#4077ad,#2d5a8a)}.item-avatar--edu{background:linear-gradient(135deg,#4077ad,#4338ca)}.provider-layout{display:flex;flex-direction:column}.provider-company-first{order:-1}.section-locked{pointer-events:none;opacity:.45;filter:blur(1.5px);-webkit-user-select:none;user-select:none}.btn.btn-primary{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important;padding:.375rem .75rem;line-height:1.5}.btn.btn-primary:hover:not(:disabled),.btn.btn-primary:focus:not(:disabled),.btn.btn-primary:active:not(:disabled){background-color:#356895!important;border-color:#356895!important;color:#fff!important}.btn.btn-success,.btn.btn-outline-success{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-success:hover:not(:disabled),.btn.btn-success:focus:not(:disabled),.btn.btn-success:active:not(:disabled),.btn.btn-outline-success:hover:not(:disabled),.btn.btn-outline-success:focus:not(:disabled),.btn.btn-outline-success:active:not(:disabled){background-color:#336843!important;border-color:#336843!important;color:#fff!important}.btn.btn-outline-secondary.rounded-pill{background-color:#69707d!important;border-color:#69707d!important;color:#fff!important;border-radius:5px!important}.btn.btn-outline-secondary.rounded-pill:hover:not(:disabled),.btn.btn-outline-secondary.rounded-pill:focus:not(:disabled),.btn.btn-outline-secondary.rounded-pill:active:not(:disabled){background-color:#565c66!important;border-color:#565c66!important;color:#fff!important}.preview-back-btn{background-color:#426c85!important;border-color:#426c85!important;color:#fff!important}.preview-dashboard-btn{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-outline-success:hover:not(:disabled),.btn.btn-outline-success:focus:not(:disabled),.btn.btn-outline-success:active:not(:disabled){background-color:transparent!important;border-color:#198754!important;color:#198754!important}.btn.btn-outline-secondary:not(.rounded-pill){background-color:#d4dae6!important;border-color:#d4dae6!important;color:#69707d!important}.btn.btn-outline-secondary:not(.rounded-pill):hover:not(:disabled),.btn.btn-outline-secondary:not(.rounded-pill):focus:not(:disabled),.btn.btn-outline-secondary:not(.rounded-pill):active:not(:disabled){background-color:#c2cbde!important;border-color:#c2cbde!important;color:#69707d!important}.btn.btn-danger{background-color:#b43026!important;border-color:#b43026!important;color:#fff!important}.btn.btn-danger:hover:not(:disabled),.btn.btn-danger:focus:not(:disabled),.btn.btn-danger:active:not(:disabled){background-color:#96271f!important;border-color:#96271f!important;color:#fff!important}.btn.btn-outline-danger.rounded-circle{border-color:#b43026!important;color:#b43026!important;border-radius:5px!important}.btn.btn-outline-danger.rounded-circle:hover:not(:disabled),.btn.btn-outline-danger.rounded-circle:focus:not(:disabled),.btn.btn-outline-danger.rounded-circle:active:not(:disabled){border-color:#96271f!important;color:#b43026!important}.btn.btn-link.text-secondary{background-color:#d4dae6!important;border-color:#d4dae6!important;color:#69707d!important;text-decoration:none!important;border-radius:5px;padding:.375rem .75rem;line-height:1.5}.btn.btn-link.text-secondary:hover:not(:disabled),.btn.btn-link.text-secondary:focus:not(:disabled){background-color:#c2cbde!important;color:#69707d!important}.btn.btn-link.text-danger{background-color:#b43026!important;border-color:#b43026!important;color:#fff!important;text-decoration:none!important;border-radius:5px;padding:.375rem .75rem;line-height:1.5}.btn.btn-link.text-danger:hover:not(:disabled),.btn.btn-link.text-danger:focus:not(:disabled){background-color:#96271f!important;color:#fff!important}.btn{border-radius:5px!important;box-shadow:none!important}.badge.bg-warning-subtle.text-warning{background-color:#fff3cd!important;color:#664d03!important;border-color:#ffe69c!important}.badge.bg-success-subtle.text-success{background-color:#4077ad!important;color:#fff!important;border-color:#4077ad!important}.badge.bg-primary-subtle.text-primary{background-color:#e0edf2!important;color:#4077ad!important;border-color:#e0edf2!important}.update-profile-card label,.update-profile-card .form-control,.update-profile-card .form-select{font-size:12px}.update-profile-card .form-control::placeholder{font-size:12px}.update-profile-card ::ng-deep im-address-verify-field .form-control{font-size:12px}.add-profession-card label,.add-profession-card .form-control{font-size:12px}.add-profession-card .form-control::placeholder{font-size:12px}.add-profession-card .btn{font-size:14px}.add-profession-card ::ng-deep .add-profession-select .ng-select-container,.add-profession-card ::ng-deep .add-profession-select .ng-placeholder,.add-profession-card ::ng-deep .add-profession-select .ng-value-label{font-size:12px}::ng-deep .add-profession-select .ng-option,::ng-deep .add-profession-select .ng-placeholder{font-size:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ModalModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i7.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: i7.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i7.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i7.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i7.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i7.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i7.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i7.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i7.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: NgSelectModule }, { kind: "component", type: i12.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "ngmodule", type: NgxStarsModule }, { kind: "ngmodule", type: BsDatepickerModule }, { kind: "directive", type: i13.BsDatepickerDirective, selector: "[bsDatepicker]", inputs: ["placement", "triggers", "outsideClick", "container", "outsideEsc", "isDisabled", "minDate", "maxDate", "ignoreMinMaxErrors", "minMode", "daysDisabled", "datesDisabled", "datesEnabled", "dateCustomClasses", "dateTooltipTexts", "isOpen", "bsValue", "bsConfig"], outputs: ["onShown", "onHidden", "bsValueChange"], exportAs: ["bsDatepicker"] }, { kind: "directive", type: i13.BsDatepickerInputDirective, selector: "input[bsDatepicker]" }, { kind: "ngmodule", type: TextMaskModule }, { kind: "ngmodule", type: AddressVerifyFieldModule }, { kind: "component", type: AddressVerifyFieldComponent, selector: "im-address-verify-field", inputs: ["placeholder", "options", "maxLength", "inputId", "name", "autocompleteAttr", "inputClass", "invalid", "inputStyle", "initialLat", "initialLng"], outputs: ["addressResolved", "manualEdit"] }] });
|
|
7404
7386
|
}
|
|
7405
7387
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: PreviewComponent, decorators: [{
|
|
7406
7388
|
type: Component,
|
|
@@ -7408,7 +7390,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
7408
7390
|
CommonModule, ModalModule, FormsModule, ReactiveFormsModule,
|
|
7409
7391
|
NgSelectModule, NgxStarsModule, BsDatepickerModule, TextMaskModule,
|
|
7410
7392
|
AddressVerifyFieldModule
|
|
7411
|
-
], template: "<div class=\"preview-page-header\" *ngIf=\"!isResume\">\r\n <div class=\"d-flex align-items-center gap-2 mb-1\">\r\n <h2 class=\"preview-title mb-0\">Review Extracted Information</h2>\r\n </div>\r\n <p class=\"preview-subtitle text-muted\">We\u2019ve automatically extracted details from your uploaded resume. Please review and confirm accuracy before proceeding.</p>\r\n</div>\r\n\r\n\r\n<div [ngClass]=\"isResume ? '' : 'container py-4'\" [class.provider-layout]=\"roleData?.role?.name === 'Provider'\">\r\n\r\n <!-- Provider initial setup: combined company + personal form (shown until both APIs succeed) -->\r\n <div class=\"section mb-5\" *ngIf=\"roleData?.role?.name === 'Provider' && !hasUserDetailData && !isResume\">\r\n <div class=\"d-flex align-items-center gap-2 mb-3 section-header-title\">\r\n <img src=\"/assets/images/icons/building.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Company & Personal Details</h5>\r\n <span class=\"badge border section-flag bg-warning-subtle text-warning\">Required to continue</span>\r\n </div>\r\n <div class=\"card shadow-sm border-0\">\r\n <div class=\"card-header bg-white fw-semibold\">Company Information</div>\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-3\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': (!tempCompanyDetails.companyName?.trim() && companyFormSubmitted) || companyNameError}\"\r\n [(ngModel)]=\"tempCompanyDetails.companyName\" name=\"setupCompanyName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyName?.trim() && companyFormSubmitted\">Company name is required</div>\r\n <div class=\"invalid-feedback\" *ngIf=\"companyNameError\">{{ companyNameError }}</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" maxlength=\"14\" inputmode=\"numeric\"\r\n (input)=\"phoneMask($event, 'company')\" (keypress)=\"allowOnlyNumbers($event)\"\r\n [ngClass]=\"{'is-invalid': companyFormSubmitted && (!tempCompanyDetails.companyPhoneNumber?.trim() || getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10)}\"\r\n [(ngModel)]=\"tempCompanyDetails.companyPhoneNumber\" name=\"setupCompanyPhone\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyPhoneNumber?.trim() && companyFormSubmitted\">Company phone is required</div>\r\n <div class=\"invalid-feedback\" *ngIf=\"tempCompanyDetails.companyPhoneNumber?.trim() && getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10 && companyFormSubmitted\">Company phone must be 10 digits</div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Company Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempCompanyDetails.address1\" name=\"setupCompanyAddress\"\r\n [options]=\"options\" inputClass=\"form-control form-control-sm\"\r\n [invalid]=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempCompanyDetails.latitude\" [initialLng]=\"tempCompanyDetails.longitude\"\r\n (addressResolved)=\"onCompanyAddressResolved($event)\"\r\n (manualEdit)=\"onCompanyAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\">Address is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.city?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.city\" name=\"setupCompanyCity\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.city?.trim() && companyFormSubmitted\">City is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.state?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.state\" name=\"setupCompanyState\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.state?.trim() && companyFormSubmitted\">State is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.zipcode?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.zipcode\" name=\"setupCompanyZip\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.zipcode?.trim() && companyFormSubmitted\">Zip code is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.country?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.country\" name=\"setupCompanyCountry\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.country?.trim() && companyFormSubmitted\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <input type=\"file\" accept=\".png,.jpg,.jpeg\" class=\"form-control form-control-sm\" (change)=\"uploadCompanyImage($event)\" name=\"setupCompanyLogo\" />\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"tempCompanyLogoUrl\">\r\n <label class=\"small text-muted d-block\">Logo Preview</label>\r\n <img [src]=\"tempCompanyLogoUrl\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-header bg-white fw-semibold border-top\">Personal Information</div>\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-3\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">First Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.firstName?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.firstName\" name=\"setupFirstName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.firstName?.trim() && companyFormSubmitted\">First name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Last Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.lastName?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.lastName\" name=\"setupLastName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.lastName?.trim() && companyFormSubmitted\">Last name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Email <span class=\"text-danger\">*</span></label>\r\n <input type=\"email\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.email?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.email\" name=\"setupEmail\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.email?.trim() && companyFormSubmitted\">Email is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Phone Number <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" maxlength=\"14\" inputmode=\"numeric\"\r\n (input)=\"phoneMask($event, 'profile')\" (keypress)=\"allowOnlyNumbers($event)\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.phone?.trim() && companyFormSubmitted}\"\r\n [ngModel]=\"tempProfile?.phone\" name=\"setupPhone\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.phone?.trim() && companyFormSubmitted\">Phone number is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Home Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempProfile.address\" name=\"setupAddress\" [options]=\"options\"\r\n inputClass=\"form-control form-control-sm\" [invalid]=\"!tempProfile?.address?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempProfile.latitude\" [initialLng]=\"tempProfile.longitude\"\r\n (addressResolved)=\"onUserAddressResolved($event)\"\r\n (manualEdit)=\"onUserAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.address?.trim() && companyFormSubmitted\">Home address is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.city?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.city\" name=\"setupUserCity\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.city?.trim() && companyFormSubmitted\">City is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.state?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.state\" name=\"setupUserState\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.state?.trim() && companyFormSubmitted\">State is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.zipCode?.trim() && companyFormSubmitted}\"\r\n [ngModel]=\"tempProfile?.zipCode\" (ngModelChange)=\"tempProfile.zipCode = sanitizeZipCode($event)\"\r\n name=\"setupUserZip\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.zipCode?.trim() && companyFormSubmitted\">Zip code is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.country?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.country\" name=\"setupUserCountry\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.country?.trim() && companyFormSubmitted\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [(ngModel)]=\"tempProfile.jobTitle\" name=\"setupJobTitle\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control form-control-sm\" [(ngModel)]=\"tempProfile.yearsOfExperience\"\r\n [ngClass]=\"{'is-invalid': !(tempProfile?.yearsOfExperience > 0) && companyFormSubmitted}\"\r\n name=\"setupYearsOfExp\" min=\"1\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!(tempProfile?.yearsOfExperience > 0) && companyFormSubmitted\">Years of experience is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Profile Picture</label>\r\n <input #setupHeadshotFile type=\"file\" accept=\".png,.jpg,.jpeg\" class=\"d-none\" (change)=\"uploadHeadshotImage($event)\" name=\"setupHeadshotFile\" />\r\n <div class=\"position-relative\">\r\n <input type=\"text\" class=\"form-control form-control-sm pe-5\" [value]=\"headshotFileName\" readonly\r\n placeholder=\"Upload Profile Picture\" (click)=\"setupHeadshotFile.click()\" />\r\n <img *ngIf=\"!isHeadshotLoading\" src=\"assets/images/icons/upload.svg\" alt=\"Upload\" class=\"upload-icon\" style=\"position:absolute;right:12px;top:50%;transform:translateY(-50%);cursor:pointer;width:18px;\" (click)=\"setupHeadshotFile.click()\" />\r\n <div *ngIf=\"isHeadshotLoading\" style=\"position:absolute;right:12px;top:50%;transform:translateY(-50%);\">\r\n <span class=\"spinner-border spinner-border-sm text-primary\"></span>\r\n </div>\r\n </div>\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"headshotPreviewUrl\">\r\n <label class=\"small text-muted d-block\">Preview</label>\r\n <img [src]=\"headshotPreviewUrl\" class=\"img-thumbnail rounded-circle\" style=\"width:64px;height:64px;object-fit:cover;\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-footer d-flex align-items-center justify-content-end gap-2\">\r\n <span *ngIf=\"providerSetupError\" class=\"small text-danger me-auto\">{{ providerSetupError }}</span>\r\n <button class=\"btn btn-success px-5 \"\r\n [disabled]=\"isSavingProviderSetup || !isProviderSetupFormComplete\"\r\n (click)=\"saveProviderSetup()\">\r\n <span *ngIf=\"isSavingProviderSetup\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingProviderSetup ? 'Saving...' : 'Save & Continue' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\" *ngIf=\"roleData?.role?.name !== 'Provider' || hasUserDetailData\">\r\n <div *ngIf=\"details() as data; else loading\">\r\n <div class=\"card profile-header-card shadow-sm border-0 rounded-3 overflow-hidden\" *ngIf=\"!isEditMode()\">\r\n <div class=\"card-body p-0\">\r\n <div class=\"preview-card-gradient\">\r\n <div class=\"d-flex justify-content-between align-items-start mb-4\">\r\n <div class=\"d-flex align-items-start gap-3\">\r\n <div class=\"profile-avatar-circle\" *ngIf=\"!headshotPreviewUrl\">\r\n {{ (data.firstName?.[0] || '') }}{{ (data.lastName?.[0] || '') }}\r\n </div>\r\n <img *ngIf=\"headshotPreviewUrl\" [src]=\"headshotPreviewUrl\"\r\n class=\"rounded-circle\" style=\"width:56px;height:56px;object-fit:cover;\" alt=\"Profile\" />\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h2 class=\"fw-bold mb-1\">{{ data.firstName }} {{ data.lastName }}</h2>\r\n <span *ngIf=\"basicSectionHasIssues()\" class=\"badge bg-warning-subtle text-warning border section-flag\">\r\n Missing info\r\n </span>\r\n <span class=\"badge border section-flag\"\r\n [ngClass]=\"basicDetailsSaved ? 'bg-success-subtle text-success' : 'bg-warning-subtle text-warning'\">\r\n {{ basicDetailsSaved ? 'Saved' : 'Not saved yet' }}\r\n </span>\r\n </div>\r\n <p class=\"text-muted\">{{ data.jobTitle }} \u2022 {{ data.yearsOfExperience }} Years Exp.</p>\r\n <div *ngIf=\"basicIssues().length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ basicIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <span class=\"badge bg-primary-subtle text-primary border p-2\">Email Verified</span>\r\n </div>\r\n\r\n </div>\r\n <div class=\"px-4 py-3\">\r\n <div class=\"row g-4\">\r\n <div class=\"col-12 border-bottom pb-2\">\r\n <h6 class=\"text-uppercase small fw-bold text-muted\">Summary</h6>\r\n <p class=\"text-secondary small mb-0\">{{ data.summary }}</p>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/envelope.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Email</span>\r\n <span class=\"field-value-sm d-block\">{{ data.email }}</span>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/telephone.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Phone</span>\r\n <span class=\"field-value-sm d-block\">{{ data.phone }}</span>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/geo-alt.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Location</span>\r\n <span class=\"field-value-sm d-block\">{{ data.address }}, {{ data.city }}, {{ data.state }}, {{ data.zipCode }}, {{ data.country }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer d-flex align-items-center justify-content-between\">\r\n <span *ngIf=\"!basicDetailsSaved\" class=\"small text-warning fw-semibold\">\r\n <img src=\"/assets/images/icons/exclamation-circle.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" /> Click \"Edit\" to review and save your basic info.\r\n </span>\r\n <span *ngIf=\"basicDetailsSaved\" class=\"small text-success fw-semibold\">\r\n <img src=\"/assets/images/icons/check-circle.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" /> Basic details saved.\r\n </span>\r\n <button class=\"btn btn-sm btn-primary px-4 ms-auto\" (click)=\"toggleEdit()\">Edit</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"isEditMode()\">\r\n <div class=\"card-header bg-white fw-bold\">Update Profile</div>\r\n <div class=\"card-body p-4\">\r\n <form class=\"row g-3\" #basicForm=\"ngForm\" novalidate>\r\n <div *ngIf=\"basicIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ basicIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">First Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.firstName\" name=\"fName\"\r\n placeholder=\"First Name\" required #fName=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"fName.invalid && (fName.dirty || fName.touched)\">First name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Last Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.lastName\" name=\"lName\"\r\n placeholder=\"Last Name\" required #lName=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"lName.invalid && (lName.dirty || lName.touched)\">Last name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Email <span class=\"text-danger\">*</span></label>\r\n <input type=\"email\" class=\"form-control\" [(ngModel)]=\"tempProfile.email\" name=\"email\" placeholder=\"Email\"\r\n required email #email=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"email.invalid && (email.dirty || email.touched)\">\r\n <span *ngIf=\"email.errors?.['required']\">Email is required</span>\r\n <span *ngIf=\"email.errors?.['email']\">Email format is invalid</span>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Phone Number <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"tempProfile.phone\" (input)=\"phoneMask($event, 'profile')\"\r\n name=\"phone\" placeholder=\"Phone (10 digits)\" (keypress)=\"allowOnlyNumbers($event)\"\r\n required pattern=\"^\\(\\d{3}\\) \\d{3}-\\d{4}$\" maxlength=\"14\" inputmode=\"numeric\" #phone=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"phone.invalid && (phone.dirty || phone.touched)\">\r\n <span *ngIf=\"phone.errors?.['required']\">Phone number is required</span>\r\n <span *ngIf=\"phone.errors?.['pattern']\">Phone number must be 10 digits</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\"></span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.jobTitle\" name=\"jobTitle\"\r\n placeholder=\"Job Title\" #jobTitle=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"jobTitle.invalid && (jobTitle.dirty || jobTitle.touched)\">Job\r\n title is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [ngClass]=\"{'is-invalid': !(tempProfile?.yearsOfExperience > 0)}\"\r\n [(ngModel)]=\"tempProfile.yearsOfExperience\"\r\n name=\"yearsOfExperience\" placeholder=\"Years of Experience\" required min=\"1\"\r\n #yearsOfExperience=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!(tempProfile?.yearsOfExperience > 0)\">\r\n Years of experience is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Home Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempProfile.address\" name=\"address\" [options]=\"options\"\r\n placeholder=\"Home Address\" required #address=\"ngModel\"\r\n [invalid]=\"address.invalid && (address.dirty || address.touched)\"\r\n [initialLat]=\"tempProfile.latitude\" [initialLng]=\"tempProfile.longitude\"\r\n (addressResolved)=\"onUserAddressResolved($event)\"\r\n (manualEdit)=\"onUserAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"address.invalid && (address.dirty || address.touched)\">Home\r\n address is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.city\" name=\"city\" placeholder=\"City\"\r\n required #city=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"city.invalid && (city.dirty || city.touched)\">City is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.state\" name=\"state\" placeholder=\"State\"\r\n required #state=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"state.invalid && (state.dirty || state.touched)\">State is\r\n required</div>\r\n </div>\r\n\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"tempProfile.zipCode\"\r\n (ngModelChange)=\"tempProfile.zipCode = sanitizeZipCode($event)\" name=\"zipCode\" placeholder=\"Zip Code\"\r\n required pattern=\"^\\d{1,6}$\" maxlength=\"6\" inputmode=\"numeric\" #zipCode=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"zipCode.invalid && (zipCode.dirty || zipCode.touched)\">Zip code\r\n is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"zipCode.errors?.['pattern'] && (zipCode.dirty || zipCode.touched)\">\r\n Zip code must be up to 6 digits\r\n </div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.country\" name=\"country\"\r\n placeholder=\"Country\" required #country=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"country.invalid && (country.dirty || country.touched)\">Country\r\n is required</div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Summary</label>\r\n <textarea class=\"form-control\" rows=\"3\" [(ngModel)]=\"tempProfile.summary\" name=\"sum\"\r\n placeholder=\"Summary\"></textarea>\r\n </div>\r\n\r\n\r\n </form>\r\n </div>\r\n <div class=\"card-footer text-end gap-2 d-flex justify-content-end\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancel()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingBasic || !isBasicFormValid\" (click)=\"save()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Saving...' : 'Save Changes' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5 provider-company-first\" *ngIf=\"roleData?.role?.name === 'Provider' && hasUserDetailData && !isResume\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/building.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Company Details</h5>\r\n <span *ngIf=\"companyDetailsSaved\"\r\n class=\"badge border section-flag bg-success-subtle text-success\">\r\n Saved\r\n </span>\r\n <span *ngIf=\"!companyDetailsSaved\"\r\n class=\"badge border section-flag bg-warning-subtle text-warning\">\r\n Not saved yet\r\n </span>\r\n </div>\r\n <button class=\"btn btn-sm btn-primary px-4\" (click)=\"toggleCompanyEdit()\">Edit</button>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"!isCompanyEditMode()\">\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-4\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name</label>\r\n <span class=\"fw-bold small\">{{ companyDetails()?.companyName}}</span>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone</label>\r\n <span class=\"fw-bold small\">{{ companyDetails()?.companyPhoneNumber}}</span>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Company Address</label>\r\n <span class=\"small\">{{ companyDetails()?.address1}}, {{ companyDetails()?.city}}, {{ companyDetails()?.state}}, {{ companyDetails()?.zipcode}}, {{ companyDetails()?.country}}</span>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"companyLogoUrl()\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <img [src]=\"companyLogoUrl()\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"isCompanyEditMode()\">\r\n <div class=\"card-header bg-white fw-bold\">Update Company Details</div>\r\n <div class=\"card-body p-4\">\r\n <form class=\"row g-3\" #companyForm=\"ngForm\" novalidate>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': (!tempCompanyDetails.companyName?.trim() && companyFormSubmitted) || companyNameError }\"\r\n [(ngModel)]=\"tempCompanyDetails.companyName\" name=\"companyName\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyName?.trim() && companyFormSubmitted\">\r\n Company name is required\r\n </div>\r\n <div class=\"invalid-feedback\" *ngIf=\"companyNameError\">\r\n {{ companyNameError }}\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone <span class=\"text-danger\">*</span></label>\r\n <input (input)=\"phoneMask($event, 'company')\" type=\"text\" maxlength=\"14\" (keypress)=\"allowOnlyNumbers($event)\" inputmode=\"numeric\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{ 'is-invalid': companyFormSubmitted && (!tempCompanyDetails.companyPhoneNumber?.trim() || getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10) }\"\r\n [(ngModel)]=\"tempCompanyDetails.companyPhoneNumber\" name=\"companyPhoneNumber\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyPhoneNumber?.trim() && companyFormSubmitted\">\r\n Company phone is required\r\n </div>\r\n <div class=\"invalid-feedback\" *ngIf=\"tempCompanyDetails.companyPhoneNumber?.trim() && getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10 && companyFormSubmitted\">\r\n Company phone must be 10 digits\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempCompanyDetails.address1\" name=\"address1\" [options]=\"options\"\r\n required [invalid]=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempCompanyDetails.latitude\" [initialLng]=\"tempCompanyDetails.longitude\"\r\n (addressResolved)=\"onCompanyAddressResolved($event)\"\r\n (manualEdit)=\"onCompanyAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\">\r\n Address is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.city?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.city\" name=\"city\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.city?.trim() && companyFormSubmitted\">\r\n City is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.state?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.state\" name=\"state\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.state?.trim() && companyFormSubmitted\">\r\n State is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.zipcode?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.zipcode\" name=\"zipcode\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.zipcode?.trim() && companyFormSubmitted\">\r\n Zip code is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.country?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.country\" name=\"country\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.country?.trim() && companyFormSubmitted\">\r\n Country is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <input #uploadCompanyFile type=\"file\" accept=\".png,.jpg,.jpeg\" (change)=\"uploadCompanyImage($event)\" class=\"form-control\" />\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"tempCompanyLogoUrl\">\r\n <label class=\"small text-muted d-block\">Logo Preview</label>\r\n <img [src]=\"tempCompanyLogoUrl\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"card-footer text-end gap-2 d-flex justify-content-end\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelCompanyEdit()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingCompany\" \r\n (click)=\"saveCompanyDetails()\">\r\n <span *ngIf=\"isSavingCompany\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCompany ? 'Saving...' : 'Save Changes' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div [class.section-locked]=\"roleData?.role?.name === 'Provider' && !hasUserDetailData\">\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/briefcase-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Profession</h5>\r\n <span *ngIf=\"selectedProfessionCount > 0\" class=\"badge border section-flag bg-warning-subtle text-warning\">\r\n {{ selectedProfessionCount }} selected\r\n </span>\r\n </div>\r\n <button type=\"button\" class=\"btn btn-sm btn-primary px-4\"\r\n [disabled]=\"selectedProfessionCount === 0 || isSavingProfessionsTable\"\r\n (click)=\"submitProfessions()\">\r\n <span *ngIf=\"isSavingProfessionsTable\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingProfessionsTable ? 'Saving...' : professionSubmitLabel }}\r\n </button>\r\n </div>\r\n\r\n <div class=\"mb-3\">\r\n <input type=\"text\" class=\"form-control profession-search-input\" placeholder=\"Search or Add Profession\"\r\n [(ngModel)]=\"professionSearchQry\" name=\"professionSearchQry\"\r\n (keydown.enter)=\"createManualProfessionRow()\" />\r\n </div>\r\n\r\n <div class=\"table-responsive bg-white border rounded shadow-sm\">\r\n <table class=\"table align-middle mb-0 profession-table\">\r\n <thead>\r\n <tr>\r\n <th style=\"width: 36px;\"></th>\r\n <th>Profession Name</th>\r\n <th>Group</th>\r\n <th>Type</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <ng-container *ngFor=\"let p of filteredProfessionTypes\">\r\n <tr [class.profession-row-selected]=\"getProfessionSelection(p.id).selected\">\r\n <td style=\"text-align: center;\">\r\n <input type=\"checkbox\" class=\"form-check-input\" [checked]=\"getProfessionSelection(p.id).selected\"\r\n (change)=\"onProfessionRowCheck(p, $event)\" />\r\n </td>\r\n <td>\r\n {{ p.professionName }}\r\n <span *ngIf=\"isProfessionSaved(p.id)\" class=\"badge border bg-success-subtle text-success ms-1\">Saved</span>\r\n </td>\r\n <td>\r\n <ng-container *ngIf=\"p.isManual; else groupText\">\r\n <select class=\"form-select form-select-sm profession-inline-select\" [ngModel]=\"p.professionGroup\"\r\n (ngModelChange)=\"setManualProfessionGroup(p, $event)\" [name]=\"'manualGroup-' + p.id\">\r\n <option [ngValue]=\"null\" disabled>Select group</option>\r\n <option *ngFor=\"let g of professionGroupOptions\" [ngValue]=\"g\">{{ g }}</option>\r\n </select>\r\n </ng-container>\r\n <ng-template #groupText>{{ p.professionGroup || '\u2013' }}</ng-template>\r\n </td>\r\n <td>\r\n <ng-container *ngIf=\"p.isManual; else typeText\">\r\n <select class=\"form-select form-select-sm profession-inline-select\" [ngModel]=\"p.residentialCommercial\"\r\n (ngModelChange)=\"setManualProfessionType(p, $event)\" [name]=\"'manualType-' + p.id\">\r\n <option [ngValue]=\"null\" disabled>Select type</option>\r\n <option *ngFor=\"let t of professionTypeOptions\" [ngValue]=\"t\">{{ t }}</option>\r\n </select>\r\n </ng-container>\r\n <ng-template #typeText>{{ p.residentialCommercial || '\u2013' }}</ng-template>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"getProfessionSelection(p.id).selected\" class=\"profession-row-selected\">\r\n <td></td>\r\n <td colspan=\"3\">\r\n <div *ngIf=\"p.isManual && !isManualRowReady(p.id)\" class=\"small text-danger mb-2\">\r\n Select a Group and Type above to enable saving this profession.\r\n </div>\r\n <div class=\"d-flex flex-wrap align-items-start gap-4 py-2\">\r\n <div class=\"flex-shrink-0\" style=\"white-space: nowrap;\">\r\n <label class=\"small text-muted d-block mb-1\">Self Ability Rating</label>\r\n <span *ngFor=\"let s of [1,2,3,4,5]\" class=\"fs-5\" style=\"cursor: pointer;\"\r\n (click)=\"setProfessionRowStars(p, s)\"\r\n [class.text-warning]=\"(getProfessionSelection(p.id).starRating || 0) / 2 >= s\"\r\n [class.text-muted]=\"(getProfessionSelection(p.id).starRating || 0) / 2 < s\">\u2605</span>\r\n </div>\r\n <div class=\"flex-shrink-0\" style=\"white-space: nowrap;\">\r\n <label class=\"small text-muted d-block mb-1\">Experience</label>\r\n <div class=\"d-flex align-items-center gap-1\">\r\n <input type=\"number\" class=\"form-control form-control-sm\" style=\"width: 70px;\" min=\"0\" max=\"30\"\r\n [(ngModel)]=\"getProfessionSelection(p.id).year\" [name]=\"'profYear-' + p.id\" />\r\n <span class=\"small text-muted\">Yrs</span>\r\n </div>\r\n </div>\r\n <div class=\"d-flex flex-column align-items-center flex-shrink-0\" style=\"min-width: 80px; white-space: nowrap;\">\r\n <label class=\"small text-muted d-block mb-1\">Visibility</label>\r\n <input type=\"checkbox\" class=\"profession-visibility-checkbox\" [(ngModel)]=\"getProfessionSelection(p.id).profileVisibility\"\r\n [name]=\"'profVis-' + p.id\" />\r\n </div>\r\n <div class=\"flex-grow-1\" style=\"min-width: 200px;\">\r\n <label class=\"small text-muted d-block mb-1\">Notes</label>\r\n <textarea rows=\"3\" class=\"form-control form-control-sm profession-notes-input\" [(ngModel)]=\"getProfessionSelection(p.id).notes\"\r\n [name]=\"'profNotes-' + p.id\" placeholder=\"Notes\"></textarea>\r\n </div>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-container>\r\n <tr *ngIf=\"hasNoProfessionMatches\">\r\n <td colspan=\"4\" class=\"text-center small py-3\">\r\n <span class=\"text-muted\">No professions found for \"{{ professionSearchQry?.trim() }}\".</span>\r\n <button type=\"button\" class=\"btn btn-sm btn-primary ms-2\" (click)=\"createManualProfessionRow()\">\r\n Add \"{{ professionSearchQry?.trim() }}\"\r\n </button>\r\n </td>\r\n </tr>\r\n <tr *ngIf=\"!professionSearchQry?.trim() && filteredProfessionTypes.length === 0\">\r\n <td colspan=\"4\" class=\"text-center text-muted small py-3\">No professions found.</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/briefcase-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Work Experience</h5>\r\n <span *ngIf=\"experience().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"workSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ workSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"experience().length === 0 || !workSectionHasUnsavedItems() || isSavingWork || isAddingJob() || editingJobIndex() !== null\"\r\n (click)=\"confirmAllWork()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add work experience\" (click)=\"addJob()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"experience().length === 0 && !isAddingJob()\" class=\"empty-state-wrap mb-3\" role=\"button\"\r\n (click)=\"addJob()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/briefcase.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No work experience added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3\">\r\n <div *ngIf=\"isAddingJob() && tempJob()\" class=\"list-group-item p-0 border-0\">\r\n <div class=\"form-panel mb-2\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.jobTitle\"\r\n (ngModelChange)=\"patchTempJob({ jobTitle: $event })\" name=\"newJobTitle\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.company\"\r\n (ngModelChange)=\"patchTempJob({ company: $event })\" name=\"newCompany\" />\r\n </div>\r\n <div class=\"align-items-end col-md-12 d-flex justify-content-end pe-3\">\r\n <div class=\"form-check\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"tempJob()?.isCurrent\"\r\n (ngModelChange)=\"setTempJobIsCurrent($event)\" name=\"newIsCurrent\" id=\"newIsCurrent\" />\r\n <label class=\"form-check-label\" for=\"newIsCurrent\">Current</label>\r\n </div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.country\"\r\n (ngModelChange)=\"patchTempJob({ country: $event })\" name=\"newCountry\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.state\"\r\n (ngModelChange)=\"patchTempJob({ state: $event })\" name=\"newState\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.city\"\r\n (ngModelChange)=\"patchTempJob({ city: $event })\" name=\"newCity\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempJob()?.startDate)\"\r\n (bsValueChange)=\"setTempJobMonth('startDate', $event)\" name=\"newStartDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.startDate)\">Start date is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [disabled]=\"tempJob()?.isCurrent\"\r\n [ngModel]=\"monthInputToDate(tempJob()?.endDate)\" (bsValueChange)=\"setTempJobMonth('endDate', $event)\"\r\n name=\"newEndDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!tempJob()?.isCurrent && isBlank(tempJob()?.endDate)\">End date is\r\n required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"!tempJob()?.isCurrent && isMonthRangeInvalid(tempJob()?.startDate, tempJob()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Responsibilities (one per line)</label>\r\n <textarea rows=\"4\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"(tempJob()?.responsibilities || []).join('\\n')\"\r\n (ngModelChange)=\"updateTempResponsibilities($event)\" name=\"newResponsibilities\"></textarea>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onWorkExperienceFileSelected($event)\" name=\"newWorkAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempJob()?.fileName\">\r\n <span>{{ tempJob()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempJob())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n <div class=\"d-flex justify-content-end gap-2 mt-3\">\r\n <button class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditJob(); $event.stopPropagation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingWork\"\r\n (click)=\"saveEditJob(); $event.stopPropagation()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Uploading...' : workActionLabel(editingJobIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <div *ngFor=\"let job of experience(); let i = index\" class=\"list-group-item p-0 border-0 mb-2\">\r\n\r\n <div class=\"work-accent-item p-3 rounded-3 bg-white border\">\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n <div class=\"d-flex align-items-center cursor-pointer flex-grow-1\" (click)=\"toggleJob(i)\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h6 class=\"mb-0 fw-bold item-title-sm\">{{ job.jobTitle }}</h6>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedWorkItem(i) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedWorkItem(i) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ job.company || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ formatMonthYear(job.startDate) }} - {{ job.isCurrent ? 'Present' :\r\n formatMonthYear(job.endDate) }}</span>\r\n <span class=\"item-meta-line\">{{ job.city }}<span *ngIf=\"job.city && job.state\">, </span>{{ job.state }}<ng-container *ngIf=\"!job.city && !job.state\">\u2014</ng-container></span>\r\n <div *ngIf=\"editingJobIndex() !== i && (workIssuesByIndex()[i] || []).length > 0\"\r\n class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (workIssuesByIndex()[i] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex align-items-center gap-2\">\r\n\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\" (click)=\"startEditJob(i)\"\r\n title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteJob(i);\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n \r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <div class=\"mt-3 p-3 rounded small\" *ngIf=\"expandedIndex() === i\">\r\n <ng-container *ngIf=\"editingJobIndex() !== i; else editJobForm\">\r\n <ul class=\"mb-0\">\r\n <li *ngFor=\"let res of job.responsibilities\">{{ res }}</li>\r\n </ul>\r\n </ng-container>\r\n\r\n <ng-template #editJobForm>\r\n <div *ngIf=\"(workIssuesByIndex()[i] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (workIssuesByIndex()[i] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.jobTitle\"\r\n (ngModelChange)=\"patchTempJob({ jobTitle: $event })\" name=\"jobTitle{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.jobTitle)\">Job title is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.company\"\r\n (ngModelChange)=\"patchTempJob({ company: $event })\" name=\"company{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.company)\">Company name is required</div>\r\n </div>\r\n\r\n <div class=\"align-items-end col-md-12 d-flex justify-content-end pe-3\">\r\n <div class=\"form-check\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"tempJob()?.isCurrent\"\r\n (ngModelChange)=\"setTempJobIsCurrent($event)\" name=\"isCurrent{{ i }}\" id=\"isCurrent{{ i }}\" />\r\n <label class=\"form-check-label\" for=\"isCurrent{{ i }}\">Current</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.country\"\r\n (ngModelChange)=\"patchTempJob({ country: $event })\" name=\"country{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.state\"\r\n (ngModelChange)=\"patchTempJob({ state: $event })\" name=\"state{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.city\"\r\n (ngModelChange)=\"patchTempJob({ city: $event })\" name=\"city{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.city)\">City is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempJob()?.startDate)\"\r\n (bsValueChange)=\"setTempJobMonth('startDate', $event)\" name=\"startDate{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.startDate)\">Start date is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [disabled]=\"tempJob()?.isCurrent\"\r\n [ngModel]=\"monthInputToDate(tempJob()?.endDate)\" (bsValueChange)=\"setTempJobMonth('endDate', $event)\"\r\n name=\"endDate{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!tempJob()?.isCurrent && isBlank(tempJob()?.endDate)\">\r\n End date is required\r\n </div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"!tempJob()?.isCurrent && isMonthRangeInvalid(tempJob()?.startDate, tempJob()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Responsibilities (one per line)</label>\r\n <textarea rows=\"4\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"(tempJob()?.responsibilities || []).join('\\n')\"\r\n (ngModelChange)=\"updateTempResponsibilities($event)\" name=\"responsibilities{{ i }}\"></textarea>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onWorkExperienceFileSelected($event)\" name=\"workAttachment{{ i }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempJob()?.fileName\">\r\n <span>{{ tempJob()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempJob())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n </ng-template>\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-3\" *ngIf=\"editingJobIndex() === i\">\r\n <button class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditJob(); $event.stopPropagation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4 \" [disabled]=\"isSavingWork\"\r\n (click)=\"saveEditJob(); $event.stopPropagation()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Uploading...' : workActionLabel(editingJobIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/patch-check-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Certifications</h5>\r\n <span *ngIf=\"certs().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"certificationSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ certificationSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"certs().length === 0 || !certificationSectionHasUnsavedItems() || isSavingCertification || isAddingCertification() || editingCertificationIndex() !== null\"\r\n (click)=\"confirmAllCertifications()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add certification\" (click)=\"addCertification()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"certs().length === 0 && !isAddingCertification() && editingCertificationIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addCertification()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/patch-check.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No certifications added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3 border\">\r\n <div *ngIf=\"isAddingCertification() && tempCertification()\" class=\"list-group-item py-3 px-3\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"tempCertification()?.professionId\" (change)=\"onCertificationProfessionChange($event)\"\r\n name=\"newCertProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('certificate')\">+</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.name\"\r\n (ngModelChange)=\"patchTempCertification({ name: $event })\" name=\"newCertName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempCertification()?.name)\">Certificate name is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.issuingOrganization || ''\"\r\n (ngModelChange)=\"patchTempCertification({ issuingOrganization: $event || null })\" name=\"newCertOrg\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.state || ''\"\r\n (ngModelChange)=\"patchTempCertification({ state: $event || null })\" name=\"newCertState\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certification Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.credentialId || ''\"\r\n (ngModelChange)=\"patchTempCertification({ credentialId: $event || null })\" name=\"newCertCredentialId\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('issueDate', $event)\" name=\"newCertIssueDate\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('expiryDate', $event)\" name=\"newCertExpiryDate\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempCertification()?.issueDate || null, tempCertification()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onCertificationFileSelected($event)\" name=\"newCertAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempCertification()?.fileName\">\r\n <span>{{ tempCertification()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempCertification())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditCertification()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\"\r\n [disabled]=\"isSavingCertification\"\r\n (click)=\"saveCertificationEditor()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Uploading...' : certificationActionLabel(editingCertificationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let cert of certs(); let ci = index\" class=\"list-group-item py-3 cert-accent-item\">\r\n <ng-container *ngIf=\"editingCertificationIndex() !== ci; else editCert\">\r\n <div class=\"d-flex justify-content-between align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <div class=\"fw-semibold item-title-sm\">{{ cert.name }}</div>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedCertificationItem(ci) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedCertificationItem(ci) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ cert.issuingOrganization || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.credentialId || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.issueDate ? formatMonthYear(cert.issueDate) : '\u2014' }} - {{ cert.expiryDate ? formatMonthYear(cert.expiryDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.state || '\u2014' }}</span>\r\n <div *ngIf=\"(certIssuesByIndex()[ci] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (certIssuesByIndex()[ci] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditCertification(ci)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\"\r\n (click)=\"deleteCertification(ci)\" title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #editCert>\r\n <div *ngIf=\"(certIssuesByIndex()[ci] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (certIssuesByIndex()[ci] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"tempCertification()?.professionId\" (change)=\"onCertificationProfessionChange($event)\"\r\n name=\"certProfessionType{{ ci }}\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('certificate')\">+</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.name\"\r\n (ngModelChange)=\"patchTempCertification({ name: $event })\" name=\"certName{{ ci }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempCertification()?.name)\">Certificate name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.issuingOrganization || ''\"\r\n (ngModelChange)=\"patchTempCertification({ issuingOrganization: $event || null })\"\r\n name=\"certOrg{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.state || ''\"\r\n (ngModelChange)=\"patchTempCertification({ state: $event || null })\" name=\"certState{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certification Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.credentialId || ''\"\r\n (ngModelChange)=\"patchTempCertification({ credentialId: $event || null })\"\r\n name=\"certCredentialId{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('issueDate', $event)\" name=\"certIssue{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('expiryDate', $event)\" name=\"certExpiry{{ ci }}\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempCertification()?.issueDate || null, tempCertification()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onCertificationFileSelected($event)\" name=\"certAttachment{{ ci }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempCertification()?.fileName\">\r\n <span>{{ tempCertification()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempCertification())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditCertification()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingCertification\"\r\n (click)=\"saveCertificationEditor()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Uploading...' : certificationActionLabel(editingCertificationIndex()) }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/card-checklist-warning.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Licenses</h5>\r\n <span *ngIf=\"licenses().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"licenseSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ licenseSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"licenses().length === 0 || !licenseSectionHasUnsavedItems() || isSavingLicense || isAddingLicense() || editingLicenseIndex() !== null\"\r\n (click)=\"confirmAllLicenses()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add license\" (click)=\"addLicense()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"licenses().length === 0 && !isAddingLicense() && editingLicenseIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addLicense()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/card-checklist.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No licenses added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3 border\">\r\n <div *ngIf=\"isAddingLicense() && tempLicense()\" class=\"list-group-item py-3 px-3\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.name\"\r\n (ngModelChange)=\"patchTempLicense({ name: $event })\" name=\"newLicName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempLicense()?.name)\">License name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.issuingAuthority || ''\"\r\n (ngModelChange)=\"patchTempLicense({ issuingAuthority: $event || null })\" name=\"newLicAuthority\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.licenseNumber || ''\"\r\n (ngModelChange)=\"patchTempLicense({ licenseNumber: $event || null })\" name=\"newLicNumber\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.state || ''\"\r\n (ngModelChange)=\"patchTempLicense({ state: $event || null })\" name=\"newLicState\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('issueDate', $event)\" name=\"newLicIssueDate\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('expiryDate', $event)\" name=\"newLicExpiryDate\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempLicense()?.issueDate || null, tempLicense()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">License File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onLicenseFileSelected($event)\" name=\"newLicenseAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempLicense()?.fileName\">\r\n <span>{{ tempLicense()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempLicense())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelEditLicense()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingLicense\"\r\n (click)=\"saveLicenseEditor()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Uploading...' : licenseActionLabel(editingLicenseIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let lic of licenses(); let li = index\" class=\"list-group-item py-3 lic-accent-item\">\r\n <ng-container *ngIf=\"editingLicenseIndex() !== li; else editLic\">\r\n <div class=\"d-flex justify-content-between align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <div class=\"fw-semibold item-title-sm\">{{ lic.name }}</div>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedLicenseItem(li) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedLicenseItem(li) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ lic.issuingAuthority || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.licenseNumber || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.issueDate ? formatMonthYear(lic.issueDate) : '\u2014' }} - {{ lic.expiryDate ? formatMonthYear(lic.expiryDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.state || '\u2014' }}</span>\r\n <div *ngIf=\"(licenseIssuesByIndex()[li] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (licenseIssuesByIndex()[li] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditLicense(li)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteLicense(li)\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #editLic>\r\n <div *ngIf=\"(licenseIssuesByIndex()[li] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (licenseIssuesByIndex()[li] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.name\"\r\n (ngModelChange)=\"patchTempLicense({ name: $event })\" name=\"licName{{ li }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempLicense()?.name)\">License name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.issuingAuthority || ''\"\r\n (ngModelChange)=\"patchTempLicense({ issuingAuthority: $event || null })\" name=\"licAuthority{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.licenseNumber || ''\"\r\n (ngModelChange)=\"patchTempLicense({ licenseNumber: $event || null })\" name=\"licNumber{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.state || ''\"\r\n (ngModelChange)=\"patchTempLicense({ state: $event || null })\" name=\"licState{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('issueDate', $event)\" name=\"licIssue{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('expiryDate', $event)\" name=\"licExpiry{{ li }}\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempLicense()?.issueDate || null, tempLicense()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">License File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onLicenseFileSelected($event)\" name=\"licenseAttachment{{ li }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempLicense()?.fileName\">\r\n <span>{{ tempLicense()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempLicense())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditLicense()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingLicense\"\r\n (click)=\"saveLicenseEditor()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Uploading...' : licenseActionLabel(editingLicenseIndex()) }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/tools.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Tools</h5>\r\n <span *ngIf=\"tools().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"toolsSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ toolsSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"tools().length === 0 || !toolsSectionHasUnsavedItems() || isSavingTool || isToolEditorOpen()\" (click)=\"confirmAllTools()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add tool\" (click)=\"addTool()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex flex-wrap gap-2 p-3 bg-white border rounded shadow-sm\">\r\n <div *ngFor=\"let tool of tools(); let ti = index\" class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\"\r\n class=\"btn btn-light border res-flex d-inline-flex align-items-center gap-2 px-3 py-2\"\r\n (click)=\"openToolEditor(ti)\" title=\"Edit\">\r\n <span class=\"fw-normal item-name-text\">{{ tool }}</span>\r\n <span class=\"badge border ms-1\"\r\n [ngClass]=\"hasUnsavedToolItem(ti) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedToolItem(ti) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n <span *ngIf=\"(toolIssuesByIndex()[ti] || []).length > 0\"\r\n class=\"badge bg-warning-subtle text-warning border ms-1\">\r\n Missing info\r\n </span>\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-danger rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Delete tool\" (click)=\"deleteTool(ti)\">\r\n <span class=\"fw-bold\">\u00D7</span>\r\n </button>\r\n </div>\r\n\r\n <span *ngIf=\"tools().length === 0\" class=\"text-muted small\">No tools added.</span>\r\n </div>\r\n\r\n <div *ngIf=\"isToolEditorOpen()\" class=\"position-fixed top-0 start-0 w-100 h-100\"\r\n style=\"background: rgba(0,0,0,0.35); z-index: 9999999;\" (click)=\"closeToolEditor()\">\r\n <div class=\"container h-100 d-flex align-items-start justify-content-center pt-4\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"card shadow border-0 w-100\" style=\"max-width: 900px;\">\r\n <div class=\"card-header bg-white d-flex align-items-center gap-3\">\r\n <button type=\"button\" class=\"btn btn-link p-0 text-decoration-none\" (click)=\"closeToolEditor()\">\r\n <img src=\"/assets/images/icons/arrow-left-blue.svg\" width=\"20\" height=\"20\" alt=\"\" />\r\n </button>\r\n <div class=\"fw-bold\">{{ isAddingTool() ? 'Add Tool' : ('Edit ' + (toolForm()?.name || '') + ' Tool') }}\r\n </div>\r\n </div>\r\n <div class=\"card-body p-4\">\r\n <div *ngIf=\"toolFormIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ toolFormIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"row g-3\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"toolForm()?.professionId\" (change)=\"onToolProfessionChange($event)\"\r\n name=\"toolProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('tool')\">+</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Tool Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"toolForm()?.name\"\r\n (ngModelChange)=\"patchToolForm({ name: $event })\" name=\"toolName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(toolForm()?.name)\">Tool name is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span\r\n class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempToolStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"(toolForm()?.stars || 0) >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ (toolForm()?.stars || 0) >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ toolForm()?.stars || 0 }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"(toolForm()?.stars || 0) <= 0\">Star rating is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [ngModel]=\"toolForm()?.year\"\r\n (ngModelChange)=\"patchToolForm({ year: $event === '' ? null : +$event })\" name=\"toolYear\" min=\"1\"\r\n max=\"30\" placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"toolForm()?.year === null || toolForm()?.year === undefined\">\r\n Years of experience is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4 text-center\">\r\n <label class=\"small text-muted d-block\">Profile Visibility</label>\r\n <div class=\"form-checks form-switch mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"toolForm()?.profileVisibility\"\r\n (ngModelChange)=\"patchToolForm({ profileVisibility: $event })\" name=\"toolVisible\" id=\"toolVisible\"\r\n style=\"width: 55px;height: 25px;margin-left: -57px;\" />\r\n <label class=\"form-check-label ps-2 pt-1\" for=\"toolVisible\">Visible</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Comment</label>\r\n <textarea rows=\"4\" class=\"form-control\" [ngModel]=\"toolForm()?.notes\"\r\n (ngModelChange)=\"patchToolForm({ notes: $event })\" name=\"toolNotes\"\r\n placeholder=\"Enter additional details (optional)\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer bg-white d-flex justify-content-end gap-2\">\r\n <button *ngIf=\"!isAddingTool() && editingToolIndex() !== null\" type=\"button\"\r\n class=\"btn btn-link text-danger me-auto\" (click)=\"deleteTool(editingToolIndex()!)\">\r\n Delete\r\n </button>\r\n <button type=\"button\" class=\"btn btn-link text-secondary\" (click)=\"closeToolEditor()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary px-4\" [disabled]=\"isSavingTool\" (click)=\"saveToolEditor()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Saving...' : toolActionLabel(editingToolIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row g-4 mb-5\">\r\n <div class=\"col-md-12\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/stars.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Skills</h5>\r\n <span *ngIf=\"skills().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"skillsSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ skillsSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"skills().length === 0 || !skillsSectionHasUnsavedItems() || isSavingSkill || isSkillEditorOpen()\" (click)=\"confirmAllSkills()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add skill\" (click)=\"addSkill()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex flex-wrap gap-2 p-3 bg-white border rounded shadow-sm\">\r\n <div *ngFor=\"let skill of skills(); let si = index\" class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\"\r\n class=\"btn btn-light border res-flex d-inline-flex align-items-center gap-2 px-3 py-2\"\r\n (click)=\"openSkillEditor(si)\" title=\"Edit\">\r\n <span class=\"fw-normal item-name-text\">{{ skill }}</span>\r\n <span class=\"badge border ms-1\"\r\n [ngClass]=\"hasUnsavedSkillItem(si) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedSkillItem(si) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n <span *ngIf=\"(skillIssuesByIndex()[si] || []).length > 0\"\r\n class=\"badge bg-warning-subtle text-warning border ms-1\">\r\n Missing info\r\n </span>\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-danger rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Delete skill\"\r\n (click)=\"deleteSkill(si); $event.stopPropagation()\">\r\n <span class=\"fw-bold\">\u00D7</span>\r\n </button>\r\n </div>\r\n\r\n <span *ngIf=\"skills().length === 0\" class=\"text-muted small\">No skills added.</span>\r\n </div>\r\n <div *ngIf=\"isSkillEditorOpen()\" class=\"position-fixed top-0 start-0 w-100 h-100\"\r\n style=\"background: rgba(0,0,0,0.35); z-index: 9999999;\" (click)=\"closeSkillEditor()\">\r\n <div class=\"container h-100 d-flex align-items-start justify-content-center pt-4\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"card shadow border-0 w-100\" style=\"max-width: 900px;\">\r\n <div class=\"card-header bg-white d-flex align-items-center gap-3\">\r\n <button type=\"button\" class=\"btn btn-link p-0 text-decoration-none\" (click)=\"closeSkillEditor()\">\r\n <img src=\"/assets/images/icons/arrow-left-blue.svg\" width=\"20\" height=\"20\" alt=\"\" />\r\n </button>\r\n <div class=\"fw-bold\">{{ isAddingSkill() ? 'Add Skill' : ('Edit ' + (skillForm()?.name || '') + ' Skill')\r\n }}</div>\r\n </div>\r\n <div class=\"card-body p-4\">\r\n <div *ngIf=\"skillFormIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ skillFormIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"row g-3\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"skillForm()?.professionId\" (change)=\"onSkillProfessionChange($event)\"\r\n name=\"skillProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('skill')\">+</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Skills Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"skillForm()?.name\"\r\n (ngModelChange)=\"patchSkillForm({ name: $event })\" name=\"skillName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(skillForm()?.name)\">Skillset name is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span\r\n class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempSkillStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"(skillForm()?.stars || 0) >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ (skillForm()?.stars || 0) >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ skillForm()?.stars || 0 }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"(skillForm()?.stars || 0) <= 0\">Star rating is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [ngModel]=\"skillForm()?.year\"\r\n (ngModelChange)=\"patchSkillForm({ year: $event === '' ? null : +$event })\" name=\"skillYear\" min=\"1\"\r\n max=\"30\" placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"skillForm()?.year === null || skillForm()?.year === undefined\">Years of experience is\r\n required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4 text-center\">\r\n <label class=\"small text-muted d-block\">Profile Visibility</label>\r\n <div class=\"form-checks form-switch mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"skillForm()?.profileVisibility\"\r\n (ngModelChange)=\"patchSkillForm({ profileVisibility: $event })\" name=\"skillVisible\"\r\n id=\"skillVisible\" style=\"width: 55px;height: 25px;margin-left: -57px;\" />\r\n <label class=\"form-check-label ps-2 pt-1\" for=\"skillVisible\">Visible</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Comment</label>\r\n <textarea rows=\"4\" class=\"form-control\" [ngModel]=\"skillForm()?.notes\"\r\n (ngModelChange)=\"patchSkillForm({ notes: $event })\" name=\"skillNotes\"\r\n placeholder=\"Enter additional details (optional)\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer bg-white d-flex justify-content-end gap-2\">\r\n <button *ngIf=\"!isAddingSkill() && editingSkillIndex() !== null\" type=\"button\"\r\n class=\"btn btn-link text-danger me-auto\" (click)=\"deleteSkill(editingSkillIndex()!)\">\r\n Delete\r\n </button>\r\n <button type=\"button\" class=\"btn btn-link text-secondary\" (click)=\"closeSkillEditor()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary px-4\" [disabled]=\"isSavingSkill\" (click)=\"saveSkillEditor()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Saving...' : skillActionLabel(editingSkillIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row g-4 mb-5\">\r\n <div class=\"col-md-12\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/mortarboard-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Education</h5>\r\n <span *ngIf=\"educationList().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"educationSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ educationSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"educationList().length === 0 || !educationSectionHasUnsavedItems() || isSavingEducation || isAddingEducation() || editingEducationIndex() !== null\"\r\n (click)=\"confirmAllEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add education\" (click)=\"addEducation()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"educationList().length === 0 && !isAddingEducation() && editingEducationIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addEducation()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/mortarboard.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No education added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div *ngIf=\"isAddingEducation() && tempEducation()\" class=\"mb-2\">\r\n <div class=\"form-panel\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.degree\"\r\n (ngModelChange)=\"patchTempEducation({ degree: $event })\" name=\"newEduDegree\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degree)\">Degree / Course name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Institution <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.institution\"\r\n (ngModelChange)=\"patchTempEducation({ institution: $event })\" name=\"newEduInstitution\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree / Course Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"ng-select-sm\" [items]=\"educationDegreeTypeOptions\" [clearable]=\"false\"\r\n placeholder=\"Select degree / course type\" [ngModel]=\"tempEducation()?.degreeType\"\r\n (ngModelChange)=\"patchTempEducation({ degreeType: $event })\" name=\"newEduDegreeType\">\r\n </ng-select>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degreeType)\">Degree / Course type is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.country\"\r\n (ngModelChange)=\"patchTempEducation({ country: $event })\" name=\"newEduCountry\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.state\"\r\n (ngModelChange)=\"patchTempEducation({ state: $event })\" name=\"newEduState\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.city\"\r\n (ngModelChange)=\"patchTempEducation({ city: $event })\" name=\"newEduCity\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.startDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('startDate', $event)\" name=\"newEduStartDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.startDate)\">Start date is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.endDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('endDate', $event)\" name=\"newEduEndDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.endDate)\">End date is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempEducation()?.startDate, tempEducation()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Education File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onEducationFileSelected($event)\" name=\"newEducationAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempEducation()?.fileName\">\r\n <span>{{ tempEducation()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempEducation())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditEducation()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingEducation\"\r\n (click)=\"saveEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Uploading...' : educationActionLabel(editingEducationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let edu of educationList(); let ei = index\" class=\"edu-accent-item p-3 bg-white border rounded-3 shadow-sm mb-2\">\r\n <div class=\"d-flex justify-content-between align-items-start\">\r\n <div class=\"d-flex align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h6 class=\"fw-bold mb-0 item-title-sm\">{{ edu.degree }}</h6>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedEducationItem(ei) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedEducationItem(ei) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ edu.institution || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.degreeType || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.startDate ? formatMonthYear(edu.startDate) : '\u2014' }} - {{ edu.endDate ? formatMonthYear(edu.endDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.city }}<span *ngIf=\"edu.city && edu.state\">, </span>{{ edu.state }}<ng-container *ngIf=\"!edu.city && !edu.state\">\u2014</ng-container></span>\r\n <div *ngIf=\"(educationIssuesByIndex()[ei] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (educationIssuesByIndex()[ei] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\" *ngIf=\"editingEducationIndex() !== ei\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditEducation(ei)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteEducation(ei)\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"editingEducationIndex() === ei\" class=\"mt-3\">\r\n <div *ngIf=\"(educationIssuesByIndex()[ei] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (educationIssuesByIndex()[ei] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.degree\"\r\n (ngModelChange)=\"patchTempEducation({ degree: $event })\" name=\"eduDegree{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degree)\">Degree / Course name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Institution <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.institution\"\r\n (ngModelChange)=\"patchTempEducation({ institution: $event })\" name=\"eduInstitution{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.institution)\">Institution name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree / Course Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"ng-select-sm\" [items]=\"educationDegreeTypeOptions\" [clearable]=\"false\"\r\n placeholder=\"Select degree / course type\" [ngModel]=\"tempEducation()?.degreeType\"\r\n (ngModelChange)=\"patchTempEducation({ degreeType: $event })\" name=\"eduDegreeType{{ ei }}\">\r\n </ng-select>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degreeType)\">Degree / Course type is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.country\"\r\n (ngModelChange)=\"patchTempEducation({ country: $event })\" name=\"eduCountry{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.state\"\r\n (ngModelChange)=\"patchTempEducation({ state: $event })\" name=\"eduState{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.city\"\r\n (ngModelChange)=\"patchTempEducation({ city: $event })\" name=\"eduCity{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.startDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('startDate', $event)\" name=\"eduStartDate{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.startDate)\">Start date is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.endDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('endDate', $event)\" name=\"eduEndDate{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.endDate)\">End date is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempEducation()?.startDate, tempEducation()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Education File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onEducationFileSelected($event)\" name=\"educationAttachment{{ ei }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempEducation()?.fileName\">\r\n <span>{{ tempEducation()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempEducation())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelEditEducation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingEducation\" (click)=\"saveEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Uploading...' : educationActionLabel(editingEducationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n </div>\r\n <div class=\"d-flex gap-3 justify-content-center mt-5 pt-2\" *ngIf=\"!isResume\">\r\n <button class=\"btn btn-outline-secondary preview-back-btn px-5 h-auto\" style=\"border-radius: 5px !important;\" (click)=\"onBackClick()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"me-1\" style=\"vertical-align:-0.1em\">\r\n <path d=\"M11 3 5 8l6 5\" />\r\n </svg> Back\r\n </button>\r\n <button class=\"btn btn-primary preview-dashboard-btn px-5 h-auto\" style=\"border-radius: 5px !important;\" [disabled]=\"!canConfirmAndContinue() || isSavingBasic\"\r\n (click)=\"onGoToDashboardClick()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Saving...' : 'Go to Dashboard' }}\r\n <img *ngIf=\"!isSavingBasic\" src=\"/assets/images/icons/arrow-right-white.svg\" width=\"14\" height=\"14\" class=\"ms-1\" style=\"vertical-align:-0.1em\" alt=\"\" />\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<ng-template #loading>\r\n <div class=\"text-center p-5\">\r\n <div class=\"spinner-border text-primary\"></div>\r\n <p class=\"text-muted mt-2\">Loading data...</p>\r\n </div>\r\n</ng-template>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showCustomProfessionForm\" style=\"z-index: 9999999;\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 420px;\">\r\n <h4 class=\"mb-1\">Add New Profession</h4>\r\n <p class=\"text-muted small mb-4\">This profession isn't in the list yet. Add it here so you can link it to this\r\n {{ customProfessionContext }}.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"customProfessionName\" name=\"customProfessionName\"\r\n placeholder=\"Enter profession name\" />\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Group <span class=\"text-danger\">*</span></label>\r\n <select class=\"form-select\" [(ngModel)]=\"customProfessionGroup\" name=\"customProfessionGroup\">\r\n <option [ngValue]=\"null\" disabled>Select group</option>\r\n <option *ngFor=\"let g of professionGroupOptions\" [ngValue]=\"g\">{{ g }}</option>\r\n </select>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Type <span class=\"text-danger\">*</span></label>\r\n <select class=\"form-select\" [(ngModel)]=\"customProfessionType\" name=\"customProfessionType\">\r\n <option [ngValue]=\"null\" disabled>Select type</option>\r\n <option *ngFor=\"let t of professionTypeOptions\" [ngValue]=\"t\">{{ t }}</option>\r\n </select>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelCustomProfessionForm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\" [disabled]=\"!canSaveCustomProfession || isSavingCustomProfession\"\r\n (click)=\"saveCustomProfession()\">\r\n <span *ngIf=\"isSavingCustomProfession\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCustomProfession ? 'Saving...' : 'Add Profession' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBulkSkillConfirm\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 480px;\">\r\n <h4 class=\"mb-1\">Set Rating for All Skills</h4>\r\n <p class=\"text-muted small mb-4\">Enter a star rating and years of experience (and optionally a profession type) to apply to all skills that are missing these values.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Type</label>\r\n <ng-select [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"bulkSkillProfessionId\" (change)=\"onBulkSkillProfessionChange($event)\"\r\n name=\"bulkSkillProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"bulkSkillStars = s\">\r\n <span [class]=\"bulkSkillStars >= s ? 'text-warning fs-4' : 'text-muted fs-4'\">\r\n {{ bulkSkillStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ bulkSkillStars }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkSkillStars <= 0\">Star rating is required</div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"bulkSkillYear\" min=\"1\" max=\"30\"\r\n placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkSkillYear === null || bulkSkillYear === undefined\">Years of experience is required</div>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelBulkSkillConfirm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\"\r\n [disabled]=\"isSavingSkill || bulkSkillStars <= 0 || bulkSkillYear === null\"\r\n (click)=\"applyBulkSkillConfirm()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Saving...' : 'Apply to All & Save' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBulkToolConfirm\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 480px;\">\r\n <h4 class=\"mb-1\">Set Rating for All Tools</h4>\r\n <p class=\"text-muted small mb-4\">Enter a star rating and years of experience (and optionally a profession type) to apply to all tools that are missing these values.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Type</label>\r\n <ng-select [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"bulkToolProfessionId\" (change)=\"onBulkToolProfessionChange($event)\"\r\n name=\"bulkToolProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"bulkToolStars = s\">\r\n <span [class]=\"bulkToolStars >= s ? 'text-warning fs-4' : 'text-muted fs-4'\">\r\n {{ bulkToolStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ bulkToolStars }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkToolStars <= 0\">Star rating is required</div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"bulkToolYear\" min=\"1\" max=\"30\"\r\n placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkToolYear === null || bulkToolYear === undefined\">Years of experience is required</div>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelBulkToolConfirm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\"\r\n [disabled]=\"isSavingTool || bulkToolStars <= 0 || bulkToolYear === null\"\r\n (click)=\"applyBulkToolConfirm()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Saving...' : 'Apply to All & Save' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBackConfirmPopup\">\r\n <div class=\"confirm-modal-card\">\r\n <h4 class=\"mb-2\">Leave this page?</h4>\r\n <p class=\"text-muted mb-4\">If you go back, only saved data will be retained.</p>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"stayOnPreview()\">Stay</button>\r\n <button type=\"button\" class=\"btn btn-danger h-auto\" (click)=\"proceedBack()\">Proceed Back</button>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showDashboardConfirmPopup\">\r\n <div class=\"confirm-modal-card\">\r\n <h4 class=\"mb-2\">Finish Setup and Continue</h4>\r\n <p class=\"text-muted mb-4\">Save your information and go to your dashboard</p>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" [disabled]=\"isSavingBasic\"\r\n (click)=\"cancelDashboardRedirect()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\" [disabled]=\"isSavingBasic\" (click)=\"goToDashboard()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Proceeding...' : 'Proceed' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{color:#69707d}.res-flex:hover,.res-flex:focus,.res-flex:active{transform:none!important;box-shadow:none!important}::ng-deep .form-check-input{margin-left:unset!important}.profession-search-input{font-size:11px}.profession-search-input::placeholder{font-size:11px}.profession-row-selected{background-color:#f2f4fa!important}.profession-row-selected>td{background-color:#f2f4fa!important}.profession-visibility-checkbox{all:revert;width:16px!important;height:16px!important;min-width:16px!important;max-width:16px!important;margin:7px 0 0!important;padding:0!important;position:static!important;float:none!important;vertical-align:middle!important;background-image:none!important;transform:none!important}.profession-table{font-size:12px;color:#69707d}.profession-table th{font-size:13px;font-weight:600;color:#69707d;text-transform:uppercase;letter-spacing:.03em}.profession-table td{font-size:12px;color:#69707d;font-weight:600;padding-left:0}.profession-table label.small{font-size:12px;color:#69707d}.profession-inline-select{min-width:160px;font-size:12px}.profession-notes-input{min-height:76px;resize:vertical}.container{max-width:900px;margin:30px auto;font-family:Arial,sans-serif;color:#69707d}.preview-page-header{max-width:900px;margin:50px auto 10px;padding:0 12px}.preview-title{font-size:18px;font-weight:700;color:#69707d;margin:0}.preview-subtitle{margin-top:7px;font-size:14px;color:#69707d}.preview-card-gradient h2,.section h5.fw-bold{font-size:18px}.section{margin-bottom:25px}.section-title{font-weight:600;display:block;margin-bottom:8px}.section-title .sub{font-weight:400;color:#777;font-size:13px}.dropdown-box{border:1px solid #ddd;border-radius:8px;padding:12px 15px;display:flex;justify-content:space-between;align-items:center}.icons{display:flex;gap:10px}.icon{cursor:pointer;font-size:14px;color:#777}.card{border:1px solid #ddd;border-radius:5px;padding:20px;background:#fff}.category{border-bottom:1px solid #eee;padding:15px 0}.category:last-child{border-bottom:none}.category-header{display:flex;justify-content:space-between;font-weight:600;margin-bottom:10px}.tags{display:flex;flex-wrap:wrap;gap:10px}.tag{background:#f2f4f7;padding:6px 12px;border-radius:6px;font-size:13px}.footer{text-align:center;margin-top:15px;color:#777;cursor:pointer}.actions{display:flex;justify-content:space-between;margin:50px 0 27px}.text-secondary{white-space:pre-line;font-size:12px;color:#69707d}.extra-small{font-size:.8rem}.card{transition:box-shadow .2s ease}.achievement-section .badge{font-size:.75rem;white-space:normal;text-align:left}.skill-tag .badge{font-weight:500;font-size:.9rem;transition:all .2s ease;cursor:default}.skill-tag .badge:hover{transform:translateY(-2px)}.skill-tag .btn-close{opacity:.5}.skill-tag .btn-close:hover{opacity:1}.bg-light.text-dark.border{background-color:#f8f9fa!important;border-color:#dee2e6!important}.card{transition:all .3s cubic-bezier(.25,.8,.25,1)}.card:hover .bg-light{background-color:#e8f5e9!important}.position-fixed .card:hover{transform:none!important}code{background-color:#f8f9fa;padding:2px 6px;border-radius:4px}.list-group-item{transition:background-color .2s ease-in-out}.list-group-item:hover{background-color:#fcfcfc}.border-dashed{border-style:dashed!important}.tool-card{transition:all .2s ease-in-out;border-radius:12px}.tool-card:hover{transform:translateY(-5px);border-color:var(--bs-primary)!important}.tool-card:hover .icon-box{background-color:var(--bs-primary-subtle)!important}.tool-card .icon-box{width:60px;height:60px;transition:background-color .2s ease}.border-dashed{border:2px dashed #dee2e6!important}.border-dashed:hover{border-color:var(--bs-primary)!important;background-color:#fff!important}.popup{position:fixed;top:20%;right:20px;width:320px;max-width:calc(100vw - 32px);background:#fff;border-radius:10px;padding:16px}.status-row{display:flex;justify-content:space-between;margin:10px 0}.success{color:#2e7d32;font-weight:700}.error{color:#d32f2f}.pending{color:#f9a825}.section-flag{font-weight:600}button.btn.btn-sm.btn-outline-primary{background-color:#4077ad;border-color:#4077ad;color:#fff;border-radius:5px!important}button.btn.btn-sm.btn-outline-primary:hover{background-color:#356895;border-color:#356895;color:#fff}button.btn.btn-sm.btn-outline-danger{border:1px solid #dc3545;color:#dc3545;border-radius:5px!important}button.btn.btn-sm.btn-outline-primary.rounded-circle{background-color:#4077ad;border-color:#4077ad;color:#fff;border-radius:5px!important}button.action-icon-btn{min-width:22px;width:22px;height:22px;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:5px!important;background:transparent!important;border:none!important;line-height:1}button.action-icon-btn.btn-outline-primary{color:#4077ad!important;border-color:#4077ad!important}button.action-icon-btn.btn-outline-danger{color:#dc3545!important}.action-icon-image{width:20px;height:20px;object-fit:contain;display:inline-block}.action-icon-image.edit-icon{filter:brightness(0) saturate(100%) invert(41%) sepia(39%) saturate(774%) hue-rotate(170deg) brightness(91%) contrast(89%)}.action-icon-image.delete-icon{filter:brightness(0) saturate(100%) invert(24%) sepia(79%) saturate(4008%) hue-rotate(344deg) brightness(91%) contrast(90%)}.modal-overlay{position:fixed;inset:0;background:#11182773;display:flex;align-items:center;justify-content:center;z-index:2500;padding:20px}.status-modal-card{width:min(760px,96vw);max-height:85vh;overflow:auto;background:#fff;border-radius:16px;border:1px solid #e5e7eb}.status-modal-header{padding:20px 24px 14px;border-bottom:1px solid #eef2f7}.status-modal-body{padding:12px 20px 20px}.status-modal-footer{padding:12px 20px 20px;border-top:1px solid #eef2f7;display:flex;justify-content:end;align-items:center;gap:12px}.status-modal-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px 10px;border-bottom:1px solid #f1f5f9}.status-modal-row:last-child{border-bottom:0}.status-modal-name{font-size:14px;font-weight:600;color:#69707d}.status-modal-state{font-size:.92rem;font-weight:600}.status-modal-state.pending{color:#a16207}.status-modal-state.success{color:#166534}.status-modal-state.partial{color:#b45309}.status-modal-state.error{color:#b91c1c}.confirm-modal-card{width:min(520px,96vw);background:#fff;border-radius:5px;border:1px solid #e5e7eb;padding:24px}.year-experience-select{max-height:150px}@media screen and (max-width: 768px){.res-flex{flex-wrap:wrap!important;justify-content:center!important}.res-flex .fw-normal{width:100%;text-align:center;font-size:14px!important}.d-flex.flex-wrap.gap-2.p-3.bg-white.border.rounded.shadow-sm{justify-content:center}.preview-page-header{margin:20px auto 8px;padding:0 4px}.container{padding-left:4px;padding-right:4px}.preview-title{font-size:16px}.preview-subtitle{font-size:14px}.actions{margin:24px 0 16px}.section-header-title{flex-wrap:wrap}.section-header-title>.section-flag{flex-basis:53%}.section-header-row{align-items:flex-start}.preview-card-gradient{padding:14px 14px 12px}.preview-card-gradient h2{font-size:18px}.popup{width:calc(100vw - 40px);right:16px;top:12%}.card{padding:0}.card-body.p-4,.px-4.py-3{padding:12px!important}.row.g-4,.row.g-3{--bs-gutter-x: .75rem}.d-flex.gap-4{gap:10px!important}.preview-card-gradient>.d-flex.justify-content-between.align-items-start{flex-wrap:wrap;row-gap:8px}.preview-card-gradient>.d-flex.justify-content-between.align-items-start>.badge.bg-primary-subtle{margin-left:auto}}@media screen and (max-width: 575px){.preview-title{font-size:16px}.preview-subtitle{font-size:14px}.section>.d-flex{flex-wrap:wrap;row-gap:8px}.section>.d-flex>.d-flex:last-child{width:100%;justify-content:flex-end}}::ng-deep .bs-datepicker-head{background-color:#4077ad!important}::ng-deep .bs-datepicker-body table td span.selected,.bs-datepicker-body table td.selected span{background-color:#4077ad!important}.profile-avatar-circle{width:58px;height:58px;border-radius:5px;background:#4077ad;display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:700;color:#fff;letter-spacing:1px;flex-shrink:0}.section-header-icon{font-size:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;opacity:.9;filter:invert(47%) sepia(8%) saturate(483%) hue-rotate(176deg) brightness(91%) contrast(87%)}.section-header-title h5.fw-bold{color:#69707d}.text-muted{color:#69707d!important}h6.text-uppercase.fw-bold.text-muted{font-size:14px;color:#69707d!important}.work-accent-item{border-radius:5px!important;transition:background-color .18s ease,box-shadow .18s ease}.work-accent-item:hover{background-color:#f5f8ff!important;box-shadow:0 4px 14px #4077ad17!important}.edu-accent-item{border-radius:5px!important;transition:background-color .18s ease,box-shadow .18s ease}.edu-accent-item:hover{background-color:#f8f8ff!important;box-shadow:0 4px 14px #6366f117!important}.cert-accent-item{border-radius:5px!important;transition:background-color .18s ease}.cert-accent-item:hover{background-color:#f0fdf4!important}.lic-accent-item{border-radius:5px!important;transition:background-color .18s ease}.lic-accent-item:hover{background-color:#fffbeb!important}.field-label-sm{font-size:14px;font-weight:700;letter-spacing:.08em;color:#69707d;margin-bottom:3px;display:block}.item-name-text{color:#69707d}.field-value-sm{font-weight:600;font-size:12px;color:#69707d}.item-title-sm{font-size:14px;color:#69707d!important}.item-meta-line{display:block;font-size:12px;color:#69707d;margin-top:3px}.empty-state-wrap{text-align:center;padding:32px 20px;background:#fafbfc;border:1.5px dashed #d1d5db;border-radius:5px;cursor:pointer;transition:background-color .18s ease,border-color .18s ease}.empty-state-wrap .empty-icon{font-size:2rem;color:#d1d5db;margin-bottom:8px}.empty-state-wrap p{color:#9ca3af;margin:0;font-size:14px}.empty-state-wrap:hover{background:#f0f6ff;border-color:#4077ad}.form-panel{background:#fff;border:1px solid #e2e8f0;border-radius:5px;padding:20px}.form-panel .form-control,.form-panel .form-select{border-color:#d1d5db;border-radius:8px;font-size:12px}.form-panel .form-control:focus,.form-panel .form-select:focus{border-color:#4077ad;box-shadow:0 0 0 3px #4077ad1f}.section-header-bar{display:flex;align-items:center;justify-content:space-between;padding:10px 0 14px;border-bottom:2px solid #f1f5f9;margin-bottom:16px}.preview-card-gradient{background:linear-gradient(135deg,#fff,#eff6ff);border-bottom:1px solid #e2e8f0;padding:20px 24px 16px;border-radius:5px 5px 0 0}.profile-header-card{border:1px solid #e2e8f0!important}.item-icon-circle{width:40px;height:40px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;color:#fff;flex-shrink:0}.item-avatar--work{background:linear-gradient(135deg,#4077ad,#2d5a8a)}.item-avatar--edu{background:linear-gradient(135deg,#4077ad,#4338ca)}.provider-layout{display:flex;flex-direction:column}.provider-company-first{order:-1}.section-locked{pointer-events:none;opacity:.45;filter:blur(1.5px);-webkit-user-select:none;user-select:none}.btn.btn-primary{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-primary:hover:not(:disabled),.btn.btn-primary:focus:not(:disabled),.btn.btn-primary:active:not(:disabled){background-color:#356895!important;border-color:#356895!important;color:#fff!important}.btn.btn-success,.btn.btn-outline-success{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-success:hover:not(:disabled),.btn.btn-success:focus:not(:disabled),.btn.btn-success:active:not(:disabled),.btn.btn-outline-success:hover:not(:disabled),.btn.btn-outline-success:focus:not(:disabled),.btn.btn-outline-success:active:not(:disabled){background-color:#336843!important;border-color:#336843!important;color:#fff!important}.btn.btn-outline-secondary.rounded-pill{background-color:#69707d!important;border-color:#69707d!important;color:#fff!important;border-radius:5px!important}.btn.btn-outline-secondary.rounded-pill:hover:not(:disabled),.btn.btn-outline-secondary.rounded-pill:focus:not(:disabled),.btn.btn-outline-secondary.rounded-pill:active:not(:disabled){background-color:#565c66!important;border-color:#565c66!important;color:#fff!important}.preview-back-btn{background-color:#426c85!important;border-color:#426c85!important;color:#fff!important}.preview-dashboard-btn{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-outline-success:hover:not(:disabled),.btn.btn-outline-success:focus:not(:disabled),.btn.btn-outline-success:active:not(:disabled){background-color:transparent!important;border-color:#198754!important;color:#198754!important}.btn.btn-outline-secondary:not(.rounded-pill){background-color:#d4dae6!important;border-color:#d4dae6!important;color:#69707d!important}.btn.btn-outline-secondary:not(.rounded-pill):hover:not(:disabled),.btn.btn-outline-secondary:not(.rounded-pill):focus:not(:disabled),.btn.btn-outline-secondary:not(.rounded-pill):active:not(:disabled){background-color:#c2cbde!important;border-color:#c2cbde!important;color:#69707d!important}.btn.btn-danger{background-color:#b43026!important;border-color:#b43026!important;color:#fff!important}.btn.btn-danger:hover:not(:disabled),.btn.btn-danger:focus:not(:disabled),.btn.btn-danger:active:not(:disabled){background-color:#96271f!important;border-color:#96271f!important;color:#fff!important}.btn.btn-outline-danger.rounded-circle{border-color:#b43026!important;color:#b43026!important;border-radius:5px!important}.btn.btn-outline-danger.rounded-circle:hover:not(:disabled),.btn.btn-outline-danger.rounded-circle:focus:not(:disabled),.btn.btn-outline-danger.rounded-circle:active:not(:disabled){border-color:#96271f!important;color:#b43026!important}.btn.btn-link.text-secondary{background-color:#d4dae6!important;border-color:#d4dae6!important;color:#69707d!important;text-decoration:none!important;border-radius:5px}.btn.btn-link.text-secondary:hover:not(:disabled),.btn.btn-link.text-secondary:focus:not(:disabled){background-color:#c2cbde!important;color:#69707d!important}.btn.btn-link.text-danger{background-color:#b43026!important;border-color:#b43026!important;color:#fff!important;text-decoration:none!important;border-radius:5px}.btn.btn-link.text-danger:hover:not(:disabled),.btn.btn-link.text-danger:focus:not(:disabled){background-color:#96271f!important;color:#fff!important}.btn{border-radius:5px!important;box-shadow:none!important}.badge.bg-warning-subtle.text-warning{background-color:#fff3cd!important;color:#664d03!important;border-color:#ffe69c!important}.badge.bg-success-subtle.text-success{background-color:#4077ad!important;color:#fff!important;border-color:#4077ad!important}.badge.bg-primary-subtle.text-primary{background-color:#e0edf2!important;color:#4077ad!important;border-color:#e0edf2!important}\n"] }]
|
|
7393
|
+
], template: "<div class=\"preview-page-header\" *ngIf=\"!isResume\">\r\n <div class=\"d-flex align-items-center gap-2 mb-1\">\r\n <h2 class=\"preview-title mb-0\">Review Extracted Information</h2>\r\n </div>\r\n <p class=\"preview-subtitle text-muted\">We\u2019ve automatically extracted details from your uploaded resume. Please review and confirm accuracy before proceeding.</p>\r\n</div>\r\n\r\n\r\n<div [ngClass]=\"isResume ? '' : 'container py-4'\" [class.provider-layout]=\"roleData?.role?.name === 'Provider'\">\r\n\r\n <!-- Provider initial setup: combined company + personal form (shown until both APIs succeed) -->\r\n <div class=\"section mb-5\" *ngIf=\"roleData?.role?.name === 'Provider' && !hasUserDetailData && !isResume\">\r\n <div class=\"d-flex align-items-center gap-2 mb-3 section-header-title\">\r\n <img src=\"/assets/images/icons/building.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Company & Personal Details</h5>\r\n <span class=\"badge border section-flag bg-warning-subtle text-warning\">Required to continue</span>\r\n </div>\r\n <div class=\"card shadow-sm border-0\">\r\n <div class=\"card-header bg-white fw-semibold\">Company Information</div>\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-3\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': (!tempCompanyDetails.companyName?.trim() && companyFormSubmitted) || companyNameError}\"\r\n [(ngModel)]=\"tempCompanyDetails.companyName\" name=\"setupCompanyName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyName?.trim() && companyFormSubmitted\">Company name is required</div>\r\n <div class=\"invalid-feedback\" *ngIf=\"companyNameError\">{{ companyNameError }}</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" maxlength=\"14\" inputmode=\"numeric\"\r\n (input)=\"phoneMask($event, 'company')\" (keypress)=\"allowOnlyNumbers($event)\"\r\n [ngClass]=\"{'is-invalid': companyFormSubmitted && (!tempCompanyDetails.companyPhoneNumber?.trim() || getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10)}\"\r\n [(ngModel)]=\"tempCompanyDetails.companyPhoneNumber\" name=\"setupCompanyPhone\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyPhoneNumber?.trim() && companyFormSubmitted\">Company phone is required</div>\r\n <div class=\"invalid-feedback\" *ngIf=\"tempCompanyDetails.companyPhoneNumber?.trim() && getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10 && companyFormSubmitted\">Company phone must be 10 digits</div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Company Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempCompanyDetails.address1\" name=\"setupCompanyAddress\"\r\n [options]=\"options\" inputClass=\"form-control form-control-sm\"\r\n [invalid]=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempCompanyDetails.latitude\" [initialLng]=\"tempCompanyDetails.longitude\"\r\n (addressResolved)=\"onCompanyAddressResolved($event)\"\r\n (manualEdit)=\"onCompanyAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\">Address is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.city?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.city\" name=\"setupCompanyCity\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.city?.trim() && companyFormSubmitted\">City is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.state?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.state\" name=\"setupCompanyState\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.state?.trim() && companyFormSubmitted\">State is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.zipcode?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.zipcode\" name=\"setupCompanyZip\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.zipcode?.trim() && companyFormSubmitted\">Zip code is required</div>\r\n </div>\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempCompanyDetails.country?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempCompanyDetails.country\" name=\"setupCompanyCountry\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.country?.trim() && companyFormSubmitted\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <input type=\"file\" accept=\".png,.jpg,.jpeg\" class=\"form-control form-control-sm\" (change)=\"uploadCompanyImage($event)\" name=\"setupCompanyLogo\" />\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"tempCompanyLogoUrl\">\r\n <label class=\"small text-muted d-block\">Logo Preview</label>\r\n <img [src]=\"tempCompanyLogoUrl\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-header bg-white fw-semibold border-top\">Personal Information</div>\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-3\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">First Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.firstName?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.firstName\" name=\"setupFirstName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.firstName?.trim() && companyFormSubmitted\">First name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Last Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.lastName?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.lastName\" name=\"setupLastName\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.lastName?.trim() && companyFormSubmitted\">Last name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Email <span class=\"text-danger\">*</span></label>\r\n <input type=\"email\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.email?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.email\" name=\"setupEmail\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.email?.trim() && companyFormSubmitted\">Email is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Phone Number <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" maxlength=\"14\" inputmode=\"numeric\"\r\n (input)=\"phoneMask($event, 'profile')\" (keypress)=\"allowOnlyNumbers($event)\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.phone?.trim() && companyFormSubmitted}\"\r\n [ngModel]=\"tempProfile?.phone\" name=\"setupPhone\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.phone?.trim() && companyFormSubmitted\">Phone number is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Home Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempProfile.address\" name=\"setupAddress\" [options]=\"options\"\r\n inputClass=\"form-control form-control-sm\" [invalid]=\"!tempProfile?.address?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempProfile.latitude\" [initialLng]=\"tempProfile.longitude\"\r\n (addressResolved)=\"onUserAddressResolved($event)\"\r\n (manualEdit)=\"onUserAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.address?.trim() && companyFormSubmitted\">Home address is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.city?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.city\" name=\"setupUserCity\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.city?.trim() && companyFormSubmitted\">City is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.state?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.state\" name=\"setupUserState\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.state?.trim() && companyFormSubmitted\">State is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.zipCode?.trim() && companyFormSubmitted}\"\r\n [ngModel]=\"tempProfile?.zipCode\" (ngModelChange)=\"tempProfile.zipCode = sanitizeZipCode($event)\"\r\n name=\"setupUserZip\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.zipCode?.trim() && companyFormSubmitted\">Zip code is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{'is-invalid': !tempProfile?.country?.trim() && companyFormSubmitted}\"\r\n [(ngModel)]=\"tempProfile.country\" name=\"setupUserCountry\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempProfile?.country?.trim() && companyFormSubmitted\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [(ngModel)]=\"tempProfile.jobTitle\" name=\"setupJobTitle\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control form-control-sm\" [(ngModel)]=\"tempProfile.yearsOfExperience\"\r\n [ngClass]=\"{'is-invalid': !(tempProfile?.yearsOfExperience > 0) && companyFormSubmitted}\"\r\n name=\"setupYearsOfExp\" min=\"1\" />\r\n <div class=\"invalid-feedback\" *ngIf=\"!(tempProfile?.yearsOfExperience > 0) && companyFormSubmitted\">Years of experience is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Profile Picture</label>\r\n <input #setupHeadshotFile type=\"file\" accept=\".png,.jpg,.jpeg\" class=\"d-none\" (change)=\"uploadHeadshotImage($event)\" name=\"setupHeadshotFile\" />\r\n <div class=\"position-relative\">\r\n <input type=\"text\" class=\"form-control form-control-sm pe-5\" [value]=\"headshotFileName\" readonly\r\n placeholder=\"Upload Profile Picture\" (click)=\"setupHeadshotFile.click()\" />\r\n <img *ngIf=\"!isHeadshotLoading\" src=\"assets/images/icons/upload.svg\" alt=\"Upload\" class=\"upload-icon\" style=\"position:absolute;right:12px;top:50%;transform:translateY(-50%);cursor:pointer;width:18px;\" (click)=\"setupHeadshotFile.click()\" />\r\n <div *ngIf=\"isHeadshotLoading\" style=\"position:absolute;right:12px;top:50%;transform:translateY(-50%);\">\r\n <span class=\"spinner-border spinner-border-sm text-primary\"></span>\r\n </div>\r\n </div>\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"headshotPreviewUrl\">\r\n <label class=\"small text-muted d-block\">Preview</label>\r\n <img [src]=\"headshotPreviewUrl\" class=\"img-thumbnail rounded-circle\" style=\"width:64px;height:64px;object-fit:cover;\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card-footer d-flex align-items-center justify-content-end gap-2\">\r\n <span *ngIf=\"providerSetupError\" class=\"small text-danger me-auto\">{{ providerSetupError }}</span>\r\n <button class=\"btn btn-success px-5 \"\r\n [disabled]=\"isSavingProviderSetup || !isProviderSetupFormComplete\"\r\n (click)=\"saveProviderSetup()\">\r\n <span *ngIf=\"isSavingProviderSetup\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingProviderSetup ? 'Saving...' : 'Save & Continue' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\" *ngIf=\"roleData?.role?.name !== 'Provider' || hasUserDetailData\">\r\n <div *ngIf=\"details() as data; else loading\">\r\n <div class=\"card profile-header-card shadow-sm border-0 rounded-3 overflow-hidden\" *ngIf=\"!isEditMode()\">\r\n <div class=\"card-body p-0\">\r\n <div class=\"preview-card-gradient\">\r\n <div class=\"d-flex justify-content-between align-items-start mb-4\">\r\n <div class=\"d-flex align-items-start gap-3\">\r\n <div class=\"profile-avatar-circle\" *ngIf=\"!headshotPreviewUrl\">\r\n {{ (data.firstName?.[0] || '') }}{{ (data.lastName?.[0] || '') }}\r\n </div>\r\n <img *ngIf=\"headshotPreviewUrl\" [src]=\"headshotPreviewUrl\"\r\n class=\"rounded-circle\" style=\"width:56px;height:56px;object-fit:cover;\" alt=\"Profile\" />\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h2 class=\"fw-bold mb-1\">{{ data.firstName }} {{ data.lastName }}</h2>\r\n <span *ngIf=\"basicSectionHasIssues()\" class=\"badge bg-warning-subtle text-warning border section-flag\">\r\n Missing info\r\n </span>\r\n <span class=\"badge border section-flag\"\r\n [ngClass]=\"basicDetailsSaved ? 'bg-success-subtle text-success' : 'bg-warning-subtle text-warning'\">\r\n {{ basicDetailsSaved ? 'Saved' : 'Not saved yet' }}\r\n </span>\r\n </div>\r\n <p class=\"text-muted\">{{ data.jobTitle }} \u2022 {{ data.yearsOfExperience }} Years Exp.</p>\r\n <div *ngIf=\"basicIssues().length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ basicIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <span class=\"badge bg-primary-subtle text-primary border p-2\">Email Verified</span>\r\n </div>\r\n\r\n </div>\r\n <div class=\"px-4 py-3\">\r\n <div class=\"row g-4\">\r\n <div class=\"col-12 border-bottom pb-2\">\r\n <h6 class=\"text-uppercase small fw-bold text-muted\">Summary</h6>\r\n <p class=\"text-secondary small mb-0\">{{ data.summary }}</p>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/envelope.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Email</span>\r\n <span class=\"field-value-sm d-block\">{{ data.email }}</span>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/telephone.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Phone</span>\r\n <span class=\"field-value-sm d-block\">{{ data.phone }}</span>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <span class=\"field-label-sm\"><img src=\"/assets/images/icons/geo-alt.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" />Location</span>\r\n <span class=\"field-value-sm d-block\">{{ data.address }}, {{ data.city }}, {{ data.state }}, {{ data.zipCode }}, {{ data.country }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer d-flex align-items-center justify-content-between\">\r\n <span *ngIf=\"!basicDetailsSaved\" class=\"small text-warning fw-semibold\">\r\n <img src=\"/assets/images/icons/exclamation-circle.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" /> Click \"Edit\" to review and save your basic info.\r\n </span>\r\n <span *ngIf=\"basicDetailsSaved\" class=\"small text-success fw-semibold\">\r\n <img src=\"/assets/images/icons/check-circle.svg\" width=\"13\" height=\"13\" class=\"me-1\" style=\"vertical-align:-0.1em\" alt=\"\" /> Basic details saved.\r\n </span>\r\n <button class=\"btn btn-sm btn-primary px-4 ms-auto\" (click)=\"toggleEdit()\">Edit</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0 update-profile-card\" *ngIf=\"isEditMode()\">\r\n <div class=\"card-header bg-white fw-bold\">Update Profile</div>\r\n <div class=\"card-body p-4\">\r\n <form class=\"row g-3\" #basicForm=\"ngForm\" novalidate>\r\n <div *ngIf=\"basicIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ basicIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">First Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.firstName\" name=\"fName\"\r\n placeholder=\"First Name\" required #fName=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"fName.invalid && (fName.dirty || fName.touched)\">First name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Last Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.lastName\" name=\"lName\"\r\n placeholder=\"Last Name\" required #lName=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"lName.invalid && (lName.dirty || lName.touched)\">Last name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Email <span class=\"text-danger\">*</span></label>\r\n <input type=\"email\" class=\"form-control\" [(ngModel)]=\"tempProfile.email\" name=\"email\" placeholder=\"Email\"\r\n required email #email=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"email.invalid && (email.dirty || email.touched)\">\r\n <span *ngIf=\"email.errors?.['required']\">Email is required</span>\r\n <span *ngIf=\"email.errors?.['email']\">Email format is invalid</span>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Phone Number <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"tempProfile.phone\" (input)=\"phoneMask($event, 'profile')\"\r\n name=\"phone\" placeholder=\"Phone (10 digits)\" (keypress)=\"allowOnlyNumbers($event)\"\r\n required pattern=\"^\\(\\d{3}\\) \\d{3}-\\d{4}$\" maxlength=\"14\" inputmode=\"numeric\" #phone=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"phone.invalid && (phone.dirty || phone.touched)\">\r\n <span *ngIf=\"phone.errors?.['required']\">Phone number is required</span>\r\n <span *ngIf=\"phone.errors?.['pattern']\">Phone number must be 10 digits</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\"></span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.jobTitle\" name=\"jobTitle\"\r\n placeholder=\"Job Title\" #jobTitle=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"jobTitle.invalid && (jobTitle.dirty || jobTitle.touched)\">Job\r\n title is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [ngClass]=\"{'is-invalid': !(tempProfile?.yearsOfExperience > 0)}\"\r\n [(ngModel)]=\"tempProfile.yearsOfExperience\"\r\n name=\"yearsOfExperience\" placeholder=\"Years of Experience\" required min=\"1\"\r\n #yearsOfExperience=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!(tempProfile?.yearsOfExperience > 0)\">\r\n Years of experience is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-3\">\r\n <label class=\"small text-muted d-block\">Home Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempProfile.address\" name=\"address\" [options]=\"options\"\r\n placeholder=\"Home Address\" required #address=\"ngModel\"\r\n [invalid]=\"address.invalid && (address.dirty || address.touched)\"\r\n [initialLat]=\"tempProfile.latitude\" [initialLng]=\"tempProfile.longitude\"\r\n (addressResolved)=\"onUserAddressResolved($event)\"\r\n (manualEdit)=\"onUserAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"address.invalid && (address.dirty || address.touched)\">Home\r\n address is required</div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.city\" name=\"city\" placeholder=\"City\"\r\n required #city=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"city.invalid && (city.dirty || city.touched)\">City is required\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.state\" name=\"state\" placeholder=\"State\"\r\n required #state=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"state.invalid && (state.dirty || state.touched)\">State is\r\n required</div>\r\n </div>\r\n\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"tempProfile.zipCode\"\r\n (ngModelChange)=\"tempProfile.zipCode = sanitizeZipCode($event)\" name=\"zipCode\" placeholder=\"Zip Code\"\r\n required pattern=\"^\\d{1,6}$\" maxlength=\"6\" inputmode=\"numeric\" #zipCode=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"zipCode.invalid && (zipCode.dirty || zipCode.touched)\">Zip code\r\n is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"zipCode.errors?.['pattern'] && (zipCode.dirty || zipCode.touched)\">\r\n Zip code must be up to 6 digits\r\n </div>\r\n </div>\r\n <div class=\"col-md-2\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"tempProfile.country\" name=\"country\"\r\n placeholder=\"Country\" required #country=\"ngModel\">\r\n <div class=\"small text-danger mt-1\" *ngIf=\"country.invalid && (country.dirty || country.touched)\">Country\r\n is required</div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Summary</label>\r\n <textarea class=\"form-control\" rows=\"3\" [(ngModel)]=\"tempProfile.summary\" name=\"sum\"\r\n placeholder=\"Summary\"></textarea>\r\n </div>\r\n\r\n\r\n </form>\r\n </div>\r\n <div class=\"card-footer text-end gap-2 d-flex justify-content-end\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancel()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingBasic || !isBasicFormValid\" (click)=\"save()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Saving...' : 'Save Changes' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5 provider-company-first\" *ngIf=\"roleData?.role?.name === 'Provider' && hasUserDetailData && !isResume\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/building.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Company Details</h5>\r\n <span *ngIf=\"companyDetailsSaved\"\r\n class=\"badge border section-flag bg-success-subtle text-success\">\r\n Saved\r\n </span>\r\n <span *ngIf=\"!companyDetailsSaved\"\r\n class=\"badge border section-flag bg-warning-subtle text-warning\">\r\n Not saved yet\r\n </span>\r\n </div>\r\n <button class=\"btn btn-sm btn-primary px-4\" (click)=\"toggleCompanyEdit()\">Edit</button>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"!isCompanyEditMode()\">\r\n <div class=\"card-body p-4\">\r\n <div class=\"row g-4\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name</label>\r\n <span class=\"fw-bold small\">{{ companyDetails()?.companyName}}</span>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone</label>\r\n <span class=\"fw-bold small\">{{ companyDetails()?.companyPhoneNumber}}</span>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Company Address</label>\r\n <span class=\"small\">{{ companyDetails()?.address1}}, {{ companyDetails()?.city}}, {{ companyDetails()?.state}}, {{ companyDetails()?.zipcode}}, {{ companyDetails()?.country}}</span>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"companyLogoUrl()\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <img [src]=\"companyLogoUrl()\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"card shadow-sm border-0\" *ngIf=\"isCompanyEditMode()\">\r\n <div class=\"card-header bg-white fw-bold\">Update Company Details</div>\r\n <div class=\"card-body p-4\">\r\n <form class=\"row g-3\" #companyForm=\"ngForm\" novalidate>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': (!tempCompanyDetails.companyName?.trim() && companyFormSubmitted) || companyNameError }\"\r\n [(ngModel)]=\"tempCompanyDetails.companyName\" name=\"companyName\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyName?.trim() && companyFormSubmitted\">\r\n Company name is required\r\n </div>\r\n <div class=\"invalid-feedback\" *ngIf=\"companyNameError\">\r\n {{ companyNameError }}\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Phone <span class=\"text-danger\">*</span></label>\r\n <input (input)=\"phoneMask($event, 'company')\" type=\"text\" maxlength=\"14\" (keypress)=\"allowOnlyNumbers($event)\" inputmode=\"numeric\" class=\"form-control form-control-sm\"\r\n [ngClass]=\"{ 'is-invalid': companyFormSubmitted && (!tempCompanyDetails.companyPhoneNumber?.trim() || getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10) }\"\r\n [(ngModel)]=\"tempCompanyDetails.companyPhoneNumber\" name=\"companyPhoneNumber\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.companyPhoneNumber?.trim() && companyFormSubmitted\">\r\n Company phone is required\r\n </div>\r\n <div class=\"invalid-feedback\" *ngIf=\"tempCompanyDetails.companyPhoneNumber?.trim() && getDigitCount(tempCompanyDetails.companyPhoneNumber) !== 10 && companyFormSubmitted\">\r\n Company phone must be 10 digits\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Address <span class=\"text-danger\">*</span></label>\r\n <im-address-verify-field [(ngModel)]=\"tempCompanyDetails.address1\" name=\"address1\" [options]=\"options\"\r\n required [invalid]=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\"\r\n [initialLat]=\"tempCompanyDetails.latitude\" [initialLng]=\"tempCompanyDetails.longitude\"\r\n (addressResolved)=\"onCompanyAddressResolved($event)\"\r\n (manualEdit)=\"onCompanyAddressManualEdit()\"></im-address-verify-field>\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.address1?.trim() && companyFormSubmitted\">\r\n Address is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.city?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.city\" name=\"city\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.city?.trim() && companyFormSubmitted\">\r\n City is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.state?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.state\" name=\"state\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.state?.trim() && companyFormSubmitted\">\r\n State is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Zip Code <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.zipcode?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.zipcode\" name=\"zipcode\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.zipcode?.trim() && companyFormSubmitted\">\r\n Zip code is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" \r\n [ngClass]=\"{ 'is-invalid': !tempCompanyDetails.country?.trim() && companyFormSubmitted }\"\r\n [(ngModel)]=\"tempCompanyDetails.country\" name=\"country\" required />\r\n <div class=\"invalid-feedback\" *ngIf=\"!tempCompanyDetails.country?.trim() && companyFormSubmitted\">\r\n Country is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company Logo</label>\r\n <input #uploadCompanyFile type=\"file\" accept=\".png,.jpg,.jpeg\" (change)=\"uploadCompanyImage($event)\" class=\"form-control\" />\r\n <small class=\"text-muted d-block mt-1\" style=\"font-size: 12px;\">Allowed formats: PNG, JPG, JPEG</small>\r\n </div>\r\n <div class=\"col-md-6\" *ngIf=\"tempCompanyLogoUrl\">\r\n <label class=\"small text-muted d-block\">Logo Preview</label>\r\n <img [src]=\"tempCompanyLogoUrl\" class=\"img-thumbnail\" style=\"max-height: 80px;\" />\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"card-footer text-end gap-2 d-flex justify-content-end\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelCompanyEdit()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingCompany\" \r\n (click)=\"saveCompanyDetails()\">\r\n <span *ngIf=\"isSavingCompany\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCompany ? 'Saving...' : 'Save Changes' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div [class.section-locked]=\"roleData?.role?.name === 'Provider' && !hasUserDetailData\">\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/briefcase-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Profession</h5>\r\n <span *ngIf=\"selectedProfessionCount > 0\" class=\"badge border section-flag bg-warning-subtle text-warning\">\r\n {{ selectedProfessionCount }} selected\r\n </span>\r\n </div>\r\n <button type=\"button\" class=\"btn btn-sm btn-primary px-4\"\r\n [disabled]=\"selectedProfessionCount === 0 || isSavingProfessionsTable\"\r\n (click)=\"submitProfessions()\">\r\n <span *ngIf=\"isSavingProfessionsTable\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingProfessionsTable ? 'Saving...' : professionSubmitLabel }}\r\n </button>\r\n </div>\r\n\r\n <div class=\"mb-3\">\r\n <input type=\"text\" class=\"form-control profession-search-input\" placeholder=\"Search or Add Profession\"\r\n [(ngModel)]=\"professionSearchQry\" name=\"professionSearchQry\"\r\n (keydown.enter)=\"createManualProfessionRow()\" />\r\n </div>\r\n\r\n <div class=\"bg-white border rounded shadow-sm profession-accordion\">\r\n <div class=\"profession-acc-columns\">\r\n <span></span>\r\n <span>Profession Name</span>\r\n <span>Group</span>\r\n <span>Type</span>\r\n <span></span>\r\n </div>\r\n\r\n <ng-container *ngFor=\"let p of filteredProfessionTypes; trackBy: trackByProfessionId\">\r\n <div class=\"profession-acc-item\" [class.profession-row-selected]=\"getProfessionSelection(p.id).selected\">\r\n <div class=\"profession-acc-header\" (click)=\"toggleProfessionRow(p, $event)\">\r\n <div class=\"text-center\" (click)=\"$event.stopPropagation()\">\r\n <input type=\"checkbox\" class=\"form-check-input\" [checked]=\"getProfessionSelection(p.id).selected\"\r\n (change)=\"onProfessionRowCheck(p, $event)\" />\r\n </div>\r\n <div class=\"profession-acc-name\">\r\n {{ p.professionName }}\r\n <span *ngIf=\"isProfessionSaved(p.id)\" class=\"badge border bg-success-subtle text-success ms-1\">Saved</span>\r\n </div>\r\n <div (mousedown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\r\n <ng-container *ngIf=\"p.isManual; else groupText\">\r\n <ng-select class=\"profession-inline-select\" [items]=\"professionGroupOptions\" [ngModel]=\"p.professionGroup\"\r\n (ngModelChange)=\"setManualProfessionGroup(p, $event)\" [name]=\"'manualGroup-' + p.id\"\r\n placeholder=\"Select group\" [clearable]=\"false\">\r\n </ng-select>\r\n </ng-container>\r\n <ng-template #groupText>{{ p.professionGroup || '\u2013' }}</ng-template>\r\n </div>\r\n <div (mousedown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\r\n <ng-container *ngIf=\"p.isManual; else typeText\">\r\n <ng-select class=\"profession-inline-select\" [items]=\"professionTypeOptions\" [ngModel]=\"p.residentialCommercial\"\r\n (ngModelChange)=\"setManualProfessionType(p, $event)\" [name]=\"'manualType-' + p.id\"\r\n placeholder=\"Select type\" [clearable]=\"false\">\r\n </ng-select>\r\n </ng-container>\r\n <ng-template #typeText>{{ p.residentialCommercial || '\u2013' }}</ng-template>\r\n </div>\r\n <button type=\"button\" class=\"profession-acc-chevron-btn\"\r\n [attr.aria-label]=\"getProfessionSelection(p.id).selected ? 'Collapse' : 'Expand'\">\r\n <svg class=\"profession-acc-chevron\" [class.profession-acc-chevron--open]=\"getProfessionSelection(p.id).selected\"\r\n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <polyline points=\"6 9 12 15 18 9\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"profession-acc-body\" *ngIf=\"getProfessionSelection(p.id).selected\">\r\n <div class=\"profession-acc-panel\">\r\n <div *ngIf=\"p.isManual && !isManualRowReady(p.id)\" class=\"small text-danger mb-3\">\r\n Select a Group and Type above to enable saving this profession.\r\n </div>\r\n <div class=\"profession-acc-fields\">\r\n <div class=\"profession-acc-field\">\r\n <label class=\"small text-muted d-block mb-1\">Self Ability Rating</label>\r\n <div class=\"profession-acc-stars\">\r\n <span *ngFor=\"let s of [1,2,3,4,5]\" class=\"fs-5\" style=\"cursor: pointer;\"\r\n (click)=\"setProfessionRowStars(p, s)\"\r\n [class.text-warning]=\"(getProfessionSelection(p.id).starRating || 0) / 2 >= s\"\r\n [class.text-muted]=\"(getProfessionSelection(p.id).starRating || 0) / 2 < s\">\u2605</span>\r\n </div>\r\n </div>\r\n <div class=\"profession-acc-field\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience</label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <input type=\"number\" class=\"form-control form-control-sm profession-acc-year-input\" min=\"0\" max=\"30\"\r\n [(ngModel)]=\"getProfessionSelection(p.id).year\" [name]=\"'profYear-' + p.id\" />\r\n <span class=\"small text-muted\">Yrs</span>\r\n </div>\r\n </div>\r\n <div class=\"profession-acc-field profession-acc-field--visibility\">\r\n <label class=\"small text-muted d-block mb-1\">Visibility</label>\r\n <input type=\"checkbox\" class=\"profession-visibility-checkbox\" [(ngModel)]=\"getProfessionSelection(p.id).profileVisibility\"\r\n [name]=\"'profVis-' + p.id\" />\r\n </div>\r\n <div class=\"profession-acc-field profession-acc-field--notes\">\r\n <label class=\"small text-muted d-block mb-1\">Additional Details</label>\r\n <textarea rows=\"3\" class=\"form-control form-control-sm profession-notes-input\" [(ngModel)]=\"getProfessionSelection(p.id).notes\"\r\n [name]=\"'profNotes-' + p.id\" placeholder=\"Additional Details\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <div *ngIf=\"hasNoProfessionMatches\" class=\"text-center small py-3\">\r\n <span class=\"text-muted\">No professions found for \"{{ professionSearchQry?.trim() }}\".</span>\r\n <button type=\"button\" class=\"btn btn-sm btn-primary ms-2\" (click)=\"createManualProfessionRow()\">\r\n Add \"{{ professionSearchQry?.trim() }}\"\r\n </button>\r\n </div>\r\n <div *ngIf=\"!professionSearchQry?.trim() && filteredProfessionTypes.length === 0\"\r\n class=\"text-center text-muted small py-3\">\r\n No professions found.\r\n </div>\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/briefcase-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Work Experience</h5>\r\n <span *ngIf=\"experience().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"workSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ workSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"experience().length === 0 || !workSectionHasUnsavedItems() || isSavingWork || isAddingJob() || editingJobIndex() !== null\"\r\n (click)=\"confirmAllWork()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add work experience\" (click)=\"addJob()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"experience().length === 0 && !isAddingJob()\" class=\"empty-state-wrap mb-3\" role=\"button\"\r\n (click)=\"addJob()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/briefcase.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No work experience added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3\">\r\n <div *ngIf=\"isAddingJob() && tempJob()\" class=\"list-group-item p-0 border-0\">\r\n <div class=\"form-panel mb-2\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.jobTitle\"\r\n (ngModelChange)=\"patchTempJob({ jobTitle: $event })\" name=\"newJobTitle\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.company\"\r\n (ngModelChange)=\"patchTempJob({ company: $event })\" name=\"newCompany\" />\r\n </div>\r\n <div class=\"align-items-end col-md-12 d-flex justify-content-end pe-3\">\r\n <div class=\"form-check\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"tempJob()?.isCurrent\"\r\n (ngModelChange)=\"setTempJobIsCurrent($event)\" name=\"newIsCurrent\" id=\"newIsCurrent\" />\r\n <label class=\"form-check-label\" for=\"newIsCurrent\">Current</label>\r\n </div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.country\"\r\n (ngModelChange)=\"patchTempJob({ country: $event })\" name=\"newCountry\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.state\"\r\n (ngModelChange)=\"patchTempJob({ state: $event })\" name=\"newState\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.city\"\r\n (ngModelChange)=\"patchTempJob({ city: $event })\" name=\"newCity\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempJob()?.startDate)\"\r\n (bsValueChange)=\"setTempJobMonth('startDate', $event)\" name=\"newStartDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.startDate)\">Start date is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [disabled]=\"tempJob()?.isCurrent\"\r\n [ngModel]=\"monthInputToDate(tempJob()?.endDate)\" (bsValueChange)=\"setTempJobMonth('endDate', $event)\"\r\n name=\"newEndDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!tempJob()?.isCurrent && isBlank(tempJob()?.endDate)\">End date is\r\n required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"!tempJob()?.isCurrent && isMonthRangeInvalid(tempJob()?.startDate, tempJob()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Responsibilities (one per line)</label>\r\n <textarea rows=\"4\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"(tempJob()?.responsibilities || []).join('\\n')\"\r\n (ngModelChange)=\"updateTempResponsibilities($event)\" name=\"newResponsibilities\"></textarea>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onWorkExperienceFileSelected($event)\" name=\"newWorkAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempJob()?.fileName\">\r\n <span>{{ tempJob()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempJob())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n <div class=\"d-flex justify-content-end gap-2 mt-3\">\r\n <button class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditJob(); $event.stopPropagation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingWork\"\r\n (click)=\"saveEditJob(); $event.stopPropagation()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Uploading...' : workActionLabel(editingJobIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <div *ngFor=\"let job of experience(); let i = index\" class=\"list-group-item p-0 border-0 mb-2\">\r\n\r\n <div class=\"work-accent-item p-3 rounded-3 bg-white border\">\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n <div class=\"d-flex align-items-center cursor-pointer flex-grow-1\" (click)=\"toggleJob(i)\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h6 class=\"mb-0 fw-bold item-title-sm\">{{ job.jobTitle }}</h6>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedWorkItem(i) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedWorkItem(i) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ job.company || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ formatMonthYear(job.startDate) }} - {{ job.isCurrent ? 'Present' :\r\n formatMonthYear(job.endDate) }}</span>\r\n <span class=\"item-meta-line\">{{ job.city }}<span *ngIf=\"job.city && job.state\">, </span>{{ job.state }}<ng-container *ngIf=\"!job.city && !job.state\">\u2014</ng-container></span>\r\n <div *ngIf=\"editingJobIndex() !== i && (workIssuesByIndex()[i] || []).length > 0\"\r\n class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (workIssuesByIndex()[i] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex align-items-center gap-2\">\r\n\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\" (click)=\"startEditJob(i)\"\r\n title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteJob(i);\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n \r\n </div>\r\n </div>\r\n\r\n\r\n\r\n <div class=\"mt-3 p-3 rounded small\" *ngIf=\"expandedIndex() === i\">\r\n <ng-container *ngIf=\"editingJobIndex() !== i; else editJobForm\">\r\n <ul class=\"mb-0\">\r\n <li *ngFor=\"let res of job.responsibilities\">{{ res }}</li>\r\n </ul>\r\n </ng-container>\r\n\r\n <ng-template #editJobForm>\r\n <div *ngIf=\"(workIssuesByIndex()[i] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (workIssuesByIndex()[i] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Job Title <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.jobTitle\"\r\n (ngModelChange)=\"patchTempJob({ jobTitle: $event })\" name=\"jobTitle{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.jobTitle)\">Job title is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Company <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.company\"\r\n (ngModelChange)=\"patchTempJob({ company: $event })\" name=\"company{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.company)\">Company name is required</div>\r\n </div>\r\n\r\n <div class=\"align-items-end col-md-12 d-flex justify-content-end pe-3\">\r\n <div class=\"form-check\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"tempJob()?.isCurrent\"\r\n (ngModelChange)=\"setTempJobIsCurrent($event)\" name=\"isCurrent{{ i }}\" id=\"isCurrent{{ i }}\" />\r\n <label class=\"form-check-label\" for=\"isCurrent{{ i }}\">Current</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.country\"\r\n (ngModelChange)=\"patchTempJob({ country: $event })\" name=\"country{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.state\"\r\n (ngModelChange)=\"patchTempJob({ state: $event })\" name=\"state{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempJob()?.city\"\r\n (ngModelChange)=\"patchTempJob({ city: $event })\" name=\"city{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.city)\">City is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempJob()?.startDate)\"\r\n (bsValueChange)=\"setTempJobMonth('startDate', $event)\" name=\"startDate{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempJob()?.startDate)\">Start date is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [disabled]=\"tempJob()?.isCurrent\"\r\n [ngModel]=\"monthInputToDate(tempJob()?.endDate)\" (bsValueChange)=\"setTempJobMonth('endDate', $event)\"\r\n name=\"endDate{{ i }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"!tempJob()?.isCurrent && isBlank(tempJob()?.endDate)\">\r\n End date is required\r\n </div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"!tempJob()?.isCurrent && isMonthRangeInvalid(tempJob()?.startDate, tempJob()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Responsibilities (one per line)</label>\r\n <textarea rows=\"4\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"(tempJob()?.responsibilities || []).join('\\n')\"\r\n (ngModelChange)=\"updateTempResponsibilities($event)\" name=\"responsibilities{{ i }}\"></textarea>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onWorkExperienceFileSelected($event)\" name=\"workAttachment{{ i }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempJob()?.fileName\">\r\n <span>{{ tempJob()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempJob())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n </ng-template>\r\n </div>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-3\" *ngIf=\"editingJobIndex() === i\">\r\n <button class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditJob(); $event.stopPropagation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4 \" [disabled]=\"isSavingWork\"\r\n (click)=\"saveEditJob(); $event.stopPropagation()\">\r\n <span *ngIf=\"isSavingWork\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingWork ? 'Uploading...' : workActionLabel(editingJobIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/patch-check-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Certifications</h5>\r\n <span *ngIf=\"certs().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"certificationSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ certificationSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"certs().length === 0 || !certificationSectionHasUnsavedItems() || isSavingCertification || isAddingCertification() || editingCertificationIndex() !== null\"\r\n (click)=\"confirmAllCertifications()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add certification\" (click)=\"addCertification()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"certs().length === 0 && !isAddingCertification() && editingCertificationIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addCertification()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/patch-check.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No certifications added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3 border\">\r\n <div *ngIf=\"isAddingCertification() && tempCertification()\" class=\"list-group-item py-3 px-3\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"tempCertification()?.professionId\" (change)=\"onCertificationProfessionChange($event)\"\r\n name=\"newCertProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('certificate')\">+</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.name\"\r\n (ngModelChange)=\"patchTempCertification({ name: $event })\" name=\"newCertName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempCertification()?.name)\">Certificate name is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.issuingOrganization || ''\"\r\n (ngModelChange)=\"patchTempCertification({ issuingOrganization: $event || null })\" name=\"newCertOrg\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.state || ''\"\r\n (ngModelChange)=\"patchTempCertification({ state: $event || null })\" name=\"newCertState\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certification Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.credentialId || ''\"\r\n (ngModelChange)=\"patchTempCertification({ credentialId: $event || null })\" name=\"newCertCredentialId\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('issueDate', $event)\" name=\"newCertIssueDate\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('expiryDate', $event)\" name=\"newCertExpiryDate\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempCertification()?.issueDate || null, tempCertification()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onCertificationFileSelected($event)\" name=\"newCertAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempCertification()?.fileName\">\r\n <span>{{ tempCertification()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempCertification())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditCertification()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\"\r\n [disabled]=\"isSavingCertification\"\r\n (click)=\"saveCertificationEditor()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Uploading...' : certificationActionLabel(editingCertificationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let cert of certs(); let ci = index\" class=\"list-group-item py-3 cert-accent-item\">\r\n <ng-container *ngIf=\"editingCertificationIndex() !== ci; else editCert\">\r\n <div class=\"d-flex justify-content-between align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <div class=\"fw-semibold item-title-sm\">{{ cert.name }}</div>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedCertificationItem(ci) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedCertificationItem(ci) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ cert.issuingOrganization || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.credentialId || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.issueDate ? formatMonthYear(cert.issueDate) : '\u2014' }} - {{ cert.expiryDate ? formatMonthYear(cert.expiryDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ cert.state || '\u2014' }}</span>\r\n <div *ngIf=\"(certIssuesByIndex()[ci] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (certIssuesByIndex()[ci] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditCertification(ci)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\"\r\n (click)=\"deleteCertification(ci)\" title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #editCert>\r\n <div *ngIf=\"(certIssuesByIndex()[ci] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (certIssuesByIndex()[ci] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"tempCertification()?.professionId\" (change)=\"onCertificationProfessionChange($event)\"\r\n name=\"certProfessionType{{ ci }}\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('certificate')\">+</button>\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.name\"\r\n (ngModelChange)=\"patchTempCertification({ name: $event })\" name=\"certName{{ ci }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempCertification()?.name)\">Certificate name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certificate Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.issuingOrganization || ''\"\r\n (ngModelChange)=\"patchTempCertification({ issuingOrganization: $event || null })\"\r\n name=\"certOrg{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempCertification()?.state || ''\"\r\n (ngModelChange)=\"patchTempCertification({ state: $event || null })\" name=\"certState{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Certification Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\"\r\n [ngModel]=\"tempCertification()?.credentialId || ''\"\r\n (ngModelChange)=\"patchTempCertification({ credentialId: $event || null })\"\r\n name=\"certCredentialId{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('issueDate', $event)\" name=\"certIssue{{ ci }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempCertification()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempCertificationMonth('expiryDate', $event)\" name=\"certExpiry{{ ci }}\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempCertification()?.issueDate || null, tempCertification()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Certification File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onCertificationFileSelected($event)\" name=\"certAttachment{{ ci }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempCertification()?.fileName\">\r\n <span>{{ tempCertification()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempCertification())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditCertification()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingCertification\"\r\n (click)=\"saveCertificationEditor()\">\r\n <span *ngIf=\"isSavingCertification\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCertification ? 'Uploading...' : certificationActionLabel(editingCertificationIndex()) }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/card-checklist-warning.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Licenses</h5>\r\n <span *ngIf=\"licenses().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"licenseSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ licenseSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"licenses().length === 0 || !licenseSectionHasUnsavedItems() || isSavingLicense || isAddingLicense() || editingLicenseIndex() !== null\"\r\n (click)=\"confirmAllLicenses()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add license\" (click)=\"addLicense()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n <div *ngIf=\"licenses().length === 0 && !isAddingLicense() && editingLicenseIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addLicense()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/card-checklist.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No licenses added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div class=\"list-group list-group-flush shadow-sm rounded-3 border\">\r\n <div *ngIf=\"isAddingLicense() && tempLicense()\" class=\"list-group-item py-3 px-3\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.name\"\r\n (ngModelChange)=\"patchTempLicense({ name: $event })\" name=\"newLicName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempLicense()?.name)\">License name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.issuingAuthority || ''\"\r\n (ngModelChange)=\"patchTempLicense({ issuingAuthority: $event || null })\" name=\"newLicAuthority\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.licenseNumber || ''\"\r\n (ngModelChange)=\"patchTempLicense({ licenseNumber: $event || null })\" name=\"newLicNumber\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.state || ''\"\r\n (ngModelChange)=\"patchTempLicense({ state: $event || null })\" name=\"newLicState\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('issueDate', $event)\" name=\"newLicIssueDate\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('expiryDate', $event)\" name=\"newLicExpiryDate\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempLicense()?.issueDate || null, tempLicense()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">License File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onLicenseFileSelected($event)\" name=\"newLicenseAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempLicense()?.fileName\">\r\n <span>{{ tempLicense()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempLicense())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelEditLicense()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingLicense\"\r\n (click)=\"saveLicenseEditor()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Uploading...' : licenseActionLabel(editingLicenseIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let lic of licenses(); let li = index\" class=\"list-group-item py-3 lic-accent-item\">\r\n <ng-container *ngIf=\"editingLicenseIndex() !== li; else editLic\">\r\n <div class=\"d-flex justify-content-between align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <div class=\"fw-semibold item-title-sm\">{{ lic.name }}</div>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedLicenseItem(li) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedLicenseItem(li) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ lic.issuingAuthority || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.licenseNumber || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.issueDate ? formatMonthYear(lic.issueDate) : '\u2014' }} - {{ lic.expiryDate ? formatMonthYear(lic.expiryDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ lic.state || '\u2014' }}</span>\r\n <div *ngIf=\"(licenseIssuesByIndex()[li] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (licenseIssuesByIndex()[li] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditLicense(li)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteLicense(li)\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #editLic>\r\n <div *ngIf=\"(licenseIssuesByIndex()[li] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (licenseIssuesByIndex()[li] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.name\"\r\n (ngModelChange)=\"patchTempLicense({ name: $event })\" name=\"licName{{ li }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempLicense()?.name)\">License name is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Issued By</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.issuingAuthority || ''\"\r\n (ngModelChange)=\"patchTempLicense({ issuingAuthority: $event || null })\" name=\"licAuthority{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">License Number</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.licenseNumber || ''\"\r\n (ngModelChange)=\"patchTempLicense({ licenseNumber: $event || null })\" name=\"licNumber{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issued State</label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempLicense()?.state || ''\"\r\n (ngModelChange)=\"patchTempLicense({ state: $event || null })\" name=\"licState{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Issue Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.issueDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('issueDate', $event)\" name=\"licIssue{{ li }}\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Expiry Date</label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempLicense()?.expiryDate || null)\"\r\n (bsValueChange)=\"setTempLicenseMonth('expiryDate', $event)\" name=\"licExpiry{{ li }}\" />\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempLicense()?.issueDate || null, tempLicense()?.expiryDate || null)\">\r\n Issued date must be less than expiry date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">License File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onLicenseFileSelected($event)\" name=\"licenseAttachment{{ li }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempLicense()?.fileName\">\r\n <span>{{ tempLicense()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempLicense())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditLicense()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingLicense\"\r\n (click)=\"saveLicenseEditor()\">\r\n <span *ngIf=\"isSavingLicense\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingLicense ? 'Uploading...' : licenseActionLabel(editingLicenseIndex()) }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section mb-5\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/tools.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Tools</h5>\r\n <span *ngIf=\"tools().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"toolsSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ toolsSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"tools().length === 0 || !toolsSectionHasUnsavedItems() || isSavingTool || isToolEditorOpen()\" (click)=\"confirmAllTools()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add tool\" (click)=\"addTool()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex flex-wrap gap-2 p-3 bg-white border rounded shadow-sm\">\r\n <div *ngFor=\"let tool of tools(); let ti = index\" class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\"\r\n class=\"btn btn-light border res-flex d-inline-flex align-items-center gap-2 px-3 py-2\"\r\n (click)=\"openToolEditor(ti)\" title=\"Edit\">\r\n <span class=\"fw-normal item-name-text\">{{ tool }}</span>\r\n <span class=\"badge border ms-1\"\r\n [ngClass]=\"hasUnsavedToolItem(ti) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedToolItem(ti) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n <span *ngIf=\"(toolIssuesByIndex()[ti] || []).length > 0\"\r\n class=\"badge bg-warning-subtle text-warning border ms-1\">\r\n Missing info\r\n </span>\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-danger rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Delete tool\" (click)=\"deleteTool(ti)\">\r\n <span class=\"fw-bold\">\u00D7</span>\r\n </button>\r\n </div>\r\n\r\n <span *ngIf=\"tools().length === 0\" class=\"text-muted small\">No tools added.</span>\r\n </div>\r\n\r\n <div *ngIf=\"isToolEditorOpen()\" class=\"position-fixed top-0 start-0 w-100 h-100\"\r\n style=\"background: rgba(0,0,0,0.35); z-index: 9999999;\" (click)=\"closeToolEditor()\">\r\n <div class=\"container h-100 d-flex align-items-start justify-content-center pt-4\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"card shadow border-0 w-100\" style=\"max-width: 900px;\">\r\n <div class=\"card-header bg-white d-flex align-items-center gap-3\">\r\n <button type=\"button\" class=\"btn btn-link p-0 text-decoration-none\" (click)=\"closeToolEditor()\">\r\n <img src=\"/assets/images/icons/arrow-left-blue.svg\" width=\"20\" height=\"20\" alt=\"\" />\r\n </button>\r\n <div class=\"fw-bold\">{{ isAddingTool() ? 'Add Tool' : ('Edit ' + (toolForm()?.name || '') + ' Tool') }}\r\n </div>\r\n </div>\r\n <div class=\"card-body p-4\">\r\n <div *ngIf=\"toolFormIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ toolFormIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"row g-3\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"toolForm()?.professionId\" (change)=\"onToolProfessionChange($event)\"\r\n name=\"toolProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('tool')\">+</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Tool Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"toolForm()?.name\"\r\n (ngModelChange)=\"patchToolForm({ name: $event })\" name=\"toolName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(toolForm()?.name)\">Tool name is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating</label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempToolStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"(toolForm()?.stars || 0) >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ (toolForm()?.stars || 0) >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ toolForm()?.stars || 0 }}/5</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Years of Experience</label>\r\n <input type=\"number\" class=\"form-control\" [ngModel]=\"toolForm()?.year\"\r\n (ngModelChange)=\"patchToolForm({ year: $event === '' ? 0 : +$event })\" name=\"toolYear\" min=\"0\"\r\n max=\"30\" placeholder=\"Years of Experience\" />\r\n </div>\r\n\r\n <div class=\"col-md-4 text-center\">\r\n <label class=\"small text-muted d-block\">Profile Visibility</label>\r\n <div class=\"form-checks form-switch mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"toolForm()?.profileVisibility\"\r\n (ngModelChange)=\"patchToolForm({ profileVisibility: $event })\" name=\"toolVisible\" id=\"toolVisible\"\r\n style=\"width: 55px;height: 25px;margin-left: -57px;\" />\r\n <label class=\"form-check-label ps-2 pt-1\" for=\"toolVisible\">Visible</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Comment</label>\r\n <textarea rows=\"4\" class=\"form-control\" [ngModel]=\"toolForm()?.notes\"\r\n (ngModelChange)=\"patchToolForm({ notes: $event })\" name=\"toolNotes\"\r\n placeholder=\"Enter additional details (optional)\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer bg-white d-flex justify-content-end gap-2\">\r\n <button *ngIf=\"!isAddingTool() && editingToolIndex() !== null\" type=\"button\"\r\n class=\"btn btn-link text-danger me-auto\" (click)=\"deleteTool(editingToolIndex()!)\">\r\n Delete\r\n </button>\r\n <button type=\"button\" class=\"btn btn-link text-secondary\" (click)=\"closeToolEditor()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary px-4\" [disabled]=\"isSavingTool\" (click)=\"saveToolEditor()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Saving...' : toolActionLabel(editingToolIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row g-4 mb-5\">\r\n <div class=\"col-md-12\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/stars.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Skills</h5>\r\n <span *ngIf=\"skills().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"skillsSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ skillsSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"skills().length === 0 || !skillsSectionHasUnsavedItems() || isSavingSkill || isSkillEditorOpen()\" (click)=\"confirmAllSkills()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add skill\" (click)=\"addSkill()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"d-flex flex-wrap gap-2 p-3 bg-white border rounded shadow-sm\">\r\n <div *ngFor=\"let skill of skills(); let si = index\" class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\"\r\n class=\"btn btn-light border res-flex d-inline-flex align-items-center gap-2 px-3 py-2\"\r\n (click)=\"openSkillEditor(si)\" title=\"Edit\">\r\n <span class=\"fw-normal item-name-text\">{{ skill }}</span>\r\n <span class=\"badge border ms-1\"\r\n [ngClass]=\"hasUnsavedSkillItem(si) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedSkillItem(si) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n <span *ngIf=\"(skillIssuesByIndex()[si] || []).length > 0\"\r\n class=\"badge bg-warning-subtle text-warning border ms-1\">\r\n Missing info\r\n </span>\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-danger rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Delete skill\"\r\n (click)=\"deleteSkill(si); $event.stopPropagation()\">\r\n <span class=\"fw-bold\">\u00D7</span>\r\n </button>\r\n </div>\r\n\r\n <span *ngIf=\"skills().length === 0\" class=\"text-muted small\">No skills added.</span>\r\n </div>\r\n <div *ngIf=\"isSkillEditorOpen()\" class=\"position-fixed top-0 start-0 w-100 h-100\"\r\n style=\"background: rgba(0,0,0,0.35); z-index: 9999999;\" (click)=\"closeSkillEditor()\">\r\n <div class=\"container h-100 d-flex align-items-start justify-content-center pt-4\"\r\n (click)=\"$event.stopPropagation()\">\r\n <div class=\"card shadow border-0 w-100\" style=\"max-width: 900px;\">\r\n <div class=\"card-header bg-white d-flex align-items-center gap-3\">\r\n <button type=\"button\" class=\"btn btn-link p-0 text-decoration-none\" (click)=\"closeSkillEditor()\">\r\n <img src=\"/assets/images/icons/arrow-left-blue.svg\" width=\"20\" height=\"20\" alt=\"\" />\r\n </button>\r\n <div class=\"fw-bold\">{{ isAddingSkill() ? 'Add Skill' : ('Edit ' + (skillForm()?.name || '') + ' Skill')\r\n }}</div>\r\n </div>\r\n <div class=\"card-body p-4\">\r\n <div *ngIf=\"skillFormIssues().length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ skillFormIssues().join(' \u2022 ') }}</div>\r\n </div>\r\n <div class=\"row g-3\">\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Profession Type</label>\r\n <div class=\"d-flex align-items-start gap-2\">\r\n <ng-select class=\"flex-grow-1\" [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"skillForm()?.professionId\" (change)=\"onSkillProfessionChange($event)\"\r\n name=\"skillProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n <button type=\"button\" class=\"btn btn-outline-primary btn-sm\" title=\"Add new profession\"\r\n (click)=\"openCustomProfessionForm('skill')\">+</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Skills Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [ngModel]=\"skillForm()?.name\"\r\n (ngModelChange)=\"patchSkillForm({ name: $event })\" name=\"skillName\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(skillForm()?.name)\">Skillset name is required</div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating</label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempSkillStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"(skillForm()?.stars || 0) >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ (skillForm()?.stars || 0) >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ skillForm()?.stars || 0 }}/5</span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Years of Experience</label>\r\n <input type=\"number\" class=\"form-control\" [ngModel]=\"skillForm()?.year\"\r\n (ngModelChange)=\"patchSkillForm({ year: $event === '' ? 0 : +$event })\" name=\"skillYear\" min=\"0\"\r\n max=\"30\" placeholder=\"Years of Experience\" />\r\n </div>\r\n\r\n <div class=\"col-md-4 text-center\">\r\n <label class=\"small text-muted d-block\">Profile Visibility</label>\r\n <div class=\"form-checks form-switch mt-2\">\r\n <input class=\"form-check-input\" type=\"checkbox\" [ngModel]=\"skillForm()?.profileVisibility\"\r\n (ngModelChange)=\"patchSkillForm({ profileVisibility: $event })\" name=\"skillVisible\"\r\n id=\"skillVisible\" style=\"width: 55px;height: 25px;margin-left: -57px;\" />\r\n <label class=\"form-check-label ps-2 pt-1\" for=\"skillVisible\">Visible</label>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Comment</label>\r\n <textarea rows=\"4\" class=\"form-control\" [ngModel]=\"skillForm()?.notes\"\r\n (ngModelChange)=\"patchSkillForm({ notes: $event })\" name=\"skillNotes\"\r\n placeholder=\"Enter additional details (optional)\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card-footer bg-white d-flex justify-content-end gap-2\">\r\n <button *ngIf=\"!isAddingSkill() && editingSkillIndex() !== null\" type=\"button\"\r\n class=\"btn btn-link text-danger me-auto\" (click)=\"deleteSkill(editingSkillIndex()!)\">\r\n Delete\r\n </button>\r\n <button type=\"button\" class=\"btn btn-link text-secondary\" (click)=\"closeSkillEditor()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary px-4\" [disabled]=\"isSavingSkill\" (click)=\"saveSkillEditor()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Saving...' : skillActionLabel(editingSkillIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row g-4 mb-5\">\r\n <div class=\"col-md-12\">\r\n <div class=\"d-flex justify-content-between align-items-center mb-3 section-header-row\">\r\n <div class=\"d-flex align-items-center gap-2 section-header-title\">\r\n <img src=\"/assets/images/icons/mortarboard-fill.svg\" width=\"20\" height=\"20\" class=\"section-header-icon\" alt=\"\" />\r\n <h5 class=\"fw-bold mb-0\">Education</h5>\r\n <span *ngIf=\"educationList().length > 0\" class=\"badge border section-flag\"\r\n [ngClass]=\"educationSectionHasUnsavedItems() ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ educationSectionHasUnsavedItems() ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-success\"\r\n [disabled]=\"educationList().length === 0 || !educationSectionHasUnsavedItems() || isSavingEducation || isAddingEducation() || editingEducationIndex() !== null\"\r\n (click)=\"confirmAllEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Confirming...' : 'Confirm All' }}\r\n </button>\r\n <button type=\"button\"\r\n class=\"btn btn-sm btn-outline-primary rounded-circle d-inline-flex align-items-center justify-content-center\"\r\n style=\"width: 32px; height: 32px; line-height: 1;\" title=\"Add education\" (click)=\"addEducation()\">\r\n <span class=\"fw-bold fs-5\">+</span>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"educationList().length === 0 && !isAddingEducation() && editingEducationIndex() === null\"\r\n class=\"empty-state-wrap mb-3\" role=\"button\" (click)=\"addEducation()\">\r\n <div class=\"empty-icon\"><img src=\"/assets/images/icons/mortarboard.svg\" width=\"32\" height=\"32\" alt=\"\" /></div>\r\n <p>No education added yet. Click <strong>+</strong> to add one.</p>\r\n </div>\r\n\r\n <div *ngIf=\"isAddingEducation() && tempEducation()\" class=\"mb-2\">\r\n <div class=\"form-panel\">\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.degree\"\r\n (ngModelChange)=\"patchTempEducation({ degree: $event })\" name=\"newEduDegree\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degree)\">Degree / Course name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Institution <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.institution\"\r\n (ngModelChange)=\"patchTempEducation({ institution: $event })\" name=\"newEduInstitution\" />\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree / Course Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"ng-select-sm\" [items]=\"educationDegreeTypeOptions\" [clearable]=\"false\"\r\n placeholder=\"Select degree / course type\" [ngModel]=\"tempEducation()?.degreeType\"\r\n (ngModelChange)=\"patchTempEducation({ degreeType: $event })\" name=\"newEduDegreeType\">\r\n </ng-select>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degreeType)\">Degree / Course type is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.country\"\r\n (ngModelChange)=\"patchTempEducation({ country: $event })\" name=\"newEduCountry\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.state\"\r\n (ngModelChange)=\"patchTempEducation({ state: $event })\" name=\"newEduState\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.city\"\r\n (ngModelChange)=\"patchTempEducation({ city: $event })\" name=\"newEduCity\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.startDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('startDate', $event)\" name=\"newEduStartDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.startDate)\">Start date is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.endDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('endDate', $event)\" name=\"newEduEndDate\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.endDate)\">End date is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempEducation()?.startDate, tempEducation()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Education File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onEducationFileSelected($event)\" name=\"newEducationAttachment\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempEducation()?.fileName\">\r\n <span>{{ tempEducation()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempEducation())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button type=\"button\" class=\"btn btn-sm btn-link text-secondary\"\r\n (click)=\"cancelEditEducation()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingEducation\"\r\n (click)=\"saveEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Uploading...' : educationActionLabel(editingEducationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div *ngFor=\"let edu of educationList(); let ei = index\" class=\"edu-accent-item p-3 bg-white border rounded-3 shadow-sm mb-2\">\r\n <div class=\"d-flex justify-content-between align-items-start\">\r\n <div class=\"d-flex align-items-start gap-3\">\r\n <div>\r\n <div class=\"d-flex align-items-center gap-2 flex-wrap\">\r\n <h6 class=\"fw-bold mb-0 item-title-sm\">{{ edu.degree }}</h6>\r\n <span class=\"badge border\"\r\n [ngClass]=\"hasUnsavedEducationItem(ei) ? 'bg-warning-subtle text-warning' : 'bg-success-subtle text-success'\">\r\n {{ hasUnsavedEducationItem(ei) ? 'Not saved yet' : 'Saved' }}\r\n </span>\r\n </div>\r\n <span class=\"item-meta-line\">{{ edu.institution || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.degreeType || '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.startDate ? formatMonthYear(edu.startDate) : '\u2014' }} - {{ edu.endDate ? formatMonthYear(edu.endDate) : '\u2014' }}</span>\r\n <span class=\"item-meta-line\">{{ edu.city }}<span *ngIf=\"edu.city && edu.state\">, </span>{{ edu.state }}<ng-container *ngIf=\"!edu.city && !edu.state\">\u2014</ng-container></span>\r\n <div *ngIf=\"(educationIssuesByIndex()[ei] || []).length > 0\" class=\"alert alert-warning py-1 px-2 mt-2\">\r\n <div class=\"fw-semibold small\">Missing required fields</div>\r\n <div class=\"small\">{{ (educationIssuesByIndex()[ei] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex align-items-center gap-2\" *ngIf=\"editingEducationIndex() !== ei\">\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-primary action-icon-btn\"\r\n (click)=\"startEditEducation(ei)\" title=\"Edit\">\r\n <img class=\"action-icon-image edit-icon\" src=\"/assets/images/icons/edit-text.png\" alt=\"Edit\" />\r\n </button>\r\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger action-icon-btn\" (click)=\"deleteEducation(ei)\"\r\n title=\"Delete\">\r\n <img class=\"action-icon-image delete-icon\" src=\"/assets/images/icons/delete.png\" alt=\"Delete\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"editingEducationIndex() === ei\" class=\"mt-3\">\r\n <div *ngIf=\"(educationIssuesByIndex()[ei] || []).length > 0\" class=\"alert alert-warning py-2 px-3 mb-3\">\r\n <div class=\"fw-semibold\">Missing required fields</div>\r\n <div class=\"small\">{{ (educationIssuesByIndex()[ei] || []).join(' \u2022 ') }}</div>\r\n </div>\r\n <form class=\"row g-2\">\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.degree\"\r\n (ngModelChange)=\"patchTempEducation({ degree: $event })\" name=\"eduDegree{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degree)\">Degree / Course name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Institution <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.institution\"\r\n (ngModelChange)=\"patchTempEducation({ institution: $event })\" name=\"eduInstitution{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.institution)\">Institution name is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Degree / Course Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"ng-select-sm\" [items]=\"educationDegreeTypeOptions\" [clearable]=\"false\"\r\n placeholder=\"Select degree / course type\" [ngModel]=\"tempEducation()?.degreeType\"\r\n (ngModelChange)=\"patchTempEducation({ degreeType: $event })\" name=\"eduDegreeType{{ ei }}\">\r\n </ng-select>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.degreeType)\">Degree / Course type is\r\n required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">Country <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.country\"\r\n (ngModelChange)=\"patchTempEducation({ country: $event })\" name=\"eduCountry{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.country)\">Country is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">State <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.state\"\r\n (ngModelChange)=\"patchTempEducation({ state: $event })\" name=\"eduState{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.state)\">State is required</div>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <label class=\"small text-muted d-block\">City <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control form-control-sm\" [ngModel]=\"tempEducation()?.city\"\r\n (ngModelChange)=\"patchTempEducation({ city: $event })\" name=\"eduCity{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.city)\">City is required</div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">Start Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"maxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.startDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('startDate', $event)\" name=\"eduStartDate{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.startDate)\">Start date is required\r\n </div>\r\n </div>\r\n <div class=\"col-md-6\">\r\n <label class=\"small text-muted d-block\">End Date <span class=\"text-danger\">*</span></label>\r\n <input class=\"form-control form-control-sm\" placeholder=\"MM/YYYY\" bsDatepicker [maxDate]=\"futureMaxDate\"\r\n [bsConfig]=\"monthPickerConfig\" [ngModel]=\"monthInputToDate(tempEducation()?.endDate)\"\r\n (bsValueChange)=\"setTempEducationMonth('endDate', $event)\" name=\"eduEndDate{{ ei }}\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"isBlank(tempEducation()?.endDate)\">End date is required</div>\r\n <div class=\"small text-danger mt-1\"\r\n *ngIf=\"isMonthRangeInvalid(tempEducation()?.startDate, tempEducation()?.endDate)\">\r\n Start date must be less than end date\r\n </div>\r\n </div>\r\n <div class=\"col-12\">\r\n <label class=\"small text-muted d-block\">Education File</label>\r\n <input type=\"file\" accept=\".pdf,.doc,.docx,.jpg,.jpeg,.png\" class=\"form-control form-control-sm\"\r\n (change)=\"onEducationFileSelected($event)\" name=\"educationAttachment{{ ei }}\" />\r\n <small class=\"text-muted\" style=\"font-size: 12px;\">Allowed formats: PDF, DOC, DOCX, JPG, JPEG, PNG</small>\r\n <div class=\"small text-muted mt-1 d-flex align-items-center gap-2\" *ngIf=\"tempEducation()?.fileName\">\r\n <span>{{ tempEducation()?.fileName }}</span>\r\n <button type=\"button\" class=\"btn btn-link btn-sm p-0\"\r\n (click)=\"previewSelectedFile(tempEducation())\">Preview</button>\r\n </div>\r\n </div>\r\n </form>\r\n\r\n <div class=\"d-flex justify-content-end gap-2 mt-2\">\r\n <button class=\"btn btn-sm btn-link text-secondary\" (click)=\"cancelEditEducation()\">Cancel</button>\r\n <button class=\"btn btn-sm btn-success px-4\" [disabled]=\"isSavingEducation\" (click)=\"saveEducation()\">\r\n <span *ngIf=\"isSavingEducation\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingEducation ? 'Uploading...' : educationActionLabel(editingEducationIndex()) }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n </div>\r\n <div class=\"d-flex gap-3 justify-content-center mt-5 pt-2\" *ngIf=\"!isResume\">\r\n <button class=\"btn btn-outline-secondary preview-back-btn px-5 h-auto\" style=\"border-radius: 5px !important;\" (click)=\"onBackClick()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"me-1\" style=\"vertical-align:-0.1em\">\r\n <path d=\"M11 3 5 8l6 5\" />\r\n </svg> Back\r\n </button>\r\n <button class=\"btn btn-primary preview-dashboard-btn px-5 h-auto\" style=\"border-radius: 5px !important;\" [disabled]=\"!canConfirmAndContinue() || isSavingBasic\"\r\n (click)=\"onGoToDashboardClick()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Saving...' : 'Go to Dashboard' }}\r\n <img *ngIf=\"!isSavingBasic\" src=\"/assets/images/icons/arrow-right-white.svg\" width=\"14\" height=\"14\" class=\"ms-1\" style=\"vertical-align:-0.1em\" alt=\"\" />\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<ng-template #loading>\r\n <div class=\"text-center p-5\">\r\n <div class=\"spinner-border text-primary\"></div>\r\n <p class=\"text-muted mt-2\">Loading data...</p>\r\n </div>\r\n</ng-template>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showCustomProfessionForm\" style=\"z-index: 9999999;\">\r\n <div class=\"confirm-modal-card add-profession-card\" style=\"max-width: 420px;\">\r\n <h4 class=\"mb-1\">Add New Profession</h4>\r\n <p class=\"text-muted small mb-4\">This profession isn't in the list yet. Add it here so you can link it to this\r\n {{ customProfessionContext }}.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Name <span class=\"text-danger\">*</span></label>\r\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"customProfessionName\" name=\"customProfessionName\"\r\n placeholder=\"Enter profession name\" />\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Group <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"add-profession-select\" [items]=\"professionGroupOptions\" [(ngModel)]=\"customProfessionGroup\" name=\"customProfessionGroup\"\r\n placeholder=\"Select group\" [clearable]=\"false\" [appendTo]=\"'body'\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Type <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"add-profession-select\" [items]=\"professionTypeOptions\" [(ngModel)]=\"customProfessionType\" name=\"customProfessionType\"\r\n placeholder=\"Select type\" [clearable]=\"false\" [appendTo]=\"'body'\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating</label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"setTempCustomProfessionStars(s)\" [attr.aria-label]=\"'Set rating ' + s\">\r\n <span [class]=\"customProfessionStars >= s ? 'text-warning fs-5' : 'text-muted fs-5'\">\r\n {{ customProfessionStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ customProfessionStars }}/5</span>\r\n </div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience</label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"customProfessionYear\" name=\"customProfessionYear\"\r\n min=\"0\" max=\"30\" placeholder=\"Years of Experience\" />\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelCustomProfessionForm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\" [disabled]=\"!canSaveCustomProfession || isSavingCustomProfession\"\r\n (click)=\"saveCustomProfession()\">\r\n <span *ngIf=\"isSavingCustomProfession\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingCustomProfession ? 'Saving...' : 'Add Profession' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBulkSkillConfirm\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 480px;\">\r\n <h4 class=\"mb-1\">Set Rating for All Skills</h4>\r\n <p class=\"text-muted small mb-4\">Enter a star rating and years of experience (and optionally a profession type) to apply to all skills that are missing these values.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Type</label>\r\n <ng-select [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"bulkSkillProfessionId\" (change)=\"onBulkSkillProfessionChange($event)\"\r\n name=\"bulkSkillProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"bulkSkillStars = s\">\r\n <span [class]=\"bulkSkillStars >= s ? 'text-warning fs-4' : 'text-muted fs-4'\">\r\n {{ bulkSkillStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ bulkSkillStars }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkSkillStars <= 0\">Star rating is required</div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"bulkSkillYear\" min=\"1\" max=\"30\"\r\n placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkSkillYear === null || bulkSkillYear === undefined\">Years of experience is required</div>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelBulkSkillConfirm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\"\r\n [disabled]=\"isSavingSkill || bulkSkillStars <= 0 || bulkSkillYear === null\"\r\n (click)=\"applyBulkSkillConfirm()\">\r\n <span *ngIf=\"isSavingSkill\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingSkill ? 'Saving...' : 'Apply to All & Save' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBulkToolConfirm\">\r\n <div class=\"confirm-modal-card\" style=\"max-width: 480px;\">\r\n <h4 class=\"mb-1\">Set Rating for All Tools</h4>\r\n <p class=\"text-muted small mb-4\">Enter a star rating and years of experience (and optionally a profession type) to apply to all tools that are missing these values.</p>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Profession Type</label>\r\n <ng-select [items]=\"userProfessionOptions\" bindLabel=\"professionName\" bindValue=\"professionId\"\r\n [ngModel]=\"bulkToolProfessionId\" (change)=\"onBulkToolProfessionChange($event)\"\r\n name=\"bulkToolProfessionType\" placeholder=\"Select or search profession type\" [clearable]=\"true\">\r\n </ng-select>\r\n </div>\r\n <div class=\"mb-3\">\r\n <label class=\"small text-muted d-block mb-1\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <div class=\"d-flex align-items-center gap-2\">\r\n <button *ngFor=\"let s of [1,2,3,4,5]\" type=\"button\" class=\"btn btn-link p-0 text-decoration-none\"\r\n (click)=\"bulkToolStars = s\">\r\n <span [class]=\"bulkToolStars >= s ? 'text-warning fs-4' : 'text-muted fs-4'\">\r\n {{ bulkToolStars >= s ? '\u2605' : '\u2606' }}\r\n </span>\r\n </button>\r\n <span class=\"small text-muted\">{{ bulkToolStars }}/5</span>\r\n </div>\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkToolStars <= 0\">Star rating is required</div>\r\n </div>\r\n <div class=\"mb-4\">\r\n <label class=\"small text-muted d-block mb-1\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <input type=\"number\" class=\"form-control\" [(ngModel)]=\"bulkToolYear\" min=\"1\" max=\"30\"\r\n placeholder=\"Years of Experience\" />\r\n <div class=\"small text-danger mt-1\" *ngIf=\"bulkToolYear === null || bulkToolYear === undefined\">Years of experience is required</div>\r\n </div>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"cancelBulkToolConfirm()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\"\r\n [disabled]=\"isSavingTool || bulkToolStars <= 0 || bulkToolYear === null\"\r\n (click)=\"applyBulkToolConfirm()\">\r\n <span *ngIf=\"isSavingTool\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingTool ? 'Saving...' : 'Apply to All & Save' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showBackConfirmPopup\">\r\n <div class=\"confirm-modal-card\">\r\n <h4 class=\"mb-2\">Leave this page?</h4>\r\n <p class=\"text-muted mb-4\">If you go back, only saved data will be retained.</p>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" (click)=\"stayOnPreview()\">Stay</button>\r\n <button type=\"button\" class=\"btn btn-danger h-auto\" (click)=\"proceedBack()\">Proceed Back</button>\r\n </div>\r\n </div>\r\n\r\n</div>\r\n\r\n<div class=\"modal-overlay\" *ngIf=\"showDashboardConfirmPopup\">\r\n <div class=\"confirm-modal-card\">\r\n <h4 class=\"mb-2\">Finish Setup and Continue</h4>\r\n <p class=\"text-muted mb-4\">Save your information and go to your dashboard</p>\r\n <div class=\"d-flex justify-content-end gap-2\">\r\n <button type=\"button\" class=\"btn btn-outline-secondary h-auto\" [disabled]=\"isSavingBasic\"\r\n (click)=\"cancelDashboardRedirect()\">Cancel</button>\r\n <button type=\"button\" class=\"btn btn-primary h-auto\" [disabled]=\"isSavingBasic\" (click)=\"goToDashboard()\">\r\n <span *ngIf=\"isSavingBasic\" class=\"spinner-border spinner-border-sm me-1\"></span>\r\n {{ isSavingBasic ? 'Proceeding...' : 'Proceed' }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [":host{color:#69707d}.res-flex:hover,.res-flex:focus,.res-flex:active{transform:none!important;box-shadow:none!important}::ng-deep .form-check-input{margin-left:unset!important}.profession-search-input{font-size:12px}.profession-search-input::placeholder{font-size:12px}.profession-row-selected{background-color:#f2f4fa}.profession-row-selected .profession-acc-header:hover{background-color:#eceffa}.profession-visibility-checkbox{all:revert;width:16px!important;height:16px!important;min-width:16px!important;max-width:16px!important;margin:4px auto 0!important;padding:0!important;position:static!important;float:none!important;vertical-align:middle!important;background-image:none!important;transform:none!important}.profession-accordion,.profession-accordion label.small{font-size:12px;color:#69707d}.profession-acc-columns,.profession-acc-header{display:grid;grid-template-columns:36px 2fr 1fr 1fr 32px;align-items:center;gap:12px}.profession-acc-columns{padding:12px 16px;border-bottom:1px solid #e9ecef;font-size:13px;font-weight:600;color:#69707d;text-transform:uppercase}@media (max-width: 767.98px){.profession-acc-columns{display:none}}.profession-acc-item{border-bottom:1px solid #f1f3f5}.profession-acc-item:last-child{border-bottom:none}.profession-acc-header{padding:12px 16px;cursor:pointer;transition:background-color .15s ease}.profession-acc-header:hover{background-color:#f8f9fb}.profession-acc-name{color:#69707d}.profession-acc-chevron-btn{background:transparent;border:none;padding:4px;display:inline-flex;align-items:center;justify-content:center;color:#69707d}.profession-acc-chevron{transition:transform .2s ease}.profession-acc-chevron--open{transform:rotate(180deg)}.profession-acc-body{padding:0 16px 16px}.profession-acc-panel{background-color:#fff;border:1px solid #e9ecef;border-radius:8px;padding:16px 20px}.profession-acc-fields{display:flex;flex-wrap:wrap;align-items:flex-start;gap:32px}.profession-acc-field{min-width:100px}.profession-acc-field--visibility{display:flex;flex-direction:column;align-items:center;width:90px;flex-shrink:0}.profession-acc-field--visibility label{text-align:center;width:100%}.profession-acc-field--notes{flex:1 1 220px;margin:0}.profession-acc-stars{font-size:1.05rem;letter-spacing:2px}.profession-acc-year-input{width:72px}.profession-inline-select{min-width:160px;font-size:12px}.profession-inline-select ::ng-deep .ng-select-container{min-height:32px!important;height:32px!important}::ng-deep .profession-inline-select .ng-option,::ng-deep .profession-inline-select .ng-placeholder{font-size:12px}.profession-notes-input{min-height:76px;resize:vertical}.container{max-width:900px;margin:30px auto;font-family:Arial,sans-serif;color:#69707d}.preview-page-header{max-width:900px;margin:50px auto 10px;padding:0 12px}.preview-title{font-size:18px;font-weight:700;color:#69707d;margin:0}.preview-subtitle{margin-top:7px;font-size:14px;color:#69707d}.preview-card-gradient h2,.section h5.fw-bold{font-size:18px}.section{margin-bottom:25px}.section-title{font-weight:600;display:block;margin-bottom:8px}.section-title .sub{font-weight:400;color:#777;font-size:13px}.dropdown-box{border:1px solid #ddd;border-radius:8px;padding:12px 15px;display:flex;justify-content:space-between;align-items:center}.icons{display:flex;gap:10px}.icon{cursor:pointer;font-size:14px;color:#777}.card{border:1px solid #ddd;border-radius:5px;padding:20px;background:#fff}.category{border-bottom:1px solid #eee;padding:15px 0}.category:last-child{border-bottom:none}.category-header{display:flex;justify-content:space-between;font-weight:600;margin-bottom:10px}.tags{display:flex;flex-wrap:wrap;gap:10px}.tag{background:#f2f4f7;padding:6px 12px;border-radius:6px;font-size:13px}.footer{text-align:center;margin-top:15px;color:#777;cursor:pointer}.actions{display:flex;justify-content:space-between;margin:50px 0 27px}.text-secondary{white-space:pre-line;font-size:12px;color:#69707d}.extra-small{font-size:.8rem}.card{transition:box-shadow .2s ease}.achievement-section .badge{font-size:.75rem;white-space:normal;text-align:left}.skill-tag .badge{font-weight:500;font-size:.9rem;transition:all .2s ease;cursor:default}.skill-tag .badge:hover{transform:translateY(-2px)}.skill-tag .btn-close{opacity:.5}.skill-tag .btn-close:hover{opacity:1}.bg-light.text-dark.border{background-color:#f8f9fa!important;border-color:#dee2e6!important}.card{transition:all .3s cubic-bezier(.25,.8,.25,1)}.card:hover .bg-light{background-color:#e8f5e9!important}.position-fixed .card:hover{transform:none!important}code{background-color:#f8f9fa;padding:2px 6px;border-radius:4px}.list-group-item{transition:background-color .2s ease-in-out}.list-group-item:hover{background-color:#fcfcfc}.border-dashed{border-style:dashed!important}.tool-card{transition:all .2s ease-in-out;border-radius:12px}.tool-card:hover{transform:translateY(-5px);border-color:var(--bs-primary)!important}.tool-card:hover .icon-box{background-color:var(--bs-primary-subtle)!important}.tool-card .icon-box{width:60px;height:60px;transition:background-color .2s ease}.border-dashed{border:2px dashed #dee2e6!important}.border-dashed:hover{border-color:var(--bs-primary)!important;background-color:#fff!important}.popup{position:fixed;top:20%;right:20px;width:320px;max-width:calc(100vw - 32px);background:#fff;border-radius:10px;padding:16px}.status-row{display:flex;justify-content:space-between;margin:10px 0}.success{color:#2e7d32;font-weight:700}.error{color:#d32f2f}.pending{color:#f9a825}.section-flag{font-weight:600}button.btn.btn-sm.btn-outline-primary{background-color:#4077ad;border-color:#4077ad;color:#fff;border-radius:5px!important}button.btn.btn-sm.btn-outline-primary:hover{background-color:#356895;border-color:#356895;color:#fff}button.btn.btn-sm.btn-outline-danger{border:1px solid #dc3545;color:#dc3545;border-radius:5px!important}button.btn.btn-sm.btn-outline-primary.rounded-circle{background-color:#4077ad;border-color:#4077ad;color:#fff;border-radius:5px!important}button.action-icon-btn{min-width:22px;width:22px;height:22px;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:5px!important;background:transparent!important;border:none!important;line-height:1}button.action-icon-btn.btn-outline-primary{color:#4077ad!important;border-color:#4077ad!important}button.action-icon-btn.btn-outline-danger{color:#dc3545!important}.action-icon-image{width:20px;height:20px;object-fit:contain;display:inline-block}.action-icon-image.edit-icon{filter:brightness(0) saturate(100%) invert(41%) sepia(39%) saturate(774%) hue-rotate(170deg) brightness(91%) contrast(89%)}.action-icon-image.delete-icon{filter:brightness(0) saturate(100%) invert(24%) sepia(79%) saturate(4008%) hue-rotate(344deg) brightness(91%) contrast(90%)}.modal-overlay{position:fixed;inset:0;background:#11182773;display:flex;align-items:center;justify-content:center;z-index:2500;padding:20px}.status-modal-card{width:min(760px,96vw);max-height:85vh;overflow:auto;background:#fff;border-radius:16px;border:1px solid #e5e7eb}.status-modal-header{padding:20px 24px 14px;border-bottom:1px solid #eef2f7}.status-modal-body{padding:12px 20px 20px}.status-modal-footer{padding:12px 20px 20px;border-top:1px solid #eef2f7;display:flex;justify-content:end;align-items:center;gap:12px}.status-modal-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:14px 10px;border-bottom:1px solid #f1f5f9}.status-modal-row:last-child{border-bottom:0}.status-modal-name{font-size:14px;font-weight:600;color:#69707d}.status-modal-state{font-size:.92rem;font-weight:600}.status-modal-state.pending{color:#a16207}.status-modal-state.success{color:#166534}.status-modal-state.partial{color:#b45309}.status-modal-state.error{color:#b91c1c}.confirm-modal-card{width:min(520px,96vw);max-height:85vh;overflow-y:auto;background:#fff;border-radius:5px;border:1px solid #e5e7eb;padding:24px}.year-experience-select{max-height:150px}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:220px;overflow-y:auto}@media screen and (max-width: 768px){.res-flex{flex-wrap:wrap!important;justify-content:center!important}.res-flex .fw-normal{width:100%;text-align:center;font-size:14px!important}.d-flex.flex-wrap.gap-2.p-3.bg-white.border.rounded.shadow-sm{justify-content:center}.preview-page-header{margin:20px auto 8px;padding:0 4px}.container{padding-left:4px;padding-right:4px}.preview-title{font-size:16px}.preview-subtitle{font-size:14px}.actions{margin:24px 0 16px}.section-header-title{flex-wrap:wrap}.section-header-title>.section-flag{flex-basis:53%}.section-header-row{align-items:flex-start}.preview-card-gradient{padding:14px 14px 12px}.preview-card-gradient h2{font-size:18px}.popup{width:calc(100vw - 40px);right:16px;top:12%}.card{padding:0}.card-body.p-4,.px-4.py-3{padding:12px!important}.row.g-4,.row.g-3{--bs-gutter-x: .75rem}.d-flex.gap-4{gap:10px!important}.preview-card-gradient>.d-flex.justify-content-between.align-items-start{flex-wrap:wrap;row-gap:8px}.preview-card-gradient>.d-flex.justify-content-between.align-items-start>.badge.bg-primary-subtle{margin-left:auto}}@media screen and (max-width: 575px){.preview-title{font-size:16px}.preview-subtitle{font-size:14px}.section>.d-flex{flex-wrap:wrap;row-gap:8px}.section>.d-flex>.d-flex:last-child{width:100%;justify-content:flex-end}}::ng-deep .bs-datepicker-head{background-color:#4077ad!important}::ng-deep .bs-datepicker-body table td span.selected,.bs-datepicker-body table td.selected span{background-color:#4077ad!important}.profile-avatar-circle{width:58px;height:58px;border-radius:5px;background:#4077ad;display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:700;color:#fff;letter-spacing:1px;flex-shrink:0}.section-header-icon{font-size:20px;line-height:1;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;opacity:.9;filter:invert(47%) sepia(8%) saturate(483%) hue-rotate(176deg) brightness(91%) contrast(87%)}.section-header-title h5.fw-bold{color:#69707d}.text-muted{color:#69707d!important}h6.text-uppercase.fw-bold.text-muted{font-size:14px;color:#69707d!important}.work-accent-item{border-radius:5px!important;transition:background-color .18s ease,box-shadow .18s ease}.work-accent-item:hover{background-color:#f5f8ff!important;box-shadow:0 4px 14px #4077ad17!important}.edu-accent-item{border-radius:5px!important;transition:background-color .18s ease,box-shadow .18s ease}.edu-accent-item:hover{background-color:#f8f8ff!important;box-shadow:0 4px 14px #6366f117!important}.cert-accent-item{border-radius:5px!important;transition:background-color .18s ease}.cert-accent-item:hover{background-color:#f0fdf4!important}.lic-accent-item{border-radius:5px!important;transition:background-color .18s ease}.lic-accent-item:hover{background-color:#fffbeb!important}.field-label-sm{font-size:14px;font-weight:700;color:#69707d;margin-bottom:3px;display:block}.item-name-text,.field-value-sm{font-size:12px;color:#69707d}.item-title-sm{font-size:14px;color:#69707d!important}.item-meta-line{display:block;font-size:12px;color:#69707d;margin-top:3px}.empty-state-wrap{text-align:center;padding:32px 20px;background:#fafbfc;border:1.5px dashed #d1d5db;border-radius:5px;cursor:pointer;transition:background-color .18s ease,border-color .18s ease}.empty-state-wrap .empty-icon{font-size:2rem;color:#d1d5db;margin-bottom:8px}.empty-state-wrap p{color:#9ca3af;margin:0;font-size:14px}.empty-state-wrap:hover{background:#f0f6ff;border-color:#4077ad}.form-panel{background:#fff;border:1px solid #e2e8f0;border-radius:5px;padding:20px}.form-panel .form-control,.form-panel .form-select{border-color:#d1d5db;border-radius:8px;font-size:12px}.form-panel .form-control:focus,.form-panel .form-select:focus{border-color:#4077ad;box-shadow:0 0 0 3px #4077ad1f}.section-header-bar{display:flex;align-items:center;justify-content:space-between;padding:10px 0 14px;border-bottom:2px solid #f1f5f9;margin-bottom:16px}.preview-card-gradient{background:linear-gradient(135deg,#fff,#eff6ff);border-bottom:1px solid #e2e8f0;padding:20px 24px 16px;border-radius:5px 5px 0 0}.profile-header-card{border:1px solid #e2e8f0!important}.item-icon-circle{width:40px;height:40px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;color:#fff;flex-shrink:0}.item-avatar--work{background:linear-gradient(135deg,#4077ad,#2d5a8a)}.item-avatar--edu{background:linear-gradient(135deg,#4077ad,#4338ca)}.provider-layout{display:flex;flex-direction:column}.provider-company-first{order:-1}.section-locked{pointer-events:none;opacity:.45;filter:blur(1.5px);-webkit-user-select:none;user-select:none}.btn.btn-primary{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important;padding:.375rem .75rem;line-height:1.5}.btn.btn-primary:hover:not(:disabled),.btn.btn-primary:focus:not(:disabled),.btn.btn-primary:active:not(:disabled){background-color:#356895!important;border-color:#356895!important;color:#fff!important}.btn.btn-success,.btn.btn-outline-success{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-success:hover:not(:disabled),.btn.btn-success:focus:not(:disabled),.btn.btn-success:active:not(:disabled),.btn.btn-outline-success:hover:not(:disabled),.btn.btn-outline-success:focus:not(:disabled),.btn.btn-outline-success:active:not(:disabled){background-color:#336843!important;border-color:#336843!important;color:#fff!important}.btn.btn-outline-secondary.rounded-pill{background-color:#69707d!important;border-color:#69707d!important;color:#fff!important;border-radius:5px!important}.btn.btn-outline-secondary.rounded-pill:hover:not(:disabled),.btn.btn-outline-secondary.rounded-pill:focus:not(:disabled),.btn.btn-outline-secondary.rounded-pill:active:not(:disabled){background-color:#565c66!important;border-color:#565c66!important;color:#fff!important}.preview-back-btn{background-color:#426c85!important;border-color:#426c85!important;color:#fff!important}.preview-dashboard-btn{background-color:#4077ad!important;border-color:#4077ad!important;color:#fff!important}.btn.btn-outline-success:hover:not(:disabled),.btn.btn-outline-success:focus:not(:disabled),.btn.btn-outline-success:active:not(:disabled){background-color:transparent!important;border-color:#198754!important;color:#198754!important}.btn.btn-outline-secondary:not(.rounded-pill){background-color:#d4dae6!important;border-color:#d4dae6!important;color:#69707d!important}.btn.btn-outline-secondary:not(.rounded-pill):hover:not(:disabled),.btn.btn-outline-secondary:not(.rounded-pill):focus:not(:disabled),.btn.btn-outline-secondary:not(.rounded-pill):active:not(:disabled){background-color:#c2cbde!important;border-color:#c2cbde!important;color:#69707d!important}.btn.btn-danger{background-color:#b43026!important;border-color:#b43026!important;color:#fff!important}.btn.btn-danger:hover:not(:disabled),.btn.btn-danger:focus:not(:disabled),.btn.btn-danger:active:not(:disabled){background-color:#96271f!important;border-color:#96271f!important;color:#fff!important}.btn.btn-outline-danger.rounded-circle{border-color:#b43026!important;color:#b43026!important;border-radius:5px!important}.btn.btn-outline-danger.rounded-circle:hover:not(:disabled),.btn.btn-outline-danger.rounded-circle:focus:not(:disabled),.btn.btn-outline-danger.rounded-circle:active:not(:disabled){border-color:#96271f!important;color:#b43026!important}.btn.btn-link.text-secondary{background-color:#d4dae6!important;border-color:#d4dae6!important;color:#69707d!important;text-decoration:none!important;border-radius:5px;padding:.375rem .75rem;line-height:1.5}.btn.btn-link.text-secondary:hover:not(:disabled),.btn.btn-link.text-secondary:focus:not(:disabled){background-color:#c2cbde!important;color:#69707d!important}.btn.btn-link.text-danger{background-color:#b43026!important;border-color:#b43026!important;color:#fff!important;text-decoration:none!important;border-radius:5px;padding:.375rem .75rem;line-height:1.5}.btn.btn-link.text-danger:hover:not(:disabled),.btn.btn-link.text-danger:focus:not(:disabled){background-color:#96271f!important;color:#fff!important}.btn{border-radius:5px!important;box-shadow:none!important}.badge.bg-warning-subtle.text-warning{background-color:#fff3cd!important;color:#664d03!important;border-color:#ffe69c!important}.badge.bg-success-subtle.text-success{background-color:#4077ad!important;color:#fff!important;border-color:#4077ad!important}.badge.bg-primary-subtle.text-primary{background-color:#e0edf2!important;color:#4077ad!important;border-color:#e0edf2!important}.update-profile-card label,.update-profile-card .form-control,.update-profile-card .form-select{font-size:12px}.update-profile-card .form-control::placeholder{font-size:12px}.update-profile-card ::ng-deep im-address-verify-field .form-control{font-size:12px}.add-profession-card label,.add-profession-card .form-control{font-size:12px}.add-profession-card .form-control::placeholder{font-size:12px}.add-profession-card .btn{font-size:14px}.add-profession-card ::ng-deep .add-profession-select .ng-select-container,.add-profession-card ::ng-deep .add-profession-select .ng-placeholder,.add-profession-card ::ng-deep .add-profession-select .ng-value-label{font-size:12px}::ng-deep .add-profession-select .ng-option,::ng-deep .add-profession-select .ng-placeholder{font-size:12px}\n"] }]
|
|
7412
7394
|
}], ctorParameters: () => [{ type: CredentialingStore }, { type: FileService }, { type: UserSkillSetService }, { type: UserToolService }, { type: ProfessionService }, { type: UserProfessionService }, { type: UserDocumentService }, { type: UserEducationService }, { type: UserDetailService }, { type: UserExperienceService }, { type: i1$4.TokenService }, { type: i1$4.RoleContextService }, { type: ProvidersService }, { type: FrontEndProvidersService }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
|
|
7413
7395
|
type: Inject,
|
|
7414
7396
|
args: [LIBRARY_CONFIG]
|
|
@@ -9531,8 +9513,8 @@ class SkillsComponent {
|
|
|
9531
9513
|
skillSetId: [skillSetId ?? null],
|
|
9532
9514
|
skillSetName: [skillName ?? null],
|
|
9533
9515
|
notes: [''],
|
|
9534
|
-
year: [null
|
|
9535
|
-
starRating: [null
|
|
9516
|
+
year: [null],
|
|
9517
|
+
starRating: [null],
|
|
9536
9518
|
profileVisibility: [false, Validators.required],
|
|
9537
9519
|
status: [RequestedStatus.InReview],
|
|
9538
9520
|
emailId: [this.user.email],
|
|
@@ -9873,7 +9855,11 @@ class SkillsComponent {
|
|
|
9873
9855
|
}
|
|
9874
9856
|
if (this.tab.invalid)
|
|
9875
9857
|
return;
|
|
9876
|
-
this.userSkillSetModels = this.tab.value
|
|
9858
|
+
this.userSkillSetModels = (this.tab.value || []).map((v) => ({
|
|
9859
|
+
...v,
|
|
9860
|
+
starRating: v.starRating ?? 0,
|
|
9861
|
+
year: v.year ?? 0,
|
|
9862
|
+
}));
|
|
9877
9863
|
if (this.model?.id) {
|
|
9878
9864
|
this.userSkillSetModels[0].id = this.model.id;
|
|
9879
9865
|
}
|
|
@@ -9960,7 +9946,7 @@ class SkillsComponent {
|
|
|
9960
9946
|
this.userSkillsSub?.unsubscribe();
|
|
9961
9947
|
}
|
|
9962
9948
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SkillsComponent, deps: [{ token: SkillSetService }, { token: UserSkillSetService }, { token: UserService }, { token: i7.UntypedFormBuilder }, { token: UtilsService }, { token: i1$4.RoleContextService }, { token: CredentialingStore }, { token: i1$4.TokenService }], target: i0.ɵɵFactoryTarget.Component });
|
|
9963
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: SkillsComponent, isStandalone: false, selector: "app-skills", inputs: { providerId: "providerId", providerName: "providerName" }, viewQueries: [{ propertyName: "skillDetailList", first: true, predicate: ["skillDetailList"], descendants: true }], ngImport: i0, template: "<!-- \u2500\u2500\u2500 Skills Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"skills-container\" *ngIf=\"store.stepView() === 'preview'\">\r\n <div class=\"preview-header\">\r\n <div class=\"preview-header-icon\">\r\n <img src=\"/assets/images/icons/stars.svg\" alt=\"skills\" width=\"20\" height=\"20\" />\r\n </div>\r\n <div>\r\n <h3 class=\"preview-header-title\">Skills</h3>\r\n <p class=\"preview-subtitle\">{{ userSkillsPreview.length }} skill{{ userSkillsPreview.length !== 1 ? 's' : '' }} added</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sk-grid\">\r\n <div *ngFor=\"let skill of userSkillsPreview; let i = index\" class=\"sk-card\">\r\n <div class=\"sk-card-body\">\r\n\r\n <div class=\"sk-head\">\r\n <div class=\"sk-avatar\">{{ (skill.skillSetName || '?').charAt(0).toUpperCase() }}</div>\r\n <div class=\"sk-title-block\">\r\n <span class=\"sk-name\">{{ skill.skillSetName }}</span>\r\n <span class=\"sk-sub\" *ngIf=\"skill.providerName\">{{ skill.providerName }}</span>\r\n </div>\r\n <div class=\"sk-top-actions\">\r\n <ng-container *ngIf=\"isEditMode && getSkillKey(model) === getSkillKey(skill)\">\r\n <button class=\"sk-text-btn cancel\" type=\"button\" (click)=\"backToSkill(null)\">Cancel</button>\r\n <button class=\"sk-text-btn save\" type=\"button\" (click)=\"saveUserSkillset()\" [disabled]=\"showLoader\">Update</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isEditMode || getSkillKey(model) !== getSkillKey(skill)\">\r\n <button class=\"icon-btn edit-btn\" (click)=\"editSkillFromPreview(skill, null, $event)\" title=\"Edit\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </button>\r\n <button class=\"icon-btn delete-btn\" (click)=\"deleteSkillFromPreview(skill, $event)\" title=\"Delete\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/></svg>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- View mode -->\r\n <ng-container *ngIf=\"!isEditMode || getSkillKey(model) !== getSkillKey(skill)\">\r\n <div class=\"detail-row\">\r\n <div class=\"detail-item\" *ngIf=\"skill.year\">\r\n <span class=\"detail-label\">Years of Experience</span>\r\n <span class=\"detail-value\">{{ skill.year }} yr(s)</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"skill.profileVisibility\">\r\n <span class=\"detail-label\">Visibility</span>\r\n <span class=\"detail-value\">Visible</span>\r\n </div>\r\n </div>\r\n <div class=\"sk-stars-row stars-readonly\">\r\n <ngx-stars [initialStars]=\"skill.starRating/2\" [maxStars]=\"5\"></ngx-stars>\r\n </div>\r\n <p class=\"sk-description\" *ngIf=\"skill.notes\">{{ skill.notes }}</p>\r\n </ng-container>\r\n\r\n <!-- Edit mode (inline) -->\r\n <div *ngIf=\"isEditMode && getSkillKey(model) === getSkillKey(skill)\"\r\n [formGroup]=\"tab.at(0)\" class=\"sk-edit-panel\">\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Self Ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars *ngIf=\"tab.at(0)?.get('starRating')?.value !== null\"\r\n [key]=\"tab.at(0).get('starRating')?.value\"\r\n [initialStars]=\"(tab.at(0).get('starRating')?.value || 0) / 2\"\r\n [maxStars]=\"5\"\r\n (ratingOutput)=\"onEditRating($event)\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" [searchable]=\"false\" [clearable]=\"false\"\r\n bindLabel=\"text\" formControlName=\"year\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.year?.errors }\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\"></ng-select>\r\n </div>\r\n <div class=\"sk-edit-field sk-toggle-field\">\r\n <label class=\"sk-label\">Visible</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-field sk-edit-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea class=\"form-control\" rows=\"2\" formControlName=\"notes\" placeholder=\"Enter notes\"></textarea>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \u2500\u2500\u2500 Skills Add \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"skills-container\" *ngIf=\"store.stepView() === 'add'\">\r\n <div class=\"step-card-header mb-4\" style=\"border-radius: 10px;\">\r\n <div class=\"step-card-header-icon\">\r\n <img src=\"/assets/images/icons/stars.svg\" alt=\"skills\" width=\"22\" height=\"22\" />\r\n </div>\r\n <div>\r\n <h3 class=\"step-card-title\">Add Skills</h3>\r\n <p class=\"step-card-subtitle\">Select your skill areas and rate your proficiency</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Step 1: Select skills -->\r\n <div class=\"sk-section\">\r\n <div class=\"sk-select-row\">\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Profession</label>\r\n <ng-select\r\n [items]=\"professions\"\r\n bindLabel=\"professionName\"\r\n bindValue=\"id\"\r\n [(ngModel)]=\"selectedProfessionValue\"\r\n placeholder=\"Select Profession\"\r\n [clearable]=\"true\"\r\n (change)=\"onProfessionChange($event)\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Skill</label>\r\n <div class=\"search-part\">\r\n <input type=\"text\" placeholder=\"Search / Add Skillsets here\" [(ngModel)]=\"searchSkillQry\"\r\n (input)=\"getSkillSets()\" />\r\n <button class=\"btn\" (click)=\"createNewSkills()\" tooltip=\"Add Skillset\">\r\n <img src=\"/assets/images/icons/plus.svg\" alt=\"add\" class=\"create-plus\" width=\"18\" height=\"18\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"errMsg\" class=\"invalid-feedback is-invalid d-block\">Please Enter Skillsets Name</div>\r\n <div *ngIf=\"nameError\" class=\"invalid-feedback is-invalid d-block\">{{ nameError }}</div>\r\n <div class=\"skill-chips-wrapper\" [ngClass]=\"showLoading && !isEditMode ? 'loader' : ''\"\r\n [class.chips-collapsed]=\"!showAllSkills\">\r\n <div class=\"skill-chips\" [class.collapsed]=\"!showAllSkills\"\r\n [ngStyle]=\"showLoader && !isEditMode ? {'min-height': '120px'} : {}\">\r\n <label class=\"skill-chip\" *ngFor=\"let skill of skillSets\"\r\n [class.selected]=\"skill.selected\"\r\n [attr.for]=\"skill.id\"\r\n (mouseenter)=\"onSkillChipEnter($event, skill)\"\r\n (mouseleave)=\"onSkillChipLeave()\">\r\n <input type=\"checkbox\" [checked]=\"skill.selected\"\r\n (change)=\"onSelectedSkillsets($event, skill)\"\r\n [id]=\"skill.id\" [name]=\"skill.id\" />\r\n <svg *ngIf=\"skill.selected\" class=\"chip-check-icon\" width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n {{ skill.name }}\r\n <div class=\"chip-popover\" *ngIf=\"hoveredSkill === skill\"\r\n [style.top.px]=\"chipPopoverTop\" [style.left.px]=\"chipPopoverLeft\"\r\n (click)=\"$event.preventDefault(); $event.stopPropagation()\">\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionName\">\r\n <span class=\"chip-popover-label\">Profession Name</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionName }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionGroup\">\r\n <span class=\"chip-popover-label\">Profession Group</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionGroup }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.residentialCommercial\">\r\n <span class=\"chip-popover-label\">Residential / Commercial</span>\r\n <span class=\"chip-popover-value\">{{ skill.residentialCommercial }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionDescription\">\r\n <span class=\"chip-popover-label\">profession Description</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionDescription }}</span>\r\n </div>\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n <button *ngIf=\"!showLoading && skillSets.length > 0\" type=\"button\"\r\n class=\"show-more-btn\" (click)=\"showAllSkills = !showAllSkills\">\r\n {{ showAllSkills ? 'Show Less' : 'Show More' }}\r\n <svg [class.rotated]=\"showAllSkills\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Step 2: Per-skill detail cards (replaces tabset) -->\r\n <div class=\"sk-detail-list\" #skillDetailList\r\n *ngIf=\"tab.controls.length > 0\"\r\n [ngClass]=\"{ 'loader': showLoading && !isEditMode, 'edit-mode': isEditMode }\">\r\n <div class=\"sk-detail-list-header\">\r\n <span class=\"sk-section-label\">Skill Details</span>\r\n <span class=\"sk-count-badge\">{{ tab.controls.length }} selected</span>\r\n </div>\r\n\r\n <div *ngFor=\"let group of tab.controls; let index = index\"\r\n [formGroup]=\"group\" class=\"sk-detail-card\">\r\n <div class=\"sk-detail-card-hd\">\r\n <div class=\"sk-detail-avatar\">{{ (tabs[index] || '?').charAt(0).toUpperCase() }}</div>\r\n <span class=\"sk-detail-card-name\">{{ tabs[index] }}</span>\r\n <div class=\"sk-detail-card-actions\">\r\n <label class=\"sk-copy-toggle\" *ngIf=\"tab.controls.length > 1 && index === 0\" title=\"Copy these values to all skills\">\r\n <input type=\"checkbox\" class=\"form-check-input\"\r\n (click)=\"setCopyToAllTabs(index, group.value)\" role=\"switch\" />\r\n Copy to all\r\n </label>\r\n <button *ngIf=\"!isEditMode\" class=\"icon-btn delete-btn\" type=\"button\"\r\n (click)=\"removeTab(index, group.controls.skillSetId.value)\" title=\"Remove\">\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6L6 18M6 6l12 12\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"sk-detail-fields\">\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Self Ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars [initialStars]=\"initialStarts\" (ratingOutput)=\"onRatingSet($event, index)\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.starRating?.errors }\" [maxStars]=\"5\">\r\n </ngx-stars>\r\n <div *ngIf=\"userSkillSubmitted && k?.starRating?.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Rating is required\r\n </div>\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" [searchable]=\"false\" [clearable]=\"false\"\r\n bindLabel=\"text\" formControlName=\"year\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.year?.errors }\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\" (change)=\"onYearChange(group)\"></ng-select>\r\n <div *ngIf=\"userSkillSubmitted && k?.year?.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Year is required\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-toggle-field\">\r\n <label class=\"sk-label\">Profile Visibility</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-field-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea placeholder=\"Describe your skill...\" formControlName=\"notes\" class=\"form-control\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.notes?.errors }\" rows=\"2\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Add mode -->\r\n<div *ngIf=\"store.stepView() === 'add'\" class=\"skills-container last footer-actions\">\r\n <button class=\"back-btn\" (click)=\"userSkillsPreview.length > 0 ? cancel() : back()\">\r\n <svg *ngIf=\"userSkillsPreview.length > 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\r\n <svg *ngIf=\"userSkillsPreview.length === 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n {{ userSkillsPreview.length > 0 ? 'Cancel' : 'Back' }}\r\n </button>\r\n <div class=\"mb-res\">\r\n <button class=\"back-btn me-3\" *ngIf=\"userSkillsPreview.length === 0\" (click)=\"next()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n Skip\r\n </button>\r\n <button class=\"continue-btn\" (click)=\"onContinue()\" [disabled]=\"showLoader\" [ng2-loading]=\"showLoader\">\r\n Continue\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Preview mode -->\r\n<div *ngIf=\"store.stepView() !== 'add'\" class=\"skills-container last footer-actions\">\r\n <button class=\"back-btn\" (click)=\"back()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n Back\r\n </button>\r\n <div class=\"mb-res\">\r\n <button class=\"continue-btn add me-3\" *ngIf=\"store.stepView() === 'preview'\" (click)=\"goToAddSkillsMode()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add More Skills\r\n </button>\r\n <button class=\"continue-btn\" (click)=\"onContinue()\" [disabled]=\"showLoader\" [ng2-loading]=\"showLoader\">\r\n Continue\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".skills-container{max-width:1000px;margin:0 auto;padding:28px 24px;min-height:300px;background:#fff}.skills-container.last{min-height:unset}.title{font-size:20px;font-weight:700;color:#1e293b;margin-bottom:4px}.subtitle{font-size:14px;color:#69707d;margin-bottom:24px}.content-part{background:#fff}.content-part p{font-size:13px;color:#69707d}.content-part div{font-size:13px}.content-part .card{margin-top:15px;background:#fff;border:1px solid #e2e8f0;border-radius:12px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.content-part .card .row{margin-top:-15px}.content-part .card .sub-section{padding:0 10px}.content-part .card .sub-section .title{font-size:15px;font-weight:500;color:#1e293b}.content-part .card .sub-section .info-title{font-size:12px;font-weight:400;color:#69707d;margin-left:5px}.content-part .card .sub-section .content{font-size:13px;color:#69707d}.content-part .card .sub-section .subsection{font-weight:600;padding-top:10px;font-size:12px;color:#69707d}.content-part .card .sub-section .subsection input{width:30%}.content-part .card .sub-section .icon{width:35px;filter:opacity(.5)}.content-part .tab-card{background:#fff;border:1px solid #e2e8f0;border-radius:8px;color:#1e293b;margin-top:15px}.content-part .tab-card .row{margin-top:2px}.search-part{width:100%;position:relative;border-radius:8px;border:1.5px solid #e2e8f0;padding:0 0 0 14px;display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;height:42px;background:#f9fafb;transition:all .2s ease}.search-part:focus-within{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.search-part input{width:auto;flex:1;color:#1e293b;font-size:14px;font-weight:400;border:none;background:none;outline:none}.search-part input::placeholder{color:#69707d}.search-part .btn{background:#4077ad;border-radius:5px;padding:0;width:42px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:0;border:none;cursor:pointer;transition:all .2s ease}.search-part .btn:hover{background:#2d5a8a}.search-part .btn img{filter:brightness(0) invert(1);width:16px;height:16px}textarea{width:100%;height:100px;min-height:96px;background:#f9fafb;border:1.5px solid #e2e8f0;border-radius:8px;padding:12px 14px;font-size:14px;color:#1e293b;resize:vertical;outline:none;transition:all .2s ease}textarea:focus{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.skill-chips-wrapper{margin:8px 0 4px;position:relative;max-height:300px;overflow-y:auto}.skill-chips-wrapper.chips-collapsed:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:52px;background:linear-gradient(to bottom,transparent,#ffffff);pointer-events:none}.skill-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.skill-chips.collapsed{max-height:190px;overflow:hidden}.show-more-btn{display:inline-flex;align-items:center;gap:5px;background:none;border:1.5px solid #e2e8f0;border-radius:5px;color:#4077ad;font-size:14px;font-weight:600;padding:5px 14px;cursor:pointer;transition:all .2s ease;margin-bottom:12px}.show-more-btn:hover{background:#ebf2f9;border-color:#4077ad}.show-more-btn svg{transition:transform .2s ease}.show-more-btn svg.rotated{transform:rotate(180deg)}.skill-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:12px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4;position:relative}.skill-chip input[type=checkbox]{display:none}.skill-chip .chip-check-icon{flex-shrink:0}.skill-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.skill-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.skill-chip .chip-popover{position:fixed;transform:translate(-50%,-100%);background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;padding:10px 14px;min-width:220px;max-width:300px;z-index:99999;text-align:left;pointer-events:none;white-space:normal}.skill-chip .chip-popover:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:7px solid transparent;border-top-color:#e2e8f0}.skill-chip .chip-popover:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:-1px;border:6px solid transparent;border-top-color:#fff;z-index:1}.chip-popover-row{display:flex;flex-direction:column;gap:2px;padding:5px 0;border-bottom:1px solid #e2e8f0}.chip-popover-row:last-child{border-bottom:none;padding-bottom:0}.chip-popover-row:first-child{padding-top:0}.chip-popover-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#69707d;line-height:1.3}.chip-popover-value{font-size:12px;font-weight:500;color:#1e293b;line-height:1.45;word-break:break-word}.form-check-input{width:43px;height:21px;margin:0 5px;background-color:#c7c7c7!important;background-image:url(/assets/images/icons/toogle-circle.svg);background-position:left 4px top 2px;background-size:15px;border:1px solid #c7c7c7;outline:none!important;box-shadow:none!important;border-radius:25px;cursor:pointer}.form-check-input:checked{background-position:right 4px top 2px;background-image:url(/assets/images/icons/toogle-circle.svg);background-color:#22c55e!important;border:1px solid #22c55e!important}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:210px}::ng-deep .ng-select .ng-select-container{min-height:42px;border:1.5px solid #e2e8f0;border-radius:8px;background:#f9fafb;font-size:14px;color:#1e293b;transition:all .2s ease}::ng-deep .ng-select .ng-select-container .ng-value-container{padding-left:14px}::ng-deep .ng-select.ng-select-opened>.ng-select-container{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .ng-select.ng-select-focused .ng-select-container{border-color:#4077ad;box-shadow:0 0 0 3px #4077ad1f}.label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em;padding-bottom:6px;display:block;margin-bottom:2px}.form-control{color:#1e293b;background:#f9fafb!important;min-height:36px;font-size:14px;height:42px;border:1.5px solid #e2e8f0;border-radius:8px;transition:all .2s ease}.form-control:focus{border-color:#4077ad;background:#fff!important;box-shadow:0 0 0 3px #4077ad1f!important}.form-control:focus{border:1.5px solid #4077AD;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .nav-link{color:#69707d!important}::ng-deep .nav-link.active{color:#4077ad!important;font-weight:600}.loader{filter:blur(3px);height:40px}.edit-mode ::ng-deep .nav-tabs{display:none!important}::ng-deep accordion-group+accordion-group{margin-top:20px}.close-popup{position:absolute;right:7px;top:4px;width:25px;cursor:pointer;opacity:.6;transition:all .2s ease}.close-popup:hover{opacity:1}.back-btn,.skip-btn{height:42px;min-width:130px;background:#69707d;color:#fff;border:1.5px solid #69707D;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.back-btn:hover,.skip-btn:hover{border-color:#565c66;color:#fff;background:#565c66}.back-btn.edit,.skip-btn.edit{padding:5px 15px;min-height:20px;min-width:auto}.mb-res .back-btn{background:#f2f4fa;color:#69707d;border:1.5px solid #F2F4FA}.mb-res .back-btn:hover{background:#e4e8f2;border-color:#e4e8f2;color:#69707d}.save-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease;margin-left:15px}.save-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.save-btn:active{transform:translateY(0)}.save-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.create-btn{height:42px;min-width:9rem;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.create-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.create-btn:active{transform:translateY(0)}.continue-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.continue-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.continue-btn:active{transform:translateY(0)}.continue-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.continue-btn.edit{padding:5px 15px;min-height:20px;min-width:auto}.continue-btn.add{background:#f2f4fa;color:#69707d}.continue-btn.add:hover{background:#e4e8f2}.footer-actions{display:flex;justify-content:space-between;align-items:center;margin-top:64px}.preview-header{display:flex;align-items:center;gap:14px;margin-bottom:24px;padding-bottom:18px;border-bottom:1px solid #e2e8f0}.preview-header-icon{width:42px;height:42px;background:#ebf2f9;border-radius:10px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.preview-header-title{font-size:18px;font-weight:700;color:#1e293b;margin:0 0 2px}.preview-subtitle{font-size:12px;color:#69707d;margin:0}.sk-grid{display:grid;gap:14px;margin-bottom:24px}.sk-card{display:flex;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;transition:box-shadow .18s ease,transform .18s ease}.sk-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;transform:translateY(-1px)}.sk-card-body{flex:1;padding:14px 16px;min-width:0}.sk-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}.sk-avatar{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#4077ad,#2d5a8a);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;flex-shrink:0}.sk-title-block{flex:1;min-width:0}.sk-name{display:block;font-size:16px;font-weight:700;color:#4077ad;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-sub{display:block;font-size:12px;color:#69707d;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-top-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.sk-text-btn{height:28px;padding:0 12px;border-radius:5px;font-size:12px;font-weight:600;cursor:pointer;border:none;transition:all .2s ease}.sk-text-btn.cancel{background:#d4dae6;color:#69707d;border:1px solid #D4DAE6}.sk-text-btn.cancel:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.sk-text-btn.save{background:#4077ad;color:#fff;margin-left:4px}.sk-text-btn.save:hover{background:#2d5a8a}.sk-text-btn.save:disabled{background:#69707d;cursor:not-allowed}.icon-btn{width:28px;height:28px;border:none;min-width:unset!important;border-radius:5px;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.icon-btn.edit-btn{color:#4077ad}.icon-btn.edit-btn:hover{background:#ebf2f9}.icon-btn.delete-btn{color:#ef4444}.icon-btn.delete-btn:hover{background:#fef2f2}.sk-meta-row{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.chip.chip-year{background:#ebf2f9;color:#4077ad}.chip.chip-visible{background:#f0fdf4;color:#15803d}.chip.chip-make{background:#fff7ed;color:#c2410c}.chip.chip-model{background:#f5f3ff;color:#6d28d9}.chip.chip-serial{background:#f8fafc;color:#69707d;font-family:monospace;font-size:11px}.sk-stars-row{margin-bottom:6px}.sk-description{font-size:12px;color:#69707d;line-height:1.55;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.sk-edit-panel{margin-top:10px;padding-top:10px;border-top:1px solid #e2e8f0}.sk-edit-row{display:grid;grid-template-columns:1fr 1fr auto;gap:12px;margin-bottom:10px}.sk-edit-field{display:flex;flex-direction:column;gap:4px}.sk-edit-full{grid-column:1/-1;margin-top:4px}.sk-toggle-field{align-items:center;justify-content:center}.sk-label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em}.sk-section{margin-bottom:20px}.sk-select-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px}.sk-select-col{display:flex;flex-direction:column;gap:6px}.sk-select-col .search-part{margin-bottom:0}.sk-section-label{font-size:12px;font-weight:700;color:#1e293b;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;display:block}.sk-detail-list{display:flex;flex-direction:column;gap:12px;margin-top:8px}.sk-detail-list-header{display:flex;align-items:center;gap:10px;margin-bottom:4px}.sk-count-badge{display:inline-flex;align-items:center;padding:2px 8px;background:#ebf2f9;color:#4077ad;border-radius:20px;font-size:12px;font-weight:600}.sk-detail-card{border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden}.sk-detail-card-hd{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#ebf2f9;border-bottom:1px solid #e2e8f0}.sk-detail-avatar{width:32px;height:32px;border-radius:8px;background:#4077ad;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;flex-shrink:0}.sk-detail-card-name{flex:1;font-size:14px;font-weight:700;color:#4077ad;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-detail-card-actions{display:flex;align-items:center;gap:10px;flex-shrink:0}.sk-copy-toggle{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:#69707d;cursor:pointer;-webkit-user-select:none;user-select:none}.sk-detail-fields{padding:14px 16px}.sk-fields-row{display:grid;grid-template-columns:1fr 1fr auto;gap:14px;margin-bottom:12px}.sk-field{display:flex;flex-direction:column;gap:4px}.sk-field-full{grid-column:1/-1}.skill-preview-wrapper{margin-bottom:24px}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;margin-bottom:12px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden;transition:box-shadow .35s ease,transform .25s ease,border-color .25s ease}.skill-preview-wrapper{display:flex;flex-direction:column;gap:16px;margin-bottom:32px}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;background:#fff;transition:box-shadow .25s ease}.skill-preview-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a}.skill-preview-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:#fff;font-size:15px;font-weight:700;color:#1e293b;border-bottom:1px solid transparent;cursor:pointer}.skill-preview-header.open{background:#ebf2f9;color:#2d5a8a;border-bottom:1px solid #e2e8f0}.skill-preview-body{padding:0;background:#fff}.skill-preview-body>div{padding:16px 20px;border-bottom:1px solid #e2e8f0}.skill-preview-body>div:last-child{border-bottom:none}.skill-preview-body label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.skill-preview-body p{margin:0;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5}h5.title{font-size:22px;font-weight:700;color:#1e293b!important;margin-bottom:4px}.preview-detail-grid,.preview-edit-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0}.preview-cell{padding:14px 20px;border-bottom:1px solid #e2e8f0;border-right:1px solid #e2e8f0}.preview-cell:nth-child(3n){border-right:none}.preview-full{grid-column:1/-1;border-right:none;border-bottom:none}.preview-label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.preview-value{display:block;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word;min-height:21px}.stars-readonly{pointer-events:none;display:block}.icon-color{cursor:pointer;width:20px;height:20px;background:transparent;transition:transform .3s ease;filter:brightness(0) saturate(100%) invert(48%) sepia(8%) saturate(350%) hue-rotate(170deg) brightness(92%) contrast(88%)}.icon-color.edit{width:18px;height:18px}.rotate{transform:rotate(-180deg)}.step-card{max-width:1000px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 1px 3px #0000000f,0 4px 16px #4077ad14}.step-card-header{display:flex;align-items:center;gap:16px;padding:20px 28px;background:linear-gradient(135deg,#ebf2f9,#f0f6ff);border-bottom:1px solid #d5e8f5;border-radius:12px 12px 0 0}.step-card-header-icon{width:46px;height:46px;background:#fff;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px #4077ad2e;flex-shrink:0}.step-card-header-icon img{filter:brightness(0) saturate(100%) invert(37%) sepia(55%) saturate(500%) hue-rotate(190deg) brightness(95%) contrast(85%);width:22px;height:22px}.step-card-title{font-size:16px;font-weight:700;color:#1e293b;margin:0 0 3px;letter-spacing:-.01em}.step-card-subtitle{font-size:14px;color:#69707d;margin:0;line-height:1.4}.step-card-body{padding:24px 28px 8px}.field-section{margin-bottom:18px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px 6px}.field-section-title{font-size:12px;font-weight:700;color:#4077ad;text-transform:uppercase;letter-spacing:.07em;margin-bottom:14px;display:flex;align-items:center;gap:7px}.field-section-title:before{content:\"\";display:inline-block;width:5px;height:5px;background:#4077ad;border-radius:50%;flex-shrink:0}.doc-type-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.doc-type-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:13px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4}.doc-type-chip input[type=checkbox]{display:none}.doc-type-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.doc-type-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.detail-row{display:flex;flex-wrap:wrap;column-gap:22px;row-gap:6px;margin-bottom:8px}.detail-item{display:flex;align-items:baseline;gap:6px;white-space:nowrap}.detail-label{font-size:14px;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:#4077ad}.detail-value{font-size:12.5px;font-weight:600;color:#1e293b}button.primary,button.secondary,button.back-btn,button.continue-btn,button.save-btn,button.add-btn,button.upload-btn,.actions button,.action button,.navigation-buttons button{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-radius:5px;box-shadow:none}button.primary svg,button.secondary svg,button.back-btn svg,button.continue-btn svg,button.save-btn svg,button.add-btn svg,button.upload-btn svg,.actions button svg,.action button svg,.navigation-buttons button svg{flex-shrink:0;width:14px;height:14px}.step-toast{position:fixed;bottom:28px;right:28px;display:flex;align-items:flex-start;gap:14px;background:#fff;border-radius:12px;padding:16px 20px 20px;box-shadow:0 8px 32px #00000024;z-index:9999;min-width:290px;max-width:360px;animation:toastSlideIn .32s cubic-bezier(.34,1.56,.64,1);overflow:hidden}@keyframes toastSlideIn{0%{transform:translate(110%);opacity:0}to{transform:translate(0);opacity:1}}.step-toast-icon{width:34px;height:34px;background:#dcfce7;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;color:#16a34a}.step-toast-body{flex:1}.step-toast-title{font-size:14px;font-weight:700;color:#1e293b;margin-bottom:2px}.step-toast-msg{font-size:12px;color:#69707d;line-height:1.4}.step-toast-progress{position:absolute;bottom:0;left:0;height:3px;background:#22c55e;border-radius:0 2px 2px 0;animation:toastProgress 3.5s linear forwards}@keyframes toastProgress{0%{width:100%}to{width:0%}}@media screen and (max-width: 767px){.step-card-header{padding:14px 16px}.step-card-body{padding:16px 16px 8px}.step-toast{right:12px;bottom:16px;min-width:calc(100vw - 24px);max-width:calc(100vw - 24px)}}@media screen and (max-width: 767px){.skills-container{padding:16px}.title,h5.title{font-size:18px}.form-control,textarea{font-size:16px}.footer-actions{flex-direction:column-reverse;gap:8px;margin-top:48px}.back-btn,.skip-btn{width:100%}.continue-btn{padding:10px 22px;width:100%}.mb-res{display:flex;flex-direction:column-reverse;gap:8px;width:100%}.preview-detail-grid,.preview-edit-grid{grid-template-columns:1fr}.preview-cell{border-right:none}.sk-grid,.sk-edit-row,.sk-fields-row,.sk-select-row{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i7.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: i7.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i7.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i7.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i12.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: Ng2LoadingSpinnerDirective, selector: "[ng2-loading]", inputs: ["ng2-loading", "config", "template"] }, { kind: "component", type: NgxStarsComponent, selector: "ngx-stars", inputs: ["maxStars", "initialStars", "readonly", "size", "color", "animation", "animationSpeed", "customPadding", "wholeStars", "customStarIcons"], outputs: ["ratingOutput"] }, { kind: "directive", type: i14.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }], animations: [
|
|
9949
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: SkillsComponent, isStandalone: false, selector: "app-skills", inputs: { providerId: "providerId", providerName: "providerName" }, viewQueries: [{ propertyName: "skillDetailList", first: true, predicate: ["skillDetailList"], descendants: true }], ngImport: i0, template: "<!-- \u2500\u2500\u2500 Skills Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"skills-container\" *ngIf=\"store.stepView() === 'preview'\">\r\n <div class=\"preview-header\">\r\n <div class=\"preview-header-icon\">\r\n <img src=\"/assets/images/icons/stars.svg\" alt=\"skills\" width=\"20\" height=\"20\" />\r\n </div>\r\n <div>\r\n <h3 class=\"preview-header-title\">Skills</h3>\r\n <p class=\"preview-subtitle\">{{ userSkillsPreview.length }} skill{{ userSkillsPreview.length !== 1 ? 's' : '' }} added</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sk-grid\">\r\n <div *ngFor=\"let skill of userSkillsPreview; let i = index\" class=\"sk-card\">\r\n <div class=\"sk-card-body\">\r\n\r\n <div class=\"sk-head\">\r\n <div class=\"sk-avatar\">{{ (skill.skillSetName || '?').charAt(0).toUpperCase() }}</div>\r\n <div class=\"sk-title-block\">\r\n <span class=\"sk-name\">{{ skill.skillSetName }}</span>\r\n <span class=\"sk-sub\" *ngIf=\"skill.providerName\">{{ skill.providerName }}</span>\r\n </div>\r\n <div class=\"sk-top-actions\">\r\n <ng-container *ngIf=\"isEditMode && getSkillKey(model) === getSkillKey(skill)\">\r\n <button class=\"sk-text-btn cancel\" type=\"button\" (click)=\"backToSkill(null)\">Cancel</button>\r\n <button class=\"sk-text-btn save\" type=\"button\" (click)=\"saveUserSkillset()\" [disabled]=\"showLoader\">Update</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isEditMode || getSkillKey(model) !== getSkillKey(skill)\">\r\n <button class=\"icon-btn edit-btn\" (click)=\"editSkillFromPreview(skill, null, $event)\" title=\"Edit\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </button>\r\n <button class=\"icon-btn delete-btn\" (click)=\"deleteSkillFromPreview(skill, $event)\" title=\"Delete\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/></svg>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- View mode -->\r\n <ng-container *ngIf=\"!isEditMode || getSkillKey(model) !== getSkillKey(skill)\">\r\n <div class=\"detail-row\">\r\n <div class=\"detail-item\" *ngIf=\"skill.year\">\r\n <span class=\"detail-label\">Years of Experience</span>\r\n <span class=\"detail-value\">{{ skill.year }} yr(s)</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"skill.profileVisibility\">\r\n <span class=\"detail-label\">Visibility</span>\r\n <span class=\"detail-value\">Visible</span>\r\n </div>\r\n </div>\r\n <div class=\"sk-stars-row stars-readonly\">\r\n <ngx-stars [initialStars]=\"skill.starRating/2\" [maxStars]=\"5\"></ngx-stars>\r\n </div>\r\n <p class=\"sk-description\" *ngIf=\"skill.notes\">{{ skill.notes }}</p>\r\n </ng-container>\r\n\r\n <!-- Edit mode (inline) -->\r\n <div *ngIf=\"isEditMode && getSkillKey(model) === getSkillKey(skill)\"\r\n [formGroup]=\"tab.at(0)\" class=\"sk-edit-panel\">\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Self Ability Rating</label>\r\n <ngx-stars *ngIf=\"tab.at(0)?.get('starRating')?.value !== null\"\r\n [key]=\"tab.at(0).get('starRating')?.value\"\r\n [initialStars]=\"(tab.at(0).get('starRating')?.value || 0) / 2\"\r\n [maxStars]=\"5\"\r\n (ratingOutput)=\"onEditRating($event)\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Years of Experience</label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" [searchable]=\"false\" [clearable]=\"false\"\r\n bindLabel=\"text\" formControlName=\"year\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\"></ng-select>\r\n </div>\r\n <div class=\"sk-edit-field sk-toggle-field\">\r\n <label class=\"sk-label\">Visible</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-field sk-edit-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea class=\"form-control\" rows=\"2\" formControlName=\"notes\" placeholder=\"Enter notes\"></textarea>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \u2500\u2500\u2500 Skills Add \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"skills-container\" *ngIf=\"store.stepView() === 'add'\">\r\n <div class=\"step-card-header mb-4\" style=\"border-radius: 10px;\">\r\n <div class=\"step-card-header-icon\">\r\n <img src=\"/assets/images/icons/stars.svg\" alt=\"skills\" width=\"22\" height=\"22\" />\r\n </div>\r\n <div>\r\n <h3 class=\"step-card-title\">Add Skills</h3>\r\n <p class=\"step-card-subtitle\">Select your skill areas and rate your proficiency</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Step 1: Select skills -->\r\n <div class=\"sk-section\">\r\n <div class=\"sk-select-row\">\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Profession</label>\r\n <ng-select\r\n [items]=\"professions\"\r\n bindLabel=\"professionName\"\r\n bindValue=\"id\"\r\n [(ngModel)]=\"selectedProfessionValue\"\r\n placeholder=\"Select Profession\"\r\n [clearable]=\"true\"\r\n (change)=\"onProfessionChange($event)\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Skill</label>\r\n <div class=\"search-part\">\r\n <input type=\"text\" placeholder=\"Search / Add Skillsets here\" [(ngModel)]=\"searchSkillQry\"\r\n (input)=\"getSkillSets()\" />\r\n <button class=\"btn\" (click)=\"createNewSkills()\" tooltip=\"Add Skillset\">\r\n <img src=\"/assets/images/icons/plus.svg\" alt=\"add\" class=\"create-plus\" width=\"18\" height=\"18\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"errMsg\" class=\"invalid-feedback is-invalid d-block\">Please Enter Skillsets Name</div>\r\n <div *ngIf=\"nameError\" class=\"invalid-feedback is-invalid d-block\">{{ nameError }}</div>\r\n <div class=\"skill-chips-wrapper\" [ngClass]=\"showLoading && !isEditMode ? 'loader' : ''\"\r\n [class.chips-collapsed]=\"!showAllSkills\">\r\n <div class=\"skill-chips\" [class.collapsed]=\"!showAllSkills\"\r\n [ngStyle]=\"showLoader && !isEditMode ? {'min-height': '120px'} : {}\">\r\n <label class=\"skill-chip\" *ngFor=\"let skill of skillSets\"\r\n [class.selected]=\"skill.selected\"\r\n [attr.for]=\"skill.id\"\r\n (mouseenter)=\"onSkillChipEnter($event, skill)\"\r\n (mouseleave)=\"onSkillChipLeave()\">\r\n <input type=\"checkbox\" [checked]=\"skill.selected\"\r\n (change)=\"onSelectedSkillsets($event, skill)\"\r\n [id]=\"skill.id\" [name]=\"skill.id\" />\r\n <svg *ngIf=\"skill.selected\" class=\"chip-check-icon\" width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n {{ skill.name }}\r\n <div class=\"chip-popover\" *ngIf=\"hoveredSkill === skill\"\r\n [style.top.px]=\"chipPopoverTop\" [style.left.px]=\"chipPopoverLeft\"\r\n (click)=\"$event.preventDefault(); $event.stopPropagation()\">\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionName\">\r\n <span class=\"chip-popover-label\">Profession Name</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionName }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionGroup\">\r\n <span class=\"chip-popover-label\">Profession Group</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionGroup }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.residentialCommercial\">\r\n <span class=\"chip-popover-label\">Residential / Commercial</span>\r\n <span class=\"chip-popover-value\">{{ skill.residentialCommercial }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionDescription\">\r\n <span class=\"chip-popover-label\">profession Description</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionDescription }}</span>\r\n </div>\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n <button *ngIf=\"!showLoading && skillSets.length > 0\" type=\"button\"\r\n class=\"show-more-btn\" (click)=\"showAllSkills = !showAllSkills\">\r\n {{ showAllSkills ? 'Show Less' : 'Show More' }}\r\n <svg [class.rotated]=\"showAllSkills\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Step 2: Per-skill detail cards (replaces tabset) -->\r\n <div class=\"sk-detail-list\" #skillDetailList\r\n *ngIf=\"tab.controls.length > 0\"\r\n [ngClass]=\"{ 'loader': showLoading && !isEditMode, 'edit-mode': isEditMode }\">\r\n <div class=\"sk-detail-list-header\">\r\n <span class=\"sk-section-label\">Skill Details</span>\r\n <span class=\"sk-count-badge\">{{ tab.controls.length }} selected</span>\r\n </div>\r\n\r\n <div *ngFor=\"let group of tab.controls; let index = index\"\r\n [formGroup]=\"group\" class=\"sk-detail-card\">\r\n <div class=\"sk-detail-card-hd\">\r\n <div class=\"sk-detail-avatar\">{{ (tabs[index] || '?').charAt(0).toUpperCase() }}</div>\r\n <span class=\"sk-detail-card-name\">{{ tabs[index] }}</span>\r\n <div class=\"sk-detail-card-actions\">\r\n <label class=\"sk-copy-toggle\" *ngIf=\"tab.controls.length > 1 && index === 0\" title=\"Copy these values to all skills\">\r\n <input type=\"checkbox\" class=\"form-check-input\"\r\n (click)=\"setCopyToAllTabs(index, group.value)\" role=\"switch\" />\r\n Copy to all\r\n </label>\r\n <button *ngIf=\"!isEditMode\" class=\"icon-btn delete-btn\" type=\"button\"\r\n (click)=\"removeTab(index, group.controls.skillSetId.value)\" title=\"Remove\">\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6L6 18M6 6l12 12\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"sk-detail-fields\">\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Self Ability Rating</label>\r\n <ngx-stars [initialStars]=\"initialStarts\" (ratingOutput)=\"onRatingSet($event, index)\"\r\n [maxStars]=\"5\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Years of Experience</label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" [searchable]=\"false\" [clearable]=\"false\"\r\n bindLabel=\"text\" formControlName=\"year\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\" (change)=\"onYearChange(group)\"></ng-select>\r\n </div>\r\n <div class=\"sk-field sk-toggle-field\">\r\n <label class=\"sk-label\">Profile Visibility</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-field-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea placeholder=\"Describe your skill...\" formControlName=\"notes\" class=\"form-control\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.notes?.errors }\" rows=\"2\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Add mode -->\r\n<div *ngIf=\"store.stepView() === 'add'\" class=\"skills-container last footer-actions\">\r\n <button class=\"back-btn\" (click)=\"userSkillsPreview.length > 0 ? cancel() : back()\">\r\n <svg *ngIf=\"userSkillsPreview.length > 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\r\n <svg *ngIf=\"userSkillsPreview.length === 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n {{ userSkillsPreview.length > 0 ? 'Cancel' : 'Back' }}\r\n </button>\r\n <div class=\"mb-res\">\r\n <button class=\"back-btn me-3\" *ngIf=\"userSkillsPreview.length === 0\" (click)=\"next()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n Skip\r\n </button>\r\n <button class=\"continue-btn\" (click)=\"onContinue()\" [disabled]=\"showLoader\" [ng2-loading]=\"showLoader\">\r\n Continue\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Preview mode -->\r\n<div *ngIf=\"store.stepView() !== 'add'\" class=\"skills-container last footer-actions\">\r\n <button class=\"back-btn\" (click)=\"back()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n Back\r\n </button>\r\n <div class=\"mb-res\">\r\n <button class=\"continue-btn add me-3\" *ngIf=\"store.stepView() === 'preview'\" (click)=\"goToAddSkillsMode()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add More Skills\r\n </button>\r\n <button class=\"continue-btn\" (click)=\"onContinue()\" [disabled]=\"showLoader\" [ng2-loading]=\"showLoader\">\r\n Continue\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".skills-container{max-width:1000px;margin:0 auto;padding:28px 24px;min-height:300px;background:#fff}.skills-container.last{min-height:unset}.title{font-size:20px;font-weight:700;color:#1e293b;margin-bottom:4px}.subtitle{font-size:14px;color:#69707d;margin-bottom:24px}.content-part{background:#fff}.content-part p{font-size:13px;color:#69707d}.content-part div{font-size:13px}.content-part .card{margin-top:15px;background:#fff;border:1px solid #e2e8f0;border-radius:12px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.content-part .card .row{margin-top:-15px}.content-part .card .sub-section{padding:0 10px}.content-part .card .sub-section .title{font-size:15px;font-weight:500;color:#1e293b}.content-part .card .sub-section .info-title{font-size:12px;font-weight:400;color:#69707d;margin-left:5px}.content-part .card .sub-section .content{font-size:13px;color:#69707d}.content-part .card .sub-section .subsection{font-weight:600;padding-top:10px;font-size:12px;color:#69707d}.content-part .card .sub-section .subsection input{width:30%}.content-part .card .sub-section .icon{width:35px;filter:opacity(.5)}.content-part .tab-card{background:#fff;border:1px solid #e2e8f0;border-radius:8px;color:#1e293b;margin-top:15px}.content-part .tab-card .row{margin-top:2px}.search-part{width:100%;position:relative;border-radius:8px;border:1.5px solid #e2e8f0;padding:0 0 0 14px;display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;height:42px;background:#f9fafb;transition:all .2s ease}.search-part:focus-within{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.search-part input{width:auto;flex:1;color:#1e293b;font-size:14px;font-weight:400;border:none;background:none;outline:none}.search-part input::placeholder{color:#69707d}.search-part .btn{background:#4077ad;border-radius:5px;padding:0;width:42px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:0;border:none;cursor:pointer;transition:all .2s ease}.search-part .btn:hover{background:#2d5a8a}.search-part .btn img{filter:brightness(0) invert(1);width:16px;height:16px}textarea{width:100%;height:100px;min-height:96px;background:#f9fafb;border:1.5px solid #e2e8f0;border-radius:8px;padding:12px 14px;font-size:14px;color:#1e293b;resize:vertical;outline:none;transition:all .2s ease}textarea:focus{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.skill-chips-wrapper{margin:8px 0 4px;position:relative;max-height:300px;overflow-y:auto}.skill-chips-wrapper.chips-collapsed:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:52px;background:linear-gradient(to bottom,transparent,#ffffff);pointer-events:none}.skill-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.skill-chips.collapsed{max-height:190px;overflow:hidden}.show-more-btn{display:inline-flex;align-items:center;gap:5px;background:none;border:1.5px solid #e2e8f0;border-radius:5px;color:#4077ad;font-size:14px;font-weight:600;padding:5px 14px;cursor:pointer;transition:all .2s ease;margin-bottom:12px}.show-more-btn:hover{background:#ebf2f9;border-color:#4077ad}.show-more-btn svg{transition:transform .2s ease}.show-more-btn svg.rotated{transform:rotate(180deg)}.skill-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:12px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4;position:relative}.skill-chip input[type=checkbox]{display:none}.skill-chip .chip-check-icon{flex-shrink:0}.skill-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.skill-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.skill-chip .chip-popover{position:fixed;transform:translate(-50%,-100%);background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;padding:10px 14px;min-width:220px;max-width:300px;z-index:99999;text-align:left;pointer-events:none;white-space:normal}.skill-chip .chip-popover:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:7px solid transparent;border-top-color:#e2e8f0}.skill-chip .chip-popover:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:-1px;border:6px solid transparent;border-top-color:#fff;z-index:1}.chip-popover-row{display:flex;flex-direction:column;gap:2px;padding:5px 0;border-bottom:1px solid #e2e8f0}.chip-popover-row:last-child{border-bottom:none;padding-bottom:0}.chip-popover-row:first-child{padding-top:0}.chip-popover-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#69707d;line-height:1.3}.chip-popover-value{font-size:12px;font-weight:500;color:#1e293b;line-height:1.45;word-break:break-word}.form-check-input{width:43px;height:21px;margin:0 5px;background-color:#c7c7c7!important;background-image:url(/assets/images/icons/toogle-circle.svg);background-position:left 4px top 2px;background-size:15px;border:1px solid #c7c7c7;outline:none!important;box-shadow:none!important;border-radius:25px;cursor:pointer}.form-check-input:checked{background-position:right 4px top 2px;background-image:url(/assets/images/icons/toogle-circle.svg);background-color:#22c55e!important;border:1px solid #22c55e!important}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:210px}::ng-deep .ng-select .ng-select-container{min-height:42px;border:1.5px solid #e2e8f0;border-radius:8px;background:#f9fafb;font-size:14px;color:#1e293b;transition:all .2s ease}::ng-deep .ng-select .ng-select-container .ng-value-container{padding-left:14px}::ng-deep .ng-select.ng-select-opened>.ng-select-container{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .ng-select.ng-select-focused .ng-select-container{border-color:#4077ad;box-shadow:0 0 0 3px #4077ad1f}.label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em;padding-bottom:6px;display:block;margin-bottom:2px}.form-control{color:#1e293b;background:#f9fafb!important;min-height:36px;font-size:14px;height:42px;border:1.5px solid #e2e8f0;border-radius:8px;transition:all .2s ease}.form-control:focus{border-color:#4077ad;background:#fff!important;box-shadow:0 0 0 3px #4077ad1f!important}.form-control:focus{border:1.5px solid #4077AD;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .nav-link{color:#69707d!important}::ng-deep .nav-link.active{color:#4077ad!important;font-weight:600}.loader{filter:blur(3px);height:40px}.edit-mode ::ng-deep .nav-tabs{display:none!important}::ng-deep accordion-group+accordion-group{margin-top:20px}.close-popup{position:absolute;right:7px;top:4px;width:25px;cursor:pointer;opacity:.6;transition:all .2s ease}.close-popup:hover{opacity:1}.back-btn,.skip-btn{height:42px;min-width:130px;background:#69707d;color:#fff;border:1.5px solid #69707D;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.back-btn:hover,.skip-btn:hover{border-color:#565c66;color:#fff;background:#565c66}.back-btn.edit,.skip-btn.edit{padding:5px 15px;min-height:20px;min-width:auto}.mb-res .back-btn{background:#f2f4fa;color:#69707d;border:1.5px solid #F2F4FA}.mb-res .back-btn:hover{background:#e4e8f2;border-color:#e4e8f2;color:#69707d}.save-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease;margin-left:15px}.save-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.save-btn:active{transform:translateY(0)}.save-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.create-btn{height:42px;min-width:9rem;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.create-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.create-btn:active{transform:translateY(0)}.continue-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.continue-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.continue-btn:active{transform:translateY(0)}.continue-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.continue-btn.edit{padding:5px 15px;min-height:20px;min-width:auto}.continue-btn.add{background:#f2f4fa;color:#69707d}.continue-btn.add:hover{background:#e4e8f2}.footer-actions{display:flex;justify-content:space-between;align-items:center;margin-top:64px}.preview-header{display:flex;align-items:center;gap:14px;margin-bottom:24px;padding-bottom:18px;border-bottom:1px solid #e2e8f0}.preview-header-icon{width:42px;height:42px;background:#ebf2f9;border-radius:10px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.preview-header-title{font-size:18px;font-weight:700;color:#1e293b;margin:0 0 2px}.preview-subtitle{font-size:12px;color:#69707d;margin:0}.sk-grid{display:grid;gap:14px;margin-bottom:24px}.sk-card{display:flex;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;transition:box-shadow .18s ease,transform .18s ease}.sk-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;transform:translateY(-1px)}.sk-card-body{flex:1;padding:14px 16px;min-width:0}.sk-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}.sk-avatar{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#4077ad,#2d5a8a);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;flex-shrink:0}.sk-title-block{flex:1;min-width:0}.sk-name{display:block;font-size:16px;font-weight:700;color:#4077ad;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-sub{display:block;font-size:12px;color:#69707d;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-top-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.sk-text-btn{height:28px;padding:0 12px;border-radius:5px;font-size:12px;font-weight:600;cursor:pointer;border:none;transition:all .2s ease}.sk-text-btn.cancel{background:#d4dae6;color:#69707d;border:1px solid #D4DAE6}.sk-text-btn.cancel:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.sk-text-btn.save{background:#4077ad;color:#fff;margin-left:4px}.sk-text-btn.save:hover{background:#2d5a8a}.sk-text-btn.save:disabled{background:#69707d;cursor:not-allowed}.icon-btn{width:28px;height:28px;border:none;min-width:unset!important;border-radius:5px;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.icon-btn.edit-btn{color:#4077ad}.icon-btn.edit-btn:hover{background:#ebf2f9}.icon-btn.delete-btn{color:#ef4444}.icon-btn.delete-btn:hover{background:#fef2f2}.sk-meta-row{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.chip.chip-year{background:#ebf2f9;color:#4077ad}.chip.chip-visible{background:#f0fdf4;color:#15803d}.chip.chip-make{background:#fff7ed;color:#c2410c}.chip.chip-model{background:#f5f3ff;color:#6d28d9}.chip.chip-serial{background:#f8fafc;color:#69707d;font-family:monospace;font-size:11px}.sk-stars-row{margin-bottom:6px}.sk-description{font-size:12px;color:#69707d;line-height:1.55;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.sk-edit-panel{margin-top:10px;padding-top:10px;border-top:1px solid #e2e8f0}.sk-edit-row{display:grid;grid-template-columns:1fr 1fr auto;gap:12px;margin-bottom:10px}.sk-edit-field{display:flex;flex-direction:column;gap:4px}.sk-edit-full{grid-column:1/-1;margin-top:4px}.sk-toggle-field{align-items:center;justify-content:center}.sk-label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em}.sk-section{margin-bottom:20px}.sk-select-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px}.sk-select-col{display:flex;flex-direction:column;gap:6px}.sk-select-col .search-part{margin-bottom:0}.sk-section-label{font-size:12px;font-weight:700;color:#1e293b;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;display:block}.sk-detail-list{display:flex;flex-direction:column;gap:12px;margin-top:8px}.sk-detail-list-header{display:flex;align-items:center;gap:10px;margin-bottom:4px}.sk-count-badge{display:inline-flex;align-items:center;padding:2px 8px;background:#ebf2f9;color:#4077ad;border-radius:20px;font-size:12px;font-weight:600}.sk-detail-card{border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden}.sk-detail-card-hd{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#ebf2f9;border-bottom:1px solid #e2e8f0}.sk-detail-avatar{width:32px;height:32px;border-radius:8px;background:#4077ad;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;flex-shrink:0}.sk-detail-card-name{flex:1;font-size:14px;font-weight:700;color:#4077ad;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-detail-card-actions{display:flex;align-items:center;gap:10px;flex-shrink:0}.sk-copy-toggle{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:#69707d;cursor:pointer;-webkit-user-select:none;user-select:none}.sk-detail-fields{padding:14px 16px}.sk-fields-row{display:grid;grid-template-columns:1fr 1fr auto;gap:14px;margin-bottom:12px}.sk-field{display:flex;flex-direction:column;gap:4px}.sk-field-full{grid-column:1/-1}.skill-preview-wrapper{margin-bottom:24px}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;margin-bottom:12px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden;transition:box-shadow .35s ease,transform .25s ease,border-color .25s ease}.skill-preview-wrapper{display:flex;flex-direction:column;gap:16px;margin-bottom:32px}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;background:#fff;transition:box-shadow .25s ease}.skill-preview-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a}.skill-preview-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:#fff;font-size:15px;font-weight:700;color:#1e293b;border-bottom:1px solid transparent;cursor:pointer}.skill-preview-header.open{background:#ebf2f9;color:#2d5a8a;border-bottom:1px solid #e2e8f0}.skill-preview-body{padding:0;background:#fff}.skill-preview-body>div{padding:16px 20px;border-bottom:1px solid #e2e8f0}.skill-preview-body>div:last-child{border-bottom:none}.skill-preview-body label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.skill-preview-body p{margin:0;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5}h5.title{font-size:22px;font-weight:700;color:#1e293b!important;margin-bottom:4px}.preview-detail-grid,.preview-edit-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0}.preview-cell{padding:14px 20px;border-bottom:1px solid #e2e8f0;border-right:1px solid #e2e8f0}.preview-cell:nth-child(3n){border-right:none}.preview-full{grid-column:1/-1;border-right:none;border-bottom:none}.preview-label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.preview-value{display:block;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word;min-height:21px}.stars-readonly{pointer-events:none;display:block}.icon-color{cursor:pointer;width:20px;height:20px;background:transparent;transition:transform .3s ease;filter:brightness(0) saturate(100%) invert(48%) sepia(8%) saturate(350%) hue-rotate(170deg) brightness(92%) contrast(88%)}.icon-color.edit{width:18px;height:18px}.rotate{transform:rotate(-180deg)}.step-card{max-width:1000px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 1px 3px #0000000f,0 4px 16px #4077ad14}.step-card-header{display:flex;align-items:center;gap:16px;padding:20px 28px;background:linear-gradient(135deg,#ebf2f9,#f0f6ff);border-bottom:1px solid #d5e8f5;border-radius:12px 12px 0 0}.step-card-header-icon{width:46px;height:46px;background:#fff;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px #4077ad2e;flex-shrink:0}.step-card-header-icon img{filter:brightness(0) saturate(100%) invert(37%) sepia(55%) saturate(500%) hue-rotate(190deg) brightness(95%) contrast(85%);width:22px;height:22px}.step-card-title{font-size:16px;font-weight:700;color:#1e293b;margin:0 0 3px;letter-spacing:-.01em}.step-card-subtitle{font-size:14px;color:#69707d;margin:0;line-height:1.4}.step-card-body{padding:24px 28px 8px}.field-section{margin-bottom:18px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px 6px}.field-section-title{font-size:12px;font-weight:700;color:#4077ad;text-transform:uppercase;letter-spacing:.07em;margin-bottom:14px;display:flex;align-items:center;gap:7px}.field-section-title:before{content:\"\";display:inline-block;width:5px;height:5px;background:#4077ad;border-radius:50%;flex-shrink:0}.doc-type-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.doc-type-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:13px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4}.doc-type-chip input[type=checkbox]{display:none}.doc-type-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.doc-type-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.detail-row{display:flex;flex-wrap:wrap;column-gap:22px;row-gap:6px;margin-bottom:8px}.detail-item{display:flex;align-items:baseline;gap:6px;white-space:nowrap}.detail-label{font-size:14px;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:#4077ad}.detail-value{font-size:12.5px;font-weight:600;color:#1e293b}button.primary,button.secondary,button.back-btn,button.continue-btn,button.save-btn,button.add-btn,button.upload-btn,.actions button,.action button,.navigation-buttons button{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-radius:5px;box-shadow:none}button.primary svg,button.secondary svg,button.back-btn svg,button.continue-btn svg,button.save-btn svg,button.add-btn svg,button.upload-btn svg,.actions button svg,.action button svg,.navigation-buttons button svg{flex-shrink:0;width:14px;height:14px}.step-toast{position:fixed;bottom:28px;right:28px;display:flex;align-items:flex-start;gap:14px;background:#fff;border-radius:12px;padding:16px 20px 20px;box-shadow:0 8px 32px #00000024;z-index:9999;min-width:290px;max-width:360px;animation:toastSlideIn .32s cubic-bezier(.34,1.56,.64,1);overflow:hidden}@keyframes toastSlideIn{0%{transform:translate(110%);opacity:0}to{transform:translate(0);opacity:1}}.step-toast-icon{width:34px;height:34px;background:#dcfce7;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;color:#16a34a}.step-toast-body{flex:1}.step-toast-title{font-size:14px;font-weight:700;color:#1e293b;margin-bottom:2px}.step-toast-msg{font-size:12px;color:#69707d;line-height:1.4}.step-toast-progress{position:absolute;bottom:0;left:0;height:3px;background:#22c55e;border-radius:0 2px 2px 0;animation:toastProgress 3.5s linear forwards}@keyframes toastProgress{0%{width:100%}to{width:0%}}@media screen and (max-width: 767px){.step-card-header{padding:14px 16px}.step-card-body{padding:16px 16px 8px}.step-toast{right:12px;bottom:16px;min-width:calc(100vw - 24px);max-width:calc(100vw - 24px)}}@media screen and (max-width: 767px){.skills-container{padding:16px}.title,h5.title{font-size:18px}.form-control,textarea{font-size:16px}.footer-actions{flex-direction:column-reverse;gap:8px;margin-top:48px}.back-btn,.skip-btn{width:100%}.continue-btn{padding:10px 22px;width:100%}.mb-res{display:flex;flex-direction:column-reverse;gap:8px;width:100%}.preview-detail-grid,.preview-edit-grid{grid-template-columns:1fr}.preview-cell{border-right:none}.sk-grid,.sk-edit-row,.sk-fields-row,.sk-select-row{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i7.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: i7.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i7.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i7.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i12.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: Ng2LoadingSpinnerDirective, selector: "[ng2-loading]", inputs: ["ng2-loading", "config", "template"] }, { kind: "component", type: NgxStarsComponent, selector: "ngx-stars", inputs: ["maxStars", "initialStars", "readonly", "size", "color", "animation", "animationSpeed", "customPadding", "wholeStars", "customStarIcons"], outputs: ["ratingOutput"] }, { kind: "directive", type: i14.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }], animations: [
|
|
9964
9950
|
trigger('expandCollapse', [
|
|
9965
9951
|
state('open', style({
|
|
9966
9952
|
height: '*',
|
|
@@ -9998,7 +9984,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
9998
9984
|
})),
|
|
9999
9985
|
transition('open <=> closed', animate('300ms ease'))
|
|
10000
9986
|
])
|
|
10001
|
-
], template: "<!-- \u2500\u2500\u2500 Skills Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"skills-container\" *ngIf=\"store.stepView() === 'preview'\">\r\n <div class=\"preview-header\">\r\n <div class=\"preview-header-icon\">\r\n <img src=\"/assets/images/icons/stars.svg\" alt=\"skills\" width=\"20\" height=\"20\" />\r\n </div>\r\n <div>\r\n <h3 class=\"preview-header-title\">Skills</h3>\r\n <p class=\"preview-subtitle\">{{ userSkillsPreview.length }} skill{{ userSkillsPreview.length !== 1 ? 's' : '' }} added</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sk-grid\">\r\n <div *ngFor=\"let skill of userSkillsPreview; let i = index\" class=\"sk-card\">\r\n <div class=\"sk-card-body\">\r\n\r\n <div class=\"sk-head\">\r\n <div class=\"sk-avatar\">{{ (skill.skillSetName || '?').charAt(0).toUpperCase() }}</div>\r\n <div class=\"sk-title-block\">\r\n <span class=\"sk-name\">{{ skill.skillSetName }}</span>\r\n <span class=\"sk-sub\" *ngIf=\"skill.providerName\">{{ skill.providerName }}</span>\r\n </div>\r\n <div class=\"sk-top-actions\">\r\n <ng-container *ngIf=\"isEditMode && getSkillKey(model) === getSkillKey(skill)\">\r\n <button class=\"sk-text-btn cancel\" type=\"button\" (click)=\"backToSkill(null)\">Cancel</button>\r\n <button class=\"sk-text-btn save\" type=\"button\" (click)=\"saveUserSkillset()\" [disabled]=\"showLoader\">Update</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isEditMode || getSkillKey(model) !== getSkillKey(skill)\">\r\n <button class=\"icon-btn edit-btn\" (click)=\"editSkillFromPreview(skill, null, $event)\" title=\"Edit\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </button>\r\n <button class=\"icon-btn delete-btn\" (click)=\"deleteSkillFromPreview(skill, $event)\" title=\"Delete\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/></svg>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- View mode -->\r\n <ng-container *ngIf=\"!isEditMode || getSkillKey(model) !== getSkillKey(skill)\">\r\n <div class=\"detail-row\">\r\n <div class=\"detail-item\" *ngIf=\"skill.year\">\r\n <span class=\"detail-label\">Years of Experience</span>\r\n <span class=\"detail-value\">{{ skill.year }} yr(s)</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"skill.profileVisibility\">\r\n <span class=\"detail-label\">Visibility</span>\r\n <span class=\"detail-value\">Visible</span>\r\n </div>\r\n </div>\r\n <div class=\"sk-stars-row stars-readonly\">\r\n <ngx-stars [initialStars]=\"skill.starRating/2\" [maxStars]=\"5\"></ngx-stars>\r\n </div>\r\n <p class=\"sk-description\" *ngIf=\"skill.notes\">{{ skill.notes }}</p>\r\n </ng-container>\r\n\r\n <!-- Edit mode (inline) -->\r\n <div *ngIf=\"isEditMode && getSkillKey(model) === getSkillKey(skill)\"\r\n [formGroup]=\"tab.at(0)\" class=\"sk-edit-panel\">\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Self Ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars *ngIf=\"tab.at(0)?.get('starRating')?.value !== null\"\r\n [key]=\"tab.at(0).get('starRating')?.value\"\r\n [initialStars]=\"(tab.at(0).get('starRating')?.value || 0) / 2\"\r\n [maxStars]=\"5\"\r\n (ratingOutput)=\"onEditRating($event)\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" [searchable]=\"false\" [clearable]=\"false\"\r\n bindLabel=\"text\" formControlName=\"year\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.year?.errors }\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\"></ng-select>\r\n </div>\r\n <div class=\"sk-edit-field sk-toggle-field\">\r\n <label class=\"sk-label\">Visible</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-field sk-edit-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea class=\"form-control\" rows=\"2\" formControlName=\"notes\" placeholder=\"Enter notes\"></textarea>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \u2500\u2500\u2500 Skills Add \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"skills-container\" *ngIf=\"store.stepView() === 'add'\">\r\n <div class=\"step-card-header mb-4\" style=\"border-radius: 10px;\">\r\n <div class=\"step-card-header-icon\">\r\n <img src=\"/assets/images/icons/stars.svg\" alt=\"skills\" width=\"22\" height=\"22\" />\r\n </div>\r\n <div>\r\n <h3 class=\"step-card-title\">Add Skills</h3>\r\n <p class=\"step-card-subtitle\">Select your skill areas and rate your proficiency</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Step 1: Select skills -->\r\n <div class=\"sk-section\">\r\n <div class=\"sk-select-row\">\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Profession</label>\r\n <ng-select\r\n [items]=\"professions\"\r\n bindLabel=\"professionName\"\r\n bindValue=\"id\"\r\n [(ngModel)]=\"selectedProfessionValue\"\r\n placeholder=\"Select Profession\"\r\n [clearable]=\"true\"\r\n (change)=\"onProfessionChange($event)\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Skill</label>\r\n <div class=\"search-part\">\r\n <input type=\"text\" placeholder=\"Search / Add Skillsets here\" [(ngModel)]=\"searchSkillQry\"\r\n (input)=\"getSkillSets()\" />\r\n <button class=\"btn\" (click)=\"createNewSkills()\" tooltip=\"Add Skillset\">\r\n <img src=\"/assets/images/icons/plus.svg\" alt=\"add\" class=\"create-plus\" width=\"18\" height=\"18\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"errMsg\" class=\"invalid-feedback is-invalid d-block\">Please Enter Skillsets Name</div>\r\n <div *ngIf=\"nameError\" class=\"invalid-feedback is-invalid d-block\">{{ nameError }}</div>\r\n <div class=\"skill-chips-wrapper\" [ngClass]=\"showLoading && !isEditMode ? 'loader' : ''\"\r\n [class.chips-collapsed]=\"!showAllSkills\">\r\n <div class=\"skill-chips\" [class.collapsed]=\"!showAllSkills\"\r\n [ngStyle]=\"showLoader && !isEditMode ? {'min-height': '120px'} : {}\">\r\n <label class=\"skill-chip\" *ngFor=\"let skill of skillSets\"\r\n [class.selected]=\"skill.selected\"\r\n [attr.for]=\"skill.id\"\r\n (mouseenter)=\"onSkillChipEnter($event, skill)\"\r\n (mouseleave)=\"onSkillChipLeave()\">\r\n <input type=\"checkbox\" [checked]=\"skill.selected\"\r\n (change)=\"onSelectedSkillsets($event, skill)\"\r\n [id]=\"skill.id\" [name]=\"skill.id\" />\r\n <svg *ngIf=\"skill.selected\" class=\"chip-check-icon\" width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n {{ skill.name }}\r\n <div class=\"chip-popover\" *ngIf=\"hoveredSkill === skill\"\r\n [style.top.px]=\"chipPopoverTop\" [style.left.px]=\"chipPopoverLeft\"\r\n (click)=\"$event.preventDefault(); $event.stopPropagation()\">\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionName\">\r\n <span class=\"chip-popover-label\">Profession Name</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionName }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionGroup\">\r\n <span class=\"chip-popover-label\">Profession Group</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionGroup }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.residentialCommercial\">\r\n <span class=\"chip-popover-label\">Residential / Commercial</span>\r\n <span class=\"chip-popover-value\">{{ skill.residentialCommercial }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionDescription\">\r\n <span class=\"chip-popover-label\">profession Description</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionDescription }}</span>\r\n </div>\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n <button *ngIf=\"!showLoading && skillSets.length > 0\" type=\"button\"\r\n class=\"show-more-btn\" (click)=\"showAllSkills = !showAllSkills\">\r\n {{ showAllSkills ? 'Show Less' : 'Show More' }}\r\n <svg [class.rotated]=\"showAllSkills\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Step 2: Per-skill detail cards (replaces tabset) -->\r\n <div class=\"sk-detail-list\" #skillDetailList\r\n *ngIf=\"tab.controls.length > 0\"\r\n [ngClass]=\"{ 'loader': showLoading && !isEditMode, 'edit-mode': isEditMode }\">\r\n <div class=\"sk-detail-list-header\">\r\n <span class=\"sk-section-label\">Skill Details</span>\r\n <span class=\"sk-count-badge\">{{ tab.controls.length }} selected</span>\r\n </div>\r\n\r\n <div *ngFor=\"let group of tab.controls; let index = index\"\r\n [formGroup]=\"group\" class=\"sk-detail-card\">\r\n <div class=\"sk-detail-card-hd\">\r\n <div class=\"sk-detail-avatar\">{{ (tabs[index] || '?').charAt(0).toUpperCase() }}</div>\r\n <span class=\"sk-detail-card-name\">{{ tabs[index] }}</span>\r\n <div class=\"sk-detail-card-actions\">\r\n <label class=\"sk-copy-toggle\" *ngIf=\"tab.controls.length > 1 && index === 0\" title=\"Copy these values to all skills\">\r\n <input type=\"checkbox\" class=\"form-check-input\"\r\n (click)=\"setCopyToAllTabs(index, group.value)\" role=\"switch\" />\r\n Copy to all\r\n </label>\r\n <button *ngIf=\"!isEditMode\" class=\"icon-btn delete-btn\" type=\"button\"\r\n (click)=\"removeTab(index, group.controls.skillSetId.value)\" title=\"Remove\">\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6L6 18M6 6l12 12\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"sk-detail-fields\">\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Self Ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars [initialStars]=\"initialStarts\" (ratingOutput)=\"onRatingSet($event, index)\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.starRating?.errors }\" [maxStars]=\"5\">\r\n </ngx-stars>\r\n <div *ngIf=\"userSkillSubmitted && k?.starRating?.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Rating is required\r\n </div>\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" [searchable]=\"false\" [clearable]=\"false\"\r\n bindLabel=\"text\" formControlName=\"year\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.year?.errors }\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\" (change)=\"onYearChange(group)\"></ng-select>\r\n <div *ngIf=\"userSkillSubmitted && k?.year?.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Year is required\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-toggle-field\">\r\n <label class=\"sk-label\">Profile Visibility</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-field-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea placeholder=\"Describe your skill...\" formControlName=\"notes\" class=\"form-control\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.notes?.errors }\" rows=\"2\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Add mode -->\r\n<div *ngIf=\"store.stepView() === 'add'\" class=\"skills-container last footer-actions\">\r\n <button class=\"back-btn\" (click)=\"userSkillsPreview.length > 0 ? cancel() : back()\">\r\n <svg *ngIf=\"userSkillsPreview.length > 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\r\n <svg *ngIf=\"userSkillsPreview.length === 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n {{ userSkillsPreview.length > 0 ? 'Cancel' : 'Back' }}\r\n </button>\r\n <div class=\"mb-res\">\r\n <button class=\"back-btn me-3\" *ngIf=\"userSkillsPreview.length === 0\" (click)=\"next()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n Skip\r\n </button>\r\n <button class=\"continue-btn\" (click)=\"onContinue()\" [disabled]=\"showLoader\" [ng2-loading]=\"showLoader\">\r\n Continue\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Preview mode -->\r\n<div *ngIf=\"store.stepView() !== 'add'\" class=\"skills-container last footer-actions\">\r\n <button class=\"back-btn\" (click)=\"back()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n Back\r\n </button>\r\n <div class=\"mb-res\">\r\n <button class=\"continue-btn add me-3\" *ngIf=\"store.stepView() === 'preview'\" (click)=\"goToAddSkillsMode()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add More Skills\r\n </button>\r\n <button class=\"continue-btn\" (click)=\"onContinue()\" [disabled]=\"showLoader\" [ng2-loading]=\"showLoader\">\r\n Continue\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".skills-container{max-width:1000px;margin:0 auto;padding:28px 24px;min-height:300px;background:#fff}.skills-container.last{min-height:unset}.title{font-size:20px;font-weight:700;color:#1e293b;margin-bottom:4px}.subtitle{font-size:14px;color:#69707d;margin-bottom:24px}.content-part{background:#fff}.content-part p{font-size:13px;color:#69707d}.content-part div{font-size:13px}.content-part .card{margin-top:15px;background:#fff;border:1px solid #e2e8f0;border-radius:12px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.content-part .card .row{margin-top:-15px}.content-part .card .sub-section{padding:0 10px}.content-part .card .sub-section .title{font-size:15px;font-weight:500;color:#1e293b}.content-part .card .sub-section .info-title{font-size:12px;font-weight:400;color:#69707d;margin-left:5px}.content-part .card .sub-section .content{font-size:13px;color:#69707d}.content-part .card .sub-section .subsection{font-weight:600;padding-top:10px;font-size:12px;color:#69707d}.content-part .card .sub-section .subsection input{width:30%}.content-part .card .sub-section .icon{width:35px;filter:opacity(.5)}.content-part .tab-card{background:#fff;border:1px solid #e2e8f0;border-radius:8px;color:#1e293b;margin-top:15px}.content-part .tab-card .row{margin-top:2px}.search-part{width:100%;position:relative;border-radius:8px;border:1.5px solid #e2e8f0;padding:0 0 0 14px;display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;height:42px;background:#f9fafb;transition:all .2s ease}.search-part:focus-within{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.search-part input{width:auto;flex:1;color:#1e293b;font-size:14px;font-weight:400;border:none;background:none;outline:none}.search-part input::placeholder{color:#69707d}.search-part .btn{background:#4077ad;border-radius:5px;padding:0;width:42px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:0;border:none;cursor:pointer;transition:all .2s ease}.search-part .btn:hover{background:#2d5a8a}.search-part .btn img{filter:brightness(0) invert(1);width:16px;height:16px}textarea{width:100%;height:100px;min-height:96px;background:#f9fafb;border:1.5px solid #e2e8f0;border-radius:8px;padding:12px 14px;font-size:14px;color:#1e293b;resize:vertical;outline:none;transition:all .2s ease}textarea:focus{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.skill-chips-wrapper{margin:8px 0 4px;position:relative;max-height:300px;overflow-y:auto}.skill-chips-wrapper.chips-collapsed:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:52px;background:linear-gradient(to bottom,transparent,#ffffff);pointer-events:none}.skill-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.skill-chips.collapsed{max-height:190px;overflow:hidden}.show-more-btn{display:inline-flex;align-items:center;gap:5px;background:none;border:1.5px solid #e2e8f0;border-radius:5px;color:#4077ad;font-size:14px;font-weight:600;padding:5px 14px;cursor:pointer;transition:all .2s ease;margin-bottom:12px}.show-more-btn:hover{background:#ebf2f9;border-color:#4077ad}.show-more-btn svg{transition:transform .2s ease}.show-more-btn svg.rotated{transform:rotate(180deg)}.skill-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:12px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4;position:relative}.skill-chip input[type=checkbox]{display:none}.skill-chip .chip-check-icon{flex-shrink:0}.skill-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.skill-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.skill-chip .chip-popover{position:fixed;transform:translate(-50%,-100%);background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;padding:10px 14px;min-width:220px;max-width:300px;z-index:99999;text-align:left;pointer-events:none;white-space:normal}.skill-chip .chip-popover:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:7px solid transparent;border-top-color:#e2e8f0}.skill-chip .chip-popover:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:-1px;border:6px solid transparent;border-top-color:#fff;z-index:1}.chip-popover-row{display:flex;flex-direction:column;gap:2px;padding:5px 0;border-bottom:1px solid #e2e8f0}.chip-popover-row:last-child{border-bottom:none;padding-bottom:0}.chip-popover-row:first-child{padding-top:0}.chip-popover-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#69707d;line-height:1.3}.chip-popover-value{font-size:12px;font-weight:500;color:#1e293b;line-height:1.45;word-break:break-word}.form-check-input{width:43px;height:21px;margin:0 5px;background-color:#c7c7c7!important;background-image:url(/assets/images/icons/toogle-circle.svg);background-position:left 4px top 2px;background-size:15px;border:1px solid #c7c7c7;outline:none!important;box-shadow:none!important;border-radius:25px;cursor:pointer}.form-check-input:checked{background-position:right 4px top 2px;background-image:url(/assets/images/icons/toogle-circle.svg);background-color:#22c55e!important;border:1px solid #22c55e!important}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:210px}::ng-deep .ng-select .ng-select-container{min-height:42px;border:1.5px solid #e2e8f0;border-radius:8px;background:#f9fafb;font-size:14px;color:#1e293b;transition:all .2s ease}::ng-deep .ng-select .ng-select-container .ng-value-container{padding-left:14px}::ng-deep .ng-select.ng-select-opened>.ng-select-container{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .ng-select.ng-select-focused .ng-select-container{border-color:#4077ad;box-shadow:0 0 0 3px #4077ad1f}.label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em;padding-bottom:6px;display:block;margin-bottom:2px}.form-control{color:#1e293b;background:#f9fafb!important;min-height:36px;font-size:14px;height:42px;border:1.5px solid #e2e8f0;border-radius:8px;transition:all .2s ease}.form-control:focus{border-color:#4077ad;background:#fff!important;box-shadow:0 0 0 3px #4077ad1f!important}.form-control:focus{border:1.5px solid #4077AD;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .nav-link{color:#69707d!important}::ng-deep .nav-link.active{color:#4077ad!important;font-weight:600}.loader{filter:blur(3px);height:40px}.edit-mode ::ng-deep .nav-tabs{display:none!important}::ng-deep accordion-group+accordion-group{margin-top:20px}.close-popup{position:absolute;right:7px;top:4px;width:25px;cursor:pointer;opacity:.6;transition:all .2s ease}.close-popup:hover{opacity:1}.back-btn,.skip-btn{height:42px;min-width:130px;background:#69707d;color:#fff;border:1.5px solid #69707D;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.back-btn:hover,.skip-btn:hover{border-color:#565c66;color:#fff;background:#565c66}.back-btn.edit,.skip-btn.edit{padding:5px 15px;min-height:20px;min-width:auto}.mb-res .back-btn{background:#f2f4fa;color:#69707d;border:1.5px solid #F2F4FA}.mb-res .back-btn:hover{background:#e4e8f2;border-color:#e4e8f2;color:#69707d}.save-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease;margin-left:15px}.save-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.save-btn:active{transform:translateY(0)}.save-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.create-btn{height:42px;min-width:9rem;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.create-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.create-btn:active{transform:translateY(0)}.continue-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.continue-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.continue-btn:active{transform:translateY(0)}.continue-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.continue-btn.edit{padding:5px 15px;min-height:20px;min-width:auto}.continue-btn.add{background:#f2f4fa;color:#69707d}.continue-btn.add:hover{background:#e4e8f2}.footer-actions{display:flex;justify-content:space-between;align-items:center;margin-top:64px}.preview-header{display:flex;align-items:center;gap:14px;margin-bottom:24px;padding-bottom:18px;border-bottom:1px solid #e2e8f0}.preview-header-icon{width:42px;height:42px;background:#ebf2f9;border-radius:10px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.preview-header-title{font-size:18px;font-weight:700;color:#1e293b;margin:0 0 2px}.preview-subtitle{font-size:12px;color:#69707d;margin:0}.sk-grid{display:grid;gap:14px;margin-bottom:24px}.sk-card{display:flex;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;transition:box-shadow .18s ease,transform .18s ease}.sk-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;transform:translateY(-1px)}.sk-card-body{flex:1;padding:14px 16px;min-width:0}.sk-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}.sk-avatar{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#4077ad,#2d5a8a);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;flex-shrink:0}.sk-title-block{flex:1;min-width:0}.sk-name{display:block;font-size:16px;font-weight:700;color:#4077ad;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-sub{display:block;font-size:12px;color:#69707d;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-top-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.sk-text-btn{height:28px;padding:0 12px;border-radius:5px;font-size:12px;font-weight:600;cursor:pointer;border:none;transition:all .2s ease}.sk-text-btn.cancel{background:#d4dae6;color:#69707d;border:1px solid #D4DAE6}.sk-text-btn.cancel:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.sk-text-btn.save{background:#4077ad;color:#fff;margin-left:4px}.sk-text-btn.save:hover{background:#2d5a8a}.sk-text-btn.save:disabled{background:#69707d;cursor:not-allowed}.icon-btn{width:28px;height:28px;border:none;min-width:unset!important;border-radius:5px;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.icon-btn.edit-btn{color:#4077ad}.icon-btn.edit-btn:hover{background:#ebf2f9}.icon-btn.delete-btn{color:#ef4444}.icon-btn.delete-btn:hover{background:#fef2f2}.sk-meta-row{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.chip.chip-year{background:#ebf2f9;color:#4077ad}.chip.chip-visible{background:#f0fdf4;color:#15803d}.chip.chip-make{background:#fff7ed;color:#c2410c}.chip.chip-model{background:#f5f3ff;color:#6d28d9}.chip.chip-serial{background:#f8fafc;color:#69707d;font-family:monospace;font-size:11px}.sk-stars-row{margin-bottom:6px}.sk-description{font-size:12px;color:#69707d;line-height:1.55;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.sk-edit-panel{margin-top:10px;padding-top:10px;border-top:1px solid #e2e8f0}.sk-edit-row{display:grid;grid-template-columns:1fr 1fr auto;gap:12px;margin-bottom:10px}.sk-edit-field{display:flex;flex-direction:column;gap:4px}.sk-edit-full{grid-column:1/-1;margin-top:4px}.sk-toggle-field{align-items:center;justify-content:center}.sk-label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em}.sk-section{margin-bottom:20px}.sk-select-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px}.sk-select-col{display:flex;flex-direction:column;gap:6px}.sk-select-col .search-part{margin-bottom:0}.sk-section-label{font-size:12px;font-weight:700;color:#1e293b;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;display:block}.sk-detail-list{display:flex;flex-direction:column;gap:12px;margin-top:8px}.sk-detail-list-header{display:flex;align-items:center;gap:10px;margin-bottom:4px}.sk-count-badge{display:inline-flex;align-items:center;padding:2px 8px;background:#ebf2f9;color:#4077ad;border-radius:20px;font-size:12px;font-weight:600}.sk-detail-card{border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden}.sk-detail-card-hd{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#ebf2f9;border-bottom:1px solid #e2e8f0}.sk-detail-avatar{width:32px;height:32px;border-radius:8px;background:#4077ad;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;flex-shrink:0}.sk-detail-card-name{flex:1;font-size:14px;font-weight:700;color:#4077ad;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-detail-card-actions{display:flex;align-items:center;gap:10px;flex-shrink:0}.sk-copy-toggle{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:#69707d;cursor:pointer;-webkit-user-select:none;user-select:none}.sk-detail-fields{padding:14px 16px}.sk-fields-row{display:grid;grid-template-columns:1fr 1fr auto;gap:14px;margin-bottom:12px}.sk-field{display:flex;flex-direction:column;gap:4px}.sk-field-full{grid-column:1/-1}.skill-preview-wrapper{margin-bottom:24px}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;margin-bottom:12px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden;transition:box-shadow .35s ease,transform .25s ease,border-color .25s ease}.skill-preview-wrapper{display:flex;flex-direction:column;gap:16px;margin-bottom:32px}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;background:#fff;transition:box-shadow .25s ease}.skill-preview-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a}.skill-preview-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:#fff;font-size:15px;font-weight:700;color:#1e293b;border-bottom:1px solid transparent;cursor:pointer}.skill-preview-header.open{background:#ebf2f9;color:#2d5a8a;border-bottom:1px solid #e2e8f0}.skill-preview-body{padding:0;background:#fff}.skill-preview-body>div{padding:16px 20px;border-bottom:1px solid #e2e8f0}.skill-preview-body>div:last-child{border-bottom:none}.skill-preview-body label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.skill-preview-body p{margin:0;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5}h5.title{font-size:22px;font-weight:700;color:#1e293b!important;margin-bottom:4px}.preview-detail-grid,.preview-edit-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0}.preview-cell{padding:14px 20px;border-bottom:1px solid #e2e8f0;border-right:1px solid #e2e8f0}.preview-cell:nth-child(3n){border-right:none}.preview-full{grid-column:1/-1;border-right:none;border-bottom:none}.preview-label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.preview-value{display:block;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word;min-height:21px}.stars-readonly{pointer-events:none;display:block}.icon-color{cursor:pointer;width:20px;height:20px;background:transparent;transition:transform .3s ease;filter:brightness(0) saturate(100%) invert(48%) sepia(8%) saturate(350%) hue-rotate(170deg) brightness(92%) contrast(88%)}.icon-color.edit{width:18px;height:18px}.rotate{transform:rotate(-180deg)}.step-card{max-width:1000px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 1px 3px #0000000f,0 4px 16px #4077ad14}.step-card-header{display:flex;align-items:center;gap:16px;padding:20px 28px;background:linear-gradient(135deg,#ebf2f9,#f0f6ff);border-bottom:1px solid #d5e8f5;border-radius:12px 12px 0 0}.step-card-header-icon{width:46px;height:46px;background:#fff;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px #4077ad2e;flex-shrink:0}.step-card-header-icon img{filter:brightness(0) saturate(100%) invert(37%) sepia(55%) saturate(500%) hue-rotate(190deg) brightness(95%) contrast(85%);width:22px;height:22px}.step-card-title{font-size:16px;font-weight:700;color:#1e293b;margin:0 0 3px;letter-spacing:-.01em}.step-card-subtitle{font-size:14px;color:#69707d;margin:0;line-height:1.4}.step-card-body{padding:24px 28px 8px}.field-section{margin-bottom:18px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px 6px}.field-section-title{font-size:12px;font-weight:700;color:#4077ad;text-transform:uppercase;letter-spacing:.07em;margin-bottom:14px;display:flex;align-items:center;gap:7px}.field-section-title:before{content:\"\";display:inline-block;width:5px;height:5px;background:#4077ad;border-radius:50%;flex-shrink:0}.doc-type-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.doc-type-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:13px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4}.doc-type-chip input[type=checkbox]{display:none}.doc-type-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.doc-type-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.detail-row{display:flex;flex-wrap:wrap;column-gap:22px;row-gap:6px;margin-bottom:8px}.detail-item{display:flex;align-items:baseline;gap:6px;white-space:nowrap}.detail-label{font-size:14px;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:#4077ad}.detail-value{font-size:12.5px;font-weight:600;color:#1e293b}button.primary,button.secondary,button.back-btn,button.continue-btn,button.save-btn,button.add-btn,button.upload-btn,.actions button,.action button,.navigation-buttons button{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-radius:5px;box-shadow:none}button.primary svg,button.secondary svg,button.back-btn svg,button.continue-btn svg,button.save-btn svg,button.add-btn svg,button.upload-btn svg,.actions button svg,.action button svg,.navigation-buttons button svg{flex-shrink:0;width:14px;height:14px}.step-toast{position:fixed;bottom:28px;right:28px;display:flex;align-items:flex-start;gap:14px;background:#fff;border-radius:12px;padding:16px 20px 20px;box-shadow:0 8px 32px #00000024;z-index:9999;min-width:290px;max-width:360px;animation:toastSlideIn .32s cubic-bezier(.34,1.56,.64,1);overflow:hidden}@keyframes toastSlideIn{0%{transform:translate(110%);opacity:0}to{transform:translate(0);opacity:1}}.step-toast-icon{width:34px;height:34px;background:#dcfce7;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;color:#16a34a}.step-toast-body{flex:1}.step-toast-title{font-size:14px;font-weight:700;color:#1e293b;margin-bottom:2px}.step-toast-msg{font-size:12px;color:#69707d;line-height:1.4}.step-toast-progress{position:absolute;bottom:0;left:0;height:3px;background:#22c55e;border-radius:0 2px 2px 0;animation:toastProgress 3.5s linear forwards}@keyframes toastProgress{0%{width:100%}to{width:0%}}@media screen and (max-width: 767px){.step-card-header{padding:14px 16px}.step-card-body{padding:16px 16px 8px}.step-toast{right:12px;bottom:16px;min-width:calc(100vw - 24px);max-width:calc(100vw - 24px)}}@media screen and (max-width: 767px){.skills-container{padding:16px}.title,h5.title{font-size:18px}.form-control,textarea{font-size:16px}.footer-actions{flex-direction:column-reverse;gap:8px;margin-top:48px}.back-btn,.skip-btn{width:100%}.continue-btn{padding:10px 22px;width:100%}.mb-res{display:flex;flex-direction:column-reverse;gap:8px;width:100%}.preview-detail-grid,.preview-edit-grid{grid-template-columns:1fr}.preview-cell{border-right:none}.sk-grid,.sk-edit-row,.sk-fields-row,.sk-select-row{grid-template-columns:1fr}}\n"] }]
|
|
9987
|
+
], template: "<!-- \u2500\u2500\u2500 Skills Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"skills-container\" *ngIf=\"store.stepView() === 'preview'\">\r\n <div class=\"preview-header\">\r\n <div class=\"preview-header-icon\">\r\n <img src=\"/assets/images/icons/stars.svg\" alt=\"skills\" width=\"20\" height=\"20\" />\r\n </div>\r\n <div>\r\n <h3 class=\"preview-header-title\">Skills</h3>\r\n <p class=\"preview-subtitle\">{{ userSkillsPreview.length }} skill{{ userSkillsPreview.length !== 1 ? 's' : '' }} added</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sk-grid\">\r\n <div *ngFor=\"let skill of userSkillsPreview; let i = index\" class=\"sk-card\">\r\n <div class=\"sk-card-body\">\r\n\r\n <div class=\"sk-head\">\r\n <div class=\"sk-avatar\">{{ (skill.skillSetName || '?').charAt(0).toUpperCase() }}</div>\r\n <div class=\"sk-title-block\">\r\n <span class=\"sk-name\">{{ skill.skillSetName }}</span>\r\n <span class=\"sk-sub\" *ngIf=\"skill.providerName\">{{ skill.providerName }}</span>\r\n </div>\r\n <div class=\"sk-top-actions\">\r\n <ng-container *ngIf=\"isEditMode && getSkillKey(model) === getSkillKey(skill)\">\r\n <button class=\"sk-text-btn cancel\" type=\"button\" (click)=\"backToSkill(null)\">Cancel</button>\r\n <button class=\"sk-text-btn save\" type=\"button\" (click)=\"saveUserSkillset()\" [disabled]=\"showLoader\">Update</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isEditMode || getSkillKey(model) !== getSkillKey(skill)\">\r\n <button class=\"icon-btn edit-btn\" (click)=\"editSkillFromPreview(skill, null, $event)\" title=\"Edit\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </button>\r\n <button class=\"icon-btn delete-btn\" (click)=\"deleteSkillFromPreview(skill, $event)\" title=\"Delete\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/></svg>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- View mode -->\r\n <ng-container *ngIf=\"!isEditMode || getSkillKey(model) !== getSkillKey(skill)\">\r\n <div class=\"detail-row\">\r\n <div class=\"detail-item\" *ngIf=\"skill.year\">\r\n <span class=\"detail-label\">Years of Experience</span>\r\n <span class=\"detail-value\">{{ skill.year }} yr(s)</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"skill.profileVisibility\">\r\n <span class=\"detail-label\">Visibility</span>\r\n <span class=\"detail-value\">Visible</span>\r\n </div>\r\n </div>\r\n <div class=\"sk-stars-row stars-readonly\">\r\n <ngx-stars [initialStars]=\"skill.starRating/2\" [maxStars]=\"5\"></ngx-stars>\r\n </div>\r\n <p class=\"sk-description\" *ngIf=\"skill.notes\">{{ skill.notes }}</p>\r\n </ng-container>\r\n\r\n <!-- Edit mode (inline) -->\r\n <div *ngIf=\"isEditMode && getSkillKey(model) === getSkillKey(skill)\"\r\n [formGroup]=\"tab.at(0)\" class=\"sk-edit-panel\">\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Self Ability Rating</label>\r\n <ngx-stars *ngIf=\"tab.at(0)?.get('starRating')?.value !== null\"\r\n [key]=\"tab.at(0).get('starRating')?.value\"\r\n [initialStars]=\"(tab.at(0).get('starRating')?.value || 0) / 2\"\r\n [maxStars]=\"5\"\r\n (ratingOutput)=\"onEditRating($event)\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Years of Experience</label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" [searchable]=\"false\" [clearable]=\"false\"\r\n bindLabel=\"text\" formControlName=\"year\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\"></ng-select>\r\n </div>\r\n <div class=\"sk-edit-field sk-toggle-field\">\r\n <label class=\"sk-label\">Visible</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-field sk-edit-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea class=\"form-control\" rows=\"2\" formControlName=\"notes\" placeholder=\"Enter notes\"></textarea>\r\n </div>\r\n </div>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \u2500\u2500\u2500 Skills Add \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"skills-container\" *ngIf=\"store.stepView() === 'add'\">\r\n <div class=\"step-card-header mb-4\" style=\"border-radius: 10px;\">\r\n <div class=\"step-card-header-icon\">\r\n <img src=\"/assets/images/icons/stars.svg\" alt=\"skills\" width=\"22\" height=\"22\" />\r\n </div>\r\n <div>\r\n <h3 class=\"step-card-title\">Add Skills</h3>\r\n <p class=\"step-card-subtitle\">Select your skill areas and rate your proficiency</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Step 1: Select skills -->\r\n <div class=\"sk-section\">\r\n <div class=\"sk-select-row\">\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Profession</label>\r\n <ng-select\r\n [items]=\"professions\"\r\n bindLabel=\"professionName\"\r\n bindValue=\"id\"\r\n [(ngModel)]=\"selectedProfessionValue\"\r\n placeholder=\"Select Profession\"\r\n [clearable]=\"true\"\r\n (change)=\"onProfessionChange($event)\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Skill</label>\r\n <div class=\"search-part\">\r\n <input type=\"text\" placeholder=\"Search / Add Skillsets here\" [(ngModel)]=\"searchSkillQry\"\r\n (input)=\"getSkillSets()\" />\r\n <button class=\"btn\" (click)=\"createNewSkills()\" tooltip=\"Add Skillset\">\r\n <img src=\"/assets/images/icons/plus.svg\" alt=\"add\" class=\"create-plus\" width=\"18\" height=\"18\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"errMsg\" class=\"invalid-feedback is-invalid d-block\">Please Enter Skillsets Name</div>\r\n <div *ngIf=\"nameError\" class=\"invalid-feedback is-invalid d-block\">{{ nameError }}</div>\r\n <div class=\"skill-chips-wrapper\" [ngClass]=\"showLoading && !isEditMode ? 'loader' : ''\"\r\n [class.chips-collapsed]=\"!showAllSkills\">\r\n <div class=\"skill-chips\" [class.collapsed]=\"!showAllSkills\"\r\n [ngStyle]=\"showLoader && !isEditMode ? {'min-height': '120px'} : {}\">\r\n <label class=\"skill-chip\" *ngFor=\"let skill of skillSets\"\r\n [class.selected]=\"skill.selected\"\r\n [attr.for]=\"skill.id\"\r\n (mouseenter)=\"onSkillChipEnter($event, skill)\"\r\n (mouseleave)=\"onSkillChipLeave()\">\r\n <input type=\"checkbox\" [checked]=\"skill.selected\"\r\n (change)=\"onSelectedSkillsets($event, skill)\"\r\n [id]=\"skill.id\" [name]=\"skill.id\" />\r\n <svg *ngIf=\"skill.selected\" class=\"chip-check-icon\" width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n {{ skill.name }}\r\n <div class=\"chip-popover\" *ngIf=\"hoveredSkill === skill\"\r\n [style.top.px]=\"chipPopoverTop\" [style.left.px]=\"chipPopoverLeft\"\r\n (click)=\"$event.preventDefault(); $event.stopPropagation()\">\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionName\">\r\n <span class=\"chip-popover-label\">Profession Name</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionName }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionGroup\">\r\n <span class=\"chip-popover-label\">Profession Group</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionGroup }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.residentialCommercial\">\r\n <span class=\"chip-popover-label\">Residential / Commercial</span>\r\n <span class=\"chip-popover-value\">{{ skill.residentialCommercial }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"skill.professionDescription\">\r\n <span class=\"chip-popover-label\">profession Description</span>\r\n <span class=\"chip-popover-value\">{{ skill.professionDescription }}</span>\r\n </div>\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n <button *ngIf=\"!showLoading && skillSets.length > 0\" type=\"button\"\r\n class=\"show-more-btn\" (click)=\"showAllSkills = !showAllSkills\">\r\n {{ showAllSkills ? 'Show Less' : 'Show More' }}\r\n <svg [class.rotated]=\"showAllSkills\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Step 2: Per-skill detail cards (replaces tabset) -->\r\n <div class=\"sk-detail-list\" #skillDetailList\r\n *ngIf=\"tab.controls.length > 0\"\r\n [ngClass]=\"{ 'loader': showLoading && !isEditMode, 'edit-mode': isEditMode }\">\r\n <div class=\"sk-detail-list-header\">\r\n <span class=\"sk-section-label\">Skill Details</span>\r\n <span class=\"sk-count-badge\">{{ tab.controls.length }} selected</span>\r\n </div>\r\n\r\n <div *ngFor=\"let group of tab.controls; let index = index\"\r\n [formGroup]=\"group\" class=\"sk-detail-card\">\r\n <div class=\"sk-detail-card-hd\">\r\n <div class=\"sk-detail-avatar\">{{ (tabs[index] || '?').charAt(0).toUpperCase() }}</div>\r\n <span class=\"sk-detail-card-name\">{{ tabs[index] }}</span>\r\n <div class=\"sk-detail-card-actions\">\r\n <label class=\"sk-copy-toggle\" *ngIf=\"tab.controls.length > 1 && index === 0\" title=\"Copy these values to all skills\">\r\n <input type=\"checkbox\" class=\"form-check-input\"\r\n (click)=\"setCopyToAllTabs(index, group.value)\" role=\"switch\" />\r\n Copy to all\r\n </label>\r\n <button *ngIf=\"!isEditMode\" class=\"icon-btn delete-btn\" type=\"button\"\r\n (click)=\"removeTab(index, group.controls.skillSetId.value)\" title=\"Remove\">\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6L6 18M6 6l12 12\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"sk-detail-fields\">\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Self Ability Rating</label>\r\n <ngx-stars [initialStars]=\"initialStarts\" (ratingOutput)=\"onRatingSet($event, index)\"\r\n [maxStars]=\"5\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Years of Experience</label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" [searchable]=\"false\" [clearable]=\"false\"\r\n bindLabel=\"text\" formControlName=\"year\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\" (change)=\"onYearChange(group)\"></ng-select>\r\n </div>\r\n <div class=\"sk-field sk-toggle-field\">\r\n <label class=\"sk-label\">Profile Visibility</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-field-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea placeholder=\"Describe your skill...\" formControlName=\"notes\" class=\"form-control\"\r\n [ngClass]=\"{ 'is-invalid': userSkillSubmitted && k?.notes?.errors }\" rows=\"2\"></textarea>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Add mode -->\r\n<div *ngIf=\"store.stepView() === 'add'\" class=\"skills-container last footer-actions\">\r\n <button class=\"back-btn\" (click)=\"userSkillsPreview.length > 0 ? cancel() : back()\">\r\n <svg *ngIf=\"userSkillsPreview.length > 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\r\n <svg *ngIf=\"userSkillsPreview.length === 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n {{ userSkillsPreview.length > 0 ? 'Cancel' : 'Back' }}\r\n </button>\r\n <div class=\"mb-res\">\r\n <button class=\"back-btn me-3\" *ngIf=\"userSkillsPreview.length === 0\" (click)=\"next()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n Skip\r\n </button>\r\n <button class=\"continue-btn\" (click)=\"onContinue()\" [disabled]=\"showLoader\" [ng2-loading]=\"showLoader\">\r\n Continue\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Preview mode -->\r\n<div *ngIf=\"store.stepView() !== 'add'\" class=\"skills-container last footer-actions\">\r\n <button class=\"back-btn\" (click)=\"back()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n Back\r\n </button>\r\n <div class=\"mb-res\">\r\n <button class=\"continue-btn add me-3\" *ngIf=\"store.stepView() === 'preview'\" (click)=\"goToAddSkillsMode()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add More Skills\r\n </button>\r\n <button class=\"continue-btn\" (click)=\"onContinue()\" [disabled]=\"showLoader\" [ng2-loading]=\"showLoader\">\r\n Continue\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M5 12h14M12 5l7 7-7 7\"/></svg>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [".skills-container{max-width:1000px;margin:0 auto;padding:28px 24px;min-height:300px;background:#fff}.skills-container.last{min-height:unset}.title{font-size:20px;font-weight:700;color:#1e293b;margin-bottom:4px}.subtitle{font-size:14px;color:#69707d;margin-bottom:24px}.content-part{background:#fff}.content-part p{font-size:13px;color:#69707d}.content-part div{font-size:13px}.content-part .card{margin-top:15px;background:#fff;border:1px solid #e2e8f0;border-radius:12px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.content-part .card .row{margin-top:-15px}.content-part .card .sub-section{padding:0 10px}.content-part .card .sub-section .title{font-size:15px;font-weight:500;color:#1e293b}.content-part .card .sub-section .info-title{font-size:12px;font-weight:400;color:#69707d;margin-left:5px}.content-part .card .sub-section .content{font-size:13px;color:#69707d}.content-part .card .sub-section .subsection{font-weight:600;padding-top:10px;font-size:12px;color:#69707d}.content-part .card .sub-section .subsection input{width:30%}.content-part .card .sub-section .icon{width:35px;filter:opacity(.5)}.content-part .tab-card{background:#fff;border:1px solid #e2e8f0;border-radius:8px;color:#1e293b;margin-top:15px}.content-part .tab-card .row{margin-top:2px}.search-part{width:100%;position:relative;border-radius:8px;border:1.5px solid #e2e8f0;padding:0 0 0 14px;display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;height:42px;background:#f9fafb;transition:all .2s ease}.search-part:focus-within{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.search-part input{width:auto;flex:1;color:#1e293b;font-size:14px;font-weight:400;border:none;background:none;outline:none}.search-part input::placeholder{color:#69707d}.search-part .btn{background:#4077ad;border-radius:5px;padding:0;width:42px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:0;border:none;cursor:pointer;transition:all .2s ease}.search-part .btn:hover{background:#2d5a8a}.search-part .btn img{filter:brightness(0) invert(1);width:16px;height:16px}textarea{width:100%;height:100px;min-height:96px;background:#f9fafb;border:1.5px solid #e2e8f0;border-radius:8px;padding:12px 14px;font-size:14px;color:#1e293b;resize:vertical;outline:none;transition:all .2s ease}textarea:focus{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.skill-chips-wrapper{margin:8px 0 4px;position:relative;max-height:300px;overflow-y:auto}.skill-chips-wrapper.chips-collapsed:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:52px;background:linear-gradient(to bottom,transparent,#ffffff);pointer-events:none}.skill-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.skill-chips.collapsed{max-height:190px;overflow:hidden}.show-more-btn{display:inline-flex;align-items:center;gap:5px;background:none;border:1.5px solid #e2e8f0;border-radius:5px;color:#4077ad;font-size:14px;font-weight:600;padding:5px 14px;cursor:pointer;transition:all .2s ease;margin-bottom:12px}.show-more-btn:hover{background:#ebf2f9;border-color:#4077ad}.show-more-btn svg{transition:transform .2s ease}.show-more-btn svg.rotated{transform:rotate(180deg)}.skill-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:12px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4;position:relative}.skill-chip input[type=checkbox]{display:none}.skill-chip .chip-check-icon{flex-shrink:0}.skill-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.skill-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.skill-chip .chip-popover{position:fixed;transform:translate(-50%,-100%);background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;padding:10px 14px;min-width:220px;max-width:300px;z-index:99999;text-align:left;pointer-events:none;white-space:normal}.skill-chip .chip-popover:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:7px solid transparent;border-top-color:#e2e8f0}.skill-chip .chip-popover:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:-1px;border:6px solid transparent;border-top-color:#fff;z-index:1}.chip-popover-row{display:flex;flex-direction:column;gap:2px;padding:5px 0;border-bottom:1px solid #e2e8f0}.chip-popover-row:last-child{border-bottom:none;padding-bottom:0}.chip-popover-row:first-child{padding-top:0}.chip-popover-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#69707d;line-height:1.3}.chip-popover-value{font-size:12px;font-weight:500;color:#1e293b;line-height:1.45;word-break:break-word}.form-check-input{width:43px;height:21px;margin:0 5px;background-color:#c7c7c7!important;background-image:url(/assets/images/icons/toogle-circle.svg);background-position:left 4px top 2px;background-size:15px;border:1px solid #c7c7c7;outline:none!important;box-shadow:none!important;border-radius:25px;cursor:pointer}.form-check-input:checked{background-position:right 4px top 2px;background-image:url(/assets/images/icons/toogle-circle.svg);background-color:#22c55e!important;border:1px solid #22c55e!important}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:210px}::ng-deep .ng-select .ng-select-container{min-height:42px;border:1.5px solid #e2e8f0;border-radius:8px;background:#f9fafb;font-size:14px;color:#1e293b;transition:all .2s ease}::ng-deep .ng-select .ng-select-container .ng-value-container{padding-left:14px}::ng-deep .ng-select.ng-select-opened>.ng-select-container{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .ng-select.ng-select-focused .ng-select-container{border-color:#4077ad;box-shadow:0 0 0 3px #4077ad1f}.label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em;padding-bottom:6px;display:block;margin-bottom:2px}.form-control{color:#1e293b;background:#f9fafb!important;min-height:36px;font-size:14px;height:42px;border:1.5px solid #e2e8f0;border-radius:8px;transition:all .2s ease}.form-control:focus{border-color:#4077ad;background:#fff!important;box-shadow:0 0 0 3px #4077ad1f!important}.form-control:focus{border:1.5px solid #4077AD;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .nav-link{color:#69707d!important}::ng-deep .nav-link.active{color:#4077ad!important;font-weight:600}.loader{filter:blur(3px);height:40px}.edit-mode ::ng-deep .nav-tabs{display:none!important}::ng-deep accordion-group+accordion-group{margin-top:20px}.close-popup{position:absolute;right:7px;top:4px;width:25px;cursor:pointer;opacity:.6;transition:all .2s ease}.close-popup:hover{opacity:1}.back-btn,.skip-btn{height:42px;min-width:130px;background:#69707d;color:#fff;border:1.5px solid #69707D;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.back-btn:hover,.skip-btn:hover{border-color:#565c66;color:#fff;background:#565c66}.back-btn.edit,.skip-btn.edit{padding:5px 15px;min-height:20px;min-width:auto}.mb-res .back-btn{background:#f2f4fa;color:#69707d;border:1.5px solid #F2F4FA}.mb-res .back-btn:hover{background:#e4e8f2;border-color:#e4e8f2;color:#69707d}.save-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease;margin-left:15px}.save-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.save-btn:active{transform:translateY(0)}.save-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.create-btn{height:42px;min-width:9rem;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.create-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.create-btn:active{transform:translateY(0)}.continue-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.continue-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.continue-btn:active{transform:translateY(0)}.continue-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.continue-btn.edit{padding:5px 15px;min-height:20px;min-width:auto}.continue-btn.add{background:#f2f4fa;color:#69707d}.continue-btn.add:hover{background:#e4e8f2}.footer-actions{display:flex;justify-content:space-between;align-items:center;margin-top:64px}.preview-header{display:flex;align-items:center;gap:14px;margin-bottom:24px;padding-bottom:18px;border-bottom:1px solid #e2e8f0}.preview-header-icon{width:42px;height:42px;background:#ebf2f9;border-radius:10px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.preview-header-title{font-size:18px;font-weight:700;color:#1e293b;margin:0 0 2px}.preview-subtitle{font-size:12px;color:#69707d;margin:0}.sk-grid{display:grid;gap:14px;margin-bottom:24px}.sk-card{display:flex;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;transition:box-shadow .18s ease,transform .18s ease}.sk-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;transform:translateY(-1px)}.sk-card-body{flex:1;padding:14px 16px;min-width:0}.sk-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}.sk-avatar{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#4077ad,#2d5a8a);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;flex-shrink:0}.sk-title-block{flex:1;min-width:0}.sk-name{display:block;font-size:16px;font-weight:700;color:#4077ad;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-sub{display:block;font-size:12px;color:#69707d;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-top-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.sk-text-btn{height:28px;padding:0 12px;border-radius:5px;font-size:12px;font-weight:600;cursor:pointer;border:none;transition:all .2s ease}.sk-text-btn.cancel{background:#d4dae6;color:#69707d;border:1px solid #D4DAE6}.sk-text-btn.cancel:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.sk-text-btn.save{background:#4077ad;color:#fff;margin-left:4px}.sk-text-btn.save:hover{background:#2d5a8a}.sk-text-btn.save:disabled{background:#69707d;cursor:not-allowed}.icon-btn{width:28px;height:28px;border:none;min-width:unset!important;border-radius:5px;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.icon-btn.edit-btn{color:#4077ad}.icon-btn.edit-btn:hover{background:#ebf2f9}.icon-btn.delete-btn{color:#ef4444}.icon-btn.delete-btn:hover{background:#fef2f2}.sk-meta-row{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.chip.chip-year{background:#ebf2f9;color:#4077ad}.chip.chip-visible{background:#f0fdf4;color:#15803d}.chip.chip-make{background:#fff7ed;color:#c2410c}.chip.chip-model{background:#f5f3ff;color:#6d28d9}.chip.chip-serial{background:#f8fafc;color:#69707d;font-family:monospace;font-size:11px}.sk-stars-row{margin-bottom:6px}.sk-description{font-size:12px;color:#69707d;line-height:1.55;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.sk-edit-panel{margin-top:10px;padding-top:10px;border-top:1px solid #e2e8f0}.sk-edit-row{display:grid;grid-template-columns:1fr 1fr auto;gap:12px;margin-bottom:10px}.sk-edit-field{display:flex;flex-direction:column;gap:4px}.sk-edit-full{grid-column:1/-1;margin-top:4px}.sk-toggle-field{align-items:center;justify-content:center}.sk-label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em}.sk-section{margin-bottom:20px}.sk-select-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px}.sk-select-col{display:flex;flex-direction:column;gap:6px}.sk-select-col .search-part{margin-bottom:0}.sk-section-label{font-size:12px;font-weight:700;color:#1e293b;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;display:block}.sk-detail-list{display:flex;flex-direction:column;gap:12px;margin-top:8px}.sk-detail-list-header{display:flex;align-items:center;gap:10px;margin-bottom:4px}.sk-count-badge{display:inline-flex;align-items:center;padding:2px 8px;background:#ebf2f9;color:#4077ad;border-radius:20px;font-size:12px;font-weight:600}.sk-detail-card{border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden}.sk-detail-card-hd{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#ebf2f9;border-bottom:1px solid #e2e8f0}.sk-detail-avatar{width:32px;height:32px;border-radius:8px;background:#4077ad;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;flex-shrink:0}.sk-detail-card-name{flex:1;font-size:14px;font-weight:700;color:#4077ad;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-detail-card-actions{display:flex;align-items:center;gap:10px;flex-shrink:0}.sk-copy-toggle{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:#69707d;cursor:pointer;-webkit-user-select:none;user-select:none}.sk-detail-fields{padding:14px 16px}.sk-fields-row{display:grid;grid-template-columns:1fr 1fr auto;gap:14px;margin-bottom:12px}.sk-field{display:flex;flex-direction:column;gap:4px}.sk-field-full{grid-column:1/-1}.skill-preview-wrapper{margin-bottom:24px}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;margin-bottom:12px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden;transition:box-shadow .35s ease,transform .25s ease,border-color .25s ease}.skill-preview-wrapper{display:flex;flex-direction:column;gap:16px;margin-bottom:32px}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;background:#fff;transition:box-shadow .25s ease}.skill-preview-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a}.skill-preview-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:#fff;font-size:15px;font-weight:700;color:#1e293b;border-bottom:1px solid transparent;cursor:pointer}.skill-preview-header.open{background:#ebf2f9;color:#2d5a8a;border-bottom:1px solid #e2e8f0}.skill-preview-body{padding:0;background:#fff}.skill-preview-body>div{padding:16px 20px;border-bottom:1px solid #e2e8f0}.skill-preview-body>div:last-child{border-bottom:none}.skill-preview-body label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.skill-preview-body p{margin:0;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5}h5.title{font-size:22px;font-weight:700;color:#1e293b!important;margin-bottom:4px}.preview-detail-grid,.preview-edit-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0}.preview-cell{padding:14px 20px;border-bottom:1px solid #e2e8f0;border-right:1px solid #e2e8f0}.preview-cell:nth-child(3n){border-right:none}.preview-full{grid-column:1/-1;border-right:none;border-bottom:none}.preview-label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.preview-value{display:block;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word;min-height:21px}.stars-readonly{pointer-events:none;display:block}.icon-color{cursor:pointer;width:20px;height:20px;background:transparent;transition:transform .3s ease;filter:brightness(0) saturate(100%) invert(48%) sepia(8%) saturate(350%) hue-rotate(170deg) brightness(92%) contrast(88%)}.icon-color.edit{width:18px;height:18px}.rotate{transform:rotate(-180deg)}.step-card{max-width:1000px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 1px 3px #0000000f,0 4px 16px #4077ad14}.step-card-header{display:flex;align-items:center;gap:16px;padding:20px 28px;background:linear-gradient(135deg,#ebf2f9,#f0f6ff);border-bottom:1px solid #d5e8f5;border-radius:12px 12px 0 0}.step-card-header-icon{width:46px;height:46px;background:#fff;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px #4077ad2e;flex-shrink:0}.step-card-header-icon img{filter:brightness(0) saturate(100%) invert(37%) sepia(55%) saturate(500%) hue-rotate(190deg) brightness(95%) contrast(85%);width:22px;height:22px}.step-card-title{font-size:16px;font-weight:700;color:#1e293b;margin:0 0 3px;letter-spacing:-.01em}.step-card-subtitle{font-size:14px;color:#69707d;margin:0;line-height:1.4}.step-card-body{padding:24px 28px 8px}.field-section{margin-bottom:18px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px 6px}.field-section-title{font-size:12px;font-weight:700;color:#4077ad;text-transform:uppercase;letter-spacing:.07em;margin-bottom:14px;display:flex;align-items:center;gap:7px}.field-section-title:before{content:\"\";display:inline-block;width:5px;height:5px;background:#4077ad;border-radius:50%;flex-shrink:0}.doc-type-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.doc-type-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:13px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4}.doc-type-chip input[type=checkbox]{display:none}.doc-type-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.doc-type-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.detail-row{display:flex;flex-wrap:wrap;column-gap:22px;row-gap:6px;margin-bottom:8px}.detail-item{display:flex;align-items:baseline;gap:6px;white-space:nowrap}.detail-label{font-size:14px;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:#4077ad}.detail-value{font-size:12.5px;font-weight:600;color:#1e293b}button.primary,button.secondary,button.back-btn,button.continue-btn,button.save-btn,button.add-btn,button.upload-btn,.actions button,.action button,.navigation-buttons button{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-radius:5px;box-shadow:none}button.primary svg,button.secondary svg,button.back-btn svg,button.continue-btn svg,button.save-btn svg,button.add-btn svg,button.upload-btn svg,.actions button svg,.action button svg,.navigation-buttons button svg{flex-shrink:0;width:14px;height:14px}.step-toast{position:fixed;bottom:28px;right:28px;display:flex;align-items:flex-start;gap:14px;background:#fff;border-radius:12px;padding:16px 20px 20px;box-shadow:0 8px 32px #00000024;z-index:9999;min-width:290px;max-width:360px;animation:toastSlideIn .32s cubic-bezier(.34,1.56,.64,1);overflow:hidden}@keyframes toastSlideIn{0%{transform:translate(110%);opacity:0}to{transform:translate(0);opacity:1}}.step-toast-icon{width:34px;height:34px;background:#dcfce7;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;color:#16a34a}.step-toast-body{flex:1}.step-toast-title{font-size:14px;font-weight:700;color:#1e293b;margin-bottom:2px}.step-toast-msg{font-size:12px;color:#69707d;line-height:1.4}.step-toast-progress{position:absolute;bottom:0;left:0;height:3px;background:#22c55e;border-radius:0 2px 2px 0;animation:toastProgress 3.5s linear forwards}@keyframes toastProgress{0%{width:100%}to{width:0%}}@media screen and (max-width: 767px){.step-card-header{padding:14px 16px}.step-card-body{padding:16px 16px 8px}.step-toast{right:12px;bottom:16px;min-width:calc(100vw - 24px);max-width:calc(100vw - 24px)}}@media screen and (max-width: 767px){.skills-container{padding:16px}.title,h5.title{font-size:18px}.form-control,textarea{font-size:16px}.footer-actions{flex-direction:column-reverse;gap:8px;margin-top:48px}.back-btn,.skip-btn{width:100%}.continue-btn{padding:10px 22px;width:100%}.mb-res{display:flex;flex-direction:column-reverse;gap:8px;width:100%}.preview-detail-grid,.preview-edit-grid{grid-template-columns:1fr}.preview-cell{border-right:none}.sk-grid,.sk-edit-row,.sk-fields-row,.sk-select-row{grid-template-columns:1fr}}\n"] }]
|
|
10002
9988
|
}], ctorParameters: () => [{ type: SkillSetService }, { type: UserSkillSetService }, { type: UserService }, { type: i7.UntypedFormBuilder }, { type: UtilsService }, { type: i1$4.RoleContextService }, { type: CredentialingStore }, { type: i1$4.TokenService }], propDecorators: { providerId: [{
|
|
10003
9989
|
type: Input
|
|
10004
9990
|
}], providerName: [{
|
|
@@ -10586,8 +10572,8 @@ class ToolsComponent {
|
|
|
10586
10572
|
userName: [this.user.fullName],
|
|
10587
10573
|
toolId: [toolId],
|
|
10588
10574
|
toolName: [toolName],
|
|
10589
|
-
starRating: [null
|
|
10590
|
-
year: [null
|
|
10575
|
+
starRating: [null],
|
|
10576
|
+
year: [null],
|
|
10591
10577
|
make: [null],
|
|
10592
10578
|
model: [null],
|
|
10593
10579
|
serialNumber: [null],
|
|
@@ -10992,7 +10978,11 @@ class ToolsComponent {
|
|
|
10992
10978
|
if (this.tab?.invalid) {
|
|
10993
10979
|
return;
|
|
10994
10980
|
}
|
|
10995
|
-
this.userToolModels = this.tab?.value
|
|
10981
|
+
this.userToolModels = (this.tab?.value || []).map((v) => ({
|
|
10982
|
+
...v,
|
|
10983
|
+
starRating: v.starRating ?? 0,
|
|
10984
|
+
year: v.year ?? 0,
|
|
10985
|
+
}));
|
|
10996
10986
|
if (this.model?.id) {
|
|
10997
10987
|
this.userToolModels[0].id = this.model.id;
|
|
10998
10988
|
}
|
|
@@ -11126,7 +11116,7 @@ class ToolsComponent {
|
|
|
11126
11116
|
});
|
|
11127
11117
|
}
|
|
11128
11118
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ToolsComponent, deps: [{ token: ToolService }, { token: UserToolService }, { token: i7.UntypedFormBuilder }, { token: UserService }, { token: UtilsService }, { token: CredentialingStore }, { token: i1$4.TokenService }, { token: i1$4.RoleContextService }, { token: UserDetailService }, { token: ProfessionService }, { token: LIBRARY_CONFIG }], target: i0.ɵɵFactoryTarget.Component });
|
|
11129
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: ToolsComponent, isStandalone: false, selector: "app-tools", inputs: { roleData: "roleData", providerId: "providerId", providerName: "providerName", signatureUrl: "signatureUrl", signatureFileId: "signatureFileId" }, viewQueries: [{ propertyName: "toolDetailList", first: true, predicate: ["toolDetailList"], descendants: true }, { propertyName: "toolChipsWrapperRef", first: true, predicate: ["toolChipsWrapper"], descendants: true }], ngImport: i0, template: "<!-- \u2500\u2500\u2500 Tools Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"tools-container\" *ngIf=\"store.toolStepView() === 'preview'\">\r\n <div class=\"preview-header\">\r\n <div class=\"preview-header-icon\">\r\n <img src=\"/assets/images/icons/tools.svg\" alt=\"tools\" width=\"20\" height=\"20\" />\r\n </div>\r\n <div>\r\n <h3 class=\"preview-header-title\">Tools & Equipment</h3>\r\n <p class=\"preview-subtitle\">{{ userToolsPreview.length }} tool{{ userToolsPreview.length !== 1 ? 's' : '' }} added</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sk-grid\">\r\n <div *ngFor=\"let tool of userToolsPreview; let i = index\" class=\"sk-card sk-card--tool\">\r\n <div class=\"sk-card-body\">\r\n\r\n <div class=\"sk-head\">\r\n <div class=\"sk-avatar sk-avatar--tool\">{{ (tool.toolName || '?').charAt(0).toUpperCase() }}</div>\r\n <div class=\"sk-title-block\">\r\n <span class=\"sk-name\">{{ tool.toolName }}</span>\r\n <span class=\"sk-sub\" *ngIf=\"tool.providerName\">{{ tool.providerName }}</span>\r\n </div>\r\n <div class=\"sk-top-actions\">\r\n <ng-container *ngIf=\"isEditMode && editingToolKey === getToolKey(tool)\">\r\n <button class=\"sk-text-btn cancel\" type=\"button\" (click)=\"backTool(null)\">Cancel</button>\r\n <button class=\"sk-text-btn save\" type=\"button\" (click)=\"saveUserTools()\" [disabled]=\"showLoader\">Update</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isEditMode || editingToolKey !== getToolKey(tool)\">\r\n <button class=\"icon-btn edit-btn\" (click)=\"editToolFromPreview(tool, null, $event)\" title=\"Edit\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </button>\r\n <button class=\"icon-btn delete-btn\" (click)=\"deleteToolFromPreview(tool, $event)\" title=\"Delete\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/></svg>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- View mode -->\r\n <ng-container *ngIf=\"!isEditMode || editingToolKey !== getToolKey(tool)\">\r\n <div class=\"detail-row\">\r\n <div class=\"detail-item\" *ngIf=\"tool.year\">\r\n <span class=\"detail-label\">Years of Experience</span>\r\n <span class=\"detail-value\">{{ tool.year }} yr(s)</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.make\">\r\n <span class=\"detail-label\">Manufacturer</span>\r\n <span class=\"detail-value\">{{ tool.make }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.model\">\r\n <span class=\"detail-label\">Model</span>\r\n <span class=\"detail-value\">{{ tool.model }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.serialNumber\">\r\n <span class=\"detail-label\">Serial Number</span>\r\n <span class=\"detail-value\">{{ tool.serialNumber }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.profileVisibility\">\r\n <span class=\"detail-label\">Visibility</span>\r\n <span class=\"detail-value\">Active</span>\r\n </div>\r\n </div>\r\n <div class=\"sk-stars-row stars-readonly\">\r\n <ngx-stars [initialStars]=\"tool.starRating\" [maxStars]=\"5\"></ngx-stars>\r\n </div>\r\n <p class=\"sk-description\" *ngIf=\"tool.notes\">{{ tool.notes }}</p>\r\n </ng-container>\r\n\r\n <!-- Edit mode (inline) -->\r\n <ng-container *ngIf=\"isEditMode && editingToolKey === getToolKey(tool)\" [formGroup]=\"tab.at(0)\">\r\n <div class=\"sk-edit-panel\">\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Self Ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars [initialStars]=\"(tab.at(0).get('starRating')?.value || 0) / 2\" [maxStars]=\"5\"\r\n (ratingOutput)=\"onRatingSets($event)\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" bindLabel=\"text\" bindValue=\"value\"\r\n formControlName=\"year\" [clearable]=\"false\" [searchable]=\"false\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-edit-field sk-toggle-field\">\r\n <label class=\"sk-label\">Active</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Manufacturer</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"make\">\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Model</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"model\">\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Serial Number</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"serialNumber\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-field sk-edit-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea class=\"form-control\" rows=\"2\" formControlName=\"notes\"></textarea>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \u2500\u2500\u2500 Tools Add \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"tools-container\" *ngIf=\"store.toolStepView() === 'add'\">\r\n <div class=\"step-card-header mb-4\" style=\"border-radius: 10px;\">\r\n <div class=\"step-card-header-icon\">\r\n <img src=\"/assets/images/icons/tools.svg\" alt=\"tools\" width=\"22\" height=\"22\" />\r\n </div>\r\n <div>\r\n <h3 class=\"step-card-title\">Add Tools & Equipment</h3>\r\n <p class=\"step-card-subtitle\">Manage specialty tools and equipment</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Step 1: Search + select tools -->\r\n <div class=\"sk-section\">\r\n <div class=\"sk-select-row\">\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Profession</label>\r\n <ng-select\r\n [items]=\"professions\"\r\n bindLabel=\"professionName\"\r\n bindValue=\"id\"\r\n [(ngModel)]=\"selectedProfessionValue\"\r\n [clearable]=\"false\"\r\n (change)=\"onProfessionChange($event)\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Tool</label>\r\n <div class=\"search-part\" *ngIf=\"!isEditMode\">\r\n <input type=\"text\" placeholder=\"Search / Add Tools here\" [(ngModel)]=\"searchToolQry\" (input)=\"getTools()\" />\r\n <button class=\"btn\" (click)=\"createNewTools()\" tooltip=\"Add Tool\">\r\n <img src=\"/assets/images/icons/plus.svg\" alt=\"add\" class=\"create-plus\" width=\"18\" height=\"18\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"!searchToolQry && toolSubmittedValue\" class=\"invalid-feedback is-invalid d-block\">\r\n Please Enter Tools Name\r\n </div>\r\n <div *ngIf=\"nameError\" class=\"invalid-feedback is-invalid d-block\">{{ nameError }}</div>\r\n <div class=\"tool-chips-wrapper\" #toolChipsWrapper [ngClass]=\"showLoading ? 'loader' : ''\"\r\n [class.chips-collapsed]=\"!showAllTools\">\r\n <div class=\"tool-chips\" [class.collapsed]=\"!showAllTools\"\r\n [ngStyle]=\"showLoader ? {'min-height': '120px'} : {}\">\r\n <label class=\"tool-chip\" *ngFor=\"let Tool of tools\"\r\n [class.selected]=\"Tool.selected\"\r\n [attr.for]=\"Tool.id\"\r\n (mouseenter)=\"onToolChipMouseEnter($event, Tool)\">\r\n <input type=\"checkbox\" [checked]=\"Tool.selected\"\r\n (change)=\"onSelectedTools($event, Tool)\"\r\n [id]=\"Tool.id\" [name]=\"Tool.id\" />\r\n <svg *ngIf=\"Tool.selected\" class=\"chip-check-icon\" width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n {{ Tool.name }}\r\n <div class=\"chip-popover\" [class.chip-popover--below]=\"flippedToolChipId === Tool.id\" *ngIf=\"Tool.professionName || Tool.professionGroup || Tool.residentialCommercial || Tool.professionDescription\" (click)=\"$event.preventDefault(); $event.stopPropagation()\">\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionName\">\r\n <span class=\"chip-popover-label\">Profession Name</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionName }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionGroup\">\r\n <span class=\"chip-popover-label\">Profession Group</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionGroup }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.residentialCommercial\">\r\n <span class=\"chip-popover-label\">Residential / Commercial</span>\r\n <span class=\"chip-popover-value\">{{ Tool.residentialCommercial }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionDescription\">\r\n <span class=\"chip-popover-label\">Description</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionDescription }}</span>\r\n </div>\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n <button *ngIf=\"!showLoading && tools.length > 0\" type=\"button\"\r\n class=\"show-more-btn\" (click)=\"showAllTools = !showAllTools\">\r\n {{ showAllTools ? 'Show Less' : 'Show More' }}\r\n <svg [class.rotated]=\"showAllTools\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Step 2: Per-tool detail cards (replaces tabset) -->\r\n <div class=\"sk-detail-list\" #toolDetailList\r\n *ngIf=\"tab?.controls.length > 0\"\r\n [ngClass]=\"{ 'loader': showLoading, 'edit-mode': isEditMode }\">\r\n <div class=\"sk-detail-list-header\">\r\n <span class=\"sk-section-label\">Tool Details</span>\r\n <span class=\"sk-count-badge\">{{ tab?.controls.length }} selected</span>\r\n </div>\r\n\r\n <div *ngFor=\"let group of tab?.controls; let index = index\"\r\n [formGroup]=\"group\" class=\"sk-detail-card\">\r\n <div class=\"sk-detail-card-hd\">\r\n <div class=\"sk-detail-avatar sk-detail-avatar--tool\">{{ (tabs[index] || '?').charAt(0).toUpperCase() }}</div>\r\n <span class=\"sk-detail-card-name\">{{ tabs[index] }}</span>\r\n <div class=\"sk-detail-card-actions\">\r\n <label class=\"sk-copy-toggle\" *ngIf=\"tab?.controls.length > 1 && index === 0\" title=\"Copy these values to all tools\">\r\n <input type=\"checkbox\" class=\"form-check-input\"\r\n (click)=\"setCopyToAllTabs(index, group.value, false)\" role=\"switch\" />\r\n Copy to all\r\n </label>\r\n <button *ngIf=\"!isEditMode\" class=\"icon-btn delete-btn\" type=\"button\"\r\n (click)=\"removeTab(index, group.controls.toolId.value)\" title=\"Remove\">\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6L6 18M6 6l12 12\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"sk-detail-fields\">\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars [initialStars]=\"initialStarts\" (ratingOutput)=\"onRatingSet($event, index)\"\r\n [ngClass]=\"{ 'is-invalid': userToolSubmitted && k.starRating.errors }\" [maxStars]=\"5\">\r\n </ngx-stars>\r\n <div *ngIf=\"userToolSubmitted && k.starRating.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Rating is required\r\n </div>\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" bindLabel=\"text\" (change)=\"onYearChange(group)\"\r\n formControlName=\"year\"\r\n [ngClass]=\"{ 'is-invalid': userToolSubmitted && k.year.errors }\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" [clearable]=\"false\" [searchable]=\"false\"\r\n placeholder=\"Select\" [appendTo]=\"'body'\"></ng-select>\r\n <div *ngIf=\"userToolSubmitted && k.year.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Year is required\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-toggle-field\">\r\n <label class=\"sk-label\">Profile Visibility</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\" />\r\n </div>\r\n </div>\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Manufacturer</label>\r\n <input formControlName=\"make\" class=\"form-control\" type=\"text\"\r\n placeholder=\"e.g. Fluke, Bosch...\" (change)=\"onYearChange(group)\" />\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Model</label>\r\n <input formControlName=\"model\" class=\"form-control\" type=\"text\"\r\n placeholder=\"Model name / number\" (change)=\"onYearChange(group)\" />\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Serial Number</label>\r\n <input formControlName=\"serialNumber\" class=\"form-control\" type=\"text\"\r\n placeholder=\"Serial / asset number\" />\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-field-full\">\r\n <label class=\"sk-label\">Comment</label>\r\n <textarea placeholder=\"Additional notes about this tool...\" formControlName=\"notes\"\r\n class=\"form-control\"\r\n [ngClass]=\"{ 'is-invalid': userToolSubmitted && k.notes.errors }\" rows=\"2\"></textarea>\r\n <div *ngIf=\"userToolSubmitted && k.notes.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Description is required\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Add mode -->\r\n<div class=\"tools-container last\" *ngIf=\"store.toolStepView() === 'add'\">\r\n <div class=\"d-flex justify-content-between pt-3 mob-res\">\r\n <button class=\"back-btn\" (click)=\"userToolsPreview.length > 0 ? cancel() : goBack()\">\r\n <svg *ngIf=\"userToolsPreview.length > 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\r\n <svg *ngIf=\"userToolsPreview.length === 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n {{ userToolsPreview.length > 0 ? 'Cancel' : 'Back' }}\r\n </button>\r\n <div class=\"mob-view\">\r\n <button (click)=\"onToolContinue()\" [ng2-loading]=\"showLoader\" [disabled]=\"showLoader\" class=\"float-end save-btn\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add\r\n </button>\r\n <button *ngIf=\"userToolsPreview.length === 0\" [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\"\r\n (click)=\"openDashboardModal()\" class=\"float-end save-btn ms-2\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H5a1 1 0 01-1-1V9.5z\"/><path d=\"M9 21V12h6v9\"/></svg>\r\n Go To Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Preview mode -->\r\n<div class=\"tools-container last\" *ngIf=\"store.toolStepView() !== 'add'\">\r\n <div class=\"d-flex justify-content-between pt-3 mob-res\">\r\n <button class=\"back-btn\" (click)=\"goBack()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n Back\r\n </button>\r\n <div class=\"mob-view\">\r\n <button class=\"back-btn me-3 add\" *ngIf=\"store.toolStepView() === 'preview'\" (click)=\"goToAddSkillsMode()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add More Tools\r\n </button>\r\n <button [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\" (click)=\"openDashboardModal()\"\r\n class=\"float-end save-btn\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H5a1 1 0 01-1-1V9.5z\"/><path d=\"M9 21V12h6v9\"/></svg>\r\n Go To Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Dashboard Confirmation Modal -->\r\n<div class=\"dashboard-modal-overlay\" *ngIf=\"showDashboardModal\" (click)=\"closeDashboardModal()\">\r\n <div class=\"dashboard-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"dashboard-modal-icon\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <circle cx=\"12\" cy=\"12\" r=\"11\" stroke=\"#22c55e\" stroke-width=\"1.5\"/>\r\n <path d=\"M7 12.5l3.5 3.5 6.5-7\" stroke=\"#22c55e\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n <h3 class=\"dashboard-modal-title\">All Information Saved!</h3>\r\n <p class=\"dashboard-modal-message\">\r\n Your profile setup is complete. All your information has been saved successfully.\r\n Clicking <strong>Go to Dashboard</strong> will take you to your dashboard.\r\n </p>\r\n <div class=\"dashboard-modal-actions\">\r\n <button type=\"button\" class=\"modal-cancel-btn\" (click)=\"closeDashboardModal()\">Cancel</button>\r\n <button type=\"button\" class=\"modal-confirm-btn\" [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\"\r\n (click)=\"closeDashboardModal(); saveFinal()\">\r\n Go to Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".tools-container{max-width:1000px;margin:0 auto;padding:28px 24px;min-height:300px;background:#fff}.tools-container.last{min-height:unset}.tools-container h3{font-size:18px;font-weight:700;color:#1e293b;margin-bottom:4px}.tools-container .info{font-size:14px;color:#69707d;margin-bottom:24px}.content-part{background:#fff}.content-part p{font-size:13px;color:#69707d}.content-part div{font-size:14px}.content-part div .label{font-size:12px!important;font-weight:700!important;color:#69707d!important;text-transform:uppercase;letter-spacing:.05em;padding-bottom:6px!important}.content-part .row{margin-top:-15px}.content-part .sub-section{padding:0 10px}.content-part .sub-section .title{font-size:15px;font-weight:500;color:#1e293b}.content-part .sub-section .info-title{font-size:12px;font-weight:400;color:#69707d;margin-left:5px}.content-part .sub-section .content{font-size:13px;color:#69707d}.content-part .sub-section .subsection{font-weight:600;padding-top:10px;font-size:12px;color:#69707d}.content-part .sub-section .subsection input{width:30%}.content-part .sub-section .icon{width:35px;filter:opacity(.5)}.content-part .tab-card{background:#fff;border:1px solid #e2e8f0;border-radius:8px;color:#1e293b}.content-part .tab-card .row{margin-top:2px}.search-part{width:100%;height:42px;position:relative;border-radius:8px;border:1.5px solid #e2e8f0;padding:0 0 0 14px;display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;background:#f9fafb;transition:all .2s ease}.search-part:focus-within{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.search-part input{width:auto;flex:1;color:#1e293b;font-size:14px;font-weight:400;border:none;background:none;outline:none}.search-part input::placeholder{color:#69707d}.search-part .btn{background:#4077ad;border-radius:5px;padding:0;width:42px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:0;border:none;cursor:pointer;transition:all .2s ease}.search-part .btn:hover{background:#2d5a8a}.search-part .btn img{filter:brightness(0) invert(1);width:16px;height:16px}textarea{width:100%;min-height:96px;background:#f9fafb;border:1.5px solid #e2e8f0;border-radius:8px;padding:12px 14px;font-size:14px;color:#1e293b;resize:vertical;outline:none;transition:all .2s ease}textarea:focus{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.tool-chips-wrapper{margin:8px 0 4px;position:relative;max-height:300px;overflow-y:auto}.tool-chips-wrapper.chips-collapsed:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:52px;background:linear-gradient(to bottom,transparent,#ffffff);pointer-events:none}.tool-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.tool-chips.collapsed{max-height:190px;overflow:hidden}.show-more-btn{display:inline-flex;align-items:center;gap:5px;background:none;border:1.5px solid #e2e8f0;border-radius:5px;color:#4077ad;font-size:14px;font-weight:600;padding:5px 14px;cursor:pointer;transition:all .2s ease;margin-bottom:12px}.show-more-btn:hover{background:#ebf2f9;border-color:#4077ad}.show-more-btn svg{transition:transform .2s ease}.show-more-btn svg.rotated{transform:rotate(180deg)}.tool-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:12px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4;position:relative}.tool-chip input[type=checkbox]{display:none}.tool-chip .chip-check-icon{flex-shrink:0}.tool-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.tool-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.tool-chip .chip-popover{display:none;position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;padding:10px 14px;min-width:220px;max-width:300px;z-index:99999;text-align:left;pointer-events:none;white-space:normal}.tool-chip .chip-popover:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:7px solid transparent;border-top-color:#e2e8f0}.tool-chip .chip-popover:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:-1px;border:6px solid transparent;border-top-color:#fff;z-index:1}.tool-chip .chip-popover--below{bottom:auto;top:calc(100% + 10px)}.tool-chip .chip-popover--below:after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:#e2e8f0}.tool-chip .chip-popover--below:before{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-top-color:transparent;border-bottom-color:#fff}.tool-chip:hover .chip-popover{display:block}.chip-popover-row{display:flex;flex-direction:column;gap:2px;padding:5px 0;border-bottom:1px solid #e2e8f0}.chip-popover-row:last-child{border-bottom:none;padding-bottom:0}.chip-popover-row:first-child{padding-top:0}.chip-popover-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#69707d;line-height:1.3}.chip-popover-value{font-size:12px;font-weight:500;color:#1e293b;line-height:1.45;word-break:break-word}.form-check-input{width:43px;height:21px;margin:0 5px;background-color:#c7c7c7!important;background-image:url(/assets/images/icons/toogle-circle.svg);background-position:left 4px top 2px;background-size:15px;border:1px solid #c7c7c7;outline:none!important;box-shadow:none!important;border-radius:25px;cursor:pointer}.form-check-input:checked{background-position:right 4px top 2px;background-image:url(/assets/images/icons/toogle-circle.svg);background-color:#22c55e!important;border:1px solid #22c55e!important}.copyAll{position:absolute;right:0;text-align:end;top:-40px}.close-popup{position:absolute;right:7px;top:4px;width:25px;cursor:pointer;opacity:.6;transition:all .2s ease}.close-popup:hover{opacity:1}.form-control{color:#1e293b;background:#f9fafb!important;font-size:14px;height:42px;border:1.5px solid #e2e8f0;border-radius:8px;transition:all .2s ease}.form-control:focus{border-color:#4077ad;background:#fff!important;box-shadow:0 0 0 3px #4077ad1f!important}.form-control:focus{border:1.5px solid #4077AD;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .nav-link{color:#69707d!important}::ng-deep .nav-link.active{color:#4077ad!important;font-weight:600}.loader{filter:blur(3px)}.edit-mode ::ng-deep .nav-tabs{display:none!important}::ng-deep accordion-group+accordion-group{margin-top:20px}.back-btn{height:42px;min-width:130px;background:#69707d;color:#fff;border:1.5px solid #69707D;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.back-btn:hover{border-color:#565c66;color:#fff;background:#565c66}.back-btn.edit{padding:5px 20px;min-height:20px;min-width:auto}.back-btn.add{background:#f2f4fa;color:#69707d;border:1.5px solid #F2F4FA}.back-btn.add:hover{background:#e4e8f2;border-color:#e4e8f2;color:#69707d}.save-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease;margin-left:15px}.save-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.save-btn:active{transform:translateY(0)}.save-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.create-btn{height:42px;min-width:9rem;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.create-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.create-btn:active{transform:translateY(0)}.continue-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.continue-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.continue-btn:active{transform:translateY(0)}.continue-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:210px}.preview-header{display:flex;align-items:center;gap:14px;margin-bottom:24px;padding-bottom:18px;border-bottom:1px solid #e2e8f0}.preview-header-icon{width:42px;height:42px;background:#fff7ed;border-radius:10px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.preview-header-title{font-size:18px;font-weight:700;color:#1e293b;margin:0 0 2px}.preview-subtitle{font-size:12px;color:#69707d;margin:0}.sk-grid{display:grid;gap:14px;margin-bottom:24px}.sk-card{display:flex;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;transition:box-shadow .18s ease,transform .18s ease}.sk-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;transform:translateY(-1px)}.sk-card-body{flex:1;padding:14px 16px;min-width:0}.sk-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}.sk-avatar{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#4077ad,#2d5a8a);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;flex-shrink:0}.sk-avatar--tool{background:linear-gradient(135deg,#d97706,#b45309)}.sk-title-block{flex:1;min-width:0}.sk-name{display:block;font-size:16px;font-weight:700;color:#4077ad;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-sub{display:block;font-size:12px;color:#69707d;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-top-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.sk-text-btn{height:28px;padding:0 12px;border-radius:5px;font-size:12px;font-weight:600;cursor:pointer;border:none;transition:all .2s ease}.sk-text-btn.cancel{background:#d4dae6;color:#69707d;border:1px solid #D4DAE6}.sk-text-btn.cancel:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.sk-text-btn.save{background:#4077ad;color:#fff;margin-left:4px}.sk-text-btn.save:hover{background:#2d5a8a}.sk-text-btn.save:disabled{background:#69707d;cursor:not-allowed}.icon-btn{width:28px;height:28px;border:none;min-width:unset!important;border-radius:5px;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.icon-btn.edit-btn{color:#4077ad}.icon-btn.edit-btn:hover{background:#ebf2f9}.icon-btn.delete-btn{color:#ef4444}.icon-btn.delete-btn:hover{background:#fef2f2}.sk-meta-row{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.chip.chip-year{background:#ebf2f9;color:#4077ad}.chip.chip-visible{background:#f0fdf4;color:#15803d}.chip.chip-make{background:#fff7ed;color:#c2410c}.chip.chip-model{background:#f5f3ff;color:#6d28d9}.chip.chip-serial{background:#f8fafc;color:#69707d;font-family:monospace;font-size:11px}.sk-stars-row{margin-bottom:6px}.sk-description{font-size:12px;color:#69707d;line-height:1.55;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.sk-edit-panel{margin-top:10px;padding-top:10px;border-top:1px solid #e2e8f0}.sk-edit-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:10px}.sk-edit-field{display:flex;flex-direction:column;gap:4px}.sk-edit-full{grid-column:1/-1;margin-top:4px}.sk-toggle-field{align-items:center;justify-content:center}.sk-label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em}.sk-section{margin-bottom:20px}.sk-section-label{font-size:12px;font-weight:700;color:#1e293b;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;display:block}.sk-detail-list{display:flex;flex-direction:column;gap:12px;margin-top:8px}.sk-detail-list-header{display:flex;align-items:center;gap:10px;margin-bottom:4px}.sk-count-badge{display:inline-flex;align-items:center;padding:2px 8px;background:#fff7ed;color:#d97706;border-radius:20px;font-size:12px;font-weight:600}.sk-detail-card{border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden}.sk-detail-card-hd{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fff7ed;border-bottom:1px solid #e2e8f0}.sk-detail-avatar{width:32px;height:32px;border-radius:8px;background:#d97706;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;flex-shrink:0}.sk-detail-avatar--tool{background:#d97706}.sk-detail-card-name{flex:1;font-size:14px;font-weight:700;color:#92400e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-detail-card-actions{display:flex;align-items:center;gap:10px;flex-shrink:0}.sk-copy-toggle{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:#69707d;cursor:pointer;-webkit-user-select:none;user-select:none}.sk-detail-fields{padding:14px 16px}.sk-fields-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:12px}.sk-field{display:flex;flex-direction:column;gap:4px}.sk-field-full{grid-column:1/-1}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;margin-bottom:16px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden;background:#fff;transition:box-shadow .25s ease}.skill-preview-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a}.skill-preview-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:#fff;font-size:15px;font-weight:700;color:#1e293b;border-bottom:1px solid transparent;cursor:pointer}.skill-preview-header.open{background:#ebf2f9;color:#2d5a8a;border-bottom:1px solid #e2e8f0}.skill-preview-body{padding:0;background:#fff}.skill-preview-body label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.skill-preview-body .value{font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word}h5.title{font-size:22px;font-weight:700;color:#1e293b!important;margin-bottom:4px}.preview-detail-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0}.preview-cell{padding:14px 20px;border-bottom:1px solid #e2e8f0;border-right:1px solid #e2e8f0}.preview-cell:nth-child(3n){border-right:none}.preview-full{grid-column:1/-1;border-right:none;border-bottom:none}.preview-label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.preview-value{display:block;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word;min-height:21px}.stars-readonly{pointer-events:none;display:block}.action-btns{display:flex;justify-content:space-between;align-items:center}.actions{display:flex;justify-content:flex-end;gap:12px;margin-top:16px}.actions button{height:42px;padding:10px 22px;border:none;border-radius:5px;font-size:14px;transition:all .2s ease;font-weight:600;min-width:120px;cursor:pointer}.actions .secondary{color:#69707d;background:#fff;border:1.5px solid #e2e8f0}.actions .secondary:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.actions .primary{background:#4077ad;color:#fff}.actions .primary:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.actions .primary:active{transform:translateY(0)}.footer-actions{display:flex;justify-content:space-between;align-items:center;margin-top:64px}.icon-color{cursor:pointer;width:20px;height:20px;background:transparent;transition:transform .2s ease;filter:brightness(0) saturate(100%) invert(48%) sepia(8%) saturate(350%) hue-rotate(170deg) brightness(92%) contrast(88%)}.icon-color.edit{width:18px;height:18px}.icon-color.rotate{transform:rotate(180deg)}.sk-select-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px}.sk-select-col{display:flex;flex-direction:column;gap:6px}.sk-select-col .search-part{margin-bottom:0;max-width:unset}.step-card{max-width:1000px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 1px 3px #0000000f,0 4px 16px #4077ad14}.step-card-header{display:flex;align-items:center;gap:16px;padding:20px 28px;background:linear-gradient(135deg,#ebf2f9,#f0f6ff);border-bottom:1px solid #d5e8f5;border-radius:12px 12px 0 0}.step-card-header-icon{width:46px;height:46px;background:#fff;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px #4077ad2e;flex-shrink:0}.step-card-header-icon img{filter:brightness(0) saturate(100%) invert(37%) sepia(55%) saturate(500%) hue-rotate(190deg) brightness(95%) contrast(85%);width:22px;height:22px}.step-card-title{font-size:16px;font-weight:700;color:#1e293b;margin:0 0 3px;letter-spacing:-.01em}.step-card-subtitle{font-size:14px;color:#69707d;margin:0;line-height:1.4}.step-card-body{padding:24px 28px 8px}.field-section{margin-bottom:18px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px 6px}.field-section-title{font-size:12px;font-weight:700;color:#4077ad;text-transform:uppercase;letter-spacing:.07em;margin-bottom:14px;display:flex;align-items:center;gap:7px}.field-section-title:before{content:\"\";display:inline-block;width:5px;height:5px;background:#4077ad;border-radius:50%;flex-shrink:0}.doc-type-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.doc-type-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:13px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4}.doc-type-chip input[type=checkbox]{display:none}.doc-type-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.doc-type-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.detail-row{display:flex;flex-wrap:wrap;column-gap:22px;row-gap:6px;margin-bottom:8px}.detail-item{display:flex;align-items:baseline;gap:6px;white-space:nowrap}.detail-label{font-size:14px;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:#4077ad}.detail-value{font-size:12.5px;font-weight:600;color:#1e293b}button.primary,button.secondary,button.back-btn,button.continue-btn,button.save-btn,button.add-btn,button.upload-btn,.actions button,.action button,.navigation-buttons button{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-radius:5px;box-shadow:none}button.primary svg,button.secondary svg,button.back-btn svg,button.continue-btn svg,button.save-btn svg,button.add-btn svg,button.upload-btn svg,.actions button svg,.action button svg,.navigation-buttons button svg{flex-shrink:0;width:14px;height:14px}.step-toast{position:fixed;bottom:28px;right:28px;display:flex;align-items:flex-start;gap:14px;background:#fff;border-radius:12px;padding:16px 20px 20px;box-shadow:0 8px 32px #00000024;z-index:9999;min-width:290px;max-width:360px;animation:toastSlideIn .32s cubic-bezier(.34,1.56,.64,1);overflow:hidden}@keyframes toastSlideIn{0%{transform:translate(110%);opacity:0}to{transform:translate(0);opacity:1}}.step-toast-icon{width:34px;height:34px;background:#dcfce7;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;color:#16a34a}.step-toast-body{flex:1}.step-toast-title{font-size:14px;font-weight:700;color:#1e293b;margin-bottom:2px}.step-toast-msg{font-size:12px;color:#69707d;line-height:1.4}.step-toast-progress{position:absolute;bottom:0;left:0;height:3px;background:#22c55e;border-radius:0 2px 2px 0;animation:toastProgress 3.5s linear forwards}@keyframes toastProgress{0%{width:100%}to{width:0%}}@media screen and (max-width: 767px){.step-card-header{padding:14px 16px}.step-card-body{padding:16px 16px 8px}.step-toast{right:12px;bottom:16px;min-width:calc(100vw - 24px);max-width:calc(100vw - 24px)}}@media only screen and (min-width: 300px) and (max-width: 450px){.modal-content .close-popup{width:16px}}@media (max-width: 600px){.actions{flex-direction:column;align-items:stretch}.actions button{width:100%}}@media screen and (max-width: 767px){.sk-select-row{grid-template-columns:1fr}.tools-container h3,h5.title{font-size:18px}.form-control,textarea{font-size:16px}.tools-container{padding:16px}.tools-container .mob-view{display:flex;justify-content:space-between;flex-direction:column-reverse;gap:8px}.tools-container .mob-res{flex-direction:column-reverse;gap:8px}.footer-actions{flex-direction:column-reverse;gap:8px;margin-top:48px}.continue-btn{padding:10px 22px;width:100%}.back-btn{width:100%}.save-btn{padding:10px 15px;width:unset;margin-left:0!important}.preview-detail-grid{grid-template-columns:1fr}.preview-cell{border-right:none}.sk-grid,.sk-edit-row,.sk-fields-row{grid-template-columns:1fr}}.dashboard-modal-overlay{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;z-index:1050;animation:fadeInOverlay .2s ease}@keyframes fadeInOverlay{0%{opacity:0}to{opacity:1}}.dashboard-modal{background:#fff;border-radius:12px;padding:40px 36px 32px;max-width:440px;width:90%;text-align:center;box-shadow:0 20px 60px #0000002e;animation:slideUpModal .25s ease}@keyframes slideUpModal{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.dashboard-modal-icon{display:flex;justify-content:center;margin-bottom:20px}.dashboard-modal-icon svg{width:56px;height:56px}.dashboard-modal-title{font-size:18px;font-weight:700;color:#1e293b;margin-bottom:12px}.dashboard-modal-message{font-size:14px;color:#69707d;line-height:1.6;margin-bottom:28px}.dashboard-modal-actions{display:flex;gap:12px;justify-content:center}.modal-cancel-btn{height:42px;min-width:110px;border-radius:5px;border:1.5px solid #D4DAE6;background:#d4dae6;color:#69707d;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.modal-cancel-btn:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.modal-confirm-btn{height:42px;min-width:150px;border-radius:5px;border:none;background:#4077ad;color:#fff;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.modal-confirm-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.modal-confirm-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}\n"], dependencies: [{ kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i7.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: i7.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i7.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i7.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i12.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: Ng2LoadingSpinnerDirective, selector: "[ng2-loading]", inputs: ["ng2-loading", "config", "template"] }, { kind: "component", type: NgxStarsComponent, selector: "ngx-stars", inputs: ["maxStars", "initialStars", "readonly", "size", "color", "animation", "animationSpeed", "customPadding", "wholeStars", "customStarIcons"], outputs: ["ratingOutput"] }, { kind: "directive", type: i14.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }], animations: [
|
|
11119
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: ToolsComponent, isStandalone: false, selector: "app-tools", inputs: { roleData: "roleData", providerId: "providerId", providerName: "providerName", signatureUrl: "signatureUrl", signatureFileId: "signatureFileId" }, viewQueries: [{ propertyName: "toolDetailList", first: true, predicate: ["toolDetailList"], descendants: true }, { propertyName: "toolChipsWrapperRef", first: true, predicate: ["toolChipsWrapper"], descendants: true }], ngImport: i0, template: "<!-- \u2500\u2500\u2500 Tools Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"tools-container\" *ngIf=\"store.toolStepView() === 'preview'\">\r\n <div class=\"preview-header\">\r\n <div class=\"preview-header-icon\">\r\n <img src=\"/assets/images/icons/tools.svg\" alt=\"tools\" width=\"20\" height=\"20\" />\r\n </div>\r\n <div>\r\n <h3 class=\"preview-header-title\">Tools & Equipment</h3>\r\n <p class=\"preview-subtitle\">{{ userToolsPreview.length }} tool{{ userToolsPreview.length !== 1 ? 's' : '' }} added</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sk-grid\">\r\n <div *ngFor=\"let tool of userToolsPreview; let i = index\" class=\"sk-card sk-card--tool\">\r\n <div class=\"sk-card-body\">\r\n\r\n <div class=\"sk-head\">\r\n <div class=\"sk-avatar sk-avatar--tool\">{{ (tool.toolName || '?').charAt(0).toUpperCase() }}</div>\r\n <div class=\"sk-title-block\">\r\n <span class=\"sk-name\">{{ tool.toolName }}</span>\r\n <span class=\"sk-sub\" *ngIf=\"tool.providerName\">{{ tool.providerName }}</span>\r\n </div>\r\n <div class=\"sk-top-actions\">\r\n <ng-container *ngIf=\"isEditMode && editingToolKey === getToolKey(tool)\">\r\n <button class=\"sk-text-btn cancel\" type=\"button\" (click)=\"backTool(null)\">Cancel</button>\r\n <button class=\"sk-text-btn save\" type=\"button\" (click)=\"saveUserTools()\" [disabled]=\"showLoader\">Update</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isEditMode || editingToolKey !== getToolKey(tool)\">\r\n <button class=\"icon-btn edit-btn\" (click)=\"editToolFromPreview(tool, null, $event)\" title=\"Edit\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </button>\r\n <button class=\"icon-btn delete-btn\" (click)=\"deleteToolFromPreview(tool, $event)\" title=\"Delete\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/></svg>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- View mode -->\r\n <ng-container *ngIf=\"!isEditMode || editingToolKey !== getToolKey(tool)\">\r\n <div class=\"detail-row\">\r\n <div class=\"detail-item\" *ngIf=\"tool.year\">\r\n <span class=\"detail-label\">Years of Experience</span>\r\n <span class=\"detail-value\">{{ tool.year }} yr(s)</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.make\">\r\n <span class=\"detail-label\">Manufacturer</span>\r\n <span class=\"detail-value\">{{ tool.make }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.model\">\r\n <span class=\"detail-label\">Model</span>\r\n <span class=\"detail-value\">{{ tool.model }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.serialNumber\">\r\n <span class=\"detail-label\">Serial Number</span>\r\n <span class=\"detail-value\">{{ tool.serialNumber }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.profileVisibility\">\r\n <span class=\"detail-label\">Visibility</span>\r\n <span class=\"detail-value\">Active</span>\r\n </div>\r\n </div>\r\n <div class=\"sk-stars-row stars-readonly\">\r\n <ngx-stars [initialStars]=\"tool.starRating\" [maxStars]=\"5\"></ngx-stars>\r\n </div>\r\n <p class=\"sk-description\" *ngIf=\"tool.notes\">{{ tool.notes }}</p>\r\n </ng-container>\r\n\r\n <!-- Edit mode (inline) -->\r\n <ng-container *ngIf=\"isEditMode && editingToolKey === getToolKey(tool)\" [formGroup]=\"tab.at(0)\">\r\n <div class=\"sk-edit-panel\">\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Self Ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars [initialStars]=\"(tab.at(0).get('starRating')?.value || 0) / 2\" [maxStars]=\"5\"\r\n (ratingOutput)=\"onRatingSets($event)\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" bindLabel=\"text\" bindValue=\"value\"\r\n formControlName=\"year\" [clearable]=\"false\" [searchable]=\"false\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-edit-field sk-toggle-field\">\r\n <label class=\"sk-label\">Active</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Manufacturer</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"make\">\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Model</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"model\">\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Serial Number</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"serialNumber\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-field sk-edit-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea class=\"form-control\" rows=\"2\" formControlName=\"notes\"></textarea>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \u2500\u2500\u2500 Tools Add \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"tools-container\" *ngIf=\"store.toolStepView() === 'add'\">\r\n <div class=\"step-card-header mb-4\" style=\"border-radius: 10px;\">\r\n <div class=\"step-card-header-icon\">\r\n <img src=\"/assets/images/icons/tools.svg\" alt=\"tools\" width=\"22\" height=\"22\" />\r\n </div>\r\n <div>\r\n <h3 class=\"step-card-title\">Add Tools & Equipment</h3>\r\n <p class=\"step-card-subtitle\">Manage specialty tools and equipment</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Step 1: Search + select tools -->\r\n <div class=\"sk-section\">\r\n <div class=\"sk-select-row\">\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Profession</label>\r\n <ng-select\r\n [items]=\"professions\"\r\n bindLabel=\"professionName\"\r\n bindValue=\"id\"\r\n [(ngModel)]=\"selectedProfessionValue\"\r\n [clearable]=\"false\"\r\n (change)=\"onProfessionChange($event)\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Tool</label>\r\n <div class=\"search-part\" *ngIf=\"!isEditMode\">\r\n <input type=\"text\" placeholder=\"Search / Add Tools here\" [(ngModel)]=\"searchToolQry\" (input)=\"getTools()\" />\r\n <button class=\"btn\" (click)=\"createNewTools()\" tooltip=\"Add Tool\">\r\n <img src=\"/assets/images/icons/plus.svg\" alt=\"add\" class=\"create-plus\" width=\"18\" height=\"18\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"!searchToolQry && toolSubmittedValue\" class=\"invalid-feedback is-invalid d-block\">\r\n Please Enter Tools Name\r\n </div>\r\n <div *ngIf=\"nameError\" class=\"invalid-feedback is-invalid d-block\">{{ nameError }}</div>\r\n <div class=\"tool-chips-wrapper\" #toolChipsWrapper [ngClass]=\"showLoading ? 'loader' : ''\"\r\n [class.chips-collapsed]=\"!showAllTools\">\r\n <div class=\"tool-chips\" [class.collapsed]=\"!showAllTools\"\r\n [ngStyle]=\"showLoader ? {'min-height': '120px'} : {}\">\r\n <label class=\"tool-chip\" *ngFor=\"let Tool of tools\"\r\n [class.selected]=\"Tool.selected\"\r\n [attr.for]=\"Tool.id\"\r\n (mouseenter)=\"onToolChipMouseEnter($event, Tool)\">\r\n <input type=\"checkbox\" [checked]=\"Tool.selected\"\r\n (change)=\"onSelectedTools($event, Tool)\"\r\n [id]=\"Tool.id\" [name]=\"Tool.id\" />\r\n <svg *ngIf=\"Tool.selected\" class=\"chip-check-icon\" width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n {{ Tool.name }}\r\n <div class=\"chip-popover\" [class.chip-popover--below]=\"flippedToolChipId === Tool.id\" *ngIf=\"Tool.professionName || Tool.professionGroup || Tool.residentialCommercial || Tool.professionDescription\" (click)=\"$event.preventDefault(); $event.stopPropagation()\">\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionName\">\r\n <span class=\"chip-popover-label\">Profession Name</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionName }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionGroup\">\r\n <span class=\"chip-popover-label\">Profession Group</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionGroup }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.residentialCommercial\">\r\n <span class=\"chip-popover-label\">Residential / Commercial</span>\r\n <span class=\"chip-popover-value\">{{ Tool.residentialCommercial }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionDescription\">\r\n <span class=\"chip-popover-label\">Description</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionDescription }}</span>\r\n </div>\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n <button *ngIf=\"!showLoading && tools.length > 0\" type=\"button\"\r\n class=\"show-more-btn\" (click)=\"showAllTools = !showAllTools\">\r\n {{ showAllTools ? 'Show Less' : 'Show More' }}\r\n <svg [class.rotated]=\"showAllTools\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Step 2: Per-tool detail cards (replaces tabset) -->\r\n <div class=\"sk-detail-list\" #toolDetailList\r\n *ngIf=\"tab?.controls.length > 0\"\r\n [ngClass]=\"{ 'loader': showLoading, 'edit-mode': isEditMode }\">\r\n <div class=\"sk-detail-list-header\">\r\n <span class=\"sk-section-label\">Tool Details</span>\r\n <span class=\"sk-count-badge\">{{ tab?.controls.length }} selected</span>\r\n </div>\r\n\r\n <div *ngFor=\"let group of tab?.controls; let index = index\"\r\n [formGroup]=\"group\" class=\"sk-detail-card\">\r\n <div class=\"sk-detail-card-hd\">\r\n <div class=\"sk-detail-avatar sk-detail-avatar--tool\">{{ (tabs[index] || '?').charAt(0).toUpperCase() }}</div>\r\n <span class=\"sk-detail-card-name\">{{ tabs[index] }}</span>\r\n <div class=\"sk-detail-card-actions\">\r\n <label class=\"sk-copy-toggle\" *ngIf=\"tab?.controls.length > 1 && index === 0\" title=\"Copy these values to all tools\">\r\n <input type=\"checkbox\" class=\"form-check-input\"\r\n (click)=\"setCopyToAllTabs(index, group.value, false)\" role=\"switch\" />\r\n Copy to all\r\n </label>\r\n <button *ngIf=\"!isEditMode\" class=\"icon-btn delete-btn\" type=\"button\"\r\n (click)=\"removeTab(index, group.controls.toolId.value)\" title=\"Remove\">\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6L6 18M6 6l12 12\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"sk-detail-fields\">\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Self-ability Rating</label>\r\n <ngx-stars [initialStars]=\"initialStarts\" (ratingOutput)=\"onRatingSet($event, index)\"\r\n [maxStars]=\"5\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Years of Experience</label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" bindLabel=\"text\" (change)=\"onYearChange(group)\"\r\n formControlName=\"year\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" [clearable]=\"false\" [searchable]=\"false\"\r\n placeholder=\"Select\" [appendTo]=\"'body'\"></ng-select>\r\n </div>\r\n <div class=\"sk-field sk-toggle-field\">\r\n <label class=\"sk-label\">Profile Visibility</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\" />\r\n </div>\r\n </div>\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Manufacturer</label>\r\n <input formControlName=\"make\" class=\"form-control\" type=\"text\"\r\n placeholder=\"e.g. Fluke, Bosch...\" (change)=\"onYearChange(group)\" />\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Model</label>\r\n <input formControlName=\"model\" class=\"form-control\" type=\"text\"\r\n placeholder=\"Model name / number\" (change)=\"onYearChange(group)\" />\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Serial Number</label>\r\n <input formControlName=\"serialNumber\" class=\"form-control\" type=\"text\"\r\n placeholder=\"Serial / asset number\" />\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-field-full\">\r\n <label class=\"sk-label\">Comment</label>\r\n <textarea placeholder=\"Additional notes about this tool...\" formControlName=\"notes\"\r\n class=\"form-control\"\r\n [ngClass]=\"{ 'is-invalid': userToolSubmitted && k.notes.errors }\" rows=\"2\"></textarea>\r\n <div *ngIf=\"userToolSubmitted && k.notes.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Description is required\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Add mode -->\r\n<div class=\"tools-container last\" *ngIf=\"store.toolStepView() === 'add'\">\r\n <div class=\"d-flex justify-content-between pt-3 mob-res\">\r\n <button class=\"back-btn\" (click)=\"userToolsPreview.length > 0 ? cancel() : goBack()\">\r\n <svg *ngIf=\"userToolsPreview.length > 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\r\n <svg *ngIf=\"userToolsPreview.length === 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n {{ userToolsPreview.length > 0 ? 'Cancel' : 'Back' }}\r\n </button>\r\n <div class=\"mob-view\">\r\n <button (click)=\"onToolContinue()\" [ng2-loading]=\"showLoader\" [disabled]=\"showLoader\" class=\"float-end save-btn\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add\r\n </button>\r\n <button *ngIf=\"userToolsPreview.length === 0\" [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\"\r\n (click)=\"openDashboardModal()\" class=\"float-end save-btn ms-2\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H5a1 1 0 01-1-1V9.5z\"/><path d=\"M9 21V12h6v9\"/></svg>\r\n Go To Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Preview mode -->\r\n<div class=\"tools-container last\" *ngIf=\"store.toolStepView() !== 'add'\">\r\n <div class=\"d-flex justify-content-between pt-3 mob-res\">\r\n <button class=\"back-btn\" (click)=\"goBack()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n Back\r\n </button>\r\n <div class=\"mob-view\">\r\n <button class=\"back-btn me-3 add\" *ngIf=\"store.toolStepView() === 'preview'\" (click)=\"goToAddSkillsMode()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add More Tools\r\n </button>\r\n <button [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\" (click)=\"openDashboardModal()\"\r\n class=\"float-end save-btn\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H5a1 1 0 01-1-1V9.5z\"/><path d=\"M9 21V12h6v9\"/></svg>\r\n Go To Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Dashboard Confirmation Modal -->\r\n<div class=\"dashboard-modal-overlay\" *ngIf=\"showDashboardModal\" (click)=\"closeDashboardModal()\">\r\n <div class=\"dashboard-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"dashboard-modal-icon\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <circle cx=\"12\" cy=\"12\" r=\"11\" stroke=\"#22c55e\" stroke-width=\"1.5\"/>\r\n <path d=\"M7 12.5l3.5 3.5 6.5-7\" stroke=\"#22c55e\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n <h3 class=\"dashboard-modal-title\">All Information Saved!</h3>\r\n <p class=\"dashboard-modal-message\">\r\n Your profile setup is complete. All your information has been saved successfully.\r\n Clicking <strong>Go to Dashboard</strong> will take you to your dashboard.\r\n </p>\r\n <div class=\"dashboard-modal-actions\">\r\n <button type=\"button\" class=\"modal-cancel-btn\" (click)=\"closeDashboardModal()\">Cancel</button>\r\n <button type=\"button\" class=\"modal-confirm-btn\" [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\"\r\n (click)=\"closeDashboardModal(); saveFinal()\">\r\n Go to Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".tools-container{max-width:1000px;margin:0 auto;padding:28px 24px;min-height:300px;background:#fff}.tools-container.last{min-height:unset}.tools-container h3{font-size:18px;font-weight:700;color:#1e293b;margin-bottom:4px}.tools-container .info{font-size:14px;color:#69707d;margin-bottom:24px}.content-part{background:#fff}.content-part p{font-size:13px;color:#69707d}.content-part div{font-size:14px}.content-part div .label{font-size:12px!important;font-weight:700!important;color:#69707d!important;text-transform:uppercase;letter-spacing:.05em;padding-bottom:6px!important}.content-part .row{margin-top:-15px}.content-part .sub-section{padding:0 10px}.content-part .sub-section .title{font-size:15px;font-weight:500;color:#1e293b}.content-part .sub-section .info-title{font-size:12px;font-weight:400;color:#69707d;margin-left:5px}.content-part .sub-section .content{font-size:13px;color:#69707d}.content-part .sub-section .subsection{font-weight:600;padding-top:10px;font-size:12px;color:#69707d}.content-part .sub-section .subsection input{width:30%}.content-part .sub-section .icon{width:35px;filter:opacity(.5)}.content-part .tab-card{background:#fff;border:1px solid #e2e8f0;border-radius:8px;color:#1e293b}.content-part .tab-card .row{margin-top:2px}.search-part{width:100%;height:42px;position:relative;border-radius:8px;border:1.5px solid #e2e8f0;padding:0 0 0 14px;display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;background:#f9fafb;transition:all .2s ease}.search-part:focus-within{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.search-part input{width:auto;flex:1;color:#1e293b;font-size:14px;font-weight:400;border:none;background:none;outline:none}.search-part input::placeholder{color:#69707d}.search-part .btn{background:#4077ad;border-radius:5px;padding:0;width:42px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:0;border:none;cursor:pointer;transition:all .2s ease}.search-part .btn:hover{background:#2d5a8a}.search-part .btn img{filter:brightness(0) invert(1);width:16px;height:16px}textarea{width:100%;min-height:96px;background:#f9fafb;border:1.5px solid #e2e8f0;border-radius:8px;padding:12px 14px;font-size:14px;color:#1e293b;resize:vertical;outline:none;transition:all .2s ease}textarea:focus{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.tool-chips-wrapper{margin:8px 0 4px;position:relative;max-height:300px;overflow-y:auto}.tool-chips-wrapper.chips-collapsed:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:52px;background:linear-gradient(to bottom,transparent,#ffffff);pointer-events:none}.tool-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.tool-chips.collapsed{max-height:190px;overflow:hidden}.show-more-btn{display:inline-flex;align-items:center;gap:5px;background:none;border:1.5px solid #e2e8f0;border-radius:5px;color:#4077ad;font-size:14px;font-weight:600;padding:5px 14px;cursor:pointer;transition:all .2s ease;margin-bottom:12px}.show-more-btn:hover{background:#ebf2f9;border-color:#4077ad}.show-more-btn svg{transition:transform .2s ease}.show-more-btn svg.rotated{transform:rotate(180deg)}.tool-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:12px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4;position:relative}.tool-chip input[type=checkbox]{display:none}.tool-chip .chip-check-icon{flex-shrink:0}.tool-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.tool-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.tool-chip .chip-popover{display:none;position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;padding:10px 14px;min-width:220px;max-width:300px;z-index:99999;text-align:left;pointer-events:none;white-space:normal}.tool-chip .chip-popover:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:7px solid transparent;border-top-color:#e2e8f0}.tool-chip .chip-popover:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:-1px;border:6px solid transparent;border-top-color:#fff;z-index:1}.tool-chip .chip-popover--below{bottom:auto;top:calc(100% + 10px)}.tool-chip .chip-popover--below:after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:#e2e8f0}.tool-chip .chip-popover--below:before{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-top-color:transparent;border-bottom-color:#fff}.tool-chip:hover .chip-popover{display:block}.chip-popover-row{display:flex;flex-direction:column;gap:2px;padding:5px 0;border-bottom:1px solid #e2e8f0}.chip-popover-row:last-child{border-bottom:none;padding-bottom:0}.chip-popover-row:first-child{padding-top:0}.chip-popover-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#69707d;line-height:1.3}.chip-popover-value{font-size:12px;font-weight:500;color:#1e293b;line-height:1.45;word-break:break-word}.form-check-input{width:43px;height:21px;margin:0 5px;background-color:#c7c7c7!important;background-image:url(/assets/images/icons/toogle-circle.svg);background-position:left 4px top 2px;background-size:15px;border:1px solid #c7c7c7;outline:none!important;box-shadow:none!important;border-radius:25px;cursor:pointer}.form-check-input:checked{background-position:right 4px top 2px;background-image:url(/assets/images/icons/toogle-circle.svg);background-color:#22c55e!important;border:1px solid #22c55e!important}.copyAll{position:absolute;right:0;text-align:end;top:-40px}.close-popup{position:absolute;right:7px;top:4px;width:25px;cursor:pointer;opacity:.6;transition:all .2s ease}.close-popup:hover{opacity:1}.form-control{color:#1e293b;background:#f9fafb!important;font-size:14px;height:42px;border:1.5px solid #e2e8f0;border-radius:8px;transition:all .2s ease}.form-control:focus{border-color:#4077ad;background:#fff!important;box-shadow:0 0 0 3px #4077ad1f!important}.form-control:focus{border:1.5px solid #4077AD;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .nav-link{color:#69707d!important}::ng-deep .nav-link.active{color:#4077ad!important;font-weight:600}.loader{filter:blur(3px)}.edit-mode ::ng-deep .nav-tabs{display:none!important}::ng-deep accordion-group+accordion-group{margin-top:20px}.back-btn{height:42px;min-width:130px;background:#69707d;color:#fff;border:1.5px solid #69707D;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.back-btn:hover{border-color:#565c66;color:#fff;background:#565c66}.back-btn.edit{padding:5px 20px;min-height:20px;min-width:auto}.back-btn.add{background:#f2f4fa;color:#69707d;border:1.5px solid #F2F4FA}.back-btn.add:hover{background:#e4e8f2;border-color:#e4e8f2;color:#69707d}.save-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease;margin-left:15px}.save-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.save-btn:active{transform:translateY(0)}.save-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.create-btn{height:42px;min-width:9rem;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.create-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.create-btn:active{transform:translateY(0)}.continue-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.continue-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.continue-btn:active{transform:translateY(0)}.continue-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:210px}.preview-header{display:flex;align-items:center;gap:14px;margin-bottom:24px;padding-bottom:18px;border-bottom:1px solid #e2e8f0}.preview-header-icon{width:42px;height:42px;background:#fff7ed;border-radius:10px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.preview-header-title{font-size:18px;font-weight:700;color:#1e293b;margin:0 0 2px}.preview-subtitle{font-size:12px;color:#69707d;margin:0}.sk-grid{display:grid;gap:14px;margin-bottom:24px}.sk-card{display:flex;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;transition:box-shadow .18s ease,transform .18s ease}.sk-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;transform:translateY(-1px)}.sk-card-body{flex:1;padding:14px 16px;min-width:0}.sk-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}.sk-avatar{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#4077ad,#2d5a8a);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;flex-shrink:0}.sk-avatar--tool{background:linear-gradient(135deg,#d97706,#b45309)}.sk-title-block{flex:1;min-width:0}.sk-name{display:block;font-size:16px;font-weight:700;color:#4077ad;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-sub{display:block;font-size:12px;color:#69707d;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-top-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.sk-text-btn{height:28px;padding:0 12px;border-radius:5px;font-size:12px;font-weight:600;cursor:pointer;border:none;transition:all .2s ease}.sk-text-btn.cancel{background:#d4dae6;color:#69707d;border:1px solid #D4DAE6}.sk-text-btn.cancel:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.sk-text-btn.save{background:#4077ad;color:#fff;margin-left:4px}.sk-text-btn.save:hover{background:#2d5a8a}.sk-text-btn.save:disabled{background:#69707d;cursor:not-allowed}.icon-btn{width:28px;height:28px;border:none;min-width:unset!important;border-radius:5px;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.icon-btn.edit-btn{color:#4077ad}.icon-btn.edit-btn:hover{background:#ebf2f9}.icon-btn.delete-btn{color:#ef4444}.icon-btn.delete-btn:hover{background:#fef2f2}.sk-meta-row{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.chip.chip-year{background:#ebf2f9;color:#4077ad}.chip.chip-visible{background:#f0fdf4;color:#15803d}.chip.chip-make{background:#fff7ed;color:#c2410c}.chip.chip-model{background:#f5f3ff;color:#6d28d9}.chip.chip-serial{background:#f8fafc;color:#69707d;font-family:monospace;font-size:11px}.sk-stars-row{margin-bottom:6px}.sk-description{font-size:12px;color:#69707d;line-height:1.55;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.sk-edit-panel{margin-top:10px;padding-top:10px;border-top:1px solid #e2e8f0}.sk-edit-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:10px}.sk-edit-field{display:flex;flex-direction:column;gap:4px}.sk-edit-full{grid-column:1/-1;margin-top:4px}.sk-toggle-field{align-items:center;justify-content:center}.sk-label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em}.sk-section{margin-bottom:20px}.sk-section-label{font-size:12px;font-weight:700;color:#1e293b;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;display:block}.sk-detail-list{display:flex;flex-direction:column;gap:12px;margin-top:8px}.sk-detail-list-header{display:flex;align-items:center;gap:10px;margin-bottom:4px}.sk-count-badge{display:inline-flex;align-items:center;padding:2px 8px;background:#fff7ed;color:#d97706;border-radius:20px;font-size:12px;font-weight:600}.sk-detail-card{border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden}.sk-detail-card-hd{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fff7ed;border-bottom:1px solid #e2e8f0}.sk-detail-avatar{width:32px;height:32px;border-radius:8px;background:#d97706;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;flex-shrink:0}.sk-detail-avatar--tool{background:#d97706}.sk-detail-card-name{flex:1;font-size:14px;font-weight:700;color:#92400e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-detail-card-actions{display:flex;align-items:center;gap:10px;flex-shrink:0}.sk-copy-toggle{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:#69707d;cursor:pointer;-webkit-user-select:none;user-select:none}.sk-detail-fields{padding:14px 16px}.sk-fields-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:12px}.sk-field{display:flex;flex-direction:column;gap:4px}.sk-field-full{grid-column:1/-1}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;margin-bottom:16px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden;background:#fff;transition:box-shadow .25s ease}.skill-preview-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a}.skill-preview-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:#fff;font-size:15px;font-weight:700;color:#1e293b;border-bottom:1px solid transparent;cursor:pointer}.skill-preview-header.open{background:#ebf2f9;color:#2d5a8a;border-bottom:1px solid #e2e8f0}.skill-preview-body{padding:0;background:#fff}.skill-preview-body label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.skill-preview-body .value{font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word}h5.title{font-size:22px;font-weight:700;color:#1e293b!important;margin-bottom:4px}.preview-detail-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0}.preview-cell{padding:14px 20px;border-bottom:1px solid #e2e8f0;border-right:1px solid #e2e8f0}.preview-cell:nth-child(3n){border-right:none}.preview-full{grid-column:1/-1;border-right:none;border-bottom:none}.preview-label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.preview-value{display:block;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word;min-height:21px}.stars-readonly{pointer-events:none;display:block}.action-btns{display:flex;justify-content:space-between;align-items:center}.actions{display:flex;justify-content:flex-end;gap:12px;margin-top:16px}.actions button{height:42px;padding:10px 22px;border:none;border-radius:5px;font-size:14px;transition:all .2s ease;font-weight:600;min-width:120px;cursor:pointer}.actions .secondary{color:#69707d;background:#fff;border:1.5px solid #e2e8f0}.actions .secondary:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.actions .primary{background:#4077ad;color:#fff}.actions .primary:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.actions .primary:active{transform:translateY(0)}.footer-actions{display:flex;justify-content:space-between;align-items:center;margin-top:64px}.icon-color{cursor:pointer;width:20px;height:20px;background:transparent;transition:transform .2s ease;filter:brightness(0) saturate(100%) invert(48%) sepia(8%) saturate(350%) hue-rotate(170deg) brightness(92%) contrast(88%)}.icon-color.edit{width:18px;height:18px}.icon-color.rotate{transform:rotate(180deg)}.sk-select-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px}.sk-select-col{display:flex;flex-direction:column;gap:6px}.sk-select-col .search-part{margin-bottom:0;max-width:unset}.step-card{max-width:1000px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 1px 3px #0000000f,0 4px 16px #4077ad14}.step-card-header{display:flex;align-items:center;gap:16px;padding:20px 28px;background:linear-gradient(135deg,#ebf2f9,#f0f6ff);border-bottom:1px solid #d5e8f5;border-radius:12px 12px 0 0}.step-card-header-icon{width:46px;height:46px;background:#fff;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px #4077ad2e;flex-shrink:0}.step-card-header-icon img{filter:brightness(0) saturate(100%) invert(37%) sepia(55%) saturate(500%) hue-rotate(190deg) brightness(95%) contrast(85%);width:22px;height:22px}.step-card-title{font-size:16px;font-weight:700;color:#1e293b;margin:0 0 3px;letter-spacing:-.01em}.step-card-subtitle{font-size:14px;color:#69707d;margin:0;line-height:1.4}.step-card-body{padding:24px 28px 8px}.field-section{margin-bottom:18px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px 6px}.field-section-title{font-size:12px;font-weight:700;color:#4077ad;text-transform:uppercase;letter-spacing:.07em;margin-bottom:14px;display:flex;align-items:center;gap:7px}.field-section-title:before{content:\"\";display:inline-block;width:5px;height:5px;background:#4077ad;border-radius:50%;flex-shrink:0}.doc-type-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.doc-type-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:13px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4}.doc-type-chip input[type=checkbox]{display:none}.doc-type-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.doc-type-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.detail-row{display:flex;flex-wrap:wrap;column-gap:22px;row-gap:6px;margin-bottom:8px}.detail-item{display:flex;align-items:baseline;gap:6px;white-space:nowrap}.detail-label{font-size:14px;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:#4077ad}.detail-value{font-size:12.5px;font-weight:600;color:#1e293b}button.primary,button.secondary,button.back-btn,button.continue-btn,button.save-btn,button.add-btn,button.upload-btn,.actions button,.action button,.navigation-buttons button{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-radius:5px;box-shadow:none}button.primary svg,button.secondary svg,button.back-btn svg,button.continue-btn svg,button.save-btn svg,button.add-btn svg,button.upload-btn svg,.actions button svg,.action button svg,.navigation-buttons button svg{flex-shrink:0;width:14px;height:14px}.step-toast{position:fixed;bottom:28px;right:28px;display:flex;align-items:flex-start;gap:14px;background:#fff;border-radius:12px;padding:16px 20px 20px;box-shadow:0 8px 32px #00000024;z-index:9999;min-width:290px;max-width:360px;animation:toastSlideIn .32s cubic-bezier(.34,1.56,.64,1);overflow:hidden}@keyframes toastSlideIn{0%{transform:translate(110%);opacity:0}to{transform:translate(0);opacity:1}}.step-toast-icon{width:34px;height:34px;background:#dcfce7;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;color:#16a34a}.step-toast-body{flex:1}.step-toast-title{font-size:14px;font-weight:700;color:#1e293b;margin-bottom:2px}.step-toast-msg{font-size:12px;color:#69707d;line-height:1.4}.step-toast-progress{position:absolute;bottom:0;left:0;height:3px;background:#22c55e;border-radius:0 2px 2px 0;animation:toastProgress 3.5s linear forwards}@keyframes toastProgress{0%{width:100%}to{width:0%}}@media screen and (max-width: 767px){.step-card-header{padding:14px 16px}.step-card-body{padding:16px 16px 8px}.step-toast{right:12px;bottom:16px;min-width:calc(100vw - 24px);max-width:calc(100vw - 24px)}}@media only screen and (min-width: 300px) and (max-width: 450px){.modal-content .close-popup{width:16px}}@media (max-width: 600px){.actions{flex-direction:column;align-items:stretch}.actions button{width:100%}}@media screen and (max-width: 767px){.sk-select-row{grid-template-columns:1fr}.tools-container h3,h5.title{font-size:18px}.form-control,textarea{font-size:16px}.tools-container{padding:16px}.tools-container .mob-view{display:flex;justify-content:space-between;flex-direction:column-reverse;gap:8px}.tools-container .mob-res{flex-direction:column-reverse;gap:8px}.footer-actions{flex-direction:column-reverse;gap:8px;margin-top:48px}.continue-btn{padding:10px 22px;width:100%}.back-btn{width:100%}.save-btn{padding:10px 15px;width:unset;margin-left:0!important}.preview-detail-grid{grid-template-columns:1fr}.preview-cell{border-right:none}.sk-grid,.sk-edit-row,.sk-fields-row{grid-template-columns:1fr}}.dashboard-modal-overlay{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;z-index:1050;animation:fadeInOverlay .2s ease}@keyframes fadeInOverlay{0%{opacity:0}to{opacity:1}}.dashboard-modal{background:#fff;border-radius:12px;padding:40px 36px 32px;max-width:440px;width:90%;text-align:center;box-shadow:0 20px 60px #0000002e;animation:slideUpModal .25s ease}@keyframes slideUpModal{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.dashboard-modal-icon{display:flex;justify-content:center;margin-bottom:20px}.dashboard-modal-icon svg{width:56px;height:56px}.dashboard-modal-title{font-size:18px;font-weight:700;color:#1e293b;margin-bottom:12px}.dashboard-modal-message{font-size:14px;color:#69707d;line-height:1.6;margin-bottom:28px}.dashboard-modal-actions{display:flex;gap:12px;justify-content:center}.modal-cancel-btn{height:42px;min-width:110px;border-radius:5px;border:1.5px solid #D4DAE6;background:#d4dae6;color:#69707d;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.modal-cancel-btn:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.modal-confirm-btn{height:42px;min-width:150px;border-radius:5px;border:none;background:#4077ad;color:#fff;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.modal-confirm-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.modal-confirm-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}\n"], dependencies: [{ kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i7.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: i7.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i7.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i7.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i12.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd", "deselectOnClick"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { kind: "directive", type: Ng2LoadingSpinnerDirective, selector: "[ng2-loading]", inputs: ["ng2-loading", "config", "template"] }, { kind: "component", type: NgxStarsComponent, selector: "ngx-stars", inputs: ["maxStars", "initialStars", "readonly", "size", "color", "animation", "animationSpeed", "customPadding", "wholeStars", "customStarIcons"], outputs: ["ratingOutput"] }, { kind: "directive", type: i14.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }], animations: [
|
|
11130
11120
|
trigger('expandCollapse', [
|
|
11131
11121
|
state('open', style({
|
|
11132
11122
|
height: '*',
|
|
@@ -11164,7 +11154,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
11164
11154
|
})),
|
|
11165
11155
|
transition('open <=> closed', animate('300ms ease'))
|
|
11166
11156
|
])
|
|
11167
|
-
], template: "<!-- \u2500\u2500\u2500 Tools Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"tools-container\" *ngIf=\"store.toolStepView() === 'preview'\">\r\n <div class=\"preview-header\">\r\n <div class=\"preview-header-icon\">\r\n <img src=\"/assets/images/icons/tools.svg\" alt=\"tools\" width=\"20\" height=\"20\" />\r\n </div>\r\n <div>\r\n <h3 class=\"preview-header-title\">Tools & Equipment</h3>\r\n <p class=\"preview-subtitle\">{{ userToolsPreview.length }} tool{{ userToolsPreview.length !== 1 ? 's' : '' }} added</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sk-grid\">\r\n <div *ngFor=\"let tool of userToolsPreview; let i = index\" class=\"sk-card sk-card--tool\">\r\n <div class=\"sk-card-body\">\r\n\r\n <div class=\"sk-head\">\r\n <div class=\"sk-avatar sk-avatar--tool\">{{ (tool.toolName || '?').charAt(0).toUpperCase() }}</div>\r\n <div class=\"sk-title-block\">\r\n <span class=\"sk-name\">{{ tool.toolName }}</span>\r\n <span class=\"sk-sub\" *ngIf=\"tool.providerName\">{{ tool.providerName }}</span>\r\n </div>\r\n <div class=\"sk-top-actions\">\r\n <ng-container *ngIf=\"isEditMode && editingToolKey === getToolKey(tool)\">\r\n <button class=\"sk-text-btn cancel\" type=\"button\" (click)=\"backTool(null)\">Cancel</button>\r\n <button class=\"sk-text-btn save\" type=\"button\" (click)=\"saveUserTools()\" [disabled]=\"showLoader\">Update</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isEditMode || editingToolKey !== getToolKey(tool)\">\r\n <button class=\"icon-btn edit-btn\" (click)=\"editToolFromPreview(tool, null, $event)\" title=\"Edit\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </button>\r\n <button class=\"icon-btn delete-btn\" (click)=\"deleteToolFromPreview(tool, $event)\" title=\"Delete\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/></svg>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- View mode -->\r\n <ng-container *ngIf=\"!isEditMode || editingToolKey !== getToolKey(tool)\">\r\n <div class=\"detail-row\">\r\n <div class=\"detail-item\" *ngIf=\"tool.year\">\r\n <span class=\"detail-label\">Years of Experience</span>\r\n <span class=\"detail-value\">{{ tool.year }} yr(s)</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.make\">\r\n <span class=\"detail-label\">Manufacturer</span>\r\n <span class=\"detail-value\">{{ tool.make }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.model\">\r\n <span class=\"detail-label\">Model</span>\r\n <span class=\"detail-value\">{{ tool.model }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.serialNumber\">\r\n <span class=\"detail-label\">Serial Number</span>\r\n <span class=\"detail-value\">{{ tool.serialNumber }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.profileVisibility\">\r\n <span class=\"detail-label\">Visibility</span>\r\n <span class=\"detail-value\">Active</span>\r\n </div>\r\n </div>\r\n <div class=\"sk-stars-row stars-readonly\">\r\n <ngx-stars [initialStars]=\"tool.starRating\" [maxStars]=\"5\"></ngx-stars>\r\n </div>\r\n <p class=\"sk-description\" *ngIf=\"tool.notes\">{{ tool.notes }}</p>\r\n </ng-container>\r\n\r\n <!-- Edit mode (inline) -->\r\n <ng-container *ngIf=\"isEditMode && editingToolKey === getToolKey(tool)\" [formGroup]=\"tab.at(0)\">\r\n <div class=\"sk-edit-panel\">\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Self Ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars [initialStars]=\"(tab.at(0).get('starRating')?.value || 0) / 2\" [maxStars]=\"5\"\r\n (ratingOutput)=\"onRatingSets($event)\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" bindLabel=\"text\" bindValue=\"value\"\r\n formControlName=\"year\" [clearable]=\"false\" [searchable]=\"false\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-edit-field sk-toggle-field\">\r\n <label class=\"sk-label\">Active</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Manufacturer</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"make\">\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Model</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"model\">\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Serial Number</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"serialNumber\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-field sk-edit-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea class=\"form-control\" rows=\"2\" formControlName=\"notes\"></textarea>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \u2500\u2500\u2500 Tools Add \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"tools-container\" *ngIf=\"store.toolStepView() === 'add'\">\r\n <div class=\"step-card-header mb-4\" style=\"border-radius: 10px;\">\r\n <div class=\"step-card-header-icon\">\r\n <img src=\"/assets/images/icons/tools.svg\" alt=\"tools\" width=\"22\" height=\"22\" />\r\n </div>\r\n <div>\r\n <h3 class=\"step-card-title\">Add Tools & Equipment</h3>\r\n <p class=\"step-card-subtitle\">Manage specialty tools and equipment</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Step 1: Search + select tools -->\r\n <div class=\"sk-section\">\r\n <div class=\"sk-select-row\">\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Profession</label>\r\n <ng-select\r\n [items]=\"professions\"\r\n bindLabel=\"professionName\"\r\n bindValue=\"id\"\r\n [(ngModel)]=\"selectedProfessionValue\"\r\n [clearable]=\"false\"\r\n (change)=\"onProfessionChange($event)\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Tool</label>\r\n <div class=\"search-part\" *ngIf=\"!isEditMode\">\r\n <input type=\"text\" placeholder=\"Search / Add Tools here\" [(ngModel)]=\"searchToolQry\" (input)=\"getTools()\" />\r\n <button class=\"btn\" (click)=\"createNewTools()\" tooltip=\"Add Tool\">\r\n <img src=\"/assets/images/icons/plus.svg\" alt=\"add\" class=\"create-plus\" width=\"18\" height=\"18\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"!searchToolQry && toolSubmittedValue\" class=\"invalid-feedback is-invalid d-block\">\r\n Please Enter Tools Name\r\n </div>\r\n <div *ngIf=\"nameError\" class=\"invalid-feedback is-invalid d-block\">{{ nameError }}</div>\r\n <div class=\"tool-chips-wrapper\" #toolChipsWrapper [ngClass]=\"showLoading ? 'loader' : ''\"\r\n [class.chips-collapsed]=\"!showAllTools\">\r\n <div class=\"tool-chips\" [class.collapsed]=\"!showAllTools\"\r\n [ngStyle]=\"showLoader ? {'min-height': '120px'} : {}\">\r\n <label class=\"tool-chip\" *ngFor=\"let Tool of tools\"\r\n [class.selected]=\"Tool.selected\"\r\n [attr.for]=\"Tool.id\"\r\n (mouseenter)=\"onToolChipMouseEnter($event, Tool)\">\r\n <input type=\"checkbox\" [checked]=\"Tool.selected\"\r\n (change)=\"onSelectedTools($event, Tool)\"\r\n [id]=\"Tool.id\" [name]=\"Tool.id\" />\r\n <svg *ngIf=\"Tool.selected\" class=\"chip-check-icon\" width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n {{ Tool.name }}\r\n <div class=\"chip-popover\" [class.chip-popover--below]=\"flippedToolChipId === Tool.id\" *ngIf=\"Tool.professionName || Tool.professionGroup || Tool.residentialCommercial || Tool.professionDescription\" (click)=\"$event.preventDefault(); $event.stopPropagation()\">\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionName\">\r\n <span class=\"chip-popover-label\">Profession Name</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionName }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionGroup\">\r\n <span class=\"chip-popover-label\">Profession Group</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionGroup }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.residentialCommercial\">\r\n <span class=\"chip-popover-label\">Residential / Commercial</span>\r\n <span class=\"chip-popover-value\">{{ Tool.residentialCommercial }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionDescription\">\r\n <span class=\"chip-popover-label\">Description</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionDescription }}</span>\r\n </div>\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n <button *ngIf=\"!showLoading && tools.length > 0\" type=\"button\"\r\n class=\"show-more-btn\" (click)=\"showAllTools = !showAllTools\">\r\n {{ showAllTools ? 'Show Less' : 'Show More' }}\r\n <svg [class.rotated]=\"showAllTools\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Step 2: Per-tool detail cards (replaces tabset) -->\r\n <div class=\"sk-detail-list\" #toolDetailList\r\n *ngIf=\"tab?.controls.length > 0\"\r\n [ngClass]=\"{ 'loader': showLoading, 'edit-mode': isEditMode }\">\r\n <div class=\"sk-detail-list-header\">\r\n <span class=\"sk-section-label\">Tool Details</span>\r\n <span class=\"sk-count-badge\">{{ tab?.controls.length }} selected</span>\r\n </div>\r\n\r\n <div *ngFor=\"let group of tab?.controls; let index = index\"\r\n [formGroup]=\"group\" class=\"sk-detail-card\">\r\n <div class=\"sk-detail-card-hd\">\r\n <div class=\"sk-detail-avatar sk-detail-avatar--tool\">{{ (tabs[index] || '?').charAt(0).toUpperCase() }}</div>\r\n <span class=\"sk-detail-card-name\">{{ tabs[index] }}</span>\r\n <div class=\"sk-detail-card-actions\">\r\n <label class=\"sk-copy-toggle\" *ngIf=\"tab?.controls.length > 1 && index === 0\" title=\"Copy these values to all tools\">\r\n <input type=\"checkbox\" class=\"form-check-input\"\r\n (click)=\"setCopyToAllTabs(index, group.value, false)\" role=\"switch\" />\r\n Copy to all\r\n </label>\r\n <button *ngIf=\"!isEditMode\" class=\"icon-btn delete-btn\" type=\"button\"\r\n (click)=\"removeTab(index, group.controls.toolId.value)\" title=\"Remove\">\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6L6 18M6 6l12 12\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"sk-detail-fields\">\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Self-ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars [initialStars]=\"initialStarts\" (ratingOutput)=\"onRatingSet($event, index)\"\r\n [ngClass]=\"{ 'is-invalid': userToolSubmitted && k.starRating.errors }\" [maxStars]=\"5\">\r\n </ngx-stars>\r\n <div *ngIf=\"userToolSubmitted && k.starRating.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Rating is required\r\n </div>\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" bindLabel=\"text\" (change)=\"onYearChange(group)\"\r\n formControlName=\"year\"\r\n [ngClass]=\"{ 'is-invalid': userToolSubmitted && k.year.errors }\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" [clearable]=\"false\" [searchable]=\"false\"\r\n placeholder=\"Select\" [appendTo]=\"'body'\"></ng-select>\r\n <div *ngIf=\"userToolSubmitted && k.year.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Year is required\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-toggle-field\">\r\n <label class=\"sk-label\">Profile Visibility</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\" />\r\n </div>\r\n </div>\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Manufacturer</label>\r\n <input formControlName=\"make\" class=\"form-control\" type=\"text\"\r\n placeholder=\"e.g. Fluke, Bosch...\" (change)=\"onYearChange(group)\" />\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Model</label>\r\n <input formControlName=\"model\" class=\"form-control\" type=\"text\"\r\n placeholder=\"Model name / number\" (change)=\"onYearChange(group)\" />\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Serial Number</label>\r\n <input formControlName=\"serialNumber\" class=\"form-control\" type=\"text\"\r\n placeholder=\"Serial / asset number\" />\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-field-full\">\r\n <label class=\"sk-label\">Comment</label>\r\n <textarea placeholder=\"Additional notes about this tool...\" formControlName=\"notes\"\r\n class=\"form-control\"\r\n [ngClass]=\"{ 'is-invalid': userToolSubmitted && k.notes.errors }\" rows=\"2\"></textarea>\r\n <div *ngIf=\"userToolSubmitted && k.notes.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Description is required\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Add mode -->\r\n<div class=\"tools-container last\" *ngIf=\"store.toolStepView() === 'add'\">\r\n <div class=\"d-flex justify-content-between pt-3 mob-res\">\r\n <button class=\"back-btn\" (click)=\"userToolsPreview.length > 0 ? cancel() : goBack()\">\r\n <svg *ngIf=\"userToolsPreview.length > 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\r\n <svg *ngIf=\"userToolsPreview.length === 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n {{ userToolsPreview.length > 0 ? 'Cancel' : 'Back' }}\r\n </button>\r\n <div class=\"mob-view\">\r\n <button (click)=\"onToolContinue()\" [ng2-loading]=\"showLoader\" [disabled]=\"showLoader\" class=\"float-end save-btn\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add\r\n </button>\r\n <button *ngIf=\"userToolsPreview.length === 0\" [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\"\r\n (click)=\"openDashboardModal()\" class=\"float-end save-btn ms-2\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H5a1 1 0 01-1-1V9.5z\"/><path d=\"M9 21V12h6v9\"/></svg>\r\n Go To Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Preview mode -->\r\n<div class=\"tools-container last\" *ngIf=\"store.toolStepView() !== 'add'\">\r\n <div class=\"d-flex justify-content-between pt-3 mob-res\">\r\n <button class=\"back-btn\" (click)=\"goBack()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n Back\r\n </button>\r\n <div class=\"mob-view\">\r\n <button class=\"back-btn me-3 add\" *ngIf=\"store.toolStepView() === 'preview'\" (click)=\"goToAddSkillsMode()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add More Tools\r\n </button>\r\n <button [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\" (click)=\"openDashboardModal()\"\r\n class=\"float-end save-btn\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H5a1 1 0 01-1-1V9.5z\"/><path d=\"M9 21V12h6v9\"/></svg>\r\n Go To Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Dashboard Confirmation Modal -->\r\n<div class=\"dashboard-modal-overlay\" *ngIf=\"showDashboardModal\" (click)=\"closeDashboardModal()\">\r\n <div class=\"dashboard-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"dashboard-modal-icon\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <circle cx=\"12\" cy=\"12\" r=\"11\" stroke=\"#22c55e\" stroke-width=\"1.5\"/>\r\n <path d=\"M7 12.5l3.5 3.5 6.5-7\" stroke=\"#22c55e\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n <h3 class=\"dashboard-modal-title\">All Information Saved!</h3>\r\n <p class=\"dashboard-modal-message\">\r\n Your profile setup is complete. All your information has been saved successfully.\r\n Clicking <strong>Go to Dashboard</strong> will take you to your dashboard.\r\n </p>\r\n <div class=\"dashboard-modal-actions\">\r\n <button type=\"button\" class=\"modal-cancel-btn\" (click)=\"closeDashboardModal()\">Cancel</button>\r\n <button type=\"button\" class=\"modal-confirm-btn\" [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\"\r\n (click)=\"closeDashboardModal(); saveFinal()\">\r\n Go to Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".tools-container{max-width:1000px;margin:0 auto;padding:28px 24px;min-height:300px;background:#fff}.tools-container.last{min-height:unset}.tools-container h3{font-size:18px;font-weight:700;color:#1e293b;margin-bottom:4px}.tools-container .info{font-size:14px;color:#69707d;margin-bottom:24px}.content-part{background:#fff}.content-part p{font-size:13px;color:#69707d}.content-part div{font-size:14px}.content-part div .label{font-size:12px!important;font-weight:700!important;color:#69707d!important;text-transform:uppercase;letter-spacing:.05em;padding-bottom:6px!important}.content-part .row{margin-top:-15px}.content-part .sub-section{padding:0 10px}.content-part .sub-section .title{font-size:15px;font-weight:500;color:#1e293b}.content-part .sub-section .info-title{font-size:12px;font-weight:400;color:#69707d;margin-left:5px}.content-part .sub-section .content{font-size:13px;color:#69707d}.content-part .sub-section .subsection{font-weight:600;padding-top:10px;font-size:12px;color:#69707d}.content-part .sub-section .subsection input{width:30%}.content-part .sub-section .icon{width:35px;filter:opacity(.5)}.content-part .tab-card{background:#fff;border:1px solid #e2e8f0;border-radius:8px;color:#1e293b}.content-part .tab-card .row{margin-top:2px}.search-part{width:100%;height:42px;position:relative;border-radius:8px;border:1.5px solid #e2e8f0;padding:0 0 0 14px;display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;background:#f9fafb;transition:all .2s ease}.search-part:focus-within{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.search-part input{width:auto;flex:1;color:#1e293b;font-size:14px;font-weight:400;border:none;background:none;outline:none}.search-part input::placeholder{color:#69707d}.search-part .btn{background:#4077ad;border-radius:5px;padding:0;width:42px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:0;border:none;cursor:pointer;transition:all .2s ease}.search-part .btn:hover{background:#2d5a8a}.search-part .btn img{filter:brightness(0) invert(1);width:16px;height:16px}textarea{width:100%;min-height:96px;background:#f9fafb;border:1.5px solid #e2e8f0;border-radius:8px;padding:12px 14px;font-size:14px;color:#1e293b;resize:vertical;outline:none;transition:all .2s ease}textarea:focus{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.tool-chips-wrapper{margin:8px 0 4px;position:relative;max-height:300px;overflow-y:auto}.tool-chips-wrapper.chips-collapsed:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:52px;background:linear-gradient(to bottom,transparent,#ffffff);pointer-events:none}.tool-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.tool-chips.collapsed{max-height:190px;overflow:hidden}.show-more-btn{display:inline-flex;align-items:center;gap:5px;background:none;border:1.5px solid #e2e8f0;border-radius:5px;color:#4077ad;font-size:14px;font-weight:600;padding:5px 14px;cursor:pointer;transition:all .2s ease;margin-bottom:12px}.show-more-btn:hover{background:#ebf2f9;border-color:#4077ad}.show-more-btn svg{transition:transform .2s ease}.show-more-btn svg.rotated{transform:rotate(180deg)}.tool-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:12px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4;position:relative}.tool-chip input[type=checkbox]{display:none}.tool-chip .chip-check-icon{flex-shrink:0}.tool-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.tool-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.tool-chip .chip-popover{display:none;position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;padding:10px 14px;min-width:220px;max-width:300px;z-index:99999;text-align:left;pointer-events:none;white-space:normal}.tool-chip .chip-popover:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:7px solid transparent;border-top-color:#e2e8f0}.tool-chip .chip-popover:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:-1px;border:6px solid transparent;border-top-color:#fff;z-index:1}.tool-chip .chip-popover--below{bottom:auto;top:calc(100% + 10px)}.tool-chip .chip-popover--below:after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:#e2e8f0}.tool-chip .chip-popover--below:before{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-top-color:transparent;border-bottom-color:#fff}.tool-chip:hover .chip-popover{display:block}.chip-popover-row{display:flex;flex-direction:column;gap:2px;padding:5px 0;border-bottom:1px solid #e2e8f0}.chip-popover-row:last-child{border-bottom:none;padding-bottom:0}.chip-popover-row:first-child{padding-top:0}.chip-popover-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#69707d;line-height:1.3}.chip-popover-value{font-size:12px;font-weight:500;color:#1e293b;line-height:1.45;word-break:break-word}.form-check-input{width:43px;height:21px;margin:0 5px;background-color:#c7c7c7!important;background-image:url(/assets/images/icons/toogle-circle.svg);background-position:left 4px top 2px;background-size:15px;border:1px solid #c7c7c7;outline:none!important;box-shadow:none!important;border-radius:25px;cursor:pointer}.form-check-input:checked{background-position:right 4px top 2px;background-image:url(/assets/images/icons/toogle-circle.svg);background-color:#22c55e!important;border:1px solid #22c55e!important}.copyAll{position:absolute;right:0;text-align:end;top:-40px}.close-popup{position:absolute;right:7px;top:4px;width:25px;cursor:pointer;opacity:.6;transition:all .2s ease}.close-popup:hover{opacity:1}.form-control{color:#1e293b;background:#f9fafb!important;font-size:14px;height:42px;border:1.5px solid #e2e8f0;border-radius:8px;transition:all .2s ease}.form-control:focus{border-color:#4077ad;background:#fff!important;box-shadow:0 0 0 3px #4077ad1f!important}.form-control:focus{border:1.5px solid #4077AD;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .nav-link{color:#69707d!important}::ng-deep .nav-link.active{color:#4077ad!important;font-weight:600}.loader{filter:blur(3px)}.edit-mode ::ng-deep .nav-tabs{display:none!important}::ng-deep accordion-group+accordion-group{margin-top:20px}.back-btn{height:42px;min-width:130px;background:#69707d;color:#fff;border:1.5px solid #69707D;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.back-btn:hover{border-color:#565c66;color:#fff;background:#565c66}.back-btn.edit{padding:5px 20px;min-height:20px;min-width:auto}.back-btn.add{background:#f2f4fa;color:#69707d;border:1.5px solid #F2F4FA}.back-btn.add:hover{background:#e4e8f2;border-color:#e4e8f2;color:#69707d}.save-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease;margin-left:15px}.save-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.save-btn:active{transform:translateY(0)}.save-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.create-btn{height:42px;min-width:9rem;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.create-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.create-btn:active{transform:translateY(0)}.continue-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.continue-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.continue-btn:active{transform:translateY(0)}.continue-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:210px}.preview-header{display:flex;align-items:center;gap:14px;margin-bottom:24px;padding-bottom:18px;border-bottom:1px solid #e2e8f0}.preview-header-icon{width:42px;height:42px;background:#fff7ed;border-radius:10px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.preview-header-title{font-size:18px;font-weight:700;color:#1e293b;margin:0 0 2px}.preview-subtitle{font-size:12px;color:#69707d;margin:0}.sk-grid{display:grid;gap:14px;margin-bottom:24px}.sk-card{display:flex;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;transition:box-shadow .18s ease,transform .18s ease}.sk-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;transform:translateY(-1px)}.sk-card-body{flex:1;padding:14px 16px;min-width:0}.sk-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}.sk-avatar{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#4077ad,#2d5a8a);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;flex-shrink:0}.sk-avatar--tool{background:linear-gradient(135deg,#d97706,#b45309)}.sk-title-block{flex:1;min-width:0}.sk-name{display:block;font-size:16px;font-weight:700;color:#4077ad;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-sub{display:block;font-size:12px;color:#69707d;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-top-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.sk-text-btn{height:28px;padding:0 12px;border-radius:5px;font-size:12px;font-weight:600;cursor:pointer;border:none;transition:all .2s ease}.sk-text-btn.cancel{background:#d4dae6;color:#69707d;border:1px solid #D4DAE6}.sk-text-btn.cancel:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.sk-text-btn.save{background:#4077ad;color:#fff;margin-left:4px}.sk-text-btn.save:hover{background:#2d5a8a}.sk-text-btn.save:disabled{background:#69707d;cursor:not-allowed}.icon-btn{width:28px;height:28px;border:none;min-width:unset!important;border-radius:5px;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.icon-btn.edit-btn{color:#4077ad}.icon-btn.edit-btn:hover{background:#ebf2f9}.icon-btn.delete-btn{color:#ef4444}.icon-btn.delete-btn:hover{background:#fef2f2}.sk-meta-row{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.chip.chip-year{background:#ebf2f9;color:#4077ad}.chip.chip-visible{background:#f0fdf4;color:#15803d}.chip.chip-make{background:#fff7ed;color:#c2410c}.chip.chip-model{background:#f5f3ff;color:#6d28d9}.chip.chip-serial{background:#f8fafc;color:#69707d;font-family:monospace;font-size:11px}.sk-stars-row{margin-bottom:6px}.sk-description{font-size:12px;color:#69707d;line-height:1.55;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.sk-edit-panel{margin-top:10px;padding-top:10px;border-top:1px solid #e2e8f0}.sk-edit-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:10px}.sk-edit-field{display:flex;flex-direction:column;gap:4px}.sk-edit-full{grid-column:1/-1;margin-top:4px}.sk-toggle-field{align-items:center;justify-content:center}.sk-label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em}.sk-section{margin-bottom:20px}.sk-section-label{font-size:12px;font-weight:700;color:#1e293b;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;display:block}.sk-detail-list{display:flex;flex-direction:column;gap:12px;margin-top:8px}.sk-detail-list-header{display:flex;align-items:center;gap:10px;margin-bottom:4px}.sk-count-badge{display:inline-flex;align-items:center;padding:2px 8px;background:#fff7ed;color:#d97706;border-radius:20px;font-size:12px;font-weight:600}.sk-detail-card{border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden}.sk-detail-card-hd{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fff7ed;border-bottom:1px solid #e2e8f0}.sk-detail-avatar{width:32px;height:32px;border-radius:8px;background:#d97706;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;flex-shrink:0}.sk-detail-avatar--tool{background:#d97706}.sk-detail-card-name{flex:1;font-size:14px;font-weight:700;color:#92400e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-detail-card-actions{display:flex;align-items:center;gap:10px;flex-shrink:0}.sk-copy-toggle{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:#69707d;cursor:pointer;-webkit-user-select:none;user-select:none}.sk-detail-fields{padding:14px 16px}.sk-fields-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:12px}.sk-field{display:flex;flex-direction:column;gap:4px}.sk-field-full{grid-column:1/-1}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;margin-bottom:16px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden;background:#fff;transition:box-shadow .25s ease}.skill-preview-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a}.skill-preview-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:#fff;font-size:15px;font-weight:700;color:#1e293b;border-bottom:1px solid transparent;cursor:pointer}.skill-preview-header.open{background:#ebf2f9;color:#2d5a8a;border-bottom:1px solid #e2e8f0}.skill-preview-body{padding:0;background:#fff}.skill-preview-body label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.skill-preview-body .value{font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word}h5.title{font-size:22px;font-weight:700;color:#1e293b!important;margin-bottom:4px}.preview-detail-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0}.preview-cell{padding:14px 20px;border-bottom:1px solid #e2e8f0;border-right:1px solid #e2e8f0}.preview-cell:nth-child(3n){border-right:none}.preview-full{grid-column:1/-1;border-right:none;border-bottom:none}.preview-label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.preview-value{display:block;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word;min-height:21px}.stars-readonly{pointer-events:none;display:block}.action-btns{display:flex;justify-content:space-between;align-items:center}.actions{display:flex;justify-content:flex-end;gap:12px;margin-top:16px}.actions button{height:42px;padding:10px 22px;border:none;border-radius:5px;font-size:14px;transition:all .2s ease;font-weight:600;min-width:120px;cursor:pointer}.actions .secondary{color:#69707d;background:#fff;border:1.5px solid #e2e8f0}.actions .secondary:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.actions .primary{background:#4077ad;color:#fff}.actions .primary:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.actions .primary:active{transform:translateY(0)}.footer-actions{display:flex;justify-content:space-between;align-items:center;margin-top:64px}.icon-color{cursor:pointer;width:20px;height:20px;background:transparent;transition:transform .2s ease;filter:brightness(0) saturate(100%) invert(48%) sepia(8%) saturate(350%) hue-rotate(170deg) brightness(92%) contrast(88%)}.icon-color.edit{width:18px;height:18px}.icon-color.rotate{transform:rotate(180deg)}.sk-select-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px}.sk-select-col{display:flex;flex-direction:column;gap:6px}.sk-select-col .search-part{margin-bottom:0;max-width:unset}.step-card{max-width:1000px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 1px 3px #0000000f,0 4px 16px #4077ad14}.step-card-header{display:flex;align-items:center;gap:16px;padding:20px 28px;background:linear-gradient(135deg,#ebf2f9,#f0f6ff);border-bottom:1px solid #d5e8f5;border-radius:12px 12px 0 0}.step-card-header-icon{width:46px;height:46px;background:#fff;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px #4077ad2e;flex-shrink:0}.step-card-header-icon img{filter:brightness(0) saturate(100%) invert(37%) sepia(55%) saturate(500%) hue-rotate(190deg) brightness(95%) contrast(85%);width:22px;height:22px}.step-card-title{font-size:16px;font-weight:700;color:#1e293b;margin:0 0 3px;letter-spacing:-.01em}.step-card-subtitle{font-size:14px;color:#69707d;margin:0;line-height:1.4}.step-card-body{padding:24px 28px 8px}.field-section{margin-bottom:18px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px 6px}.field-section-title{font-size:12px;font-weight:700;color:#4077ad;text-transform:uppercase;letter-spacing:.07em;margin-bottom:14px;display:flex;align-items:center;gap:7px}.field-section-title:before{content:\"\";display:inline-block;width:5px;height:5px;background:#4077ad;border-radius:50%;flex-shrink:0}.doc-type-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.doc-type-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:13px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4}.doc-type-chip input[type=checkbox]{display:none}.doc-type-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.doc-type-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.detail-row{display:flex;flex-wrap:wrap;column-gap:22px;row-gap:6px;margin-bottom:8px}.detail-item{display:flex;align-items:baseline;gap:6px;white-space:nowrap}.detail-label{font-size:14px;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:#4077ad}.detail-value{font-size:12.5px;font-weight:600;color:#1e293b}button.primary,button.secondary,button.back-btn,button.continue-btn,button.save-btn,button.add-btn,button.upload-btn,.actions button,.action button,.navigation-buttons button{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-radius:5px;box-shadow:none}button.primary svg,button.secondary svg,button.back-btn svg,button.continue-btn svg,button.save-btn svg,button.add-btn svg,button.upload-btn svg,.actions button svg,.action button svg,.navigation-buttons button svg{flex-shrink:0;width:14px;height:14px}.step-toast{position:fixed;bottom:28px;right:28px;display:flex;align-items:flex-start;gap:14px;background:#fff;border-radius:12px;padding:16px 20px 20px;box-shadow:0 8px 32px #00000024;z-index:9999;min-width:290px;max-width:360px;animation:toastSlideIn .32s cubic-bezier(.34,1.56,.64,1);overflow:hidden}@keyframes toastSlideIn{0%{transform:translate(110%);opacity:0}to{transform:translate(0);opacity:1}}.step-toast-icon{width:34px;height:34px;background:#dcfce7;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;color:#16a34a}.step-toast-body{flex:1}.step-toast-title{font-size:14px;font-weight:700;color:#1e293b;margin-bottom:2px}.step-toast-msg{font-size:12px;color:#69707d;line-height:1.4}.step-toast-progress{position:absolute;bottom:0;left:0;height:3px;background:#22c55e;border-radius:0 2px 2px 0;animation:toastProgress 3.5s linear forwards}@keyframes toastProgress{0%{width:100%}to{width:0%}}@media screen and (max-width: 767px){.step-card-header{padding:14px 16px}.step-card-body{padding:16px 16px 8px}.step-toast{right:12px;bottom:16px;min-width:calc(100vw - 24px);max-width:calc(100vw - 24px)}}@media only screen and (min-width: 300px) and (max-width: 450px){.modal-content .close-popup{width:16px}}@media (max-width: 600px){.actions{flex-direction:column;align-items:stretch}.actions button{width:100%}}@media screen and (max-width: 767px){.sk-select-row{grid-template-columns:1fr}.tools-container h3,h5.title{font-size:18px}.form-control,textarea{font-size:16px}.tools-container{padding:16px}.tools-container .mob-view{display:flex;justify-content:space-between;flex-direction:column-reverse;gap:8px}.tools-container .mob-res{flex-direction:column-reverse;gap:8px}.footer-actions{flex-direction:column-reverse;gap:8px;margin-top:48px}.continue-btn{padding:10px 22px;width:100%}.back-btn{width:100%}.save-btn{padding:10px 15px;width:unset;margin-left:0!important}.preview-detail-grid{grid-template-columns:1fr}.preview-cell{border-right:none}.sk-grid,.sk-edit-row,.sk-fields-row{grid-template-columns:1fr}}.dashboard-modal-overlay{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;z-index:1050;animation:fadeInOverlay .2s ease}@keyframes fadeInOverlay{0%{opacity:0}to{opacity:1}}.dashboard-modal{background:#fff;border-radius:12px;padding:40px 36px 32px;max-width:440px;width:90%;text-align:center;box-shadow:0 20px 60px #0000002e;animation:slideUpModal .25s ease}@keyframes slideUpModal{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.dashboard-modal-icon{display:flex;justify-content:center;margin-bottom:20px}.dashboard-modal-icon svg{width:56px;height:56px}.dashboard-modal-title{font-size:18px;font-weight:700;color:#1e293b;margin-bottom:12px}.dashboard-modal-message{font-size:14px;color:#69707d;line-height:1.6;margin-bottom:28px}.dashboard-modal-actions{display:flex;gap:12px;justify-content:center}.modal-cancel-btn{height:42px;min-width:110px;border-radius:5px;border:1.5px solid #D4DAE6;background:#d4dae6;color:#69707d;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.modal-cancel-btn:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.modal-confirm-btn{height:42px;min-width:150px;border-radius:5px;border:none;background:#4077ad;color:#fff;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.modal-confirm-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.modal-confirm-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}\n"] }]
|
|
11157
|
+
], template: "<!-- \u2500\u2500\u2500 Tools Preview \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"tools-container\" *ngIf=\"store.toolStepView() === 'preview'\">\r\n <div class=\"preview-header\">\r\n <div class=\"preview-header-icon\">\r\n <img src=\"/assets/images/icons/tools.svg\" alt=\"tools\" width=\"20\" height=\"20\" />\r\n </div>\r\n <div>\r\n <h3 class=\"preview-header-title\">Tools & Equipment</h3>\r\n <p class=\"preview-subtitle\">{{ userToolsPreview.length }} tool{{ userToolsPreview.length !== 1 ? 's' : '' }} added</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"sk-grid\">\r\n <div *ngFor=\"let tool of userToolsPreview; let i = index\" class=\"sk-card sk-card--tool\">\r\n <div class=\"sk-card-body\">\r\n\r\n <div class=\"sk-head\">\r\n <div class=\"sk-avatar sk-avatar--tool\">{{ (tool.toolName || '?').charAt(0).toUpperCase() }}</div>\r\n <div class=\"sk-title-block\">\r\n <span class=\"sk-name\">{{ tool.toolName }}</span>\r\n <span class=\"sk-sub\" *ngIf=\"tool.providerName\">{{ tool.providerName }}</span>\r\n </div>\r\n <div class=\"sk-top-actions\">\r\n <ng-container *ngIf=\"isEditMode && editingToolKey === getToolKey(tool)\">\r\n <button class=\"sk-text-btn cancel\" type=\"button\" (click)=\"backTool(null)\">Cancel</button>\r\n <button class=\"sk-text-btn save\" type=\"button\" (click)=\"saveUserTools()\" [disabled]=\"showLoader\">Update</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isEditMode || editingToolKey !== getToolKey(tool)\">\r\n <button class=\"icon-btn edit-btn\" (click)=\"editToolFromPreview(tool, null, $event)\" title=\"Edit\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>\r\n </button>\r\n <button class=\"icon-btn delete-btn\" (click)=\"deleteToolFromPreview(tool, $event)\" title=\"Delete\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6\"/><path d=\"M10 11v6M14 11v6\"/><path d=\"M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2\"/></svg>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- View mode -->\r\n <ng-container *ngIf=\"!isEditMode || editingToolKey !== getToolKey(tool)\">\r\n <div class=\"detail-row\">\r\n <div class=\"detail-item\" *ngIf=\"tool.year\">\r\n <span class=\"detail-label\">Years of Experience</span>\r\n <span class=\"detail-value\">{{ tool.year }} yr(s)</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.make\">\r\n <span class=\"detail-label\">Manufacturer</span>\r\n <span class=\"detail-value\">{{ tool.make }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.model\">\r\n <span class=\"detail-label\">Model</span>\r\n <span class=\"detail-value\">{{ tool.model }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.serialNumber\">\r\n <span class=\"detail-label\">Serial Number</span>\r\n <span class=\"detail-value\">{{ tool.serialNumber }}</span>\r\n </div>\r\n <div class=\"detail-item\" *ngIf=\"tool.profileVisibility\">\r\n <span class=\"detail-label\">Visibility</span>\r\n <span class=\"detail-value\">Active</span>\r\n </div>\r\n </div>\r\n <div class=\"sk-stars-row stars-readonly\">\r\n <ngx-stars [initialStars]=\"tool.starRating\" [maxStars]=\"5\"></ngx-stars>\r\n </div>\r\n <p class=\"sk-description\" *ngIf=\"tool.notes\">{{ tool.notes }}</p>\r\n </ng-container>\r\n\r\n <!-- Edit mode (inline) -->\r\n <ng-container *ngIf=\"isEditMode && editingToolKey === getToolKey(tool)\" [formGroup]=\"tab.at(0)\">\r\n <div class=\"sk-edit-panel\">\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Self Ability Rating <span class=\"text-danger\">*</span></label>\r\n <ngx-stars [initialStars]=\"(tab.at(0).get('starRating')?.value || 0) / 2\" [maxStars]=\"5\"\r\n (ratingOutput)=\"onRatingSets($event)\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Years of Experience <span class=\"text-danger\">*</span></label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" bindLabel=\"text\" bindValue=\"value\"\r\n formControlName=\"year\" [clearable]=\"false\" [searchable]=\"false\" placeholder=\"Select\"\r\n [appendTo]=\"'body'\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-edit-field sk-toggle-field\">\r\n <label class=\"sk-label\">Active</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-row\">\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Manufacturer</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"make\">\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Model</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"model\">\r\n </div>\r\n <div class=\"sk-edit-field\">\r\n <label class=\"sk-label\">Serial Number</label>\r\n <input class=\"form-control\" type=\"text\" formControlName=\"serialNumber\">\r\n </div>\r\n </div>\r\n <div class=\"sk-edit-field sk-edit-full\">\r\n <label class=\"sk-label\">Description</label>\r\n <textarea class=\"form-control\" rows=\"2\" formControlName=\"notes\"></textarea>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \u2500\u2500\u2500 Tools Add \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n<div class=\"tools-container\" *ngIf=\"store.toolStepView() === 'add'\">\r\n <div class=\"step-card-header mb-4\" style=\"border-radius: 10px;\">\r\n <div class=\"step-card-header-icon\">\r\n <img src=\"/assets/images/icons/tools.svg\" alt=\"tools\" width=\"22\" height=\"22\" />\r\n </div>\r\n <div>\r\n <h3 class=\"step-card-title\">Add Tools & Equipment</h3>\r\n <p class=\"step-card-subtitle\">Manage specialty tools and equipment</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Step 1: Search + select tools -->\r\n <div class=\"sk-section\">\r\n <div class=\"sk-select-row\">\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Profession</label>\r\n <ng-select\r\n [items]=\"professions\"\r\n bindLabel=\"professionName\"\r\n bindValue=\"id\"\r\n [(ngModel)]=\"selectedProfessionValue\"\r\n [clearable]=\"false\"\r\n (change)=\"onProfessionChange($event)\">\r\n </ng-select>\r\n </div>\r\n <div class=\"sk-select-col\">\r\n <label class=\"sk-label\">Select Tool</label>\r\n <div class=\"search-part\" *ngIf=\"!isEditMode\">\r\n <input type=\"text\" placeholder=\"Search / Add Tools here\" [(ngModel)]=\"searchToolQry\" (input)=\"getTools()\" />\r\n <button class=\"btn\" (click)=\"createNewTools()\" tooltip=\"Add Tool\">\r\n <img src=\"/assets/images/icons/plus.svg\" alt=\"add\" class=\"create-plus\" width=\"18\" height=\"18\" />\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div *ngIf=\"!searchToolQry && toolSubmittedValue\" class=\"invalid-feedback is-invalid d-block\">\r\n Please Enter Tools Name\r\n </div>\r\n <div *ngIf=\"nameError\" class=\"invalid-feedback is-invalid d-block\">{{ nameError }}</div>\r\n <div class=\"tool-chips-wrapper\" #toolChipsWrapper [ngClass]=\"showLoading ? 'loader' : ''\"\r\n [class.chips-collapsed]=\"!showAllTools\">\r\n <div class=\"tool-chips\" [class.collapsed]=\"!showAllTools\"\r\n [ngStyle]=\"showLoader ? {'min-height': '120px'} : {}\">\r\n <label class=\"tool-chip\" *ngFor=\"let Tool of tools\"\r\n [class.selected]=\"Tool.selected\"\r\n [attr.for]=\"Tool.id\"\r\n (mouseenter)=\"onToolChipMouseEnter($event, Tool)\">\r\n <input type=\"checkbox\" [checked]=\"Tool.selected\"\r\n (change)=\"onSelectedTools($event, Tool)\"\r\n [id]=\"Tool.id\" [name]=\"Tool.id\" />\r\n <svg *ngIf=\"Tool.selected\" class=\"chip-check-icon\" width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\">\r\n <path d=\"M2 6l3 3 5-5\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n {{ Tool.name }}\r\n <div class=\"chip-popover\" [class.chip-popover--below]=\"flippedToolChipId === Tool.id\" *ngIf=\"Tool.professionName || Tool.professionGroup || Tool.residentialCommercial || Tool.professionDescription\" (click)=\"$event.preventDefault(); $event.stopPropagation()\">\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionName\">\r\n <span class=\"chip-popover-label\">Profession Name</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionName }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionGroup\">\r\n <span class=\"chip-popover-label\">Profession Group</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionGroup }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.residentialCommercial\">\r\n <span class=\"chip-popover-label\">Residential / Commercial</span>\r\n <span class=\"chip-popover-value\">{{ Tool.residentialCommercial }}</span>\r\n </div>\r\n <div class=\"chip-popover-row\" *ngIf=\"Tool.professionDescription\">\r\n <span class=\"chip-popover-label\">Description</span>\r\n <span class=\"chip-popover-value\">{{ Tool.professionDescription }}</span>\r\n </div>\r\n </div>\r\n </label>\r\n </div>\r\n </div>\r\n <button *ngIf=\"!showLoading && tools.length > 0\" type=\"button\"\r\n class=\"show-more-btn\" (click)=\"showAllTools = !showAllTools\">\r\n {{ showAllTools ? 'Show Less' : 'Show More' }}\r\n <svg [class.rotated]=\"showAllTools\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\"\r\n stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Step 2: Per-tool detail cards (replaces tabset) -->\r\n <div class=\"sk-detail-list\" #toolDetailList\r\n *ngIf=\"tab?.controls.length > 0\"\r\n [ngClass]=\"{ 'loader': showLoading, 'edit-mode': isEditMode }\">\r\n <div class=\"sk-detail-list-header\">\r\n <span class=\"sk-section-label\">Tool Details</span>\r\n <span class=\"sk-count-badge\">{{ tab?.controls.length }} selected</span>\r\n </div>\r\n\r\n <div *ngFor=\"let group of tab?.controls; let index = index\"\r\n [formGroup]=\"group\" class=\"sk-detail-card\">\r\n <div class=\"sk-detail-card-hd\">\r\n <div class=\"sk-detail-avatar sk-detail-avatar--tool\">{{ (tabs[index] || '?').charAt(0).toUpperCase() }}</div>\r\n <span class=\"sk-detail-card-name\">{{ tabs[index] }}</span>\r\n <div class=\"sk-detail-card-actions\">\r\n <label class=\"sk-copy-toggle\" *ngIf=\"tab?.controls.length > 1 && index === 0\" title=\"Copy these values to all tools\">\r\n <input type=\"checkbox\" class=\"form-check-input\"\r\n (click)=\"setCopyToAllTabs(index, group.value, false)\" role=\"switch\" />\r\n Copy to all\r\n </label>\r\n <button *ngIf=\"!isEditMode\" class=\"icon-btn delete-btn\" type=\"button\"\r\n (click)=\"removeTab(index, group.controls.toolId.value)\" title=\"Remove\">\r\n <svg width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M18 6L6 18M6 6l12 12\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"sk-detail-fields\">\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Self-ability Rating</label>\r\n <ngx-stars [initialStars]=\"initialStarts\" (ratingOutput)=\"onRatingSet($event, index)\"\r\n [maxStars]=\"5\">\r\n </ngx-stars>\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Years of Experience</label>\r\n <ng-select class=\"w-100\" [items]=\"expYears\" bindLabel=\"text\" (change)=\"onYearChange(group)\"\r\n formControlName=\"year\"\r\n bindValue=\"value\" [closeOnSelect]=\"true\" [clearable]=\"false\" [searchable]=\"false\"\r\n placeholder=\"Select\" [appendTo]=\"'body'\"></ng-select>\r\n </div>\r\n <div class=\"sk-field sk-toggle-field\">\r\n <label class=\"sk-label\">Profile Visibility</label>\r\n <input class=\"form-check-input\" type=\"checkbox\" formControlName=\"profileVisibility\" role=\"switch\" />\r\n </div>\r\n </div>\r\n <div class=\"sk-fields-row\">\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Manufacturer</label>\r\n <input formControlName=\"make\" class=\"form-control\" type=\"text\"\r\n placeholder=\"e.g. Fluke, Bosch...\" (change)=\"onYearChange(group)\" />\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Model</label>\r\n <input formControlName=\"model\" class=\"form-control\" type=\"text\"\r\n placeholder=\"Model name / number\" (change)=\"onYearChange(group)\" />\r\n </div>\r\n <div class=\"sk-field\">\r\n <label class=\"sk-label\">Serial Number</label>\r\n <input formControlName=\"serialNumber\" class=\"form-control\" type=\"text\"\r\n placeholder=\"Serial / asset number\" />\r\n </div>\r\n </div>\r\n <div class=\"sk-field sk-field-full\">\r\n <label class=\"sk-label\">Comment</label>\r\n <textarea placeholder=\"Additional notes about this tool...\" formControlName=\"notes\"\r\n class=\"form-control\"\r\n [ngClass]=\"{ 'is-invalid': userToolSubmitted && k.notes.errors }\" rows=\"2\"></textarea>\r\n <div *ngIf=\"userToolSubmitted && k.notes.errors\" class=\"invalid-feedback is-invalid d-block\">\r\n Description is required\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Add mode -->\r\n<div class=\"tools-container last\" *ngIf=\"store.toolStepView() === 'add'\">\r\n <div class=\"d-flex justify-content-between pt-3 mob-res\">\r\n <button class=\"back-btn\" (click)=\"userToolsPreview.length > 0 ? cancel() : goBack()\">\r\n <svg *ngIf=\"userToolsPreview.length > 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>\r\n <svg *ngIf=\"userToolsPreview.length === 0\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n {{ userToolsPreview.length > 0 ? 'Cancel' : 'Back' }}\r\n </button>\r\n <div class=\"mob-view\">\r\n <button (click)=\"onToolContinue()\" [ng2-loading]=\"showLoader\" [disabled]=\"showLoader\" class=\"float-end save-btn\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add\r\n </button>\r\n <button *ngIf=\"userToolsPreview.length === 0\" [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\"\r\n (click)=\"openDashboardModal()\" class=\"float-end save-btn ms-2\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H5a1 1 0 01-1-1V9.5z\"/><path d=\"M9 21V12h6v9\"/></svg>\r\n Go To Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Footer: Preview mode -->\r\n<div class=\"tools-container last\" *ngIf=\"store.toolStepView() !== 'add'\">\r\n <div class=\"d-flex justify-content-between pt-3 mob-res\">\r\n <button class=\"back-btn\" (click)=\"goBack()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M19 12H5M12 5l-7 7 7 7\"/></svg>\r\n Back\r\n </button>\r\n <div class=\"mob-view\">\r\n <button class=\"back-btn me-3 add\" *ngIf=\"store.toolStepView() === 'preview'\" (click)=\"goToAddSkillsMode()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 5v14M5 12h14\"/></svg>\r\n Add More Tools\r\n </button>\r\n <button [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\" (click)=\"openDashboardModal()\"\r\n class=\"float-end save-btn\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H5a1 1 0 01-1-1V9.5z\"/><path d=\"M9 21V12h6v9\"/></svg>\r\n Go To Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Dashboard Confirmation Modal -->\r\n<div class=\"dashboard-modal-overlay\" *ngIf=\"showDashboardModal\" (click)=\"closeDashboardModal()\">\r\n <div class=\"dashboard-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"dashboard-modal-icon\">\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <circle cx=\"12\" cy=\"12\" r=\"11\" stroke=\"#22c55e\" stroke-width=\"1.5\"/>\r\n <path d=\"M7 12.5l3.5 3.5 6.5-7\" stroke=\"#22c55e\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </div>\r\n <h3 class=\"dashboard-modal-title\">All Information Saved!</h3>\r\n <p class=\"dashboard-modal-message\">\r\n Your profile setup is complete. All your information has been saved successfully.\r\n Clicking <strong>Go to Dashboard</strong> will take you to your dashboard.\r\n </p>\r\n <div class=\"dashboard-modal-actions\">\r\n <button type=\"button\" class=\"modal-cancel-btn\" (click)=\"closeDashboardModal()\">Cancel</button>\r\n <button type=\"button\" class=\"modal-confirm-btn\" [disabled]=\"homeLoader\" [ng2-loading]=\"homeLoader\"\r\n (click)=\"closeDashboardModal(); saveFinal()\">\r\n Go to Dashboard\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".tools-container{max-width:1000px;margin:0 auto;padding:28px 24px;min-height:300px;background:#fff}.tools-container.last{min-height:unset}.tools-container h3{font-size:18px;font-weight:700;color:#1e293b;margin-bottom:4px}.tools-container .info{font-size:14px;color:#69707d;margin-bottom:24px}.content-part{background:#fff}.content-part p{font-size:13px;color:#69707d}.content-part div{font-size:14px}.content-part div .label{font-size:12px!important;font-weight:700!important;color:#69707d!important;text-transform:uppercase;letter-spacing:.05em;padding-bottom:6px!important}.content-part .row{margin-top:-15px}.content-part .sub-section{padding:0 10px}.content-part .sub-section .title{font-size:15px;font-weight:500;color:#1e293b}.content-part .sub-section .info-title{font-size:12px;font-weight:400;color:#69707d;margin-left:5px}.content-part .sub-section .content{font-size:13px;color:#69707d}.content-part .sub-section .subsection{font-weight:600;padding-top:10px;font-size:12px;color:#69707d}.content-part .sub-section .subsection input{width:30%}.content-part .sub-section .icon{width:35px;filter:opacity(.5)}.content-part .tab-card{background:#fff;border:1px solid #e2e8f0;border-radius:8px;color:#1e293b}.content-part .tab-card .row{margin-top:2px}.search-part{width:100%;height:42px;position:relative;border-radius:8px;border:1.5px solid #e2e8f0;padding:0 0 0 14px;display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;background:#f9fafb;transition:all .2s ease}.search-part:focus-within{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.search-part input{width:auto;flex:1;color:#1e293b;font-size:14px;font-weight:400;border:none;background:none;outline:none}.search-part input::placeholder{color:#69707d}.search-part .btn{background:#4077ad;border-radius:5px;padding:0;width:42px;height:40px;display:flex;align-items:center;justify-content:center;margin-right:0;border:none;cursor:pointer;transition:all .2s ease}.search-part .btn:hover{background:#2d5a8a}.search-part .btn img{filter:brightness(0) invert(1);width:16px;height:16px}textarea{width:100%;min-height:96px;background:#f9fafb;border:1.5px solid #e2e8f0;border-radius:8px;padding:12px 14px;font-size:14px;color:#1e293b;resize:vertical;outline:none;transition:all .2s ease}textarea:focus{border-color:#4077ad;background:#fff;box-shadow:0 0 0 3px #4077ad1f}.tool-chips-wrapper{margin:8px 0 4px;position:relative;max-height:300px;overflow-y:auto}.tool-chips-wrapper.chips-collapsed:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:52px;background:linear-gradient(to bottom,transparent,#ffffff);pointer-events:none}.tool-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.tool-chips.collapsed{max-height:190px;overflow:hidden}.show-more-btn{display:inline-flex;align-items:center;gap:5px;background:none;border:1.5px solid #e2e8f0;border-radius:5px;color:#4077ad;font-size:14px;font-weight:600;padding:5px 14px;cursor:pointer;transition:all .2s ease;margin-bottom:12px}.show-more-btn:hover{background:#ebf2f9;border-color:#4077ad}.show-more-btn svg{transition:transform .2s ease}.show-more-btn svg.rotated{transform:rotate(180deg)}.tool-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:12px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4;position:relative}.tool-chip input[type=checkbox]{display:none}.tool-chip .chip-check-icon{flex-shrink:0}.tool-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.tool-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.tool-chip .chip-popover{display:none;position:absolute;bottom:calc(100% + 10px);left:50%;transform:translate(-50%);background:#fff;border:1.5px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;padding:10px 14px;min-width:220px;max-width:300px;z-index:99999;text-align:left;pointer-events:none;white-space:normal}.tool-chip .chip-popover:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border:7px solid transparent;border-top-color:#e2e8f0}.tool-chip .chip-popover:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);margin-top:-1px;border:6px solid transparent;border-top-color:#fff;z-index:1}.tool-chip .chip-popover--below{bottom:auto;top:calc(100% + 10px)}.tool-chip .chip-popover--below:after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:#e2e8f0}.tool-chip .chip-popover--below:before{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-top-color:transparent;border-bottom-color:#fff}.tool-chip:hover .chip-popover{display:block}.chip-popover-row{display:flex;flex-direction:column;gap:2px;padding:5px 0;border-bottom:1px solid #e2e8f0}.chip-popover-row:last-child{border-bottom:none;padding-bottom:0}.chip-popover-row:first-child{padding-top:0}.chip-popover-label{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#69707d;line-height:1.3}.chip-popover-value{font-size:12px;font-weight:500;color:#1e293b;line-height:1.45;word-break:break-word}.form-check-input{width:43px;height:21px;margin:0 5px;background-color:#c7c7c7!important;background-image:url(/assets/images/icons/toogle-circle.svg);background-position:left 4px top 2px;background-size:15px;border:1px solid #c7c7c7;outline:none!important;box-shadow:none!important;border-radius:25px;cursor:pointer}.form-check-input:checked{background-position:right 4px top 2px;background-image:url(/assets/images/icons/toogle-circle.svg);background-color:#22c55e!important;border:1px solid #22c55e!important}.copyAll{position:absolute;right:0;text-align:end;top:-40px}.close-popup{position:absolute;right:7px;top:4px;width:25px;cursor:pointer;opacity:.6;transition:all .2s ease}.close-popup:hover{opacity:1}.form-control{color:#1e293b;background:#f9fafb!important;font-size:14px;height:42px;border:1.5px solid #e2e8f0;border-radius:8px;transition:all .2s ease}.form-control:focus{border-color:#4077ad;background:#fff!important;box-shadow:0 0 0 3px #4077ad1f!important}.form-control:focus{border:1.5px solid #4077AD;box-shadow:0 0 0 3px #4077ad1f}::ng-deep .nav-link{color:#69707d!important}::ng-deep .nav-link.active{color:#4077ad!important;font-weight:600}.loader{filter:blur(3px)}.edit-mode ::ng-deep .nav-tabs{display:none!important}::ng-deep accordion-group+accordion-group{margin-top:20px}.back-btn{height:42px;min-width:130px;background:#69707d;color:#fff;border:1.5px solid #69707D;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.back-btn:hover{border-color:#565c66;color:#fff;background:#565c66}.back-btn.edit{padding:5px 20px;min-height:20px;min-width:auto}.back-btn.add{background:#f2f4fa;color:#69707d;border:1.5px solid #F2F4FA}.back-btn.add:hover{background:#e4e8f2;border-color:#e4e8f2;color:#69707d}.save-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease;margin-left:15px}.save-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.save-btn:active{transform:translateY(0)}.save-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}.create-btn{height:42px;min-width:9rem;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 18px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.create-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.create-btn:active{transform:translateY(0)}.continue-btn{height:42px;min-width:130px;background:#4077ad;color:#fff;border:none;border-radius:5px;padding:10px 22px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.continue-btn:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.continue-btn:active{transform:translateY(0)}.continue-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}::ng-deep .ng-dropdown-panel{min-width:180px}::ng-deep .ng-dropdown-panel .ng-dropdown-panel-items{max-height:210px}.preview-header{display:flex;align-items:center;gap:14px;margin-bottom:24px;padding-bottom:18px;border-bottom:1px solid #e2e8f0}.preview-header-icon{width:42px;height:42px;background:#fff7ed;border-radius:10px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.preview-header-title{font-size:18px;font-weight:700;color:#1e293b;margin:0 0 2px}.preview-subtitle{font-size:12px;color:#69707d;margin:0}.sk-grid{display:grid;gap:14px;margin-bottom:24px}.sk-card{display:flex;border:1px solid #e2e8f0;border-radius:12px;overflow:hidden;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;transition:box-shadow .18s ease,transform .18s ease}.sk-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a;transform:translateY(-1px)}.sk-card-body{flex:1;padding:14px 16px;min-width:0}.sk-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}.sk-avatar{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#4077ad,#2d5a8a);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;flex-shrink:0}.sk-avatar--tool{background:linear-gradient(135deg,#d97706,#b45309)}.sk-title-block{flex:1;min-width:0}.sk-name{display:block;font-size:16px;font-weight:700;color:#4077ad;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-sub{display:block;font-size:12px;color:#69707d;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-top-actions{display:flex;align-items:center;gap:2px;flex-shrink:0}.sk-text-btn{height:28px;padding:0 12px;border-radius:5px;font-size:12px;font-weight:600;cursor:pointer;border:none;transition:all .2s ease}.sk-text-btn.cancel{background:#d4dae6;color:#69707d;border:1px solid #D4DAE6}.sk-text-btn.cancel:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.sk-text-btn.save{background:#4077ad;color:#fff;margin-left:4px}.sk-text-btn.save:hover{background:#2d5a8a}.sk-text-btn.save:disabled{background:#69707d;cursor:not-allowed}.icon-btn{width:28px;height:28px;border:none;min-width:unset!important;border-radius:5px;background:transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.icon-btn.edit-btn{color:#4077ad}.icon-btn.edit-btn:hover{background:#ebf2f9}.icon-btn.delete-btn{color:#ef4444}.icon-btn.delete-btn:hover{background:#fef2f2}.sk-meta-row{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:500;line-height:1.6;white-space:nowrap}.chip.chip-year{background:#ebf2f9;color:#4077ad}.chip.chip-visible{background:#f0fdf4;color:#15803d}.chip.chip-make{background:#fff7ed;color:#c2410c}.chip.chip-model{background:#f5f3ff;color:#6d28d9}.chip.chip-serial{background:#f8fafc;color:#69707d;font-family:monospace;font-size:11px}.sk-stars-row{margin-bottom:6px}.sk-description{font-size:12px;color:#69707d;line-height:1.55;margin:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.sk-edit-panel{margin-top:10px;padding-top:10px;border-top:1px solid #e2e8f0}.sk-edit-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:10px}.sk-edit-field{display:flex;flex-direction:column;gap:4px}.sk-edit-full{grid-column:1/-1;margin-top:4px}.sk-toggle-field{align-items:center;justify-content:center}.sk-label{font-size:12px;font-weight:700;color:#69707d;text-transform:uppercase;letter-spacing:.05em}.sk-section{margin-bottom:20px}.sk-section-label{font-size:12px;font-weight:700;color:#1e293b;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;display:block}.sk-detail-list{display:flex;flex-direction:column;gap:12px;margin-top:8px}.sk-detail-list-header{display:flex;align-items:center;gap:10px;margin-bottom:4px}.sk-count-badge{display:inline-flex;align-items:center;padding:2px 8px;background:#fff7ed;color:#d97706;border-radius:20px;font-size:12px;font-weight:600}.sk-detail-card{border:1px solid #e2e8f0;border-radius:12px;background:#fff;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden}.sk-detail-card-hd{display:flex;align-items:center;gap:10px;padding:12px 16px;background:#fff7ed;border-bottom:1px solid #e2e8f0}.sk-detail-avatar{width:32px;height:32px;border-radius:8px;background:#d97706;color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;flex-shrink:0}.sk-detail-avatar--tool{background:#d97706}.sk-detail-card-name{flex:1;font-size:14px;font-weight:700;color:#92400e;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sk-detail-card-actions{display:flex;align-items:center;gap:10px;flex-shrink:0}.sk-copy-toggle{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:#69707d;cursor:pointer;-webkit-user-select:none;user-select:none}.sk-detail-fields{padding:14px 16px}.sk-fields-row{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:12px}.sk-field{display:flex;flex-direction:column;gap:4px}.sk-field-full{grid-column:1/-1}.skill-preview-card{border:1px solid #e2e8f0;border-radius:12px;margin-bottom:16px;box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a;overflow:hidden;background:#fff;transition:box-shadow .25s ease}.skill-preview-card:hover{box-shadow:0 4px 6px -1px #00000012,0 2px 4px -1px #0000000a}.skill-preview-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;background:#fff;font-size:15px;font-weight:700;color:#1e293b;border-bottom:1px solid transparent;cursor:pointer}.skill-preview-header.open{background:#ebf2f9;color:#2d5a8a;border-bottom:1px solid #e2e8f0}.skill-preview-body{padding:0;background:#fff}.skill-preview-body label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.skill-preview-body .value{font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word}h5.title{font-size:22px;font-weight:700;color:#1e293b!important;margin-bottom:4px}.preview-detail-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0}.preview-cell{padding:14px 20px;border-bottom:1px solid #e2e8f0;border-right:1px solid #e2e8f0}.preview-cell:nth-child(3n){border-right:none}.preview-full{grid-column:1/-1;border-right:none;border-bottom:none}.preview-label{display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:#69707d;margin-bottom:5px}.preview-value{display:block;font-size:14px;font-weight:500;color:#1e293b;line-height:1.5;word-break:break-word;min-height:21px}.stars-readonly{pointer-events:none;display:block}.action-btns{display:flex;justify-content:space-between;align-items:center}.actions{display:flex;justify-content:flex-end;gap:12px;margin-top:16px}.actions button{height:42px;padding:10px 22px;border:none;border-radius:5px;font-size:14px;transition:all .2s ease;font-weight:600;min-width:120px;cursor:pointer}.actions .secondary{color:#69707d;background:#fff;border:1.5px solid #e2e8f0}.actions .secondary:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.actions .primary{background:#4077ad;color:#fff}.actions .primary:hover{background:#2d5a8a;transform:translateY(-1px);box-shadow:0 1px 3px #00000014,0 1px 2px #0000000a}.actions .primary:active{transform:translateY(0)}.footer-actions{display:flex;justify-content:space-between;align-items:center;margin-top:64px}.icon-color{cursor:pointer;width:20px;height:20px;background:transparent;transition:transform .2s ease;filter:brightness(0) saturate(100%) invert(48%) sepia(8%) saturate(350%) hue-rotate(170deg) brightness(92%) contrast(88%)}.icon-color.edit{width:18px;height:18px}.icon-color.rotate{transform:rotate(180deg)}.sk-select-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:12px}.sk-select-col{display:flex;flex-direction:column;gap:6px}.sk-select-col .search-part{margin-bottom:0;max-width:unset}.step-card{max-width:1000px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 1px 3px #0000000f,0 4px 16px #4077ad14}.step-card-header{display:flex;align-items:center;gap:16px;padding:20px 28px;background:linear-gradient(135deg,#ebf2f9,#f0f6ff);border-bottom:1px solid #d5e8f5;border-radius:12px 12px 0 0}.step-card-header-icon{width:46px;height:46px;background:#fff;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 4px #4077ad2e;flex-shrink:0}.step-card-header-icon img{filter:brightness(0) saturate(100%) invert(37%) sepia(55%) saturate(500%) hue-rotate(190deg) brightness(95%) contrast(85%);width:22px;height:22px}.step-card-title{font-size:16px;font-weight:700;color:#1e293b;margin:0 0 3px;letter-spacing:-.01em}.step-card-subtitle{font-size:14px;color:#69707d;margin:0;line-height:1.4}.step-card-body{padding:24px 28px 8px}.field-section{margin-bottom:18px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:16px 18px 6px}.field-section-title{font-size:12px;font-weight:700;color:#4077ad;text-transform:uppercase;letter-spacing:.07em;margin-bottom:14px;display:flex;align-items:center;gap:7px}.field-section-title:before{content:\"\";display:inline-block;width:5px;height:5px;background:#4077ad;border-radius:50%;flex-shrink:0}.doc-type-chips{display:flex;flex-wrap:wrap;gap:8px;padding:4px 0 12px}.doc-type-chip{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;border-radius:5px;border:1.5px solid #e2e8f0;background:#fff;color:#69707d;font-size:13px;font-weight:500;cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none;line-height:1.4}.doc-type-chip input[type=checkbox]{display:none}.doc-type-chip:hover{border-color:#4077ad;color:#4077ad;background:#ebf2f9}.doc-type-chip.selected{background:#4077ad;border-color:#4077ad;color:#fff;font-weight:600;box-shadow:0 2px 6px #4077ad4d}.detail-row{display:flex;flex-wrap:wrap;column-gap:22px;row-gap:6px;margin-bottom:8px}.detail-item{display:flex;align-items:baseline;gap:6px;white-space:nowrap}.detail-label{font-size:14px;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:#4077ad}.detail-value{font-size:12.5px;font-weight:600;color:#1e293b}button.primary,button.secondary,button.back-btn,button.continue-btn,button.save-btn,button.add-btn,button.upload-btn,.actions button,.action button,.navigation-buttons button{display:inline-flex;align-items:center;justify-content:center;gap:6px;border-radius:5px;box-shadow:none}button.primary svg,button.secondary svg,button.back-btn svg,button.continue-btn svg,button.save-btn svg,button.add-btn svg,button.upload-btn svg,.actions button svg,.action button svg,.navigation-buttons button svg{flex-shrink:0;width:14px;height:14px}.step-toast{position:fixed;bottom:28px;right:28px;display:flex;align-items:flex-start;gap:14px;background:#fff;border-radius:12px;padding:16px 20px 20px;box-shadow:0 8px 32px #00000024;z-index:9999;min-width:290px;max-width:360px;animation:toastSlideIn .32s cubic-bezier(.34,1.56,.64,1);overflow:hidden}@keyframes toastSlideIn{0%{transform:translate(110%);opacity:0}to{transform:translate(0);opacity:1}}.step-toast-icon{width:34px;height:34px;background:#dcfce7;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px;color:#16a34a}.step-toast-body{flex:1}.step-toast-title{font-size:14px;font-weight:700;color:#1e293b;margin-bottom:2px}.step-toast-msg{font-size:12px;color:#69707d;line-height:1.4}.step-toast-progress{position:absolute;bottom:0;left:0;height:3px;background:#22c55e;border-radius:0 2px 2px 0;animation:toastProgress 3.5s linear forwards}@keyframes toastProgress{0%{width:100%}to{width:0%}}@media screen and (max-width: 767px){.step-card-header{padding:14px 16px}.step-card-body{padding:16px 16px 8px}.step-toast{right:12px;bottom:16px;min-width:calc(100vw - 24px);max-width:calc(100vw - 24px)}}@media only screen and (min-width: 300px) and (max-width: 450px){.modal-content .close-popup{width:16px}}@media (max-width: 600px){.actions{flex-direction:column;align-items:stretch}.actions button{width:100%}}@media screen and (max-width: 767px){.sk-select-row{grid-template-columns:1fr}.tools-container h3,h5.title{font-size:18px}.form-control,textarea{font-size:16px}.tools-container{padding:16px}.tools-container .mob-view{display:flex;justify-content:space-between;flex-direction:column-reverse;gap:8px}.tools-container .mob-res{flex-direction:column-reverse;gap:8px}.footer-actions{flex-direction:column-reverse;gap:8px;margin-top:48px}.continue-btn{padding:10px 22px;width:100%}.back-btn{width:100%}.save-btn{padding:10px 15px;width:unset;margin-left:0!important}.preview-detail-grid{grid-template-columns:1fr}.preview-cell{border-right:none}.sk-grid,.sk-edit-row,.sk-fields-row{grid-template-columns:1fr}}.dashboard-modal-overlay{position:fixed;inset:0;background:#00000073;display:flex;align-items:center;justify-content:center;z-index:1050;animation:fadeInOverlay .2s ease}@keyframes fadeInOverlay{0%{opacity:0}to{opacity:1}}.dashboard-modal{background:#fff;border-radius:12px;padding:40px 36px 32px;max-width:440px;width:90%;text-align:center;box-shadow:0 20px 60px #0000002e;animation:slideUpModal .25s ease}@keyframes slideUpModal{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}.dashboard-modal-icon{display:flex;justify-content:center;margin-bottom:20px}.dashboard-modal-icon svg{width:56px;height:56px}.dashboard-modal-title{font-size:18px;font-weight:700;color:#1e293b;margin-bottom:12px}.dashboard-modal-message{font-size:14px;color:#69707d;line-height:1.6;margin-bottom:28px}.dashboard-modal-actions{display:flex;gap:12px;justify-content:center}.modal-cancel-btn{height:42px;min-width:110px;border-radius:5px;border:1.5px solid #D4DAE6;background:#d4dae6;color:#69707d;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.modal-cancel-btn:hover{border-color:#c2cbde;color:#69707d;background:#c2cbde}.modal-confirm-btn{height:42px;min-width:150px;border-radius:5px;border:none;background:#4077ad;color:#fff;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s ease}.modal-confirm-btn:hover{background:#2d5a8a;transform:translateY(-1px)}.modal-confirm-btn:disabled{background:#69707d;cursor:not-allowed;transform:none}\n"] }]
|
|
11168
11158
|
}], ctorParameters: () => [{ type: ToolService }, { type: UserToolService }, { type: i7.UntypedFormBuilder }, { type: UserService }, { type: UtilsService }, { type: CredentialingStore }, { type: i1$4.TokenService }, { type: i1$4.RoleContextService }, { type: UserDetailService }, { type: ProfessionService }, { type: undefined, decorators: [{
|
|
11169
11159
|
type: Inject,
|
|
11170
11160
|
args: [LIBRARY_CONFIG]
|