Skip to content

Commit

Permalink
Fixes for password dialog.
Browse files Browse the repository at this point in the history
  • Loading branch information
cvs0 committed Feb 6, 2025
1 parent 19b6d88 commit 00e3153
Showing 1 changed file with 41 additions and 35 deletions.
76 changes: 41 additions & 35 deletions src/components/vault/dialogs/create-password-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,25 @@ import { Input } from "@/components/ui/input";
import { encrypt } from "@/utils/encryption";
import { useUser } from "@clerk/nextjs";
import { Loader2 } from "lucide-react";
import { useState } from "react";
import { ChangeEvent, useState } from "react";
import toast from "react-hot-toast";
import { z } from "zod";

const initialPasswordItemState = {
name: "",
username: "",
website: "",
password: "",
};

export const CreatePasswordDialog = ({
open,
onClose,
}: {
open: boolean;
onClose: () => void;
}) => {
const [name, setName] = useState("");
const [username, setUsername] = useState("");
const [website, setWebsite] = useState("");
const [password, setPassword] = useState("");
const [passwordItem, setPasswordItem] = useState(initialPasswordItemState);
const [loading, setLoading] = useState(false);

const { user: clerkuser } = useUser();
Expand All @@ -53,41 +57,39 @@ export const CreatePasswordDialog = ({

const handleSave = async () => {
setLoading(true);

const formattedWebsite = website.startsWith("https://")
? website
: `https://${website}`;

const validationResult = passwordSchema.safeParse({
name,
username,
website: formattedWebsite,
password,
});


const validationResult = passwordSchema.safeParse(passwordItem);

if (!validationResult.success) {
const errorMessage =
validationResult.error.errors[0]?.message || "Validation failed";
toast.error(errorMessage);
setLoading(false);
return;
}

try {
await createPasswordItem(
encrypt(username, clerkuser),
encrypt(formattedWebsite, clerkuser),
encrypt(password, clerkuser)
encrypt(passwordItem.username, clerkuser),
encrypt(passwordItem.website, clerkuser),
encrypt(passwordItem.password, clerkuser)
);
toast.success("Password created");
setPasswordItem(initialPasswordItemState);
onClose();
} catch (error) {
toast.error("Failed to create password");
} finally {
setLoading(false);
}
};


const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
setPasswordItem((prevState) => ({
...prevState,
[e.target.name]: e.target.value,
}));
};

return (
<Dialog open={open} onOpenChange={onClose}>
Expand All @@ -99,31 +101,33 @@ export const CreatePasswordDialog = ({
<div className="relative">
<Input
placeholder="Name"
value={name}
onChange={(e) => setName(e.target.value)}
value={passwordItem.name}
onChange={handleChange}
maxLength={50}
name="name"
/>
<div
className="pointer-events-none absolute inset-y-0 end-0 flex items-center justify-center pe-3 text-xs tabular-nums text-muted-foreground peer-disabled:opacity-50"
aria-live="polite"
role="status"
>
{name.length}/50
{passwordItem.name.length}/50
</div>
</div>
<div className="relative">
<Input
placeholder="Username"
value={username}
onChange={(e) => setUsername(e.target.value)}
value={passwordItem.username}
onChange={handleChange}
maxLength={30}
name="username"
/>
<div
className="pointer-events-none absolute inset-y-0 end-0 flex items-center justify-center pe-3 text-xs tabular-nums text-muted-foreground peer-disabled:opacity-50"
aria-live="polite"
role="status"
>
{username.length}/30
{passwordItem.username.length} / 30
</div>
</div>
<div className="flex relative rounded-lg">
Expand All @@ -133,38 +137,40 @@ export const CreatePasswordDialog = ({
<Input
placeholder="Website"
className="-ms-px h-12 rounded-tl-none rounded-bl-none"
value={website}
onChange={(e) => setWebsite(e.target.value)}
value={passwordItem.website}
onChange={handleChange}
maxLength={50}
name="website"
/>
<div
className="pointer-events-none absolute inset-y-0 end-0 flex items-center justify-center pe-3 text-xs tabular-nums text-muted-foreground peer-disabled:opacity-50"
aria-live="polite"
role="status"
>
{website.length}/50
{passwordItem.website.length}/50
</div>
</div>
<div className="relative">
<Input
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
value={passwordItem.password}
onChange={handleChange}
type="password"
maxLength={128}
name="password"
/>
<div
className="pointer-events-none absolute inset-y-0 end-0 flex items-center justify-center pe-3 text-xs tabular-nums text-muted-foreground peer-disabled:opacity-50"
aria-live="polite"
role="status"
>
{password.length}/128
{passwordItem.password.length}/128
</div>
</div>
</div>
<DialogFooter>
<div className="mt-4 flex justify-end gap-2">
<Button variant="outline" onClick={onClose}>
<Button variant="outline" onClick={() => onClose()}>
Cancel
</Button>
<Button onClick={handleSave}>
Expand Down

0 comments on commit 00e3153

Please sign in to comment.