Cash Bank List
This commit is contained in:
parent
00620026e4
commit
66589abdd4
@ -0,0 +1,7 @@
|
||||
import CashBankList from '@/views/apps/cash-bank/CashBankList'
|
||||
|
||||
const CashBankPage = () => {
|
||||
return <CashBankList />
|
||||
}
|
||||
|
||||
export default CashBankPage
|
||||
@ -116,6 +116,14 @@ const VerticalMenu = ({ dictionary, scrollMenu }: Props) => {
|
||||
<SubMenu label={dictionary['navigation'].expenses} icon={<i className='tabler-cash' />}>
|
||||
<MenuItem href={`/${locale}/apps/expense`}>{dictionary['navigation'].list}</MenuItem>
|
||||
</SubMenu>
|
||||
<MenuItem
|
||||
href={`/${locale}/apps/cash-bank`}
|
||||
icon={<i className='tabler-mail' />}
|
||||
exactMatch={false}
|
||||
activeUrl='/apps/cash-bank'
|
||||
>
|
||||
{dictionary['navigation'].cash_and_bank}
|
||||
</MenuItem>
|
||||
<SubMenu label={dictionary['navigation'].inventory} icon={<i className='tabler-salad' />}>
|
||||
<SubMenu label={dictionary['navigation'].products}>
|
||||
<MenuItem href={`/${locale}/apps/inventory/products/list`}>{dictionary['navigation'].list}</MenuItem>
|
||||
|
||||
@ -123,6 +123,7 @@
|
||||
"deliveries": "Deliveries",
|
||||
"sales_orders": "Orders",
|
||||
"quotes": "Quotes",
|
||||
"expenses": "Expenses"
|
||||
"expenses": "Expenses",
|
||||
"cash_and_bank": "Cash & Bank"
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,6 +123,7 @@
|
||||
"deliveries": "Pengiriman",
|
||||
"sales_orders": "Pemesanan",
|
||||
"quotes": "Penawaran",
|
||||
"expenses": "Biaya"
|
||||
"expenses": "Biaya",
|
||||
"cash_and_bank": "Kas & Bank"
|
||||
}
|
||||
}
|
||||
|
||||
263
src/views/apps/cash-bank/CashBankCard.tsx
Normal file
263
src/views/apps/cash-bank/CashBankCard.tsx
Normal file
@ -0,0 +1,263 @@
|
||||
'use client'
|
||||
|
||||
// Next Imports
|
||||
import dynamic from 'next/dynamic'
|
||||
|
||||
// MUI Imports
|
||||
import Card from '@mui/material/Card'
|
||||
import CardHeader from '@mui/material/CardHeader'
|
||||
import CardContent from '@mui/material/CardContent'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Box from '@mui/material/Box'
|
||||
import Button from '@mui/material/Button'
|
||||
|
||||
// Third-party Imports
|
||||
import type { ApexOptions } from 'apexcharts'
|
||||
|
||||
// Styled Component Imports
|
||||
const AppReactApexCharts = dynamic(() => import('@/libs/styles/AppReactApexCharts'))
|
||||
|
||||
// Types
|
||||
interface Balance {
|
||||
amount: string | number
|
||||
label: string
|
||||
}
|
||||
|
||||
interface ChartData {
|
||||
name: string
|
||||
data: number[]
|
||||
}
|
||||
|
||||
interface CashBankCardProps {
|
||||
title: string
|
||||
accountNumber: string
|
||||
balances: Balance[]
|
||||
chartData: ChartData[]
|
||||
categories: string[]
|
||||
buttonText?: string
|
||||
buttonIcon?: string
|
||||
onButtonClick?: () => void
|
||||
chartColor?: string
|
||||
height?: number
|
||||
currency?: 'IDR' | 'USD' | 'EUR'
|
||||
showButton?: boolean
|
||||
maxValue?: number
|
||||
enableHover?: boolean
|
||||
}
|
||||
|
||||
const CashBankCard = ({
|
||||
title,
|
||||
accountNumber,
|
||||
balances,
|
||||
chartData,
|
||||
categories,
|
||||
onButtonClick,
|
||||
chartColor = '#ff6b9d',
|
||||
height = 300,
|
||||
currency = 'IDR',
|
||||
showButton = true,
|
||||
maxValue,
|
||||
enableHover = true
|
||||
}: CashBankCardProps) => {
|
||||
// Vars
|
||||
const divider = 'var(--mui-palette-divider)'
|
||||
const disabledText = 'var(--mui-palette-text-disabled)'
|
||||
const primaryText = 'var(--mui-palette-text-primary)'
|
||||
|
||||
// Auto calculate maxValue if not provided
|
||||
const calculatedMaxValue = maxValue || Math.max(...chartData.flatMap(series => series.data)) * 1.2
|
||||
|
||||
// Currency formatter
|
||||
const formatCurrency = (value: number) => {
|
||||
const formatters = {
|
||||
IDR: new Intl.NumberFormat('id-ID', {
|
||||
style: 'currency',
|
||||
currency: 'IDR',
|
||||
minimumFractionDigits: 0
|
||||
}),
|
||||
USD: new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD',
|
||||
minimumFractionDigits: 0
|
||||
}),
|
||||
EUR: new Intl.NumberFormat('de-DE', {
|
||||
style: 'currency',
|
||||
currency: 'EUR',
|
||||
minimumFractionDigits: 0
|
||||
})
|
||||
}
|
||||
return formatters[currency].format(value)
|
||||
}
|
||||
|
||||
// Format balance display
|
||||
const formatBalance = (amount: string | number) => {
|
||||
if (typeof amount === 'string') return amount
|
||||
return new Intl.NumberFormat('id-ID').format(amount)
|
||||
}
|
||||
|
||||
// Y-axis label formatter based on currency
|
||||
const formatYAxisLabel = (val: number) => {
|
||||
if (currency === 'IDR') {
|
||||
return (val / 1000000).toFixed(0) + '.000.000'
|
||||
}
|
||||
return (val / 1000).toFixed(0) + 'K'
|
||||
}
|
||||
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
height: height,
|
||||
type: 'area',
|
||||
parentHeightOffset: 0,
|
||||
zoom: { enabled: false },
|
||||
toolbar: { show: false }
|
||||
},
|
||||
colors: [chartColor],
|
||||
fill: {
|
||||
type: 'gradient',
|
||||
gradient: {
|
||||
shade: 'light',
|
||||
type: 'vertical',
|
||||
shadeIntensity: 0.4,
|
||||
gradientToColors: [chartColor],
|
||||
inverseColors: false,
|
||||
opacityFrom: 0.8,
|
||||
opacityTo: 0.1,
|
||||
stops: [0, 100]
|
||||
}
|
||||
},
|
||||
stroke: {
|
||||
curve: 'smooth',
|
||||
width: 3
|
||||
},
|
||||
dataLabels: { enabled: false },
|
||||
grid: {
|
||||
show: true,
|
||||
borderColor: divider,
|
||||
strokeDashArray: 3,
|
||||
padding: {
|
||||
top: -10,
|
||||
bottom: -10,
|
||||
left: 20,
|
||||
right: 20
|
||||
},
|
||||
xaxis: {
|
||||
lines: { show: true }
|
||||
},
|
||||
yaxis: {
|
||||
lines: { show: true }
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
y: {
|
||||
formatter: function (val: number) {
|
||||
return formatCurrency(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
min: 0,
|
||||
max: calculatedMaxValue,
|
||||
tickAmount: 7,
|
||||
labels: {
|
||||
style: {
|
||||
colors: disabledText,
|
||||
fontSize: '12px',
|
||||
fontWeight: '400'
|
||||
},
|
||||
formatter: function (val: number) {
|
||||
return formatYAxisLabel(val)
|
||||
}
|
||||
}
|
||||
},
|
||||
xaxis: {
|
||||
axisBorder: { show: false },
|
||||
axisTicks: { show: false },
|
||||
crosshairs: {
|
||||
stroke: { color: divider }
|
||||
},
|
||||
labels: {
|
||||
style: {
|
||||
colors: disabledText,
|
||||
fontSize: '12px',
|
||||
fontWeight: '400'
|
||||
}
|
||||
},
|
||||
categories: categories
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Card
|
||||
sx={{
|
||||
height: '100%',
|
||||
transition: 'transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out',
|
||||
'&:hover': enableHover
|
||||
? {
|
||||
transform: 'translateY(-4px)',
|
||||
boxShadow: '0 12px 35px rgba(0, 0, 0, 0.15)'
|
||||
}
|
||||
: {},
|
||||
cursor: enableHover ? 'pointer' : 'default'
|
||||
}}
|
||||
>
|
||||
<CardHeader
|
||||
title={
|
||||
<Box>
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', mb: 2 }}>
|
||||
<Box>
|
||||
<Typography variant='h6' sx={{ fontWeight: 600, color: primaryText }}>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant='body2' sx={{ color: disabledText }}>
|
||||
{accountNumber}
|
||||
</Typography>
|
||||
</Box>
|
||||
{showButton && (
|
||||
<Button
|
||||
variant='contained'
|
||||
size='small'
|
||||
onClick={onButtonClick}
|
||||
className='bg-primary '
|
||||
sx={{
|
||||
textTransform: 'none',
|
||||
fontSize: '12px'
|
||||
}}
|
||||
>
|
||||
<i className='tabler-wallet text-sm mr-2' /> Atur Akun
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, mb: 3 }}>
|
||||
{balances.map((balance, index) => (
|
||||
<Box key={index}>
|
||||
<Typography variant='h4' sx={{ fontWeight: 700, color: primaryText }}>
|
||||
{formatBalance(balance.amount)}
|
||||
</Typography>
|
||||
<Typography variant='body2' sx={{ color: disabledText }}>
|
||||
{balance.label}
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
sx={{
|
||||
pb: 0,
|
||||
'& .MuiCardHeader-content': {
|
||||
width: '100%'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<CardContent sx={{ pt: 0 }}>
|
||||
<AppReactApexCharts type='area' width='100%' height={height} options={options} series={chartData} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default CashBankCard
|
||||
326
src/views/apps/cash-bank/CashBankList.tsx
Normal file
326
src/views/apps/cash-bank/CashBankList.tsx
Normal file
@ -0,0 +1,326 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useMemo, useEffect } from 'react'
|
||||
import Grid from '@mui/material/Grid2'
|
||||
import TextField, { TextFieldProps } from '@mui/material/TextField'
|
||||
import InputAdornment from '@mui/material/InputAdornment'
|
||||
import Box from '@mui/material/Box'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Chip from '@mui/material/Chip'
|
||||
import FormControl from '@mui/material/FormControl'
|
||||
import InputLabel from '@mui/material/InputLabel'
|
||||
import Select from '@mui/material/Select'
|
||||
import MenuItem from '@mui/material/MenuItem'
|
||||
import CashBankCard from './CashBankCard' // Adjust import path as needed
|
||||
import CustomTextField from '@/@core/components/mui/TextField'
|
||||
|
||||
// Types
|
||||
interface BankAccount {
|
||||
id: string
|
||||
title: string
|
||||
accountNumber: string
|
||||
balances: Array<{
|
||||
amount: string | number
|
||||
label: string
|
||||
}>
|
||||
chartData: Array<{
|
||||
name: string
|
||||
data: number[]
|
||||
}>
|
||||
categories: string[]
|
||||
chartColor?: string
|
||||
currency: 'IDR' | 'USD' | 'EUR'
|
||||
accountType: 'giro' | 'savings' | 'investment' | 'credit' | 'cash'
|
||||
bank: string
|
||||
status: 'active' | 'inactive' | 'blocked'
|
||||
}
|
||||
|
||||
// Dummy Data
|
||||
const dummyAccounts: BankAccount[] = [
|
||||
{
|
||||
id: '1',
|
||||
title: 'Giro',
|
||||
accountNumber: '1-10003',
|
||||
balances: [
|
||||
{ amount: '7.313.321', label: 'Saldo di bank' },
|
||||
{ amount: '30.631.261', label: 'Saldo di kledo' }
|
||||
],
|
||||
chartData: [
|
||||
{
|
||||
name: 'Saldo',
|
||||
data: [
|
||||
20000000, 21000000, 20500000, 20800000, 21500000, 22000000, 25000000, 26000000, 28000000, 29000000, 30000000,
|
||||
31000000
|
||||
]
|
||||
}
|
||||
],
|
||||
categories: ['Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des', 'Jan', 'Feb', 'Mar'],
|
||||
chartColor: '#ff6b9d',
|
||||
currency: 'IDR',
|
||||
accountType: 'giro',
|
||||
bank: 'Bank Mandiri',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: 'Tabungan Premium',
|
||||
accountNumber: 'SAV-001234',
|
||||
balances: [
|
||||
{ amount: 15420000, label: 'Saldo Tersedia' },
|
||||
{ amount: 18750000, label: 'Total Saldo' }
|
||||
],
|
||||
chartData: [
|
||||
{
|
||||
name: 'Balance',
|
||||
data: [
|
||||
12000000, 13500000, 14200000, 15000000, 15800000, 16200000, 17000000, 17500000, 18000000, 18200000, 18500000,
|
||||
18750000
|
||||
]
|
||||
}
|
||||
],
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'],
|
||||
chartColor: '#4285f4',
|
||||
currency: 'IDR',
|
||||
accountType: 'savings',
|
||||
bank: 'Bank BCA',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: 'Investment Portfolio',
|
||||
accountNumber: 'INV-789012',
|
||||
balances: [
|
||||
{ amount: 125000, label: 'Portfolio Value' },
|
||||
{ amount: 8750, label: 'Total Gains' }
|
||||
],
|
||||
chartData: [
|
||||
{
|
||||
name: 'Portfolio Value',
|
||||
data: [110000, 115000, 112000, 118000, 122000, 119000, 125000, 128000, 126000, 130000, 127000, 125000]
|
||||
}
|
||||
],
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
||||
currency: 'USD',
|
||||
accountType: 'investment',
|
||||
bank: 'Charles Schwab',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
title: 'Kartu Kredit Platinum',
|
||||
accountNumber: 'CC-456789',
|
||||
balances: [
|
||||
{ amount: 2500000, label: 'Saldo Saat Ini' },
|
||||
{ amount: 47500000, label: 'Limit Tersedia' }
|
||||
],
|
||||
chartData: [
|
||||
{
|
||||
name: 'Spending',
|
||||
data: [
|
||||
1200000, 1800000, 2200000, 1900000, 2100000, 2400000, 2800000, 2600000, 2300000, 2500000, 2700000, 2500000
|
||||
]
|
||||
}
|
||||
],
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'],
|
||||
currency: 'IDR',
|
||||
accountType: 'credit',
|
||||
bank: 'Bank BNI',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
title: 'Deposito Berjangka',
|
||||
accountNumber: 'DEP-334455',
|
||||
balances: [
|
||||
{ amount: 50000000, label: 'Pokok Deposito' },
|
||||
{ amount: 2500000, label: 'Bunga Terkumpul' }
|
||||
],
|
||||
chartData: [
|
||||
{
|
||||
name: 'Deposito Growth',
|
||||
data: [
|
||||
50000000, 50200000, 50420000, 50650000, 50880000, 51120000, 51360000, 51610000, 51860000, 52120000, 52380000,
|
||||
52500000
|
||||
]
|
||||
}
|
||||
],
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'],
|
||||
currency: 'IDR',
|
||||
accountType: 'savings',
|
||||
bank: 'Bank BRI',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
title: 'Cash Management',
|
||||
accountNumber: 'CSH-111222',
|
||||
balances: [{ amount: 5000, label: 'Available Cash' }],
|
||||
chartData: [
|
||||
{
|
||||
name: 'Cash Flow',
|
||||
data: [4000, 4500, 4200, 4800, 5200, 4900, 5000, 5300, 5100, 5400, 5200, 5000]
|
||||
}
|
||||
],
|
||||
categories: ['Q1', 'Q2', 'Q3', 'Q4', 'Q1', 'Q2', 'Q3', 'Q4', 'Q1', 'Q2', 'Q3', 'Q4'],
|
||||
chartColor: '#00bcd4',
|
||||
currency: 'USD',
|
||||
accountType: 'cash',
|
||||
bank: 'Wells Fargo',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
title: 'Rekening Bisnis',
|
||||
accountNumber: 'BIZ-998877',
|
||||
balances: [
|
||||
{ amount: 85000000, label: 'Saldo Operasional' },
|
||||
{ amount: 15000000, label: 'Dana Cadangan' }
|
||||
],
|
||||
chartData: [
|
||||
{
|
||||
name: 'Business Account',
|
||||
data: [
|
||||
70000000, 75000000, 80000000, 82000000, 85000000, 88000000, 90000000, 87000000, 85000000, 89000000, 92000000,
|
||||
100000000
|
||||
]
|
||||
}
|
||||
],
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'],
|
||||
chartColor: '#ff9800',
|
||||
currency: 'IDR',
|
||||
accountType: 'giro',
|
||||
bank: 'Bank Mandiri',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
title: 'Tabungan Pendidikan',
|
||||
accountNumber: 'EDU-567890',
|
||||
balances: [
|
||||
{ amount: 25000000, label: 'Dana Pendidikan' },
|
||||
{ amount: 3500000, label: 'Bunga Terkumpul' }
|
||||
],
|
||||
chartData: [
|
||||
{
|
||||
name: 'Education Savings',
|
||||
data: [
|
||||
20000000, 21000000, 22000000, 23000000, 24000000, 24500000, 25000000, 25500000, 26000000, 27000000, 28000000,
|
||||
28500000
|
||||
]
|
||||
}
|
||||
],
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'],
|
||||
chartColor: '#3f51b5',
|
||||
currency: 'IDR',
|
||||
accountType: 'savings',
|
||||
bank: 'Bank BCA',
|
||||
status: 'inactive'
|
||||
}
|
||||
]
|
||||
const DebouncedInput = ({
|
||||
value: initialValue,
|
||||
onChange,
|
||||
debounce = 500,
|
||||
...props
|
||||
}: {
|
||||
value: string | number
|
||||
onChange: (value: string | number) => void
|
||||
debounce?: number
|
||||
} & Omit<TextFieldProps, 'onChange'>) => {
|
||||
// States
|
||||
const [value, setValue] = useState(initialValue)
|
||||
|
||||
useEffect(() => {
|
||||
setValue(initialValue)
|
||||
}, [initialValue])
|
||||
|
||||
useEffect(() => {
|
||||
const timeout = setTimeout(() => {
|
||||
onChange(value)
|
||||
}, debounce)
|
||||
|
||||
return () => clearTimeout(timeout)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [value])
|
||||
|
||||
return <CustomTextField {...props} value={value} onChange={e => setValue(e.target.value)} />
|
||||
}
|
||||
const CashBankList = () => {
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
|
||||
// Handle button clicks
|
||||
const handleAccountAction = (accountId: string, action: string) => {
|
||||
console.log(`Action: ${action} for account: ${accountId}`)
|
||||
// Implement your action logic here
|
||||
}
|
||||
|
||||
// Filter and search logic
|
||||
const filteredAccounts = useMemo(() => {
|
||||
return dummyAccounts.filter(account => {
|
||||
const matchesSearch =
|
||||
account.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
account.accountNumber.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
account.bank.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
return matchesSearch
|
||||
})
|
||||
}, [searchQuery])
|
||||
|
||||
return (
|
||||
<Box sx={{ p: 3 }}>
|
||||
{/* Search and Filters */}
|
||||
<Box sx={{ mb: 4 }}>
|
||||
<Grid container spacing={2} sx={{ mb: 3 }}>
|
||||
<Grid size={{ xs: 12, md: 6 }}>
|
||||
<DebouncedInput
|
||||
value={searchQuery}
|
||||
onChange={value => setSearchQuery(value as string)}
|
||||
placeholder='Cari '
|
||||
className='max-sm:is-full'
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
{/* Account Cards */}
|
||||
<Grid container spacing={3}>
|
||||
{filteredAccounts.length > 0 ? (
|
||||
filteredAccounts.map(account => (
|
||||
<Grid key={account.id} size={{ xs: 12, lg: 6, xl: 4 }}>
|
||||
<CashBankCard
|
||||
title={account.title}
|
||||
accountNumber={account.accountNumber}
|
||||
balances={account.balances}
|
||||
chartData={account.chartData}
|
||||
categories={account.categories}
|
||||
chartColor={account.chartColor}
|
||||
currency={account.currency}
|
||||
showButton={account.accountType !== 'cash'}
|
||||
onButtonClick={() => handleAccountAction(account.id, account.accountType || 'default')}
|
||||
/>
|
||||
</Grid>
|
||||
))
|
||||
) : (
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<Box
|
||||
sx={{
|
||||
textAlign: 'center',
|
||||
py: 8,
|
||||
backgroundColor: 'grey.50',
|
||||
borderRadius: 2
|
||||
}}
|
||||
>
|
||||
<Typography variant='h6' color='text.secondary' gutterBottom>
|
||||
Tidak ada akun yang ditemukan
|
||||
</Typography>
|
||||
<Typography variant='body2' color='text.secondary'>
|
||||
Coba ubah kata kunci pencarian atau filter yang digunakan
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default CashBankList
|
||||
Loading…
x
Reference in New Issue
Block a user