initial: bootstrap from BukidBountyApp base
This commit is contained in:
162
resources/js/composables/Market/usePosSession.js
Normal file
162
resources/js/composables/Market/usePosSession.js
Normal file
@@ -0,0 +1,162 @@
|
||||
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
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user