Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create A Bank Transactions Section in the Admin Dashboard #1398

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions public/locales/bg/bank-transactions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"all": "Всички банкови транзакции",
"bank-transactions": "Банкови транзакции",
"transaction-date": "Дата на транзакция",
"amount": "Сума",
"currency": "Валута",
"donation-status": "Статус на дарението",
"id": "ID на транзакцията",
"bank-name": "Банка",
"type": "Вид",
"description": "Основание",
"cta": {
"download": "Изтегли",
"status": "Статус на дарението",
"type": "Тип",
"from": "От",
"to": "До"
}
}
22 changes: 22 additions & 0 deletions src/common/hooks/bank-transactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { BankTransactionsHistoryResponse } from 'gql/bank-transactions'
import { useSession } from 'next-auth/react'

import { useQuery } from '@tanstack/react-query'

import { endpoints } from 'service/apiEndpoints'
import { PaginationData, FilterData } from 'gql/types'
import { authQueryFnFactory } from 'service/restRequests'

export function useBankTransactionsList(
paginationData?: PaginationData,
filterData?: FilterData,
searchData?: string,
) {
const { data: session } = useSession()
return useQuery<BankTransactionsHistoryResponse>(
[endpoints.bankTransactions.transactionsList(paginationData, filterData, searchData).url],
{
queryFn: authQueryFnFactory(session?.accessToken),
},
)
}
3 changes: 3 additions & 0 deletions src/common/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ export const routes = {
add: '/admin/bankaccounts/add',
edit: (id: string | number) => `/admin/bankaccounts/edit/${id}`,
},
bankTransactions: {
index: '/admin/bank-transactions',
},
cities: {
home: '/admin/cities',
create: '/admin/cities/create',
Expand Down
23 changes: 23 additions & 0 deletions src/components/admin/bank-transactions/BankTransactionsPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useTranslation } from 'next-i18next'
import { ModalStoreImpl } from 'stores/dashboard/ModalStore'
import AdminContainer from 'components/common/navigation/AdminContainer'
import AdminLayout from 'components/common/navigation/AdminLayout'
import Grid from './grid/Grid'
import GridAppbar from './grid/GridAppbar'
import GridFilters from './grid/GridFilters'

export const ModalStore = new ModalStoreImpl()

export default function DocumentsPage() {
const { t } = useTranslation()

return (
<AdminLayout>
<AdminContainer title={t('bank-transactions:bank-transactions')}>
<GridAppbar />
<GridFilters />
<Grid />
</AdminContainer>
</AdminLayout>
)
}
77 changes: 77 additions & 0 deletions src/components/admin/bank-transactions/grid/Filter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { useTranslation } from 'next-i18next'
import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material'
import { Close } from '@mui/icons-material'

type Options = {
name: string
label: string
}

interface DropdownFilterProps {
options: Options
value: string
onChange: (filterName: string, filterValue: string) => void
menuItems: string[]
}

export default function DropdownFilter(props: DropdownFilterProps) {
const { t } = useTranslation()
const {
options: { name, label },
value,
onChange,
menuItems,
} = props

const handleChange = (e: SelectChangeEvent) => {
e.stopPropagation()
const filterName = e.target.name as string
const filterValue = e.target.value as string
onChange(filterName, filterValue)
}

const handleClear = (event: React.MouseEvent, filterName: string, filterValue: string) => {
event.stopPropagation()
onChange(filterName, filterValue)
}

const selectElementStyle = {
minWidth: 115,
marginRight: 1,
marginLeft: 1,
}

const closeIconStyle = {
color: '#365b99',
cursor: 'pointer',
}

return (
<FormControl style={selectElementStyle}>
<InputLabel size="small">{t(label)}</InputLabel>
<Select
startAdornment={
value ? (
<Close
fontSize="small"
style={closeIconStyle}
onClick={(e) => handleClear(e, name, '')}
/>
) : null
}
name={name}
value={value}
label={t(label)}
size="small"
onChange={(e) => handleChange(e)}>
{menuItems.map((key) => {
return (
<MenuItem key={key} value={key}>
{key}
</MenuItem>
)
})}
</Select>
</FormControl>
)
}
160 changes: 160 additions & 0 deletions src/components/admin/bank-transactions/grid/Grid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import React, { useState } from 'react'
import { UseQueryResult } from '@tanstack/react-query'
import { useTranslation } from 'next-i18next'
import { Box } from '@mui/material'
import { DataGrid, GridColDef, GridColumns, GridRenderCellParams } from '@mui/x-data-grid'
import { observer } from 'mobx-react'

