Get Account
This commit is contained in:
parent
27fe48e99e
commit
2d69a024c1
36
src/services/queries/account.ts
Normal file
36
src/services/queries/account.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { useQuery } from '@tanstack/react-query'
|
||||||
|
import { api } from '../api'
|
||||||
|
import { Accounts } from '@/types/services/chartOfAccount'
|
||||||
|
|
||||||
|
interface AccountQueryParams {
|
||||||
|
page?: number
|
||||||
|
limit?: number
|
||||||
|
search?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAccounts(params: AccountQueryParams = {}) {
|
||||||
|
const { page = 1, limit = 10, search = '', ...filters } = params
|
||||||
|
|
||||||
|
return useQuery<Accounts>({
|
||||||
|
queryKey: ['accounts', { page, limit, search, ...filters }],
|
||||||
|
queryFn: async () => {
|
||||||
|
const queryParams = new URLSearchParams()
|
||||||
|
|
||||||
|
queryParams.append('page', page.toString())
|
||||||
|
queryParams.append('limit', limit.toString())
|
||||||
|
|
||||||
|
if (search) {
|
||||||
|
queryParams.append('search', search)
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.entries(filters).forEach(([key, value]) => {
|
||||||
|
if (value !== undefined && value !== null && value !== '') {
|
||||||
|
queryParams.append(key, value.toString())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await api.get(`/accounts?${queryParams.toString()}`)
|
||||||
|
return res.data.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -37,3 +37,28 @@ export interface ChartOfAccounts {
|
|||||||
page: number
|
page: number
|
||||||
total: number
|
total: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Account {
|
||||||
|
id: string
|
||||||
|
organization_id: string
|
||||||
|
outlet_id: string
|
||||||
|
chart_of_account_id: string
|
||||||
|
name: string
|
||||||
|
number: string
|
||||||
|
account_type: string
|
||||||
|
opening_balance: number
|
||||||
|
current_balance: number
|
||||||
|
description: string
|
||||||
|
is_active: true
|
||||||
|
is_system: false
|
||||||
|
created_at: string
|
||||||
|
updated_at: string
|
||||||
|
chart_of_account: ChartOfAccount
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Accounts {
|
||||||
|
data: Account[]
|
||||||
|
limit: number
|
||||||
|
page: number
|
||||||
|
total: number
|
||||||
|
}
|
||||||
|
|||||||
@ -41,6 +41,11 @@ import TablePaginationComponent from '@/components/TablePaginationComponent'
|
|||||||
import Loading from '@/components/layout/shared/Loading'
|
import Loading from '@/components/layout/shared/Loading'
|
||||||
import { getLocalizedUrl } from '@/utils/i18n'
|
import { getLocalizedUrl } from '@/utils/i18n'
|
||||||
import AccountFormDrawer from './AccountFormDrawer'
|
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
|
// Account Type
|
||||||
export type AccountType = {
|
export type AccountType = {
|
||||||
@ -60,119 +65,10 @@ declare module '@tanstack/table-core' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccountTypeWithAction = AccountType & {
|
type AccountTypeWithAction = Account & {
|
||||||
actions?: string
|
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
|
// Styled Components
|
||||||
const Icon = styled('i')({})
|
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
|
// Column Definitions
|
||||||
const columnHelper = createColumnHelper<AccountTypeWithAction>()
|
const columnHelper = createColumnHelper<AccountTypeWithAction>()
|
||||||
|
|
||||||
@ -261,53 +147,25 @@ const AccountListTable = () => {
|
|||||||
// States
|
// States
|
||||||
const [addAccountOpen, setAddAccountOpen] = useState(false)
|
const [addAccountOpen, setAddAccountOpen] = useState(false)
|
||||||
const [rowSelection, setRowSelection] = useState({})
|
const [rowSelection, setRowSelection] = useState({})
|
||||||
const [currentPage, setCurrentPage] = useState(0)
|
const [currentPage, setCurrentPage] = useState(1)
|
||||||
const [pageSize, setPageSize] = useState(10)
|
const [pageSize, setPageSize] = useState(10)
|
||||||
const [openConfirm, setOpenConfirm] = useState(false)
|
const [openConfirm, setOpenConfirm] = useState(false)
|
||||||
const [accountId, setAccountId] = useState('')
|
const [accountId, setAccountId] = useState('')
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState('')
|
||||||
const [categoryFilter, setCategoryFilter] = useState<string>('Semua')
|
const [categoryFilter, setCategoryFilter] = useState<string>('Semua')
|
||||||
const [filteredData, setFilteredData] = useState<AccountType[]>(accountsData)
|
const [editingAccount, setEditingAccount] = useState<Account | null>(null)
|
||||||
const [data, setData] = useState<AccountType[]>(accountsData)
|
|
||||||
const [editingAccount, setEditingAccount] = useState<AccountType | null>(null)
|
const { data, isLoading } = useAccounts({
|
||||||
|
page: currentPage,
|
||||||
|
limit: pageSize,
|
||||||
|
search
|
||||||
|
})
|
||||||
|
|
||||||
// Hooks
|
// Hooks
|
||||||
const { lang: locale } = useParams()
|
const { lang: locale } = useParams()
|
||||||
|
|
||||||
// Get unique categories for filter
|
const accounts = data?.data ?? []
|
||||||
const categories = useMemo(() => {
|
const totalCount = data?.total ?? 0
|
||||||
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 handlePageChange = useCallback((event: unknown, newPage: number) => {
|
const handlePageChange = useCallback((event: unknown, newPage: number) => {
|
||||||
setCurrentPage(newPage)
|
setCurrentPage(newPage)
|
||||||
@ -319,12 +177,8 @@ const AccountListTable = () => {
|
|||||||
setCurrentPage(0)
|
setCurrentPage(0)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleDelete = () => {
|
|
||||||
setOpenConfirm(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle row click for edit
|
// 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
|
// Don't trigger row click if clicking on checkbox or link
|
||||||
const target = event.target as HTMLElement
|
const target = event.target as HTMLElement
|
||||||
if (target.closest('input[type="checkbox"]') || target.closest('a') || target.closest('button')) {
|
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',
|
header: 'Kode Akun',
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<Button
|
<Button
|
||||||
@ -381,7 +235,7 @@ const AccountListTable = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{row.original.code}
|
{row.original.number}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
@ -393,26 +247,21 @@ const AccountListTable = () => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor('category', {
|
columnHelper.accessor('chart_of_account.name', {
|
||||||
header: 'Kategori',
|
header: 'Kategori',
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<Chip
|
<Typography color='text.primary' className='font-medium'>
|
||||||
variant='tonal'
|
{row.original.chart_of_account.name}
|
||||||
label={row.original.category}
|
</Typography>
|
||||||
size='small'
|
|
||||||
color={getCategoryColor(row.original.category) as any}
|
|
||||||
className='capitalize'
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor('balance', {
|
columnHelper.accessor('current_balance', {
|
||||||
header: 'Saldo',
|
header: 'Saldo',
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const balance = parseInt(row.original.balance)
|
|
||||||
return (
|
return (
|
||||||
<Typography className='font-medium text-right text-primary'>
|
<Typography className='font-medium text-right text-primary'>
|
||||||
{balance < 0 ? '-' : ''}
|
{row.original.current_balance < 0 ? '-' : ''}
|
||||||
{formatCurrency(row.original.balance)}
|
{formatCurrency(row.original.current_balance)}
|
||||||
</Typography>
|
</Typography>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -422,7 +271,7 @@ const AccountListTable = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data: paginatedData as AccountType[],
|
data: accounts as Account[],
|
||||||
columns,
|
columns,
|
||||||
filterFns: {
|
filterFns: {
|
||||||
fuzzy: fuzzyFilter
|
fuzzy: fuzzyFilter
|
||||||
@ -512,7 +361,7 @@ const AccountListTable = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</thead>
|
</thead>
|
||||||
{filteredData.length === 0 ? (
|
{accounts.length === 0 ? (
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={table.getVisibleFlatColumns().length} className='text-center'>
|
<td colSpan={table.getVisibleFlatColumns().length} className='text-center'>
|
||||||
@ -558,15 +407,16 @@ const AccountListTable = () => {
|
|||||||
onPageChange={handlePageChange}
|
onPageChange={handlePageChange}
|
||||||
onRowsPerPageChange={handlePageSizeChange}
|
onRowsPerPageChange={handlePageSizeChange}
|
||||||
rowsPerPageOptions={[10, 25, 50]}
|
rowsPerPageOptions={[10, 25, 50]}
|
||||||
|
disabled={isLoading}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
<AccountFormDrawer
|
{/* <AccountFormDrawer
|
||||||
open={addAccountOpen}
|
open={addAccountOpen}
|
||||||
handleClose={handleCloseDrawer}
|
handleClose={handleCloseDrawer}
|
||||||
accountData={data}
|
accountData={data}
|
||||||
setData={setData}
|
setData={setData}
|
||||||
editingAccount={editingAccount}
|
editingAccount={editingAccount}
|
||||||
/>
|
/> */}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user