1
0
mirror of https://github.com/bitwarden/browser synced 2026-01-06 10:33:57 +00: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:
Gbubemi Smith
2022-07-20 02:00:25 +01:00
committed by GitHub
parent 8aca6459cf
commit f07e071f09
16 changed files with 259 additions and 31 deletions

View File

@@ -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;
}
}

View File

@@ -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 }}

View File

@@ -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>();

View File

@@ -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

View File

@@ -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;