diff --git a/src/components/customers/subscriptions/CustomerSubscriptionsList.tsx b/src/components/customers/subscriptions/CustomerSubscriptionsList.tsx index 2566fb30d..447d7325d 100644 --- a/src/components/customers/subscriptions/CustomerSubscriptionsList.tsx +++ b/src/components/customers/subscriptions/CustomerSubscriptionsList.tsx @@ -1,7 +1,13 @@ import { forwardRef, MutableRefObject, useRef } from 'react' import styled, { css } from 'styled-components' +import { useParams } from 'react-router-dom' +import { gql } from '@apollo/client' -import { SubscriptionItemFragment, TimezoneEnum } from '~/generated/graphql' +import { + SubscriptionItemFragmentDoc, + TimezoneEnum, + useGetCustomerSubscriptionForListQuery, +} from '~/generated/graphql' import { Typography, Button } from '~/components/designSystem' import { useInternationalization } from '~/hooks/core/useInternationalization' import { theme, HEADER_TABLE_HEIGHT } from '~/styles' @@ -18,87 +24,104 @@ import { TerminateCustomerSubscriptionDialogRef, } from './TerminateCustomerSubscriptionDialog' +gql` + query getCustomerSubscriptionForList($id: ID!) { + customer(id: $id) { + id + subscriptions(status: [active, pending]) { + id + plan { + id + amountCurrency + } + ...SubscriptionItem + } + } + } + + ${SubscriptionItemFragmentDoc} +` + interface CustomerSubscriptionsListProps { - subscriptions?: SubscriptionItemFragment[] customerTimezone: TimezoneEnum - loading?: boolean } export const CustomerSubscriptionsList = forwardRef< AddSubscriptionDrawerRef, CustomerSubscriptionsListProps ->( - ( - { subscriptions, loading, customerTimezone }: CustomerSubscriptionsListProps, - addSubscriptionDialogRef - ) => { - const { translate } = useInternationalization() - const hasNoSubscription = !subscriptions || !subscriptions.length - const editSubscriptionDrawerRef = useRef(null) - const terminateSubscriptionDialogRef = useRef(null) - const subscriptionItemRef = useRef({ - addSubscriptionDialogRef, - editSubscriptionDrawerRef, - terminateSubscriptionDialogRef, - }) - - return ( - -
- {translate('text_6250304370f0f700a8fdc28d')} - -
- {loading ? ( - - {[0, 1, 2].map((_, i) => ( - - ))} - - ) : hasNoSubscription ? ( - {translate('text_6250304370f0f700a8fdc28f')} - ) : ( - <> - - - {translate('text_6253f11816f710014600b9ed')} - - - {translate('text_62d7f6178ec94cd09370e5fb')} - - - {translate('text_6253f11816f710014600b9f1')} - - - - {subscriptions.map((subscription, i) => { - return ( - - ) - })} - - - )} - - -
- ) - } -) +>(({ customerTimezone }: CustomerSubscriptionsListProps, addSubscriptionDialogRef) => { + const { id } = useParams() + const { translate } = useInternationalization() + const { data, loading } = useGetCustomerSubscriptionForListQuery({ + variables: { id: id as string }, + skip: !id, + }) + const subscriptions = data?.customer?.subscriptions + const hasNoSubscription = !subscriptions || !subscriptions.length + const editSubscriptionDrawerRef = useRef(null) + const terminateSubscriptionDialogRef = useRef(null) + const subscriptionItemRef = useRef({ + addSubscriptionDialogRef, + editSubscriptionDrawerRef, + terminateSubscriptionDialogRef, + }) + + return ( + +
+ {translate('text_6250304370f0f700a8fdc28d')} + +
+ {loading ? ( + + {[0, 1, 2].map((_, i) => ( + + ))} + + ) : hasNoSubscription ? ( + {translate('text_6250304370f0f700a8fdc28f')} + ) : ( + <> + + + {translate('text_6253f11816f710014600b9ed')} + + + {translate('text_62d7f6178ec94cd09370e5fb')} + + + {translate('text_6253f11816f710014600b9f1')} + + + + {subscriptions.map((subscription, i) => { + return ( + + ) + })} + + + )} + + +
+ ) +}) CustomerSubscriptionsList.displayName = 'CustomerSubscriptionsList' diff --git a/src/components/customers/subscriptions/TerminateCustomerSubscriptionDialog.tsx b/src/components/customers/subscriptions/TerminateCustomerSubscriptionDialog.tsx index fb57a9d49..c39707441 100644 --- a/src/components/customers/subscriptions/TerminateCustomerSubscriptionDialog.tsx +++ b/src/components/customers/subscriptions/TerminateCustomerSubscriptionDialog.tsx @@ -4,13 +4,21 @@ import { gql } from '@apollo/client' import { DialogRef } from '~/components/designSystem' import { useInternationalization } from '~/hooks/core/useInternationalization' import { addToast } from '~/core/apolloClient' -import { useTerminateCustomerSubscriptionMutation } from '~/generated/graphql' +import { + CustomerDetailsFragment, + CustomerDetailsFragmentDoc, + useTerminateCustomerSubscriptionMutation, +} from '~/generated/graphql' import { WarningDialog } from '~/components/WarningDialog' gql` mutation terminateCustomerSubscription($input: TerminateSubscriptionInput!) { terminateSubscription(input: $input) { id + customer { + id + activeSubscriptionCount + } } } ` @@ -41,6 +49,24 @@ export const TerminateCustomerSubscriptionDialog = }) cache.evict({ id: cacheId }) + + const cachedCustomerId = `Customer:${data.terminateSubscription.customer.id}` + + const previousData: CustomerDetailsFragment | null = cache.readFragment({ + id: cachedCustomerId, + fragment: CustomerDetailsFragmentDoc, + fragmentName: 'CustomerDetails', + }) + + cache.writeFragment({ + id: cachedCustomerId, + fragment: CustomerDetailsFragmentDoc, + fragmentName: 'CustomerDetails', + data: { + ...previousData, + activeSubscriptionCount: data.terminateSubscription.customer.activeSubscriptionCount, + }, + }) }, }) const [subscription, setSubscription] = useState< @@ -64,7 +90,7 @@ export const TerminateCustomerSubscriptionDialog = onContinue={async () => await terminate({ variables: { input: { id: subscription?.id as string } }, - refetchQueries: ['getCustomer'], + refetchQueries: ['getCustomerSubscriptionForList'], }) } continueText={translate('text_62d7f6178ec94cd09370e351')} diff --git a/src/components/customers/usage/CustomerUsage.tsx b/src/components/customers/usage/CustomerUsage.tsx index 3e2307367..92fb3b2a2 100644 --- a/src/components/customers/usage/CustomerUsage.tsx +++ b/src/components/customers/usage/CustomerUsage.tsx @@ -1,10 +1,11 @@ import { gql } from '@apollo/client' import styled from 'styled-components' +import { useParams } from 'react-router-dom' import { - CustomerUsageSubscriptionFragment, StatusTypeEnum, TimezoneEnum, + useGetCustomerSubscriptionForUsageQuery, } from '~/generated/graphql' import { useInternationalization } from '~/hooks/core/useInternationalization' import { theme, NAV_HEIGHT } from '~/styles' @@ -13,7 +14,7 @@ import { Typography } from '~/components/designSystem' import { UsageItem, UsageItemSkeleton } from './UsageItem' gql` - fragment CustomerUsageSubscription on Subscription { + fragment CustomerSubscriptionForUsage on Subscription { id name status @@ -23,22 +24,30 @@ gql` code } } + + query getCustomerSubscriptionForUsage($id: ID!) { + customer(id: $id) { + id + subscriptions(status: [active, pending]) { + id + ...CustomerSubscriptionForUsage + } + } + } ` interface CustomerUsageProps { - id: string - subscriptions: CustomerUsageSubscriptionFragment[] - loading?: boolean customerTimezone: TimezoneEnum } -export const CustomerUsage = ({ - loading, - id, - subscriptions, - customerTimezone, -}: CustomerUsageProps) => { +export const CustomerUsage = ({ customerTimezone }: CustomerUsageProps) => { + const { id } = useParams() const { translate } = useInternationalization() + const { data, loading } = useGetCustomerSubscriptionForUsageQuery({ + variables: { id: id as string }, + skip: !id, + }) + const subscriptions = data?.customer?.subscriptions return (
@@ -58,7 +67,7 @@ export const CustomerUsage = ({ .map((subscription) => ( diff --git a/src/components/customers/usage/UsageItem.tsx b/src/components/customers/usage/UsageItem.tsx index df16ece7e..f336283c6 100644 --- a/src/components/customers/usage/UsageItem.tsx +++ b/src/components/customers/usage/UsageItem.tsx @@ -7,7 +7,7 @@ import { ChargeUsage, CurrencyEnum, CustomerUsageForUsageDetailsFragmentDoc, - CustomerUsageSubscriptionFragment, + CustomerSubscriptionForUsageFragment, useCustomerUsageLazyQuery, TimezoneEnum, } from '~/generated/graphql' @@ -51,7 +51,7 @@ gql` interface UsageItemProps { customerId: string - subscription: CustomerUsageSubscriptionFragment + subscription: CustomerSubscriptionForUsageFragment customerTimezone: TimezoneEnum } diff --git a/src/generated/graphql.tsx b/src/generated/graphql.tsx index fc0923d56..66426459f 100644 --- a/src/generated/graphql.tsx +++ b/src/generated/graphql.tsx @@ -3356,6 +3356,13 @@ export type VoidCreditNoteMutationVariables = Exact<{ export type VoidCreditNoteMutation = { __typename?: 'Mutation', voidCreditNote?: { __typename?: 'CreditNote', id: string } | null }; +export type GetCustomerSubscriptionForListQueryVariables = Exact<{ + id: Scalars['ID']; +}>; + + +export type GetCustomerSubscriptionForListQuery = { __typename?: 'Query', customer?: { __typename?: 'Customer', id: string, subscriptions: Array<{ __typename?: 'Subscription', id: string, status?: StatusTypeEnum | null, startedAt?: any | null, nextPendingStartDate?: any | null, name?: string | null, nextName?: string | null, externalId: string, periodEndDate?: any | null, subscriptionAt?: any | null, plan: { __typename?: 'Plan', id: string, amountCurrency: CurrencyEnum, name: string, code: string }, nextPlan?: { __typename?: 'Plan', id: string, name: string, code: string } | null }> } | null }; + export type UpdateCustomerSubscriptionMutationVariables = Exact<{ input: UpdateSubscriptionInput; }>; @@ -3372,9 +3379,16 @@ export type TerminateCustomerSubscriptionMutationVariables = Exact<{ }>; -export type TerminateCustomerSubscriptionMutation = { __typename?: 'Mutation', terminateSubscription?: { __typename?: 'Subscription', id: string } | null }; +export type TerminateCustomerSubscriptionMutation = { __typename?: 'Mutation', terminateSubscription?: { __typename?: 'Subscription', id: string, customer: { __typename?: 'Customer', id: string, activeSubscriptionCount: number } } | null }; + +export type CustomerSubscriptionForUsageFragment = { __typename?: 'Subscription', id: string, name?: string | null, status?: StatusTypeEnum | null, plan: { __typename?: 'Plan', id: string, name: string, code: string } }; + +export type GetCustomerSubscriptionForUsageQueryVariables = Exact<{ + id: Scalars['ID']; +}>; + -export type CustomerUsageSubscriptionFragment = { __typename?: 'Subscription', id: string, name?: string | null, status?: StatusTypeEnum | null, plan: { __typename?: 'Plan', id: string, name: string, code: string } }; +export type GetCustomerSubscriptionForUsageQuery = { __typename?: 'Query', customer?: { __typename?: 'Customer', id: string, subscriptions: Array<{ __typename?: 'Subscription', id: string, name?: string | null, status?: StatusTypeEnum | null, plan: { __typename?: 'Plan', id: string, name: string, code: string } }> } | null }; export type CustomerUsageForUsageDetailsFragment = { __typename?: 'CustomerUsage', fromDatetime: any, toDatetime: any, chargesUsage: Array<{ __typename?: 'ChargeUsage', billableMetric: { __typename?: 'BillableMetric', name: string }, groups?: Array<{ __typename?: 'GroupUsage', id: string, amountCents: any, key?: string | null, units: number, value: string }> | null }> }; @@ -3661,7 +3675,7 @@ export type CreateSubscriptionMutationVariables = Exact<{ }>; -export type CreateSubscriptionMutation = { __typename?: 'Mutation', createSubscription?: { __typename?: 'Subscription', id: string, status?: StatusTypeEnum | null, startedAt?: any | null, nextPendingStartDate?: any | null, name?: string | null, nextName?: string | null, externalId: string, periodEndDate?: any | null, subscriptionAt?: any | null, plan: { __typename?: 'Plan', id: string, amountCurrency: CurrencyEnum, name: string, code: string }, nextPlan?: { __typename?: 'Plan', id: string, name: string, code: string } | null } | null }; +export type CreateSubscriptionMutation = { __typename?: 'Mutation', createSubscription?: { __typename?: 'Subscription', id: string, customer: { __typename?: 'Customer', id: string, activeSubscriptionCount: number } } | null }; export type GetSinglePlanQueryVariables = Exact<{ id: Scalars['ID']; @@ -3867,20 +3881,18 @@ export type GetCreditNoteQueryVariables = Exact<{ export type GetCreditNoteQuery = { __typename?: 'Query', creditNote?: { __typename?: 'CreditNote', id: string, balanceAmountCents: any, canBeVoided: boolean, createdAt: any, creditAmountCents: any, creditAmountCurrency: CurrencyEnum, creditStatus?: CreditNoteCreditStatusEnum | null, number: string, refundAmountCents: any, refundedAt?: any | null, refundStatus?: CreditNoteRefundStatusEnum | null, subTotalVatExcludedAmountCents: any, subTotalVatExcludedAmountCurrency: CurrencyEnum, totalAmountCents: any, totalAmountCurrency: CurrencyEnum, vatAmountCents: any, vatAmountCurrency: CurrencyEnum, customer: { __typename?: 'Customer', id: string, name?: string | null, deletedAt?: any | null, applicableTimezone: TimezoneEnum }, invoice?: { __typename?: 'Invoice', id: string, number: string } | null, items: Array<{ __typename?: 'CreditNoteItem', amountCents: any, amountCurrency: CurrencyEnum, fee: { __typename?: 'Fee', id: string, amountCents: any, amountCurrency: CurrencyEnum, eventsCount?: any | null, units: number, feeType: FeeTypesEnum, itemName: string, charge?: { __typename?: 'Charge', id: string, billableMetric: { __typename?: 'BillableMetric', id: string, name: string, aggregationType: AggregationTypeEnum } } | null, subscription?: { __typename?: 'Subscription', id: string, name?: string | null, plan: { __typename?: 'Plan', id: string, name: string } } | null, group?: { __typename?: 'Group', id: string, key?: string | null, value: string } | null } }> } | null }; -export type CustomerSubscriptionFragment = { __typename?: 'Subscription', id: string, status?: StatusTypeEnum | null, startedAt?: any | null, nextPendingStartDate?: any | null, name?: string | null, nextName?: string | null, externalId: string, periodEndDate?: any | null, subscriptionAt?: any | null, plan: { __typename?: 'Plan', id: string, amountCurrency: CurrencyEnum, name: string, code: string }, nextPlan?: { __typename?: 'Plan', id: string, name: string, code: string } | null }; - export type CustomerAppliedAddOnsFragment = { __typename?: 'Customer', id: string, appliedAddOns?: Array<{ __typename?: 'AppliedAddOn', id: string, amountCents: any, amountCurrency: CurrencyEnum, createdAt: any, addOn: { __typename?: 'AddOn', id: string, name: string } }> | null }; export type CustomerAppliedCouponsFragment = { __typename?: 'Customer', id: string, appliedCoupons?: Array<{ __typename?: 'AppliedCoupon', id: string, amountCurrency?: CurrencyEnum | null, amountCents?: any | null, amountCentsRemaining?: any | null, percentageRate?: number | null, frequency: CouponFrequency, frequencyDuration?: number | null, frequencyDurationRemaining?: number | null, coupon: { __typename?: 'Coupon', id: string, name: string } }> | null }; -export type CustomerDetailsFragment = { __typename?: 'Customer', id: string, name?: string | null, externalId: string, hasActiveWallet: boolean, currency?: CurrencyEnum | null, hasCreditNotes: boolean, creditNotesCreditsAvailableCount: number, creditNotesBalanceAmountCents: any, applicableTimezone: TimezoneEnum, addressLine1?: string | null, addressLine2?: string | null, canEditAttributes: boolean, city?: string | null, country?: CountryCode | null, email?: string | null, legalName?: string | null, legalNumber?: string | null, paymentProvider?: ProviderTypeEnum | null, phone?: string | null, state?: string | null, timezone?: TimezoneEnum | null, zipcode?: string | null, subscriptions: Array<{ __typename?: 'Subscription', id: string, status?: StatusTypeEnum | null, startedAt?: any | null, nextPendingStartDate?: any | null, name?: string | null, nextName?: string | null, externalId: string, periodEndDate?: any | null, subscriptionAt?: any | null, plan: { __typename?: 'Plan', id: string, amountCurrency: CurrencyEnum, name: string, code: string }, nextPlan?: { __typename?: 'Plan', id: string, name: string, code: string } | null }>, appliedCoupons?: Array<{ __typename?: 'AppliedCoupon', id: string, amountCurrency?: CurrencyEnum | null, amountCents?: any | null, amountCentsRemaining?: any | null, percentageRate?: number | null, frequency: CouponFrequency, frequencyDuration?: number | null, frequencyDurationRemaining?: number | null, coupon: { __typename?: 'Coupon', id: string, name: string } }> | null, appliedAddOns?: Array<{ __typename?: 'AppliedAddOn', id: string, amountCents: any, amountCurrency: CurrencyEnum, createdAt: any, addOn: { __typename?: 'AddOn', id: string, name: string } }> | null, providerCustomer?: { __typename?: 'ProviderCustomer', id: string, providerCustomerId?: string | null, syncWithProvider?: boolean | null } | null, metadata?: Array<{ __typename?: 'CustomerMetadata', id: string, key: string, value: string, displayInInvoice: boolean }> | null }; +export type CustomerDetailsFragment = { __typename?: 'Customer', id: string, name?: string | null, externalId: string, hasActiveWallet: boolean, currency?: CurrencyEnum | null, hasCreditNotes: boolean, creditNotesCreditsAvailableCount: number, creditNotesBalanceAmountCents: any, applicableTimezone: TimezoneEnum, activeSubscriptionCount: number, addressLine1?: string | null, addressLine2?: string | null, canEditAttributes: boolean, city?: string | null, country?: CountryCode | null, email?: string | null, legalName?: string | null, legalNumber?: string | null, paymentProvider?: ProviderTypeEnum | null, phone?: string | null, state?: string | null, timezone?: TimezoneEnum | null, zipcode?: string | null, appliedCoupons?: Array<{ __typename?: 'AppliedCoupon', id: string, amountCurrency?: CurrencyEnum | null, amountCents?: any | null, amountCentsRemaining?: any | null, percentageRate?: number | null, frequency: CouponFrequency, frequencyDuration?: number | null, frequencyDurationRemaining?: number | null, coupon: { __typename?: 'Coupon', id: string, name: string } }> | null, appliedAddOns?: Array<{ __typename?: 'AppliedAddOn', id: string, amountCents: any, amountCurrency: CurrencyEnum, createdAt: any, addOn: { __typename?: 'AddOn', id: string, name: string } }> | null, providerCustomer?: { __typename?: 'ProviderCustomer', id: string, providerCustomerId?: string | null, syncWithProvider?: boolean | null } | null, metadata?: Array<{ __typename?: 'CustomerMetadata', id: string, key: string, value: string, displayInInvoice: boolean }> | null }; export type GetCustomerQueryVariables = Exact<{ id: Scalars['ID']; }>; -export type GetCustomerQuery = { __typename?: 'Query', customer?: { __typename?: 'Customer', id: string, name?: string | null, externalId: string, hasActiveWallet: boolean, currency?: CurrencyEnum | null, hasCreditNotes: boolean, creditNotesCreditsAvailableCount: number, creditNotesBalanceAmountCents: any, applicableTimezone: TimezoneEnum, addressLine1?: string | null, addressLine2?: string | null, canEditAttributes: boolean, city?: string | null, country?: CountryCode | null, email?: string | null, legalName?: string | null, legalNumber?: string | null, paymentProvider?: ProviderTypeEnum | null, phone?: string | null, state?: string | null, timezone?: TimezoneEnum | null, zipcode?: string | null, subscriptions: Array<{ __typename?: 'Subscription', id: string, status?: StatusTypeEnum | null, startedAt?: any | null, nextPendingStartDate?: any | null, name?: string | null, nextName?: string | null, externalId: string, periodEndDate?: any | null, subscriptionAt?: any | null, plan: { __typename?: 'Plan', id: string, amountCurrency: CurrencyEnum, name: string, code: string }, nextPlan?: { __typename?: 'Plan', id: string, name: string, code: string } | null }>, appliedCoupons?: Array<{ __typename?: 'AppliedCoupon', id: string, amountCurrency?: CurrencyEnum | null, amountCents?: any | null, amountCentsRemaining?: any | null, percentageRate?: number | null, frequency: CouponFrequency, frequencyDuration?: number | null, frequencyDurationRemaining?: number | null, coupon: { __typename?: 'Coupon', id: string, name: string } }> | null, appliedAddOns?: Array<{ __typename?: 'AppliedAddOn', id: string, amountCents: any, amountCurrency: CurrencyEnum, createdAt: any, addOn: { __typename?: 'AddOn', id: string, name: string } }> | null, providerCustomer?: { __typename?: 'ProviderCustomer', id: string, providerCustomerId?: string | null, syncWithProvider?: boolean | null } | null, metadata?: Array<{ __typename?: 'CustomerMetadata', id: string, key: string, value: string, displayInInvoice: boolean }> | null } | null }; +export type GetCustomerQuery = { __typename?: 'Query', customer?: { __typename?: 'Customer', id: string, name?: string | null, externalId: string, hasActiveWallet: boolean, currency?: CurrencyEnum | null, hasCreditNotes: boolean, creditNotesCreditsAvailableCount: number, creditNotesBalanceAmountCents: any, applicableTimezone: TimezoneEnum, activeSubscriptionCount: number, addressLine1?: string | null, addressLine2?: string | null, canEditAttributes: boolean, city?: string | null, country?: CountryCode | null, email?: string | null, legalName?: string | null, legalNumber?: string | null, paymentProvider?: ProviderTypeEnum | null, phone?: string | null, state?: string | null, timezone?: TimezoneEnum | null, zipcode?: string | null, appliedCoupons?: Array<{ __typename?: 'AppliedCoupon', id: string, amountCurrency?: CurrencyEnum | null, amountCents?: any | null, amountCentsRemaining?: any | null, percentageRate?: number | null, frequency: CouponFrequency, frequencyDuration?: number | null, frequencyDurationRemaining?: number | null, coupon: { __typename?: 'Coupon', id: string, name: string } }> | null, appliedAddOns?: Array<{ __typename?: 'AppliedAddOn', id: string, amountCents: any, amountCurrency: CurrencyEnum, createdAt: any, addOn: { __typename?: 'AddOn', id: string, name: string } }> | null, providerCustomer?: { __typename?: 'ProviderCustomer', id: string, providerCustomerId?: string | null, syncWithProvider?: boolean | null } | null, metadata?: Array<{ __typename?: 'CustomerMetadata', id: string, key: string, value: string, displayInInvoice: boolean }> | null } | null }; export type GetCustomerDraftInvoicesQueryVariables = Exact<{ customerId: Scalars['ID']; @@ -4313,6 +4325,44 @@ export const CreditNotesForListFragmentDoc = gql` } } `; +export const SubscriptionLinePlanFragmentDoc = gql` + fragment SubscriptionLinePlan on Plan { + id + name + code +} + `; +export const SubscriptionItemFragmentDoc = gql` + fragment SubscriptionItem on Subscription { + id + status + startedAt + nextPendingStartDate + name + nextName + externalId + periodEndDate + subscriptionAt + plan { + ...SubscriptionLinePlan + } + nextPlan { + ...SubscriptionLinePlan + } +} + ${SubscriptionLinePlanFragmentDoc}`; +export const CustomerSubscriptionForUsageFragmentDoc = gql` + fragment CustomerSubscriptionForUsage on Subscription { + id + name + status + plan { + id + name + code + } +} + `; export const CustomerUsageForUsageDetailsFragmentDoc = gql` fragment CustomerUsageForUsageDetails on CustomerUsage { fromDatetime @@ -4977,56 +5027,6 @@ export const EditPlanFragmentDoc = gql` } } ${ChargeAccordionFragmentDoc}`; -export const SubscriptionLinePlanFragmentDoc = gql` - fragment SubscriptionLinePlan on Plan { - id - name - code -} - `; -export const SubscriptionItemFragmentDoc = gql` - fragment SubscriptionItem on Subscription { - id - status - startedAt - nextPendingStartDate - name - nextName - externalId - periodEndDate - subscriptionAt - plan { - ...SubscriptionLinePlan - } - nextPlan { - ...SubscriptionLinePlan - } -} - ${SubscriptionLinePlanFragmentDoc}`; -export const CustomerUsageSubscriptionFragmentDoc = gql` - fragment CustomerUsageSubscription on Subscription { - id - name - status - plan { - id - name - code - } -} - `; -export const CustomerSubscriptionFragmentDoc = gql` - fragment CustomerSubscription on Subscription { - id - plan { - id - amountCurrency - } - ...SubscriptionItem - ...CustomerUsageSubscription -} - ${SubscriptionItemFragmentDoc} -${CustomerUsageSubscriptionFragmentDoc}`; export const AppliedCouponCaptionFragmentDoc = gql` fragment AppliedCouponCaption on AppliedCoupon { id @@ -5117,16 +5117,13 @@ export const CustomerDetailsFragmentDoc = gql` creditNotesCreditsAvailableCount creditNotesBalanceAmountCents applicableTimezone - subscriptions(status: [active, pending]) { - ...CustomerSubscription - } + activeSubscriptionCount ...CustomerAppliedCoupons ...CustomerAppliedAddOns ...AddCustomerDrawer ...CustomerMainInfos } - ${CustomerSubscriptionFragmentDoc} -${CustomerAppliedCouponsFragmentDoc} + ${CustomerAppliedCouponsFragmentDoc} ${CustomerAppliedAddOnsFragmentDoc} ${AddCustomerDrawerFragmentDoc} ${CustomerMainInfosFragmentDoc}`; @@ -6106,6 +6103,49 @@ export function useVoidCreditNoteMutation(baseOptions?: Apollo.MutationHookOptio export type VoidCreditNoteMutationHookResult = ReturnType; export type VoidCreditNoteMutationResult = Apollo.MutationResult; export type VoidCreditNoteMutationOptions = Apollo.BaseMutationOptions; +export const GetCustomerSubscriptionForListDocument = gql` + query getCustomerSubscriptionForList($id: ID!) { + customer(id: $id) { + id + subscriptions(status: [active, pending]) { + id + plan { + id + amountCurrency + } + ...SubscriptionItem + } + } +} + ${SubscriptionItemFragmentDoc}`; + +/** + * __useGetCustomerSubscriptionForListQuery__ + * + * To run a query within a React component, call `useGetCustomerSubscriptionForListQuery` and pass it any options that fit your needs. + * When your component renders, `useGetCustomerSubscriptionForListQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetCustomerSubscriptionForListQuery({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useGetCustomerSubscriptionForListQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetCustomerSubscriptionForListDocument, options); + } +export function useGetCustomerSubscriptionForListLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetCustomerSubscriptionForListDocument, options); + } +export type GetCustomerSubscriptionForListQueryHookResult = ReturnType; +export type GetCustomerSubscriptionForListLazyQueryHookResult = ReturnType; +export type GetCustomerSubscriptionForListQueryResult = Apollo.QueryResult; export const UpdateCustomerSubscriptionDocument = gql` mutation updateCustomerSubscription($input: UpdateSubscriptionInput!) { updateSubscription(input: $input) { @@ -6147,6 +6187,10 @@ export const TerminateCustomerSubscriptionDocument = gql` mutation terminateCustomerSubscription($input: TerminateSubscriptionInput!) { terminateSubscription(input: $input) { id + customer { + id + activeSubscriptionCount + } } } `; @@ -6176,6 +6220,45 @@ export function useTerminateCustomerSubscriptionMutation(baseOptions?: Apollo.Mu export type TerminateCustomerSubscriptionMutationHookResult = ReturnType; export type TerminateCustomerSubscriptionMutationResult = Apollo.MutationResult; export type TerminateCustomerSubscriptionMutationOptions = Apollo.BaseMutationOptions; +export const GetCustomerSubscriptionForUsageDocument = gql` + query getCustomerSubscriptionForUsage($id: ID!) { + customer(id: $id) { + id + subscriptions(status: [active, pending]) { + id + ...CustomerSubscriptionForUsage + } + } +} + ${CustomerSubscriptionForUsageFragmentDoc}`; + +/** + * __useGetCustomerSubscriptionForUsageQuery__ + * + * To run a query within a React component, call `useGetCustomerSubscriptionForUsageQuery` and pass it any options that fit your needs. + * When your component renders, `useGetCustomerSubscriptionForUsageQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetCustomerSubscriptionForUsageQuery({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useGetCustomerSubscriptionForUsageQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetCustomerSubscriptionForUsageDocument, options); + } +export function useGetCustomerSubscriptionForUsageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetCustomerSubscriptionForUsageDocument, options); + } +export type GetCustomerSubscriptionForUsageQueryHookResult = ReturnType; +export type GetCustomerSubscriptionForUsageLazyQueryHookResult = ReturnType; +export type GetCustomerSubscriptionForUsageQueryResult = Apollo.QueryResult; export const CustomerUsageDocument = gql` query customerUsage($customerId: ID!, $subscriptionId: ID!) { customerUsage(customerId: $customerId, subscriptionId: $subscriptionId) { @@ -7230,10 +7313,14 @@ export type GetPlansQueryResult = Apollo.QueryResult; /** diff --git a/src/hooks/customer/useAddSubscription.tsx b/src/hooks/customer/useAddSubscription.tsx index f4c16ae38..3569c1d80 100644 --- a/src/hooks/customer/useAddSubscription.tsx +++ b/src/hooks/customer/useAddSubscription.tsx @@ -11,7 +11,8 @@ import { useCreateSubscriptionMutation, LagoApiError, CreateSubscriptionInput, - CustomerSubscriptionFragmentDoc, + CustomerDetailsFragment, + CustomerDetailsFragmentDoc, } from '~/generated/graphql' import { SubscriptionUpdateInfo, addToast, hasDefinedGQLError } from '~/core/apolloClient' import { ComboBoxProps } from '~/components/form' @@ -36,11 +37,13 @@ gql` mutation createSubscription($input: CreateSubscriptionInput!) { createSubscription(input: $input) { - ...CustomerSubscription + id + customer { + id + activeSubscriptionCount + } } } - - ${CustomerSubscriptionFragmentDoc} ` interface UseAddSubscriptionReturn { @@ -89,7 +92,28 @@ export const useAddSubscription: UseAddSubscription = ({ }) } }, - refetchQueries: ['getCustomer'], + update(cache, { data: updatedData }) { + if (!updatedData?.createSubscription) return + + const cachedCustomerId = `Customer:${updatedData?.createSubscription.customer.id}` + + const previousData: CustomerDetailsFragment | null = cache.readFragment({ + id: cachedCustomerId, + fragment: CustomerDetailsFragmentDoc, + fragmentName: 'CustomerDetails', + }) + + cache.writeFragment({ + id: cachedCustomerId, + fragment: CustomerDetailsFragmentDoc, + fragmentName: 'CustomerDetails', + data: { + ...previousData, + activeSubscriptionCount: updatedData.createSubscription.customer.activeSubscriptionCount, + }, + }) + }, + refetchQueries: ['getCustomerSubscriptionForList'], }) const selectedPlan = useMemo(() => { diff --git a/src/pages/CustomerDetails.tsx b/src/pages/CustomerDetails.tsx index 9ff02cf30..b83278a0c 100644 --- a/src/pages/CustomerDetails.tsx +++ b/src/pages/CustomerDetails.tsx @@ -23,8 +23,6 @@ import { CustomerCouponFragmentDoc, CustomerMainInfosFragmentDoc, CustomerAddOnsFragmentDoc, - CustomerUsageSubscriptionFragmentDoc, - StatusTypeEnum, TimezoneEnum, AddCustomerDrawerFragmentDoc, } from '~/generated/graphql' @@ -65,16 +63,6 @@ import { import { CustomerCreditNotesList } from '~/components/customers/CustomerCreditNotesList' gql` - fragment CustomerSubscription on Subscription { - id - plan { - id - amountCurrency - } - ...SubscriptionItem - ...CustomerUsageSubscription - } - fragment CustomerAppliedAddOns on Customer { id appliedAddOns { @@ -99,9 +87,7 @@ gql` creditNotesCreditsAvailableCount creditNotesBalanceAmountCents applicableTimezone - subscriptions(status: [active, pending]) { - ...CustomerSubscription - } + activeSubscriptionCount ...CustomerAppliedCoupons ...CustomerAppliedAddOns ...AddCustomerDrawer @@ -119,7 +105,6 @@ gql` ${CustomerCouponFragmentDoc} ${CustomerAddOnsFragmentDoc} ${CustomerMainInfosFragmentDoc} - ${CustomerUsageSubscriptionFragmentDoc} ` export enum CustomerDetailsTabsOptions { @@ -156,12 +141,9 @@ const CustomerDetails = () => { hasActiveWallet, hasCreditNotes, name, - subscriptions, + activeSubscriptionCount, applicableTimezone, } = data?.customer || {} - const hasActiveSubscription = !!(subscriptions || [])?.filter( - (s) => s?.status === StatusTypeEnum.Active - ).length const safeTimezone = applicableTimezone || TimezoneEnum.TzUtc return ( @@ -350,8 +332,6 @@ const CustomerDetails = () => { )} @@ -381,15 +361,10 @@ const CustomerDetails = () => { tab: CustomerDetailsTabsOptions.usage, }), routerState: { disableScrollTop: true }, - hidden: !hasActiveSubscription, + hidden: activeSubscriptionCount === 0, component: ( - + ), },