import { getExactDateTime } from 'common/util/date'
import { useRouter } from 'next/router'
import { money } from 'common/util/money'

import { useStores } from '../../../../common/hooks/useStores'
import { BankTransactionsHistoryResponse } from 'gql/bank-transactions'
import { useBankTransactionsList } from 'common/hooks/bank-transactions'

interface RenderCellProps {
params: GridRenderCellParams
}
const addIconStyles = {
background: '#4ac3ff',
borderRadius: '50%',
cursor: 'pointer',
padding: 0.7,
boxShadow: 3,
}
export default observer(function Grid() {
const { bankTransactionsStore } = useStores()
const [paginationData, setPaginationData] = useState({
pageIndex: 0,
pageSize: 20,
})

const { t } = useTranslation()

const {
data: { items: bankTransactions, total: all_rows } = { items: [], total: 0 },
error: bankTransactionsHistoryError,
isLoading: bankDonationsHistoryLoading,
refetch,
}: UseQueryResult<BankTransactionsHistoryResponse> = useBankTransactionsList(
paginationData,
bankTransactionsStore.bankTransactionsFilter,
bankTransactionsStore.bankTransactionSearch,
)

const RenderMoneyCell = ({ params }: RenderCellProps) => {
return <>{money(params.row.amount, params.row.currency)}</>
}

const commonProps: Partial<GridColDef> = {
align: 'left',
width: 150,
headerAlign: 'left',
}

const columns: GridColumns = [
{
field: 'id',
headerName: t('bank-transactions:id'),
hide: false,
width: 150,
},
{
field: 'bankName',
headerName: t('bank-transactions:bank-name'),
width: 100,
},
{
field: 'transactionDate',
headerName: t('bank-transactions:transaction-date'),
...commonProps,
width: 220,
renderCell: (params: GridRenderCellParams) => {
return getExactDateTime(params?.row.transactionDate)
},
},
{
field: 'type',
headerName: t('bank-transactions:type'),
},
{
field: 'amount',
headerName: t('bank-transactions:amount'),
renderCell: (params: GridRenderCellParams) => {
return <RenderMoneyCell params={params} />
},
},
{
field: 'currency',
headerName: t('bank-transactions:currency'),
...commonProps,
width: 100,
},
{
field: 'senderName',
headerName: 'Sender Name',
width: 250,
},
{
field: 'senderIban',
headerName: 'Sender IBAN',
width: 230,
},
{
field: 'recipientName',
headerName: 'Recipient Name',
width: 250,
},
{
field: 'recipientIban',
headerName: 'Recipient IBAN',
width: 230,
},
{
field: 'description',
headerName: t('bank-transactions:description'),
...commonProps,
width: 350,
},
{
field: 'bankDonationStatus',
headerName: t('bank-transactions:donation-status'),
width: 150,
},
]

return (
<>
<Box sx={{ mx: 'auto', width: 700 }}>
<DataGrid
style={{
background: 'white',
position: 'absolute',
height: 'calc(100vh - 300px)',
border: 'none',
width: 'calc(100% - 48px)',
left: '24px',
overflowY: 'auto',
overflowX: 'hidden',
borderRadius: '0 0 13px 13px',
}}
rows={bankTransactions || []}
columns={columns}
rowsPerPageOptions={[5, 10, 20]}
pageSize={paginationData.pageSize}
pagination
loading={bankDonationsHistoryLoading}
error={bankTransactionsHistoryError}
page={paginationData.pageIndex}
onPageChange={(pageIndex) => setPaginationData({ ...paginationData, pageIndex })}
onPageSizeChange={(pageSize) => setPaginationData({ ...paginationData, pageSize })}
paginationMode="server"
rowCount={all_rows}
disableSelectionOnClick
isCellEditable={() => true}
/>
</Box>
</>
)
})
Loading