diff --git a/components/Layout/FiltersFrame.js b/components/Layout/FiltersFrame.js index c772e4e83..fcd01610e 100644 --- a/components/Layout/FiltersFrame.js +++ b/components/Layout/FiltersFrame.js @@ -68,7 +68,9 @@ export default function FiltersFrame({ rowsPerPage, setRowsPerPage, onlyCsv, - filters + filters, + loading, + setLoading }) { const { t } = useTranslation() const router = useRouter() @@ -104,6 +106,8 @@ export default function FiltersFrame({ }, [activeView]) const handleChangePage = (event, newPage) => { + if(loading) return + setLoading(true) setPage(newPage) } @@ -148,6 +152,7 @@ export default function FiltersFrame({ rowsPerPage={rowsPerPage} onRowsPerPageChange={handleChangeRowsPerPage} rowsPerPageOptions={width <= 440 ? [] : rowsPerPageOptions} + disabled={loading} //slotProps={{ select: }} /> @@ -157,7 +162,7 @@ export default function FiltersFrame({ {orderList && ( <> - + @@ -182,6 +187,7 @@ export default function FiltersFrame({ rowsPerPage={rowsPerPage} onRowsPerPageChange={handleChangeRowsPerPage} rowsPerPageOptions={rowsPerPageOptions} + disabled={loading} //slotProps={{ select: }} /> @@ -203,7 +209,9 @@ export default function FiltersFrame({ {orderList?.map((item, i) => (
  • hideMobileSortMenu(item.value)} suppressHydrationWarning > diff --git a/components/Layout/Header/MobileMenu.js b/components/Layout/Header/MobileMenu.js index d4fc939a5..67a58ad4e 100644 --- a/components/Layout/Header/MobileMenu.js +++ b/components/Layout/Header/MobileMenu.js @@ -173,6 +173,9 @@ export default function MobileMenu({ {t('menu.services.tax-reports')} + + Try Out Tax Reports + {t('menu.project-registration')} diff --git a/components/Layout/Header/index.js b/components/Layout/Header/index.js index 81376d486..ed4b458a5 100644 --- a/components/Layout/Header/index.js +++ b/components/Layout/Header/index.js @@ -199,6 +199,7 @@ export default function Header({ {t('menu.services.nft-mint')} {t('menu.usernames')} {t('menu.services.tax-reports')} + Try Out Tax Reports {t('menu.project-registration')} {!devNet && {t('menu.price-alerts', { nativeCurrency })}} {t('menu.submit-offline-tx')} diff --git a/components/UI/SimpleSelect.js b/components/UI/SimpleSelect.js index e146a8c5a..6bf7394d5 100644 --- a/components/UI/SimpleSelect.js +++ b/components/UI/SimpleSelect.js @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import Select from 'react-select' -export default function SimpleSelect({ value, setValue, optionsList, className }) { +export default function SimpleSelect({ value, setValue, optionsList, className, disabled }) { const [rendered, setRendered] = useState(false) const [choosenOption, setChoosenOption] = useState() @@ -36,6 +36,7 @@ export default function SimpleSelect({ value, setValue, optionsList, className } setValue(a.value) }} isSearchable={false} + isDisabled={disabled} className={`dropdown ${className}`} classNamePrefix="react-select" /> diff --git a/pages/admin/pro/history.js b/pages/admin/pro/history.js index 51833ab7c..ac8242810 100644 --- a/pages/admin/pro/history.js +++ b/pages/admin/pro/history.js @@ -48,6 +48,7 @@ const showAmount = (amount) => { } const showFiat = (fiat, selectedCurrency) => { + if (isNaN(fiat)) return '' if (!fiat && fiat !== 0) return '' return ( 0 ? 'green' : fiat < 0 ? 'red' : '')}> @@ -195,6 +196,12 @@ const platformList = [ { value: 'CryptoTax', label: 'CryptoTax' } ] +const defaultWalletList = [ + 'rDLNm4ehD7XQCtYKWuMjEKY7TCfmf3CwzH', + 'r3sQYvXxc82iSNs5DnUUvXtcQQQqigCdW', + 'raWYT6DD2XFAvjCqRPsCCzr1CMBzJydf9E', +] + export default function History({ queryAddress, selectedCurrency, @@ -368,6 +375,7 @@ export default function History({ }, []) useEffect(() => { + setLoading(true) if (filteredActivities.length > 0) { if (rowsPerPage === -1) { setCurrentList(filteredActivities) @@ -377,8 +385,14 @@ export default function History({ } else { setCurrentList([]) } - if ((page + 2) * rowsPerPage > filteredActivities.length && data?.marker) { + + if(page * rowsPerPage > data?.total) { + setPage(0) + getProAddressHistory() + }else if ((page + 2) * rowsPerPage > filteredActivities.length && data?.marker) { getProAddressHistory({ marker: data.marker }) + } else { + setLoading(false) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [filteredActivities, page, rowsPerPage]) @@ -430,8 +444,12 @@ export default function History({ ] const getProAddressHistory = async (options) => { - if (addressesToCheck.length === 0) return - setLoading(true) + if (addressesToCheck.length === 0) { + setLoading(false) + setActivities([]) + setData(null) + return + } let orderPart = order let sortCurrency = null @@ -475,7 +493,6 @@ export default function History({ setErrorMessage(t(error.response?.data?.error || 'error.' + error.message)) } }) - setLoading(false) let res = response?.data /* { @@ -535,7 +552,7 @@ export default function History({ } setData(res) // last request data if (options?.marker) { - setActivities(activities.concat(res.activities)) // joines data + setActivities(prevActivities => prevActivities.concat(res.activities)) // joins data } else { setActivities(res.activities) // rewrite old data } @@ -544,58 +561,70 @@ export default function History({ const getVerifiedAddresses = async () => { setLoadingVerifiedAddresses(true) - const response = await axiosAdmin.get('user/addresses').catch((error) => { + if (!sessionToken) { + // Create hardcoded wallet data for non-authenticated users + const walletDatas = defaultWalletList.map((address, index) => ({ + address: address, + name: `Test Wallet ${index + 1}`, + crawler: { status: "synced" } + })) + setVerifiedAddresses(walletDatas) setLoadingVerifiedAddresses(false) - if (error.response?.data?.error === 'errors.token.required') { - router.push('/admin') - return + // Set first hardcoded wallet as default selection + if (addressesToCheck?.length === 0 && walletDatas[0]?.address) { + setAddressesToCheck([walletDatas[0].address]) } - if (error && error.message !== 'canceled') { - setErrorMessage(t(error.response?.data?.error || 'error.' + error.message)) - } - }) - setLoadingVerifiedAddresses(false) - const data = response?.data - /* - { - "total": 1, - "count": 1, - "addresses": [ - { - "id": 28, - "createdAt": 1721741550, - "address": "raN6cSu", - "name": "vasia", - "crawler": { - "status": "queued", - "createdAt": 1728212999, - "updatedAt": 1728212999, - "lastCrawledAt": null, - "firstLedgerIndex": null, - "currentLedgerIndex": null, - "lastLedgerIndex": null + } else { + const response = await axiosAdmin.get('user/addresses').catch((error) => { + setLoadingVerifiedAddresses(false) + if (error.response?.data?.error === 'errors.token.required') { + router.push('/admin') + return + } + if (error && error.message !== 'canceled') { + setErrorMessage(t(error.response?.data?.error || 'error.' + error.message)) + } + }) + const data = response?.data + /* + { + "total": 1, + "count": 1, + "addresses": [ + { + "id": 28, + "createdAt": 1721741550, + "address": "raN6cSu", + "name": "vasia", + "crawler": { + "status": "queued", + "createdAt": 1728212999, + "updatedAt": 1728212999, + "lastCrawledAt": null, + "firstLedgerIndex": null, + "currentLedgerIndex": null, + "lastLedgerIndex": null + } } - } - ] + ] + } + */ + setVerifiedAddresses(data?.addresses) + setLoadingVerifiedAddresses(false) + if (addressesToCheck?.length === 0 && data?.addresses?.[0]?.address) { + setAddressesToCheck([data.addresses[0].address]) } - */ - setVerifiedAddresses(data?.addresses) - if (addressesToCheck?.length === 0 && data?.addresses?.[0]?.address) { - setAddressesToCheck([data.addresses[0].address]) } } useEffect(() => { - if (sessionToken) { - getVerifiedAddresses() - } + getVerifiedAddresses() // eslint-disable-next-line react-hooks/exhaustive-deps }, [sessionToken]) useEffect(() => { - if (sessionToken) { - getProAddressHistory() - } + setLoading(true) + getProAddressHistory() // eslint-disable-next-line react-hooks/exhaustive-deps }, [addressesToCheck, selectedCurrency, period, order, sessionToken]) @@ -613,6 +642,17 @@ export default function History({

    Pro address balances history

    + {!sessionToken && ( +
    +

    + Use these test wallets to try all features of the page. Want to add your address?{' '} + + Sign in here + +

    +
    + )} +
    @@ -630,285 +670,268 @@ export default function History({
    - {sessionToken ? ( + <> - + {verifiedAddresses?.length > 0 && data && activities && data.total > activities.length && ( +
    + +
    +
    +
    + )} +
    Addresses
    + {verifiedAddresses?.length > 0 ? ( <> - {verifiedAddresses?.length > 0 && data && activities && data.total > activities.length && ( -
    - -
    -
    + + + + + + + +
    + avatar + + {address.name} -{' '} + {crawlerStatus(address.crawler, { inline: true })} +
    + {addressLink(address.address, { short: 10 })} +
    +
    - )} -
    Addresses
    - {verifiedAddresses?.length > 0 ? ( - <> - {verifiedAddresses.map((address, i) => ( -
    - { - setAddressesToCheck( - addressesToCheck.includes(address.address) - ? addressesToCheck.filter((a) => a !== address.address) - : [...addressesToCheck, address.address] - ) - }} - outline - checkmarkStyle={{ top: '10px' }} - > - - - - - - - -
    - avatar - - {address.name} -{' '} - {crawlerStatus(address.crawler, { inline: true })} -
    - {addressLink(address.address, { short: 10 })} -
    -
    -
    - ))} - + ))} + + ) : ( + <> + {loadingVerifiedAddresses ? ( + 'Loading data...' ) : ( - <> - {loadingVerifiedAddresses ? ( - 'Loading data...' - ) : ( -
    -
    - - Add - -
    - )} - +
    +
    + + Add + +
    )} -
    - Period - -
    -
    - - Remove dust transactions - -
    -
    - Tax Export Platform - - {rendered && ( - header.platform.toLowerCase() === platformCSVExport.toLowerCase() - )?.headers || [] - } - filename={'export ' + platformCSVExport + ' ' + new Date().toISOString() + '.csv'} - className={'button-action' + (!(activities?.length > 0) ? ' disabled' : '')} - uFEFF={platformCSVExport === 'BlockPit' ? false : undefined} - > - CSV for {platformCSVExport} - - )} - {platformCSVExport === 'Koinly' && ( - <> -
    -
    - Let us know if we miss koinlyIDs for your tokens. We will add them to the system. - - )} -
    + )} +
    + Period + +
    +
    + + Remove dust transactions + +
    +
    + Tax Export Platform + + {rendered && ( + header.platform.toLowerCase() === platformCSVExport.toLowerCase() + )?.headers || [] + } + filename={'export ' + platformCSVExport + ' ' + new Date().toISOString() + '.csv'} + className={'button-action' + (!(activities?.length > 0) ? ' disabled' : '')} + uFEFF={platformCSVExport === 'BlockPit' ? false : undefined} + > + CSV for {platformCSVExport} + + )} + {platformCSVExport === 'Koinly' && ( + <> +
    +
    + Let us know if we miss koinlyIDs for your tokens. We will add them to the system. + + )} +
    + + <> + {addressesToCheck.length > 0 && ( <> - {addressesToCheck.length > 0 && ( - <> - {!width || width > 800 ? ( - 800 ? { width: 780 } : {}}> - - - - - {addressesToCheck.length > 1 && } - - - - - - - - - {currentList?.length > 0 ? ( - <> - {currentList.map((a, i) => ( - - - - {addressesToCheck.length > 1 && } - - - - - - - ))} - - ) : ( - - + + + )} + +
    #TimestampAddressTxMemoTransfer FeeTx FeeBalance change
    {a.index}{fullDateAndTime(a.timestamp)}{addressName(a.address)} - - - - -
    - 20 ? 'tooltip' : ''}> - {a.memo && a.memo?.slice(0, 20) + (a.memo?.length > 20 ? '...' : '')} - {a.memo?.length > 20 && {a.memo}} - -
    -
    - {/* showAmount(a.transferFee) */} -
    - {a.transferFee ? ( - niceNumber(a.transferFeeInFiats?.[selectedCurrency], 0, selectedCurrency, 6) - ) : ( -
    - )} -
    - {showAmount(a.txFee)} -
    - {a.txFee ? ( - niceNumber(a.txFeeInFiats?.[selectedCurrency], 0, selectedCurrency, 6) - ) : ( -
    - )} -
    - {showAmount(a.amount)} -
    - {showFiat(a.amountInFiats?.[selectedCurrency], selectedCurrency) ||
    } -
    - {loading ? 'Loading data...' : 'There is no data to show here.'} + {!width || width > 800 ? ( + 800 ? { width: 780 } : {}}> + + + + + {addressesToCheck.length > 1 && } + + + + + + + + + {currentList?.length > 0 ? ( + <> + {currentList.map((a, i) => ( + + + + {addressesToCheck.length > 1 && } + + + + + - )} - -
    #TimestampAddressTxMemoTransfer FeeTx FeeBalance change
    {a.index}{fullDateAndTime(a.timestamp)}{addressName(a.address)} + + + + +
    + 20 ? 'tooltip' : ''}> + {a.memo && a.memo?.slice(0, 20) + (a.memo?.length > 20 ? '...' : '')} + {a.memo?.length > 20 && {a.memo}} + +
    +
    + {/* showAmount(a.transferFee) */} +
    + {a.transferFee ? ( + niceNumber(a.transferFeeInFiats?.[selectedCurrency], 0, selectedCurrency, 6) + ) : ( +
    + )} +
    + {showAmount(a.txFee)} +
    + {a.txFee ? ( + niceNumber(a.txFeeInFiats?.[selectedCurrency], 0, selectedCurrency, 6) + ) : ( +
    + )} +
    + {showAmount(a.amount)} +
    + {showFiat(a.amountInFiats?.[selectedCurrency], selectedCurrency) ||
    }
    - ) : ( - - - {currentList?.length > 0 ? ( - <> - {currentList.map((a, i) => ( - - - - - ))} - - ) : ( - - + + + )} + +
    #{a.index} -

    - Timestamp: {fullDateAndTime(a.timestamp)} -

    - {addressesToCheck.length > 1 && ( -

    - Address: {addressName(a.address)} -

    - )} -

    Type: {a.txType}

    -

    - Ledger Amount: {showAmount(a.amount)} -

    -

    - {selectedCurrency.toUpperCase()} equavalent:{' '} - {showFiat(a.amountInFiats?.[selectedCurrency], selectedCurrency)} -

    - {a.memo && ( -

    Memo: {a.memo?.slice(0, 197) + (a.memo?.length > 197 ? '...' : '')}

    - )} -

    - Tx: -

    -
    - {loading ? 'Loading data...' : 'There is no data to show here.'} + ))} + + ) : ( +
    + {loading ? 'Loading data...' : 'There is no data to show here.'} +
    + ) : ( + + + {currentList?.length > 0 ? ( + <> + {currentList.map((a, i) => ( + + + - )} - -
    #{a.index} +

    + Timestamp: {fullDateAndTime(a.timestamp)} +

    + {addressesToCheck.length > 1 && ( +

    + Address: {addressName(a.address)} +

    + )} +

    Type: {a.txType}

    +

    + Ledger Amount: {showAmount(a.amount)} +

    +

    + {selectedCurrency.toUpperCase()} equavalent:{' '} + {showFiat(a.amountInFiats?.[selectedCurrency], selectedCurrency)} +

    + {a.memo && ( +

    Memo: {a.memo?.slice(0, 197) + (a.memo?.length > 197 ? '...' : '')}

    + )} +

    + Tx: +

    - )} - + ))} + + ) : ( +
    + {loading ? 'Loading data...' : 'There is no data to show here.'} +
    )} -
    -
    - {errorMessage ?
    {errorMessage}
    :
    } -
    - - ) : ( - <> -
    -
    -

    - View detailed balance history for your verified addresses.

    -

    - Export data for tax reporting and analysis.

    -
    -
    - Read how it works: XRP and XAH Taxes -
    -
    -
    -
    -
    - -
    -
    + )}
    +
    + {errorMessage ?
    {errorMessage}
    :
    } - )} +
    )