163 lines
5.9 KiB
JavaScript
163 lines
5.9 KiB
JavaScript
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
|
|
};
|
|
}
|