feat: implement barangay system phases 2-14
Complete adaptation from BukidBountyApp to Philippine barangay governance: - Barangay models: Resident, Household, HouseholdMember, Blotter, BlotterHearing, DocumentRequest, RequestPayment, RequestType, BarangayProject, BarangayBudget - Controllers: ResidentController, HouseholdController, BlotterController, BlotterHearingController, DocumentRequestController, RequestTypeController, ProjectController, BudgetController, QRPHController, AdminConsoleController, UserController, FileController, ChapterController, LoginController - Vue pages: Home, ManageResidents, ResidentProfile, ManageHouseholds, ManageBlotters, BlotterDetail, RequestDocument, ManageDocumentRequests, DocumentRequestDetail, ManageRequestTypes, ManageProjects, BudgetLedger, AdminConsole - Barangay roles: PunongBarangay, Kagawad, Secretary, Treasurer, SK, Tanod, BHW, Staff, Resident - UserPermissions matrix rewritten with barangay-specific permission mappings - VueRouteMap replaced with barangay SPA routes - UserActions enum references corrected across all controllers - Removed all market/cooperative/POS/subscription code and models
This commit is contained in:
@@ -1,53 +1,35 @@
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { ref, computed } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { UserTypes } from '../../utils/UserTypes.js';
|
||||
import { UserTypes, ADMIN_ROLES, STAFF_ROLES } 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;
|
||||
}
|
||||
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 && 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();
|
||||
}
|
||||
@@ -58,90 +40,79 @@ export function resetRole() {
|
||||
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) {
|
||||
} catch {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
// Barangay-specific role helpers
|
||||
const isSuperAdmin = computed(() => role.value === UserTypes.SUPER_ADMIN);
|
||||
const isPunongBarangay = computed(() => role.value === UserTypes.PUNONG_BARANGAY);
|
||||
const isKagawad = computed(() => role.value === UserTypes.KAGAWAD);
|
||||
const isSecretary = computed(() => role.value === UserTypes.SECRETARY);
|
||||
const isTreasurer = computed(() => role.value === UserTypes.TREASURER);
|
||||
const isSkChairperson = computed(() => role.value === UserTypes.SK_CHAIRPERSON);
|
||||
const isSkCouncilor = computed(() => role.value === UserTypes.SK_COUNCILOR);
|
||||
const isTanod = computed(() => role.value === UserTypes.TANOD);
|
||||
const isBhw = computed(() => role.value === UserTypes.BHW);
|
||||
const isDaycareWorker = computed(() => role.value === UserTypes.DAYCARE_WORKER);
|
||||
const isStaff = computed(() => role.value === UserTypes.STAFF);
|
||||
const isResident = computed(() => role.value === UserTypes.RESIDENT);
|
||||
const isAudit = computed(() => role.value === UserTypes.AUDIT);
|
||||
const isPublic = computed(() => role.value === UserTypes.PUBLIC || !userStore.isLoggedIn);
|
||||
const isLoggedIn = computed(() => userStore.isLoggedIn);
|
||||
|
||||
// Group helpers
|
||||
const isAdmin = computed(() => ADMIN_ROLES.includes(role.value));
|
||||
const isBarangayStaff = computed(() => STAFF_ROLES.includes(role.value));
|
||||
|
||||
return {
|
||||
user: currentUser,
|
||||
role,
|
||||
hasRole,
|
||||
isUltimate,
|
||||
isSuperOperator,
|
||||
isOperator,
|
||||
isCoordinator,
|
||||
isStoreOwner,
|
||||
isStoreManager,
|
||||
isRider,
|
||||
isSupplier,
|
||||
isSupplierOverseer,
|
||||
isWholesaleBuyer,
|
||||
isSuperAdmin,
|
||||
isPunongBarangay,
|
||||
isKagawad,
|
||||
isSecretary,
|
||||
isTreasurer,
|
||||
isSkChairperson,
|
||||
isSkCouncilor,
|
||||
isTanod,
|
||||
isBhw,
|
||||
isDaycareWorker,
|
||||
isStaff,
|
||||
isResident,
|
||||
isAudit,
|
||||
isUser,
|
||||
isCoopOfficer,
|
||||
isCoopMember,
|
||||
isPOSTerminal,
|
||||
isPublic,
|
||||
isLoggedIn,
|
||||
isAdmin,
|
||||
isBarangayStaff,
|
||||
UserTypes,
|
||||
refreshRole: fetchRole,
|
||||
// Expose the user store for direct access to user data
|
||||
userStore
|
||||
userStore,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { usePosStore } from '../../stores/pos';
|
||||
import { useUIStore } from '../../stores/ui';
|
||||
import { useOfflineStore } from '../useOfflineStore';
|
||||
import { useNetworkStore } from '../../stores/network';
|
||||
|
||||
export function usePosSession(props) {
|
||||
const posStore = usePosStore();
|
||||
const uiStore = useUIStore();
|
||||
const offlineStore = useOfflineStore();
|
||||
const networkStore = useNetworkStore();
|
||||
const storeHash = ref(null);
|
||||
const showSuccessAnimation = ref(false);
|
||||
const isOfflineMode = ref(false);
|
||||
|
||||
// Helper: Access key from URL or LocalStorage
|
||||
const getStoredAccessKey = () => {
|
||||
try {
|
||||
return localStorage.getItem('pos_access_key');
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const initialize = async () => {
|
||||
// Check for existing session in URL or Storage
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const accessKey = props.access_key || urlParams.get('key') || getStoredAccessKey();
|
||||
const hashkey = props.target;
|
||||
|
||||
if (accessKey) {
|
||||
localStorage.setItem('pos_access_key', accessKey);
|
||||
}
|
||||
|
||||
// 1. Load Session or treat as Store Hash
|
||||
if (hashkey) {
|
||||
// Try loading as session
|
||||
await posStore.loadSession(hashkey, accessKey);
|
||||
|
||||
if (!posStore.activeSession) {
|
||||
// Not a session? Treat it as a direct link to a store terminal
|
||||
storeHash.value = hashkey;
|
||||
posStore.error = null;
|
||||
} else if (posStore.activeSession?.store?.hashkey) {
|
||||
storeHash.value = posStore.activeSession.store.hashkey;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fetch products (Always synchronized with access key/store hash)
|
||||
await posStore.fetchProducts(accessKey, storeHash.value);
|
||||
|
||||
// 3. Fallback: If no direct session yet, try to load one by access key
|
||||
if (!posStore.activeSession && accessKey) {
|
||||
await posStore.loadSession(null, accessKey);
|
||||
}
|
||||
|
||||
// 4. Synchronization: ensure products are loaded if session was found later
|
||||
if (posStore.activeSession && posStore.products.length === 0) {
|
||||
await posStore.fetchProducts(accessKey, storeHash.value);
|
||||
}
|
||||
|
||||
// 5. Restore offline cart if no server session was found
|
||||
if (!posStore.activeSession) {
|
||||
try {
|
||||
const savedRaw = localStorage.getItem('pos_cart_session')
|
||||
const saved = savedRaw ? JSON.parse(savedRaw) : null
|
||||
if (saved?.offline && saved.cart?.length > 0) {
|
||||
posStore.activeSession = { hashkey: saved.sessionHashkey, offline: true, transactions: [] }
|
||||
posStore.cart = saved.cart
|
||||
posStore.isOfflineMode = true
|
||||
isOfflineMode.value = true
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
// 6. Load terminal stats
|
||||
await posStore.fetchTodayStats(storeHash.value);
|
||||
};
|
||||
|
||||
const completeTransaction = async (customerName) => {
|
||||
const currentStoreHash = storeHash.value || posStore.activeSession?.store?.hashkey;
|
||||
|
||||
// Try Online First (skip if session is a local offline-only session)
|
||||
let success = false;
|
||||
const isOfflineSession = posStore.activeSession?.offline === true;
|
||||
if (networkStore.isOnline && !isOfflineSession) {
|
||||
success = await posStore.completeTransaction(customerName);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// Offline Fallback
|
||||
const txnData = {
|
||||
store_hash: currentStoreHash,
|
||||
customer_name: customerName,
|
||||
items: posStore.cart.map(item => ({
|
||||
product_hashkey: item.product?.hashkey,
|
||||
quantity: item.quantity,
|
||||
price_at_sale: item.price_at_sale
|
||||
})),
|
||||
total: posStore.totalAmount,
|
||||
received: posStore.receivedAmount,
|
||||
change: posStore.changeAmount,
|
||||
method: posStore.paymentMethod
|
||||
};
|
||||
|
||||
const id = await offlineStore.storeTransactionOffline(txnData);
|
||||
if (id) {
|
||||
success = true;
|
||||
isOfflineMode.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
showSuccessAnimation.value = true;
|
||||
|
||||
// Clean up state
|
||||
posStore.resetSession();
|
||||
|
||||
// Delayed re-initialization (gives time for animation)
|
||||
setTimeout(async () => {
|
||||
showSuccessAnimation.value = false;
|
||||
if (networkStore.isOnline) {
|
||||
await posStore.startNewSession(currentStoreHash, '', getStoredAccessKey());
|
||||
await Promise.all([
|
||||
posStore.fetchTodayStats(currentStoreHash),
|
||||
posStore.fetchPosSessions(currentStoreHash, 1)
|
||||
]);
|
||||
isOfflineMode.value = false;
|
||||
}
|
||||
}, 2500);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const startNewSessionSilently = async () => {
|
||||
const accessKey = getStoredAccessKey();
|
||||
if (!storeHash.value && !accessKey) {
|
||||
posStore.error = 'No store selected. Open the POS from a store page or use an access key.';
|
||||
return false;
|
||||
}
|
||||
return await posStore.startNewSession(storeHash.value, '', accessKey);
|
||||
};
|
||||
|
||||
// Keep storeHash in sync with active session if it changes
|
||||
watch(() => posStore.activeSession, (session) => {
|
||||
if (session?.store?.hashkey) {
|
||||
storeHash.value = session.store.hashkey;
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
return {
|
||||
storeHash,
|
||||
showSuccessAnimation,
|
||||
initialize,
|
||||
completeTransaction,
|
||||
startNewSessionSilently,
|
||||
getStoredAccessKey,
|
||||
isOfflineMode
|
||||
};
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { computed, onMounted } from 'vue';
|
||||
import { useGlobalTransactionStore } from '../stores/globalTransaction';
|
||||
|
||||
export function useGlobalTransactions(filters = null) {
|
||||
const store = useGlobalTransactionStore();
|
||||
|
||||
const transactions = computed(() => store.transactions);
|
||||
const isLoading = computed(() => store.isLoading);
|
||||
const error = computed(() => store.error);
|
||||
|
||||
const fetchTransactions = async (newFilters = null) => {
|
||||
return await store.fetchTransactions(newFilters || filters || {});
|
||||
};
|
||||
|
||||
const getProductTransactions = (productHash) => {
|
||||
return computed(() => store.getTransactionsByProduct(productHash));
|
||||
};
|
||||
|
||||
const precache = () => store.precache();
|
||||
|
||||
return {
|
||||
transactions,
|
||||
isLoading,
|
||||
error,
|
||||
fetchTransactions,
|
||||
getProductTransactions,
|
||||
precache
|
||||
};
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
import { ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { useFileBlobCache } from './useFileBlobCache';
|
||||
|
||||
/**
|
||||
* Composable for fetching and managing a list of photos for a specific entity.
|
||||
*/
|
||||
export function usePhotoList() {
|
||||
const { getFile, preCacheFiles, blobCache } = useFileBlobCache();
|
||||
|
||||
const photos = ref([]);
|
||||
const loading = ref(false);
|
||||
const error = ref(null);
|
||||
|
||||
/**
|
||||
* Fetch photos for a target hash and type.
|
||||
*
|
||||
* @param {string} targetHash
|
||||
* @param {string} type - 'StoreMarket', 'ProductMarket', 'User'
|
||||
*/
|
||||
const fetchPhotos = async (targetHash, type = 'StoreMarket') => {
|
||||
if (!targetHash) return;
|
||||
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
|
||||
try {
|
||||
const response = await axios.post(`/Request/Photos/${type}`, {
|
||||
target: targetHash
|
||||
});
|
||||
|
||||
if (response.data && Array.isArray(response.data)) {
|
||||
photos.value = response.data;
|
||||
// Pre-cache all blobs for these hashes
|
||||
await preCacheFiles(photos.value);
|
||||
} else {
|
||||
photos.value = [];
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching photos:', err);
|
||||
error.value = 'Failed to load photos.';
|
||||
photos.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
photos,
|
||||
loading,
|
||||
error,
|
||||
fetchPhotos,
|
||||
blobCache,
|
||||
getFile
|
||||
};
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
import { ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
export function useUltimate() {
|
||||
const loading = ref(false);
|
||||
const stats = ref(null);
|
||||
const queryResults = ref(null);
|
||||
const affectedRows = ref(0);
|
||||
const commandOutput = ref('');
|
||||
|
||||
const getStats = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/admin/ultimate/stats');
|
||||
if (response.data.success) {
|
||||
stats.value = response.data.data;
|
||||
}
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch stats:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const runQuery = async (query) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/admin/ultimate/query', { query });
|
||||
if (response.data.success) {
|
||||
queryResults.value = response.data.data || null;
|
||||
affectedRows.value = response.data.affected || 0;
|
||||
}
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Failed to run query:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const toggleMaintenance = async (enabled) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/admin/ultimate/maintenance/toggle', { enabled });
|
||||
if (response.data.success && stats.value) {
|
||||
stats.value.maintenance_mode = response.data.maintenance_mode;
|
||||
}
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Failed to toggle maintenance:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const sendGlobalMessage = async (message, type = 'info') => {
|
||||
loading.value = true;
|
||||
try {
|
||||
return await axios.post('/admin/ultimate/global-message', { message, type });
|
||||
} catch (error) {
|
||||
console.error('Failed to send global message:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const flushData = async (target) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
return await axios.post('/admin/ultimate/flush', { target });
|
||||
} catch (error) {
|
||||
console.error('Failed to flush data:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const testNotification = async (userHash) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
return await axios.post('/admin/ultimate/test-notification', { user_hash: userHash });
|
||||
} catch (error) {
|
||||
console.error('Failed to test notification:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const batchManage = async (action, ids, data = {}) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
return await axios.post('/admin/ultimate/batch', { action, ids, data });
|
||||
} catch (error) {
|
||||
console.error('Failed to run batch operation:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const runCommand = async (command) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/admin/ultimate/command', { command });
|
||||
if (response.data.success) {
|
||||
commandOutput.value = response.data.output;
|
||||
}
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Failed to run command:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const getLogs = async (type = 'database') => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/admin/ultimate/logs', { type });
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch logs:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const downloadBackup = () => {
|
||||
// Simple window location change to trigger GET download
|
||||
window.location.href = '/admin/ultimate/backup/download';
|
||||
};
|
||||
|
||||
const getBackups = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/admin/ultimate/backups/list');
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch backups:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const downloadBackupByHash = (hash) => {
|
||||
window.location.href = `/admin/ultimate/backup/download/hash?hash=${hash}`;
|
||||
};
|
||||
|
||||
const renameBackup = async (hash, name) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
return await axios.post('/admin/ultimate/backup/rename', { hash, name });
|
||||
} catch (error) {
|
||||
console.error('Failed to rename backup:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const deleteBackup = async (hash) => {
|
||||
loading.value = true;
|
||||
try {
|
||||
return await axios.post('/admin/ultimate/backup/delete', { hash });
|
||||
} catch (error) {
|
||||
console.error('Failed to delete backup:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
loading,
|
||||
stats,
|
||||
queryResults,
|
||||
affectedRows,
|
||||
commandOutput,
|
||||
getStats,
|
||||
runQuery,
|
||||
toggleMaintenance,
|
||||
sendGlobalMessage,
|
||||
flushData,
|
||||
testNotification,
|
||||
batchManage,
|
||||
runCommand,
|
||||
getLogs,
|
||||
downloadBackup,
|
||||
getBackups,
|
||||
downloadBackupByHash,
|
||||
renameBackup,
|
||||
deleteBackup
|
||||
};
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
import { ref, onMounted } from 'vue';
|
||||
import axios from 'axios';
|
||||
|
||||
export function useUserAdditionalDetails() {
|
||||
const details = ref({
|
||||
settings: {},
|
||||
details: {}
|
||||
});
|
||||
const isLoading = ref(false);
|
||||
const joinedCooperatives = ref([]);
|
||||
|
||||
const fetchUserDetails = async () => {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/UserAdditionalDetails/Get');
|
||||
if (response.data.success) {
|
||||
details.value = response.data.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch user additional details:', error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const joinCooperative = async (cooperativeHash) => {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/UserAdditionalDetails/UpdateCooperatives', {
|
||||
cooperative_hash: cooperativeHash,
|
||||
action: 'add'
|
||||
});
|
||||
if (response.data.success) {
|
||||
// If it was successful, update the local settings to reflect it
|
||||
if (!details.value.settings.cooperatives) {
|
||||
details.value.settings.cooperatives = [];
|
||||
}
|
||||
if (!details.value.settings.cooperatives.includes(cooperativeHash)) {
|
||||
details.value.settings.cooperatives.push(cooperativeHash);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to join cooperative:', error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const leaveCooperative = async (cooperativeHash) => {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/UserAdditionalDetails/UpdateCooperatives', {
|
||||
cooperative_hash: cooperativeHash,
|
||||
action: 'remove'
|
||||
});
|
||||
if (response.data.success) {
|
||||
if (details.value.settings.cooperatives) {
|
||||
details.value.settings.cooperatives = details.value.settings.cooperatives.filter(h => h !== cooperativeHash);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to leave cooperative:', error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const fetchJoinedCooperatives = async (userHash = null) => {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/UserAdditionalDetails/GetCooperatives', {
|
||||
user_hash: userHash
|
||||
});
|
||||
if (response.data.success) {
|
||||
joinedCooperatives.value = response.data.data;
|
||||
return joinedCooperatives.value;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch user cooperatives:', error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const searchUsersByCooperative = async (cooperativeHash) => {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.post('/UserAdditionalDetails/SearchByCooperative', {
|
||||
cooperative_hash: cooperativeHash
|
||||
});
|
||||
if (response.data.success) {
|
||||
return response.data.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to search users by cooperative:', error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
const getJoinedCooperativeHashes = () => {
|
||||
return details.value.settings.cooperatives || [];
|
||||
};
|
||||
|
||||
const hasJoinedCooperative = (cooperativeHash) => {
|
||||
return getJoinedCooperativeHashes().includes(cooperativeHash);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchUserDetails();
|
||||
});
|
||||
|
||||
return {
|
||||
details,
|
||||
isLoading,
|
||||
joinedCooperatives,
|
||||
fetchUserDetails,
|
||||
joinCooperative,
|
||||
leaveCooperative,
|
||||
fetchJoinedCooperatives,
|
||||
searchUsersByCooperative,
|
||||
getJoinedCooperativeHashes,
|
||||
hasJoinedCooperative
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user