Files
BarangaySystem/resources/js/Pages/PosHistory.vue
2026-06-06 18:43:00 +08:00

162 lines
5.0 KiB
Vue

<script setup>
import { usePageTitle } from '../composables/Core/usePageTitle';
usePageTitle('POS History');
import { ref, onMounted } from 'vue';
import axios from 'axios';
import { useNavigate } from '../composables/Core/useNavigate';
import LoadingSpinner from '../Components/LoadingSpinner.vue';
import BackButton from '../Components/Core/BackButton.vue';
import PosHistoryList from '../Components/Market/PosHistoryList.vue';
import PosTodayStats from '../Components/Market/PosTodayStats.vue';
import SkeletonTable from '../Components/Core/Skeleton/SkeletonTable.vue';
import { usePosStore } from '../stores/pos';
const props = defineProps({
target: { type: String, required: true },
storeName: { type: String, default: 'Store' }
});
const { navigate } = useNavigate();
const posStore = usePosStore();
const store = ref(null);
const loadingStore = ref(false);
const loadingStats = ref(false);
const fetchStoreDetails = async () => {
// Only fetch if we don't have a specific name or if we want to ensure latest
loadingStore.value = true;
try {
const response = await axios.post('/View/Store/Details/data', {
target: props.target
});
if (response.data) {
store.value = response.data;
}
} catch (e) {
console.error('Failed to fetch store details:', e);
} finally {
loadingStore.value = false;
}
};
const fetchTodayStats = async () => {
loadingStats.value = true;
try {
await posStore.fetchTodayStats(props.target);
} catch (e) {
console.error('Failed to fetch today stats:', e);
} finally {
loadingStats.value = false;
}
};
onMounted(() => {
fetchStoreDetails();
fetchTodayStats();
});
</script>
<template>
<div class="pos-history-page pb-5">
<div class="header-section shadow-sm mb-4">
<div class="tf-container py-3">
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex align-items-center">
<BackButton
:to="{ page: 'ViewStoreMarket', props: { target: props.target } }"
text=""
className="me-3"
/>
<div>
<h4 class="fw_7 mb-0">POS History</h4>
<p class="text-muted small mb-0">
{{ store?.name || props.storeName }}
</p>
</div>
</div>
<div>
<button
@click="navigate({ page: 'PosMain', props: { target: props.target } })"
class="btn btn-primary rounded-pill shadow-sm px-3 py-2 fw_6"
>
<i class="fas fa-cash-register me-2"></i> Open POS
</button>
</div>
</div>
</div>
</div>
<div class="tf-container">
<PosTodayStats :loading="loadingStats" />
<div class="glass-card p-3 p-md-4">
<div class="d-flex align-items-center justify-content-between mb-4 mt-2">
<div class="d-flex align-items-center">
<div class="icon-avatar me-3">
<i class="fas fa-receipt text-primary"></i>
</div>
<div>
<h5 class="fw_6 mb-0">Transaction Records</h5>
<span v-if="posStore.posSessionsCount > 0" class="text-muted small">
{{ posStore.posSessionsCount }} Sessions Found
</span>
<span v-else class="text-muted small">
Past POS sessions
</span>
</div>
</div>
</div>
<div v-if="loadingStore && !store" class="mt-2">
<SkeletonTable :rows="6" :columns="4" />
</div>
<PosHistoryList v-else :storeHash="target" />
</div>
</div>
</div>
</template>
<style scoped>
.pos-history-page {
min-height: 100vh;
background: var(--bg-body);
}
.header-section {
background: var(--bg-card);
}
.glass-card {
background: var(--bg-card);
border-radius: 20px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
}
.icon-avatar {
width: 44px;
height: 44px;
background: rgba(var(--primary-rgb), 0.1);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.1rem;
}
:global(.dark-mode) .header-section,
:global(.dark-mode) .glass-card {
background: #24272c;
border: 1px solid rgba(255, 255, 255, 0.05);
}
:global(.dark-mode) .icon-avatar {
background: rgba(16, 185, 129, 0.1);
}
:global(.dark-mode) .icon-avatar i {
color: #10b981 !important;
}
</style>