@@ -13,21 +13,25 @@ import { Input } from "@/components/ui/input";
1313import { encrypt } from "@/utils/encryption" ;
1414import { useUser } from "@clerk/nextjs" ;
1515import { Loader2 } from "lucide-react" ;
16- import { useState } from "react" ;
16+ import { ChangeEvent , useState } from "react" ;
1717import toast from "react-hot-toast" ;
1818import { z } from "zod" ;
1919
20+ const initialPasswordItemState = {
21+ name : "" ,
22+ username : "" ,
23+ website : "" ,
24+ password : "" ,
25+ } ;
26+
2027export const CreatePasswordDialog = ( {
2128 open,
2229 onClose,
2330} : {
2431 open : boolean ;
2532 onClose : ( ) => void ;
2633} ) => {
27- const [ name , setName ] = useState ( "" ) ;
28- const [ username , setUsername ] = useState ( "" ) ;
29- const [ website , setWebsite ] = useState ( "" ) ;
30- const [ password , setPassword ] = useState ( "" ) ;
34+ const [ passwordItem , setPasswordItem ] = useState ( initialPasswordItemState ) ;
3135 const [ loading , setLoading ] = useState ( false ) ;
3236
3337 const { user : clerkuser } = useUser ( ) ;
@@ -53,41 +57,39 @@ export const CreatePasswordDialog = ({
5357
5458 const handleSave = async ( ) => {
5559 setLoading ( true ) ;
56-
57- const formattedWebsite = website . startsWith ( "https://" )
58- ? website
59- : `https://${ website } ` ;
60-
61- const validationResult = passwordSchema . safeParse ( {
62- name,
63- username,
64- website : formattedWebsite ,
65- password,
66- } ) ;
67-
60+
61+ const validationResult = passwordSchema . safeParse ( passwordItem ) ;
62+
6863 if ( ! validationResult . success ) {
6964 const errorMessage =
7065 validationResult . error . errors [ 0 ] ?. message || "Validation failed" ;
7166 toast . error ( errorMessage ) ;
7267 setLoading ( false ) ;
7368 return ;
7469 }
75-
70+
7671 try {
7772 await createPasswordItem (
78- encrypt ( username , clerkuser ) ,
79- encrypt ( formattedWebsite , clerkuser ) ,
80- encrypt ( password , clerkuser )
73+ encrypt ( passwordItem . username , clerkuser ) ,
74+ encrypt ( passwordItem . website , clerkuser ) ,
75+ encrypt ( passwordItem . password , clerkuser )
8176 ) ;
8277 toast . success ( "Password created" ) ;
78+ setPasswordItem ( initialPasswordItemState ) ;
8379 onClose ( ) ;
8480 } catch ( error ) {
8581 toast . error ( "Failed to create password" ) ;
8682 } finally {
8783 setLoading ( false ) ;
8884 }
8985 } ;
90-
86+
87+ const handleChange = ( e : ChangeEvent < HTMLInputElement > ) => {
88+ setPasswordItem ( ( prevState ) => ( {
89+ ...prevState ,
90+ [ e . target . name ] : e . target . value ,
91+ } ) ) ;
92+ } ;
9193
9294 return (
9395 < Dialog open = { open } onOpenChange = { onClose } >
@@ -99,31 +101,33 @@ export const CreatePasswordDialog = ({
99101 < div className = "relative" >
100102 < Input
101103 placeholder = "Name"
102- value = { name }
103- onChange = { ( e ) => setName ( e . target . value ) }
104+ value = { passwordItem . name }
105+ onChange = { handleChange }
104106 maxLength = { 50 }
107+ name = "name"
105108 />
106109 < div
107110 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"
108111 aria-live = "polite"
109112 role = "status"
110113 >
111- { name . length } /50
114+ { passwordItem . name . length } /50
112115 </ div >
113116 </ div >
114117 < div className = "relative" >
115118 < Input
116119 placeholder = "Username"
117- value = { username }
118- onChange = { ( e ) => setUsername ( e . target . value ) }
120+ value = { passwordItem . username }
121+ onChange = { handleChange }
119122 maxLength = { 30 }
123+ name = "username"
120124 />
121125 < div
122126 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"
123127 aria-live = "polite"
124128 role = "status"
125129 >
126- { username . length } / 30
130+ { passwordItem . username . length } / 30
127131 </ div >
128132 </ div >
129133 < div className = "flex relative rounded-lg" >
@@ -133,38 +137,40 @@ export const CreatePasswordDialog = ({
133137 < Input
134138 placeholder = "Website"
135139 className = "-ms-px h-12 rounded-tl-none rounded-bl-none"
136- value = { website }
137- onChange = { ( e ) => setWebsite ( e . target . value ) }
140+ value = { passwordItem . website }
141+ onChange = { handleChange }
138142 maxLength = { 50 }
143+ name = "website"
139144 />
140145 < div
141146 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"
142147 aria-live = "polite"
143148 role = "status"
144149 >
145- { website . length } /50
150+ { passwordItem . website . length } /50
146151 </ div >
147152 </ div >
148153 < div className = "relative" >
149154 < Input
150155 placeholder = "Password"
151- value = { password }
152- onChange = { ( e ) => setPassword ( e . target . value ) }
156+ value = { passwordItem . password }
157+ onChange = { handleChange }
153158 type = "password"
154159 maxLength = { 128 }
160+ name = "password"
155161 />
156162 < div
157163 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"
158164 aria-live = "polite"
159165 role = "status"
160166 >
161- { password . length } /128
167+ { passwordItem . password . length } /128
162168 </ div >
163169 </ div >
164170 </ div >
165171 < DialogFooter >
166172 < div className = "mt-4 flex justify-end gap-2" >
167- < Button variant = "outline" onClick = { onClose } >
173+ < Button variant = "outline" onClick = { ( ) => onClose ( ) } >
168174 Cancel
169175 </ Button >
170176 < Button onClick = { handleSave } >
0 commit comments