[Feat] Sistem logic kasir
This commit is contained in:
parent
3f654c6c7a
commit
a99996940e
@ -42,7 +42,7 @@ class ItemController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function show(int $id)
|
public function show(int $id)
|
||||||
{
|
{
|
||||||
$item = Item::with('produk.foto','nampan')->findOrFail($id);
|
$item = Item::with('produk.foto','nampan','itemTransaksi.transaksi')->findOrFail($id);
|
||||||
return response()->json($item);
|
return response()->json($item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,6 @@ class Item extends Model
|
|||||||
|
|
||||||
public function itemTransaksi()
|
public function itemTransaksi()
|
||||||
{
|
{
|
||||||
return $this->hasMany(ItemTransaksi::class, 'id_item');
|
return $this->hasOne(ItemTransaksi::class, 'id_item');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ class Transaksi extends Model
|
|||||||
'id_kasir',
|
'id_kasir',
|
||||||
'id_sales',
|
'id_sales',
|
||||||
'nama_sales',
|
'nama_sales',
|
||||||
|
'nama_pembeli',
|
||||||
'no_hp',
|
'no_hp',
|
||||||
'alamat',
|
'alamat',
|
||||||
'ongkos_bikin',
|
'ongkos_bikin',
|
||||||
|
@ -26,6 +26,7 @@ class TransaksiFactory extends Factory
|
|||||||
'id_kasir' => $kasir?->id,
|
'id_kasir' => $kasir?->id,
|
||||||
'id_sales' => $sales?->id,
|
'id_sales' => $sales?->id,
|
||||||
'nama_sales' => $sales?->nama ?? $this->faker->name(),
|
'nama_sales' => $sales?->nama ?? $this->faker->name(),
|
||||||
|
'nama_pembeli' => $sales?->nama ?? $this->faker->name(),
|
||||||
'no_hp' => $this->faker->phoneNumber(),
|
'no_hp' => $this->faker->phoneNumber(),
|
||||||
'alamat' => $this->faker->address(),
|
'alamat' => $this->faker->address(),
|
||||||
'ongkos_bikin' => $this->faker->randomFloat(2, 0, 1000000),
|
'ongkos_bikin' => $this->faker->randomFloat(2, 0, 1000000),
|
||||||
|
@ -16,6 +16,7 @@ return new class extends Migration
|
|||||||
$table->foreignId('id_kasir')->constrained('users');
|
$table->foreignId('id_kasir')->constrained('users');
|
||||||
$table->foreignId('id_sales')->nullable()->constrained('sales');
|
$table->foreignId('id_sales')->nullable()->constrained('sales');
|
||||||
$table->string('nama_sales', 100);
|
$table->string('nama_sales', 100);
|
||||||
|
$table->string('nama_pembeli', 100);
|
||||||
$table->string('no_hp', 20);
|
$table->string('no_hp', 20);
|
||||||
$table->string('alamat', 100);
|
$table->string('alamat', 100);
|
||||||
$table->double('ongkos_bikin')->nullable();
|
$table->double('ongkos_bikin')->nullable();
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<footer class="bg-B border-t border-D py-4 px-6 flex flex-col md:flex-row items-center justify-between">
|
<footer class="bg-B py-4 px-6 flex flex-col md:flex-row items-center justify-between">
|
||||||
<!-- Left: Logo -->
|
<!-- Left: Logo -->
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<img :src="logo" alt="Logo" class="h-10">
|
<img :src="logo" alt="Logo" class="h-10">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Center: Copyright -->
|
<!-- Center: Copyright -->
|
||||||
<div class="text-sm text-[#0f1d4a] font-medium text-center">
|
<div class="text-sm text-D font-medium text-center">
|
||||||
Abbauf Tech © 2025 Semua hak dilindungi
|
Abbauf Tech © 2025 Semua hak dilindungi
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right: Social Icons -->
|
<!-- Right: Social Icons -->
|
||||||
<div class="flex items-center gap-4 text-[#0f1d4a] mt-2 md:mt-0">
|
<div class="flex items-center gap-4 text-D mt-2 md:mt-0">
|
||||||
<a href="#" class="hover:text-sky-600"><i class="fab fa-facebook"></i></a>
|
<a href="#" class="hover:text-sky-600"><i class="fab fa-facebook"></i></a>
|
||||||
<a href="#" class="hover:text-sky-600"><i class="fab fa-twitter"></i></a>
|
<a href="#" class="hover:text-sky-600"><i class="fab fa-twitter"></i></a>
|
||||||
<a href="#" class="hover:text-sky-600"><i class="fab fa-instagram"></i></a>
|
<a href="#" class="hover:text-sky-600"><i class="fab fa-instagram"></i></a>
|
||||||
@ -24,8 +24,3 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import logo from '@/../images/logo.png'
|
import logo from '@/../images/logo.png'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Pakai Font Awesome untuk ikon */
|
|
||||||
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css');
|
|
||||||
</style>
|
|
||||||
|
@ -1,95 +1,181 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- Input Grid -->
|
<div class="grid grid-cols-2 h-full gap-4 mb-4">
|
||||||
<div class="grid grid-cols-2 gap-4 mb-4">
|
<div class="flex flex-col gap-4">
|
||||||
<div class="flex flex-col gap-4">
|
<div>
|
||||||
<div>
|
<label class="block text-sm font-medium text-D">Kode Item *</label>
|
||||||
<label class="block text-sm font-medium text-gray-700">Kode Item *</label>
|
<div class="flex flex-row justify-between mt-1 w-full rounded-md bg-A shadow-sm sm:text-sm border-B">
|
||||||
<InputField
|
<input type="text" v-model="kodeItem" @keyup.enter="inputItem" placeholder="Scan atau masukkan kode item"
|
||||||
v-model="kodeItem"
|
class=" bg-A focus:border-C focus:ring focus:ring-D focus:ring-opacity-50 p-2 w-full" />
|
||||||
type="text"
|
<button v-if="!loadingItem" @click="inputItem" class="px-3 bg-D hover:bg-D/80 text-A rounded-r-md"><i
|
||||||
placeholder="Masukkan kode item"
|
class="fas fa-arrow-right"></i></button>
|
||||||
/>
|
<div v-else class="flex items-center justify-center px-3">
|
||||||
</div>
|
<div class="rounded-full h-5 w-5 border-b-2 border-A flex items-center justify-center">
|
||||||
<div>
|
<i class="fas fa-spinner"></i>
|
||||||
<label class="block text-sm font-medium text-gray-700">Harga Jual</label>
|
</div>
|
||||||
<InputField
|
</div>
|
||||||
v-model="hargaJual"
|
|
||||||
type="number"
|
|
||||||
placeholder="Masukkan Harga Jual"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-center">
|
<div>
|
||||||
<div class="text-center">
|
<label class="block text-sm font-medium text-D">Harga Jual</label>
|
||||||
<span class="block text-gray-600 font-medium">Total:</span>
|
<InputField v-model="hargaJual" type="number" placeholder="Masukkan Harga Jual" />
|
||||||
<span class="text-3xl font-bold text-[#0f1d4a]">
|
</div>
|
||||||
Rp{{ total.toLocaleString() }},-
|
|
||||||
</span>
|
<div class="flex justify-between gap-4">
|
||||||
</div>
|
<button @click="tambahItem" class="px-4 py-2 rounded-md bg-C text-D font-medium hover:bg-C/80 transition">
|
||||||
|
Tambah Item
|
||||||
|
</button>
|
||||||
|
<button @click="konfirmasiPenjualan"
|
||||||
|
class="px-6 py-2 rounded-md bg-D text-A font-semibold hover:bg-D/80 transition">
|
||||||
|
Lanjut
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex pt-10 justify-center">
|
||||||
<!-- Buttons -->
|
<div class="text-start">
|
||||||
<div class="flex gap-4 mb-6">
|
<span class="block text-gray-600 font-medium">Total:</span>
|
||||||
<button @click="tambahItem"
|
<span class="text-3xl font-bold text-D">
|
||||||
class="px-4 py-2 rounded-md bg-[#f1ede8] text-[#0f1d4a] font-medium hover:bg-[#e4dfd8] transition">
|
Rp{{ total.toLocaleString() }},-
|
||||||
Tambah Item
|
</span>
|
||||||
</button>
|
</div>
|
||||||
<button
|
|
||||||
class="px-6 py-2 rounded-md bg-[#c6a77d] text-[#0f1d4a] font-semibold hover:bg-[#b09065] transition">
|
|
||||||
Lanjut
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Table -->
|
|
||||||
<table class="w-full border-collapse border border-gray-200 text-sm rounded-lg overflow-hidden">
|
|
||||||
<thead class="bg-gray-100 text-[#0f1d4a]">
|
|
||||||
<tr>
|
|
||||||
<th class="border border-gray-200 p-2">No</th>
|
|
||||||
<th class="border border-gray-200 p-2">Item</th>
|
|
||||||
<th class="border border-gray-200 p-2">Jml</th>
|
|
||||||
<th class="border border-gray-200 p-2">Harga</th>
|
|
||||||
<th class="border border-gray-200 p-2">Total</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="(item, index) in pesanan" :key="index" class="hover:bg-gray-50 text-center">
|
|
||||||
<td class="border border-gray-200 p-2">{{ index + 1 }}</td>
|
|
||||||
<td class="border border-gray-200 p-2">{{ item.kode }}</td>
|
|
||||||
<td class="border border-gray-200 p-2">{{ item.jumlah }}</td>
|
|
||||||
<td class="border border-gray-200 p-2">Rp{{ item.harga.toLocaleString() }}</td>
|
|
||||||
<td class="border border-gray-200 p-2">Rp{{ (item.harga * item.jumlah).toLocaleString() }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<p v-if="error" :class="{ 'animate-shake': error }" class="text-sm text-red-600 mt-1">{{ error }}</p>
|
||||||
|
<p v-if="info" class="text-sm text-C mt-1">{{ info }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="w-full border border-B text-sm rounded-lg overflow-hidden">
|
||||||
|
<thead class="bg-A text-D">
|
||||||
|
<tr>
|
||||||
|
<th class="border border-B p-2">No</th>
|
||||||
|
<th class="border border-B p-2">Nam Produk </th>
|
||||||
|
<th class="border border-B p-2">Posisi</th>
|
||||||
|
<th class="border border-B p-2">Harga</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-if="pesanan.length == 0" class="text-center text-D/70">
|
||||||
|
<td colspan="5" class="h-20 border border-B">Belum ada item dipesan</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-else v-for="(item, index) in pesanan" :key="index" class="hover:bg-gray-50 text-center">
|
||||||
|
<td class="border border-B p-2">{{ index + 1 }}</td>
|
||||||
|
<td class="border border-B p-2 text-left">{{ item.produk.nama }}</td>
|
||||||
|
<td class="border border-B p-2">{{ item.posisi ? item.posisi : 'Brankas' }}</td>
|
||||||
|
<td class="border border-B p-2">Rp{{ item.harga_deal.toLocaleString() }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
<script setup>
|
import { ref, computed } from 'vue'
|
||||||
import { ref, computed } from 'vue'
|
|
||||||
import InputField from './InputField.vue'
|
import InputField from './InputField.vue'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
const kodeItem = ref('')
|
const kodeItem = ref('')
|
||||||
const hargaJual = ref(null)
|
const info = ref('')
|
||||||
const pesanan = ref([])
|
const error = ref('')
|
||||||
|
const hargaJual = ref(null)
|
||||||
|
const item = ref(null)
|
||||||
|
const loadingItem = ref(false)
|
||||||
|
const pesanan = ref([])
|
||||||
|
|
||||||
const tambahItem = () => {
|
let errorTimeout = null
|
||||||
if (!kodeItem.value || !hargaJual.value) return
|
let infoTimeout = null
|
||||||
pesanan.value.push({
|
|
||||||
kode: kodeItem.value,
|
const inputItem = async () => {
|
||||||
jumlah: 1,
|
if (!kodeItem.value) return
|
||||||
harga: parseFloat(hargaJual.value),
|
|
||||||
})
|
info.value = ''
|
||||||
kodeItem.value = ''
|
error.value = ''
|
||||||
hargaJual.value = 0
|
clearTimeout(infoTimeout)
|
||||||
|
clearTimeout(errorTimeout)
|
||||||
|
|
||||||
|
loadingItem.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`/api/item/${kodeItem.value}`);
|
||||||
|
item.value = response.data;
|
||||||
|
hargaJual.value = item.value.produk.harga_jual
|
||||||
|
|
||||||
|
if (item.value.is_sold) {
|
||||||
|
throw new Error('Item sudah terjual')
|
||||||
|
}
|
||||||
|
if (pesanan.value.some(p => p.id === item.value.id)) {
|
||||||
|
throw new Error('Item sedang dipesan')
|
||||||
|
}
|
||||||
|
info.value = `Item dipilih: ${item.value.produk.nama} dari ${item.value.posisi ? item.value.posisi : 'Brankas'}`
|
||||||
|
|
||||||
|
infoTimeout = setTimeout(() => {
|
||||||
|
info.value = ''
|
||||||
|
}, 3000)
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
if (err == '') {
|
||||||
|
error.value = 'Error: Item tidak ditemukan'
|
||||||
|
} else {
|
||||||
|
error.value = err
|
||||||
|
}
|
||||||
|
info.value = ''
|
||||||
|
hargaJual.value = null
|
||||||
|
item.value = null
|
||||||
|
|
||||||
|
errorTimeout = setTimeout(() => {
|
||||||
|
error.value = ''
|
||||||
|
}, 3000)
|
||||||
|
} finally {
|
||||||
|
loadingItem.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tambahItem = () => {
|
||||||
|
if (!item.value || !hargaJual.value) {
|
||||||
|
error.value = 'Scan atau masukkan kode item untuk dijual.'
|
||||||
|
if (kodeItem.value) {
|
||||||
|
error.value = 'Masukkan harga jual, atau input dari kode item lagi.'
|
||||||
|
}
|
||||||
|
clearTimeout(errorTimeout)
|
||||||
|
errorTimeout = setTimeout(() => {
|
||||||
|
error.value = ''
|
||||||
|
}, 3000)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const total = computed(() =>
|
// harga deal
|
||||||
pesanan.value.reduce((sum, item) => sum + item.harga * item.jumlah, 0)
|
item.value.harga_deal = hargaJual.value
|
||||||
)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
pesanan.value.push(item.value)
|
||||||
|
|
||||||
|
// Reset input fields
|
||||||
|
kodeItem.value = ''
|
||||||
|
hargaJual.value = null
|
||||||
|
item.value = null
|
||||||
|
info.value = ''
|
||||||
|
clearTimeout(infoTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
const konfirmasiPenjualan = () => {
|
||||||
|
if (pesanan.value.length === 0) {
|
||||||
|
error.value = 'Belum ada item yang dipesan.'
|
||||||
|
clearTimeout(errorTimeout)
|
||||||
|
errorTimeout = setTimeout(() => {
|
||||||
|
error.value = ''
|
||||||
|
}, 3000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo: Implementasi konfirmasi penjualan
|
||||||
|
alert('Penjualan dikonfirmasi! (Implementasi lebih lanjut diperlukan)')
|
||||||
|
}
|
||||||
|
|
||||||
|
const total = computed(() => {
|
||||||
|
let sum = 0;
|
||||||
|
pesanan.value.forEach(item => {
|
||||||
|
sum += item.harga_deal;
|
||||||
|
});
|
||||||
|
return sum;
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
@ -1,42 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<h3 class="text-lg font-semibold mb-4 text-gray-800">Transaksi</h3>
|
<h3 class="text-lg font-semibold mb-4 text-gray-800">Transaksi</h3>
|
||||||
<table class="w-full border-collapse border border-gray-200 text-sm">
|
<table class="w-full border border-B rounded-lg text-sm">
|
||||||
<thead class="bg-gray-100">
|
<thead class="bg-A text-D">
|
||||||
<tr>
|
<tr>
|
||||||
<th class="border border-gray-200 p-2">Tanggal</th>
|
<th class="border border-B p-2">Tanggal</th>
|
||||||
<th class="border border-gray-200 p-2">Kode Transaksi</th>
|
<th class="border border-B p-2">Kode Transaksi</th>
|
||||||
<th class="border border-gray-200 p-2">Pendapatan</th>
|
<th class="border border-B p-2">Pendapatan</th>
|
||||||
<th class="border border-gray-200 p-2">Detail Item</th>
|
<th class="border border-B p-2">Detail Item</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="trx in props.transaksi" :key="trx.id">
|
<tr v-for="trx in props.transaksi" :key="trx.id" class="hover:bg-A">
|
||||||
<td class="border border-gray-200 p-2">{{ trx.tanggal }}</td>
|
<td class="border border-B p-2">{{ trx.tanggal }}</td>
|
||||||
<td class="border border-gray-200 p-2">{{ trx.kode }}</td>
|
<td class="border border-B p-2">{{ trx.kode }}</td>
|
||||||
<td class="border border-gray-200 p-2">Rp{{ (trx.pendapatan || 0).toLocaleString() }}</td>
|
<td class="border border-B p-2">Rp{{ (trx.pendapatan || 0).toLocaleString() }}</td>
|
||||||
<td class="border border-gray-200 p-2 text-center">
|
<td class="border border-B p-2 text-center">
|
||||||
<button @click="$emit('detail', trx)"
|
<button @click="$emit('detail', trx)"
|
||||||
class="px-3 py-1 rounded-md bg-[#c6a77d] text-white hover:bg-[#b09065] transition">Detail</button>
|
class="px-3 py-1 rounded-md bg-D text-A hover:bg-D/80 transition">Detail</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from "vue"
|
const props = defineProps({
|
||||||
|
transaksi: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const props = defineProps({
|
defineEmits(['detail'])
|
||||||
transaksi: {
|
</script>
|
||||||
type: Array,
|
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
defineEmits(['detail'])
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
console.log(props.transaksi);
|
|
||||||
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
@ -73,7 +73,7 @@ onBeforeUnmount(() => {
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
.modal-enter-active,
|
.modal-enter-active,
|
||||||
.modal-leave-active {
|
.modal-leave-active {
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
@ -1,36 +1,71 @@
|
|||||||
<template>
|
<template>
|
||||||
<mainLayout>
|
<mainLayout>
|
||||||
<div class="p-6 grid grid-cols-3 gap-6">
|
<div class="lg:p-2 pt-6">
|
||||||
<!-- Left Section -->
|
<div class="grid grid-cols-1 lg:grid-cols-5 gap-3 sm:gap-2 max-w-7xl mx-auto">
|
||||||
<div class="col-span-2 bg-white p-4 rounded-lg shadow-md border border-gray-200 flex flex-col">
|
<!-- Left Section - Form Kasir -->
|
||||||
<KasirForm />
|
<div class="lg:col-span-3">
|
||||||
|
<div class="bg-white rounded-xl shadow-lg border border-B overflow-hidden h-full">
|
||||||
|
<div class="p-2 md:p-4 h-full">
|
||||||
|
<KasirForm />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right Section -->
|
<!-- Right Section - Transaction List -->
|
||||||
<div class="bg-white p-4 rounded-lg shadow-md border border-gray-200">
|
<div class="lg:col-span-2">
|
||||||
<KasirTransaksiList :transaksi="transaksi" @detail="lihatDetail" />
|
<div class="bg-white rounded-xl shadow-lg border border-B overflow-hidden lg:h-fit sticky top-4">
|
||||||
|
<!-- Transaction List Content -->
|
||||||
|
<div class="p-4 sm:p-6 overflow-y-auto">
|
||||||
|
<!-- Loading State -->
|
||||||
|
<div v-if="loading" class="flex items-center justify-center py-8">
|
||||||
|
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-C"></div>
|
||||||
|
<span class="ml-3 text-D/70">Memuat transaksi...</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Empty State -->
|
||||||
|
<div v-else-if="!transaksi.length" class="text-center py-8">
|
||||||
|
<svg class="w-16 h-16 mx-auto text-B mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1"
|
||||||
|
d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
|
||||||
|
</svg>
|
||||||
|
<p class="text-[var(--color-D)]/60 text-sm">Belum ada transaksi</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Transaction List -->
|
||||||
|
<KasirTransaksiList
|
||||||
|
v-else
|
||||||
|
:transaksi="transaksi"
|
||||||
|
@detail="lihatDetail"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mainLayout>
|
</div>
|
||||||
</template>
|
</mainLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from "vue"
|
import { ref, onMounted } from "vue"
|
||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
|
|
||||||
import mainLayout from '../layouts/mainLayout.vue'
|
import mainLayout from '../layouts/mainLayout.vue'
|
||||||
import KasirForm from '../components/KasirForm.vue'
|
import KasirForm from '../components/KasirForm.vue'
|
||||||
import KasirTransaksiList from '../components/KasirTransaksiList.vue'
|
import KasirTransaksiList from '../components/KasirTransaksiList.vue'
|
||||||
|
|
||||||
const transaksi = ref([])
|
const transaksi = ref([])
|
||||||
|
const loading = ref(true)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await axios.get("/api/transaksi?limit=10") // GANTI URL SESUAI API
|
loading.value = true
|
||||||
|
const res = await axios.get("/api/transaksi?limit=10")
|
||||||
|
|
||||||
transaksi.value = res.data
|
transaksi.value = res.data
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Gagal fetch transaksi:", err)
|
console.error("Gagal fetch transaksi:", err)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user