import { computed, ref } from 'vue' import { getIntegrations, type Integration, type integrationType } from '@/constants/integrations' import { useProFeatures } from '@/composables/useProFeatures' import { useProFeatureUpgrade } from '@/composables/useProFeatureUpgrade' import { useSettingsStore } from '@/stores/useSettingsStore' /** * Integrations Composable * * Manages integration status and dynamically updates types based on: * - Pro installation status * - Current license plan * - Connection/activation state */ interface IntegrationState { [key: string]: { enabled: boolean connected: boolean } } export function useIntegrations() { const pro = useProFeatures() const settingsStore = useSettingsStore() const { isProInstalled: checkProInstalled, isProLicenseActive: checkProLicenseActive } = useProFeatureUpgrade() const integrationState = ref({}) /** * Load integration states from settings store */ const loadIntegrationStates = async () => { // Load from the settings store's integrationsSettings const storeSettings = settingsStore.integrationsSettings || {} // Transform to match our IntegrationState interface const transformed: IntegrationState = {} for (const [key, value] of Object.entries(storeSettings)) { if (value && typeof value === 'object') { transformed[key] = { enabled: (value as { enabled?: boolean }).enabled || false, connected: (value as { connected?: boolean }).connected || false, } } } integrationState.value = transformed } /** * Check if Pro is installed and meets minimum plan requirement * Also checks if license is active */ const meetsRequirement = (requiredPlan?: string): boolean => { if (!requiredPlan) return true // First check: Is Pro installed and license active? if (!checkProInstalled() || !checkProLicenseActive()) { return false } // Wait for Pro features to be loaded if (!pro.loaded.value) { return false } const currentPlan = pro.plan.value const isProInstalledCheck = currentPlan !== 'lite' && currentPlan !== 'error' && currentPlan !== 'unauthorized' if (!isProInstalledCheck) return false const planHierarchy = ['essentials', 'growth', 'agency'] const currentIndex = planHierarchy.indexOf(currentPlan) const requiredIndex = planHierarchy.indexOf(requiredPlan) return currentIndex >= requiredIndex && currentIndex !== -1 } /** * Determine integration type dynamically */ const getIntegrationType = (integration: Integration): integrationType => { const state = integrationState.value[integration.value] || { enabled: false, connected: false } // Check if this is a Pro integration (plan is not 'lite') const isProIntegration = integration.searchCategory !== 'lite' if (isProIntegration) { const proInstalled = checkProInstalled() const licenseActive = checkProLicenseActive() // CASE 1: Pro not installed at all // All Pro features show upgrade badge if (!proInstalled) { return 'upgrade' // Show upgrade with plan badge, disable toggle } // CASE 2: Pro installed but license not active // Check if the user's stored plan tier covers the required plan. // If yes → show "Activate License" (proDisabled); they have the right plan, just need a key. // If no → show "Upgrade" (upgrade); they need to purchase a higher tier. if (!licenseActive) { const planHierarchy = ['essentials', 'growth', 'agency'] const storedPlanIndex = planHierarchy.indexOf(pro.installedPlan.value) const requiredPlanIndex = planHierarchy.indexOf(integration.requiredPlan || 'essentials') if (storedPlanIndex !== -1 && storedPlanIndex >= requiredPlanIndex) { return 'proDisabled' // Right plan tier — just needs an active license } return 'upgrade' // Needs a higher plan tier } // CASE 3: Pro installed and licensed - check plan hierarchy // Plan hierarchy: essentials < growth < agency if (!meetsRequirement(integration.requiredPlan)) { // Licensed but insufficient plan // Examples: // - Essentials user viewing Growth feature → show 'upgrade' with "GROWTH" badge // - Essentials user viewing Agency feature → show 'upgrade' with "AGENCY" badge // - Growth user viewing Agency feature → show 'upgrade' with "AGENCY" badge return 'upgrade' // Show upgrade with required plan badge, disable toggle } // CASE 4: Pro installed, licensed, and plan is sufficient // User has the required plan or higher - show normal functionality // Now check if integration is enabled/connected // If not enabled, return 'proDisabled' if (!state.enabled) { return 'proDisabled' } // If enabled but not connected, return 'proDisabled' if (!state.connected) { return 'proDisabled' } // Enabled and connected return 'proActive' } // Lite integrations // PRIORITY 1: Check if plugin is installed (connected) // If installed, ALWAYS show "Learn More" regardless of toggle state if (state.connected) { return 'active' } // PRIORITY 2: Plugin is NOT installed return 'disabled' } /** * Get all integrations with dynamic types * Now async - loads from backend registry */ const integrations = ref([]) const integrationsLoaded = ref(false) const loadIntegrations = async () => { if (integrationsLoaded.value) { return integrations.value } // Call getIntegrations() to get filtered list from backend at runtime const loaded = await getIntegrations() integrations.value = loaded.map((integration) => ({ ...integration, type: getIntegrationType(integration), })) integrationsLoaded.value = true return integrations.value } /** * Update integration state */ const updateIntegrationState = (name: string, enabled: boolean, connected = false) => { integrationState.value[name] = { enabled, connected } } return { integrations: computed(() => integrations.value), integrationsLoaded: computed(() => integrationsLoaded.value), integrationState, loadIntegrations, loadIntegrationStates, updateIntegrationState, getIntegrationType, } }