Skip to content

Commit 6ea6b32

Browse files
authored
feat: Main page flow (#93)
* feat: create root page + layout * feat: complete main page flow beta * chore: fix ts block * chore: sort imports
1 parent 5bd1e25 commit 6ea6b32

File tree

13 files changed

+349
-39
lines changed

13 files changed

+349
-39
lines changed

infrastructure/eid-wallet/src/lib/fragments/AppNav/AppNav.svelte

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@ import type { HTMLAttributes } from "svelte/elements";
66
interface IHeroProps extends HTMLAttributes<HTMLElement> {
77
title?: string;
88
titleClasses?: string;
9+
iconColor?: string;
910
}
10-
const { title, titleClasses, ...restProps }: IHeroProps = $props();
11+
const {
12+
title,
13+
titleClasses,
14+
iconColor = "black",
15+
...restProps
16+
}: IHeroProps = $props();
1117
const baseClasses = "w-full relative flex justify-center h-14 items-center";
1218
</script>
1319

1420
<nav {...restProps} class={cn(baseClasses, restProps.class)}>
1521
<Button.Icon
1622
icon={ArrowLeft01Icon}
1723
iconSize="md"
18-
iconColor={"black"}
24+
{iconColor}
1925
class="absolute left-2"
2026
onclick={() => window.history.back()}
2127
/>

infrastructure/eid-wallet/src/lib/fragments/IdentityCard/IdentityCard.svelte

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script lang="ts">
22
import * as Button from "$lib/ui/Button";
3+
import { cn } from "$lib/utils";
34
import {
45
CheckmarkBadge02Icon,
56
Upload03Icon,
@@ -39,9 +40,11 @@ $effect(() => {
3940
state.progressWidth =
4041
usedStorage > 0 ? `${(usedStorage / totalStorage) * 100}%` : "0%";
4142
});
43+
44+
const baseClasses = `relative ${variant === "eName" ? "bg-black-900" : variant === "ePassport" ? "bg-primary" : "bg-gray"} rounded-3xl w-full min-h-[150px] text-white overflow-hidden`;
4245
</script>
4346

44-
<div {...restProps} class="relative {variant === 'eName' ? "bg-black-900" : variant === 'ePassport' ? "bg-primary" : "bg-gray"} rounded-3xl w-full min-h-[150px] text-white overflow-hidden">
47+
<div {...restProps} class={cn(baseClasses, restProps.class)}>
4548
<div class="w-full h-full pointer-events-none flex gap-13 justify-end absolute right-15 bottom-20">
4649
<div class="w-10 {variant === 'eVault' ? "bg-white/40" : "bg-white/10"} h-[300%] rotate-40"></div>
4750
<div class="w-10 {variant === 'eVault' ? "bg-white/40" : "bg-white/10"} h-[300%] rotate-40"></div>
@@ -55,7 +58,7 @@ $effect(() => {
5558
<Button.Icon icon={ViewIcon} iconColor={"white"} strokeWidth={2} onclick={viewBtn} />
5659
</div>
5760
{:else if variant === 'ePassport'}
58-
<p class="bg-white text-black flex items-center rounded-4xl px-5 py-2 text-xs font-semibold">HIGH SECURITY</p>
61+
<p class="bg-white text-black flex items-center leading-0 justify-center rounded-full h-7 px-5 text-xs font-medium">HIGH SECURITY</p>
5962
<Button.Icon icon={ViewIcon} iconColor={"white"} strokeWidth={2} onclick={viewBtn} />
6063

6164
{:else if variant === 'eVault'}
@@ -64,9 +67,9 @@ $effect(() => {
6467
</div>
6568
<div>
6669
{#if variant === "eName"}
67-
<p class="text-gray font-light">Your eName</p>
70+
<p class="text-gray font-normal">Your eName</p>
6871
<div class="flex items-center justify-between w-full">
69-
<p class="text-white w-[60%] font-medium">@{userId}</p>
72+
<p class="text-white w-full font-medium">@{userId}</p>
7073
</div>
7174
{:else if variant === "ePassport"}
7275
<div class="flex gap-2 flex-col">
@@ -92,7 +95,4 @@ $effect(() => {
9295
{/if}
9396
</div>
9497
</div>
95-
</div>
96-
97-
98-
98+
</div>

infrastructure/eid-wallet/src/lib/ui/Button/ButtonAction.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { HTMLButtonAttributes } from "svelte/elements";
55
interface IButtonProps extends HTMLButtonAttributes {
66
variant?: "solid" | "soft" | "danger" | "danger-soft" | "white";
77
isLoading?: boolean;
8-
callback?: () => Promise<void>;
8+
callback?: () => Promise<void> | void;
99
blockingClick?: boolean;
1010
type?: "button" | "submit" | "reset";
1111
size?: "sm" | "md";
@@ -15,6 +15,7 @@ const {
1515
variant = "solid",
1616
isLoading,
1717
callback,
18+
onclick,
1819
blockingClick,
1920
type = "button",
2021
size = "md",

infrastructure/eid-wallet/src/lib/ui/Button/ButtonIcon.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { HTMLButtonAttributes } from "svelte/elements";
66
interface IButtonProps extends HTMLButtonAttributes {
77
icon: IconSvgElement;
88
isLoading?: boolean;
9-
callback?: () => Promise<void>;
9+
callback?: () => Promise<void> | void;
1010
onclick?: () => void;
1111
blockingClick?: boolean;
1212
type?: "button" | "submit" | "reset";

infrastructure/eid-wallet/src/lib/ui/Drawer/Drawer.svelte

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,6 @@ $effect(() => {
5353
5454
return () => pane.destroy();
5555
});
56-
57-
$effect(() => {
58-
if (isPaneOpen) {
59-
pane.present({ animate: true });
60-
} else {
61-
pane.destroy({ animate: true });
62-
}
63-
drawerElem.addEventListener("click_outside", () => {
64-
handleClickOutside();
65-
});
66-
});
6756
</script>
6857

6958
<div
@@ -74,7 +63,7 @@ $effect(() => {
7463
})}
7564
onswipe={() => handleSwipe?.(isPaneOpen)}
7665
bind:this={drawerElem}
77-
use:clickOutside
66+
use:clickOutside={handleClickOutside}
7867
class={cn(restProps.class)}
7968
>
8069
<div class="px-6">

infrastructure/eid-wallet/src/lib/utils/clickOutside.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/** Dispatch event on click outside of node */
2-
export const clickOutside = (node: HTMLElement) => {
2+
export const clickOutside = (node: HTMLElement, callback: () => void) => {
33
const handleClick = (event: Event) => {
4-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
5-
// @ts-ignore
6-
if (node && !node.contains(event.target) && !event.defaultPrevented) {
7-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
8-
// @ts-ignore
9-
node.dispatchEvent(new CustomEvent("click_outside", node));
4+
if (
5+
node &&
6+
!node.contains(event.target as Node) &&
7+
!event.defaultPrevented
8+
) {
9+
callback(); // Call the provided callback
10+
node.dispatchEvent(new CustomEvent("click_outside"));
1011
}
1112
};
1213

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<script lang="ts">
2+
import { page } from "$app/state";
3+
import type { Snippet } from "svelte";
4+
import type { LayoutData } from "./$types";
5+
6+
let { data, children }: { data: LayoutData; children: Snippet } = $props();
7+
8+
let currentRoute = $derived(page.url.pathname.split("/").pop() || "home");
9+
</script>
10+
11+
<!-- Dev only: remove this when deploying to production -->
12+
{#if currentRoute === "scan-qr"}
13+
<div class="fixed -z-10 bg-black w-screen h-screen top-0">
14+
<img src="/images/dummyScan.png" class="opacity-40 w-screen h-screen object-cover" alt="dummy scan">
15+
</div>
16+
{/if}
17+
18+
<div class="p-6 mb-16">
19+
{@render children()}
20+
</div>
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<script lang="ts">
2+
import { goto } from "$app/navigation";
3+
import { Hero, IdentityCard } from "$lib/fragments";
4+
import { Drawer } from "$lib/ui";
5+
import * as Button from "$lib/ui/Button";
6+
import { QrCodeIcon } from "@hugeicons/core-free-icons";
7+
import { HugeiconsIcon } from "@hugeicons/svelte";
8+
import type { Snippet } from "svelte";
9+
10+
const dummyData = {
11+
Name: "John Doe",
12+
"Date of birth": "01 - 01 - 1990",
13+
"ID submitted": "American Passport",
14+
"Passport number": "1234567-US",
15+
};
16+
17+
let shareQRdrawerOpen = $state(false);
18+
19+
function shareQR() {
20+
alert("QR Code shared!");
21+
shareQRdrawerOpen = false;
22+
}
23+
</script>
24+
25+
26+
<Hero
27+
title="Good morning!"
28+
subtitle="Don't forget to drink water."
29+
showSettings
30+
/>
31+
32+
{#snippet Section(title: string, children: Snippet)}
33+
<section class="mt-8">
34+
<h4 class="mb-2">{title}</h4>
35+
{@render children()}
36+
</section>
37+
{/snippet}
38+
39+
{#snippet eName()}
40+
<IdentityCard
41+
variant="eName"
42+
userId="caa0f630-2413-5aceaa2c-4628ce93e497"
43+
viewBtn={() => alert("View button clicked!")}
44+
shareBtn={() => shareQRdrawerOpen = true}
45+
/>
46+
{/snippet}
47+
{#snippet ePassport()}
48+
<IdentityCard
49+
variant="ePassport"
50+
viewBtn={() => goto("/ePassport")}
51+
userData={dummyData}
52+
/>
53+
{/snippet}
54+
{#snippet eVault()}
55+
<IdentityCard
56+
variant="eVault"
57+
usedStorage={15}
58+
totalStorage={100}
59+
/>
60+
{/snippet}
61+
62+
{@render Section("eName", eName)}
63+
{@render Section("ePassport", ePassport)}
64+
{@render Section("eVault", eVault)}
65+
66+
<Drawer
67+
title="Scan QR Code"
68+
bind:isPaneOpen={shareQRdrawerOpen}
69+
isCancelRequired={true}
70+
class="flex flex-col gap-4 items-center justify-center"
71+
>
72+
<div class="flex justify-center relative items-center overflow-hidden h-full bg-gray rounded-3xl p-8">
73+
<div class="bg-white h-[72px] w-[1000px] -rotate-45 absolute top-4"></div>
74+
<div class="bg-white h-[72px] w-[1000px] -rotate-45 absolute bottom-4"></div>
75+
<img class="z-10" src="/images/dummyQR.png" alt="QR Code" />
76+
</div>
77+
78+
<h4 class="text-center">Share your eName</h4>
79+
<p class="text-black-700 text-center">Anyone scanning this can see your eName</p>
80+
<div class="flex justify-center items-center mt-4">
81+
<Button.Action
82+
variant="solid"
83+
callback={shareQR}
84+
class="w-full"
85+
>
86+
Share
87+
</Button.Action>
88+
</div>
89+
</Drawer>
90+
91+
<Button.Nav href="/scan-qr">
92+
<Button.Action
93+
variant="solid"
94+
onclick={() => alert("Action button clicked!")}
95+
class="mx-auto text-nowrap flex gap-8 fixed bottom-5 left-1/2 -translate-x-1/2 z-10"
96+
>
97+
<HugeiconsIcon
98+
size={32}
99+
strokeWidth={2}
100+
className="mr-2"
101+
icon={QrCodeIcon}
102+
/>
103+
Scan to Login
104+
</Button.Action>
105+
</Button.Nav>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<script lang="ts">
2+
import { AppNav, IdentityCard } from "$lib/fragments";
3+
import * as Button from "$lib/ui/Button";
4+
import { Share05Icon } from "@hugeicons/core-free-icons";
5+
import { HugeiconsIcon } from "@hugeicons/svelte";
6+
7+
const dummyData = {
8+
Name: "John Doe",
9+
"Date of birth": "01-01-1990",
10+
"ID submitted": "American Passport",
11+
"Passport number": "1234567-US",
12+
};
13+
14+
const secondDummyData = {
15+
"Birth Name": "John Doe",
16+
"Place of birth": "New York, USA",
17+
Nationality: "American",
18+
"ID submitted": "American Passport",
19+
"Expiry date": "19-12-2027",
20+
};
21+
22+
function shareEPassport() {
23+
alert("EPassport Code shared!");
24+
}
25+
</script>
26+
27+
<AppNav title="ePassport" class="mb-8" />
28+
29+
<div>
30+
<IdentityCard
31+
variant="ePassport"
32+
userData={dummyData}
33+
class="shadow-lg"
34+
/>
35+
<div class="p-6 pt-12 bg-gray w-full rounded-2xl -mt-8 flex flex-col gap-2">
36+
{#each Object.entries(secondDummyData) as [fieldName, value] }
37+
<div class="flex justify-between">
38+
<p class="text-black-700 font-normal">{fieldName}</p>
39+
<p class="text-black-500 font-medium">{value}</p>
40+
</div>
41+
{/each}
42+
</div>
43+
</div>
44+
45+
<Button.Action
46+
variant="solid"
47+
callback={shareEPassport}
48+
class="mx-auto text-nowrap flex gap-8 fixed bottom-5 left-1/2 -translate-x-1/2 z-10"
49+
>
50+
<HugeiconsIcon
51+
size={32}
52+
strokeWidth={2}
53+
className="mr-2"
54+
icon={Share05Icon}
55+
/>
56+
Share ePassport
57+
</Button.Action>

0 commit comments

Comments
 (0)