Skip to content

Commit

Permalink
feat: implement Portfolio page with base layout (#6062)
Browse files Browse the repository at this point in the history
# Motivation

The new page for the Portfolio route features a layout with the
following sections:
* Top section
* `TotalAssetsCard`: that takes 100% the width when the user is logged
in but only 1/3 of the space when the `LoginCard` is present.
* `LoginCard` occupies 2/3 of the space when displayed and appears as
the first card on mobile devices.
* Main section
* Cards will take up 50% of the available space, and the stack will
appear on small screens.


https://github.com/user-attachments/assets/7bfbe843-ef68-45bf-801e-4e1cdca3a705

# Changes

- New `Portfolio` page component  
-  Renders the new `Portfolio` page under the `Portfolio` route  
- Displays the appropriate layout in the `(app)/(home)/layout` when the
feature toggle is on; the `Portfolio` page is the default page

# Tests

- Unit tests to verify that the `LoginCard` renders when the user is not
logged in.

# Todos

- [ ] Add entry to changelog (if necessary).
Not necessary
  • Loading branch information
yhabib authored Dec 23, 2024
1 parent 341bade commit 6a9423d
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 3 deletions.
66 changes: 66 additions & 0 deletions frontend/src/lib/pages/Portfolio.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<script lang="ts">
import Card from "$lib/components/portfolio/Card.svelte";
import LoginCard from "$lib/components/portfolio/LoginCard.svelte";
import { authSignedInStore } from "$lib/derived/auth.derived";
</script>

<main data-tid="portfolio-page-component">
<div class="top" class:single-card={$authSignedInStore}>
{#if !$authSignedInStore}
<LoginCard />
{/if}
<Card>Card1</Card>
</div>
<div class="content">
<Card>Card3</Card>
<Card>Card4</Card>
</div>
</main>

<style lang="scss">
@use "@dfinity/gix-components/dist/styles/mixins/media";
main {
display: flex;
flex-direction: column;
gap: var(--padding-2x);
padding: var(--padding-2x);
@include media.min-width(large) {
display: grid;
grid-template-rows: auto 1fr;
gap: var(--padding-3x);
padding: var(--padding-3x);
}
.top {
display: grid;
grid-template-columns: 1fr;
gap: var(--padding-2x);
@include media.min-width(large) {
display: grid;
grid-template-columns: 1fr 2fr;
> :global(article:first-of-type) {
order: 1;
}
&.single-card {
grid-template-columns: 1fr;
}
}
}
.content {
display: grid;
grid-template-columns: 1fr;
gap: var(--padding-2x);
@include media.min-width(large) {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
}
}
</style>
8 changes: 6 additions & 2 deletions frontend/src/routes/(app)/(home)/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
<LayoutList {title}>
<Layout>
<Content>
<IslandWidthMain>
{#if $ENABLE_PORTFOLIO_PAGE}
<slot />
</IslandWidthMain>
{:else}
<IslandWidthMain>
<slot />
</IslandWidthMain>
{/if}
</Content>
</Layout>
</LayoutList>
3 changes: 2 additions & 1 deletion frontend/src/routes/(app)/(nns)/portfolio/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import TestIdWrapper from "$lib/components/common/TestIdWrapper.svelte";
import Portfolio from "$lib/pages/Portfolio.svelte";
</script>

<TestIdWrapper testId="portfolio-route-component"></TestIdWrapper>
<TestIdWrapper testId="portfolio-route-component"><Portfolio /></TestIdWrapper>
28 changes: 28 additions & 0 deletions frontend/src/tests/lib/pages/Portfolio.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Portfolio from "$lib/pages/Portfolio.svelte";
import { resetIdentity, setNoIdentity } from "$tests/mocks/auth.store.mock";
import { PortfolioPagePo } from "$tests/page-objects/PortfolioPage.page-object";
import { JestPageObjectElement } from "$tests/page-objects/jest.page-object";
import { render } from "@testing-library/svelte";

describe("Portfolio page", () => {
const renderPage = () => {
const { container } = render(Portfolio);

return PortfolioPagePo.under(new JestPageObjectElement(container));
};

beforeEach(() => {
resetIdentity();
});

it("should display the login card when the user is not logged in", async () => {
setNoIdentity();
const po = renderPage();
expect(await po.getLoginCard().isPresent()).toBe(true);
});

it("should not display the login card when the user is logged in", async () => {
const page = renderPage();
expect(await page.getLoginCard().isPresent()).toBe(false);
});
});
14 changes: 14 additions & 0 deletions frontend/src/tests/page-objects/PortfolioPage.page-object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { PageObjectElement } from "$tests/types/page-object.types";
import { BasePageObject } from "./base.page-object";

export class PortfolioPagePo extends BasePageObject {
private static readonly TID = "portfolio-page-component";

static under(element: PageObjectElement): PortfolioPagePo {
return new PortfolioPagePo(element.byTestId(PortfolioPagePo.TID));
}

getLoginCard() {
return this.getElement("portfolio-login-card");
}
}

0 comments on commit 6a9423d

Please sign in to comment.