From 94f35be93efc0fc6ad6fef15d13dac6a9877fabb Mon Sep 17 00:00:00 2001 From: codytseng Date: Mon, 3 Mar 2025 20:08:34 +0800 Subject: [PATCH] feat: list recent supporters --- src/components/Donation/RecentSupporters.tsx | 46 ++++++++++++++++++++ src/components/Donation/index.tsx | 2 + src/i18n/locales/ar.ts | 3 +- src/i18n/locales/de.ts | 3 +- src/i18n/locales/en.ts | 3 +- src/i18n/locales/es.ts | 3 +- src/i18n/locales/fr.ts | 3 +- src/i18n/locales/ja.ts | 3 +- src/i18n/locales/pl.ts | 3 +- src/i18n/locales/pt-BR.ts | 6 ++- src/i18n/locales/pt-PT.ts | 3 +- src/i18n/locales/ru.ts | 3 +- src/i18n/locales/zh.ts | 3 +- src/services/lightning.service.ts | 35 ++++++++++++++- 14 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 src/components/Donation/RecentSupporters.tsx diff --git a/src/components/Donation/RecentSupporters.tsx b/src/components/Donation/RecentSupporters.tsx new file mode 100644 index 00000000..ece6b7fa --- /dev/null +++ b/src/components/Donation/RecentSupporters.tsx @@ -0,0 +1,46 @@ +import { formatAmount } from '@/lib/lightning' +import lightning, { TRecentSupporter } from '@/services/lightning.service' +import { useEffect, useState } from 'react' +import UserAvatar from '../UserAvatar' +import Username from '../Username' +import { useTranslation } from 'react-i18next' + +export default function RecentSupporters() { + const { t } = useTranslation() + const [supporters, setSupporters] = useState([]) + + useEffect(() => { + const init = async () => { + const items = await lightning.fetchRecentSupporters() + setSupporters(items) + } + init() + }, []) + + if (!supporters.length) return null + + return ( +
+
{t('Recent Supporters')}
+
+ {supporters.map((item, index) => ( +
+
+ +
+ +
{item.comment}
+
+
+
+ {formatAmount(item.amount)} {t('sats')} +
+
+ ))} +
+
+ ) +} diff --git a/src/components/Donation/index.tsx b/src/components/Donation/index.tsx index 13615152..2eb0aad5 100644 --- a/src/components/Donation/index.tsx +++ b/src/components/Donation/index.tsx @@ -4,6 +4,7 @@ import { cn } from '@/lib/utils' import { useState } from 'react' import { useTranslation } from 'react-i18next' import ZapDialog from '../ZapDialog' +import RecentSupporters from './RecentSupporters' export default function Donation({ className }: { className?: string }) { const { t } = useTranslation() @@ -38,6 +39,7 @@ export default function Donation({ className }: { className?: string }) { ) })} + b.created_at - a.created_at) + const map = new Map() + events.forEach((event) => { + const info = extractZapInfoFromReceipt(event) + if (!info || info.eventId || !info.senderPubkey || info.senderPubkey === CODY_PUBKEY) return + + const { amount, comment, senderPubkey } = info + const item = map.get(senderPubkey) + if (!item) { + map.set(senderPubkey, { pubkey: senderPubkey, amount, comment }) + } else { + item.amount += amount + if (!item.comment && comment) item.comment = comment + } + }) + this.recentSupportersCache = Array.from(map.values()).sort((a, b) => b.amount - a.amount) + return this.recentSupportersCache + } + private async getZapEndpoint(profile: TProfile): Promise