feat(billing): refacto billing (#14243)
… prices for metered billing --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com> Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadedState';
|
||||
import { dateTimeFormatState } from '@/localization/states/dateTimeFormatState';
|
||||
import { useDateTimeFormat } from '@/localization/hooks/useDateTimeFormat';
|
||||
import { UserContext } from '@/users/contexts/UserContext';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { AppPath } from 'twenty-shared/types';
|
||||
@@ -13,7 +13,7 @@ export const UserProvider = ({ children }: React.PropsWithChildren) => {
|
||||
const isCurrentUserLoaded = useRecoilValue(isCurrentUserLoadedState);
|
||||
const location = useLocation();
|
||||
|
||||
const dateTimeFormat = useRecoilValue(dateTimeFormatState);
|
||||
const { dateFormat, timeFormat, timeZone } = useDateTimeFormat();
|
||||
|
||||
return !isCurrentUserLoaded &&
|
||||
!isMatchingLocation(location, AppPath.Verify) &&
|
||||
@@ -23,9 +23,9 @@ export const UserProvider = ({ children }: React.PropsWithChildren) => {
|
||||
) : (
|
||||
<UserContext.Provider
|
||||
value={{
|
||||
dateFormat: dateTimeFormat.dateFormat,
|
||||
timeFormat: dateTimeFormat.timeFormat,
|
||||
timeZone: dateTimeFormat.timeZone,
|
||||
dateFormat,
|
||||
timeFormat,
|
||||
timeZone,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -9,14 +9,7 @@ import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMembe
|
||||
import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMembersState';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadedState';
|
||||
import { DateFormat } from '@/localization/constants/DateFormat';
|
||||
import { TimeFormat } from '@/localization/constants/TimeFormat';
|
||||
import { dateTimeFormatState } from '@/localization/states/dateTimeFormatState';
|
||||
import { detectDateFormat } from '@/localization/utils/detectDateFormat';
|
||||
import { detectTimeFormat } from '@/localization/utils/detectTimeFormat';
|
||||
import { detectTimeZone } from '@/localization/utils/detectTimeZone';
|
||||
import { getDateFormatFromWorkspaceDateFormat } from '@/localization/utils/getDateFormatFromWorkspaceDateFormat';
|
||||
import { getTimeFormatFromWorkspaceTimeFormat } from '@/localization/utils/getTimeFormatFromWorkspaceTimeFormat';
|
||||
import { useInitializeFormatPreferences } from '@/localization/hooks/useInitializeFormatPreferences';
|
||||
import { getDateFnsLocale } from '@/ui/field/display/utils/getDateFnsLocale.util';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
@@ -46,7 +39,7 @@ export const UserProviderEffect = () => {
|
||||
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
||||
const setCurrentUserWorkspace = useSetRecoilState(currentUserWorkspaceState);
|
||||
const setAvailableWorkspaces = useSetRecoilState(availableWorkspacesState);
|
||||
const setDateTimeFormat = useSetRecoilState(dateTimeFormatState);
|
||||
const { initializeFormatPreferences } = useInitializeFormatPreferences();
|
||||
const isLoggedIn = useIsLogged();
|
||||
|
||||
const updateLocaleCatalog = useRecoilCallback(
|
||||
@@ -155,19 +148,8 @@ export const UserProviderEffect = () => {
|
||||
|
||||
updateLocaleCatalog(updatedWorkspaceMember.locale);
|
||||
|
||||
// TODO: factorize
|
||||
setDateTimeFormat({
|
||||
timeZone:
|
||||
workspaceMember.timeZone && workspaceMember.timeZone !== 'system'
|
||||
? workspaceMember.timeZone
|
||||
: detectTimeZone(),
|
||||
dateFormat: isDefined(workspaceMember.dateFormat)
|
||||
? getDateFormatFromWorkspaceDateFormat(workspaceMember.dateFormat)
|
||||
: DateFormat[detectDateFormat()],
|
||||
timeFormat: isDefined(workspaceMember.timeFormat)
|
||||
? getTimeFormatFromWorkspaceTimeFormat(workspaceMember.timeFormat)
|
||||
: TimeFormat[detectTimeFormat()],
|
||||
});
|
||||
// Initialize format preferences from workspace member
|
||||
initializeFormatPreferences(updatedWorkspaceMember);
|
||||
|
||||
dynamicActivate(
|
||||
(workspaceMember.locale as keyof typeof APP_LOCALES) ?? SOURCE_LOCALE,
|
||||
@@ -195,7 +177,7 @@ export const UserProviderEffect = () => {
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
setIsCurrentUserLoaded,
|
||||
setDateTimeFormat,
|
||||
initializeFormatPreferences,
|
||||
setCurrentWorkspaceMembersWithDeleted,
|
||||
updateLocaleCatalog,
|
||||
setCoreViews,
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { BILLING_SUBSCRIPTION_SCHEDULE_PHASE_ITEM_FRAGMENT } from '@/billing/graphql/fragments/billingSubscriptionSchedulePhaseItemFragment';
|
||||
import { BILLING_SUBSCRIPTION_SCHEDULE_PHASE_FRAGMENT } from '@/billing/graphql/fragments/billingSubscriptionSchedulePhaseFragment';
|
||||
|
||||
export const BILLING_SUBSCRIPTION_FRAGMENT = gql`
|
||||
fragment BillingSubscriptionFragment on BillingSubscription {
|
||||
id
|
||||
status
|
||||
metadata
|
||||
phases {
|
||||
...BillingSubscriptionSchedulePhaseFragment
|
||||
}
|
||||
}
|
||||
|
||||
${BILLING_SUBSCRIPTION_SCHEDULE_PHASE_ITEM_FRAGMENT}
|
||||
${BILLING_SUBSCRIPTION_SCHEDULE_PHASE_FRAGMENT}
|
||||
`;
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { BILLING_SUBSCRIPTION_SCHEDULE_PHASE_FRAGMENT } from '@/billing/graphql/fragments/billingSubscriptionSchedulePhaseFragment';
|
||||
import { BILLING_SUBSCRIPTION_SCHEDULE_PHASE_ITEM_FRAGMENT } from '@/billing/graphql/fragments/billingSubscriptionSchedulePhaseItemFragment';
|
||||
|
||||
export const CURRENT_BILLING_SUBSCRIPTION_FRAGMENT = gql`
|
||||
fragment CurrentBillingSubscriptionFragment on BillingSubscription {
|
||||
id
|
||||
status
|
||||
interval
|
||||
metadata
|
||||
currentPeriodEnd
|
||||
phases {
|
||||
...BillingSubscriptionSchedulePhaseFragment
|
||||
}
|
||||
billingSubscriptionItems {
|
||||
id
|
||||
hasReachedCurrentPeriodCap
|
||||
quantity
|
||||
stripePriceId
|
||||
billingProduct {
|
||||
name
|
||||
description
|
||||
images
|
||||
metadata {
|
||||
productKey
|
||||
planKey
|
||||
priceUsageBased
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${BILLING_SUBSCRIPTION_SCHEDULE_PHASE_ITEM_FRAGMENT}
|
||||
${BILLING_SUBSCRIPTION_SCHEDULE_PHASE_FRAGMENT}
|
||||
`;
|
||||
@@ -10,6 +10,8 @@ import { DELETED_WORKSPACE_MEMBER_QUERY_FRAGMENT } from '@/workspace-member/grap
|
||||
import { PARTIAL_WORKSPACE_MEMBER_QUERY_FRAGMENT } from '@/workspace-member/graphql/fragments/partialWorkspaceMemberQueryFragment';
|
||||
import { WORKSPACE_MEMBER_QUERY_FRAGMENT } from '@/workspace-member/graphql/fragments/workspaceMemberQueryFragment';
|
||||
import { gql } from '@apollo/client';
|
||||
import { CURRENT_BILLING_SUBSCRIPTION_FRAGMENT } from '@/users/graphql/fragments/currentBillingSubscriptionFragement';
|
||||
import { BILLING_SUBSCRIPTION_FRAGMENT } from '@/users/graphql/fragments/billingSubscriptionsFragment';
|
||||
|
||||
export const USER_QUERY_FRAGMENT = gql`
|
||||
fragment UserQueryFragment on User {
|
||||
@@ -65,31 +67,10 @@ export const USER_QUERY_FRAGMENT = gql`
|
||||
}
|
||||
metadataVersion
|
||||
currentBillingSubscription {
|
||||
id
|
||||
status
|
||||
interval
|
||||
metadata
|
||||
currentPeriodEnd
|
||||
billingSubscriptionItems {
|
||||
id
|
||||
hasReachedCurrentPeriodCap
|
||||
quantity
|
||||
stripePriceId
|
||||
billingProduct {
|
||||
name
|
||||
description
|
||||
metadata {
|
||||
planKey
|
||||
priceUsageBased
|
||||
productKey
|
||||
}
|
||||
}
|
||||
}
|
||||
...CurrentBillingSubscriptionFragment
|
||||
}
|
||||
billingSubscriptions {
|
||||
id
|
||||
status
|
||||
metadata
|
||||
...BillingSubscriptionFragment
|
||||
}
|
||||
workspaceMembersCount
|
||||
defaultRole {
|
||||
@@ -118,4 +99,6 @@ export const USER_QUERY_FRAGMENT = gql`
|
||||
${VIEW_FRAGMENT}
|
||||
${AVAILABLE_WORKSPACES_FOR_AUTH_FRAGMENT}
|
||||
${AVAILABLE_WORKSPACE_FOR_AUTH_FRAGMENT}
|
||||
${CURRENT_BILLING_SUBSCRIPTION_FRAGMENT}
|
||||
${BILLING_SUBSCRIPTION_FRAGMENT}
|
||||
`;
|
||||
|
||||
@@ -6,14 +6,7 @@ import { currentWorkspaceMembersState } from '@/auth/states/currentWorkspaceMemb
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useIsCurrentLocationOnAWorkspace } from '@/domain-manager/hooks/useIsCurrentLocationOnAWorkspace';
|
||||
import { useLastAuthenticatedWorkspaceDomain } from '@/domain-manager/hooks/useLastAuthenticatedWorkspaceDomain';
|
||||
import { DateFormat } from '@/localization/constants/DateFormat';
|
||||
import { TimeFormat } from '@/localization/constants/TimeFormat';
|
||||
import { dateTimeFormatState } from '@/localization/states/dateTimeFormatState';
|
||||
import { detectDateFormat } from '@/localization/utils/detectDateFormat';
|
||||
import { detectTimeFormat } from '@/localization/utils/detectTimeFormat';
|
||||
import { detectTimeZone } from '@/localization/utils/detectTimeZone';
|
||||
import { getDateFormatFromWorkspaceDateFormat } from '@/localization/utils/getDateFormatFromWorkspaceDateFormat';
|
||||
import { getTimeFormatFromWorkspaceTimeFormat } from '@/localization/utils/getTimeFormatFromWorkspaceTimeFormat';
|
||||
import { useInitializeFormatPreferences } from '@/localization/hooks/useInitializeFormatPreferences';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { useCallback } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
@@ -38,7 +31,7 @@ export const useLoadCurrentUser = () => {
|
||||
currentWorkspaceMembersState,
|
||||
);
|
||||
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
|
||||
const setDateTimeFormat = useSetRecoilState(dateTimeFormatState);
|
||||
const { initializeFormatPreferences } = useInitializeFormatPreferences();
|
||||
const setCoreViews = useSetRecoilState(coreViewsState);
|
||||
|
||||
const { isOnAWorkspace } = useIsCurrentLocationOnAWorkspace();
|
||||
@@ -91,23 +84,8 @@ export const useLoadCurrentUser = () => {
|
||||
|
||||
setCurrentWorkspaceMember(workspaceMember);
|
||||
|
||||
// TODO: factorize with UserProviderEffect
|
||||
setDateTimeFormat({
|
||||
timeZone:
|
||||
workspaceMember.timeZone && workspaceMember.timeZone !== 'system'
|
||||
? workspaceMember.timeZone
|
||||
: detectTimeZone(),
|
||||
dateFormat: isDefined(user.workspaceMember.dateFormat)
|
||||
? getDateFormatFromWorkspaceDateFormat(
|
||||
user.workspaceMember.dateFormat,
|
||||
)
|
||||
: DateFormat[detectDateFormat()],
|
||||
timeFormat: isDefined(user.workspaceMember.timeFormat)
|
||||
? getTimeFormatFromWorkspaceTimeFormat(
|
||||
user.workspaceMember.timeFormat,
|
||||
)
|
||||
: TimeFormat[detectTimeFormat()],
|
||||
});
|
||||
// Initialize unified format preferences state
|
||||
initializeFormatPreferences(workspaceMember);
|
||||
dynamicActivate(
|
||||
(workspaceMember.locale as keyof typeof APP_LOCALES) ?? SOURCE_LOCALE,
|
||||
);
|
||||
@@ -143,7 +121,7 @@ export const useLoadCurrentUser = () => {
|
||||
setCurrentWorkspace,
|
||||
setCurrentWorkspaceMember,
|
||||
setCurrentWorkspaceMembers,
|
||||
setDateTimeFormat,
|
||||
initializeFormatPreferences,
|
||||
setLastAuthenticateWorkspaceDomain,
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user