-
Notifications
You must be signed in to change notification settings - Fork 4
Feat/evault provisioning via phone #188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
eb56114
2cd6d7b
c645a19
5992cac
e5bfecd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,103 +1,145 @@ | ||
<script lang="ts"> | ||
import * as Button from "$lib/ui/Button"; | ||
import { cn } from "$lib/utils"; | ||
import { | ||
CheckmarkBadge02Icon, | ||
Upload03Icon, | ||
ViewIcon, | ||
} from "@hugeicons/core-free-icons"; | ||
import { HugeiconsIcon } from "@hugeicons/svelte"; | ||
import type { HTMLAttributes } from "svelte/elements"; | ||
import * as Button from "$lib/ui/Button"; | ||
import { cn } from "$lib/utils"; | ||
import { | ||
CheckmarkBadge02Icon, | ||
Upload03Icon, | ||
ViewIcon, | ||
} from "@hugeicons/core-free-icons"; | ||
import { HugeiconsIcon } from "@hugeicons/svelte"; | ||
import type { HTMLAttributes } from "svelte/elements"; | ||
|
||
interface userData { | ||
[fieldName: string]: string; | ||
} | ||
interface IIdentityCard extends HTMLAttributes<HTMLElement> { | ||
variant?: "eName" | "ePassport" | "eVault"; | ||
userId?: string; | ||
viewBtn?: () => void; | ||
shareBtn?: () => void; | ||
userData?: userData; | ||
totalStorage?: number; | ||
usedStorage?: number; | ||
} | ||
interface userData { | ||
[fieldName: string]: string; | ||
} | ||
interface IIdentityCard extends HTMLAttributes<HTMLElement> { | ||
variant?: "eName" | "ePassport" | "eVault"; | ||
userId?: string; | ||
viewBtn?: () => void; | ||
shareBtn?: () => void; | ||
userData?: userData; | ||
totalStorage?: number; | ||
usedStorage?: number; | ||
} | ||
|
||
const { | ||
variant = "eName", | ||
userId, | ||
viewBtn, | ||
shareBtn, | ||
userData, | ||
totalStorage = 0, | ||
usedStorage = 0, | ||
...restProps | ||
}: IIdentityCard = $props(); | ||
const state = $state({ | ||
progressWidth: "0%", | ||
}); | ||
const { | ||
variant = "eName", | ||
userId, | ||
viewBtn, | ||
shareBtn, | ||
userData, | ||
totalStorage = 0, | ||
usedStorage = 0, | ||
...restProps | ||
}: IIdentityCard = $props(); | ||
const state = $state({ | ||
progressWidth: "0%", | ||
}); | ||
|
||
$effect(() => { | ||
state.progressWidth = | ||
usedStorage > 0 ? `${(usedStorage / totalStorage) * 100}%` : "0%"; | ||
}); | ||
$effect(() => { | ||
state.progressWidth = | ||
usedStorage > 0 ? `${(usedStorage / totalStorage) * 100}%` : "0%"; | ||
}); | ||
|
||
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`; | ||
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`; | ||
</script> | ||
|
||
<div {...restProps} class={cn(baseClasses, restProps.class)}> | ||
<div class="w-full h-full pointer-events-none flex gap-13 justify-end absolute right-15 bottom-20"> | ||
<div class="w-10 {variant === 'eVault' ? "bg-white/40" : "bg-white/10"} h-[300%] rotate-40"></div> | ||
<div class="w-10 {variant === 'eVault' ? "bg-white/40" : "bg-white/10"} h-[300%] rotate-40"></div> | ||
<div | ||
class="w-full h-full pointer-events-none flex gap-13 justify-end absolute right-15 bottom-20" | ||
> | ||
<div | ||
class="w-10 {variant === 'eVault' | ||
? 'bg-white/40' | ||
: 'bg-white/10'} h-[300%] rotate-40" | ||
></div> | ||
<div | ||
class="w-10 {variant === 'eVault' | ||
? 'bg-white/40' | ||
: 'bg-white/10'} h-[300%] rotate-40" | ||
></div> | ||
</div> | ||
<div class="p-5 flex flex-col gap-2"> | ||
<div class="flex justify-between"> | ||
{#if variant === 'eName'} | ||
<HugeiconsIcon size={30} strokeWidth={2} className="text-secondary" icon={CheckmarkBadge02Icon} /> | ||
<div class="flex gap-3 items-center"> | ||
{#if shareBtn} | ||
<Button.Icon icon={Upload03Icon} iconColor={"white"} strokeWidth={2} onclick={shareBtn} /> | ||
{#if variant === "eName"} | ||
<HugeiconsIcon | ||
size={30} | ||
strokeWidth={2} | ||
className="text-secondary" | ||
icon={CheckmarkBadge02Icon} | ||
/> | ||
<div class="flex gap-3 items-center"> | ||
{#if shareBtn} | ||
<Button.Icon | ||
icon={Upload03Icon} | ||
iconColor={"white"} | ||
strokeWidth={2} | ||
onclick={shareBtn} | ||
/> | ||
{/if} | ||
{#if viewBtn} | ||
<Button.Icon icon={ViewIcon} iconColor={"white"} strokeWidth={2} onclick={viewBtn} /> | ||
<Button.Icon | ||
icon={ViewIcon} | ||
iconColor={"white"} | ||
strokeWidth={2} | ||
onclick={viewBtn} | ||
/> | ||
{/if} | ||
</div> | ||
{:else if variant === 'ePassport'} | ||
<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> | ||
</div> | ||
{:else if variant === "ePassport"} | ||
<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> | ||
{#if viewBtn} | ||
<Button.Icon icon={ViewIcon} iconColor={"white"} strokeWidth={2} onclick={viewBtn} /> | ||
<Button.Icon | ||
icon={ViewIcon} | ||
iconColor={"white"} | ||
strokeWidth={2} | ||
onclick={viewBtn} | ||
/> | ||
{/if} | ||
{:else if variant === 'eVault'} | ||
<h3 class="text-black-300 text-3xl font-semibold mb-3 z-[1]">{state.progressWidth} Used</h3> | ||
{:else if variant === "eVault"} | ||
<h3 class="text-black-300 text-3xl font-semibold mb-3 z-[1]"> | ||
{state.progressWidth} Used | ||
</h3> | ||
{/if} | ||
</div> | ||
<div> | ||
{#if variant === "eName"} | ||
{#if variant === "eName"} | ||
<p class="text-gray font-normal">Your eName</p> | ||
<div class="flex items-center justify-between w-full"> | ||
<p class="text-white w-full font-medium">@{userId}</p> | ||
<p class="text-white w-full font-medium">{userId}</p> | ||
</div> | ||
{:else if variant === "ePassport"} | ||
<div class="flex gap-2 flex-col"> | ||
{#if userData} | ||
{#each Object.entries(userData) as [fieldName, value] } | ||
{#each Object.entries(userData) as [fieldName, value]} | ||
<div class="flex justify-between"> | ||
<p class="text-gray">{fieldName}</p> | ||
<p class="text-gray capitalize">{fieldName}</p> | ||
<p class=" font-medium text-white">{value}</p> | ||
</div> | ||
{/each} | ||
{/if} | ||
</div> | ||
{:else if variant === "eVault"} | ||
<div> | ||
<div class="flex justify-between mb-1 "> | ||
<p class="z-[1]">{usedStorage}GB Used</p> | ||
<p class="z-[1]">{totalStorage}GB total storage</p> | ||
</div> | ||
<div class="relative w-full h-3 rounded-full overflow-hidden bg-primary-400"> | ||
<div class="h-full bg-secondary rounded-full" style={`width: calc(${state.progressWidth})`}></div> | ||
<div> | ||
<div class="flex justify-between mb-1"> | ||
<p class="z-[1]">{usedStorage}GB Used</p> | ||
<p class="z-[1]">{totalStorage}GB total storage</p> | ||
</div> | ||
<div | ||
class="relative w-full h-3 rounded-full overflow-hidden bg-primary-400" | ||
> | ||
<div | ||
class="h-full bg-secondary rounded-full" | ||
style={`width: calc(${state.progressWidth})`} | ||
></div> | ||
</div> | ||
</div> | ||
</div> | ||
{/if} | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import type { Store } from "@tauri-apps/plugin-store"; | ||
|
||
export class VaultController { | ||
#store: Store; | ||
constructor(store: Store) { | ||
this.#store = store; | ||
} | ||
|
||
set vault( | ||
vault: | ||
| Promise<Record<string, string> | undefined> | ||
| Record<string, string> | ||
| undefined, | ||
) { | ||
if (vault instanceof Promise) { | ||
vault | ||
.then((resolvedUser) => { | ||
this.#store.set("vault", resolvedUser); | ||
}) | ||
.catch((error) => { | ||
console.error("Failed to set vault:", error); | ||
}); | ||
} else { | ||
this.#store.set("vault", vault); | ||
} | ||
} | ||
|
||
get vault() { | ||
return this.#store | ||
.get<Record<string, string>>("vault") | ||
.then((vault) => { | ||
if (!vault) { | ||
return undefined; | ||
} | ||
return vault; | ||
}) | ||
.catch((error) => { | ||
console.error("Failed to get vault:", error); | ||
return undefined; | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -54,10 +54,12 @@ export class UserController { | |||||||||||||||
* ``` | ||||||||||||||||
* @throws {Error} If the user state cannot be set in the store | ||||||||||||||||
*/ | ||||||||||||||||
set user(user: | ||||||||||||||||
| Promise<Record<string, string> | undefined> | ||||||||||||||||
| Record<string, string> | ||||||||||||||||
| undefined) { | ||||||||||||||||
set user( | ||||||||||||||||
user: | ||||||||||||||||
| Promise<Record<string, string> | undefined> | ||||||||||||||||
| Record<string, string> | ||||||||||||||||
| undefined, | ||||||||||||||||
) { | ||||||||||||||||
if (user instanceof Promise) { | ||||||||||||||||
user.then((resolvedUser) => { | ||||||||||||||||
this.#store.set("user", resolvedUser); | ||||||||||||||||
|
@@ -83,4 +85,38 @@ export class UserController { | |||||||||||||||
return undefined; | ||||||||||||||||
}); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
set document( | ||||||||||||||||
document: | ||||||||||||||||
| Promise<Record<string, string> | undefined> | ||||||||||||||||
| Record<string, string> | ||||||||||||||||
| undefined, | ||||||||||||||||
) { | ||||||||||||||||
if (document instanceof Promise) { | ||||||||||||||||
document | ||||||||||||||||
.then((resolvedDoc) => { | ||||||||||||||||
this.#store.set("doc", resolvedDoc); | ||||||||||||||||
}) | ||||||||||||||||
.catch((error) => { | ||||||||||||||||
console.error("Failed to set doc:", error); | ||||||||||||||||
}); | ||||||||||||||||
} else { | ||||||||||||||||
this.#store.set("doc", document); | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
get document() { | ||||||||||||||||
return this.#store | ||||||||||||||||
.get<Record<string, string>>("doc") | ||||||||||||||||
.then((user) => { | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix variable naming in document getter The variable should be named - .then((user) => {
+ .then((doc) => {
- if (!user) {
+ if (!doc) {
return undefined;
}
- return user;
+ return doc;
}) 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||
if (!user) { | ||||||||||||||||
return undefined; | ||||||||||||||||
} | ||||||||||||||||
return user; | ||||||||||||||||
}) | ||||||||||||||||
.catch((error) => { | ||||||||||||||||
console.error("Failed to get doc:", error); | ||||||||||||||||
return undefined; | ||||||||||||||||
}); | ||||||||||||||||
} | ||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import { Store } from "@tauri-apps/plugin-store"; | ||
import { SecurityController } from "./controllers/security"; | ||
import { UserController } from "./controllers/user"; | ||
import { VaultController } from "./controllers/evault"; | ||
/** | ||
* @author SoSweetHam <[email protected]> | ||
* @description A centralized state that can be used to control the global state of the application, meant to be used as a singleton through the main layout component. | ||
|
@@ -23,10 +24,13 @@ export class GlobalState { | |
#store: Store; | ||
securityController: SecurityController; | ||
userController: UserController; | ||
vaultController: VaultController; | ||
|
||
private constructor(store: Store) { | ||
this.#store = store; | ||
this.securityController = new SecurityController(store); | ||
this.userController = new UserController(store); | ||
this.vaultController = new VaultController(store); | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* Returns a new string with the first letter of each word in uppercase and the remaining letters in lowercase. | ||
* | ||
* @param str - The input string to capitalize. | ||
* @returns The capitalized string. | ||
*/ | ||
export function capitalize(str: string) { | ||
return str | ||
.toLowerCase() | ||
.split(" ") | ||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1)) | ||
.join(" "); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from "./mergeClasses"; | ||
export * from "./clickOutside"; | ||
export * from "./capitalize"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify the "import" package dependency.
The
import
package at version^0.0.6
appears unusual and potentially problematic. This package name is very generic and the version suggests it might be outdated or incorrect.🏁 Script executed:
Length of output: 257
🏁 Script executed:
Length of output: 82
🏁 Script executed:
Length of output: 717
Remove unused “import” dependency
The “import” package (v^0.0.6) isn’t referenced anywhere in your codebase or npm scripts, so it appears to be unused. Please either remove it from infrastructure/eid-wallet/package.json or document why it’s needed.
• File: infrastructure/eid-wallet/package.json
– Line with
"import": "^0.0.6"
🤖 Prompt for AI Agents