[fix] perbaikan transaksi code dan seeder sales

This commit is contained in:
dhilanradya 2025-10-21 10:02:02 +07:00
parent 7cd3e54402
commit 65e1bdd116
2 changed files with 50 additions and 121 deletions

View File

@ -37,17 +37,9 @@ class DatabaseSeeder extends Seeder
'updated_at' => now(), 'updated_at' => now(),
]); ]);
// Create sales record
Sales::create([
'nama' => 'Kasir',
'no_hp' => '-',
'alamat' => '-',
'created_at' => now(),
'updated_at' => now(),
]);
// Call other seeders // Call other seeders
$this->call(DataSeeder::class); $this->call(DataSeeder::class);
$this->call(DummySeeder::class); $this->call(DummySeeder::class);
} }
} }

View File

@ -18,7 +18,7 @@
<p class="flex items-center gap-2"> <p class="flex items-center gap-2">
<i class="fab fa-whatsapp text-green-500 text-xl"></i> 08158851178 <i class="fab fa-whatsapp text-green-500 text-xl"></i> 08158851178
</p> </p>
<p class=" text-sm">{{ generateTransactionCode() }}</p> <p class="text-sm">TRSXXXXXXXXXXXX</p>
</div> </div>
<div class="absolute inset-x-0 top-[-48px] flex flex-col items-center"> <div class="absolute inset-x-0 top-[-48px] flex flex-col items-center">
@ -108,7 +108,7 @@
<div class="w-[20%] p-2 flex flex-col items-center justify-center"> <div class="w-[20%] p-2 flex flex-col items-center justify-center">
<p><strong>Hormat Kami</strong></p> <p><strong>Hormat Kami</strong></p>
<inputSelect v-model="selectedSales" :options="salesOptions" <inputSelect v-model="selectedSales" :options="salesOptions" placeholder="Pilih Sales"
class="mt-16 text-sm rounded bg-B cursor-pointer !w-[160px] text-center [option]:text-left" /> class="mt-16 text-sm rounded bg-B cursor-pointer !w-[160px] text-center [option]:text-left" />
</div> </div>
@ -189,18 +189,9 @@ import inputSelect from '@/components/InputSelect.vue'
import axios from 'axios' import axios from 'axios'
const props = defineProps({ const props = defineProps({
isOpen: { isOpen: Boolean,
type: Boolean, pesanan: Array,
default: false, total: Number
},
pesanan: {
type: Array,
default: () => []
},
total: {
type: Number,
default: 0
}
}) })
const emit = defineEmits(['close', 'confirm', 'transaksi-saved']) const emit = defineEmits(['close', 'confirm', 'transaksi-saved'])
@ -218,52 +209,31 @@ const showToast = ref(false)
const toastType = ref('error') const toastType = ref('error')
const toastMessage = ref('') const toastMessage = ref('')
// 🧾 kode transaksi tetap
const transactionCode = ref('')
const toastClasses = computed(() => { const toastClasses = computed(() => {
const baseClasses = 'text-white' const base = 'text-white'
const typeClasses = { const type = {
error: 'bg-red-500', error: 'bg-red-500',
success: 'bg-green-500', success: 'bg-green-500',
info: 'bg-blue-500' info: 'bg-blue-500'
} }
return `${baseClasses} ${typeClasses[toastType.value]}` return `${base} ${type[toastType.value]}`
}) })
const grandTotal = computed(() => { const grandTotal = computed(() => props.total + (ongkosBikin.value || 0))
return props.total + (ongkosBikin.value || 0)
})
const getRowStyle = () => { const getRowStyle = () => props.pesanan.length === 1 ? { height: '126px' } : { height: '63px' }
if (props.pesanan.length === 1) { const getImageClass = () => props.pesanan.length === 1 ? 'w-25 h-25' : 'w-12 h-12'
return { height: '126px' } const getTextClass = () => props.pesanan.length === 1 ? 'text-lg font-medium' : 'text-sm'
}
return { height: '63px' }
}
const getImageClass = () => {
if (props.pesanan.length === 1) {
return 'w-25 h-25'
}
return 'w-12 h-12'
}
const getTextClass = () => {
if (props.pesanan.length === 1) {
return 'text-lg font-medium'
}
return 'text-sm'
}
const getCurrentDate = () => { const getCurrentDate = () => {
const days = ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'] 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 now = new Date()
const dayName = days[now.getDay()]
const day = String(now.getDate()).padStart(2, '0') const day = String(now.getDate()).padStart(2, '0')
const month = months[now.getMonth()] const month = String(now.getMonth() + 1).padStart(2, '0')
const year = now.getFullYear() return `${days[now.getDay()]}, ${day}-${month}-${now.getFullYear()}`
return `${dayName}, ${day}-${month}-${year}`
} }
const generateTransactionCode = () => { const generateTransactionCode = () => {
@ -276,55 +246,33 @@ const showSimpleToast = (type, message, duration = 3000) => {
toastType.value = type toastType.value = type
toastMessage.value = message toastMessage.value = message
showToast.value = true showToast.value = true
setTimeout(() => (showToast.value = false), duration)
setTimeout(() => {
showToast.value = false
}, duration)
} }
const fetchSales = async () => { const fetchSales = async () => {
try { try {
const response = await axios.get('/api/sales', { const res = await axios.get('/api/sales', {
headers: { headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }
Authorization: `Bearer ${localStorage.getItem("token")}`,
},
}) })
salesOptions.value = res.data.map(s => ({ value: s.id, label: s.nama }))
salesOptions.value = response.data.map(sales => ({ if (salesOptions.value.length > 0) selectedSales.value = salesOptions.value[0].value
value: sales.id, } catch (e) {
label: sales.nama console.error('Error fetching sales:', e)
}))
if (salesOptions.value.length > 0) {
selectedSales.value = salesOptions.value[0].value
}
} catch (error) {
console.error('Error fetching sales:', error)
} }
} }
// 🟢 Generate kode hanya saat menyimpan transaksi
const handleSimpan = () => { const handleSimpan = () => {
if (!namaPembeli.value.trim()) { if (!namaPembeli.value.trim()) return showSimpleToast('error', 'Nama pembeli harus diisi!')
showSimpleToast('error', 'Nama pembeli harus diisi!') if (!nomorTelepon.value.trim()) return showSimpleToast('error', 'Nomor telepon harus diisi!')
return if (!alamat.value.trim()) return showSimpleToast('error', 'Alamat harus diisi!')
} if (!selectedSales.value) return showSimpleToast('error', 'Sales harus dipilih!')
if (!nomorTelepon.value.trim()) { // Kode transaksi dibuat hanya saat simpan
showSimpleToast('error', 'Nomor telepon harus diisi!') transactionCode.value = generateTransactionCode()
return
}
if (!alamat.value.trim()) {
showSimpleToast('error', 'Alamat harus diisi!')
return
}
if (!selectedSales.value) {
showSimpleToast('error', 'Sales harus dipilih!')
return
}
simpanTransaksi({ simpanTransaksi({
kode_transaksi: transactionCode.value,
id_sales: selectedSales.value, id_sales: selectedSales.value,
nama_pembeli: namaPembeli.value, nama_pembeli: namaPembeli.value,
no_hp: nomorTelepon.value, no_hp: nomorTelepon.value,
@ -337,48 +285,37 @@ const handleSimpan = () => {
const simpanTransaksi = async (dataTransaksi) => { const simpanTransaksi = async (dataTransaksi) => {
if (isSaving.value) return if (isSaving.value) return
isSaving.value = true isSaving.value = true
try { try {
const response = await axios.post('/api/transaksi', dataTransaksi, { const res = await axios.post('/api/transaksi', dataTransaksi, {
headers: { headers: { Authorization: `Bearer ${localStorage.getItem("token")}` },
Authorization: `Bearer ${localStorage.getItem("token")}`, })
},
});
showSimpleToast('success', 'Transaksi berhasil disimpan!', 2000) showSimpleToast('success', 'Transaksi berhasil disimpan!', 2000)
// Emit event dengan data transaksi yang sudah disimpan
setTimeout(() => { setTimeout(() => {
emit('transaksi-saved', response.data); emit('transaksi-saved', res.data)
emit('close'); emit('close')
}, 2200); }, 2200)
} catch (err) {
} catch (error) { const msg = err.response?.data?.message || err.message || 'Terjadi kesalahan saat menyimpan transaksi'
console.error('Error saving transaksi:', error); showSimpleToast('error', `Error: ${msg}`, 4000)
const errorMessage = error.response?.data?.message || error.message || 'Terjadi kesalahan saat menyimpan transaksi';
showSimpleToast('error', `Error: ${errorMessage}`, 4000);
} finally { } finally {
isSaving.value = false isSaving.value = false
} }
}; }
onMounted(() => { onMounted(() => {
if (props.isOpen) { if (props.isOpen) fetchSales()
fetchSales()
}
}) })
function formatInput(e) { function formatInput(e) {
let value = e.target.value.replace(/\D/g, ""); let val = e.target.value.replace(/\D/g, "")
ongkosBikin.value = value ? parseInt(value, 10) : null; ongkosBikin.value = val ? parseInt(val, 10) : null
ongkosBikinFormatted.value = value ongkosBikinFormatted.value = val ? new Intl.NumberFormat("id-ID").format(val) : ""
? new Intl.NumberFormat("id-ID").format(value)
: "";
} }
</script> </script>
<style scoped> <style scoped>
@import url('https://fonts.googleapis.com/css2?family=PT+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=PT+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap');