Compare commits

..

3 Commits

Author SHA1 Message Date
Baghaztra
ae4b8a3449 [update] Tutor buat monti 2025-09-08 09:55:05 +07:00
Baghaztra
600c87d9ca Merge branch 'production' of https://git.abbauf.com/Magang-2025/Kasir into production 2025-09-08 09:49:06 +07:00
Baghaztra
b1babd6c26 [update] laporan 2025-09-08 09:46:04 +07:00
7 changed files with 100 additions and 56 deletions

View File

@ -20,9 +20,9 @@ class DatabaseSeeder extends Seeder
public function run(): void public function run(): void
{ {
User::factory()->create([ User::factory()->create([
'nama' => 'Test User', 'nama' => 'Test',
'role' => 'owner', 'role' => 'owner',
'password' => bcrypt('123123123'), 'password' => bcrypt('123123'),
]); ]);
User::factory(2)->create(); User::factory(2)->create();

View File

@ -1,12 +1,12 @@
<template> <template>
<div class="my-6"> <div class="my-6">
<hr class="border-B mb-5" /> <hr class="border-B mb-5" />
<div class="flez flex-row mb-3"> <div class="flex flex-row mb-3 overflow-x-auto">
<input type="date" v-model="tanggalDipilih" <input type="date" v-model="tanggalDipilih"
class="mt-1 block rounded-md shadow-sm sm:text-sm bg-A text-D border-B focus:border-C focus:ring focus:outline-none focus:ring-D focus:ring-opacity-50 p-2" /> class="mt-1 block rounded-md shadow-sm sm:text-sm bg-A text-D border-B focus:border-C focus:ring focus:outline-none focus:ring-D focus:ring-opacity-50 p-2" />
<InputSelect class="ml-3" :options="opsiSales" v-model="salesDipilih" />
</div> </div>
<div class="mt-5 overflow-x-auto">
<table class="w-full border-collapse border border-C rounded-md"> <table class="w-full border-collapse border border-C rounded-md">
<thead> <thead>
<tr class="bg-C text-D rounded-t-md"> <tr class="bg-C text-D rounded-t-md">
@ -39,10 +39,12 @@
</tbody> </tbody>
</table> </table>
</div> </div>
</div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted, watch, computed } from 'vue'; import { ref, onMounted, watch, computed } from 'vue';
import InputSelect from './InputSelect.vue';
import axios from 'axios'; import axios from 'axios';
const tanggalDipilih = ref(''); const tanggalDipilih = ref('');
@ -51,6 +53,24 @@ const loading = ref(false);
const produk = computed(() => data.value?.produk || []); const produk = computed(() => data.value?.produk || []);
const salesDipilih = ref(null);
const opsiSales = ref([
{ label: 'Semua Sales', value: null, selected: true },
]);
const fetchSales = async () => {
try {
const response = await axios.get('/api/sales');
const salesData = response.data;
opsiSales.value = [{ label: 'Semua Sales', value: null }, ...salesData.map(sales => ({
label: sales.nama,
value: sales.id,
}))];
} catch (error) {
console.error('Gagal mengambil data sales:', error);
}
};
const fetchData = async (date) => { const fetchData = async (date) => {
if (!date) return; if (!date) return;
@ -58,8 +78,7 @@ const fetchData = async (date) => {
try { try {
const response = await axios.get(`/api/detail-laporan?tanggal=${date}`); const response = await axios.get(`/api/detail-laporan?tanggal=${date}`);
data.value = response.data; data.value = response.data;;
// console.log("Data berhasil diambil:", data.value);
} catch (error) { } catch (error) {
console.error('Gagal mengambil data laporan:', error); console.error('Gagal mengambil data laporan:', error);
data.value = null; data.value = null;
@ -71,6 +90,8 @@ const fetchData = async (date) => {
onMounted(() => { onMounted(() => {
const today = new Date().toISOString().split('T')[0]; const today = new Date().toISOString().split('T')[0];
tanggalDipilih.value = today; tanggalDipilih.value = today;
fetchSales();
}); });
watch(tanggalDipilih, (newDate) => { watch(tanggalDipilih, (newDate) => {

View File

@ -33,7 +33,7 @@
</div> </div>
</div> </div>
<div class="mt-5"> <div class="mt-5 overflow-x-auto">
<table class="w-full border-collapse border border-C rounded-md"> <table class="w-full border-collapse border border-C rounded-md">
<thead> <thead>
<tr class="bg-C text-D rounded-t-md"> <tr class="bg-C text-D rounded-t-md">

View File

@ -33,7 +33,7 @@
</div> </div>
</div> </div>
<div class="mt-5"> <div class="mt-5 overflow-x-auto">
<table class="w-full border-collapse border border-C rounded-md"> <table class="w-full border-collapse border border-C rounded-md">
<thead> <thead>
<tr class="bg-C text-D rounded-t-md"> <tr class="bg-C text-D rounded-t-md">

View File

@ -144,7 +144,7 @@ const saveMove = async () => {
}, },
body:{ body:{
id_nampan: selectedTrayId.value, id_nampan: selectedTrayId.value,
id_produk: selectedItem.value.id_produk, // ikutkan id_produk karena API minta id_produk: selectedItem.value.id_produk,
}, },
}); });

View File

@ -151,7 +151,11 @@ const akunToDelete = ref(null);
const fetchAkun = async () => { const fetchAkun = async () => {
loading.value = true; loading.value = true;
try { try {
const response = await axios.get("/api/user"); const response = await axios.get("/api/user", {
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
});
akun.value = response.data; akun.value = response.data;
} catch (error) { } catch (error) {
console.error("Error fetching akun:", error); console.error("Error fetching akun:", error);
@ -180,7 +184,11 @@ const hapusAkun = (item) => {
const confirmDelete = async () => { const confirmDelete = async () => {
try { try {
await axios.delete(`/api/user/${akunToDelete.value.id}`); await axios.delete(`/api/user/${akunToDelete.value.id}`, {
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
});
fetchAkun(); fetchAkun();
confirmDeleteOpen.value = false; confirmDeleteOpen.value = false;
} catch (error) { } catch (error) {

View File

@ -1,11 +1,7 @@
<template> <template>
<mainLayout> <mainLayout>
<!-- Modal Buat Item --> <!-- Modal Buat Item -->
<CreateItemModal <CreateItemModal :isOpen="openItemModal" :product="editedProduct" @close="closeItemModal" />
:isOpen="openItemModal"
:product="editedProduct"
@close="closeItemModal"
/>
<div class="p-6"> <div class="p-6">
<p class="font-serif italic text-[25px] text-D">Edit Produk</p> <p class="font-serif italic text-[25px] text-D">Edit Produk</p>
@ -26,7 +22,8 @@
<div class="mb-3 flex flex-row w-full gap-3"> <div class="mb-3 flex flex-row w-full gap-3">
<div class="flex-1"> <div class="flex-1">
<label class="block text-D mb-1">Berat (g)</label> <label class="block text-D mb-1">Berat (g)</label>
<InputField v-model="form.berat" type="number" step="0.01" placeholder="Masukkan berat" @input="calculateHargaJual" /> <InputField v-model="form.berat" type="number" step="0.01" placeholder="Masukkan berat"
@input="calculateHargaJual" />
</div> </div>
<div class="flex-1"> <div class="flex-1">
<label class="block text-D mb-1">Kadar (K)</label> <label class="block text-D mb-1">Kadar (K)</label>
@ -37,7 +34,8 @@
<div class="mb-3 flex flex-row w-full gap-3"> <div class="mb-3 flex flex-row w-full gap-3">
<div class="flex-1"> <div class="flex-1">
<label class="block text-D mb-1">Harga per Gram</label> <label class="block text-D mb-1">Harga per Gram</label>
<InputField v-model="form.harga_per_gram" type="number" step="0.01" placeholder="Masukkan harga per gram" @input="calculateHargaJual" /> <InputField v-model="form.harga_per_gram" type="number" step="0.01" placeholder="Masukkan harga per gram"
@input="calculateHargaJual" />
</div> </div>
<div class="flex-1"> <div class="flex-1">
<label class="block text-D mb-1">Harga Jual</label> <label class="block text-D mb-1">Harga Jual</label>
@ -83,12 +81,14 @@
</path> </path>
</svg> </svg>
</div> </div>
<p class="text-xs text-gray-600 font-medium" v-html="uploadLoading ? 'Uploading...' : 'Unggah<br/>Foto'"></p> <p class="text-xs text-gray-600 font-medium"
v-html="uploadLoading ? 'Uploading...' : 'Unggah<br/>Foto'"></p>
</div> </div>
</div> </div>
</div> </div>
<input ref="fileInput" type="file" multiple accept="image/jpeg,image/jpg,image/png" @change="handleFileSelect" class="hidden" /> <input ref="fileInput" type="file" multiple accept="image/jpeg,image/jpg,image/png" @change="handleFileSelect"
class="hidden" />
<p class="text-xs text-gray-500 mt-2">Format: JPG, JPEG, PNG (Max: 2MB per file, Max: 6 foto)</p> <p class="text-xs text-gray-500 mt-2">Format: JPG, JPEG, PNG (Max: 2MB per file, Max: 6 foto)</p>
@ -164,12 +164,20 @@ const calculateHargaJual = () => {
}; };
const loadKategori = async () => { const loadKategori = async () => {
const response = await axios.get("/api/kategori"); const response = await axios.get("/api/kategori", {
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
});
category.value = response.data.map((c) => ({ value: c.id, label: c.nama })); category.value = response.data.map((c) => ({ value: c.id, label: c.nama }));
}; };
const loadProduk = async () => { const loadProduk = async () => {
const response = await axios.get(`/api/produk/${productId}`); const response = await axios.get(`/api/produk/${productId}`, {
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
});
const produk = response.data; const produk = response.data;
form.value = { form.value = {
nama: produk.nama, nama: produk.nama,
@ -216,7 +224,10 @@ const uploadFiles = async (files) => {
formData.append("foto", file); formData.append("foto", file);
formData.append("id_user", userId.value); formData.append("id_user", userId.value);
const res = await axios.post("/api/foto/upload", formData, { const res = await axios.post("/api/foto/upload", formData, {
headers: { "Content-Type": "multipart/form-data" }, headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "multipart/form-data"
},
}); });
uploadedImages.value.push(res.data); uploadedImages.value.push(res.data);
} }
@ -227,7 +238,11 @@ const uploadFiles = async (files) => {
const removeImage = async (id) => { const removeImage = async (id) => {
try { try {
await axios.delete(`/api/foto/hapus/${id}`); await axios.delete(`/api/foto/hapus/${id}`, {
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
});
uploadedImages.value = uploadedImages.value.filter((i) => i.id !== id); uploadedImages.value = uploadedImages.value.filter((i) => i.id !== id);
} catch { } catch {
uploadError.value = "Gagal menghapus foto"; uploadError.value = "Gagal menghapus foto";