118 lines
3.2 KiB
Vue
118 lines
3.2 KiB
Vue
<template>
|
|
<div>
|
|
<!-- Loading -->
|
|
<div v-if="loading" class="text-center py-6">Loading...</div>
|
|
|
|
<!-- Error -->
|
|
<div v-else-if="error" class="text-center text-red-500 py-6">{{ error }}</div>
|
|
|
|
<!-- Kalau hasil search kosong -->
|
|
<div
|
|
v-else-if="filteredTrays.length === 0"
|
|
class="text-center text-gray-500 py-6"
|
|
>
|
|
Nampan tidak ditemukan.
|
|
</div>
|
|
|
|
<!-- Grid nampan -->
|
|
<div
|
|
v-else
|
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4"
|
|
>
|
|
<div
|
|
v-for="tray in filteredTrays"
|
|
:key="tray.id"
|
|
class="border rounded-lg p-4 shadow-sm hover:shadow-md transition"
|
|
>
|
|
<!-- Header Nampan -->
|
|
<div class="flex justify-between items-center mb-3">
|
|
<h2 class="font-bold text-lg">{{ tray.nama }}</h2>
|
|
<div class="flex gap-2">
|
|
<button class="bg-yellow-300 p-1 rounded">✏️</button>
|
|
<button class="bg-red-500 text-white p-1 rounded">🗑️</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Isi Nampan -->
|
|
<div v-if="tray.items && tray.items.length > 0" class="space-y-2">
|
|
<div
|
|
v-for="item in tray.items"
|
|
:key="item.id"
|
|
class="flex justify-between items-center border rounded-lg p-2"
|
|
>
|
|
<!-- Gambar + Info -->
|
|
<div class="flex items-center gap-3">
|
|
<img
|
|
:src="item.image"
|
|
alt="Product Image"
|
|
class="w-12 h-12 object-contain"
|
|
/>
|
|
<div>
|
|
<p class="font-semibold">{{ item.produk.nama }}</p>
|
|
<p class="text-sm text-gray-500">{{ item.produk.id }}</p>
|
|
</div>
|
|
</div>
|
|
<!-- Berat -->
|
|
<span class="font-medium">{{ item.berat }}g</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Kalau nampan kosong -->
|
|
<div v-else class="text-gray-400 text-center py-4">
|
|
Nampan kosong.<br />
|
|
Masuk ke menu <b>Brankas</b> untuk memindahkan item ke nampan.
|
|
</div>
|
|
|
|
<!-- Total Berat -->
|
|
<div class="border-t mt-3 pt-2 text-right font-semibold">
|
|
Berat Total: {{ totalWeight(tray) }}g
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
import { ref, onMounted, computed } from "vue";
|
|
import axios from "axios";
|
|
|
|
// terima search dari parent
|
|
const props = defineProps({
|
|
search: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
});
|
|
|
|
const trays = ref([]);
|
|
const loading = ref(true);
|
|
const error = ref(null);
|
|
|
|
// hitung total berat
|
|
const totalWeight = (tray) => {
|
|
if (!tray.items) return 0;
|
|
return tray.items.reduce((sum, item) => sum + (item.berat || 0), 0);
|
|
};
|
|
|
|
// ambil data dari backend
|
|
onMounted(async () => {
|
|
try {
|
|
const res = await axios.get("/api/nampan");
|
|
trays.value = res.data; // harus array tray dengan items
|
|
console.log("Data nampan:", res.data);
|
|
} catch (err) {
|
|
error.value = err.message || "Gagal mengambil data";
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
});
|
|
|
|
// filter berdasarkan nama nampan
|
|
const filteredTrays = computed(() => {
|
|
if (!props.search) return trays.value;
|
|
return trays.value.filter((tray) =>
|
|
tray.nama.toLowerCase().includes(props.search.toLowerCase())
|
|
);
|
|
});
|
|
</script> |