mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 21:33:27 +00:00
142 lines
4.4 KiB
TypeScript
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();
|
|
}
|
|
}
|