efril #6
@ -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 (
|
||||
<Grid container spacing={6}>
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<PurchaseDetailHeader title='Detail Pesanan Pembelian' />
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<PurchaseDetailContent />
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
export default PurchaseBillDetailPage
|
||||
@ -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,
|
||||
|
||||
@ -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 (
|
||||
<Grid container spacing={6}>
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<PurchaseDetailInformation />
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<PurchaseDetailSendPayment />
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<PurchaseDetailTransaction />
|
||||
</Grid>
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<PurchaseDetailLog />
|
||||
</Grid>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
export default PurchaseDetailContent
|
||||
@ -0,0 +1,19 @@
|
||||
import { Typography } from '@mui/material'
|
||||
|
||||
interface Props {
|
||||
title: string
|
||||
}
|
||||
|
||||
const PurchaseDetailHeader = ({ title }: Props) => {
|
||||
return (
|
||||
<div className='flex flex-wrap sm:items-center justify-between max-sm:flex-col gap-6'>
|
||||
<div>
|
||||
<Typography variant='h4' className='mbe-1'>
|
||||
{title}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PurchaseDetailHeader
|
||||
@ -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 (
|
||||
<Card sx={{ width: '100%' }}>
|
||||
<CardHeader
|
||||
title={
|
||||
<Box display='flex' justifyContent='space-between' alignItems='center'>
|
||||
<Typography variant='h5' color='error' sx={{ fontWeight: 'bold' }}>
|
||||
Belum Dibayar
|
||||
</Typography>
|
||||
<Box>
|
||||
<Button startIcon={<i className='tabler-share' />} variant='outlined' size='small' sx={{ mr: 1 }}>
|
||||
Bagikan
|
||||
</Button>
|
||||
<Button startIcon={<i className='tabler-printer' />} variant='outlined' size='small' sx={{ mr: 1 }}>
|
||||
Print
|
||||
</Button>
|
||||
<IconButton>
|
||||
<i className='tabler-dots-vertical' />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
|
||||
<CardContent>
|
||||
{/* Purchase Information */}
|
||||
<Grid container spacing={3} sx={{ mb: 4 }}>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Box sx={{ mb: 2 }}>
|
||||
<Typography variant='subtitle2' color='text.secondary'>
|
||||
Vendor
|
||||
</Typography>
|
||||
<Typography variant='body1' color='primary' sx={{ fontWeight: 'medium', cursor: 'pointer' }}>
|
||||
{purchaseData.vendor}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ mb: 2 }}>
|
||||
<Typography variant='subtitle2' color='text.secondary'>
|
||||
Tgl. Transaksi
|
||||
</Typography>
|
||||
<Typography variant='body1'>{purchaseData.tglTransaksi}</Typography>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Typography variant='subtitle2' color='text.secondary'>
|
||||
Gudang
|
||||
</Typography>
|
||||
<Typography variant='body1' color='primary' sx={{ cursor: 'pointer' }}>
|
||||
{purchaseData.gudang}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Box sx={{ mb: 2 }}>
|
||||
<Typography variant='subtitle2' color='text.secondary'>
|
||||
Nomor
|
||||
</Typography>
|
||||
<Typography variant='body1'>{purchaseData.nomor}</Typography>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Typography variant='subtitle2' color='text.secondary'>
|
||||
Tgl. Jatuh Tempo
|
||||
</Typography>
|
||||
<Typography variant='body1'>{purchaseData.tglJatuhTempo}</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Products Table */}
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Produk</TableCell>
|
||||
<TableCell>Deskripsi</TableCell>
|
||||
<TableCell align='center'>Kuantitas</TableCell>
|
||||
<TableCell align='center'>Satuan</TableCell>
|
||||
<TableCell align='center'>Discount</TableCell>
|
||||
<TableCell align='right'>Harga</TableCell>
|
||||
<TableCell align='center'>Pajak</TableCell>
|
||||
<TableCell align='right'>Jumlah</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{products.map((product, index) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell>
|
||||
<Typography variant='body2' color='primary' sx={{ cursor: 'pointer' }}>
|
||||
{product.produk}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>{product.deskripsi}</TableCell>
|
||||
<TableCell align='center'>{product.kuantitas}</TableCell>
|
||||
<TableCell align='center'>{product.satuan}</TableCell>
|
||||
<TableCell align='center'>{product.discount}</TableCell>
|
||||
<TableCell align='right'>{formatCurrency(product.harga)}</TableCell>
|
||||
<TableCell align='center'>{product.pajak}</TableCell>
|
||||
<TableCell align='right'>{formatCurrency(product.jumlah)}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
|
||||
{/* Total Kuantitas Row */}
|
||||
<TableRow>
|
||||
<TableCell colSpan={2} sx={{ fontWeight: 'bold', borderTop: '2px solid #e0e0e0' }}>
|
||||
Total Kuantitas
|
||||
</TableCell>
|
||||
<TableCell align='center' sx={{ fontWeight: 'bold', borderTop: '2px solid #e0e0e0' }}>
|
||||
{totalKuantitas}
|
||||
</TableCell>
|
||||
<TableCell sx={{ borderTop: '2px solid #e0e0e0' }}></TableCell>
|
||||
<TableCell sx={{ borderTop: '2px solid #e0e0e0' }}></TableCell>
|
||||
<TableCell sx={{ borderTop: '2px solid #e0e0e0' }}></TableCell>
|
||||
<TableCell sx={{ borderTop: '2px solid #e0e0e0' }}></TableCell>
|
||||
<TableCell sx={{ borderTop: '2px solid #e0e0e0' }}></TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
|
||||
{/* Summary Section */}
|
||||
<Box sx={{ mt: 3 }}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid size={{ xs: 12, md: 6 }}>{/* Empty space for left side */}</Grid>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
py: 2,
|
||||
borderBottom: '1px solid #e0e0e0',
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.04)',
|
||||
transition: 'background-color 0.15s ease'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Typography variant='body1' sx={{ fontWeight: 'medium' }}>
|
||||
Sub Total
|
||||
</Typography>
|
||||
<Typography variant='body1' sx={{ fontWeight: 'medium' }}>
|
||||
{formatCurrency(subTotal)}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
py: 2,
|
||||
borderBottom: '1px solid #e0e0e0',
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.04)',
|
||||
transition: 'background-color 0.15s ease'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Typography variant='body1' sx={{ fontWeight: 'medium' }}>
|
||||
PPN
|
||||
</Typography>
|
||||
<Typography variant='body1' sx={{ fontWeight: 'medium' }}>
|
||||
{formatCurrency(ppn)}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
py: 2,
|
||||
borderBottom: '1px solid #e0e0e0',
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.04)',
|
||||
transition: 'background-color 0.15s ease'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Typography variant='body1' sx={{ fontWeight: 'bold' }}>
|
||||
Total
|
||||
</Typography>
|
||||
<Typography variant='body1' sx={{ fontWeight: 'bold' }}>
|
||||
{formatCurrency(total)}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
py: 2,
|
||||
'&:hover': {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.04)',
|
||||
transition: 'background-color 0.15s ease'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Typography variant='h6' sx={{ fontWeight: 'bold' }}>
|
||||
Sisa Tagihan
|
||||
</Typography>
|
||||
<Typography variant='h6' sx={{ fontWeight: 'bold' }}>
|
||||
{formatCurrency(sisaTagihan)}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default PurchaseDetailInformation
|
||||
@ -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 (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title={
|
||||
<Typography variant='h6' sx={{ fontWeight: 'bold' }}>
|
||||
Pantau log perubahan data
|
||||
</Typography>
|
||||
}
|
||||
sx={{ pb: 1 }}
|
||||
/>
|
||||
<CardContent sx={{ mt: 5 }}>
|
||||
{logEntries.map(entry => (
|
||||
<Box key={entry.id} sx={{ mb: 2 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<i className='tabler-edit' style={{ fontSize: '16px', color: '#1976d2' }} />
|
||||
<Link
|
||||
href='#'
|
||||
underline='hover'
|
||||
color='primary'
|
||||
sx={{
|
||||
textDecoration: 'none',
|
||||
'&:hover': {
|
||||
textDecoration: 'underline'
|
||||
}
|
||||
}}
|
||||
>
|
||||
{entry.action} {entry.user} {entry.timestamp}
|
||||
</Link>
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default PurchaseDetailLog
|
||||
@ -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<PaymentFormData>({
|
||||
totalDibayar: '849.000',
|
||||
tglTransaksi: '10/09/2025',
|
||||
referensi: '',
|
||||
nomor: 'PP/00025',
|
||||
dibayarDari: '1-10001 Kas'
|
||||
})
|
||||
|
||||
const [expanded, setExpanded] = useState<boolean>(false)
|
||||
const [pemotonganItems, setPemotonganItems] = useState<PemotonganItem[]>([])
|
||||
|
||||
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<HTMLInputElement | HTMLTextAreaElement> | 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 (
|
||||
<Card>
|
||||
<CardHeader
|
||||
title={
|
||||
<Box display='flex' justifyContent='space-between' alignItems='center'>
|
||||
<Typography variant='h5' color='error' sx={{ fontWeight: 'bold' }}>
|
||||
Kirim Pembayaran
|
||||
</Typography>
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
<CardContent>
|
||||
<Grid container spacing={3}>
|
||||
{/* Left Column */}
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
{/* Total Dibayar */}
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<CustomTextField
|
||||
fullWidth
|
||||
label={
|
||||
<span>
|
||||
<span style={{ color: 'red' }}>*</span> Total Dibayar
|
||||
</span>
|
||||
}
|
||||
value={formData.totalDibayar}
|
||||
onChange={handleChange('totalDibayar')}
|
||||
sx={{
|
||||
'& .MuiInputBase-root': {
|
||||
textAlign: 'right'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Tgl. Transaksi */}
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<CustomTextField
|
||||
fullWidth
|
||||
label={
|
||||
<span>
|
||||
<span style={{ color: 'red' }}>*</span> Tgl. Transaksi
|
||||
</span>
|
||||
}
|
||||
type='date'
|
||||
value={formData.tglTransaksi.split('/').reverse().join('-')}
|
||||
onChange={handleChange('tglTransaksi')}
|
||||
slotProps={{
|
||||
input: {
|
||||
endAdornment: <i className='tabler-calendar' style={{ color: '#666' }} />
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Referensi */}
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', mb: 1 }}>
|
||||
<Typography variant='body2' sx={{ color: 'text.secondary' }}>
|
||||
Referensi
|
||||
</Typography>
|
||||
<Tooltip title='Informasi referensi pembayaran'>
|
||||
<IconButton size='small' sx={{ ml: 0.5 }}>
|
||||
<i className='tabler-info-circle' style={{ fontSize: '16px', color: '#666' }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<CustomTextField
|
||||
fullWidth
|
||||
placeholder='Referensi'
|
||||
value={formData.referensi}
|
||||
onChange={handleChange('referensi')}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Attachment Accordion */}
|
||||
<Accordion
|
||||
expanded={expanded}
|
||||
onChange={handleAccordionChange}
|
||||
sx={{
|
||||
boxShadow: 'none',
|
||||
border: '1px solid #e0e0e0',
|
||||
borderRadius: '8px',
|
||||
'&:before': { display: 'none' }
|
||||
}}
|
||||
>
|
||||
<AccordionSummary
|
||||
expandIcon={
|
||||
<i
|
||||
className='tabler-chevron-right'
|
||||
style={{
|
||||
transform: expanded ? 'rotate(90deg)' : 'rotate(0deg)',
|
||||
transition: 'transform 0.2s'
|
||||
}}
|
||||
/>
|
||||
}
|
||||
sx={{
|
||||
backgroundColor: '#f8f9fa',
|
||||
borderRadius: '8px',
|
||||
minHeight: '48px',
|
||||
'& .MuiAccordionSummary-content': {
|
||||
margin: '12px 0'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Typography variant='body2' sx={{ fontWeight: 'medium' }}>
|
||||
Attachment
|
||||
</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails sx={{ p: 2 }}>
|
||||
<Typography variant='body2' color='text.secondary'>
|
||||
Drag and drop files here or click to upload
|
||||
</Typography>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</Grid>
|
||||
|
||||
{/* Right Column */}
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
{/* Nomor */}
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', mb: 1 }}>
|
||||
<Typography variant='body2' sx={{ color: 'text.secondary' }}>
|
||||
Nomor
|
||||
</Typography>
|
||||
<Tooltip title='Nomor pembayaran otomatis'>
|
||||
<IconButton size='small' sx={{ ml: 0.5 }}>
|
||||
<i className='tabler-info-circle' style={{ fontSize: '16px', color: '#666' }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<CustomTextField fullWidth value={formData.nomor} onChange={handleChange('nomor')} disabled />
|
||||
</Box>
|
||||
|
||||
{/* Dibayar Dari */}
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant='body2' sx={{ color: 'text.secondary', mb: 1 }}>
|
||||
<span style={{ color: 'red' }}>*</span> Dibayar Dari
|
||||
</Typography>
|
||||
<CustomAutocomplete
|
||||
fullWidth
|
||||
options={dibayarDariOptions}
|
||||
getOptionLabel={(option: { label: string; value: string }) => option.label || ''}
|
||||
value={dibayarDariOptions.find(option => option.value === formData.dibayarDari) || null}
|
||||
onChange={(_, value: { label: string; value: string } | null) => handleDibayarDariChange(value)}
|
||||
renderInput={(params: any) => <CustomTextField {...params} placeholder='Pilih akun pembayaran' />}
|
||||
noOptionsText='Tidak ada pilihan'
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Empty space to match Referensi height */}
|
||||
<Box sx={{ mb: 3, height: '74px' }}>{/* Empty space */}</Box>
|
||||
|
||||
{/* Pemotongan Button - aligned with Attachment */}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'flex-start',
|
||||
minHeight: '48px'
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
startIcon={<i className='tabler-plus' />}
|
||||
variant='text'
|
||||
color='primary'
|
||||
sx={{ textTransform: 'none' }}
|
||||
onClick={addPemotongan}
|
||||
>
|
||||
Pemotongan
|
||||
</Button>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Pemotongan Items */}
|
||||
{pemotonganItems.length > 0 && (
|
||||
<Box sx={{ mt: 3 }}>
|
||||
{pemotonganItems.map((item, index) => (
|
||||
<Box
|
||||
key={item.id}
|
||||
sx={{
|
||||
mb: 2,
|
||||
p: 2,
|
||||
border: '1px solid #e0e0e0',
|
||||
borderRadius: 1,
|
||||
position: 'relative'
|
||||
}}
|
||||
>
|
||||
<Grid container spacing={2} alignItems='center'>
|
||||
<Grid size={{ xs: 12, md: 1 }}>
|
||||
<IconButton
|
||||
color='error'
|
||||
size='small'
|
||||
onClick={() => removePemotongan(item.id)}
|
||||
sx={{
|
||||
backgroundColor: '#fff',
|
||||
border: '1px solid #f44336',
|
||||
'&:hover': { backgroundColor: '#ffebee' }
|
||||
}}
|
||||
>
|
||||
<i className='tabler-minus' style={{ fontSize: '16px' }} />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
|
||||
<Grid size={{ xs: 12, md: 4 }}>
|
||||
<CustomAutocomplete
|
||||
fullWidth
|
||||
options={pemotonganOptions}
|
||||
getOptionLabel={(option: { label: string; value: string }) => 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) => <CustomTextField {...params} placeholder='Pilih dipotong...' />}
|
||||
noOptionsText='Tidak ada pilihan'
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid size={{ xs: 12, md: 2 }}>
|
||||
<CustomTextField
|
||||
fullWidth
|
||||
value={item.persentase}
|
||||
onChange={e => updatePemotongan(item.id, 'persentase', e.target.value)}
|
||||
placeholder='0'
|
||||
sx={{
|
||||
'& .MuiInputBase-root': {
|
||||
textAlign: 'center'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid size={{ xs: 12, md: 1 }}>
|
||||
<Box sx={{ display: 'flex', gap: 0.5 }}>
|
||||
<Button
|
||||
variant={item.tipe === 'persen' ? 'contained' : 'outlined'}
|
||||
size='small'
|
||||
onClick={() => updatePemotongan(item.id, 'tipe', 'persen')}
|
||||
sx={{ minWidth: '40px', px: 1 }}
|
||||
>
|
||||
%
|
||||
</Button>
|
||||
<Button
|
||||
variant={item.tipe === 'rupiah' ? 'contained' : 'outlined'}
|
||||
size='small'
|
||||
onClick={() => updatePemotongan(item.id, 'tipe', 'rupiah')}
|
||||
sx={{ minWidth: '40px', px: 1 }}
|
||||
>
|
||||
Rp
|
||||
</Button>
|
||||
</Box>
|
||||
</Grid>
|
||||
|
||||
<Grid size={{ xs: 12, md: 4 }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center' }}>
|
||||
<Typography variant='h6' sx={{ fontWeight: 'bold' }}>
|
||||
{formatCurrency(calculatePemotongan(item))}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Bottom Section */}
|
||||
<Box sx={{ mt: 4, pt: 3, borderTop: '1px solid #e0e0e0' }}>
|
||||
<Grid container spacing={2} alignItems='center'>
|
||||
<Grid size={{ xs: 12, md: 6 }}>{/* Empty space */}</Grid>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
|
||||
<Typography variant='h6' sx={{ fontWeight: 'bold' }}>
|
||||
Total
|
||||
</Typography>
|
||||
<Typography variant='h6' sx={{ fontWeight: 'bold' }}>
|
||||
{formatCurrency(formData.totalDibayar)}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Button
|
||||
variant='contained'
|
||||
startIcon={<i className='tabler-plus' />}
|
||||
fullWidth
|
||||
sx={{
|
||||
py: 1.5,
|
||||
textTransform: 'none',
|
||||
fontWeight: 'medium'
|
||||
}}
|
||||
>
|
||||
Tambah Pembayaran
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default PurchaseDetailSendPayment
|
||||
@ -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 (
|
||||
<Card sx={{ width: '100%' }}>
|
||||
<CardHeader
|
||||
title={
|
||||
<Typography variant='h6' sx={{ fontWeight: 'bold' }}>
|
||||
Transaksi
|
||||
</Typography>
|
||||
}
|
||||
sx={{ pb: 1 }}
|
||||
/>
|
||||
<CardContent>
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||
<Typography variant='body2' sx={{ fontWeight: 'medium' }}>
|
||||
Tanggal
|
||||
</Typography>
|
||||
<i className='tabler-chevron-up' style={{ fontSize: '14px', color: '#666' }} />
|
||||
</Box>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||
<Typography variant='body2' sx={{ fontWeight: 'medium' }}>
|
||||
Transaksi
|
||||
</Typography>
|
||||
<i className='tabler-chevron-up' style={{ fontSize: '14px', color: '#666' }} />
|
||||
</Box>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||
<Typography variant='body2' sx={{ fontWeight: 'medium' }}>
|
||||
Nomor
|
||||
</Typography>
|
||||
<i className='tabler-chevron-up' style={{ fontSize: '14px', color: '#666' }} />
|
||||
</Box>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography variant='body2' sx={{ fontWeight: 'medium' }}>
|
||||
Tag
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography variant='body2' sx={{ fontWeight: 'medium' }}>
|
||||
Referensi
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell align='right'>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 0.5 }}>
|
||||
<Typography variant='body2' sx={{ fontWeight: 'medium' }}>
|
||||
Jumlah
|
||||
</Typography>
|
||||
<i className='tabler-chevron-up' style={{ fontSize: '14px', color: '#666' }} />
|
||||
</Box>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{transactions.map(transaction => (
|
||||
<TableRow key={transaction.id}>
|
||||
<TableCell>
|
||||
<Typography variant='body2'>{transaction.tanggal}</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Link
|
||||
href='#'
|
||||
underline='hover'
|
||||
color='primary'
|
||||
sx={{
|
||||
textDecoration: 'none',
|
||||
'&:hover': {
|
||||
textDecoration: 'underline'
|
||||
}
|
||||
}}
|
||||
>
|
||||
{transaction.transaksi}
|
||||
</Link>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography variant='body2'>{transaction.nomor}</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography variant='body2'>{transaction.tag || '-'}</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography variant='body2'>{transaction.referensi || '-'}</Typography>
|
||||
</TableCell>
|
||||
<TableCell align='right'>
|
||||
<Typography variant='body2' sx={{ fontWeight: 'medium' }}>
|
||||
{formatCurrency(transaction.jumlah)}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default PurchaseDetailTransaction
|
||||
Loading…
x
Reference in New Issue
Block a user