|
|
|
@@ -41,6 +41,11 @@ import TablePaginationComponent from '@/components/TablePaginationComponent'
|
|
|
|
|
import Loading from '@/components/layout/shared/Loading'
|
|
|
|
|
import { getLocalizedUrl } from '@/utils/i18n'
|
|
|
|
|
import AccountFormDrawer from './AccountFormDrawer'
|
|
|
|
|
import { useChartOfAccount } from '@/services/queries/chartOfAccount'
|
|
|
|
|
import { Account, ChartOfAccount } from '@/types/services/chartOfAccount'
|
|
|
|
|
import { useAccounts } from '@/services/queries/account'
|
|
|
|
|
import { formatCurrency } from '@/utils/transform'
|
|
|
|
|
import { useChartOfAccountTypes } from '@/services/queries/chartOfAccountType'
|
|
|
|
|
|
|
|
|
|
// Account Type
|
|
|
|
|
export type AccountType = {
|
|
|
|
@@ -60,119 +65,10 @@ declare module '@tanstack/table-core' {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type AccountTypeWithAction = AccountType & {
|
|
|
|
|
type AccountTypeWithAction = Account & {
|
|
|
|
|
actions?: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Dummy Account Data
|
|
|
|
|
export const accountsData: AccountType[] = [
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
code: '1-10001',
|
|
|
|
|
name: 'Kas',
|
|
|
|
|
category: 'Kas & Bank',
|
|
|
|
|
balance: '20000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 2,
|
|
|
|
|
code: '1-10002',
|
|
|
|
|
name: 'Bank BCA',
|
|
|
|
|
category: 'Kas & Bank',
|
|
|
|
|
balance: '150000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 3,
|
|
|
|
|
code: '1-10003',
|
|
|
|
|
name: 'Bank Mandiri',
|
|
|
|
|
category: 'Kas & Bank',
|
|
|
|
|
balance: '75000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 4,
|
|
|
|
|
code: '1-10101',
|
|
|
|
|
name: 'Piutang Usaha',
|
|
|
|
|
category: 'Piutang',
|
|
|
|
|
balance: '50000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 5,
|
|
|
|
|
code: '1-10102',
|
|
|
|
|
name: 'Piutang Karyawan',
|
|
|
|
|
category: 'Piutang',
|
|
|
|
|
balance: '5000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 6,
|
|
|
|
|
code: '1-10201',
|
|
|
|
|
name: 'Persediaan Barang',
|
|
|
|
|
category: 'Persediaan',
|
|
|
|
|
balance: '100000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 7,
|
|
|
|
|
code: '1-10301',
|
|
|
|
|
name: 'Peralatan Kantor',
|
|
|
|
|
category: 'Aset Tetap',
|
|
|
|
|
balance: '25000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 8,
|
|
|
|
|
code: '1-10302',
|
|
|
|
|
name: 'Kendaraan',
|
|
|
|
|
category: 'Aset Tetap',
|
|
|
|
|
balance: '200000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 9,
|
|
|
|
|
code: '2-20001',
|
|
|
|
|
name: 'Hutang Usaha',
|
|
|
|
|
category: 'Hutang',
|
|
|
|
|
balance: '-30000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 10,
|
|
|
|
|
code: '2-20002',
|
|
|
|
|
name: 'Hutang Gaji',
|
|
|
|
|
category: 'Hutang',
|
|
|
|
|
balance: '-15000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 11,
|
|
|
|
|
code: '3-30001',
|
|
|
|
|
name: 'Modal Pemilik',
|
|
|
|
|
category: 'Ekuitas',
|
|
|
|
|
balance: '500000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 12,
|
|
|
|
|
code: '4-40001',
|
|
|
|
|
name: 'Penjualan',
|
|
|
|
|
category: 'Pendapatan',
|
|
|
|
|
balance: '250000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 13,
|
|
|
|
|
code: '5-50001',
|
|
|
|
|
name: 'Beban Gaji',
|
|
|
|
|
category: 'Beban',
|
|
|
|
|
balance: '-80000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 14,
|
|
|
|
|
code: '5-50002',
|
|
|
|
|
name: 'Beban Listrik',
|
|
|
|
|
category: 'Beban',
|
|
|
|
|
balance: '-5000000'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 15,
|
|
|
|
|
code: '5-50003',
|
|
|
|
|
name: 'Beban Telepon',
|
|
|
|
|
category: 'Beban',
|
|
|
|
|
balance: '-2000000'
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// Styled Components
|
|
|
|
|
const Icon = styled('i')({})
|
|
|
|
|
|
|
|
|
@@ -242,16 +138,6 @@ const getCategoryColor = (category: string) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Format currency
|
|
|
|
|
const formatCurrency = (amount: string) => {
|
|
|
|
|
const numAmount = parseInt(amount)
|
|
|
|
|
return new Intl.NumberFormat('id-ID', {
|
|
|
|
|
style: 'currency',
|
|
|
|
|
currency: 'IDR',
|
|
|
|
|
minimumFractionDigits: 0
|
|
|
|
|
}).format(Math.abs(numAmount))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Column Definitions
|
|
|
|
|
const columnHelper = createColumnHelper<AccountTypeWithAction>()
|
|
|
|
|
|
|
|
|
@@ -261,53 +147,25 @@ const AccountListTable = () => {
|
|
|
|
|
// States
|
|
|
|
|
const [addAccountOpen, setAddAccountOpen] = useState(false)
|
|
|
|
|
const [rowSelection, setRowSelection] = useState({})
|
|
|
|
|
const [currentPage, setCurrentPage] = useState(0)
|
|
|
|
|
const [currentPage, setCurrentPage] = useState(1)
|
|
|
|
|
const [pageSize, setPageSize] = useState(10)
|
|
|
|
|
const [openConfirm, setOpenConfirm] = useState(false)
|
|
|
|
|
const [accountId, setAccountId] = useState('')
|
|
|
|
|
const [search, setSearch] = useState('')
|
|
|
|
|
const [categoryFilter, setCategoryFilter] = useState<string>('Semua')
|
|
|
|
|
const [filteredData, setFilteredData] = useState<AccountType[]>(accountsData)
|
|
|
|
|
const [data, setData] = useState<AccountType[]>(accountsData)
|
|
|
|
|
const [editingAccount, setEditingAccount] = useState<AccountType | null>(null)
|
|
|
|
|
const [editingAccount, setEditingAccount] = useState<Account | null>(null)
|
|
|
|
|
|
|
|
|
|
const { data, isLoading } = useAccounts({
|
|
|
|
|
page: currentPage,
|
|
|
|
|
limit: pageSize,
|
|
|
|
|
search
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Hooks
|
|
|
|
|
const { lang: locale } = useParams()
|
|
|
|
|
|
|
|
|
|
// Get unique categories for filter
|
|
|
|
|
const categories = useMemo(() => {
|
|
|
|
|
const uniqueCategories = [...new Set(data.map(account => account.category))]
|
|
|
|
|
return ['Semua', ...uniqueCategories]
|
|
|
|
|
}, [data])
|
|
|
|
|
|
|
|
|
|
// Filter data based on search and category
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
let filtered = data
|
|
|
|
|
|
|
|
|
|
// Filter by search
|
|
|
|
|
if (search) {
|
|
|
|
|
filtered = filtered.filter(
|
|
|
|
|
account =>
|
|
|
|
|
account.code.toLowerCase().includes(search.toLowerCase()) ||
|
|
|
|
|
account.name.toLowerCase().includes(search.toLowerCase()) ||
|
|
|
|
|
account.category.toLowerCase().includes(search.toLowerCase())
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Filter by category
|
|
|
|
|
if (categoryFilter !== 'Semua') {
|
|
|
|
|
filtered = filtered.filter(account => account.category === categoryFilter)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setFilteredData(filtered)
|
|
|
|
|
setCurrentPage(0)
|
|
|
|
|
}, [search, categoryFilter, data])
|
|
|
|
|
|
|
|
|
|
const totalCount = filteredData.length
|
|
|
|
|
const paginatedData = useMemo(() => {
|
|
|
|
|
const startIndex = currentPage * pageSize
|
|
|
|
|
return filteredData.slice(startIndex, startIndex + pageSize)
|
|
|
|
|
}, [filteredData, currentPage, pageSize])
|
|
|
|
|
const accounts = data?.data ?? []
|
|
|
|
|
const totalCount = data?.total ?? 0
|
|
|
|
|
|
|
|
|
|
const handlePageChange = useCallback((event: unknown, newPage: number) => {
|
|
|
|
|
setCurrentPage(newPage)
|
|
|
|
@@ -319,12 +177,8 @@ const AccountListTable = () => {
|
|
|
|
|
setCurrentPage(0)
|
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
const handleDelete = () => {
|
|
|
|
|
setOpenConfirm(false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle row click for edit
|
|
|
|
|
const handleRowClick = (account: AccountType, event: React.MouseEvent) => {
|
|
|
|
|
const handleRowClick = (account: Account, event: React.MouseEvent) => {
|
|
|
|
|
// Don't trigger row click if clicking on checkbox or link
|
|
|
|
|
const target = event.target as HTMLElement
|
|
|
|
|
if (target.closest('input[type="checkbox"]') || target.closest('a') || target.closest('button')) {
|
|
|
|
@@ -365,7 +219,7 @@ const AccountListTable = () => {
|
|
|
|
|
/>
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
columnHelper.accessor('code', {
|
|
|
|
|
columnHelper.accessor('number', {
|
|
|
|
|
header: 'Kode Akun',
|
|
|
|
|
cell: ({ row }) => (
|
|
|
|
|
<Button
|
|
|
|
@@ -381,7 +235,7 @@ const AccountListTable = () => {
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{row.original.code}
|
|
|
|
|
{row.original.number}
|
|
|
|
|
</Button>
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
@@ -393,26 +247,21 @@ const AccountListTable = () => {
|
|
|
|
|
</Typography>
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor('category', {
|
|
|
|
|
columnHelper.accessor('chart_of_account.name', {
|
|
|
|
|
header: 'Kategori',
|
|
|
|
|
cell: ({ row }) => (
|
|
|
|
|
<Chip
|
|
|
|
|
variant='tonal'
|
|
|
|
|
label={row.original.category}
|
|
|
|
|
size='small'
|
|
|
|
|
color={getCategoryColor(row.original.category) as any}
|
|
|
|
|
className='capitalize'
|
|
|
|
|
/>
|
|
|
|
|
<Typography color='text.primary' className='font-medium'>
|
|
|
|
|
{row.original.chart_of_account.name}
|
|
|
|
|
</Typography>
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
columnHelper.accessor('balance', {
|
|
|
|
|
columnHelper.accessor('current_balance', {
|
|
|
|
|
header: 'Saldo',
|
|
|
|
|
cell: ({ row }) => {
|
|
|
|
|
const balance = parseInt(row.original.balance)
|
|
|
|
|
return (
|
|
|
|
|
<Typography className='font-medium text-right text-primary'>
|
|
|
|
|
{balance < 0 ? '-' : ''}
|
|
|
|
|
{formatCurrency(row.original.balance)}
|
|
|
|
|
{row.original.current_balance < 0 ? '-' : ''}
|
|
|
|
|
{formatCurrency(row.original.current_balance)}
|
|
|
|
|
</Typography>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
@@ -422,7 +271,7 @@ const AccountListTable = () => {
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const table = useReactTable({
|
|
|
|
|
data: paginatedData as AccountType[],
|
|
|
|
|
data: accounts as Account[],
|
|
|
|
|
columns,
|
|
|
|
|
filterFns: {
|
|
|
|
|
fuzzy: fuzzyFilter
|
|
|
|
@@ -512,7 +361,7 @@ const AccountListTable = () => {
|
|
|
|
|
</tr>
|
|
|
|
|
))}
|
|
|
|
|
</thead>
|
|
|
|
|
{filteredData.length === 0 ? (
|
|
|
|
|
{accounts.length === 0 ? (
|
|
|
|
|
<tbody>
|
|
|
|
|
<tr>
|
|
|
|
|
<td colSpan={table.getVisibleFlatColumns().length} className='text-center'>
|
|
|
|
@@ -558,15 +407,16 @@ const AccountListTable = () => {
|
|
|
|
|
onPageChange={handlePageChange}
|
|
|
|
|
onRowsPerPageChange={handlePageSizeChange}
|
|
|
|
|
rowsPerPageOptions={[10, 25, 50]}
|
|
|
|
|
disabled={isLoading}
|
|
|
|
|
/>
|
|
|
|
|
</Card>
|
|
|
|
|
<AccountFormDrawer
|
|
|
|
|
{/* <AccountFormDrawer
|
|
|
|
|
open={addAccountOpen}
|
|
|
|
|
handleClose={handleCloseDrawer}
|
|
|
|
|
accountData={data}
|
|
|
|
|
setData={setData}
|
|
|
|
|
editingAccount={editingAccount}
|
|
|
|
|
/>
|
|
|
|
|
/> */}
|
|
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|