chore(server): remove useless free subscription enum (#6634)

This commit is contained in:
forehalo 2024-04-19 13:34:58 +00:00
parent 657a5250ad
commit 098e717688
No known key found for this signature in database
GPG Key ID: 56709255DC7EC728
10 changed files with 53 additions and 83 deletions

View File

@ -56,7 +56,10 @@ export class UserSubscriptionType implements Partial<UserSubscription> {
@Field({ name: 'id' })
stripeSubscriptionId!: string;
@Field(() => SubscriptionPlan)
@Field(() => SubscriptionPlan, {
description:
"The 'Free' plan just exists to be a placeholder and for the type convenience of frontend.\nThere won't actually be a subscription with plan 'Free'",
})
plan!: SubscriptionPlan;
@Field(() => SubscriptionRecurring)

View File

@ -443,6 +443,11 @@ type UserSubscription {
end: DateTime!
id: String!
nextBillAt: DateTime
"""
The 'Free' plan just exists to be a placeholder and for the type convenience of frontend.
There won't actually be a subscription with plan 'Free'
"""
plan: SubscriptionPlan!
recurring: SubscriptionRecurring!
start: DateTime!

View File

@ -21,7 +21,7 @@ export const UserPlanButton = () => {
serverConfigService.serverConfig.features$.map(r => r?.payment)
);
const plan = useLiveData(
subscriptionService.subscription.primary$.map(subscription =>
subscriptionService.subscription.pro$.map(subscription =>
subscription !== null ? subscription?.plan : null
)
);

View File

@ -1,5 +1,4 @@
import { Button, ErrorMessage, Skeleton, Tooltip } from '@affine/component';
import { SubscriptionPlan } from '@affine/graphql';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useLiveData, useService } from '@toeverything/infra';
import { cssVar } from '@toeverything/theme';
@ -45,15 +44,14 @@ export const StorageProgress = ({ onUpgrade }: StorageProgressProgress) => {
subscription.revalidate();
}, [subscription]);
const primarySubscription = useLiveData(subscription.primary$);
const isFreeUser =
!primarySubscription || primarySubscription?.plan === SubscriptionPlan.Free;
const proSubscription = useLiveData(subscription.pro$);
const isFreeUser = !proSubscription;
const quotaName = useLiveData(
quota.quota$.map(q => (q !== null ? q?.humanReadable.name : null))
);
const loading =
primarySubscription === null || percent === null || quotaName === null;
proSubscription === null || percent === null || quotaName === null;
const loadError = useLiveData(quota.error$);
const buttonType = useMemo(() => {

View File

@ -96,47 +96,39 @@ const SubscriptionSettings = () => {
subscriptionService.prices.revalidate();
}, [subscriptionService]);
const primarySubscription = useLiveData(
subscriptionService.subscription.primary$
);
const proSubscription = useLiveData(subscriptionService.subscription.pro$);
const proPrice = useLiveData(subscriptionService.prices.proPrice$);
const currentPlan =
primarySubscription === null
? null
: primarySubscription?.plan ?? SubscriptionPlan.Free;
const [openCancelModal, setOpenCancelModal] = useState(false);
const recurring =
primarySubscription?.recurring ?? SubscriptionRecurring.Monthly;
const setOpenSettingModalAtom = useSetAtom(openSettingModalAtom);
const currentPlan = proSubscription?.plan ?? SubscriptionPlan.Free;
const currentRecurring =
proSubscription?.recurring ?? SubscriptionRecurring.Monthly;
const gotoPlansSetting = useCallback(() => {
mixpanel.track('Button', {
resolve: 'ChangePlan',
currentPlan: currentPlan,
currentPlan: proSubscription?.plan,
});
setOpenSettingModalAtom({
open: true,
activeTab: 'plans',
});
}, [currentPlan, setOpenSettingModalAtom]);
}, [proSubscription, setOpenSettingModalAtom]);
const amount = currentPlan
? currentPlan === SubscriptionPlan.Free
? '0'
: proPrice
? recurring === SubscriptionRecurring.Monthly
? String((proPrice.amount ?? 0) / 100)
: String((proPrice.yearlyAmount ?? 0) / 100)
: '?'
: '?';
const amount = proSubscription
? proPrice
? proSubscription.recurring === SubscriptionRecurring.Monthly
? String((proPrice.amount ?? 0) / 100)
: String((proPrice.yearlyAmount ?? 0) / 100)
: '?'
: '0';
return (
<div className={styles.subscription}>
{currentPlan !== null ? (
{/* loaded */}
{proSubscription !== null ? (
<div className={styles.planCard}>
<div className={styles.currentPlan}>
<SettingRow
@ -144,7 +136,7 @@ const SubscriptionSettings = () => {
name={t['com.affine.payment.billing-setting.current-plan']()}
desc={
<Trans
i18nKey={getMessageKey(currentPlan, recurring)}
i18nKey={getMessageKey(currentPlan, currentRecurring)}
values={{
planName: currentPlan,
}}
@ -168,7 +160,7 @@ const SubscriptionSettings = () => {
${amount}
<span className={styles.billingFrequency}>
/
{recurring === SubscriptionRecurring.Monthly
{currentRecurring === SubscriptionRecurring.Monthly
? t['com.affine.payment.billing-setting.month']()
: t['com.affine.payment.billing-setting.year']()}
</span>
@ -179,8 +171,8 @@ const SubscriptionSettings = () => {
)}
<AIPlanCard />
{primarySubscription !== null ? (
primarySubscription?.status === SubscriptionStatus.Active && (
{proSubscription !== null ? (
proSubscription?.status === SubscriptionStatus.Active && (
<>
<SettingRow
className={styles.paymentMethod}
@ -191,26 +183,26 @@ const SubscriptionSettings = () => {
>
<PaymentMethodUpdater />
</SettingRow>
{primarySubscription.nextBillAt && (
{proSubscription.nextBillAt && (
<SettingRow
name={t['com.affine.payment.billing-setting.renew-date']()}
desc={t[
'com.affine.payment.billing-setting.renew-date.description'
]({
renewDate: new Date(
primarySubscription.nextBillAt
proSubscription.nextBillAt
).toLocaleDateString(),
})}
/>
)}
{primarySubscription.canceledAt ? (
{proSubscription.canceledAt ? (
<SettingRow
name={t['com.affine.payment.billing-setting.expiration-date']()}
desc={t[
'com.affine.payment.billing-setting.expiration-date.description'
]({
expirationDate: new Date(
primarySubscription.end
proSubscription.end
).toLocaleDateString(),
})}
>
@ -322,9 +314,9 @@ const PlanAction = ({
type="primary"
onClick={gotoPlansSetting}
>
{plan === SubscriptionPlan.Free
? t['com.affine.payment.billing-setting.upgrade']()
: t['com.affine.payment.billing-setting.change-plan']()}
{plan === SubscriptionPlan.Pro
? t['com.affine.payment.billing-setting.change-plan']()
: t['com.affine.payment.billing-setting.upgrade']()}
</Button>
);
};

View File

@ -36,9 +36,7 @@ const Settings = () => {
const scrollWrapper = useRef<HTMLDivElement>(null);
const subscriptionService = useService(SubscriptionService);
const primarySubscription = useLiveData(
subscriptionService.subscription.primary$
);
const proSubscription = useLiveData(subscriptionService.subscription.pro$);
const prices = useLiveData(subscriptionService.prices.prices$);
useEffect(() => {
@ -62,13 +60,13 @@ const Settings = () => {
});
const [recurring, setRecurring] = useState<SubscriptionRecurring>(
primarySubscription?.recurring ?? SubscriptionRecurring.Yearly
proSubscription?.recurring ?? SubscriptionRecurring.Yearly
);
const currentPlan = primarySubscription?.plan ?? SubscriptionPlan.Free;
const isCanceled = !!primarySubscription?.canceledAt;
const currentPlan = proSubscription?.plan ?? SubscriptionPlan.Free;
const isCanceled = !!proSubscription?.canceledAt;
const currentRecurring =
primarySubscription?.recurring ?? SubscriptionRecurring.Monthly;
proSubscription?.recurring ?? SubscriptionRecurring.Monthly;
const yearlyDiscount = (
planDetail.get(SubscriptionPlan.Pro) as FixedPrice | undefined

View File

@ -32,15 +32,13 @@ export const PlanCard = (props: PlanCardProps) => {
const loggedIn =
useLiveData(useService(AuthService).session.status$) === 'authenticated';
const subscriptionService = useService(SubscriptionService);
const primarySubscription = useLiveData(
subscriptionService.subscription.primary$
);
const currentPlan = primarySubscription?.plan ?? SubscriptionPlan.Free;
const proSubscription = useLiveData(subscriptionService.subscription.pro$);
const currentPlan = proSubscription?.plan ?? SubscriptionPlan.Free;
const isCurrent =
loggedIn &&
detail.plan === currentPlan &&
recurring === primarySubscription?.recurring;
recurring === proSubscription?.recurring;
const isPro = detail.plan === SubscriptionPlan.Pro;
return (
@ -93,7 +91,7 @@ const ActionButton = ({ detail, recurring }: PlanCardProps) => {
useLiveData(useService(AuthService).session.status$) === 'authenticated';
const subscriptionService = useService(SubscriptionService);
const primarySubscription = useLiveData(
subscriptionService.subscription.primary$
subscriptionService.subscription.pro$
);
const currentPlan = primarySubscription?.plan ?? SubscriptionPlan.Free;
const currentRecurring = primarySubscription?.recurring;

View File

@ -24,7 +24,7 @@ import { useRevokeMemberPermission } from '@affine/core/hooks/affine/use-revoke-
import { WorkspacePermissionService } from '@affine/core/modules/permissions';
import { WorkspaceQuotaService } from '@affine/core/modules/quota';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { Permission, SubscriptionPlan } from '@affine/graphql';
import { Permission } from '@affine/graphql';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { MoreVerticalIcon } from '@blocksuite/icons';
import {
@ -98,7 +98,7 @@ export const CloudWorkspaceMembersPanel = () => {
const workspaceQuota = useLiveData(workspaceQuotaService.quota.quota$);
const subscriptionService = useService(SubscriptionService);
const plan = useLiveData(
subscriptionService.subscription.primary$.map(s => s?.plan)
subscriptionService.subscription.pro$.map(s => s?.plan)
);
const isLimited = workspaceQuota
? checkMemberCountLimit(memberCount, workspaceQuota.memberLimit)
@ -206,7 +206,7 @@ export const CloudWorkspaceMembersPanel = () => {
<Button onClick={openModal}>{t['Invite Members']()}</Button>
{isLimited ? (
<MemberLimitModal
isFreePlan={plan === SubscriptionPlan.Free}
isFreePlan={!!plan}
open={open}
plan={workspaceQuota?.humanReadable.name ?? ''}
quota={workspaceQuota?.humanReadable.memberLimit ?? ''}

View File

@ -21,8 +21,7 @@ const UserInfo = () => {
useEffect(() => {
subscription.revalidate();
}, [subscription]);
const primary = useLiveData(subscription.primary$);
const plan = primary?.plan;
const plan = useLiveData(subscription.pro$)?.plan;
if (!user) {
// TODO: loading UI

View File

@ -28,34 +28,11 @@ export class Subscription extends Entity {
isRevalidating$ = new LiveData(false);
error$ = new LiveData<any | null>(null);
/**
* Primary subscription is the subscription that is not AI.
*/
primary$ = this.subscription$.map(subscriptions =>
subscriptions
? subscriptions.find(sub => sub.plan !== SubscriptionPlan.AI)
: null
);
isFree$ = this.subscription$.map(subscriptions =>
subscriptions
? subscriptions.some(sub => sub.plan === SubscriptionPlan.Free)
: null
);
isPro$ = this.subscription$.map(subscriptions =>
subscriptions
? subscriptions.some(sub => sub.plan === SubscriptionPlan.Pro)
: null
);
pro$ = this.subscription$.map(subscriptions =>
subscriptions
? subscriptions.find(sub => sub.plan === SubscriptionPlan.Pro)
: null
);
isSelfHosted$ = this.subscription$.map(subscriptions =>
subscriptions
? subscriptions.some(sub => sub.plan === SubscriptionPlan.SelfHosted)
: null
);
ai$ = this.subscription$.map(subscriptions =>
subscriptions
? subscriptions.find(sub => sub.plan === SubscriptionPlan.AI)