import { ref, computed, onMounted } from 'vue'; import axios from 'axios'; import { UserTypes } from '../../utils/UserTypes.js'; import { useUserStore } from '../../stores/user.js'; // Global reactive state to persist throughout the SPA session const globalRole = ref(sessionStorage.getItem('user_acct_type') || UserTypes.PUBLIC); const isFetching = ref(false); /** * Fetches the user account type from the server. * Ensures only one request is made per session. */ async function fetchRole() { if (isFetching.value) return; // If we already have a specialized role in sessionStorage, don't fetch again const cached = sessionStorage.getItem('user_acct_type'); if (cached && cached !== UserTypes.PUBLIC) { return; } isFetching.value = true; try { const response = await axios.get('/get/user/acct-type'); let acctType = response.data?.acct_type; // Handle case where acct_type might be an object (Enum serialization) if (acctType && typeof acctType === 'object' && acctType.value) { acctType = acctType.value; } if (acctType) { globalRole.value = acctType; sessionStorage.setItem('user_acct_type', acctType); } } catch (error) { // If 401, we are likely a guest if (error.response?.status === 401) { globalRole.value = UserTypes.PUBLIC; sessionStorage.setItem('user_acct_type', UserTypes.PUBLIC); } else { console.warn('Failed to fetch user acct type from server:', error); } } finally { isFetching.value = false; } } // Initial fetch attempt if we don't have a definitive role if (!sessionStorage.getItem('user_acct_type') || sessionStorage.getItem('user_acct_type') === UserTypes.PUBLIC) { fetchRole(); } export function resetRole() { globalRole.value = UserTypes.PUBLIC; isFetching.value = false; sessionStorage.removeItem('user_acct_type'); } /** * Composable for managing user roles and permissions in the frontend. * @param {Object} [user] - Optional user object for legacy support or specific overrides */ export function useAuth(user = null) { const userStore = useUserStore(); // Priority: Explicitly passed user prop > user store > sessionStorage fallback const currentUser = computed(() => { if (user?.value ?? user) return user?.value ?? user; const storeUser = userStore.user; if (storeUser && Object.keys(storeUser).length > 0) return storeUser; try { const stored = sessionStorage.getItem('currentUser'); return stored ? JSON.parse(stored) : null; } catch (e) { return null; } }); const role = computed(() => { // Priority 1: User object passed directly or from store const localRole = userStore.acctType || currentUser.value?.acct_type; if (localRole) { if (typeof localRole === 'object' && localRole.value) return localRole.value; return localRole; } // Priority 2: Global fetched role return globalRole.value; }); const hasRole = (targetRole) => { if (Array.isArray(targetRole)) { return targetRole.some(r => role.value === r); } return role.value === targetRole; }; // Role-specific helpers const isUltimate = computed(() => role.value === UserTypes.ULTIMATE); const isSuperOperator = computed(() => role.value === UserTypes.SUPER_OPERATOR); const isOperator = computed(() => role.value === UserTypes.OPERATOR); const isCoordinator = computed(() => role.value === UserTypes.COORDINATOR); const isStoreOwner = computed(() => role.value === UserTypes.STORE_OWNER); const isStoreManager = computed(() => role.value === UserTypes.STORE_MANAGER); const isRider = computed(() => role.value === UserTypes.RIDER); const isSupplier = computed(() => role.value === UserTypes.SUPPLIER); const isSupplierOverseer = computed(() => role.value === UserTypes.SUPPLIER_OVERSEER); const isWholesaleBuyer = computed(() => role.value === UserTypes.WHOLESALE_BUYER); const isAudit = computed(() => role.value === UserTypes.AUDIT); const isUser = computed(() => role.value === UserTypes.USER); const isCoopOfficer = computed(() => role.value === UserTypes.COOP_OFFICER); const isCoopMember = computed(() => role.value === UserTypes.COOP_MEMBER); const isPOSTerminal = computed(() => role.value === UserTypes.POS_TERMINAL); const isPublic = computed(() => role.value === UserTypes.PUBLIC || !userStore.isLoggedIn); const isLoggedIn = computed(() => userStore.isLoggedIn); return { user: currentUser, role, hasRole, isUltimate, isSuperOperator, isOperator, isCoordinator, isStoreOwner, isStoreManager, isRider, isSupplier, isSupplierOverseer, isWholesaleBuyer, isAudit, isUser, isCoopOfficer, isCoopMember, isPOSTerminal, isPublic, isLoggedIn, UserTypes, refreshRole: fetchRole, // Expose the user store for direct access to user data userStore }; }