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

Invalidate a donation from the admin panel #1704

Merged
merged 4 commits into from
Jan 28, 2024
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
10 changes: 10 additions & 0 deletions public/locales/bg/donations.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"edit": "Дарението беше редактирано успешно!",
"delete": "Дарението беше изтрито успешно!",
"refundSuccess": "Беше създадена успешна заявка за връщане на парите към Stripe.",
"invalidate": "Дарението беше маркирано като невалидно!",
"editDonor": "Дарителят беше редактиран успешно!",
"error": "Възникна грешка! Моля опитайте отново по-късно.",
"requiredError": "Полето е задължително."
Expand Down Expand Up @@ -66,5 +67,14 @@
"amount": "Сума:",
"email": "Е-mail на дарител:",
"confirm-button": "Възстанови парите от дарение"
},
"invalidate": {
"icon": "Маркирай като невалидно",
"title": "Маркиране на дарение като невалидно",
"confirmation": "Сигурни ли сте, че искате да маркирате като невалидно дарението:",
"number": "Номер:",
"amount": "Сума:",
"email": "Е-mail на дарител:",
"confirm-button": "Маркирай като невалидно"
}
}
10 changes: 10 additions & 0 deletions public/locales/en/donations.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"edit": "Document has been edited successfully!",
"delete": "Document has been deleted successfully!",
"refundSuccess": "A successful refund request was created with Stripe.",
"invalidate": "Document has been marked as invalid successfully!",
"editDonor": "Donation donor has been edited successfully!",
"error": "An error has occured! Please try again later.",
"requiredError": "Fields is required!"
Expand Down Expand Up @@ -66,5 +67,14 @@
"amount": "Amount:",
"email": "Donator's email:",
"confirm-button": "Refund a donation"
},
"invalidate": {
"icon": "Mark as invalid",
"title": "Mark as invalid",
"confirmation": "Are you sure you want to refund the donation:",
"number": "Number:",
"amount": "Amount:",
"email": "Е-mail",
"confirm-button": "Mark as invalid"
}
}
1 change: 1 addition & 0 deletions src/components/admin/donations/DonationsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { RefundStoreImpl } from './store/RefundStore'

export const ModalStore = new ModalStoreImpl()
export const RefundStore = new RefundStoreImpl()
export const InvalidateStore = new ModalStoreImpl()

