Skip to content

Commit 8e465ef

Browse files
authored
Merge branch 'main' into akhil/update-translations
2 parents 775be23 + 5f35dbf commit 8e465ef

35 files changed

Lines changed: 4661 additions & 2866 deletions

packages/frontend-web/app/[locale]/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { NextIntlClientProvider } from "next-intl";
88
import { getTranslations } from "next-intl/server";
99
import ReduxProvider from "../../libs/Redux/ReduxProvider";
1010
import { AuthErrorListener } from '@/components/auth-error-listener';
11+
import { Analytics } from '@vercel/analytics/react';
1112

1213
const inter = Inter({ subsets: ["latin"] });
1314

@@ -66,6 +67,7 @@ export default async function LocaleLayout({
6667
</StackTheme>
6768
</StackProvider>
6869
</NextIntlClientProvider>
70+
<Analytics />
6971
</ThemeProvider>
7072
);
7173
}

packages/frontend-web/app/globals.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@
6464
}
6565
}
6666

67+
/* Hide default sort UI in account table headers */
68+
.accounts-table-header th::after {
69+
display: none !important;
70+
}
71+
6772
/* CSS property for animation */
6873
@property --angle {
6974
syntax: "<angle>";

packages/frontend-web/components/accounts-content.tsx

Lines changed: 370 additions & 272 deletions
Large diffs are not rendered by default.

packages/frontend-web/components/add-account-dialog.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ import { encryptAccountData } from "@/libs/encryption";
1313
import { secureGetItem } from "@/libs/session-storage-utils";
1414

1515
interface AddAccountDialogProps {
16+
open: boolean;
17+
onOpenChange: (open: boolean) => void;
1618
onClose: () => void;
1719
onAccountAdded: () => void;
20+
onGeneratePasswordRequest?: () => void;
1821
}
1922

20-
export function AddAccountDialog({ onClose, onAccountAdded }: AddAccountDialogProps) {
23+
export function AddAccountDialog({ open, onOpenChange, onClose, onAccountAdded, onGeneratePasswordRequest }: AddAccountDialogProps) {
2124
const { translate } = useTranslator();
2225
const [name, setName] = useState("");
2326
const [username, setUsername] = useState("");
@@ -105,7 +108,7 @@ export function AddAccountDialog({ onClose, onAccountAdded }: AddAccountDialogPr
105108

106109
if (response.status === 200 || response.status === 201 || (response.data && response.data.status_code === 201)) {
107110
onAccountAdded();
108-
onClose();
111+
onOpenChange(false);
109112
} else {
110113
throw new Error(response.data?.message || translate("failed_to_add_account", "accounts"));
111114
}
@@ -259,7 +262,7 @@ export function AddAccountDialog({ onClose, onAccountAdded }: AddAccountDialogPr
259262
</div>
260263

261264
<div className="flex items-center justify-between gap-2 pt-4">
262-
<Button variant="outline" className="w-full" onClick={onClose} disabled={isSubmitting}>
265+
<Button variant="outline" className="w-full" onClick={() => onOpenChange(false)} disabled={isSubmitting}>
263266
{translate("cancel", "accounts")}
264267
</Button>
265268
<Button

packages/frontend-web/components/add-identity-dialog.tsx

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -215,102 +215,104 @@ export function AddIdentityDialog({
215215
{translate("add_new_identity_description", "identity", { default: "Enter your identity details below" })}
216216
</DialogDescription>
217217
</DialogHeader>
218-
<div className="space-y-4 py-4">
219-
<div className="space-y-2">
220-
<Label htmlFor="title">{translate("title", "identity", { default: "Title" })}</Label>
218+
<div className="space-y-2 py-2">
219+
<div className="space-y-1">
220+
<Label htmlFor="title" className="text-sm">{translate("title", "identity", { default: "Title" })}</Label>
221221
<Input
222222
id="title"
223223
value={title}
224224
onChange={(e) => setTitle(e.target.value)}
225225
placeholder={translate("title_placeholder", "identity", { default: "Personal Identity" })}
226-
className={validationErrors.title ? "border-red-500" : ""}
226+
className={`h-8 ${validationErrors.title ? "border-red-500" : ""}`}
227227
/>
228228
{validationErrors.title && (
229-
<p className="text-red-500 text-sm">{validationErrors.title}</p>
229+
<p className="text-red-500 text-xs">{validationErrors.title}</p>
230230
)}
231231
</div>
232232

233-
<div className="grid grid-cols-2 gap-4">
234-
<div className="space-y-2">
235-
<Label htmlFor="first_name">{translate("first_name", "identity", { default: "First Name" })}</Label>
233+
<div className="grid grid-cols-2 gap-2">
234+
<div className="space-y-1">
235+
<Label htmlFor="first_name" className="text-sm">{translate("first_name", "identity", { default: "First Name" })}</Label>
236236
<Input
237237
id="first_name"
238238
value={firstName}
239239
onChange={(e) => setFirstName(e.target.value)}
240240
placeholder={translate("first_name_placeholder", "identity", { default: "John" })}
241-
className={validationErrors.firstName ? "border-red-500" : ""}
241+
className={`h-8 ${validationErrors.firstName ? "border-red-500" : ""}`}
242242
/>
243243
{validationErrors.firstName && (
244-
<p className="text-red-500 text-sm">{validationErrors.firstName}</p>
244+
<p className="text-red-500 text-xs">{validationErrors.firstName}</p>
245245
)}
246246
</div>
247247

248-
<div className="space-y-2">
249-
<Label htmlFor="last_name">{translate("last_name", "identity", { default: "Last Name" })}</Label>
248+
<div className="space-y-1">
249+
<Label htmlFor="last_name" className="text-sm">{translate("last_name", "identity", { default: "Last Name" })}</Label>
250250
<Input
251251
id="last_name"
252252
value={lastName}
253253
onChange={(e) => setLastName(e.target.value)}
254254
placeholder={translate("last_name_placeholder", "identity", { default: "Doe" })}
255-
className={validationErrors.lastName ? "border-red-500" : ""}
255+
className={`h-8 ${validationErrors.lastName ? "border-red-500" : ""}`}
256256
/>
257257
{validationErrors.lastName && (
258-
<p className="text-red-500 text-sm">{validationErrors.lastName}</p>
258+
<p className="text-red-500 text-xs">{validationErrors.lastName}</p>
259259
)}
260260
</div>
261261
</div>
262262

263-
<div className="space-y-2">
264-
<Label htmlFor="email">{translate("email", "identity", { default: "Email" })}</Label>
263+
<div className="space-y-1">
264+
<Label htmlFor="email" className="text-sm">{translate("email", "identity", { default: "Email" })}</Label>
265265
<Input
266266
id="email"
267267
value={email}
268268
onChange={(e) => setEmail(e.target.value)}
269269
placeholder={translate("email_placeholder", "identity", { default: "john.doe@example.com" })}
270-
className={validationErrors.email ? "border-red-500" : ""}
270+
className={`h-8 ${validationErrors.email ? "border-red-500" : ""}`}
271271
/>
272272
{validationErrors.email && (
273-
<p className="text-red-500 text-sm">{validationErrors.email}</p>
273+
<p className="text-red-500 text-xs">{validationErrors.email}</p>
274274
)}
275275
</div>
276276

277-
<div className="space-y-2">
278-
<Label htmlFor="phone">{translate("phone", "identity", { default: "Phone" })}</Label>
277+
<div className="space-y-1">
278+
<Label htmlFor="phone" className="text-sm">{translate("phone", "identity", { default: "Phone" })}</Label>
279279
<Input
280280
id="phone"
281281
value={phone}
282282
onChange={(e) => setPhone(e.target.value)}
283283
placeholder={translate("phone_placeholder", "identity", { default: "+1 (555) 123-4567" })}
284+
className="h-8"
284285
/>
285286
</div>
286287

287-
<div className="space-y-2">
288-
<Label htmlFor="address">{translate("address", "identity", { default: "Address" })}</Label>
288+
<div className="space-y-1">
289+
<Label htmlFor="address" className="text-sm">{translate("address", "identity", { default: "Address" })}</Label>
289290
<Textarea
290291
id="address"
291292
value={address}
292293
onChange={(e) => setAddress(e.target.value)}
293294
placeholder={translate("address_placeholder", "identity", { default: "123 Main St, Anytown, CA 94001" })}
294295
rows={2}
296+
className="min-h-[60px]"
295297
/>
296298
</div>
297299

298-
<div className="space-y-2">
299-
<Label htmlFor="date_of_birth">{translate("date_of_birth", "identity", { default: "Date of Birth" })}</Label>
300+
<div className="space-y-1">
301+
<Label htmlFor="date_of_birth" className="text-sm">{translate("date_of_birth", "identity", { default: "Date of Birth" })}</Label>
300302
<Input
301303
id="date_of_birth"
302304
type="date"
303305
value={dateOfBirth}
304306
onChange={(e) => setDateOfBirth(e.target.value)}
305-
className={validationErrors.dateOfBirth ? "border-red-500" : ""}
307+
className={`h-8 ${validationErrors.dateOfBirth ? "border-red-500" : ""}`}
306308
/>
307309
{validationErrors.dateOfBirth && (
308-
<p className="text-red-500 text-sm">{validationErrors.dateOfBirth}</p>
310+
<p className="text-red-500 text-xs">{validationErrors.dateOfBirth}</p>
309311
)}
310312
</div>
311313

312-
<div className="space-y-2">
313-
<Label htmlFor="national_id" className="flex items-center gap-1">
314+
<div className="space-y-1">
315+
<Label htmlFor="national_id" className="flex items-center gap-1 text-sm">
314316
{translate("national_id", "identity", { default: "National ID" })}
315317
<span className="text-red-500">*</span>
316318
</Label>
@@ -319,42 +321,44 @@ export function AddIdentityDialog({
319321
value={nationalId}
320322
onChange={(e) => setNationalId(e.target.value)}
321323
placeholder={translate("national_id_placeholder", "identity", { default: "123-45-6789" })}
322-
className={validationErrors.nationalId ? "border-red-500" : ""}
324+
className={`h-8 ${validationErrors.nationalId ? "border-red-500" : ""}`}
323325
/>
324326
{validationErrors.nationalId && (
325-
<p className="text-red-500 text-sm">{validationErrors.nationalId}</p>
327+
<p className="text-red-500 text-xs">{validationErrors.nationalId}</p>
326328
)}
327329
</div>
328330

329-
<div className="space-y-2">
330-
<Label htmlFor="notes">{translate("notes", "identity", { default: "Notes" })}</Label>
331+
<div className="space-y-1">
332+
<Label htmlFor="notes" className="text-sm">{translate("notes", "identity", { default: "Notes" })}</Label>
331333
<Textarea
332334
id="notes"
333335
value={notes}
334336
onChange={(e) => setNotes(e.target.value)}
335337
placeholder={translate("notes_placeholder", "identity", { default: "Additional information" })}
336-
rows={3}
338+
rows={2}
339+
className="min-h-[60px]"
337340
/>
338341
</div>
339342

340-
<div className="space-y-2">
341-
<Label htmlFor="tags">{translate("tags", "identity", { default: "Tags" })}</Label>
343+
<div className="space-y-1">
344+
<Label htmlFor="tags" className="text-sm">{translate("tags", "identity", { default: "Tags" })}</Label>
342345
<div className="flex gap-2">
343346
<Input
344347
id="tags"
345348
value={currentTag}
346349
onChange={(e) => setCurrentTag(e.target.value)}
347350
placeholder={translate("tags_placeholder", "identity", { default: "Add tags" })}
348351
onKeyDown={(e) => e.key === "Enter" && (e.preventDefault(), handleAddTag())}
352+
className="h-8"
349353
/>
350-
<Button type="button" onClick={handleAddTag}>
354+
<Button type="button" onClick={handleAddTag} className="h-8">
351355
{translate("add", "identity", { default: "Add" })}
352356
</Button>
353357
</div>
354358
{tags.length > 0 && (
355-
<div className="flex flex-wrap gap-2 mt-2">
359+
<div className="flex flex-wrap gap-1 mt-1">
356360
{tags.map((tag) => (
357-
<Badge key={tag} variant="secondary" className="flex items-center gap-1">
361+
<Badge key={tag} variant="secondary" className="flex items-center gap-1 text-xs">
358362
{tag}
359363
<X
360364
className="h-3 w-3 cursor-pointer"
@@ -366,16 +370,17 @@ export function AddIdentityDialog({
366370
)}
367371
</div>
368372
</div>
369-
<DialogFooter>
373+
<DialogFooter className="mt-2">
370374
<Button
371375
type="button"
372376
variant="secondary"
373377
onClick={() => onOpenChange(false)}
374378
disabled={isSubmitting}
379+
className="h-8"
375380
>
376381
{translate("cancel", "identity", { default: "Cancel" })}
377382
</Button>
378-
<Button type="submit" onClick={handleSubmit} disabled={isSubmitting}>
383+
<Button type="submit" onClick={handleSubmit} disabled={isSubmitting} className="h-8">
379384
{isSubmitting
380385
? translate("adding", "identity", { default: "Adding..." })
381386
: translate("add_identity", "identity", { default: "Add Identity" })}

packages/frontend-web/components/add-passphrase-dialoge.tsx

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ interface WalletPassphrase {
2626
wallet_type: string;
2727
data: string;
2828
passphrase: string;
29+
wallet_address: string;
2930
notes?: string | null;
3031
tags?: string[];
3132
created_at: string;
@@ -62,6 +63,7 @@ export function AddPassphraseDialog({
6263
const { translate } = useTranslator();
6364
const [title, setTitle] = useState("");
6465
const [data, setData] = useState("");
66+
const [walletAddress, setWalletAddress] = useState("");
6567
const [notes, setNotes] = useState("");
6668
const [walletType, setWalletType] = useState<string>("Bitcoin");
6769
const [tags, setTags] = useState<string[]>([]);
@@ -104,6 +106,24 @@ export function AddPassphraseDialog({
104106
loadProjectKey();
105107
}, [open, selectedProjectName]);
106108

109+
// Add cleanup effect when dialog closes
110+
useEffect(() => {
111+
if (!open) {
112+
// Reset all form fields when dialog closes
113+
setTitle("");
114+
setData("");
115+
setWalletAddress("");
116+
setNotes("");
117+
setWalletType("Bitcoin");
118+
setTags([]);
119+
setNewTag("");
120+
setError("");
121+
setPassphraseError(null);
122+
setPassphraseExistsError(null);
123+
setNameExistsError(null);
124+
}
125+
}, [open]);
126+
107127
const predefinedTags = ["main", "trading", "defi", "staking"];
108128

109129
const addTag = (tag: string) => {
@@ -182,7 +202,7 @@ export function AddPassphraseDialog({
182202
};
183203

184204
const handleSubmit = async () => {
185-
if (!title || !data) {
205+
if (!title || !data || !walletAddress) {
186206
setError(translate("please_fill_all_required_fields", "wallet_passphrases", {
187207
default: "Please fill all required fields",
188208
}));
@@ -228,8 +248,11 @@ export function AddPassphraseDialog({
228248
let processedData = data;
229249
if (effectiveProjectKey) {
230250
try {
231-
// Create a simple JSON object with only the passphrase
232-
const passphraseObject = { passphrase: data };
251+
// Create a JSON object with both passphrase and wallet address
252+
const passphraseObject = {
253+
passphrase: data,
254+
wallet_address: walletAddress
255+
};
233256
const passphraseJson = JSON.stringify(passphraseObject);
234257
console.log("Passphrase JSON prepared:", passphraseJson);
235258

@@ -382,6 +405,27 @@ export function AddPassphraseDialog({
382405
)}
383406
</div>
384407

408+
<div className="space-y-2">
409+
<Label htmlFor="walletAddress">
410+
{translate("wallet_address", "wallet_passphrases", { default: "Wallet Address" })}
411+
<span className="text-red-500">*</span>
412+
</Label>
413+
<Input
414+
id="walletAddress"
415+
placeholder={translate("enter_wallet_address", "wallet_passphrases", {
416+
default: "Enter wallet address",
417+
})}
418+
value={walletAddress}
419+
onChange={(e) => setWalletAddress(e.target.value)}
420+
className={error && !walletAddress ? "border-red-500" : ""}
421+
/>
422+
<p className="text-xs text-muted-foreground">
423+
{translate("wallet_address_encryption_note", "wallet_passphrases", {
424+
default: "The wallet address will be encrypted and securely stored.",
425+
})}
426+
</p>
427+
</div>
428+
385429
<div className="space-y-2">
386430
<Label htmlFor="notes">{translate("notes", "wallet_passphrases", { default: "Notes" })}</Label>
387431
<Input

0 commit comments

Comments
 (0)