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

142 lines
5.1 KiB
Vue

<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';
import { usePageTitle } from '../composables/Core/usePageTitle';
import { useNavigate } from '../composables/Core/useNavigate';
import { useModal } from '../composables/Core/useModal';
import LoadingSpinner from '../Components/LoadingSpinner.vue';
import CardSimple from '../Components/Core/CardSimple.vue';
import InputGroupButton from '../Components/Core/Forms/InputGroupButton.vue';
const props = defineProps({
target: { type: String, required: true }
});
usePageTitle('Shipment Details');
const { navigate } = useNavigate();
const modal = useModal();
const shipment = ref(null);
const loading = ref(true);
const fetchShipmentDetail = async () => {
loading.value = true;
try {
const response = await axios.post('/Shipments/List', { target: props.target });
// Simplified: filter from list for now
if (response.data.success) {
shipment.value = response.data.data.find(s => s.hashkey === props.target);
}
} catch (error) {
console.error('Failed to fetch shipment detail:', error);
} finally {
loading.value = false;
}
};
const updateStatus = async (newStatus) => {
try {
const response = await axios.post('/Shipments/Status/Update', {
target: props.target,
status: newStatus
});
if (response.data.success) {
shipment.value.status = newStatus;
}
} catch (error) {
modal.open({
title: 'Error',
body: 'Failed to update status'
});
}
};
onMounted(fetchShipmentDetail);
</script>
<template>
<div class="shipment-detail-page pb-5">
<div class="tf-container mt-4">
<InputGroupButton
text="Back to Shipments"
variant="text"
@click="navigate({ page: 'ShipmentList' })"
class="mb-4"
>
<i class="fas fa-chevron-left me-1"></i> Back to Shipments
</InputGroupButton>
<div v-if="loading" class="text-center py-5">
<LoadingSpinner />
</div>
<div v-else-if="!shipment" class="alert alert-danger">
Shipment not found.
</div>
<div v-else>
<CardSimple title="Track Shipment" class="mb-4">
<template #headerAction>
<span class="badge bg-primary px-3 py-2 rounded-pill">{{ shipment.status }}</span>
</template>
<div class="mb-4">
<div class="small text-muted">Tracking Number</div>
<div class="fw_5 h5">{{ shipment.tracking_number || 'Pending Assignment' }}</div>
</div>
<div class="row g-4 border-top pt-4">
<div class="col-6">
<div class="small text-muted mb-1">Customer</div>
<div class="fw_5">{{ shipment.customer?.name }}</div>
<div class="small">{{ shipment.destination_address }}</div>
</div>
<div class="col-6 text-end">
<div class="small text-muted mb-1">Store</div>
<div class="fw_5">{{ shipment.store?.name }}</div>
<div class="small">Shipping Fee: {{ shipment.shipping_fee }}</div>
</div>
</div>
</CardSimple>
<CardSimple title="Update Progress">
<div class="d-flex flex-wrap gap-3">
<InputGroupButton
v-if="shipment.status === 'PENDING'"
text="Mark as Picked Up"
variant="outline"
size="sm"
@click="updateStatus('PICKED_UP')"
/>
<InputGroupButton
v-if="shipment.status === 'PICKED_UP'"
text="Mark as In Transit"
variant="outline"
size="sm"
@click="updateStatus('IN_TRANSIT')"
/>
<InputGroupButton
v-if="shipment.status === 'IN_TRANSIT'"
text="Mark as Delivered"
variant="primary"
size="sm"
@click="updateStatus('DELIVERED')"
/>
<InputGroupButton
v-if="['PENDING', 'PICKED_UP', 'IN_TRANSIT'].includes(shipment.status)"
text="Mark as Failed"
variant="danger"
size="sm"
@click="updateStatus('FAILED')"
/>
</div>
</CardSimple>
</div>
</div>
</div>
</template>
<style scoped>
.fw_5 { font-weight: 500; }
</style>