Cash Bank List
This commit is contained in:
parent
b2840ca27c
commit
20203942d2
@ -11,16 +11,18 @@ 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 CircularProgress from '@mui/material/CircularProgress'
|
||||
import CashBankCard from './CashBankCard' // Adjust import path as needed
|
||||
import CustomTextField from '@/@core/components/mui/TextField'
|
||||
import { getLocalizedUrl } from '@/utils/i18n'
|
||||
import { Locale } from '@/configs/i18n'
|
||||
import { useParams } from 'next/navigation'
|
||||
import AccountFormDrawer, { AccountType } from '../account/AccountFormDrawer'
|
||||
import { accountsData } from '../account/AccountListTable'
|
||||
import AccountFormDrawer from '../account/AccountFormDrawer'
|
||||
import { Button } from '@mui/material'
|
||||
import { Account } from '@/types/services/chartOfAccount'
|
||||
import { useAccounts } from '@/services/queries/account'
|
||||
import { formatCurrency } from '@/utils/transform'
|
||||
|
||||
// Types
|
||||
interface BankAccount {
|
||||
id: string
|
||||
title: string
|
||||
@ -41,188 +43,28 @@ interface BankAccount {
|
||||
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
|
||||
]
|
||||
// Static chart data for fallback/demo purposes
|
||||
const generateChartData = (accountType: string, balance: number) => {
|
||||
const baseValue = balance || 1000000
|
||||
const variation = baseValue * 0.2
|
||||
|
||||
return Array.from({ length: 12 }, (_, i) => {
|
||||
const randomVariation = (Math.random() - 0.5) * variation
|
||||
return Math.max(baseValue + randomVariation, baseValue * 0.5)
|
||||
})
|
||||
}
|
||||
],
|
||||
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
|
||||
]
|
||||
|
||||
const getChartColor = (accountType: string) => {
|
||||
const colors = {
|
||||
giro: '#ff6b9d',
|
||||
savings: '#4285f4',
|
||||
investment: '#00bcd4',
|
||||
credit: '#ff9800',
|
||||
cash: '#4caf50'
|
||||
}
|
||||
],
|
||||
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]
|
||||
return colors[accountType as keyof typeof colors] || '#757575'
|
||||
}
|
||||
],
|
||||
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,
|
||||
@ -251,28 +93,122 @@ const DebouncedInput = ({
|
||||
|
||||
return <CustomTextField {...props} value={value} onChange={e => setValue(e.target.value)} />
|
||||
}
|
||||
|
||||
const CashBankList = () => {
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
const [editingAccount, setEditingAccount] = useState<AccountType | null>(null)
|
||||
const [editingAccount, setEditingAccount] = useState<Account | null>(null)
|
||||
const [addAccountOpen, setAddAccountOpen] = useState(false)
|
||||
const [data, setData] = useState<AccountType[]>(accountsData)
|
||||
const [data, setData] = useState<Account[]>([])
|
||||
const { lang: locale } = useParams()
|
||||
|
||||
// Use the accounts hook with search parameter
|
||||
const { data: accountsResponse, isLoading } = useAccounts({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
search: searchQuery
|
||||
})
|
||||
|
||||
const handleCloseDrawer = () => {
|
||||
setAddAccountOpen(false)
|
||||
setEditingAccount(null)
|
||||
}
|
||||
|
||||
// Filter and search logic
|
||||
// Transform API data to match our BankAccount interface
|
||||
const transformedAccounts = useMemo((): BankAccount[] => {
|
||||
if (!accountsResponse?.data) return []
|
||||
|
||||
return accountsResponse.data.map((account: Account) => {
|
||||
const chartData = generateChartData(account.account_type, account.current_balance)
|
||||
|
||||
// Map account type to display type
|
||||
const typeMapping = {
|
||||
current_asset: 'giro' as const,
|
||||
non_current_asset: 'investment' as const,
|
||||
current_liability: 'credit' as const,
|
||||
non_current_liability: 'credit' as const,
|
||||
other_current_asset: 'cash' as const,
|
||||
other_current_liability: 'credit' as const,
|
||||
equity: 'savings' as const,
|
||||
revenue: 'savings' as const,
|
||||
expense: 'cash' as const
|
||||
}
|
||||
const displayAccountType = typeMapping[account.account_type as keyof typeof typeMapping] || 'giro'
|
||||
|
||||
// Get bank name from account
|
||||
const getBankName = (acc: Account): string => {
|
||||
if (acc.chart_of_account?.name) {
|
||||
return acc.chart_of_account.name
|
||||
}
|
||||
|
||||
const typeToBank = {
|
||||
current_asset: 'Bank Account',
|
||||
non_current_asset: 'Investment Account',
|
||||
current_liability: 'Credit Account',
|
||||
other_current_asset: 'Cash Account',
|
||||
equity: 'Equity Account',
|
||||
revenue: 'Revenue Account',
|
||||
expense: 'Expense Account'
|
||||
}
|
||||
|
||||
return typeToBank[acc.account_type as keyof typeof typeToBank] || 'General Account'
|
||||
}
|
||||
|
||||
// Create balance information
|
||||
const balances = []
|
||||
|
||||
if (account.current_balance !== account.opening_balance) {
|
||||
balances.push({
|
||||
amount: formatCurrency(account.current_balance),
|
||||
label: 'Saldo Saat Ini'
|
||||
})
|
||||
balances.push({
|
||||
amount: formatCurrency(account.opening_balance),
|
||||
label: 'Saldo Awal'
|
||||
})
|
||||
} else {
|
||||
balances.push({
|
||||
amount: formatCurrency(account.current_balance),
|
||||
label: 'Saldo'
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
id: account.id,
|
||||
title: account.name,
|
||||
accountNumber: account.number,
|
||||
balances,
|
||||
chartData: [
|
||||
{
|
||||
name: 'Saldo',
|
||||
data: chartData
|
||||
}
|
||||
],
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'],
|
||||
chartColor: getChartColor(account.account_type),
|
||||
currency: 'IDR', // Assuming IDR as default, adjust as needed
|
||||
accountType: displayAccountType,
|
||||
bank: getBankName(account),
|
||||
status: account.is_active ? 'active' : 'inactive'
|
||||
}
|
||||
})
|
||||
}, [accountsResponse])
|
||||
|
||||
// Filter accounts based on search (if not handled by API)
|
||||
const filteredAccounts = useMemo(() => {
|
||||
return dummyAccounts.filter(account => {
|
||||
if (!searchQuery || accountsResponse) {
|
||||
// If using API search or no search, return transformed accounts as is
|
||||
return transformedAccounts
|
||||
}
|
||||
|
||||
// Local filtering fallback
|
||||
return transformedAccounts.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])
|
||||
}, [transformedAccounts, searchQuery, accountsResponse])
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -283,8 +219,16 @@ const CashBankList = () => {
|
||||
<DebouncedInput
|
||||
value={searchQuery}
|
||||
onChange={value => setSearchQuery(value as string)}
|
||||
placeholder='Cari '
|
||||
placeholder='Cari akun...'
|
||||
className='max-sm:is-full'
|
||||
disabled={isLoading}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position='start'>
|
||||
<i className='tabler-search' />
|
||||
</InputAdornment>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Box>
|
||||
<Button
|
||||
@ -295,6 +239,7 @@ const CashBankList = () => {
|
||||
setEditingAccount(null)
|
||||
setAddAccountOpen(true)
|
||||
}}
|
||||
disabled={isLoading}
|
||||
>
|
||||
Tambah Akun
|
||||
</Button>
|
||||
@ -302,7 +247,15 @@ const CashBankList = () => {
|
||||
</div>
|
||||
</Box>
|
||||
|
||||
{/* Loading State */}
|
||||
{isLoading && (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', py: 8 }}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Account Cards */}
|
||||
{!isLoading && (
|
||||
<Grid container spacing={3}>
|
||||
{filteredAccounts.length > 0 ? (
|
||||
filteredAccounts.map(account => (
|
||||
@ -331,16 +284,40 @@ const CashBankList = () => {
|
||||
}}
|
||||
>
|
||||
<Typography variant='h6' color='text.secondary' gutterBottom>
|
||||
Tidak ada akun yang ditemukan
|
||||
{searchQuery ? 'Tidak ada akun yang ditemukan' : 'Belum ada akun'}
|
||||
</Typography>
|
||||
<Typography variant='body2' color='text.secondary'>
|
||||
Coba ubah kata kunci pencarian atau filter yang digunakan
|
||||
{searchQuery
|
||||
? 'Coba ubah kata kunci pencarian yang digunakan'
|
||||
: 'Mulai dengan menambahkan akun baru'}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{/* Error State (if needed) */}
|
||||
{!isLoading && !accountsResponse && (
|
||||
<Grid size={{ xs: 12 }}>
|
||||
<Box
|
||||
sx={{
|
||||
textAlign: 'center',
|
||||
py: 8,
|
||||
backgroundColor: 'error.light',
|
||||
borderRadius: 2,
|
||||
color: 'error.contrastText'
|
||||
}}
|
||||
>
|
||||
<Typography variant='h6' gutterBottom>
|
||||
Terjadi kesalahan saat memuat data
|
||||
</Typography>
|
||||
<Typography variant='body2'>Silakan coba lagi atau hubungi administrator</Typography>
|
||||
</Box>
|
||||
</Grid>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<AccountFormDrawer
|
||||
open={addAccountOpen}
|
||||
handleClose={handleCloseDrawer}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user