export default function DocumentsPage() {
const { t } = useTranslation()
Expand Down
48 changes: 37 additions & 11 deletions src/components/admin/donations/grid/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { observer } from 'mobx-react'
import { useDonationsList } from 'common/hooks/donation'

import DetailsModal from '../modals/DetailsModal'
import DeleteModal from '../modals/DeleteModal'
import { ModalStore, RefundStore } from '../DonationsPage'
import InvalidateModal from '../modals/InvalidateModal'
import { ModalStore, RefundStore, InvalidateStore } from '../DonationsPage'
import { getExactDateTime } from 'common/util/date'
import { useRouter } from 'next/router'
import { money } from 'common/util/money'
Expand All @@ -26,8 +26,10 @@ import RenderEditPersonCell from './RenderEditPersonCell'
import { useStores } from '../../../../common/hooks/useStores'
import RenderEditBillingEmailCell from './RenderEditBillingEmailCell'
import RestoreIcon from '@mui/icons-material/Restore'
import CancelIcon from '@mui/icons-material/Cancel'
import RefundModal from '../modals/RefundModal'
import { DonationStatus, PaymentProvider } from '../../../../gql/donations.enums'
import { useSession } from 'next-auth/react'

interface RenderCellProps {
params: GridRenderCellParams
Expand All @@ -51,8 +53,16 @@ export default observer(function Grid() {
const router = useRouter()
const { isDetailsOpen } = ModalStore
const { isRefundOpen } = RefundStore
const {
isDeleteOpen,
setSelectedRecord: setInvalidateRecord,
showDelete: showInvalidate,
} = InvalidateStore
const campaignId = router.query.campaignId as string | undefined

const { data: session } = useSession()
const canEditFinancials = session?.user?.realm_access?.roles.includes(
'account-edit-financials-requests',
)
const {
data: { items: donations, total: allDonationsCount } = { items: [], total: 0 },
// error: donationHistoryError,
Expand Down Expand Up @@ -147,6 +157,11 @@ export default observer(function Grid() {
showRefund()
}

function invalidateClickHandler(id: string) {
setInvalidateRecord({ id, name: '' })
showInvalidate()
}

const columns: GridColDef[] = [
{
field: 'actions',
Expand All @@ -155,20 +170,31 @@ export default observer(function Grid() {
width: 120,
resizable: false,
renderCell: (params: GridRenderCellParams) => {
return params.row?.status === DonationStatus.succeeded &&
params.row?.provider === PaymentProvider.stripe ? (
if (!canEditFinancials || params.row?.status !== DonationStatus.succeeded) {
return ''
}

return (
<>
<Tooltip title={t('donations:refund.icon')}>
{params.row.provider === PaymentProvider.stripe && (
<Tooltip title={t('donations:refund.icon')}>
<IconButton
size="small"
color="primary"
onClick={() => refundClickHandler(params.row.id)}>
<RestoreIcon />
</IconButton>
</Tooltip>
)}
<Tooltip title={t('donations:invalidate.icon')}>
slavcho marked this conversation as resolved.
Show resolved Hide resolved
<IconButton
size="small"
color="primary"
onClick={() => refundClickHandler(params.row.id)}>
<RestoreIcon />
onClick={() => invalidateClickHandler(params.row.id)}>
<CancelIcon />
</IconButton>
</Tooltip>
</>
) : (
''
)
},
},
Expand Down Expand Up @@ -292,7 +318,7 @@ export default observer(function Grid() {
{/* making sure we don't sent requests to the API when not needed */}
{isDetailsOpen && <DetailsModal />}
{isRefundOpen && <RefundModal />}
<DeleteModal />
{isDeleteOpen && <InvalidateModal onUpdate={refetch} />}
</>
)
})
48 changes: 48 additions & 0 deletions src/components/admin/donations/modals/InvalidateModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react'
import { useRouter } from 'next/router'
import { useMutation } from '@tanstack/react-query'
import { observer } from 'mobx-react'
import { AxiosError, AxiosResponse } from 'axios'
import { useTranslation } from 'next-i18next'

import { DonationResponse } from 'gql/donations'
import { ApiErrors } from 'service/apiErrors'
import { AlertStore } from 'stores/AlertStore'
import { routes } from 'common/routes'
import DeleteDialog from 'components/admin/DeleteDialog'
import { useInvalidateStripeDonation } from 'service/donation'

import { InvalidateStore } from '../DonationsPage'

type Props = {
onUpdate: () => void
}

export default observer(function InvalidateModal({ onUpdate }: Props) {
const router = useRouter()
const { hideDelete, selectedRecord } = InvalidateStore
const { t } = useTranslation()

const mutationFn = useInvalidateStripeDonation()

const invalidateMutation = useMutation<
AxiosResponse<DonationResponse>,
AxiosError<ApiErrors>,
string
>({
mutationFn,
onError: () => AlertStore.show(t('donations:alerts:error'), 'error'),
onSuccess: () => {
hideDelete()
AlertStore.show(t('donations:alerts:invalidate'), 'success')
router.push(routes.admin.donations.index)
onUpdate()
},
})

function invalidateHandler() {
invalidateMutation.mutate(selectedRecord.id)
}

return <DeleteDialog modalStore={InvalidateStore} deleteHandler={invalidateHandler} />
})
2 changes: 2 additions & 0 deletions src/service/apiEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ export const endpoints = {
createBankDonation: <Endpoint>{ url: '/donation/create-bank-payment', method: 'POST' },
refundStripePayment: (id: string) =>
<Endpoint>{ url: `/donation/refund-stripe-payment/${id}`, method: 'POST' },
invalidateStripePayment: (id: string) =>
<Endpoint>{ url: `/donation/${id}/invalidate`, method: 'PATCH' },
getDonation: (id: string) => <Endpoint>{ url: `/donation/${id}`, method: 'GET' },
donationsList: (
campaignId?: string,
Expand Down
10 changes: 10 additions & 0 deletions src/service/donation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ export const useRefundStripeDonation = () => {
)
}
}
export const useInvalidateStripeDonation = () => {
const { data: session } = useSession()
return async (extPaymentId: string) => {
return await apiClient.patch(
endpoints.donation.invalidateStripePayment(extPaymentId).url,
'',
authConfig(session?.accessToken),
)
}
}

export const useUploadBankTransactionsFiles = () => {
const { data: session } = useSession()
Expand Down
Loading