Merge branch 'production' of https://git.abbauf.com/Magang-2025/Kasir into production
This commit is contained in:
commit
0bb5b23ead
48
resources/js/components/DropdownNav.vue
Normal file
48
resources/js/components/DropdownNav.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="relative inline-block text-left">
|
||||
<!-- Tombol Dropdown -->
|
||||
<button
|
||||
@click="isOpen = !isOpen"
|
||||
class="px-4 py-2 bg-white border rounded-md shadow-sm hover:bg-gray-100"
|
||||
>
|
||||
Manajemen Produk
|
||||
</button>
|
||||
|
||||
<!-- Isi Dropdown -->
|
||||
<div
|
||||
v-if="isOpen"
|
||||
class="absolute left-0 mt-2 w-48 bg-white border rounded-md shadow-lg z-50"
|
||||
>
|
||||
<ul>
|
||||
<li
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
@click="goTo(item.route)"
|
||||
class="px-4 py-2 hover:bg-[#DAC0A3] cursor-pointer"
|
||||
>
|
||||
{{ item.label }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const isOpen = ref(false);
|
||||
const router = useRouter();
|
||||
|
||||
const items = [
|
||||
{ label: "Brankas", route: "/brankas" },
|
||||
{ label: "Nampan", route: "/nampan" },
|
||||
{ label: "Produk", route: "/produk" },
|
||||
{ label: "Sales", route: "/sales" },
|
||||
];
|
||||
|
||||
const goTo = (route) => {
|
||||
isOpen.value = false;
|
||||
router.push(route);
|
||||
};
|
||||
</script>
|
@ -1,17 +1,70 @@
|
||||
<script setup>
|
||||
const items = ['Manajemen Produk', 'Kasir', 'Laporan', 'Akun'];
|
||||
import { ref } from "vue";
|
||||
|
||||
const isOpen = ref(false);
|
||||
|
||||
const items = [
|
||||
{ label: "Kasir", route: "/kasir" },
|
||||
{ label: "Laporan", route: "/laporan" },
|
||||
{ label: "Akun", route: "/akun" },
|
||||
];
|
||||
|
||||
const subItems = [
|
||||
{ label: "Brankas", route: "/brankas" },
|
||||
{ label: "Nampan", route: "/nampan" },
|
||||
{ label: "Produk", route: "/produk" },
|
||||
{ label: "Sales", route: "/sales" },
|
||||
];
|
||||
|
||||
const toggleDropdown = () => {
|
||||
isOpen.value = !isOpen.value;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-25 shadow-lg shadow-D rounded-b-md">
|
||||
<div class="bg-D h-5 rounded-b-md shadow-lg">
|
||||
<div class="h-15"></div>
|
||||
<div class="w-full px-50 flex justify-between items-center h-5">
|
||||
<router-link to="/" v-for="item in items"
|
||||
class="text-center text-lg text-D hover:underline cursor-pointer">
|
||||
{{ item }}
|
||||
<div class="h-25 shadow-lg shadow-D rounded-b-md">
|
||||
<div class="bg-D h-5 rounded-b-md shadow-lg">
|
||||
<div class="h-15"></div>
|
||||
<div class="w-full px-50 flex justify-between items-center h-5 relative">
|
||||
|
||||
<!-- Dropdown khusus "Manajemen Produk" -->
|
||||
<div class="relative">
|
||||
<button
|
||||
@click="toggleDropdown"
|
||||
class="text-center text-lg text-D hover:underline cursor-pointer"
|
||||
>
|
||||
Manajemen Produk
|
||||
</button>
|
||||
|
||||
<!-- isi dropdown -->
|
||||
<div
|
||||
v-if="isOpen"
|
||||
class="absolute left-0 mt-2 w-48 bg-white border rounded-md shadow-lg z-50"
|
||||
>
|
||||
<ul>
|
||||
<li
|
||||
v-for="(sub, index) in subItems"
|
||||
:key="index"
|
||||
class="px-4 py-2 hover:bg-[#DAC0A3] cursor-pointer"
|
||||
>
|
||||
<router-link :to="sub.route" class="block w-full h-full">
|
||||
{{ sub.label }}
|
||||
</router-link>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- menu lain -->
|
||||
<router-link
|
||||
v-for="item in items"
|
||||
:key="item.label"
|
||||
:to="item.route"
|
||||
class="text-center text-lg text-D hover:underline cursor-pointer"
|
||||
>
|
||||
{{ item.label }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
@ -112,6 +112,11 @@ const totalWeight = (tray) => {
|
||||
if (!tray.items) return 0;
|
||||
return tray.items.reduce((sum, item) => sum + (item.produk.berat || 0), 0);
|
||||
};
|
||||
// const totalWeight = (tray) => {
|
||||
// if (!tray.items) return 0;
|
||||
// const total = tray.items.reduce((sum, item) => sum + (item.produk.berat || 0), 0);
|
||||
// return total.toFixed(2); // hasil string "12.34"
|
||||
// };
|
||||
|
||||
// ambil data dari backend
|
||||
onMounted(async () => {
|
||||
|
@ -1,34 +1,54 @@
|
||||
<template>
|
||||
<mainLayout>
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<p style="font-family: 'IM FELL Great Primer', serif; font-style: italic;font-size: 25px;">NAMPAN</p>
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
@click="openModal"
|
||||
class="px-4 py-2 hover:bg-green-700 rounded-md shadow font-semibold"
|
||||
style="background-color: #DAC0A3; color: #102C57;">
|
||||
Tambah Nampan
|
||||
</button>
|
||||
<mainLayout>
|
||||
|
||||
<button
|
||||
@click="emptyTray"
|
||||
class="px-3 py-2 bg-red-500 hover:bg-red-600 text-white rounded-md">
|
||||
Kosongkan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<searchbar v-model:search="searchQuery" />
|
||||
<TrayList :search="searchQuery"
|
||||
@edit="editTray"
|
||||
@delete="deleteTray"/>
|
||||
<div
|
||||
<!-- Header -->
|
||||
<div class="mb-4">
|
||||
<!-- Judul -->
|
||||
<p style="font-family: 'IM FELL Great Primer', serif; font-style: italic; font-size: 25px;">
|
||||
NAMPAN
|
||||
</p>
|
||||
|
||||
<!-- Searchbar -->
|
||||
<div class="flex justify-end mt-2">
|
||||
<div class="w-64">
|
||||
<searchbar v-model:search="searchQuery" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tombol -->
|
||||
<div class="flex gap-2 mt-3 justify-end">
|
||||
<!-- Tambah Nampan -->
|
||||
<button
|
||||
@click="openModal"
|
||||
class="px-4 py-2 hover:bg-green-700 rounded-md shadow font-semibold"
|
||||
style="background-color: #DAC0A3; color: #102C57;">
|
||||
Tambah Nampan
|
||||
</button>
|
||||
|
||||
<!-- Kosongkan -->
|
||||
<button
|
||||
@click="openConfirmModal"
|
||||
class="px-3 py-2 bg-red-500 hover:bg-red-600 text-white rounded-md">
|
||||
Kosongkan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- Search + List -->
|
||||
|
||||
<TrayList :search="searchQuery" @edit="editTray" @delete="deleteTray"/>
|
||||
|
||||
<!-- Modal Tambah/Edit Nampan -->
|
||||
<div
|
||||
v-if="showModal"
|
||||
class="fixed inset-0 bg-black bg-opacity-40 flex justify-center items-center z-50"
|
||||
>
|
||||
<div class="bg-white rounded-lg shadow-lg p-6 w-96">
|
||||
<h2 class="text-lg font-semibold mb-4">Tambah Nampan</h2>
|
||||
<h2 class="text-lg font-semibold mb-4" style="color: #102C57;">Tambah Nampan</h2>
|
||||
|
||||
<label class="block mb-2 text-sm font-medium">Nama Nampan</label>
|
||||
<label class="block mb-2 text-sm font-medium" style="color: #102C57;">Nama Nampan</label>
|
||||
<input
|
||||
v-model="trayName"
|
||||
type="text"
|
||||
@ -45,16 +65,43 @@
|
||||
|
||||
<button
|
||||
@click="saveTray"
|
||||
class="px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded-md">
|
||||
class="px-4 py-2 bg-[#DAC0A3] hover:bg-[#C9A77E] rounded-md"
|
||||
style="color: #102C57;">
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Konfirmasi Kosongkan -->
|
||||
<div
|
||||
v-if="showConfirmModal"
|
||||
class="fixed inset-0 bg-black bg-opacity-40 flex justify-center items-center z-50"
|
||||
>
|
||||
<div class="bg-white rounded-lg shadow-lg p-6 w-96 text-center">
|
||||
<h2 class="text-xl font-bold mb-3" style="color: #102C57;">Kosongkan semua nampan?</h2>
|
||||
<p class="text-gray-600 mb-6">
|
||||
Semua item akan dimasukkan ke brankas. <br/>
|
||||
Masuk ke menu ‘Brankas’ untuk mengembalikan item ke nampan.
|
||||
</p>
|
||||
<div class="flex justify-center gap-4">
|
||||
<button
|
||||
@click="closeConfirmModal"
|
||||
class="px-5 py-2 bg-gray-300 hover:bg-gray-400 rounded-md font-semibold">
|
||||
Batal
|
||||
</button>
|
||||
<button
|
||||
@click="confirmEmptyTray"
|
||||
class="px-5 py-2 bg-red-500 hover:bg-red-600 text-white rounded-md font-semibold">
|
||||
Ya
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</mainLayout>
|
||||
|
||||
</div>
|
||||
|
||||
</mainLayout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import axios from 'axios'
|
||||
@ -62,35 +109,31 @@ import mainLayout from '../layouts/mainLayout.vue'
|
||||
import searchbar from '../components/searchbar.vue'
|
||||
import TrayList from '../components/TrayList.vue'
|
||||
|
||||
const searchQuery = ref("") // buat search
|
||||
const showModal = ref(false) // <-- ini penting, biar tidak undefined
|
||||
const trayName = ref("") // nama nampan baru
|
||||
const searchQuery = ref("")
|
||||
const showModal = ref(false)
|
||||
const showConfirmModal = ref(false)
|
||||
const trayName = ref("")
|
||||
const editingTrayId = ref(null)
|
||||
|
||||
// buka modal
|
||||
const openModal = () => {
|
||||
showModal.value = true
|
||||
}
|
||||
|
||||
// tutup modal
|
||||
// buka modal tambah/edit
|
||||
const openModal = () => { showModal.value = true }
|
||||
const closeModal = () => {
|
||||
trayName.value = ""
|
||||
editingTrayId.value = null
|
||||
showModal.value = false
|
||||
}
|
||||
// simpan nampan baru
|
||||
|
||||
// simpan nampan
|
||||
const saveTray = async () => {
|
||||
if (!trayName.value.trim()) {
|
||||
alert("Nama Nampan tidak boleh kosong")
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
if (editingTrayId.value) {
|
||||
// mode edit
|
||||
await axios.put(`/api/nampan/${editingTrayId.value}`, { nama: trayName.value })
|
||||
alert("Nampan berhasil diupdate")
|
||||
} else {
|
||||
// mode tambah
|
||||
await axios.post("/api/nampan", { nama: trayName.value })
|
||||
alert("Nampan berhasil ditambahkan")
|
||||
}
|
||||
@ -102,14 +145,15 @@ const saveTray = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// === Konfirmasi kosongkan nampan ===
|
||||
const openConfirmModal = () => { showConfirmModal.value = true }
|
||||
const closeConfirmModal = () => { showConfirmModal.value = false }
|
||||
|
||||
// kosongkan semua nampan
|
||||
const emptyTray = async () => {
|
||||
if (!confirm("Yakin ingin memindahkan semua item ke Brankas?")) return
|
||||
|
||||
const confirmEmptyTray = async () => {
|
||||
try {
|
||||
await axios.post("/api/brankas", { action: "move_all_from_tray" })
|
||||
alert("Semua item berhasil dipindahkan ke Brankas")
|
||||
closeConfirmModal()
|
||||
location.reload()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
@ -118,7 +162,6 @@ const emptyTray = async () => {
|
||||
}
|
||||
|
||||
const editTray = (tray) => {
|
||||
// buka modal edit, bisa pake sama seperti modal tambah
|
||||
trayName.value = tray.nama
|
||||
editingTrayId.value = tray.id
|
||||
showModal.value = true
|
||||
@ -135,7 +178,4 @@ const deleteTray = async (id) => {
|
||||
alert("Gagal menghapus nampan")
|
||||
}
|
||||
}
|
||||
|
||||
const editingTrayId = ref(null)
|
||||
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user