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' />}>
|
<SubMenu label={dictionary['navigation'].expenses} icon={<i className='tabler-cash' />}>
|
||||||
<MenuItem href={`/${locale}/apps/expense`}>{dictionary['navigation'].list}</MenuItem>
|
<MenuItem href={`/${locale}/apps/expense`}>{dictionary['navigation'].list}</MenuItem>
|
||||||
</SubMenu>
|
</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'].inventory} icon={<i className='tabler-salad' />}>
|
||||||
<SubMenu label={dictionary['navigation'].products}>
|
<SubMenu label={dictionary['navigation'].products}>
|
||||||
<MenuItem href={`/${locale}/apps/inventory/products/list`}>{dictionary['navigation'].list}</MenuItem>
|
<MenuItem href={`/${locale}/apps/inventory/products/list`}>{dictionary['navigation'].list}</MenuItem>
|
||||||
|
|||||||
@ -123,6 +123,7 @@
|
|||||||
"deliveries": "Deliveries",
|
"deliveries": "Deliveries",
|
||||||
"sales_orders": "Orders",
|
"sales_orders": "Orders",
|
||||||
"quotes": "Quotes",
|
"quotes": "Quotes",
|
||||||
"expenses": "Expenses"
|
"expenses": "Expenses",
|
||||||
|
"cash_and_bank": "Cash & Bank"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -123,6 +123,7 @@
|
|||||||
"deliveries": "Pengiriman",
|
"deliveries": "Pengiriman",
|
||||||
"sales_orders": "Pemesanan",
|
"sales_orders": "Pemesanan",
|
||||||
"quotes": "Penawaran",
|
"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