Skip to content

Commit

Permalink
Transaction list placeholder (#4185)
Browse files Browse the repository at this point in the history
# Motivation

[The
design](https://www.figma.com/file/x8dk5axQUf8Bi43uUsqCHc/NNS-Production-%26-Hand-over?type=design&node-id=1319-1085&mode=design&t=BiIOfY7BQjiYMj8P-4)
for the logged-out wallet page has a new placeholder for when there are
no transactions.
We should use this also when the user is logged in but there are no
transactions.

This PR introduces a simple component to use as the placeholder when
there are no transactions and uses it just for the logged-in case.


# Changes

1. Add `NoTransactions` component.
2. Use it instead of just text when there are no transactions.

# Tests

Unit tests and page objects were updated.

# Todos

- [x] Add entry to changelog (if necessary).
  • Loading branch information
dskloetd authored Jan 12, 2024
1 parent 9122adb commit 38dd1b8
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG-Nns-Dapp-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ proposal is successful, the changes it released will be moved from this file to
#### Changed

* New light and dark theme colors.
* Placeholder when the transaction list is empty.

#### Deprecated

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { InfiniteScroll, Spinner } from "@dfinity/gix-components";
import { i18n } from "$lib/stores/i18n";
import NoTransactions from "./NoTransactions.svelte";
import IcrcTransactionCard from "./IcrcTransactionCard.svelte";
import SkeletonCard from "../ui/SkeletonCard.svelte";
import type { UiTransaction } from "$lib/types/transaction";
Expand All @@ -13,7 +13,7 @@

<div data-tid="transactions-list" class="container">
{#if transactions.length === 0 && !loading}
{$i18n.wallet.no_transactions}
<NoTransactions />
{:else if transactions.length === 0 && loading}
<SkeletonCard cardType="info" />
<SkeletonCard cardType="info" />
Expand Down
20 changes: 20 additions & 0 deletions frontend/src/lib/components/accounts/NoTransactions.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script lang="ts">
import TransactionIcon from "$lib/components/accounts/TransactionIcon.svelte";
import { i18n } from "$lib/stores/i18n";
</script>

<div class="no-transaction description" data-tid="no-transactions-component">
<div class="transaction-icon">
<TransactionIcon type="received" />
</div>
{$i18n.wallet.no_transactions}
</div>

<style lang="scss">
.no-transaction {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--padding-2x);
}
</style>
4 changes: 2 additions & 2 deletions frontend/src/lib/components/accounts/TransactionList.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script lang="ts">
import type { Transaction as NnsTransaction } from "$lib/canisters/nns-dapp/nns-dapp.types";
import type { Account } from "$lib/types/account";
import { i18n } from "$lib/stores/i18n";
import SkeletonCard from "$lib/components/ui/SkeletonCard.svelte";
import NnsTransactionCard from "./NnsTransactionCard.svelte";
import NoTransactions from "./NoTransactions.svelte";
import { getContext } from "svelte";
import {
WALLET_CONTEXT_KEY,
Expand Down Expand Up @@ -31,7 +31,7 @@
{#if account === undefined || transactions === undefined}
<SkeletonCard cardType="info" />
{:else if transactions.length === 0}
{$i18n.wallet.no_transactions}
<NoTransactions />
{:else}
{#each extendedTransactions as { toSelfTransaction, transaction } (`${transaction.timestamp.timestamp_nanos}-${toSelfTransaction}`)}
<div animate:flip={{ duration: 250 }} class="flip">
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@
"principal": "Principal",
"direction_from": "From:",
"direction_to": "To:",
"no_transactions": "No transactions",
"no_transactions": "Transactions will appear here.",
"icp_qrcode_aria_label": "A QR code that renders the address to receive ICP",
"icrc_qrcode_aria_label": "A QR code that renders the address to receive $tokenSymbol",
"token_address": "$tokenSymbol Address",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe("IcrcTransactionList", () => {
completed: true,
});

expect(await po.getText()).toBe("No transactions");
expect(await po.hasNoTransactions()).toBe(true);
});

it("should render transactions", async () => {
Expand All @@ -69,5 +69,6 @@ describe("IcrcTransactionList", () => {
});

expect(await po.getTransactionCardPos()).toHaveLength(2);
expect(await po.hasNoTransactions()).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ describe("TransactionList", () => {
it("should display no-transactions message", async () => {
const po = renderComponent({ account: mockMainAccount, transactions: [] });

expect(await po.getText()).toBe("No transactions");
expect(await po.hasNoTransactions()).toBe(true);
});

it("should render transactions", async () => {
Expand All @@ -57,5 +57,6 @@ describe("TransactionList", () => {
});

expect(await po.getTransactionCardPos()).toHaveLength(20);
expect(await po.hasNoTransactions()).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export class IcrcTransactionsListPo extends BasePageObject {
return TransactionCardPo.allUnder(this.root);
}

hasNoTransactions(): Promise<boolean> {
return this.isPresent("no-transactions-component");
}

async waitForLoaded(): Promise<void> {
await this.waitFor();
await this.getSkeletonCardPo().waitForAbsent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export class TransactionListPo extends BasePageObject {
return TransactionCardPo.allUnder(this.root);
}

hasNoTransactions(): Promise<boolean> {
return this.isPresent("no-transactions-component");
}

async waitForLoaded(): Promise<void> {
await this.waitFor();
await this.getSkeletonCardPo().waitForAbsent();
Expand Down

0 comments on commit 38dd1b8

Please sign in to comment.