'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 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 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' 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' } // 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) }) } const getChartColor = (accountType: string) => { const colors = { giro: '#ff6b9d', savings: '#4285f4', investment: '#00bcd4', credit: '#ff9800', cash: '#4caf50' } return colors[accountType as keyof typeof colors] || '#757575' } const DebouncedInput = ({ value: initialValue, onChange, debounce = 500, ...props }: { value: string | number onChange: (value: string | number) => void debounce?: number } & Omit) => { // 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 setValue(e.target.value)} /> } const CashBankList = () => { const [searchQuery, setSearchQuery] = useState('') const [editingAccount, setEditingAccount] = useState(null) const [addAccountOpen, setAddAccountOpen] = useState(false) const [data, setData] = useState([]) 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) } // 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(() => { 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 }) }, [transformedAccounts, searchQuery, accountsResponse]) return ( <> {/* Search and Filters */}
setSearchQuery(value as string)} placeholder='Cari akun...' className='max-sm:is-full' disabled={isLoading} InputProps={{ startAdornment: ( ) }} />
{/* Loading State */} {isLoading && ( )} {/* Account Cards */} {!isLoading && ( {filteredAccounts.length > 0 ? ( filteredAccounts.map(account => ( )) ) : ( {searchQuery ? 'Tidak ada akun yang ditemukan' : 'Belum ada akun'} {searchQuery ? 'Coba ubah kata kunci pencarian yang digunakan' : 'Mulai dengan menambahkan akun baru'} )} )} {/* Error State (if needed) */} {!isLoading && !accountsResponse && ( Terjadi kesalahan saat memuat data Silakan coba lagi atau hubungi administrator )}
) } export default CashBankList