[feet] struk(blm clear)
This commit is contained in:
		
							parent
							
								
									876c5301b3
								
							
						
					
					
						commit
						17892603e8
					
				| @ -42,51 +42,64 @@ class TransaksiController extends Controller | ||||
|     } | ||||
| 
 | ||||
|     // Membuat transaksi baru
 | ||||
|     public function store(Request $request) | ||||
|     { | ||||
|         $request->validate([ | ||||
|             'id_kasir'     => 'required|exists:akun,id', | ||||
|             'id_sales'     => 'nullable|exists:sales,id', | ||||
|             'nama_sales'   => 'nullable|string', | ||||
|             'no_hp'        => 'nullable|string', | ||||
|             'alamat'       => 'nullable|string', | ||||
|             'ongkos_bikin' => 'nullable|numeric', | ||||
|             'total_harga'  => 'required|numeric', | ||||
|             'items'        => 'required|array', | ||||
|             'items.*.id_item'    => 'required|exists:item,id', | ||||
|             'items.*.harga_deal' => 'required|numeric', | ||||
|    public function store(Request $request) | ||||
| { | ||||
|     // Ambil user yang login via Sanctum
 | ||||
|     $kasir = $request->user(); // user authenticated
 | ||||
|     if (!$kasir) { | ||||
|         return response()->json(['error' => 'Unauthorized'], 401); | ||||
|     } | ||||
| 
 | ||||
|     // Validasi request (id_kasir dihapus karena otomatis dari token)
 | ||||
|     $request->validate([ | ||||
|         'id_sales'           => 'nullable|exists:sales,id', | ||||
|         'nama_sales'         => 'required|string', | ||||
|         'no_hp'              => 'required|string', | ||||
|         'alamat'             => 'required|string', | ||||
|         'ongkos_bikin'       => 'nullable|numeric|min:0', | ||||
|         'total_harga'        => 'required|numeric', | ||||
|         'items'              => 'required|array', | ||||
|         'items.*.id_item'    => 'required|exists:items,id', | ||||
|         'items.*.harga_deal' => 'required|numeric', | ||||
|     ]); | ||||
| 
 | ||||
|     DB::beginTransaction(); | ||||
|     try { | ||||
|         $transaksi = Transaksi::create([ | ||||
|             'id_kasir'     => $kasir->id, // ambil dari token
 | ||||
|             'id_sales'     => $request->id_sales, | ||||
|             'nama_sales'   => $request->nama_sales, | ||||
|             'no_hp'        => $request->no_hp, | ||||
|             'alamat'       => $request->alamat, | ||||
|             'ongkos_bikin' => $request->ongkos_bikin ?? 0, | ||||
|             'total_harga'  => $request->total_harga, | ||||
|         ]); | ||||
| 
 | ||||
|         DB::beginTransaction(); | ||||
|         try { | ||||
|             $transaksi = Transaksi::create([ | ||||
|                 'id_kasir'     => $request->id_kasir, | ||||
|                 'id_sales'     => $request->id_sales, | ||||
|                 'nama_sales'   => $request->nama_sales, | ||||
|                 'no_hp'        => $request->no_hp, | ||||
|                 'alamat'       => $request->alamat, | ||||
|                 'ongkos_bikin' => $request->ongkos_bikin, | ||||
|                 'total_harga'  => $request->total_harga, | ||||
|         foreach ($request->items as $it) { | ||||
|             ItemTransaksi::create([ | ||||
|                 'id_transaksi' => $transaksi->id, | ||||
|                 'id_item'      => $it['id_item'], | ||||
|                 'harga_deal'   => $it['harga_deal'], | ||||
|             ]); | ||||
| 
 | ||||
|             foreach ($request->items as $it) { | ||||
|                 ItemTransaksi::create([ | ||||
|                     'id_transaksi' => $transaksi->id, | ||||
|                     'id_item'      => $it['id_item'], | ||||
|                     'harga_deal'   => $it['harga_deal'], | ||||
|                 ]); | ||||
| 
 | ||||
|                 Item::where('id', $it['id_item'])->update(['is_sold' => true]); | ||||
|             } | ||||
| 
 | ||||
|             DB::commit(); | ||||
|             return response()->json($transaksi->load('items'), 201); | ||||
| 
 | ||||
|         } catch (\Exception $e) { | ||||
|             DB::rollBack(); | ||||
|             return response()->json(['error' => $e->getMessage()], 500); | ||||
|             Item::where('id', $it['id_item'])->update(['is_sold' => true]); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|         DB::commit(); | ||||
|         return response()->json( | ||||
|             $transaksi->load(['itemTransaksi.item.produk.foto', 'kasir', 'sales']), | ||||
|             201 | ||||
|         ); | ||||
| 
 | ||||
|     } catch (\Exception $e) { | ||||
|     DB::rollBack(); | ||||
|     return response()->json([ | ||||
|         'error' => $e->getMessage(), | ||||
|         'trace' => $e->getTrace() | ||||
|     ], 500); | ||||
| } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|     // Update transaksi
 | ||||
|     public function update(Request $request, $id) | ||||
|  | ||||
| @ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; | ||||
| class Item extends Model | ||||
| { | ||||
|     use HasFactory; | ||||
|     protected $table = 'items'; | ||||
| 
 | ||||
|     protected $fillable = [ | ||||
|         'id_produk', | ||||
|  | ||||
| @ -11,8 +11,8 @@ class ItemTransaksi extends Model | ||||
|     use HasFactory; | ||||
| 
 | ||||
|     protected $fillable = [ | ||||
|         'id_transaksi',  | ||||
|         'id_item',  | ||||
|         'id_transaksi', | ||||
|         'id_item', | ||||
|         'harga_deal', | ||||
|         'posisi_asal' | ||||
|     ]; | ||||
|  | ||||
| @ -8,6 +8,17 @@ | ||||
|     @cancel="closeDeleteModal" | ||||
|   /> | ||||
| 
 | ||||
|   <!-- ==== TAMBAHAN: Struk Overlay ==== --> | ||||
|   <StrukOverlay | ||||
|     v-if="showStruk" | ||||
|     :isOpen="showStruk" | ||||
|     :pesanan="pesanan" | ||||
|     :total="total" | ||||
|     @close="closeStruk" | ||||
|     @confirm="simpanTransaksi" | ||||
|   /> | ||||
|   <!-- ==== END TAMBAHAN ==== --> | ||||
| 
 | ||||
|   <div class="p-2 sm:p-4"> | ||||
|     <!-- Grid Form & Total --> | ||||
|     <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"> | ||||
| @ -151,6 +162,9 @@ import { ref, computed } from "vue"; | ||||
| import InputField from "./InputField.vue"; | ||||
| import axios from "axios"; | ||||
| import ConfirmDeleteModal from "./ConfirmDeleteModal.vue"; | ||||
| // ==== TAMBAHAN: Import StrukOverlay ==== | ||||
| import StrukOverlay from "./StrukOverlay.vue"; | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| const kodeItem = ref(""); | ||||
| const info = ref(""); | ||||
| @ -162,6 +176,14 @@ const pesanan = ref([]); | ||||
| const showDeleteModal = ref(false) | ||||
| const deleteIndex = ref(null) | ||||
| 
 | ||||
| // ==== TAMBAHAN: State untuk struk ==== | ||||
| const showStruk = ref(false); | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Emit untuk parent component ==== | ||||
| const emit = defineEmits(['transaksi-saved']); | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| let errorTimeout = null; | ||||
| let infoTimeout = null; | ||||
| 
 | ||||
| @ -259,7 +281,7 @@ const hapusPesanan = () => { | ||||
|   closeDeleteModal() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // ==== MODIFIKASI: konfirmasiPenjualan sekarang menampilkan struk ==== | ||||
| const konfirmasiPenjualan = () => { | ||||
|     if (pesanan.value.length === 0) { | ||||
|         error.value = "Belum ada item yang dipesan."; | ||||
| @ -270,9 +292,56 @@ const konfirmasiPenjualan = () => { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // Todo: Implementasi konfirmasi penjualan | ||||
|     alert("Penjualan dikonfirmasi! (Implementasi lebih lanjut diperlukan)"); | ||||
|     // Tampilkan struk overlay | ||||
|     showStruk.value = true; | ||||
| }; | ||||
| // ==== END MODIFIKASI ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Fungsi untuk menutup struk ==== | ||||
| const closeStruk = () => { | ||||
|     showStruk.value = false; | ||||
| }; | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Fungsi untuk menyimpan transaksi ==== | ||||
| const simpanTransaksi = async (dataTransaksi) => { | ||||
|     try { | ||||
|         // Siapkan data untuk API | ||||
|         const transaksiData = { | ||||
|             id_kasir: localStorage.getItem('user_id'), // Asumsi user_id disimpan di localStorage | ||||
|             id_sales: dataTransaksi.selectedSales?.id || null, | ||||
|             nama_sales: dataTransaksi.namaPembeli, | ||||
|             no_hp: dataTransaksi.nomorTelepon, | ||||
|             alamat: dataTransaksi.alamat, | ||||
|             ongkos_bikin: dataTransaksi.ongkosBikin || 0, | ||||
|             total_harga: total.value + (dataTransaksi.ongkosBikin || 0), | ||||
|             items: pesanan.value.map(item => ({ | ||||
|                 id_item: item.id, | ||||
|                 harga_deal: item.harga_deal | ||||
|             })) | ||||
|         }; | ||||
| 
 | ||||
|         const response = await axios.post('/api/transaksi', transaksiData, { | ||||
|             headers: { | ||||
|                 Authorization: `Bearer ${localStorage.getItem("token")}`, | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         // Reset form setelah berhasil | ||||
|         pesanan.value = []; | ||||
|         showStruk.value = false; | ||||
| 
 | ||||
|         // Emit ke parent untuk refresh data transaksi | ||||
|         emit('transaksi-saved', response.data); | ||||
| 
 | ||||
|         alert('Transaksi berhasil disimpan!'); | ||||
| 
 | ||||
|     } catch (error) { | ||||
|         console.error('Error saving transaksi:', error); | ||||
|         alert('Error menyimpan transaksi: ' + (error.response?.data?.message || error.message)); | ||||
|     } | ||||
| }; | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| const total = computed(() => { | ||||
|     let sum = 0; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <template> | ||||
|   <div | ||||
|     v-if="isOpen" | ||||
|     class="text-D font-serif font-medium fixed inset-0 bg-black/75 flex items-center justify-center z-[9999]" | ||||
|     class="text-D pt-serif-regular-italic fixed inset-0 bg-black/75 flex items-center justify-center z-[9999]" | ||||
|   > | ||||
|     <div | ||||
|       class="bg-white w-[1224px] h-[528px] rounded-md shadow-lg relative overflow-hidden" | ||||
| @ -27,7 +27,9 @@ | ||||
|           <!-- Logo & tanggal (absolute di tengah) --> | ||||
|           <div class="absolute inset-x-0 top-0 flex flex-col items-center"> | ||||
|             <img :src="logo" alt="Logo" class="h-15" /> | ||||
|             <p class="mt-1 text-center">Selasa/20-08-2025</p> | ||||
|             <!-- ==== MODIFIKASI: Tanggal sekarang dinamis ==== --> | ||||
|             <p class="mt-1 text-center">{{ getCurrentDate() }}</p> | ||||
|             <!-- ==== END MODIFIKASI ==== --> | ||||
|           </div> | ||||
| 
 | ||||
|           <!-- Data Pembeli --> | ||||
| @ -35,22 +37,33 @@ | ||||
|             class="grid grid-cols-[130px_1fr] gap-y-2 items-center relative z-10" | ||||
|           > | ||||
|             <div class="text-right font-semibold pr-3">Nama Pembeli</div> | ||||
|             <!-- ==== MODIFIKASI: Input field sekarang v-model ==== --> | ||||
|             <inputField | ||||
|               v-model="namaPembeli" | ||||
|               class="h-7 px-2 text-sm rounded bg-blue-200 w-full" | ||||
|             /> | ||||
|             <!-- ==== END MODIFIKASI ==== --> | ||||
|             <div class="text-right font-semibold pr-3">Nomor Telepon</div> | ||||
|             <!-- ==== MODIFIKASI: Input field sekarang v-model ==== --> | ||||
|             <inputField | ||||
|               v-model="nomorTelepon" | ||||
|               class="h-7 px-2 text-sm rounded bg-blue-200 w-full" | ||||
|             /> | ||||
|             <!-- ==== END MODIFIKASI ==== --> | ||||
|             <div class="text-right font-semibold pr-3">Alamat</div> | ||||
|             <!-- ==== MODIFIKASI: Input field sekarang v-model ==== --> | ||||
|             <inputField | ||||
|               v-model="alamat" | ||||
|               class="h-7 px-2 text-sm rounded bg-blue-200 w-full" | ||||
|             /> | ||||
|             <!-- ==== END MODIFIKASI ==== --> | ||||
|           </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <!-- Nomor Transaksi --> | ||||
|         <p class="mt-1 text-sm">TRS-XXX-XXX</p> | ||||
|         <!-- ==== MODIFIKASI: Kode transaksi dinamis ==== --> | ||||
|         <p class="mt-1 text-sm">{{ generateTransactionCode() }}</p> | ||||
|         <!-- ==== END MODIFIKASI ==== --> | ||||
| 
 | ||||
|        <table class="w-full border-D mt-0 text-sm table-fixed"> | ||||
|   <thead> | ||||
| @ -65,33 +78,20 @@ | ||||
|     </tr> | ||||
|   </thead> | ||||
|   <tbody> | ||||
|     <!-- Barang 1 --> | ||||
|     <tr class="text-center"> | ||||
|     <!-- ==== MODIFIKASI: Loop pesanan dari props ==== --> | ||||
|     <tr v-for="(item, index) in pesanan" :key="index" class="text-center"> | ||||
|       <td class="flex items-center gap-2 p-2 border-r border-D"> | ||||
|         <img src="" class="w-12 h-12 object-cover" /> | ||||
|         Ring XXX | ||||
|         <img :src="item.produk.foto?.[0]?.url || ''" class="w-12 h-12 object-cover" /> | ||||
|         {{ item.produk.nama }} | ||||
|       </td> | ||||
|       <td class="border-r border-D">A1, Brankas</td> | ||||
|       <td class="border-r border-D">2,4 g</td> | ||||
|       <td class="border-r border-D">23 K</td> | ||||
|       <td class="border-r border-D">Rp9.000.000</td> | ||||
|       <td class="border-r border-D">2</td> | ||||
|       <td>Rp18.000.000</td> | ||||
|     </tr> | ||||
| 
 | ||||
|     <!-- Barang 2 --> | ||||
|     <tr class="text-center border-b"> | ||||
|       <td class="flex items-center gap-2 p-2 border-r border-D"> | ||||
|         <img src="" class="w-12 h-12 object-cover" /> | ||||
|         Necklace XXX | ||||
|       </td> | ||||
|       <td class="border-r border-D">A2</td> | ||||
|       <td class="border-r border-D">2,4 g</td> | ||||
|       <td class="border-r border-D">23 K</td> | ||||
|       <td class="border-r border-D">Rp3.000.000</td> | ||||
|       <td class="border-r border-D">{{ item.posisi || 'Brankas' }}</td> | ||||
|       <td class="border-r border-D">{{ item.produk.berat || '-' }}</td> | ||||
|       <td class="border-r border-D">{{ item.produk.kadar || '-' }}</td> | ||||
|       <td class="border-r border-D">Rp{{ item.harga_deal.toLocaleString() }}</td> | ||||
|       <td class="border-r border-D">1</td> | ||||
|       <td>Rp3.000.000</td> | ||||
|       <td>Rp{{ item.harga_deal.toLocaleString() }}</td> | ||||
|     </tr> | ||||
|     <!-- ==== END MODIFIKASI ==== --> | ||||
| 
 | ||||
|     <!-- Baris Ongkos + Total --> | ||||
|     <tr class="align-top"> | ||||
| @ -108,15 +108,13 @@ | ||||
|       <td colspan="2" rowspan="2" class="p-2 text-center align-top"> | ||||
|         <div class="flex flex-col items-center justify-center h-full"> | ||||
|           <p><strong>Sales</strong></p> | ||||
|           <!-- ==== MODIFIKASI: Sales dropdown dinamis ==== --> | ||||
|           <inputSelect | ||||
|             v-model="sales" | ||||
|             :options="[ | ||||
|                 { value: 'Timothy', label: 'Timothy' }, | ||||
|                 { value: 'Iwan', label: 'Iwan' } | ||||
|             ]" | ||||
|             v-model="selectedSales" | ||||
|             :options="salesOptions" | ||||
|             class="mt-16 text-sm rounded bg-B cursor-pointer !w-[160px] text-center [option]:text-left" | ||||
|             /> | ||||
| 
 | ||||
|           /> | ||||
|           <!-- ==== END MODIFIKASI ==== --> | ||||
|         </div> | ||||
|       </td> | ||||
| 
 | ||||
| @ -132,13 +130,19 @@ | ||||
|         <div class="space-y-2"> | ||||
|           <div class="flex items-center"> | ||||
|             <p>Rp</p> | ||||
|             <!-- ==== MODIFIKASI: Ongkos bikin input ==== --> | ||||
|             <inputField | ||||
|               v-model.number="ongkosBikin" | ||||
|               type="number" | ||||
|               class="h-7 px-2 text-sm rounded bg-blue-200 text-left w-full" | ||||
|             /> | ||||
|             <!-- ==== END MODIFIKASI ==== --> | ||||
|           </div> | ||||
|           <div class="flex items-center"> | ||||
|             <p>Rp</p> | ||||
|             <p class="px-3 py-1 text-left text-sm w-full">21.200.000</p> | ||||
|             <!-- ==== MODIFIKASI: Total dinamis ==== --> | ||||
|             <p class="px-3 py-1 text-left text-sm w-full">{{ grandTotal.toLocaleString() }}</p> | ||||
|             <!-- ==== END MODIFIKASI ==== --> | ||||
|           </div> | ||||
|         </div> | ||||
|       </td> | ||||
| @ -150,21 +154,22 @@ | ||||
|       <td></td> | ||||
|       <td class="p-2 text-center"> | ||||
|         <div class="flex gap-2"> | ||||
|           <button class="bg-gray-400 text-white px-6 py-2 rounded w-full"> | ||||
|           <!-- ==== MODIFIKASI: Tombol Batal dengan emit close ==== --> | ||||
|           <button @click="$emit('close')" class="bg-gray-400 text-white px-6 py-2 rounded w-full"> | ||||
|             Batal | ||||
|           </button> | ||||
|           <button class="bg-C text-white px-6 py-2 rounded w-full"> | ||||
|           <!-- ==== END MODIFIKASI ==== --> | ||||
|           <!-- ==== MODIFIKASI: Tombol Simpan dengan validasi ==== --> | ||||
|           <button @click="handleSimpan" class="bg-C text-white px-6 py-2 rounded w-full"> | ||||
|             Simpan | ||||
|           </button> | ||||
|           <!-- ==== END MODIFIKASI ==== --> | ||||
|         </div> | ||||
|       </td> | ||||
|     </tr> | ||||
|   </tbody> | ||||
| </table> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|       </div> | ||||
| 
 | ||||
|       <!-- Pesan bawah --> | ||||
| @ -177,20 +182,146 @@ | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref } from 'vue' | ||||
| import { ref, computed, onMounted } from 'vue' | ||||
| import logo from '@/../images/logo.png' | ||||
| import inputField from '@/components/inputField.vue' | ||||
| import inputSelect from '@/components/inputSelect.vue' | ||||
| // ==== TAMBAHAN: Import axios ==== | ||||
| import axios from 'axios' | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| defineProps({ | ||||
| // ==== MODIFIKASI: Props sekarang menerima pesanan dan total ==== | ||||
| const props = defineProps({ | ||||
|   isOpen: { | ||||
|     type: Boolean, | ||||
|     default: false, | ||||
|   }, | ||||
|   pesanan: { | ||||
|     type: Array, | ||||
|     default: () => [] | ||||
|   }, | ||||
|   total: { | ||||
|     type: Number, | ||||
|     default: 0 | ||||
|   } | ||||
| }) | ||||
| // ==== END MODIFIKASI ==== | ||||
| 
 | ||||
| const sales = ref('Timothy') | ||||
| // ==== TAMBAHAN: Define emits ==== | ||||
| const emit = defineEmits(['close', 'confirm']) | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Reactive variables untuk form ==== | ||||
| const namaPembeli = ref('') | ||||
| const nomorTelepon = ref('') | ||||
| const alamat = ref('') | ||||
| const ongkosBikin = ref(0) | ||||
| const selectedSales = ref(null) | ||||
| const salesOptions = ref([]) | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Computed untuk grand total ==== | ||||
| const grandTotal = computed(() => { | ||||
|   return props.total + (ongkosBikin.value || 0) | ||||
| }) | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Fungsi untuk generate tanggal ==== | ||||
| const getCurrentDate = () => { | ||||
|   const days = ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'] | ||||
|   const months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'] | ||||
| 
 | ||||
|   const now = new Date() | ||||
|   const dayName = days[now.getDay()] | ||||
|   const day = String(now.getDate()).padStart(2, '0') | ||||
|   const month = months[now.getMonth()] | ||||
|   const year = now.getFullYear() | ||||
| 
 | ||||
|   return `${dayName}/${day}-${month}-${year}` | ||||
| } | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Fungsi untuk generate kode transaksi ==== | ||||
| const generateTransactionCode = () => { | ||||
|   const now = new Date() | ||||
|   const timestamp = now.getTime().toString().slice(-6) | ||||
|   return `TRS-${timestamp}` | ||||
| } | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Fetch sales data ==== | ||||
| const fetchSales = async () => { | ||||
|   try { | ||||
|     const response = await axios.get('/api/sales', { | ||||
|       headers: { | ||||
|         Authorization: `Bearer ${localStorage.getItem("token")}`, | ||||
|       }, | ||||
|     }) | ||||
| 
 | ||||
|     salesOptions.value = response.data.map(sales => ({ | ||||
|       value: sales, | ||||
|       label: sales.nama | ||||
|     })) | ||||
| 
 | ||||
|     // Set default sales jika ada | ||||
|     if (salesOptions.value.length > 0) { | ||||
|       selectedSales.value = salesOptions.value[0].value | ||||
|     } | ||||
|   } catch (error) { | ||||
|     console.error('Error fetching sales:', error) | ||||
|   } | ||||
| } | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Handle simpan dengan validasi ==== | ||||
| const handleSimpan = () => { | ||||
|   // Validasi input wajib | ||||
|   if (!namaPembeli.value.trim()) { | ||||
|     alert('Nama pembeli harus diisi!') | ||||
|     return | ||||
|   } | ||||
| 
 | ||||
|   if (!nomorTelepon.value.trim()) { | ||||
|     alert('Nomor telepon harus diisi!') | ||||
|     return | ||||
|   } | ||||
| 
 | ||||
|   if (!alamat.value.trim()) { | ||||
|     alert('Alamat harus diisi!') | ||||
|     return | ||||
|   } | ||||
| 
 | ||||
|   if (!selectedSales.value) { | ||||
|     alert('Sales harus dipilih!') | ||||
|     return | ||||
|   } | ||||
| 
 | ||||
|   // Emit data ke parent | ||||
|   emit('confirm', { | ||||
|     namaPembeli: namaPembeli.value, | ||||
|     nomorTelepon: nomorTelepon.value, | ||||
|     alamat: alamat.value, | ||||
|     ongkosBikin: ongkosBikin.value || 0, | ||||
|     selectedSales: selectedSales.value | ||||
|   }) | ||||
| } | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| // ==== TAMBAHAN: Fetch sales saat component mounted ==== | ||||
| onMounted(() => { | ||||
|   if (props.isOpen) { | ||||
|     fetchSales() | ||||
|   } | ||||
| }) | ||||
| // ==== END TAMBAHAN ==== | ||||
| </script> | ||||
| 
 | ||||
| <style scoped> | ||||
| @import url('https://fonts.googleapis.com/css2?family=PT+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap'); | ||||
| .pt-serif-regular-italic { | ||||
|   font-family: "PT Serif", serif; | ||||
|   font-weight: 400; | ||||
| } | ||||
| 
 | ||||
| </style> | ||||
|  | ||||
| @ -10,7 +10,9 @@ | ||||
|                         class="bg-white rounded-xl shadow-lg border border-B overflow-hidden h-auto lg:h-full" | ||||
|                     > | ||||
|                         <div class="p-2 sm:p-3 md:p-4 h-auto lg:h-full"> | ||||
|                             <KasirForm /> | ||||
|                             <!-- ==== MODIFIKASI: Tambah event listener untuk transaksi-saved ==== --> | ||||
|                             <KasirForm @transaksi-saved="handleTransaksiSaved" /> | ||||
|                             <!-- ==== END MODIFIKASI ==== --> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
| @ -82,7 +84,8 @@ import KasirTransaksiList from "../components/KasirTransaksiList.vue"; | ||||
| const transaksi = ref([]); | ||||
| const loading = ref(true); | ||||
| 
 | ||||
| onMounted(async () => { | ||||
| // ==== TAMBAHAN: Fungsi untuk fetch transaksi (dipindah ke fungsi terpisah) ==== | ||||
| const fetchTransaksi = async () => { | ||||
|     try { | ||||
|         loading.value = true; | ||||
|         const res = await axios.get("/api/transaksi?limit=10", { | ||||
| @ -97,8 +100,22 @@ onMounted(async () => { | ||||
|     } finally { | ||||
|         loading.value = false; | ||||
|     } | ||||
| }; | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| onMounted(async () => { | ||||
|     // ==== MODIFIKASI: Panggil fungsi fetchTransaksi ==== | ||||
|     await fetchTransaksi(); | ||||
|     // ==== END MODIFIKASI ==== | ||||
| }); | ||||
| 
 | ||||
| // ==== TAMBAHAN: Handle ketika transaksi baru disimpan ==== | ||||
| const handleTransaksiSaved = async (newTransaksi) => { | ||||
|     // Refresh daftar transaksi | ||||
|     await fetchTransaksi(); | ||||
| }; | ||||
| // ==== END TAMBAHAN ==== | ||||
| 
 | ||||
| const lihatDetail = (trx) => { | ||||
|     alert(`Detail transaksi: ${trx.kode}`); | ||||
| }; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user