Skip to content

Commit a22d279

Browse files
authored
Merge pull request #1017 from PayButton/feat/year-payments-filter
Feat/year payments filter
2 parents 04e12d7 + 777a029 commit a22d279

File tree

8 files changed

+203
-35
lines changed

8 files changed

+203
-35
lines changed

components/Transaction/Invoice.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,22 @@ import { XEC_TX_EXPLORER_URL, BCH_TX_EXPLORER_URL, NETWORK_TICKERS_FROM_ID, XEC_
33
import moment from 'moment'
44
import logoImageSource from 'assets/logo.png'
55
import Image from 'next/image'
6-
7-
const Receipt = React.forwardRef((props, ref) => {
6+
interface ReceiptProps {
7+
data: {
8+
invoiceNumber: string
9+
amount: number
10+
recipientName: string
11+
recipientAddress: string
12+
description: string
13+
customerName: string
14+
customerAddress: string
15+
createdAt: string | number | Date
16+
transactionHash: string
17+
transactionDate: number
18+
transactionNetworkId: number
19+
}
20+
}
21+
const Receipt = React.forwardRef<HTMLDivElement, ReceiptProps>((props, ref) => {
822
const { data } = props
923
const {
1024
invoiceNumber,

components/Transaction/InvoiceModal.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,6 @@ export default function InvoiceModal ({
272272
}
273273
</div>
274274
<div style={{ display: 'none' }}>
275-
{/* <div> */}
276275
<PrintableReceipt ref={contentRef} data={invoiceData} />
277276
</div>
278277
</div>

pages/api/payments/count/index.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@ export default async (req: any, res: any): Promise<void> => {
1616
if (typeof req.query.buttonIds === 'string' && req.query.buttonIds !== '') {
1717
buttonIds = (req.query.buttonIds as string).split(',')
1818
}
19-
20-
if ((buttonIds !== undefined) && buttonIds.length > 0) {
21-
const totalCount = await getFilteredTransactionCount(userId, buttonIds)
19+
let years: string[] | undefined
20+
if (typeof req.query.years === 'string' && req.query.years !== '') {
21+
years = (req.query.years as string).split(',')
22+
}
23+
if (((buttonIds !== undefined) && buttonIds.length > 0) ||
24+
((years !== undefined) && years.length > 0)) {
25+
const totalCount = await getFilteredTransactionCount(userId, buttonIds, years)
2226
res.status(200).json(totalCount)
2327
} else {
2428
const totalCount = await CacheGet.paymentsCount(userId, timezone)

pages/api/payments/download/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,12 @@ export default async (req: any, res: any): Promise<void> => {
4747
if (typeof req.query.buttonIds === 'string' && req.query.buttonIds !== '') {
4848
buttonIds = req.query.buttonIds.split(',')
4949
}
50-
const transactions = await fetchAllPaymentsByUserId(userId, networkIdArray, buttonIds)
50+
let years: string[] | undefined
51+
if (typeof req.query.years === 'string' && req.query.years !== '') {
52+
years = (req.query.years as string).split(',')
53+
}
54+
55+
const transactions = await fetchAllPaymentsByUserId(userId, networkIdArray, buttonIds, years)
5156

5257
await downloadTxsFile(res, quoteSlug, timezone, transactions, userId)
5358
} catch (error: any) {

pages/api/payments/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { fetchAllPaymentsByUserIdWithPagination } from 'services/transactionService'
2+
import { fetchUserProfileFromId } from 'services/userService'
23
import { setSession } from 'utils/setSession'
34

45
export default async (req: any, res: any): Promise<void> => {
@@ -14,14 +15,23 @@ export default async (req: any, res: any): Promise<void> => {
1415
if (typeof req.query.buttonIds === 'string' && req.query.buttonIds !== '') {
1516
buttonIds = (req.query.buttonIds as string).split(',')
1617
}
18+
let years: string[] | undefined
19+
if (typeof req.query.years === 'string' && req.query.years !== '') {
20+
years = (req.query.years as string).split(',')
21+
}
22+
const userReqTimezone = req.headers.timezone as string
23+
const userProfile = await fetchUserProfileFromId(userId)
24+
const userPreferredTimezone = userProfile?.preferredTimezone
1725

1826
const resJSON = await fetchAllPaymentsByUserIdWithPagination(
1927
userId,
2028
page,
2129
pageSize,
2230
orderBy,
2331
orderDesc,
24-
buttonIds
32+
buttonIds,
33+
years,
34+
userPreferredTimezone ?? userReqTimezone
2535
)
2636
res.status(200).json(resJSON)
2737
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { fetchDistinctPaymentYearsByUser } from 'services/transactionService'
2+
import { setSession } from 'utils/setSession'
3+
4+
export default async (req: any, res: any): Promise<void> => {
5+
if (req.method === 'GET') {
6+
try {
7+
await setSession(req, res)
8+
const userId = req.session.userId
9+
const years = await fetchDistinctPaymentYearsByUser(userId)
10+
res.status(200).json({ years })
11+
} catch (err: any) {
12+
res.status(500).json({ statusCode: 500, message: err.message })
13+
}
14+
}
15+
}

pages/payments/index.tsx

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
7272
const timezone = user?.userProfile.preferredTimezone === '' ? moment.tz.guess() : user?.userProfile?.preferredTimezone
7373
const [selectedCurrencyCSV, setSelectedCurrencyCSV] = useState<string>('')
7474
const [paybuttonNetworks, setPaybuttonNetworks] = useState<Set<number>>(new Set())
75+
const [transactionYears, setTransactionYears] = useState<number[]>([])
76+
const [selectedTransactionYears, setSelectedTransactionYears] = useState<number[]>([])
77+
7578
const [loading, setLoading] = useState(false)
7679
const [buttons, setButtons] = useState<any[]>([])
7780
const [selectedButtonIds, setSelectedButtonIds] = useState<any[]>([])
@@ -133,7 +136,7 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
133136
}
134137
useEffect(() => {
135138
setRefreshCount(prev => prev + 1)
136-
}, [selectedButtonIds])
139+
}, [selectedButtonIds, selectedTransactionYears])
137140

138141
const fetchPaybuttons = async (): Promise<any> => {
139142
const res = await fetch(`/api/paybuttons?userId=${user?.userProfile.id}`, {
@@ -144,8 +147,21 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
144147
}
145148
}
146149

150+
const fetchTransactionYears = async (): Promise<any> => {
151+
const res = await fetch('/api/transaction/years', {
152+
method: 'GET'
153+
})
154+
if (res.status === 200) {
155+
const data = await res.json()
156+
return data.years
157+
} else {
158+
console.error('Failed to fetch transaction years:', res.statusText)
159+
return []
160+
}
161+
}
147162
const getDataAndSetUpCurrencyCSV = async (): Promise<void> => {
148163
const paybuttons = await fetchPaybuttons()
164+
const years = await fetchTransactionYears()
149165
const networkIds: Set<number> = new Set()
150166
setButtons(paybuttons)
151167

@@ -154,6 +170,7 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
154170
})
155171

156172
setPaybuttonNetworks(networkIds)
173+
setTransactionYears(years)
157174
}
158175

159176
useEffect(() => {
@@ -173,10 +190,24 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
173190
if (selectedButtonIds.length > 0) {
174191
url += `&buttonIds=${selectedButtonIds.join(',')}`
175192
}
193+
if (selectedTransactionYears.length > 0) {
194+
url += `&years=${selectedTransactionYears.join(',')}`
195+
}
176196

177-
const paymentsResponse = await fetch(url)
197+
const paymentsResponse = await fetch(url, {
198+
headers: {
199+
Timezone: moment.tz.guess()
200+
}
201+
})
202+
let paymentsCountUrl = '/api/payments/count'
203+
if (selectedButtonIds.length > 0) {
204+
paymentsCountUrl += `?buttonIds=${selectedButtonIds.join(',')}`
205+
}
206+
if (selectedTransactionYears.length > 0) {
207+
paymentsCountUrl += `${selectedButtonIds.length > 0 ? '&' : '?'}years=${selectedTransactionYears.join(',')}`
208+
}
178209
const paymentsCountResponse = await fetch(
179-
`/api/payments/count${selectedButtonIds.length > 0 ? `?buttonIds=${selectedButtonIds.join(',')}` : ''}`,
210+
paymentsCountUrl,
180211
{ headers: { Timezone: timezone } }
181212
)
182213

@@ -312,7 +343,7 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
312343

313344
<Image src={Plus} alt='create invoice' width={14} height={14} />
314345
</button>
315-
<div className={style.tooltiptext}>New button</div>
346+
<div className={style.tooltiptext}>New Invoice</div>
316347
</div>
317348
)
318349
: (
@@ -356,6 +387,9 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
356387
if (selectedButtonIds.length > 0) {
357388
url += `&buttonIds=${selectedButtonIds.join(',')}`
358389
}
390+
if (selectedTransactionYears.length > 0) {
391+
url += `&years=${selectedTransactionYears.join(',')}`
392+
}
359393
const isCurrencyEmptyOrUndefined = (value: string): boolean => (value === '' || value === undefined)
360394

361395
if (!isCurrencyEmptyOrUndefined(currency)) {
@@ -406,7 +440,10 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
406440
setSelectedCurrencyCSV(currencyParam)
407441
void downloadCSV(userId, user?.userProfile, currencyParam)
408442
}
409-
443+
const handleClearFilters = (): void => {
444+
setSelectedButtonIds([])
445+
setSelectedTransactionYears([])
446+
}
410447
return (
411448
<>
412449
<TopBar title="Payments" user={user?.stUser?.email} />
@@ -418,9 +455,9 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
418455
>
419456
<Image src={SettingsIcon} alt="filters" width={15} />Filters
420457
</div>
421-
{selectedButtonIds.length > 0 &&
458+
{(selectedButtonIds.length > 0 || selectedTransactionYears.length > 0) &&
422459
<div
423-
onClick={() => setSelectedButtonIds([])}
460+
onClick={() => handleClearFilters()}
424461
className={style.show_filters_button}
425462
>
426463
Clear
@@ -459,6 +496,7 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
459496
</Button>)}
460497
</div>
461498
{showFilters && (
499+
<div>
462500
<div className={style.showfilters_ctn}>
463501
<span>Filter by button</span>
464502
<div className={style.filters_ctn}>
@@ -479,6 +517,27 @@ export default function Payments ({ user, userId, organization }: PaybuttonsProp
479517
))}
480518
</div>
481519
</div>
520+
<div className={style.showfilters_ctn}>
521+
<span>Filter by year</span>
522+
<div className={style.filters_ctn}>
523+
{transactionYears.map((y) => (
524+
<div
525+
key={y}
526+
onClick={() => {
527+
setSelectedTransactionYears(prev =>
528+
prev.includes(y)
529+
? prev.filter(year => year !== y)
530+
: [...prev, y]
531+
)
532+
}}
533+
className={`${style.filter_button} ${selectedTransactionYears.includes(y) ? style.active : ''}`}
534+
>
535+
{y}
536+
</div>
537+
))}
538+
</div>
539+
</div>
540+
</div>
482541
)}
483542
<TableContainerGetter
484543
columns={columns}

0 commit comments

Comments
 (0)