411 lines
13 KiB
JavaScript
411 lines
13 KiB
JavaScript
import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
|
|
import * as types from '../mutation-types';
|
|
import AccountAPI from '../../api/account';
|
|
import { differenceInDays } from 'date-fns';
|
|
import EnterpriseAccountAPI from '../../api/enterprise/account';
|
|
import { throwErrorMessage } from '../utils/api';
|
|
import { getLanguageDirection } from 'dashboard/components/widgets/conversation/advancedFilterItems/languages';
|
|
|
|
const findRecordById = ($state, id) =>
|
|
$state.records.find(record => record.id === Number(id)) || {};
|
|
|
|
const TRIAL_PERIOD_DAYS = 15;
|
|
|
|
const state = {
|
|
records: [],
|
|
uiFlags: {
|
|
isFetching: false,
|
|
isFetchingItem: false,
|
|
isUpdating: false,
|
|
isCheckoutInProcess: false,
|
|
},
|
|
v2Billing: {
|
|
creditsBalance: null,
|
|
creditGrants: [],
|
|
pricingPlans: [],
|
|
topupOptions: [],
|
|
uiFlags: {
|
|
isFetchingBalance: false,
|
|
isFetchingGrants: false,
|
|
isFetchingPlans: false,
|
|
isFetchingTopupOptions: false,
|
|
isTopupInProcess: false,
|
|
isSubscribeInProcess: false,
|
|
isCancelInProcess: false,
|
|
},
|
|
},
|
|
};
|
|
|
|
export const getters = {
|
|
getAccount: $state => id => {
|
|
return findRecordById($state, id);
|
|
},
|
|
getUIFlags($state) {
|
|
return $state.uiFlags;
|
|
},
|
|
getV2BillingData($state) {
|
|
return $state.v2Billing;
|
|
},
|
|
getV2BillingUIFlags($state) {
|
|
return $state.v2Billing.uiFlags;
|
|
},
|
|
isRTL: ($state, _getters, rootState, rootGetters) => {
|
|
const accountId = Number(rootState.route?.params?.accountId);
|
|
const userLocale = rootGetters?.getUISettings?.locale;
|
|
const accountLocale =
|
|
accountId && findRecordById($state, accountId)?.locale;
|
|
|
|
// Prefer user locale; fallback to account locale
|
|
const effectiveLocale = userLocale ?? accountLocale;
|
|
|
|
return effectiveLocale ? getLanguageDirection(effectiveLocale) : false;
|
|
},
|
|
isTrialAccount: $state => id => {
|
|
const account = findRecordById($state, id);
|
|
const createdAt = new Date(account.created_at);
|
|
const diffDays = differenceInDays(new Date(), createdAt);
|
|
|
|
return diffDays <= TRIAL_PERIOD_DAYS;
|
|
},
|
|
isFeatureEnabledonAccount: $state => (id, featureName) => {
|
|
const { features = {} } = findRecordById($state, id);
|
|
return features[featureName] || false;
|
|
},
|
|
};
|
|
|
|
export const actions = {
|
|
get: async ({ commit }) => {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isFetchingItem: true });
|
|
try {
|
|
const response = await AccountAPI.get();
|
|
commit(types.default.ADD_ACCOUNT, response.data);
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, {
|
|
isFetchingItem: false,
|
|
});
|
|
} catch (error) {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, {
|
|
isFetchingItem: false,
|
|
});
|
|
}
|
|
},
|
|
update: async ({ commit }, { options, ...updateObj }) => {
|
|
if (options?.silent !== true) {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: true });
|
|
}
|
|
|
|
try {
|
|
const response = await AccountAPI.update('', updateObj);
|
|
commit(types.default.EDIT_ACCOUNT, response.data);
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false });
|
|
} catch (error) {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false });
|
|
throw new Error(error);
|
|
}
|
|
},
|
|
delete: async ({ commit }, { id }) => {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: true });
|
|
try {
|
|
await AccountAPI.delete(id);
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false });
|
|
} catch (error) {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false });
|
|
throw new Error(error);
|
|
}
|
|
},
|
|
toggleDeletion: async (
|
|
{ commit },
|
|
{ action_type } = { action_type: 'delete' }
|
|
) => {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: true });
|
|
try {
|
|
await EnterpriseAccountAPI.toggleDeletion(action_type);
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false });
|
|
} catch (error) {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isUpdating: false });
|
|
throw new Error(error);
|
|
}
|
|
},
|
|
create: async ({ commit }, accountInfo) => {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCreating: true });
|
|
try {
|
|
const response = await AccountAPI.createAccount(accountInfo);
|
|
const account_id = response.data.data.account_id;
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCreating: false });
|
|
return account_id;
|
|
} catch (error) {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCreating: false });
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
checkout: async ({ commit }) => {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCheckoutInProcess: true });
|
|
try {
|
|
const response = await EnterpriseAccountAPI.checkout();
|
|
window.location = response.data.redirect_url;
|
|
} catch (error) {
|
|
throwErrorMessage(error);
|
|
} finally {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCheckoutInProcess: false });
|
|
}
|
|
},
|
|
|
|
subscription: async ({ commit }) => {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCheckoutInProcess: true });
|
|
try {
|
|
await EnterpriseAccountAPI.subscription();
|
|
} catch (error) {
|
|
throwErrorMessage(error);
|
|
} finally {
|
|
commit(types.default.SET_ACCOUNT_UI_FLAG, { isCheckoutInProcess: false });
|
|
}
|
|
},
|
|
|
|
limits: async ({ commit }) => {
|
|
try {
|
|
const response = await EnterpriseAccountAPI.getLimits();
|
|
commit(types.default.SET_ACCOUNT_LIMITS, response.data);
|
|
} catch (error) {
|
|
// silent error
|
|
}
|
|
},
|
|
|
|
getCacheKeys: async () => {
|
|
return AccountAPI.getCacheKeys();
|
|
},
|
|
|
|
// V2 Billing actions
|
|
fetchCreditsBalance: async ({ commit }) => {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, { isFetchingBalance: true });
|
|
try {
|
|
const response = await EnterpriseAccountAPI.getLimits();
|
|
const responses = response.data?.limits?.captain?.responses || {};
|
|
|
|
// Transform captain.responses to the format expected by the UI
|
|
const creditsBalance = {
|
|
total_credits: responses.total_count || 0,
|
|
monthly_credits: responses.monthly || 0,
|
|
topup_credits: responses.topup || 0,
|
|
usage_this_month: responses.consumed || 0,
|
|
current_available: responses.current_available || 0,
|
|
};
|
|
|
|
commit(types.default.SET_CREDITS_BALANCE, creditsBalance);
|
|
} catch (error) {
|
|
throwErrorMessage(error);
|
|
} finally {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isFetchingBalance: false,
|
|
});
|
|
}
|
|
},
|
|
|
|
fetchCreditGrants: async ({ commit }) => {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, { isFetchingGrants: true });
|
|
try {
|
|
const response = await EnterpriseAccountAPI.creditGrants();
|
|
commit(types.default.SET_CREDIT_GRANTS, response.data.credit_grants);
|
|
} catch (error) {
|
|
throwErrorMessage(error);
|
|
} finally {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isFetchingGrants: false,
|
|
});
|
|
}
|
|
},
|
|
|
|
fetchV2PricingPlans: async ({ commit }) => {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, { isFetchingPlans: true });
|
|
try {
|
|
const response = await EnterpriseAccountAPI.v2PricingPlans();
|
|
commit(types.default.SET_V2_PRICING_PLANS, response.data.pricing_plans);
|
|
} catch (error) {
|
|
throwErrorMessage(error);
|
|
} finally {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, { isFetchingPlans: false });
|
|
}
|
|
},
|
|
|
|
fetchV2TopupOptions: async ({ commit }) => {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isFetchingTopupOptions: true,
|
|
});
|
|
try {
|
|
const response = await EnterpriseAccountAPI.v2TopupOptions();
|
|
// Transform backend structure: rename 'amount' to 'price'
|
|
const transformedOptions = response.data.topup_options.map(option => ({
|
|
...option,
|
|
price: option.amount,
|
|
id: `topup-${option.credits}`,
|
|
}));
|
|
commit(types.default.SET_V2_TOPUP_OPTIONS, transformedOptions);
|
|
} catch (error) {
|
|
throwErrorMessage(error);
|
|
} finally {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isFetchingTopupOptions: false,
|
|
});
|
|
}
|
|
},
|
|
|
|
v2Topup: async ({ commit }, data) => {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, { isTopupInProcess: true });
|
|
try {
|
|
await EnterpriseAccountAPI.v2Topup(data);
|
|
return { success: true };
|
|
} catch (error) {
|
|
const errorMessage = error.response?.data?.error || error.message;
|
|
return { success: false, error: errorMessage };
|
|
} finally {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, { isTopupInProcess: false });
|
|
}
|
|
},
|
|
|
|
v2Subscribe: async ({ commit, dispatch }, data) => {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isSubscribeInProcess: true,
|
|
});
|
|
try {
|
|
const response = await EnterpriseAccountAPI.v2Subscribe(data);
|
|
// If backend returns redirect_url, redirect to Stripe checkout
|
|
if (response.data.redirect_url) {
|
|
window.location.href = response.data.redirect_url;
|
|
return { success: true, redirecting: true };
|
|
}
|
|
// Otherwise refresh data (for non-Stripe flows)
|
|
await Promise.all([
|
|
dispatch('fetchCreditsBalance'),
|
|
dispatch('fetchV2PricingPlans'),
|
|
dispatch('subscription'),
|
|
]);
|
|
return { success: true };
|
|
} catch (error) {
|
|
throwErrorMessage(error);
|
|
return { success: false };
|
|
} finally {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isSubscribeInProcess: false,
|
|
});
|
|
}
|
|
},
|
|
|
|
v2CancelSubscription: async ({ commit, dispatch }, data) => {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, { isCancelInProcess: true });
|
|
try {
|
|
const response = await EnterpriseAccountAPI.cancelSubscription(data);
|
|
// Update account with new subscription status
|
|
if (response.data.id && response.data.custom_attributes) {
|
|
commit(types.default.SET_ACCOUNT_LIMITS, response.data);
|
|
}
|
|
// Refresh balance and plans after cancellation
|
|
await Promise.all([
|
|
dispatch('fetchCreditsBalance'),
|
|
dispatch('fetchV2PricingPlans'),
|
|
]);
|
|
return { success: true };
|
|
} catch (error) {
|
|
const errorMessage = error.response?.data?.error || error.message;
|
|
return { success: false, error: errorMessage };
|
|
} finally {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isCancelInProcess: false,
|
|
});
|
|
}
|
|
},
|
|
|
|
v2UpdateQuantity: async (
|
|
{ commit, dispatch },
|
|
{ pricingPlanId, quantity }
|
|
) => {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isSubscribeInProcess: true,
|
|
});
|
|
try {
|
|
const response = await EnterpriseAccountAPI.changePricingPlan({
|
|
pricing_plan_id: pricingPlanId,
|
|
quantity,
|
|
});
|
|
// Update account with new quantity
|
|
if (response.data.id && response.data.custom_attributes) {
|
|
commit(types.default.SET_ACCOUNT_LIMITS, response.data);
|
|
}
|
|
// Refresh balance after quantity update
|
|
await dispatch('fetchCreditsBalance');
|
|
return { success: true };
|
|
} catch (error) {
|
|
const errorMessage = error.response?.data?.error || error.message;
|
|
return { success: false, error: errorMessage };
|
|
} finally {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isSubscribeInProcess: false,
|
|
});
|
|
}
|
|
},
|
|
|
|
v2ChangePlan: async ({ commit, dispatch }, data) => {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isSubscribeInProcess: true,
|
|
});
|
|
try {
|
|
const response = await EnterpriseAccountAPI.changePricingPlan(data);
|
|
// Update account with new plan
|
|
if (response.data.id && response.data.custom_attributes) {
|
|
commit(types.default.SET_ACCOUNT_LIMITS, response.data);
|
|
}
|
|
// Refresh balance and plans after change
|
|
await Promise.all([
|
|
dispatch('fetchCreditsBalance'),
|
|
dispatch('fetchV2PricingPlans'),
|
|
]);
|
|
return { success: true };
|
|
} catch (error) {
|
|
const errorMessage = error.response?.data?.error || error.message;
|
|
return { success: false, error: errorMessage };
|
|
} finally {
|
|
commit(types.default.SET_V2_BILLING_UI_FLAG, {
|
|
isSubscribeInProcess: false,
|
|
});
|
|
}
|
|
},
|
|
};
|
|
|
|
export const mutations = {
|
|
[types.default.SET_ACCOUNT_UI_FLAG]($state, data) {
|
|
$state.uiFlags = {
|
|
...$state.uiFlags,
|
|
...data,
|
|
};
|
|
},
|
|
[types.default.ADD_ACCOUNT]: MutationHelpers.setSingleRecord,
|
|
[types.default.EDIT_ACCOUNT]: MutationHelpers.update,
|
|
[types.default.SET_ACCOUNT_LIMITS]: MutationHelpers.updateAttributes,
|
|
|
|
// V2 Billing mutations
|
|
[types.default.SET_V2_BILLING_UI_FLAG]($state, data) {
|
|
$state.v2Billing.uiFlags = {
|
|
...$state.v2Billing.uiFlags,
|
|
...data,
|
|
};
|
|
},
|
|
[types.default.SET_CREDITS_BALANCE]($state, data) {
|
|
$state.v2Billing.creditsBalance = data;
|
|
},
|
|
[types.default.SET_CREDIT_GRANTS]($state, data) {
|
|
$state.v2Billing.creditGrants = data;
|
|
},
|
|
[types.default.SET_V2_PRICING_PLANS]($state, data) {
|
|
$state.v2Billing.pricingPlans = data;
|
|
},
|
|
[types.default.SET_V2_TOPUP_OPTIONS]($state, data) {
|
|
$state.v2Billing.topupOptions = data;
|
|
},
|
|
};
|
|
|
|
export default {
|
|
namespaced: true,
|
|
state,
|
|
getters,
|
|
actions,
|
|
mutations,
|
|
};
|