omnipay-savings-sdk
Version:
Omnipay Savings SDK
191 lines (190 loc) • 10.9 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const react_native_1 = require("react-native");
const dayjs_1 = __importDefault(require("dayjs"));
const react_query_1 = require("@tanstack/react-query");
const utils_1 = require("../../utils");
const Text_1 = require("../Text");
const transactionCard_1 = __importDefault(require("../Common/transactionCard"));
const threePane_1 = __importDefault(require("../ToggleTab/threePane"));
const actions_1 = require("../../services/actions");
const SDKConfigContext_1 = require("../../contexts/SDKConfigContext");
const TransactionsList = ({ savingsId, recordsPerPage = 10, limit, showScrollIndicator = false, contentContainerStyle, scrollEnabled = true, showTabs = true, useHistoryEndpoint = false, }) => {
const { apiKey, primaryColor } = (0, SDKConfigContext_1.useSDKConfig)();
const [tabRoute, setTabRoute] = (0, react_1.useState)(0);
// Convert tab route to transaction type for API
const transactionType = (0, react_1.useMemo)(() => {
if (tabRoute === 1) {
return 'Credit';
}
if (tabRoute === 2) {
return 'Debit';
}
return undefined; // undefined means 'All' - don't pass transactionType parameter
}, [tabRoute]);
// Query key should be different for history vs savings transactions
const queryKey = useHistoryEndpoint
? ['savingsTransactionHistory', apiKey, transactionType]
: ['savingsTransactions', savingsId, apiKey, transactionType];
// Query for transactions with infinite loading
const { data: transactionsData, isLoading, isError, fetchNextPage, hasNextPage, isFetchingNextPage, isFetching, } = (0, react_query_1.useInfiniteQuery)({
queryKey,
queryFn: async ({ pageParam }) => {
try {
const params = {
recordsPerPage,
nextPageToken: pageParam,
};
// Only add transactionType if it's not 'All'
if (transactionType) {
params.transactionType = transactionType;
}
let result;
if (useHistoryEndpoint) {
// Use history endpoint - doesn't need savingsId
result = await (0, actions_1.getSavingsTransactionHistory)(apiKey, params);
console.log(result, 'result');
}
else {
// Use existing endpoint - needs savingsId
if (!savingsId) {
throw new Error('savingsId is required when not using history endpoint');
}
params.savingsId = savingsId;
result = await (0, actions_1.getSavingsTransactionsList)(apiKey, params);
}
// Ensure we always return a valid structure
return {
transactionsList: Array.isArray(result === null || result === void 0 ? void 0 : result.transactionsList) ? result.transactionsList : [],
nextPageToken: (result === null || result === void 0 ? void 0 : result.nextPageToken) || undefined,
};
}
catch (error) {
console.error('Error fetching transactions:', error);
// Return empty structure on error
return {
transactionsList: [],
nextPageToken: undefined,
};
}
},
getNextPageParam: (lastPage) => {
if (!lastPage || typeof lastPage !== 'object') {
return undefined;
}
return lastPage.nextPageToken || undefined;
},
initialPageParam: undefined,
retry: 2,
enabled: useHistoryEndpoint || !!savingsId,
// Add default data structure to prevent undefined errors
initialData: {
pages: [],
pageParams: [],
},
});
// Safely flatten all pages into a single transactions array
const allTransactions = (0, react_1.useMemo)(() => {
try {
if (!(transactionsData === null || transactionsData === void 0 ? void 0 : transactionsData.pages) || !Array.isArray(transactionsData.pages)) {
return [];
}
const flattened = transactionsData.pages
.filter(page => page && typeof page === 'object')
.flatMap(page => {
if (!Array.isArray(page.transactionsList)) {
return [];
}
return page.transactionsList.filter((transaction) => transaction &&
typeof transaction === 'object' &&
transaction.transactionId);
});
return flattened;
}
catch (error) {
console.error('Error processing transactions:', error);
return [];
}
}, [transactionsData]);
// Apply limit if specified (no need for transaction type filtering since it's done server-side)
const filteredTransactions = (0, react_1.useMemo)(() => {
if (!Array.isArray(allTransactions)) {
return [];
}
// Apply limit if specified
if (limit) {
return allTransactions.slice(0, limit);
}
return allTransactions;
}, [allTransactions, limit]);
// Group transactions by day
const getDayWiseTransactions = () => {
if (!Array.isArray(filteredTransactions) || filteredTransactions.length === 0) {
return [];
}
const transactionsWithDay = filteredTransactions
.filter((el) => el && el.createdDate)
.map(function (el) {
const formattedDay = (0, utils_1.formatDate)(el.createdDate, 'MMM D, YYYY');
const todayDate = (0, utils_1.formatDate)(new Date(), 'MMM D, YYYY');
const dayDifference = (0, dayjs_1.default)(todayDate).diff(formattedDay, 'day');
return Object.assign(Object.assign({}, el), { dayName: dayDifference === 0
? 'Today'
: dayDifference === 1
? 'Yesterday'
: formattedDay });
});
const dayGroupTransactions = (0, utils_1.groupArray)(transactionsWithDay, 'dayName');
return Object.entries(dayGroupTransactions).map(([key, value]) => ({
title: key,
data: value,
}));
};
const dayWiseTransactions = (0, react_1.useMemo)(() => getDayWiseTransactions(), [filteredTransactions]);
// Render content area (loader, error, empty state, or transactions)
const renderContent = () => {
// Show loader for initial load or refetching
if (isLoading || (isFetching && !isLoading)) {
return ((0, jsx_runtime_1.jsx)(react_native_1.View, Object.assign({ style: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: (0, utils_1.ms)(50),
} }, { children: (0, jsx_runtime_1.jsx)(react_native_1.ActivityIndicator, { size: "small", color: primaryColor }) })));
}
// Show error state
if (isError) {
return ((0, jsx_runtime_1.jsx)(react_native_1.View, Object.assign({ style: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: (0, utils_1.ms)(50),
} }, { children: (0, jsx_runtime_1.jsx)(Text_1.Text, { color: utils_1.Colors.neutral90, fontWeight: "400", fontFamily: 'Gordita-Regular', fontSize: 14, text: "Failed to load transactions" }) })));
}
// Show empty state
if (filteredTransactions.length === 0) {
return ((0, jsx_runtime_1.jsx)(react_native_1.View, Object.assign({ style: { alignItems: 'center', paddingTop: (0, utils_1.ms)(20) } }, { children: (0, jsx_runtime_1.jsx)(Text_1.Text, { color: utils_1.Colors.neutral90, fontWeight: "400", fontFamily: 'Gordita-Regular', fontSize: (0, utils_1.fontSz)(14), text: "No transactions found" }) })));
}
// Show transactions list
return ((0, jsx_runtime_1.jsx)(react_native_1.SectionList, { scrollEnabled: scrollEnabled, showsVerticalScrollIndicator: showScrollIndicator, sections: dayWiseTransactions, contentContainerStyle: contentContainerStyle, style: { marginTop: showTabs ? (0, utils_1.ms)(4) : 0 }, onEndReached: () => {
if (hasNextPage && !isFetchingNextPage && !limit) {
fetchNextPage();
}
}, onEndReachedThreshold: 0.3, ListFooterComponent: isFetchingNextPage && !limit ? ((0, jsx_runtime_1.jsx)(react_native_1.View, Object.assign({ style: { padding: (0, utils_1.ms)(20), alignItems: 'center' } }, { children: (0, jsx_runtime_1.jsx)(react_native_1.ActivityIndicator, { size: "small", color: primaryColor }) }))) : null, renderItem: ({ item, index }) => {
return ((0, jsx_runtime_1.jsx)(transactionCard_1.default, { status: item === null || item === void 0 ? void 0 : item.transactionType, title: (item === null || item === void 0 ? void 0 : item.description) || (item === null || item === void 0 ? void 0 : item.narration), transactionType: item === null || item === void 0 ? void 0 : item.transactionType, amount: item === null || item === void 0 ? void 0 : item.amount, createdDate: item === null || item === void 0 ? void 0 : item.createdDate, showTransactionType: true, onPress: () => { } }, index));
}, renderSectionHeader: ({ section }) => ((0, jsx_runtime_1.jsx)(react_native_1.View, Object.assign({ style: {
backgroundColor: utils_1.Colors.white,
paddingTop: (0, utils_1.ms)(10),
paddingBottom: (0, utils_1.ms)(5),
} }, { children: (0, jsx_runtime_1.jsx)(Text_1.Text, { color: '#515A65', fontWeight: "500", fontFamily: 'Gordita-Medium', fontSize: (0, utils_1.fontSz)(12), lineHeight: (0, utils_1.fontSz)(18), text: section.title }) }))), keyExtractor: (item, index) => `${item.transactionId}-${index}` }));
};
return ((0, jsx_runtime_1.jsxs)(react_native_1.View, Object.assign({ style: { flex: 1 } }, { children: [showTabs && ((0, jsx_runtime_1.jsx)(threePane_1.default, { selectedTab: (e) => {
setTabRoute(e);
}, currentTab: tabRoute, firstLabel: 'All', secondLabel: 'Credit', thirdLabel: 'Debit' })), renderContent()] })));
};
exports.default = TransactionsList;
;