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>
|
<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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="h-25 shadow-lg shadow-D rounded-b-md">
|
<div class="h-25 shadow-lg shadow-D rounded-b-md">
|
||||||
<div class="bg-D h-5 rounded-b-md shadow-lg">
|
<div class="bg-D h-5 rounded-b-md shadow-lg">
|
||||||
<div class="h-15"></div>
|
<div class="h-15"></div>
|
||||||
<div class="w-full px-50 flex justify-between items-center h-5">
|
<div class="w-full px-50 flex justify-between items-center h-5 relative">
|
||||||
<router-link to="/" v-for="item in items"
|
|
||||||
class="text-center text-lg text-D hover:underline cursor-pointer">
|
<!-- Dropdown khusus "Manajemen Produk" -->
|
||||||
{{ item }}
|
<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>
|
</router-link>
|
||||||
</div>
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</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>
|
</div>
|
||||||
|
</template>
|
||||||
|
@ -112,6 +112,11 @@ const totalWeight = (tray) => {
|
|||||||
if (!tray.items) return 0;
|
if (!tray.items) return 0;
|
||||||
return tray.items.reduce((sum, item) => sum + (item.produk.berat || 0), 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
|
// ambil data dari backend
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
@ -1,34 +1,54 @@
|
|||||||
<template>
|
<template>
|
||||||
<mainLayout>
|
<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>
|
<!-- Header -->
|
||||||
<div class="flex gap-2">
|
<div class="mb-4">
|
||||||
<button
|
<!-- Judul -->
|
||||||
@click="openModal"
|
<p style="font-family: 'IM FELL Great Primer', serif; font-style: italic; font-size: 25px;">
|
||||||
class="px-4 py-2 hover:bg-green-700 rounded-md shadow font-semibold"
|
NAMPAN
|
||||||
style="background-color: #DAC0A3; color: #102C57;">
|
</p>
|
||||||
Tambah Nampan
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
<!-- Searchbar -->
|
||||||
@click="emptyTray"
|
<div class="flex justify-end mt-2">
|
||||||
class="px-3 py-2 bg-red-500 hover:bg-red-600 text-white rounded-md">
|
<div class="w-64">
|
||||||
Kosongkan
|
<searchbar v-model:search="searchQuery" />
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<searchbar v-model:search="searchQuery" />
|
<!-- Tombol -->
|
||||||
<TrayList :search="searchQuery"
|
<div class="flex gap-2 mt-3 justify-end">
|
||||||
@edit="editTray"
|
<!-- Tambah Nampan -->
|
||||||
@delete="deleteTray"/>
|
<button
|
||||||
<div
|
@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"
|
v-if="showModal"
|
||||||
class="fixed inset-0 bg-black bg-opacity-40 flex justify-center items-center z-50"
|
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">
|
<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
|
<input
|
||||||
v-model="trayName"
|
v-model="trayName"
|
||||||
type="text"
|
type="text"
|
||||||
@ -45,16 +65,43 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
@click="saveTray"
|
@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
|
Save
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mainLayout>
|
|
||||||
|
|
||||||
|
<!-- 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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mainLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
@ -62,35 +109,31 @@ import mainLayout from '../layouts/mainLayout.vue'
|
|||||||
import searchbar from '../components/searchbar.vue'
|
import searchbar from '../components/searchbar.vue'
|
||||||
import TrayList from '../components/TrayList.vue'
|
import TrayList from '../components/TrayList.vue'
|
||||||
|
|
||||||
const searchQuery = ref("") // buat search
|
const searchQuery = ref("")
|
||||||
const showModal = ref(false) // <-- ini penting, biar tidak undefined
|
const showModal = ref(false)
|
||||||
const trayName = ref("") // nama nampan baru
|
const showConfirmModal = ref(false)
|
||||||
|
const trayName = ref("")
|
||||||
|
const editingTrayId = ref(null)
|
||||||
|
|
||||||
// buka modal
|
// buka modal tambah/edit
|
||||||
const openModal = () => {
|
const openModal = () => { showModal.value = true }
|
||||||
showModal.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// tutup modal
|
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
trayName.value = ""
|
trayName.value = ""
|
||||||
editingTrayId.value = null
|
editingTrayId.value = null
|
||||||
showModal.value = false
|
showModal.value = false
|
||||||
}
|
}
|
||||||
// simpan nampan baru
|
|
||||||
|
// simpan nampan
|
||||||
const saveTray = async () => {
|
const saveTray = async () => {
|
||||||
if (!trayName.value.trim()) {
|
if (!trayName.value.trim()) {
|
||||||
alert("Nama Nampan tidak boleh kosong")
|
alert("Nama Nampan tidak boleh kosong")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (editingTrayId.value) {
|
if (editingTrayId.value) {
|
||||||
// mode edit
|
|
||||||
await axios.put(`/api/nampan/${editingTrayId.value}`, { nama: trayName.value })
|
await axios.put(`/api/nampan/${editingTrayId.value}`, { nama: trayName.value })
|
||||||
alert("Nampan berhasil diupdate")
|
alert("Nampan berhasil diupdate")
|
||||||
} else {
|
} else {
|
||||||
// mode tambah
|
|
||||||
await axios.post("/api/nampan", { nama: trayName.value })
|
await axios.post("/api/nampan", { nama: trayName.value })
|
||||||
alert("Nampan berhasil ditambahkan")
|
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 confirmEmptyTray = async () => {
|
||||||
const emptyTray = async () => {
|
|
||||||
if (!confirm("Yakin ingin memindahkan semua item ke Brankas?")) return
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await axios.post("/api/brankas", { action: "move_all_from_tray" })
|
await axios.post("/api/brankas", { action: "move_all_from_tray" })
|
||||||
alert("Semua item berhasil dipindahkan ke Brankas")
|
alert("Semua item berhasil dipindahkan ke Brankas")
|
||||||
|
closeConfirmModal()
|
||||||
location.reload()
|
location.reload()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
@ -118,7 +162,6 @@ const emptyTray = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const editTray = (tray) => {
|
const editTray = (tray) => {
|
||||||
// buka modal edit, bisa pake sama seperti modal tambah
|
|
||||||
trayName.value = tray.nama
|
trayName.value = tray.nama
|
||||||
editingTrayId.value = tray.id
|
editingTrayId.value = tray.id
|
||||||
showModal.value = true
|
showModal.value = true
|
||||||
@ -135,7 +178,4 @@ const deleteTray = async (id) => {
|
|||||||
alert("Gagal menghapus nampan")
|
alert("Gagal menghapus nampan")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const editingTrayId = ref(null)
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
Reference in New Issue
Block a user