1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-10 21:33:27 +00:00
Files
browser/libs/angular/src/billing/components/manage-tax-information/manage-tax-information.component.ts

142 lines
4.4 KiB
TypeScript

import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { Subject, takeUntil } from "rxjs";
import { debounceTime } from "rxjs/operators";
import { TaxServiceAbstraction } from "@bitwarden/common/billing/abstractions/tax.service.abstraction";
import { CountryListItem, TaxInformation } from "@bitwarden/common/billing/models/domain";
@Component({
selector: "app-manage-tax-information",
templateUrl: "./manage-tax-information.component.html",
})
export class ManageTaxInformationComponent implements OnInit, OnDestroy {
@Input() startWith: TaxInformation;
@Input() onSubmit?: (taxInformation: TaxInformation) => Promise<void>;
/**
* Emits when the tax information has changed.
*/
@Output() taxInformationChanged = new EventEmitter<TaxInformation>();
/**
* Emits when the tax information has been updated.
*/
@Output() taxInformationUpdated = new EventEmitter();
private taxInformation: TaxInformation;
protected formGroup = this.formBuilder.group({
country: ["", Validators.required],
postalCode: ["", Validators.required],
taxId: "",
line1: "",
line2: "",
city: "",
state: "",
});
protected isTaxSupported: boolean;
private destroy$ = new Subject<void>();
protected readonly countries: CountryListItem[] = this.taxService.getCountries();
constructor(
private formBuilder: FormBuilder,
private taxService: TaxServiceAbstraction,
) {}
getTaxInformation(): TaxInformation {
return this.taxInformation;
}
submit = async () => {
this.formGroup.markAllAsTouched();
if (this.formGroup.invalid) {
return;
}
await this.onSubmit?.(this.taxInformation);
this.taxInformationUpdated.emit();
};
validate = (): boolean => {
this.formGroup.markAllAsTouched();
return this.formGroup.valid;
};
async ngOnInit() {
if (this.startWith) {
this.formGroup.controls.country.setValue(this.startWith.country);
this.formGroup.controls.postalCode.setValue(this.startWith.postalCode);
this.isTaxSupported =
this.startWith && this.startWith.country
? await this.taxService.isCountrySupported(this.startWith.country)
: false;
if (this.isTaxSupported) {
this.formGroup.controls.taxId.setValue(this.startWith.taxId);
this.formGroup.controls.line1.setValue(this.startWith.line1);
this.formGroup.controls.line2.setValue(this.startWith.line2);
this.formGroup.controls.city.setValue(this.startWith.city);
this.formGroup.controls.state.setValue(this.startWith.state);
}
}
this.formGroup.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((values) => {
this.taxInformation = {
country: values.country,
postalCode: values.postalCode,
taxId: values.taxId,
line1: values.line1,
line2: values.line2,
city: values.city,
state: values.state,
};
});
this.formGroup.controls.country.valueChanges
.pipe(debounceTime(1000), takeUntil(this.destroy$))
.subscribe((country: string) => {
this.taxService
.isCountrySupported(country)
.then((isSupported) => (this.isTaxSupported = isSupported))
.catch(() => (this.isTaxSupported = false))
.finally(() => {
if (!this.isTaxSupported) {
this.formGroup.controls.taxId.setValue(null);
this.formGroup.controls.line1.setValue(null);
this.formGroup.controls.line2.setValue(null);
this.formGroup.controls.city.setValue(null);
this.formGroup.controls.state.setValue(null);
}
if (this.taxInformationChanged) {
this.taxInformationChanged.emit(this.taxInformation);
}
});
});
this.formGroup.controls.postalCode.valueChanges
.pipe(debounceTime(1000), takeUntil(this.destroy$))
.subscribe(() => {
if (this.taxInformationChanged) {
this.taxInformationChanged.emit(this.taxInformation);
}
});
this.formGroup.controls.taxId.valueChanges
.pipe(debounceTime(1000), takeUntil(this.destroy$))
.subscribe(() => {
if (this.taxInformationChanged) {
this.taxInformationChanged.emit(this.taxInformation);
}
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}