Kasir/resources/js/pages/Produk.vue
2025-08-27 16:32:02 +07:00

154 lines
4.1 KiB
Vue

<template>
<mainLayout>
<div class="p-6">
<!-- Judul -->
<p class="font-serif italic text-[25px] text-D">PRODUK</p>
<!-- Search -->
<searchbar v-model:search="searchQuery" />
<!-- Tombol Tambah Produk -->
<div class="mt-3 flex justify-end">
<button
class="bg-B text-[#0a1a3c] px-4 py-2 rounded-md shadow hover:bg-C transition"
>
Tambah Produk
</button>
</div>
<!-- Grid Produk -->
<div class="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4 mt-4">
<ProductCard
v-for="item in filteredProducts"
:key="item.id"
:product="item"
@showDetail="openOverlay"
/>
</div>
</div>
<!-- Overlay Detail Produk -->
<div
v-if="showOverlay"
class="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50"
@click.self="closeOverlay"
>
<div
class="bg-white rounded-lg shadow-lg p-6 w-[400px] border-2 border-[#e6d3b3] relative"
>
<!-- Tombol Close -->
<button
@click="closeOverlay"
class="absolute top-2 right-2 text-gray-500 hover:text-black"
>
</button>
<!-- Foto Produk -->
<div class="border border-[#e6d3b3] p-2 mb-4 flex justify-center">
<img
v-if="detail.gambar"
:src="`http://127.0.0.1:8000/storage/${detail.gambar}`"
:alt="detail.nama"
class="w-40 h-40 object-contain"
/>
<span v-else class="text-gray-400 text-sm">[gambar]</span>
</div>
<!-- Stok -->
<p class="text-sm mb-1">{{ detail.item_count }} pcs</p>
<!-- Nama Produk -->
<h2 class="text-xl font-semibold text-center mb-3">
{{ detail.nama }}
</h2>
<!-- Detail Harga & Info -->
<div class="grid grid-cols-2 gap-2 text-sm mb-4">
<p>Harga Beli : Rp. {{ formatNumber(detail.harga_beli) }}</p>
<p class="text-right">{{ detail.kadar }} K</p>
<p>Harga Jual : Rp. {{ formatNumber(detail.harga_jual) }}</p>
<p class="text-right">{{ detail.berat }} gram</p>
<p class="col-span-2">
Harga/gram : Rp. {{ formatNumber(detail.harga_per_gram) }}
</p>
</div>
<!-- Tombol Aksi -->
<div class="flex justify-between">
<button
class="bg-yellow-400 text-black px-4 py-2 rounded font-bold"
>
Ubah
</button>
<button
class="bg-green-400 text-black px-4 py-2 rounded font-bold"
>
Tambah
</button>
<button
class="bg-red-500 text-white px-4 py-2 rounded font-bold"
>
Hapus
</button>
</div>
</div>
</div>
</mainLayout>
</template>
<script setup>
import { ref, onMounted, computed } from "vue";
import axios from "axios";
import mainLayout from "../layouts/mainLayout.vue";
import ProductCard from "../components/ProductCard.vue";
import searchbar from "../components/searchbar.vue";
const products = ref([]);
const searchQuery = ref("");
// overlay state
const showOverlay = ref(false);
const detail = ref({});
// Fetch data awal
onMounted(async () => {
try {
const res = await axios.get("http://127.0.0.1:8000/api/produk");
products.value = res.data;
} catch (error) {
console.error("Gagal ambil data produk:", error);
}
});
// Filter
const filteredProducts = computed(() => {
if (!searchQuery.value) return products.value;
return products.value.filter((p) =>
p.nama.toLowerCase().includes(searchQuery.value.toLowerCase())
);
});
// Fungsi buka overlay
async function openOverlay(id) {
try {
const res = await axios.get(`http://127.0.0.1:8000/api/produk/${id}`);
detail.value = res.data;
showOverlay.value = true;
} catch (error) {
console.error("Gagal fetch detail produk:", error);
}
}
// Fungsi tutup overlay
function closeOverlay() {
showOverlay.value = false;
detail.value = {};
}
// Format angka
function formatNumber(num) {
return new Intl.NumberFormat().format(num || 0);
}
</script>