mirror of
https://github.com/bitwarden/browser.git
synced 2024-09-27 04:03:00 +02:00
[SG-69] Billing payment step (#3133)
* billing folder added * initial commit * [SG-74] Trial Initiation Component with Vertical Stepper (#2913) * Vertical stepper PoC * Convert stepper css to tailwind * trial component start * trial component params * tailwind-ify header * Support teams, enterprise, and families layout param and more layout ui work * Some more theming fixes * Rename TrialModule to TrialInitiationModule * Stepper fixes, plus more functionality demo * Cleanup * layout params and placeholders * Only allow trial route to be hit if not logged in * fix typo * Use background-alt2 color for header * Move vertical stepper out of trial-initiation * Create components for the different plan types * Remove width on steps * Remove content projection for label * Tailwind style fixes * Extract step content into a component * Remove layout param for now * Remove step tags * remove pointer classes from step button * Remove most tailwind important designations * Update apps/web/src/app/modules/vertical-stepper/vertical-step.component.ts Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com> * Tailwind and layout fixes * Remove container * lint & prettier fixes * Remove extra CdkStep declaration * Styles fixes * Style logo directly * Remove 0 margin on image * Fix tiling and responsiveness * Minor padding fixes for org pages * Update apps/web/src/app/modules/trial-initiation/trial-initiation.component.html Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com> * prettier fix Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com> * [SG-65] Reusable Registration Form (#2946) * created reusable registration form * fixed conflicts * replicated reactive form changes in other clients * removed comments * client template cleanup * client template cleanup * removed comments in template file * changed to component suffix * switched show password to use component * comments resolution * comments resolution * added toast disable functionality * removed unused locale * mode custom input validator generic * fixed button * fixed linter * removed horizontal rule * switched to button component * Added billng step * Added keys to locale * billing trial initiation step * billing trial initiation step * Dont load billing content until the step is selected * billing trial initiation step * billing trial initiation step * billing trial initiation step * made the get plans endpoint anonymous * merged with master and extra changes * major changes on billing step * billing step sub label * Made changes to billing step sub label * removed unused variable * removed unused logic * cleanup * fixed suggestions * removed unused reference * added billing sub label Co-authored-by: Robyn MacCallum <robyntmaccallum@gmail.com> Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com> Co-authored-by: addison <addisonbeck1@gmail.com>
This commit is contained in:
parent
8aca6459cf
commit
f07e071f09
48
apps/web/src/app/modules/billing/billing.component.html
Normal file
48
apps/web/src/app/modules/billing/billing.component.html
Normal file
@ -0,0 +1,48 @@
|
||||
<form #form [formGroup]="formGroup" [appApiAction]="formPromise" (ngSubmit)="submit()">
|
||||
<div class="tw-container tw-mb-3">
|
||||
<div class="tw-mb-6">
|
||||
<h2 class="tw-text-base tw-font-semibold tw-mb-3">{{ "billingPlanLabel" | i18n }}</h2>
|
||||
<div class="tw-items-center tw-mb-1" *ngFor="let selectablePlan of selectablePlans">
|
||||
<label class="tw-block tw- tw-text-main" for="interval{{ selectablePlan.type }}">
|
||||
<input
|
||||
checked
|
||||
class="tw-w-4 tw-h-4 tw-align-middle"
|
||||
id="interval{{ selectablePlan.type }}"
|
||||
name="plan"
|
||||
type="radio"
|
||||
[value]="selectablePlan.type"
|
||||
formControlName="plan"
|
||||
/>
|
||||
<ng-container *ngIf="selectablePlan.isAnnual">
|
||||
{{ "annual" | i18n }} -
|
||||
{{
|
||||
(selectablePlan.basePrice === 0 ? selectablePlan.seatPrice : selectablePlan.basePrice)
|
||||
| currency: "$"
|
||||
}}
|
||||
/{{ "yr" | i18n }}
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!selectablePlan.isAnnual">
|
||||
{{ "monthly" | i18n }} -
|
||||
{{
|
||||
(selectablePlan.basePrice === 0 ? selectablePlan.seatPrice : selectablePlan.basePrice)
|
||||
| currency: "$"
|
||||
}}
|
||||
/{{ "monthAbbr" | i18n }}
|
||||
</ng-container>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tw-mb-4 tw-overflow-auto">
|
||||
<h2 class="tw-text-base tw-mb-3 tw-font-semibold">{{ "paymentType" | i18n }}</h2>
|
||||
<app-payment [hideCredit]="true" [trialFlow]="true"></app-payment>
|
||||
<app-tax-info [trialFlow]="true" (onCountryChanged)="changedCountry()"></app-tax-info>
|
||||
</div>
|
||||
|
||||
<div class="tw-flex tw-space-x-2">
|
||||
<bit-submit-button [loading]="form.loading">{{ "startTrial" | i18n }}</bit-submit-button>
|
||||
|
||||
<button bitButton type="button" buttonType="secondary" (click)="stepBack()">Back</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
68
apps/web/src/app/modules/billing/billing.component.ts
Normal file
68
apps/web/src/app/modules/billing/billing.component.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
import { FormBuilder, FormGroup } from "@angular/forms";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
|
||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { PolicyService } from "@bitwarden/common/abstractions/policy.service";
|
||||
import { SyncService } from "@bitwarden/common/abstractions/sync.service";
|
||||
|
||||
import { OrganizationPlansComponent } from "src/app/settings/organization-plans.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-billing",
|
||||
templateUrl: "./billing.component.html",
|
||||
})
|
||||
export class BillingComponent extends OrganizationPlansComponent {
|
||||
@Input() orgInfoForm: FormGroup;
|
||||
@Output() previousStep = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
apiService: ApiService,
|
||||
i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
cryptoService: CryptoService,
|
||||
router: Router,
|
||||
syncService: SyncService,
|
||||
policyService: PolicyService,
|
||||
organizationService: OrganizationService,
|
||||
logService: LogService,
|
||||
messagingService: MessagingService,
|
||||
formBuilder: FormBuilder
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
i18nService,
|
||||
platformUtilsService,
|
||||
cryptoService,
|
||||
router,
|
||||
syncService,
|
||||
policyService,
|
||||
organizationService,
|
||||
logService,
|
||||
messagingService,
|
||||
formBuilder
|
||||
);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
this.formGroup.patchValue({
|
||||
name: this.orgInfoForm.get("name")?.value,
|
||||
billingEmail: this.orgInfoForm.get("email")?.value,
|
||||
additionalSeats: 1,
|
||||
plan: this.plan,
|
||||
product: this.product,
|
||||
});
|
||||
this.isInTrialFlow = true;
|
||||
await super.ngOnInit();
|
||||
}
|
||||
|
||||
stepBack() {
|
||||
this.previousStep.emit();
|
||||
}
|
||||
}
|
12
apps/web/src/app/modules/billing/billing.module.ts
Normal file
12
apps/web/src/app/modules/billing/billing.module.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
|
||||
import { SharedModule } from "../shared.module";
|
||||
|
||||
import { BillingComponent } from "./billing.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule],
|
||||
declarations: [BillingComponent],
|
||||
exports: [BillingComponent],
|
||||
})
|
||||
export class BillingModule {}
|
@ -114,7 +114,6 @@ import { EmergencyAccessComponent } from "../settings/emergency-access.component
|
||||
import { EmergencyAddEditComponent } from "../settings/emergency-add-edit.component";
|
||||
import { OrganizationPlansComponent } from "../settings/organization-plans.component";
|
||||
import { PaymentMethodComponent } from "../settings/payment-method.component";
|
||||
import { PaymentComponent } from "../settings/payment.component";
|
||||
import { PreferencesComponent } from "../settings/preferences.component";
|
||||
import { PremiumComponent } from "../settings/premium.component";
|
||||
import { ProfileComponent } from "../settings/profile.component";
|
||||
@ -125,7 +124,6 @@ import { SettingsComponent } from "../settings/settings.component";
|
||||
import { SponsoredFamiliesComponent } from "../settings/sponsored-families.component";
|
||||
import { SponsoringOrgRowComponent } from "../settings/sponsoring-org-row.component";
|
||||
import { SubscriptionComponent } from "../settings/subscription.component";
|
||||
import { TaxInfoComponent } from "../settings/tax-info.component";
|
||||
import { TwoFactorAuthenticatorComponent } from "../settings/two-factor-authenticator.component";
|
||||
import { TwoFactorDuoComponent } from "../settings/two-factor-duo.component";
|
||||
import { TwoFactorEmailComponent } from "../settings/two-factor-email.component";
|
||||
@ -271,7 +269,6 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
|
||||
PasswordGeneratorHistoryComponent,
|
||||
PasswordGeneratorPolicyComponent,
|
||||
PasswordRepromptComponent,
|
||||
PaymentComponent,
|
||||
PaymentMethodComponent,
|
||||
PersonalOwnershipPolicyComponent,
|
||||
PreferencesComponent,
|
||||
@ -304,7 +301,6 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
|
||||
SponsoringOrgRowComponent,
|
||||
SsoComponent,
|
||||
SubscriptionComponent,
|
||||
TaxInfoComponent,
|
||||
ToolsComponent,
|
||||
TwoFactorAuthenticationPolicyComponent,
|
||||
TwoFactorAuthenticatorComponent,
|
||||
@ -425,7 +421,6 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
|
||||
PasswordGeneratorHistoryComponent,
|
||||
PasswordGeneratorPolicyComponent,
|
||||
PasswordRepromptComponent,
|
||||
PaymentComponent,
|
||||
PaymentMethodComponent,
|
||||
PersonalOwnershipPolicyComponent,
|
||||
PreferencesComponent,
|
||||
@ -458,7 +453,6 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
|
||||
SponsoringOrgRowComponent,
|
||||
SsoComponent,
|
||||
SubscriptionComponent,
|
||||
TaxInfoComponent,
|
||||
ToolsComponent,
|
||||
TwoFactorAuthenticationPolicyComponent,
|
||||
TwoFactorAuthenticatorComponent,
|
||||
|
@ -67,6 +67,8 @@ import {
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { PasswordStrengthComponent } from "../components/password-strength.component";
|
||||
import { PaymentComponent } from "../settings/payment.component";
|
||||
import { TaxInfoComponent } from "../settings/tax-info.component";
|
||||
|
||||
registerLocaleData(localeAf, "af");
|
||||
registerLocaleData(localeAz, "az");
|
||||
@ -120,7 +122,7 @@ registerLocaleData(localeZhCn, "zh-CN");
|
||||
registerLocaleData(localeZhTw, "zh-TW");
|
||||
|
||||
@NgModule({
|
||||
declarations: [PasswordStrengthComponent],
|
||||
declarations: [PasswordStrengthComponent, PaymentComponent, TaxInfoComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
DragDropModule,
|
||||
@ -155,8 +157,10 @@ registerLocaleData(localeZhTw, "zh-TW");
|
||||
ButtonModule,
|
||||
MenuModule,
|
||||
FormFieldModule,
|
||||
PasswordStrengthComponent,
|
||||
SubmitButtonModule,
|
||||
PasswordStrengthComponent,
|
||||
PaymentComponent,
|
||||
TaxInfoComponent,
|
||||
],
|
||||
providers: [DatePipe],
|
||||
bootstrap: [],
|
||||
|
@ -57,11 +57,15 @@
|
||||
Next
|
||||
</button>
|
||||
</app-vertical-step>
|
||||
<app-vertical-step label="Billing">
|
||||
<!-- Replace with Billing step -->
|
||||
<p>This is content of "Step 3"</p>
|
||||
<button bitButton buttonType="secondary" cdkStepperPrevious>Back</button>
|
||||
<button bitButton buttonType="primary" cdkStepperNext>Complete step</button>
|
||||
<app-vertical-step label="Billing" [subLabel]="billingSubLabel">
|
||||
<app-billing
|
||||
*ngIf="stepper.selectedIndex === 2"
|
||||
[plan]="plan"
|
||||
[product]="product"
|
||||
[orgInfoForm]="orgInfoFormGroup"
|
||||
(previousStep)="previousStep()"
|
||||
(onTrialBillingSuccess)="billingSuccess($event)"
|
||||
></app-billing>
|
||||
</app-vertical-step>
|
||||
<app-vertical-step label="Confirmation Details" subLabel="Fancy sub label">
|
||||
<!-- Replace with Confirmation details step -->
|
||||
|
@ -10,6 +10,8 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PolicyService } from "@bitwarden/common/abstractions/policy.service";
|
||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||
import { PlanType } from "@bitwarden/common/enums/planType";
|
||||
import { ProductType } from "@bitwarden/common/enums/productType";
|
||||
import { PolicyData } from "@bitwarden/common/models/data/policyData";
|
||||
import { MasterPasswordPolicyOptions } from "@bitwarden/common/models/domain/masterPasswordPolicyOptions";
|
||||
import { Policy } from "@bitwarden/common/models/domain/policy";
|
||||
@ -24,6 +26,10 @@ export class TrialInitiationComponent implements OnInit {
|
||||
email = "";
|
||||
org = "teams";
|
||||
orgInfoSubLabel = "";
|
||||
orgId = "";
|
||||
billingSubLabel = "";
|
||||
plan: PlanType;
|
||||
product: ProductType;
|
||||
accountCreateOnly = true;
|
||||
policies: Policy[];
|
||||
enforcedPolicyOptions: MasterPasswordPolicyOptions;
|
||||
@ -31,11 +37,7 @@ export class TrialInitiationComponent implements OnInit {
|
||||
|
||||
orgInfoFormGroup = this.formBuilder.group({
|
||||
name: ["", [Validators.required]],
|
||||
additionalStorage: [0, [Validators.min(0), Validators.max(99)]],
|
||||
additionalSeats: [0, [Validators.min(0), Validators.max(100000)]],
|
||||
businessName: [""],
|
||||
plan: [],
|
||||
product: [],
|
||||
email: [""],
|
||||
});
|
||||
|
||||
constructor(
|
||||
@ -54,9 +56,23 @@ export class TrialInitiationComponent implements OnInit {
|
||||
if (qParams.email != null && qParams.email.indexOf("@") > -1) {
|
||||
this.email = qParams.email;
|
||||
}
|
||||
if (qParams.org) {
|
||||
this.org = qParams.org;
|
||||
this.accountCreateOnly = false;
|
||||
|
||||
if (!qParams.org) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.org = qParams.org;
|
||||
this.accountCreateOnly = false;
|
||||
|
||||
if (qParams.org === "families") {
|
||||
this.plan = PlanType.FamiliesAnnually;
|
||||
this.product = ProductType.Families;
|
||||
} else if (qParams.org === "teams") {
|
||||
this.plan = PlanType.TeamsAnnually;
|
||||
this.product = ProductType.Teams;
|
||||
} else if (qParams.org === "enterprise") {
|
||||
this.plan = PlanType.EnterpriseAnnually;
|
||||
this.product = ProductType.Enterprise;
|
||||
}
|
||||
});
|
||||
|
||||
@ -93,10 +109,26 @@ export class TrialInitiationComponent implements OnInit {
|
||||
} else if (event.previouslySelectedIndex === 1) {
|
||||
this.orgInfoSubLabel = this.orgInfoFormGroup.controls.name.value;
|
||||
}
|
||||
|
||||
//set billing sub label
|
||||
if (event.selectedIndex === 2) {
|
||||
this.billingSubLabel = this.i18nService.t("billingTrialSubLabel");
|
||||
}
|
||||
}
|
||||
|
||||
createdAccount(email: string) {
|
||||
this.email = email;
|
||||
this.orgInfoFormGroup.get("email")?.setValue(email);
|
||||
this.verticalStepper.next();
|
||||
}
|
||||
|
||||
billingSuccess(event: any) {
|
||||
this.orgId = event?.orgId;
|
||||
this.billingSubLabel = event?.subLabelText;
|
||||
this.verticalStepper.next();
|
||||
}
|
||||
|
||||
previousStep() {
|
||||
this.verticalStepper.previous();
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import { RegisterFormModule } from "../register-form/register-form.module";
|
||||
import { SharedModule } from "../shared.module";
|
||||
import { VerticalStepperModule } from "../vertical-stepper/vertical-stepper.module";
|
||||
|
||||
import { BillingModule } from "./../billing/billing.module";
|
||||
import { EnterpriseContentComponent } from "./enterprise-content.component";
|
||||
import { FamiliesContentComponent } from "./families-content.component";
|
||||
import { TeamsContentComponent } from "./teams-content.component";
|
||||
@ -22,6 +23,7 @@ import { TrialInitiationComponent } from "./trial-initiation.component";
|
||||
FormFieldModule,
|
||||
RegisterFormModule,
|
||||
OrganizationCreateModule,
|
||||
BillingModule,
|
||||
],
|
||||
declarations: [
|
||||
TrialInitiationComponent,
|
||||
|
@ -43,12 +43,14 @@ export class OrganizationPlansComponent implements OnInit {
|
||||
@Input() providerId: string;
|
||||
@Output() onSuccess = new EventEmitter();
|
||||
@Output() onCanceled = new EventEmitter();
|
||||
@Output() onTrialBillingSuccess = new EventEmitter();
|
||||
|
||||
loading = true;
|
||||
selfHosted = false;
|
||||
productTypes = ProductType;
|
||||
formPromise: Promise<any>;
|
||||
singleOrgPolicyBlock = false;
|
||||
isInTrialFlow = false;
|
||||
discount = 0;
|
||||
|
||||
formGroup = this.formBuilder.group({
|
||||
@ -149,7 +151,7 @@ export class OrganizationPlansComponent implements OnInit {
|
||||
}
|
||||
|
||||
get selectablePlans() {
|
||||
return this.plans.filter(
|
||||
return this.plans?.filter(
|
||||
(plan) =>
|
||||
!plan.legacyYear && !plan.disabled && plan.product === this.formGroup.controls.product.value
|
||||
);
|
||||
@ -321,10 +323,18 @@ export class OrganizationPlansComponent implements OnInit {
|
||||
|
||||
await this.apiService.refreshIdentityToken();
|
||||
await this.syncService.fullSync(true);
|
||||
if (!this.acceptingSponsorship) {
|
||||
|
||||
if (!this.acceptingSponsorship && !this.isInTrialFlow) {
|
||||
this.router.navigate(["/organizations/" + orgId]);
|
||||
}
|
||||
|
||||
if (this.isInTrialFlow) {
|
||||
this.onTrialBillingSuccess.emit({
|
||||
orgId: orgId,
|
||||
subLabelText: this.billingSubLabelText(),
|
||||
});
|
||||
}
|
||||
|
||||
return orgId;
|
||||
};
|
||||
|
||||
@ -448,4 +458,18 @@ export class OrganizationPlansComponent implements OnInit {
|
||||
|
||||
return orgId;
|
||||
}
|
||||
|
||||
private billingSubLabelText(): string {
|
||||
const selectedPlan = this.selectedPlan;
|
||||
const price = selectedPlan.basePrice === 0 ? selectedPlan.seatPrice : selectedPlan.basePrice;
|
||||
let text = "";
|
||||
|
||||
if (selectedPlan.isAnnual) {
|
||||
text += `${this.i18nService.t("annual")} ($${price}/${this.i18nService.t("yr")})`;
|
||||
} else {
|
||||
text += `${this.i18nService.t("monthly")} ($${price}/${this.i18nService.t("monthAbbr")})`;
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
@ -58,11 +58,11 @@
|
||||
</div>
|
||||
<ng-container *ngIf="showMethods && method === paymentMethodType.Card">
|
||||
<div class="row">
|
||||
<div class="form-group col-4">
|
||||
<div [ngClass]="trialFlow ? 'col-4' : 'col-4'" class="form-group">
|
||||
<label for="stripe-card-number-element">{{ "number" | i18n }}</label>
|
||||
<div id="stripe-card-number-element" class="form-control stripe-form-control"></div>
|
||||
</div>
|
||||
<div class="form-group col-8 d-flex align-items-end">
|
||||
<div *ngIf="!trialFlow" class="form-group col-8 d-flex align-items-end">
|
||||
<img
|
||||
src="../../images/cards.png"
|
||||
alt="Visa, MasterCard, Discover, AmEx, JCB, Diners Club, UnionPay"
|
||||
@ -70,11 +70,11 @@
|
||||
height="32"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<div [ngClass]="trialFlow ? 'col-3' : 'col-4'" class="form-group">
|
||||
<label for="stripe-card-expiry-element">{{ "expiration" | i18n }}</label>
|
||||
<div id="stripe-card-expiry-element" class="form-control stripe-form-control"></div>
|
||||
</div>
|
||||
<div class="form-group col-4">
|
||||
<div [ngClass]="trialFlow ? 'col-5' : 'col-4'" class="form-group">
|
||||
<div class="d-flex">
|
||||
<label for="stripe-card-cvc-element">
|
||||
{{ "securityCode" | i18n }}
|
||||
|
@ -25,6 +25,7 @@ export class PaymentComponent implements OnInit, OnDestroy {
|
||||
@Input() hideBank = false;
|
||||
@Input() hidePaypal = false;
|
||||
@Input() hideCredit = false;
|
||||
@Input() trialFlow = false;
|
||||
|
||||
private destroy$: Subject<void> = new Subject<void>();
|
||||
|
||||
|
@ -265,7 +265,7 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div [ngClass]="trialFlow ? 'col-4' : 'col-3'">
|
||||
<div class="form-group">
|
||||
<label for="addressPostalCode">{{ "zipPostalCode" | i18n }}</label>
|
||||
<input
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component, EventEmitter, Output } from "@angular/core";
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
@ -12,6 +12,7 @@ import { TaxRateResponse } from "@bitwarden/common/models/response/taxRateRespon
|
||||
templateUrl: "tax-info.component.html",
|
||||
})
|
||||
export class TaxInfoComponent {
|
||||
@Input() trialFlow = false;
|
||||
@Output() onCountryChanged = new EventEmitter();
|
||||
|
||||
loading = true;
|
||||
|
@ -644,6 +644,9 @@
|
||||
"newAccountCreated": {
|
||||
"message": "Your new account has been created! You may now log in."
|
||||
},
|
||||
"trialAccountCreated": {
|
||||
"message": "Account created successfully."
|
||||
},
|
||||
"masterPassSent": {
|
||||
"message": "We've sent you an email with your master password hint."
|
||||
},
|
||||
@ -1669,6 +1672,12 @@
|
||||
"billing": {
|
||||
"message": "Billing"
|
||||
},
|
||||
"billingPlanLabel": {
|
||||
"message": "Billing Plan"
|
||||
},
|
||||
"paymentType": {
|
||||
"message": "Payment Type"
|
||||
},
|
||||
"accountCredit": {
|
||||
"message": "Account Credit",
|
||||
"description": "Financial term. In the case of Bitwarden, a positive balance means that you owe money, while a negative balance means that you have a credit (Bitwarden owes you money)."
|
||||
@ -1785,6 +1794,9 @@
|
||||
"year": {
|
||||
"message": "year"
|
||||
},
|
||||
"yr": {
|
||||
"message": "yr"
|
||||
},
|
||||
"month": {
|
||||
"message": "month"
|
||||
},
|
||||
@ -1813,6 +1825,9 @@
|
||||
"billingInformation": {
|
||||
"message": "Billing Information"
|
||||
},
|
||||
"billingTrialSubLabel": {
|
||||
"message": "Your payment method will not be charged during the 7 day free trial."
|
||||
},
|
||||
"creditCard": {
|
||||
"message": "Credit Card"
|
||||
},
|
||||
@ -2175,6 +2190,9 @@
|
||||
"annually": {
|
||||
"message": "Annually"
|
||||
},
|
||||
"annual": {
|
||||
"message": "Annual"
|
||||
},
|
||||
"basePrice": {
|
||||
"message": "Base Price"
|
||||
},
|
||||
|
@ -17,6 +17,7 @@ import { PasswordGenerationService } from "@bitwarden/common/abstractions/passwo
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||
import { DEFAULT_KDF_ITERATIONS, DEFAULT_KDF_TYPE } from "@bitwarden/common/enums/kdfType";
|
||||
import { PasswordLogInCredentials } from "@bitwarden/common/models/domain/logInCredentials";
|
||||
import { KeysRequest } from "@bitwarden/common/models/request/keysRequest";
|
||||
import { ReferenceEventRequest } from "@bitwarden/common/models/request/referenceEventRequest";
|
||||
import { RegisterRequest } from "@bitwarden/common/models/request/registerRequest";
|
||||
@ -200,10 +201,29 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("newAccountCreated"));
|
||||
|
||||
if (this.isInTrialFlow) {
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("trialAccountCreated")
|
||||
);
|
||||
//login user here
|
||||
const credentials = new PasswordLogInCredentials(
|
||||
email,
|
||||
masterPassword,
|
||||
this.captchaToken,
|
||||
null
|
||||
);
|
||||
await this.authService.logIn(credentials);
|
||||
|
||||
this.createdAccount.emit(this.formGroup.get("email")?.value);
|
||||
} else {
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("newAccountCreated")
|
||||
);
|
||||
this.router.navigate([this.successRoute], { queryParams: { email: email } });
|
||||
}
|
||||
} catch (e) {
|
||||
|
@ -1395,7 +1395,7 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
// Plan APIs
|
||||
|
||||
async getPlans(): Promise<ListResponse<PlanResponse>> {
|
||||
const r = await this.send("GET", "/plans/", null, true, true);
|
||||
const r = await this.send("GET", "/plans/", null, false, true);
|
||||
return new ListResponse(r, PlanResponse);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user