Skip to content

Commit

Permalink
feat: implement pagination in transaction list
Browse files Browse the repository at this point in the history
  • Loading branch information
mnindrazaka committed Sep 19, 2024
1 parent 3f5cdb7 commit a474868
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 47 deletions.
4 changes: 2 additions & 2 deletions apps/api/modules/transactions/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ func (handler Handler) GetTransactionList(w http.ResponseWriter, r *http.Request
return
}

transactions, err := handler.usecase.GetTransactionList(ctx, query, sortBy, order, skip, limit)
transactions, total, err := handler.usecase.GetTransactionList(ctx, query, sortBy, order, skip, limit)
if err != nil {
base.WriteError(w, apiContract.Error{Code: apiContract.SERVER_ERROR, Message: err.Error()})
return
}

json.NewEncoder(w).Encode(apiContract.TransactionList200Response{Data: transactions})
json.NewEncoder(w).Encode(apiContract.TransactionList200Response{Data: transactions, Meta: apiContract.MetaPage{total}})
}

func (handler Handler) GetTransactionById(w http.ResponseWriter, r *http.Request) {
Expand Down
14 changes: 14 additions & 0 deletions apps/api/modules/transactions/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ func (repo Repository) GetTransactionList(ctx context.Context, query string, sor
return transactions, result.Error
}

func (repo Repository) GetTransactionListTotal(ctx context.Context, query string) (int64, error) {
db := utils.GetDbFromCtx(ctx, repo.db)
var count int64
result := db.Table("transactions").Where("deleted_at", nil)

if query != "" {
result = result.Where("name LIKE ?", "%"+query+"%")
}

result = result.Count(&count)

return count, result.Error
}

func (repo Repository) GetTransactionById(ctx context.Context, id int64) (apiContract.Transaction, error) {
db := utils.GetDbFromCtx(ctx, repo.db)

Expand Down
14 changes: 12 additions & 2 deletions apps/api/modules/transactions/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,18 @@ func NewUsecase(repository Repository, productRepository products.Repository, wa
}
}

func (usecase Usecase) GetTransactionList(ctx context.Context, query string, sortBy string, order string, skip int, limit int) ([]apiContract.Transaction, error) {
return usecase.repository.GetTransactionList(ctx, query, sortBy, order, skip, limit)
func (usecase Usecase) GetTransactionList(ctx context.Context, query string, sortBy string, order string, skip int, limit int) ([]apiContract.Transaction, int64, error) {
transactions, err := usecase.repository.GetTransactionList(ctx, query, sortBy, order, skip, limit)
if err != nil {
return []apiContract.Transaction{}, 0, err
}

total, err := usecase.repository.GetTransactionListTotal(ctx, query)
if err != nil {
return []apiContract.Transaction{}, 0, err
}

return transactions, total, nil
}

func (usecase Usecase) GetTransactionById(ctx context.Context, id int64) (apiContract.Transaction, error) {
Expand Down
3 changes: 3 additions & 0 deletions libs/api-contract/src/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -773,11 +773,14 @@ paths:
type: object
required:
- data
- meta
properties:
data:
type: array
items:
$ref: '#/components/schemas/Transaction'
meta:
$ref: '#/components/schemas/MetaPage'
'500':
description: server error
content:
Expand Down
1 change: 1 addition & 0 deletions libs/ui/src/base/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const Pagination = ({
/>
{Array.from(Array(totalPage)).map((_, index) => (
<Button
key={index}
size="$2"
onPress={() => onChangePage(index + 1)}
disabled={currentPage === index + 1}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const TransactionForm = ({
Product will automatically added to transaction
</Paragraph>
</YStack>
<ProductList onItemPress={onAddItem} isSearchAutoFocus />
<ProductList onItemPress={onAddItem} />
</YStack>
</Sheet>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import { useMemo, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
// eslint-disable-next-line @nx/enforce-module-boundaries
import { useTransactionList } from '../../../../../api-contract/src';
import { Event, Listener, useDebounce, useEventEmitter } from '../../../base';
import { Event, Listener, useEventEmitter } from '../../../base';
import { useRouter } from 'solito/router';

const LIMIT = 10;

export const useTransactionListState = () => {
const router = useRouter();

const [searchValue, setSearhValue] = useState('');

const [query, setQuery] = useState('');

const [page, setPage] = useState(1);

useEffect(() => {
setPage(1);
const timeout = setTimeout(() => setQuery(searchValue), 600);
return () => clearTimeout(timeout);
}, [searchValue]);

const { data, status, error, refetch } = useTransactionList({
sortBy: 'created_at',
order: 'desc',
query,
limit: LIMIT,
skip: (page - 1) * LIMIT,
});

const listeners = useMemo<Listener<Event['type']>[]>(
Expand All @@ -31,19 +45,18 @@ export const useTransactionListState = () => {

const { emit } = useEventEmitter(listeners);

const debounce = useDebounce();

const handleSearchInputChange = (text: string) => {
debounce(() => setQuery(text), 600);
};

return {
transactions: data?.data ?? [],
status,
error,
refetch,
handleSearchInputChange,
searchValue,
setSearhValue,
emit,
router,
page,
setPage,
totalItem: data?.meta.total ?? 0,
itemPerPage: LIMIT,
};
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EmptyView, ErrorView, LoadingView } from '../../../base';
import { EmptyView, ErrorView, LoadingView, Pagination } from '../../../base';
import { Input, YStack } from 'tamagui';
import { useTransactionListState } from './TransactionList.state';
import { FlatList } from 'react-native';
Expand All @@ -9,52 +9,66 @@ export const TransactionList = () => {
transactions,
refetch,
status,
handleSearchInputChange,
searchValue,
setSearhValue,
emit,
router,
page,
setPage,
totalItem,
itemPerPage,
} = useTransactionListState();
return (
<YStack gap="$3" flex={1}>
<YStack>
<Input
placeholder="Search Transaction by Customer Name"
onChangeText={handleSearchInputChange}
value={searchValue}
onChangeText={setSearhValue}
/>
</YStack>
{status === 'pending' ? (
<LoadingView title="Fetching Transactions..." />
) : status === 'success' ? (
transactions.length > 0 ? (
<FlatList
data={transactions}
renderItem={({ item: transaction }) => (
<TransactionListItem
name={transaction.name}
total={transaction.total}
createdAt={transaction.createdAt}
paidAt={transaction.paidAt}
walletName={transaction.wallet?.name}
onDeleteMenuPress={() =>
emit({
type: 'TransactionDeleteConfirmation',
transactionId: transaction.id,
})
}
onEditMenuPress={() =>
router.push(`/transactions/${transaction.id}`)
}
onPayMenuPress={() =>
emit({
type: 'TransactionPayConfirmation',
transactionId: transaction.id,
})
}
onPress={() => router.push(`/transactions/${transaction.id}`)}
/>
)}
keyExtractor={(item) => item.id.toString()}
ItemSeparatorComponent={() => <YStack height="$1" />}
/>
<>
<FlatList
data={transactions}
renderItem={({ item: transaction }) => (
<TransactionListItem
name={transaction.name}
total={transaction.total}
createdAt={transaction.createdAt}
paidAt={transaction.paidAt}
walletName={transaction.wallet?.name}
onDeleteMenuPress={() =>
emit({
type: 'TransactionDeleteConfirmation',
transactionId: transaction.id,
})
}
onEditMenuPress={() =>
router.push(`/transactions/${transaction.id}`)
}
onPayMenuPress={() =>
emit({
type: 'TransactionPayConfirmation',
transactionId: transaction.id,
})
}
onPress={() => router.push(`/transactions/${transaction.id}`)}
/>
)}
keyExtractor={(item) => item.id.toString()}
ItemSeparatorComponent={() => <YStack height="$1" />}
/>
<Pagination
currentPage={page}
onChangePage={setPage}
totalItem={totalItem}
itemPerPage={itemPerPage}
/>
</>
) : (
<EmptyView
title="Oops, Transaction is Empty"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ export const getTransactionListScreenDehydratedState =
sortBy: 'created_at',
order: 'desc',
query: '',
limit: 10,
skip: 0,
}),
queryFn: ({ queryKey }) => {
return transactionList({
sortBy: queryKey[1].sortBy,
order: queryKey[1].order,
query: queryKey[1].query,
limit: queryKey[1].limit,
skip: queryKey[1].skip,
});
},
});
Expand Down

0 comments on commit a474868

Please sign in to comment.