241 lines
6.6 KiB
Vue
241 lines
6.6 KiB
Vue
<template>
|
|
<mainLayout>
|
|
<!-- Header -->
|
|
<div class="p-6">
|
|
<!-- Judul -->
|
|
<p class="font-serif italic text-[25px] text-D">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-B bg-C rounded-md shadow font-semibold"
|
|
>
|
|
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/75 flex justify-center items-center z-50 backdrop-blur-sm"
|
|
>
|
|
<div
|
|
class="bg-white rounded-lg shadow-lg p-6 w-96 transform transition-all duration-300 scale-95 opacity-0 animate-fadeIn"
|
|
>
|
|
<h2 class="text-lg font-semibold mb-4 text-[#102c57]">
|
|
{{ editingTrayId ? "Edit Nampan" : "Tambah Nampan" }}
|
|
</h2>
|
|
|
|
<label class="block mb-2 text-sm font-medium text-[#102c57]">
|
|
Nama Nampan
|
|
</label>
|
|
<input
|
|
v-model="trayName"
|
|
type="text"
|
|
placeholder="Contoh: A4"
|
|
class="w-full border rounded-md p-2 mb-4"
|
|
/>
|
|
|
|
<div class="flex justify-end gap-2">
|
|
<button
|
|
@click="closeModal"
|
|
class="px-4 py-2 bg-gray-400 hover:bg-gray-500 text-white rounded-md"
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
@click="saveTray"
|
|
class="px-4 py-2 bg-[#DAC0A3] hover:bg-[#C9A77E] rounded-md text-[#102c57]"
|
|
>
|
|
Save
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Konfirmasi Kosongkan -->
|
|
<div
|
|
v-if="showConfirmModal"
|
|
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm"
|
|
>
|
|
<div
|
|
class="bg-white rounded-2xl shadow-xl w-full max-w-md p-6 transform transition-all duration-300 scale-95 opacity-0 animate-fadeIn"
|
|
>
|
|
<!-- Judul -->
|
|
<h2 class="text-xl font-bold text-[#102c57] mb-3 text-center">
|
|
Kosongkan semua nampan?
|
|
</h2>
|
|
|
|
<!-- Deskripsi -->
|
|
<p class="text-gray-600 text-sm mb-6 text-center leading-relaxed">
|
|
Semua item akan dimasukkan ke <span class="font-semibold">Brankas</span>.<br />
|
|
Masuk ke menu <b>Brankas</b> untuk mengembalikan item ke nampan.
|
|
</p>
|
|
|
|
<!-- Tombol -->
|
|
<div class="flex justify-center gap-3">
|
|
<button
|
|
@click="closeConfirmModal"
|
|
class="px-5 py-2 rounded-lg font-semibold border border-gray-300 text-gray-700 hover:bg-gray-100 transition"
|
|
>
|
|
Batal
|
|
</button>
|
|
<button
|
|
@click="confirmEmptyTray"
|
|
class="px-5 py-2 rounded-lg font-semibold bg-red-500 text-white hover:bg-red-600 transition"
|
|
>
|
|
Ya, Kosongkan
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</mainLayout>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from "vue";
|
|
import axios from "axios";
|
|
import mainLayout from "../layouts/mainLayout.vue";
|
|
import searchbar from "../components/Searchbar.vue";
|
|
import TrayList from "../components/TrayList.vue";
|
|
|
|
const searchQuery = ref("");
|
|
const showModal = ref(false);
|
|
const showConfirmModal = ref(false);
|
|
const trayName = ref("");
|
|
const editingTrayId = ref(null);
|
|
|
|
|
|
// buka modal tambah/edit
|
|
const openModal = () => {
|
|
showModal.value = true;
|
|
};
|
|
const closeModal = () => {
|
|
trayName.value = "";
|
|
editingTrayId.value = null;
|
|
showModal.value = false;
|
|
};
|
|
|
|
// simpan nampan
|
|
const saveTray = async () => {
|
|
if (!trayName.value.trim()) {
|
|
alert("Nama Nampan tidak boleh kosong");
|
|
return;
|
|
}
|
|
try {
|
|
if (editingTrayId.value) {
|
|
await axios.put(
|
|
`/api/nampan/${editingTrayId.value}`,
|
|
{ nama: trayName.value },
|
|
{
|
|
headers: {
|
|
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
|
},
|
|
}
|
|
);
|
|
alert("Nampan berhasil diupdate");
|
|
} else {
|
|
await axios.post(
|
|
"/api/nampan",
|
|
{ nama: trayName.value },
|
|
{
|
|
headers: {
|
|
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
|
},
|
|
}
|
|
);
|
|
alert("Nampan berhasil ditambahkan");
|
|
}
|
|
closeModal();
|
|
location.reload();
|
|
} catch (error) {
|
|
console.error(error);
|
|
alert("Gagal menyimpan nampan");
|
|
}
|
|
};
|
|
|
|
// === Konfirmasi kosongkan nampan ===
|
|
const openConfirmModal = () => {
|
|
showConfirmModal.value = true;
|
|
};
|
|
const closeConfirmModal = () => {
|
|
showConfirmModal.value = false;
|
|
};
|
|
|
|
const confirmEmptyTray = async () => {
|
|
try {
|
|
await axios.delete("/api/kosongkan-nampan", {
|
|
headers: {
|
|
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
|
},
|
|
});
|
|
alert("Semua item berhasil dipindahkan ke Brankas");
|
|
closeConfirmModal();
|
|
location.reload();
|
|
} catch (error) {
|
|
console.error(error);
|
|
alert("Gagal mengosongkan nampan");
|
|
}
|
|
};
|
|
|
|
const editTray = (tray) => {
|
|
trayName.value = tray.nama;
|
|
editingTrayId.value = tray.id;
|
|
showModal.value = true;
|
|
};
|
|
|
|
const deleteTray = async (id) => {
|
|
if (!confirm("Yakin ingin menghapus nampan ini?")) return;
|
|
try {
|
|
await axios.delete(`/api/nampan/${id}`, {
|
|
headers: {
|
|
Authorization: `Bearer ${localStorage.getItem("token")}`,
|
|
},
|
|
});
|
|
alert("Nampan berhasil dihapus");
|
|
location.reload();
|
|
} catch (error) {
|
|
console.error(error);
|
|
alert("Gagal menghapus nampan");
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: scale(0.95);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: scale(1);
|
|
}
|
|
}
|
|
|
|
.animate-fadeIn {
|
|
animation: fadeIn 0.25s ease-out forwards;
|
|
}
|
|
</style>
|