diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 60477d9..204c335 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,9 +1,11 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { FormsComponent } from './forms/forms.component'; +import { KycOnboardingComponent } from './kyc/kyc-onboarding.component'; const routes: Routes = [ - { path: '', component: FormsComponent } + { path: '', component: KycOnboardingComponent }, + { path: 'demo-forms', component: FormsComponent } ]; @NgModule({ diff --git a/src/app/app.module.ts b/src/app/app.module.ts index b39111b..2af2689 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -7,6 +7,7 @@ import { AppComponent } from './app.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { FormsComponent } from './forms/forms.component'; +import { KycOnboardingComponent } from './kyc/kyc-onboarding.component'; import { MatButtonModule } from '@angular/material/button'; import { MatInputModule } from '@angular/material/input'; @@ -18,7 +19,8 @@ import { MatSelectModule } from '@angular/material/select'; @NgModule({ declarations: [ AppComponent, - FormsComponent + FormsComponent, + KycOnboardingComponent ], imports: [ BrowserModule, diff --git a/src/app/kyc/kyc-onboarding.component.html b/src/app/kyc/kyc-onboarding.component.html new file mode 100644 index 0000000..eb11695 --- /dev/null +++ b/src/app/kyc/kyc-onboarding.component.html @@ -0,0 +1,328 @@ +
+

Employee KYC Onboarding

+ +
+ +

Personal Information

+
+
+ + First Name + + Required + + + + Middle Name + + +
+ +
+ + Last Name + + Required + + + + Email + + Enter a valid email + +
+ +
+ + Phone + + Enter a valid phone + + + + Gender + + {{ g }} + + Required + + + + Date of Birth + + + + Required + +
+ +
+ + Marital Status + + {{ m }} + + + + + Nationality + + {{ c }} + + Required + +
+
+ +

Government Identity

+
+
+ + ID Type + + Passport + National ID + Driver License + + Required + + + + ID Number + + Required + + + + Issued Country + + {{ c }} + + Required + +
+ +
+ + Issue Date + + + + Required + + + + Expiry Date + + + + +
+ +
+ + Tax ID (Optional) + + +
+
+ +

Residential Address

+
+
+ + Address Line 1 + + Required + +
+
+ + Address Line 2 + + +
+ +
+ + City + + Required + + + + State/Province + + {{ s }} + + Required + + + + Postal Code + + Required + +
+ +
+ + Country + + {{ c }} + + Required + +
+
+ +

Employment Details

+
+
+ + Employee ID + + Required + + + + Department + + Required + + + + Designation + + Required + +
+ +
+ + Employment Type + + {{ e }} + + Required + + + + Date of Joining + + + + Required + + + + Annual CTC + + Enter a valid amount + +
+
+ +

Bank Details

+
+
+ + Account Holder Name + + Required + + + + Bank Name + + Required + +
+ +
+ + Account Number + + Enter a valid account + + + + IFSC/SWIFT + + Enter a valid code + + + + Branch (Optional) + + +
+
+ +

Emergency Contacts

+
+
+
+
+ + Name + + + + + Relationship + + {{ r }} + + + + + Phone + + +
+ +
+ + Email (Optional) + + + + + Address (Optional) + + +
+ +
+ +
+
+
+ + +
+ +

Declarations

+
+
+ I am a Politically Exposed Person (PEP) +
+
+ I have a criminal record +
+
+ + I confirm that the information provided is true and agree to the company's policies. + + + You must accept to proceed. + +
+
+ +
+ +
+
+
\ No newline at end of file diff --git a/src/app/kyc/kyc-onboarding.component.scss b/src/app/kyc/kyc-onboarding.component.scss new file mode 100644 index 0000000..86a1aff --- /dev/null +++ b/src/app/kyc/kyc-onboarding.component.scss @@ -0,0 +1,56 @@ +.container { + margin: 24px auto; + max-width: 1100px; +} + +.page-title { + margin: 0 0 16px 0; + font-weight: 600; +} + +.section-title { + margin: 24px 0 8px 0; + font-weight: 600; +} + +.section { + padding: 16px; + border: 1px solid rgba(0,0,0,.08); + border-radius: 8px; + background: #fff; +} + +.row { + display: flex; + gap: 16px; + flex-wrap: wrap; + margin-bottom: 8px; +} + +.col { + flex: 1 1 0; + min-width: 220px; +} + +.full { flex: 1 1 100%; } +.half { flex: 1 1 calc(50% - 16px); min-width: 280px; } +.third { flex: 1 1 calc(33.33% - 16px); min-width: 220px; } +.quarter { flex: 1 1 calc(25% - 16px); min-width: 200px; } + +.emergency-card { + padding: 12px; + border: 1px dashed rgba(0,0,0,.15); + border-radius: 8px; + margin-bottom: 12px; + background: #fafafa; +} + +.checkbox-row { + margin: 8px 0; +} + +.submit-row { + margin: 24px 0; + display: flex; + justify-content: flex-end; +} \ No newline at end of file diff --git a/src/app/kyc/kyc-onboarding.component.ts b/src/app/kyc/kyc-onboarding.component.ts new file mode 100644 index 0000000..7bc010c --- /dev/null +++ b/src/app/kyc/kyc-onboarding.component.ts @@ -0,0 +1,128 @@ +import { Component, OnInit } from '@angular/core'; +import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; + +@Component({ + selector: 'app-kyc-onboarding', + templateUrl: './kyc-onboarding.component.html', + styleUrls: ['./kyc-onboarding.component.scss'] +}) +export class KycOnboardingComponent implements OnInit { + + kycForm: FormGroup; + + genders = ['Male', 'Female', 'Other', 'Prefer not to say']; + maritalStatuses = ['Single', 'Married', 'Divorced', 'Widowed']; + countries = [ + 'United States', 'United Kingdom', 'Canada', 'India', 'Australia', + 'Germany', 'France', 'Brazil', 'Argentina', 'South Africa' + ]; + states = [ + 'N/A', 'Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', + 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', + 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', + 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', + 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', + 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', + 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', + 'Wisconsin', 'Wyoming' + ]; + employmentTypes = ['Full-time', 'Part-time', 'Contract', 'Intern', 'Consultant']; + relationshipTypes = ['Parent', 'Sibling', 'Spouse/Partner', 'Friend', 'Other']; + + constructor(private fb: FormBuilder) {} + + ngOnInit(): void { + this.kycForm = this.fb.group({ + personalInfo: this.fb.group({ + firstName: ['', Validators.required], + middleName: [''], + lastName: ['', Validators.required], + email: ['', [Validators.required, Validators.email]], + phone: ['', [Validators.required, Validators.pattern(/^[0-9 +()-]{7,20}$/)]], + gender: [null, Validators.required], + dob: [null, Validators.required], + maritalStatus: [null], + nationality: [null, Validators.required] + }), + + identity: this.fb.group({ + idType: ['Passport', Validators.required], // Passport, National ID, Driver License + idNumber: ['', [Validators.required, Validators.maxLength(32)]], + idIssuedCountry: [null, Validators.required], + idIssuedDate: [null, Validators.required], + idExpiryDate: [null], + taxId: [''] + }), + + address: this.fb.group({ + line1: ['', Validators.required], + line2: [''], + city: ['', Validators.required], + state: ['N/A', Validators.required], + postalCode: ['', [Validators.required, Validators.pattern(/^[A-Za-z0-9 -]{3,12}$/)]], + country: ['United States', Validators.required] + }), + + employment: this.fb.group({ + employeeId: ['', Validators.required], + department: ['', Validators.required], + designation: ['', Validators.required], + employmentType: [null, Validators.required], + dateOfJoining: [null, Validators.required], + annualCTC: ['', [Validators.required, Validators.pattern(/^[0-9,.]+$/)]] + }), + + bankDetails: this.fb.group({ + accountHolderName: ['', Validators.required], + bankName: ['', Validators.required], + accountNumber: ['', [Validators.required, Validators.pattern(/^[0-9]{6,18}$/)]], + ifscOrSwift: ['', [Validators.required, Validators.pattern(/^[A-Za-z0-9]{6,11}$/)]], + branch: [''] + }), + + emergencyContacts: this.fb.array([ + this.createEmergencyContactGroup() + ]), + + declarations: this.fb.group({ + politicallyExposed: [false, Validators.required], + hasCriminalRecord: [false, Validators.required], + acceptsPolicies: [false, Validators.requiredTrue] + }) + }); + } + + get emergencyContacts(): FormArray { + return this.kycForm.get('emergencyContacts') as FormArray; + } + + addEmergencyContact(): void { + this.emergencyContacts.push(this.createEmergencyContactGroup()); + } + + removeEmergencyContact(index: number): void { + if (this.emergencyContacts.length > 1) { + this.emergencyContacts.removeAt(index); + } + } + + private createEmergencyContactGroup(): FormGroup { + return this.fb.group({ + name: ['', Validators.required], + relationship: [null, Validators.required], + phone: ['', [Validators.required, Validators.pattern(/^[0-9 +()-]{7,20}$/)]], + email: ['', [Validators.email]], + address: [''] + }); + } + + submit(): void { + if (this.kycForm.valid) { + // In a real app, you would send this. For now, just log. + console.log('KYC form submission', this.kycForm.value); + alert('KYC submitted. Check console for payload.'); + } else { + this.kycForm.markAllAsTouched(); + } + } +} \ No newline at end of file