Skip to content
This repository was archived by the owner on Feb 5, 2025. It is now read-only.

feat: add message pagination to buy-me-coffee so you can read all messages #516

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
22 changes: 21 additions & 1 deletion template/web/app/buy-me-coffee/_components/ContractDemo.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { clsx } from 'clsx';
import Button from '@/components/Button/Button';
import useOnchainCoffeeMemos from '../_hooks/useOnchainCoffeeMemos';
import FormBuyCoffee from './FormBuyCoffee';
import Memos from './Memos';

export default function BuyMeCoffeeContractDemo() {
const { memos, refetchMemos } = useOnchainCoffeeMemos();
const pageSize = 5;
const { memos, refetchMemos, currentPage, goToPreviousPage, goToNextPage } =
useOnchainCoffeeMemos(pageSize);

return (
<div
Expand All @@ -22,6 +25,23 @@ export default function BuyMeCoffeeContractDemo() {
<h2 className="mb-5 w-fit text-2xl font-semibold text-white">Messages from supporters</h2>

{memos?.length > 0 && <Memos memos={memos} />}
<div className="mt-4 flex flex items-center justify-between">
<Button
className="w-auto px-10"
onClick={goToPreviousPage}
disabled={currentPage < 1}
buttonContent={<span>Read older messages</span>}
/>

<div>Page {currentPage + 1}</div>

<Button
className="w-auto px-10"
onClick={goToNextPage}
disabled={memos.length < pageSize}
buttonContent={<span>Read newer messages</span>}
/>
</div>
</section>
<aside>
<div
Expand Down
29 changes: 13 additions & 16 deletions template/web/app/buy-me-coffee/_components/Memos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,19 @@ function Memos({ memos }: MemosProps) {
}
return (
<ul className="flex w-full flex-col items-center gap-10">
{memos
.map((memo) => {
return (
<MemoCard
key={memo.time.toString()}
numCoffees={memo.numCoffees}
userName={memo.userName}
twitterHandle={memo.twitterHandle}
message={memo.message}
userAddress={memo.userAddress}
time={memo.time}
/>
);
})
.reverse()
.slice(0, 8)}
{memos.map((memo) => {
return (
<MemoCard
key={memo.time.toString()}
numCoffees={memo.numCoffees}
userName={memo.userName}
twitterHandle={memo.twitterHandle}
message={memo.message}
userAddress={memo.userAddress}
time={memo.time}
/>
);
})}
</ul>
);
}
Expand Down
25 changes: 20 additions & 5 deletions template/web/app/buy-me-coffee/_hooks/useOnchainCoffeeMemos.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMemo } from 'react';
import { useState, useMemo, useCallback } from 'react';
import { useReadContract } from 'wagmi';
import { markStep } from '@/utils/analytics';
import { useBuyMeACoffeeContract } from '../_contracts/useBuyMeACoffeeContract';
Expand All @@ -7,27 +7,42 @@ import type { CoffeeMemo } from '../_components/types';
/**
* Hooks is abstracting away the logic of calling a read-only function on a contract.
* offers a refetch function to refetch the data.
* @returns The memos and a function to refetch them.
* @returns The memos, a function to refetch them, and paging functions.
*/
function useOnchainCoffeeMemos() {
function useOnchainCoffeeMemos(pageSize: number = 5) {
const contract = useBuyMeACoffeeContract();
const [currentPage, setCurrentPage] = useState(0);

const fetchMemosArgs: [bigint, bigint] = [BigInt(currentPage * pageSize), BigInt(pageSize)];

markStep('useReadContract.refetchMemos');
const contractReadResult = useReadContract({
address: contract.status === 'ready' ? contract.address : undefined,
abi: contract.abi,
functionName: 'getMemos',
args: [BigInt(0), BigInt(25)], // TODO : Implement Paging
args: fetchMemosArgs,
});
markStep('useReadContract.refetchMemos');

const goToNextPage = useCallback(() => {
setCurrentPage((prevPage) => prevPage + 1);
}, []);

const goToPreviousPage = useCallback(() => {
setCurrentPage((prevPage) => (prevPage > 0 ? prevPage - 1 : 0));
}, []);

return useMemo(
() => ({
memos:
contractReadResult.status === 'success' ? (contractReadResult.data as CoffeeMemo[]) : [],
refetchMemos: contractReadResult.refetch,
currentPage,
goToNextPage,
goToPreviousPage,
pageSize,
}),
[contractReadResult],
[contractReadResult, currentPage, goToNextPage, goToPreviousPage],
);
}

Expand Down