Skip to content

Commit 9afba33

Browse files
[PM-26044] Update Offboarding Survey for User and Organization (#17472)
* feat(billing): update messages to add reasons * feat(billing): update survey with switching reason based on param * fix(billing): revert value of switching reasons * fix(billing): revert removal of tooExpensive message * fix(billing): Add plan type to params and update switching logic * fix(billing): update to include logic * fix(billing): PR feedback
1 parent 81453ed commit 9afba33

File tree

4 files changed

+66
-36
lines changed

4 files changed

+66
-36
lines changed

apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
344344
data: {
345345
type: "Organization",
346346
id: this.organizationId,
347+
plan: this.sub.plan.type,
347348
},
348349
});
349350

apps/web/src/app/billing/shared/offboarding-survey.component.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
</bit-label>
2222
<textarea rows="4" bitInput formControlName="feedback"></textarea>
2323
<bit-hint>{{
24-
"charactersCurrentAndMaximum" | i18n: formGroup.value.feedback.length : MaxFeedbackLength
24+
"charactersCurrentAndMaximum"
25+
| i18n: formGroup.value.feedback?.length ?? 0 : MaxFeedbackLength
2526
}}</bit-hint>
2627
</bit-form-field>
2728
</div>

apps/web/src/app/billing/shared/offboarding-survey.component.ts

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// FIXME: Update this file to be type safe and remove this and next line
22
// @ts-strict-ignore
3-
import { Component, Inject } from "@angular/core";
3+
import { ChangeDetectionStrategy, Component, Inject } from "@angular/core";
44
import { FormBuilder, Validators } from "@angular/forms";
55

66
import { BillingApiServiceAbstraction as BillingApiService } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
7+
import { PlanType } from "@bitwarden/common/billing/enums";
78
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
89
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
910
import {
@@ -21,6 +22,7 @@ type UserOffboardingParams = {
2122
type OrganizationOffboardingParams = {
2223
type: "Organization";
2324
id: string;
25+
plan: PlanType;
2426
};
2527

2628
export type OffboardingSurveyDialogParams = UserOffboardingParams | OrganizationOffboardingParams;
@@ -46,50 +48,20 @@ export const openOffboardingSurvey = (
4648
dialogConfig,
4749
);
4850

49-
// FIXME(https://bitwarden.atlassian.net/browse/CL-764): Migrate to OnPush
50-
// eslint-disable-next-line @angular-eslint/prefer-on-push-component-change-detection
5151
@Component({
5252
selector: "app-cancel-subscription-form",
5353
templateUrl: "offboarding-survey.component.html",
54+
changeDetection: ChangeDetectionStrategy.OnPush,
5455
standalone: false,
5556
})
5657
export class OffboardingSurveyComponent {
5758
protected ResultType = OffboardingSurveyDialogResultType;
5859
protected readonly MaxFeedbackLength = 400;
5960

60-
protected readonly reasons: Reason[] = [
61-
{
62-
value: null,
63-
text: this.i18nService.t("selectPlaceholder"),
64-
},
65-
{
66-
value: "missing_features",
67-
text: this.i18nService.t("missingFeatures"),
68-
},
69-
{
70-
value: "switched_service",
71-
text: this.i18nService.t("movingToAnotherTool"),
72-
},
73-
{
74-
value: "too_complex",
75-
text: this.i18nService.t("tooDifficultToUse"),
76-
},
77-
{
78-
value: "unused",
79-
text: this.i18nService.t("notUsingEnough"),
80-
},
81-
{
82-
value: "too_expensive",
83-
text: this.i18nService.t("tooExpensive"),
84-
},
85-
{
86-
value: "other",
87-
text: this.i18nService.t("other"),
88-
},
89-
];
61+
protected readonly reasons: Reason[] = [];
9062

9163
protected formGroup = this.formBuilder.group({
92-
reason: [this.reasons[0].value, [Validators.required]],
64+
reason: [null, [Validators.required]],
9365
feedback: ["", [Validators.maxLength(this.MaxFeedbackLength)]],
9466
});
9567

@@ -101,7 +73,35 @@ export class OffboardingSurveyComponent {
10173
private i18nService: I18nService,
10274
private platformUtilsService: PlatformUtilsService,
10375
private toastService: ToastService,
104-
) {}
76+
) {
77+
this.reasons = [
78+
{
79+
value: null,
80+
text: this.i18nService.t("selectPlaceholder"),
81+
},
82+
{
83+
value: "missing_features",
84+
text: this.i18nService.t("missingFeatures"),
85+
},
86+
{
87+
value: "switched_service",
88+
text: this.i18nService.t("movingToAnotherTool"),
89+
},
90+
{
91+
value: "too_complex",
92+
text: this.i18nService.t("tooDifficultToUse"),
93+
},
94+
{
95+
value: "unused",
96+
text: this.i18nService.t("notUsingEnough"),
97+
},
98+
this.getSwitchingReason(),
99+
{
100+
value: "other",
101+
text: this.i18nService.t("other"),
102+
},
103+
];
104+
}
105105

106106
submit = async () => {
107107
this.formGroup.markAllAsTouched();
@@ -127,4 +127,24 @@ export class OffboardingSurveyComponent {
127127

128128
this.dialogRef.close(this.ResultType.Submitted);
129129
};
130+
131+
private getSwitchingReason(): Reason {
132+
if (this.dialogParams.type === "User") {
133+
return {
134+
value: "too_expensive",
135+
text: this.i18nService.t("switchToFreePlan"),
136+
};
137+
}
138+
139+
const isFamilyPlan = [
140+
PlanType.FamiliesAnnually,
141+
PlanType.FamiliesAnnually2019,
142+
PlanType.FamiliesAnnually2025,
143+
].includes(this.dialogParams.plan);
144+
145+
return {
146+
value: "too_expensive",
147+
text: this.i18nService.t(isFamilyPlan ? "switchToFreeOrg" : "tooExpensive"),
148+
};
149+
}
130150
}

apps/web/src/locales/en/messages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9824,6 +9824,14 @@
98249824
"message": "Too expensive",
98259825
"description": "An option for the offboarding survey shown when a user cancels their subscription."
98269826
},
9827+
"switchToFreePlan": {
9828+
"message": "Switching to free plan",
9829+
"description": "An option for the offboarding survey shown when a user cancels their subscription."
9830+
},
9831+
"switchToFreeOrg": {
9832+
"message": "Switching to free organization",
9833+
"description": "An option for the offboarding survey shown when a user cancels their subscription."
9834+
},
98279835
"freeForOneYear": {
98289836
"message": "Free for 1 year"
98299837
},

0 commit comments

Comments
 (0)