import { createSelector } from "reselect" ; import { Account , Info , Tab , Transaction , TransactionType } from "../types" ; import { AllState } from ".." ; import { mapTransaction } from "../util/transaction" ; function createTransactionsByRecencyComparator ( prefix ? ) { type PrefixedArg = { [ id ] : any ; } ; return ( a , b ) : number => { a = prefix ? ( a as PrefixedArg ) [ prefix ] : ( a as Transaction ) ; b = prefix ? ( b as PrefixedArg ) [ prefix ] : ( b as Transaction ) ; const dateA = a . date . substring ( 0 , 10 ) ; const dateB = b . date . substring ( 0 , 10 ) ; if ( dateA > dateB ) { return - 1 ; } else if ( dateA < dateB ) { return 1 ; } else { if ( a . timestamp > b . timestamp ) { return - 1 ; } else { return 1 ; } } } ; } function sortTransactions ( transactions ) { transactions = transactions . slice ( ) ; return transactions . sort ( createTransactionsByRecencyComparator ( ) ) ; } function transactions2Accounts ( transactions ) { const participants = { } ; transactions . forEach ( ( transaction ) => { let share ; let total = 0 ; transaction . participants . forEach ( ( participant ) => ( total += participant . amount || 0 ) ) ; if ( transaction . transactionType === "DIRECT" ) { const joinedParticipants = [ ] ; transaction . participants . forEach ( ( participant ) => { if ( participant . amount ) { const participantName = participant . participant ; const storedAmount = participants [ participantName ] || 0 ; participants [ participantName ] = storedAmount + participant . amount ; } else { joinedParticipants . push ( participant ) ; } } ) ; share = total / joinedParticipants . length ; joinedParticipants . forEach ( ( participant ) => { const participantName = participant . participant ; const storedAmount = participants [ participantName ] || 0 ; const newAmount = storedAmount - share ; participants [ participantName ] = newAmount ; } ) ; } else { share = total / transaction . participants . length ; transaction . participants . forEach ( ( participant ) => { const amount = participant . amount || 0 ; const participantName = participant . participant ; const storedAmount = participants [ participantName ] || 0 ; const newAmount = storedAmount - share + amount ; participants [ participantName ] = newAmount ; } ) ; } } ) ; const result = [ ] ; for ( const participant in participants ) { const resultObj = { participant , amount : participants [ participant ] , } ; result . push ( resultObj ) ; } result . sort ( ( a , b ) => ( a . amount < b . amount ? - 1 : 1 ) ) ; return result ; } function getTabIds ( state ) { return state . app . tabs ; } function getDocsById ( state ) { return state . app . docsById ; } export function getCurrentTabId ( state ) { return state . location . payload . tabId || state . location . prev ?. payload . tabId ; } function getTransactionsByTab ( state ) { return state . app . transactionsByTab ; } function getRouteTransition ( state ) { return state . routeTransition . transition ; } function getLocation ( state ) { return state . location . type ; } function getPreviousLocation ( state ) { return state . location ?. prev . type ; } export const getCurrentLocation = createSelector ( [ getRouteTransition , getLocation , getPreviousLocation ] , ( transition , location , previousLocation ) => { if ( transition ) { return previousLocation ; } return location ; } ) ; export const getTabs = createSelector ( [ getTabIds , getDocsById , getTransactionsByTab ] , ( tabIds , docsById , transactionsByTab ) => { const tabs = tabIds . map ( ( tabId ) => { const info = docsById [ "info-" + tabId ] as Info ; const transactionIds = transactionsByTab [ tabId ] || [ ] ; const transactions = transactionIds . map ( ( transactionId ) => docsById [ transactionId ] as Transaction ) ; const mostRecentTransaction = sortTransactions ( transactions ) [ 0 ] ; return { id : tabId , info , mostRecentTransaction , } ; } ) ; const tabsWithTransactions = tabs . filter ( ( tab ) => tab . mostRecentTransaction ) . sort ( createTransactionsByRecencyComparator ( "mostRecentTransaction" ) ) ; const tabsWithoutTransactions = tabs . filter ( ( tab ) => ! tab . mostRecentTransaction ) . sort ( ( a , b ) => ( a < b ? - 1 : 1 ) ) ; return tabsWithTransactions . concat ( tabsWithoutTransactions ) ; } ) ; export const getTabInfo = createSelector ( [ getTabs , getCurrentTabId ] , ( tabs , currentTab ) => { let tab ; tabs . forEach ( ( _tab ) => { if ( _tab . id === currentTab ) { tab = _tab ; } } ) ; return tab ?. info ; } ) ; export const getTransactions = createSelector ( [ getDocsById , getCurrentTabId , getTransactionsByTab ] , ( docsById , currentTab , transactionsByTab ) => { const transactionIds = transactionsByTab [ currentTab ] || [ ] ; const transactions = transactionIds . map ( ( transactionId ) => { const transaction = docsById [ transactionId ] as Transaction ; return mapTransaction ( transaction ) ; } ) ; return sortTransactions ( transactions ) ; } ) ; export const getAccounts = createSelector ( [ getTransactions ] , ( transactions ) => transactions2Accounts ( transactions ) ) ; export const getTotal = createSelector ( [ getTransactions ] , ( transactions ) => transactions . filter ( ( transaction ) => transaction . transactionType === TransactionType . SHARED ) . reduce ( ( total , transaction ) => { const transactionSum = transaction . participants . reduce ( ( sum , participant ) => sum + participant . amount , 0 ) ; return total + transactionSum ; } , 0 ) ) ;