diff --git a/src/app/[lang]/(dashboard)/(private)/apps/purchase/purchase-bills/[id]/detail/page.tsx b/src/app/[lang]/(dashboard)/(private)/apps/purchase/purchase-bills/[id]/detail/page.tsx
new file mode 100644
index 0000000..2b95d65
--- /dev/null
+++ b/src/app/[lang]/(dashboard)/(private)/apps/purchase/purchase-bills/[id]/detail/page.tsx
@@ -0,0 +1,18 @@
+import PurchaseDetailContent from '@/views/apps/purchase/purchase-detail/PurchaseDetailContent'
+import PurchaseDetailHeader from '@/views/apps/purchase/purchase-detail/PurchaseDetailHeader'
+import Grid from '@mui/material/Grid2'
+
+const PurchaseBillDetailPage = () => {
+ return (
+
+
+
+
+
+
+
+
+ )
+}
+
+export default PurchaseBillDetailPage
diff --git a/src/views/apps/purchase/purchase-bills/list/PurchaseBillListTable.tsx b/src/views/apps/purchase/purchase-bills/list/PurchaseBillListTable.tsx
index 09f9d44..199bc47 100644
--- a/src/views/apps/purchase/purchase-bills/list/PurchaseBillListTable.tsx
+++ b/src/views/apps/purchase/purchase-bills/list/PurchaseBillListTable.tsx
@@ -188,10 +188,6 @@ const PurchaseBillListTable = () => {
setOpenConfirm(false)
}
- const handleBillClick = (billId: string) => {
- console.log('Navigasi ke detail Bill:', billId)
- }
-
const handleStatusFilter = (status: string) => {
setStatusFilter(status)
}
@@ -227,7 +223,8 @@ const PurchaseBillListTable = () => {
variant='text'
color='primary'
className='p-0 min-w-0 font-medium normal-case justify-start'
- onClick={() => handleBillClick(row.original.id.toString())}
+ component={Link}
+ href={getLocalizedUrl(`/apps/purchase/purchase-bills/${row.original.number}/detail`, locale as Locale)}
sx={{
textTransform: 'none',
fontWeight: 500,
diff --git a/src/views/apps/purchase/purchase-detail/PurchaseDetailContent.tsx b/src/views/apps/purchase/purchase-detail/PurchaseDetailContent.tsx
new file mode 100644
index 0000000..391a0b3
--- /dev/null
+++ b/src/views/apps/purchase/purchase-detail/PurchaseDetailContent.tsx
@@ -0,0 +1,26 @@
+import Grid from '@mui/material/Grid2'
+import PurchaseDetailInformation from './PurchaseDetailInformation'
+import PurchaseDetailSendPayment from './PurchaseDetailSendPayment'
+import PurchaseDetailLog from './PurchaseDetailLog'
+import PurchaseDetailTransaction from './PurchaseDetailTransaction'
+
+const PurchaseDetailContent = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default PurchaseDetailContent
diff --git a/src/views/apps/purchase/purchase-detail/PurchaseDetailHeader.tsx b/src/views/apps/purchase/purchase-detail/PurchaseDetailHeader.tsx
new file mode 100644
index 0000000..26e56d9
--- /dev/null
+++ b/src/views/apps/purchase/purchase-detail/PurchaseDetailHeader.tsx
@@ -0,0 +1,19 @@
+import { Typography } from '@mui/material'
+
+interface Props {
+ title: string
+}
+
+const PurchaseDetailHeader = ({ title }: Props) => {
+ return (
+
+ )
+}
+
+export default PurchaseDetailHeader
diff --git a/src/views/apps/purchase/purchase-detail/PurchaseDetailInformation.tsx b/src/views/apps/purchase/purchase-detail/PurchaseDetailInformation.tsx
new file mode 100644
index 0000000..232b5c6
--- /dev/null
+++ b/src/views/apps/purchase/purchase-detail/PurchaseDetailInformation.tsx
@@ -0,0 +1,310 @@
+import React from 'react'
+import {
+ Card,
+ CardHeader,
+ CardContent,
+ Typography,
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+ Box,
+ Button,
+ IconButton
+} from '@mui/material'
+import Grid from '@mui/material/Grid2'
+
+interface Product {
+ produk: string
+ deskripsi: string
+ kuantitas: number
+ satuan: string
+ discount: string
+ harga: number
+ pajak: string
+ jumlah: number
+}
+
+interface PurchaseData {
+ vendor: string
+ nomor: string
+ tglTransaksi: string
+ tglJatuhTempo: string
+ gudang: string
+ status: string
+}
+
+const PurchaseDetailInformation: React.FC = () => {
+ const purchaseData: PurchaseData = {
+ vendor: 'Bagas Rizki Sihotang S.Farm Widodo',
+ nomor: 'PI/00053',
+ tglTransaksi: '08/09/2025',
+ tglJatuhTempo: '06/10/2025',
+ gudang: 'Unassigned',
+ status: 'Belum Dibayar'
+ }
+
+ const products: Product[] = [
+ {
+ produk: 'CB1 - Chelsea Boots',
+ deskripsi: 'Ukuran XS',
+ kuantitas: 3,
+ satuan: 'Pcs',
+ discount: '0%',
+ harga: 299000,
+ pajak: 'PPN',
+ jumlah: 897000
+ },
+ {
+ produk: 'CB1 - Chelsea Boots',
+ deskripsi: 'Ukuran M',
+ kuantitas: 1,
+ satuan: 'Pcs',
+ discount: '0%',
+ harga: 299000,
+ pajak: 'PPN',
+ jumlah: 299000
+ },
+ {
+ produk: 'KH1 - Kneel High Boots',
+ deskripsi: 'Ukuran XL',
+ kuantitas: 1,
+ satuan: 'Pcs',
+ discount: '0%',
+ harga: 299000,
+ pajak: 'PPN',
+ jumlah: 299000
+ }
+ ]
+
+ const totalKuantitas: number = products.reduce((sum, product) => sum + product.kuantitas, 0)
+ const subTotal: number = 1495000
+ const ppn: number = 98670
+ const total: number = 1593670
+ const sisaTagihan: number = 1593670
+
+ const formatCurrency = (amount: number): string => {
+ return new Intl.NumberFormat('id-ID').format(amount)
+ }
+
+ return (
+
+
+
+ Belum Dibayar
+
+
+ } variant='outlined' size='small' sx={{ mr: 1 }}>
+ Bagikan
+
+ } variant='outlined' size='small' sx={{ mr: 1 }}>
+ Print
+
+
+
+
+
+
+ }
+ />
+
+
+ {/* Purchase Information */}
+
+
+
+
+ Vendor
+
+
+ {purchaseData.vendor}
+
+
+
+
+
+ Tgl. Transaksi
+
+ {purchaseData.tglTransaksi}
+
+
+
+
+ Gudang
+
+
+ {purchaseData.gudang}
+
+
+
+
+
+
+
+ Nomor
+
+ {purchaseData.nomor}
+
+
+
+
+ Tgl. Jatuh Tempo
+
+ {purchaseData.tglJatuhTempo}
+
+
+
+
+ {/* Products Table */}
+
+
+
+
+ Produk
+ Deskripsi
+ Kuantitas
+ Satuan
+ Discount
+ Harga
+ Pajak
+ Jumlah
+
+
+
+ {products.map((product, index) => (
+
+
+
+ {product.produk}
+
+
+ {product.deskripsi}
+ {product.kuantitas}
+ {product.satuan}
+ {product.discount}
+ {formatCurrency(product.harga)}
+ {product.pajak}
+ {formatCurrency(product.jumlah)}
+
+ ))}
+
+ {/* Total Kuantitas Row */}
+
+
+ Total Kuantitas
+
+
+ {totalKuantitas}
+
+
+
+
+
+
+
+
+
+
+
+ {/* Summary Section */}
+
+
+ {/* Empty space for left side */}
+
+
+
+
+ Sub Total
+
+
+ {formatCurrency(subTotal)}
+
+
+
+
+
+ PPN
+
+
+ {formatCurrency(ppn)}
+
+
+
+
+
+ Total
+
+
+ {formatCurrency(total)}
+
+
+
+
+
+ Sisa Tagihan
+
+
+ {formatCurrency(sisaTagihan)}
+
+
+
+
+
+
+
+
+ )
+}
+
+export default PurchaseDetailInformation
diff --git a/src/views/apps/purchase/purchase-detail/PurchaseDetailLog.tsx b/src/views/apps/purchase/purchase-detail/PurchaseDetailLog.tsx
new file mode 100644
index 0000000..20711ac
--- /dev/null
+++ b/src/views/apps/purchase/purchase-detail/PurchaseDetailLog.tsx
@@ -0,0 +1,59 @@
+'use client'
+
+import React from 'react'
+import { Card, CardContent, CardHeader, Typography, Box, Link } from '@mui/material'
+
+interface LogEntry {
+ id: string
+ action: string
+ timestamp: string
+ user: string
+}
+
+const PurchaseDetailLog: React.FC = () => {
+ const logEntries: LogEntry[] = [
+ {
+ id: '1',
+ action: 'Terakhir diubah oleh',
+ timestamp: '08 Sep 2025 18:26',
+ user: 'pada'
+ }
+ ]
+
+ return (
+
+
+ Pantau log perubahan data
+
+ }
+ sx={{ pb: 1 }}
+ />
+
+ {logEntries.map(entry => (
+
+
+
+
+ {entry.action} {entry.user} {entry.timestamp}
+
+
+
+ ))}
+
+
+ )
+}
+
+export default PurchaseDetailLog
diff --git a/src/views/apps/purchase/purchase-detail/PurchaseDetailSendPayment.tsx b/src/views/apps/purchase/purchase-detail/PurchaseDetailSendPayment.tsx
new file mode 100644
index 0000000..6f64a4a
--- /dev/null
+++ b/src/views/apps/purchase/purchase-detail/PurchaseDetailSendPayment.tsx
@@ -0,0 +1,417 @@
+'use client'
+
+import React, { useState } from 'react'
+import {
+ Card,
+ CardContent,
+ Typography,
+ Button,
+ Box,
+ Accordion,
+ AccordionSummary,
+ AccordionDetails,
+ Tooltip,
+ IconButton,
+ CardHeader
+} from '@mui/material'
+import Grid from '@mui/material/Grid2'
+import CustomTextField from '@/@core/components/mui/TextField'
+import CustomAutocomplete from '@/@core/components/mui/Autocomplete'
+
+interface PaymentFormData {
+ totalDibayar: string
+ tglTransaksi: string
+ referensi: string
+ nomor: string
+ dibayarDari: string
+}
+
+interface PemotonganItem {
+ id: string
+ dipotong: string
+ persentase: string
+ nominal: string
+ tipe: 'persen' | 'rupiah'
+}
+
+const PurchaseDetailSendPayment: React.FC = () => {
+ const [formData, setFormData] = useState({
+ totalDibayar: '849.000',
+ tglTransaksi: '10/09/2025',
+ referensi: '',
+ nomor: 'PP/00025',
+ dibayarDari: '1-10001 Kas'
+ })
+
+ const [expanded, setExpanded] = useState(false)
+ const [pemotonganItems, setPemotonganItems] = useState([])
+
+ const dibayarDariOptions = [
+ { label: '1-10001 Kas', value: '1-10001 Kas' },
+ { label: '1-10002 Bank BCA', value: '1-10002 Bank BCA' },
+ { label: '1-10003 Bank Mandiri', value: '1-10003 Bank Mandiri' },
+ { label: '1-10004 Petty Cash', value: '1-10004 Petty Cash' }
+ ]
+
+ const pemotonganOptions = [
+ { label: 'PPN 11%', value: 'ppn' },
+ { label: 'PPh 21', value: 'pph21' },
+ { label: 'PPh 23', value: 'pph23' },
+ { label: 'Biaya Admin', value: 'admin' }
+ ]
+
+ const handleChange =
+ (field: keyof PaymentFormData) => (event: React.ChangeEvent | any) => {
+ setFormData(prev => ({
+ ...prev,
+ [field]: event.target.value
+ }))
+ }
+
+ const handleDibayarDariChange = (value: { label: string; value: string } | null) => {
+ setFormData(prev => ({
+ ...prev,
+ dibayarDari: value?.value || ''
+ }))
+ }
+
+ const addPemotongan = () => {
+ const newItem: PemotonganItem = {
+ id: Date.now().toString(),
+ dipotong: '',
+ persentase: '0',
+ nominal: '',
+ tipe: 'persen'
+ }
+ setPemotonganItems(prev => [...prev, newItem])
+ }
+
+ const removePemotongan = (id: string) => {
+ setPemotonganItems(prev => prev.filter(item => item.id !== id))
+ }
+
+ const updatePemotongan = (id: string, field: keyof PemotonganItem, value: string) => {
+ setPemotonganItems(prev => prev.map(item => (item.id === id ? { ...item, [field]: value } : item)))
+ }
+
+ const handleAccordionChange = () => {
+ setExpanded(!expanded)
+ }
+
+ const calculatePemotongan = (item: PemotonganItem): number => {
+ const totalDibayar = parseInt(formData.totalDibayar.replace(/\D/g, '')) || 0
+ const nilai = parseFloat(item.persentase) || 0
+
+ if (item.tipe === 'persen') {
+ return (totalDibayar * nilai) / 100
+ } else {
+ return nilai
+ }
+ }
+
+ const formatCurrency = (amount: string | number): string => {
+ const numAmount = typeof amount === 'string' ? parseInt(amount.replace(/\D/g, '')) : amount
+ return new Intl.NumberFormat('id-ID').format(numAmount)
+ }
+
+ return (
+
+
+
+ Kirim Pembayaran
+
+
+ }
+ />
+
+
+ {/* Left Column */}
+
+ {/* Total Dibayar */}
+
+
+ * Total Dibayar
+
+ }
+ value={formData.totalDibayar}
+ onChange={handleChange('totalDibayar')}
+ sx={{
+ '& .MuiInputBase-root': {
+ textAlign: 'right'
+ }
+ }}
+ />
+
+
+ {/* Tgl. Transaksi */}
+
+
+ * Tgl. Transaksi
+
+ }
+ type='date'
+ value={formData.tglTransaksi.split('/').reverse().join('-')}
+ onChange={handleChange('tglTransaksi')}
+ slotProps={{
+ input: {
+ endAdornment:
+ }
+ }}
+ />
+
+
+ {/* Referensi */}
+
+
+
+ Referensi
+
+
+
+
+
+
+
+
+
+
+ {/* Attachment Accordion */}
+
+
+ }
+ sx={{
+ backgroundColor: '#f8f9fa',
+ borderRadius: '8px',
+ minHeight: '48px',
+ '& .MuiAccordionSummary-content': {
+ margin: '12px 0'
+ }
+ }}
+ >
+
+ Attachment
+
+
+
+
+ Drag and drop files here or click to upload
+
+
+
+
+
+ {/* Right Column */}
+
+ {/* Nomor */}
+
+
+
+ Nomor
+
+
+
+
+
+
+
+
+
+
+ {/* Dibayar Dari */}
+
+
+ * Dibayar Dari
+
+ option.label || ''}
+ value={dibayarDariOptions.find(option => option.value === formData.dibayarDari) || null}
+ onChange={(_, value: { label: string; value: string } | null) => handleDibayarDariChange(value)}
+ renderInput={(params: any) => }
+ noOptionsText='Tidak ada pilihan'
+ />
+
+
+ {/* Empty space to match Referensi height */}
+ {/* Empty space */}
+
+ {/* Pemotongan Button - aligned with Attachment */}
+
+ }
+ variant='text'
+ color='primary'
+ sx={{ textTransform: 'none' }}
+ onClick={addPemotongan}
+ >
+ Pemotongan
+
+
+
+
+
+ {/* Pemotongan Items */}
+ {pemotonganItems.length > 0 && (
+
+ {pemotonganItems.map((item, index) => (
+
+
+
+ removePemotongan(item.id)}
+ sx={{
+ backgroundColor: '#fff',
+ border: '1px solid #f44336',
+ '&:hover': { backgroundColor: '#ffebee' }
+ }}
+ >
+
+
+
+
+
+ option.label || ''}
+ value={pemotonganOptions.find(option => option.value === item.dipotong) || null}
+ onChange={(_, value: { label: string; value: string } | null) =>
+ updatePemotongan(item.id, 'dipotong', value?.value || '')
+ }
+ renderInput={(params: any) => }
+ noOptionsText='Tidak ada pilihan'
+ />
+
+
+
+ updatePemotongan(item.id, 'persentase', e.target.value)}
+ placeholder='0'
+ sx={{
+ '& .MuiInputBase-root': {
+ textAlign: 'center'
+ }
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+ {formatCurrency(calculatePemotongan(item))}
+
+
+
+
+
+ ))}
+
+ )}
+
+ {/* Bottom Section */}
+
+
+ {/* Empty space */}
+
+
+
+ Total
+
+
+ {formatCurrency(formData.totalDibayar)}
+
+
+
+ }
+ fullWidth
+ sx={{
+ py: 1.5,
+ textTransform: 'none',
+ fontWeight: 'medium'
+ }}
+ >
+ Tambah Pembayaran
+
+
+
+
+
+
+ )
+}
+
+export default PurchaseDetailSendPayment
diff --git a/src/views/apps/purchase/purchase-detail/PurchaseDetailTransaction.tsx b/src/views/apps/purchase/purchase-detail/PurchaseDetailTransaction.tsx
new file mode 100644
index 0000000..8be85b5
--- /dev/null
+++ b/src/views/apps/purchase/purchase-detail/PurchaseDetailTransaction.tsx
@@ -0,0 +1,150 @@
+'use client'
+
+import React from 'react'
+import {
+ Card,
+ CardContent,
+ CardHeader,
+ Typography,
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+ Link,
+ Box
+} from '@mui/material'
+
+interface TransactionData {
+ id: string
+ tanggal: string
+ transaksi: string
+ nomor: string
+ tag: string
+ referensi: string
+ jumlah: number
+}
+
+const PurchaseDetailTransaction: React.FC = () => {
+ const transactions: TransactionData[] = [
+ {
+ id: '1',
+ tanggal: '10/09/2025',
+ transaksi: 'Pembayaran Pembelian',
+ nomor: 'PP/00024',
+ tag: '',
+ referensi: '',
+ jumlah: 1593670
+ }
+ ]
+
+ const formatCurrency = (amount: number): string => {
+ return new Intl.NumberFormat('id-ID').format(amount)
+ }
+
+ return (
+
+
+ Transaksi
+
+ }
+ sx={{ pb: 1 }}
+ />
+
+
+
+
+
+
+
+
+ Tanggal
+
+
+
+
+
+
+
+ Transaksi
+
+
+
+
+
+
+
+ Nomor
+
+
+
+
+
+
+ Tag
+
+
+
+
+ Referensi
+
+
+
+
+
+ Jumlah
+
+
+
+
+
+
+
+ {transactions.map(transaction => (
+
+
+ {transaction.tanggal}
+
+
+
+ {transaction.transaksi}
+
+
+
+ {transaction.nomor}
+
+
+ {transaction.tag || '-'}
+
+
+ {transaction.referensi || '-'}
+
+
+
+ {formatCurrency(transaction.jumlah)}
+
+
+
+ ))}
+
+
+
+
+
+ )
+}
+
+export default PurchaseDetailTransaction