Implement pagination in transactions

merge-requests/3333/head
danidfra 2025-03-25 13:31:14 -03:00
rodzic 8b097aeef2
commit 0877e388d2
4 zmienionych plików z 46 dodań i 9 usunięć

Wyświetl plik

@ -89,7 +89,7 @@ interface ITransactions {
limit?: number; limit?: number;
} }
const Transactions = ({ limit = 4 }: ITransactions) => { const Transactions = ({ limit }: ITransactions) => {
const { account } = useOwnAccount(); const { account } = useOwnAccount();
const { transactions } = useTransactions(); const { transactions } = useTransactions();

Wyświetl plik

@ -4,21 +4,24 @@ import { defineMessages, useIntl } from 'react-intl';
import Button from 'soapbox/components/ui/button.tsx'; import Button from 'soapbox/components/ui/button.tsx';
import { Column } from 'soapbox/components/ui/column.tsx'; import { Column } from 'soapbox/components/ui/column.tsx';
import Transactions from 'soapbox/features/wallet/components/transactions.tsx'; import Transactions from 'soapbox/features/wallet/components/transactions.tsx';
import { useTransactions } from 'soapbox/features/zap/hooks/useHooks.ts';
const messages = defineMessages({ const messages = defineMessages({
title: { id: 'wallet.transactions', defaultMessage: 'Transactions' }, title: { id: 'wallet.transactions', defaultMessage: 'Transactions' },
more: { id: 'wallet.transactions.show_more', defaultMessage: 'Show More' }, more: { id: 'wallet.transactions.show_more', defaultMessage: 'Show More' },
loading: { id: 'wallet.loading', defaultMessage: 'Loading…' },
}); });
const WalletTransactions = () => { const WalletTransactions = () => {
const intl = useIntl(); const intl = useIntl();
const { isLoading, expandTransactions } = useTransactions();
return ( return (
<Column label={intl.formatMessage(messages.title)} > <Column label={intl.formatMessage(messages.title)} >
<Transactions limit={20} /> <Transactions />
<div className='flex w-full justify-center'> <div className='flex w-full justify-center'>
<Button icon={moreIcon} theme='primary' to='/wallet/transactions'> <Button icon={isLoading ? undefined : moreIcon} theme='primary' onClick={expandTransactions}>
{intl.formatMessage(messages.more)} {isLoading ? intl.formatMessage(messages.loading) : intl.formatMessage(messages.more)}
</Button> </Button>
</div> </div>
</Column> </Column>

Wyświetl plik

@ -11,9 +11,11 @@ interface WalletState {
wallet: WalletData | null; wallet: WalletData | null;
transactions: Transactions | null; transactions: Transactions | null;
nutzapsList: Record<string, { status: StatusEntity; amount: number; comment: string }>; // TODO: remove nutzapsList: Record<string, { status: StatusEntity; amount: number; comment: string }>; // TODO: remove
prevTransaction?: string | null;
nextTransaction?: string | null;
setWallet: (wallet: WalletData | null) => void; setWallet: (wallet: WalletData | null) => void;
setTransactions: (transactions: Transactions | null) => void; setTransactions: (transactions: Transactions | null, prevTransaction?: string | null, nextTransaction?: string | null) => void;
addNutzap: (statusId: string, data: { status: StatusEntity; amount: number; comment: string }) => void; addNutzap: (statusId: string, data: { status: StatusEntity; amount: number; comment: string }) => void;
} }
@ -25,10 +27,12 @@ interface IWalletInfo {
const useWalletStore = create<WalletState>((set) => ({ const useWalletStore = create<WalletState>((set) => ({
wallet: null, wallet: null,
transactions: null, transactions: null,
prevTransaction: null,
nextTransaction: null,
nutzapsList: {}, nutzapsList: {},
setWallet: (wallet) => set({ wallet }), setWallet: (wallet) => set({ wallet }),
setTransactions: (transactions) => set({ transactions }), setTransactions: (transactions, prevTransaction, nextTransaction) => set({ transactions, prevTransaction, nextTransaction }),
addNutzap: (statusId, data) => addNutzap: (statusId, data) =>
set((state) => ({ set((state) => ({
nutzapsList: { nutzapsList: {
@ -92,7 +96,7 @@ const useWallet = () => {
const useTransactions = () => { const useTransactions = () => {
const api = useApi(); const api = useApi();
const { transactions, setTransactions } = useWalletStore(); const { transactions, nextTransaction, setTransactions } = useWalletStore();
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
@ -100,10 +104,11 @@ const useTransactions = () => {
setIsLoading(true); setIsLoading(true);
try { try {
const response = await api.get('/api/v1/ditto/cashu/transactions'); const response = await api.get('/api/v1/ditto/cashu/transactions');
const { prev, next } = response.pagination();
const data = await response.json(); const data = await response.json();
if (data) { if (data) {
const normalizedData = transactionsSchema.parse(data); const normalizedData = transactionsSchema.parse(data);
setTransactions(normalizedData); setTransactions(normalizedData, prev, next);
} }
} catch (err) { } catch (err) {
const messageError = err instanceof Error ? err.message : 'Transactions not found'; const messageError = err instanceof Error ? err.message : 'Transactions not found';
@ -114,13 +119,37 @@ const useTransactions = () => {
} }
}; };
const expandTransactions = async () => {
if (!nextTransaction || !transactions) {
toast.info('You reached the end of transactions');
return;
}
try {
setIsLoading(true);
const response = await api.get(nextTransaction);
const { prev, next } = response.pagination();
const data = await response.json();
const normalizedData = transactionsSchema.parse(data);
const newTransactions = [...(transactions ?? []), ...normalizedData ];
setTransactions(newTransactions, prev, next);
} catch (err) {
const messageError = err instanceof Error ? err.message : 'Error expanding transactions';
toast.error(messageError);
setError(messageError);
} finally {
setIsLoading(false);
}
};
useEffect(() => { useEffect(() => {
if (!transactions) { if (!transactions) {
getTransactions(); getTransactions();
} }
}, []); }, []);
return { transactions, isLoading, error, getTransactions }; return { transactions, isLoading, error, getTransactions, expandTransactions };
}; };
const useNutzapRequest = () => { const useNutzapRequest = () => {
@ -128,6 +157,8 @@ const useNutzapRequest = () => {
const { nutzapsList, addNutzap } = useWalletStore(); const { nutzapsList, addNutzap } = useWalletStore();
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const { getWallet } = useWallet();
const { getTransactions } = useTransactions();
const nutzapRequest = async (account: AccountEntity, amount: number, comment: string, status?: StatusEntity) => { const nutzapRequest = async (account: AccountEntity, amount: number, comment: string, status?: StatusEntity) => {
setIsLoading(true); setIsLoading(true);
@ -147,6 +178,8 @@ const useNutzapRequest = () => {
} }
toast.success(data.message || 'Nutzap sent successfully!'); toast.success(data.message || 'Nutzap sent successfully!');
getWallet();
getTransactions();
} catch (err) { } catch (err) {
const messageError = err instanceof Error ? err.message : 'An unexpected error occurred'; const messageError = err instanceof Error ? err.message : 'An unexpected error occurred';
setError(messageError); setError(messageError);

Wyświetl plik

@ -1724,6 +1724,7 @@
"wallet.create_wallet.question": "Do you want create one?", "wallet.create_wallet.question": "Do you want create one?",
"wallet.create_wallet.title": "You don't have a wallet", "wallet.create_wallet.title": "You don't have a wallet",
"wallet.invalid_url": "All strings must be valid URLs.", "wallet.invalid_url": "All strings must be valid URLs.",
"wallet.loading": "Loading…",
"wallet.loading_error": "An unexpected error occurred while loading your wallet data.", "wallet.loading_error": "An unexpected error occurred while loading your wallet data.",
"wallet.management": "Wallet Management", "wallet.management": "Wallet Management",
"wallet.mints": "Mints", "wallet.mints": "Mints",