@@ -13,13 +13,14 @@ import { decrypt, generateAndStoreKey, retrieveKey } from "@/utils/encryption";
1313import { useUser } from "@clerk/nextjs" ;
1414import type { Prisma } from "@prisma/client" ;
1515import {
16+ ArrowDownAZ ,
17+ ArrowDownWideNarrow ,
18+ Clock ,
1619 Plus ,
1720 SquareArrowOutUpRight ,
1821 Trash ,
1922 User ,
20- ArrowDownAZ ,
21- ArrowDownWideNarrow ,
22- Clock ,
23+ X ,
2324} from "lucide-react" ;
2425import Image from "next/image" ;
2526import { useRouter } from "next/navigation" ;
@@ -32,10 +33,11 @@ import {
3233 ContextMenuLabel ,
3334 ContextMenuTrigger ,
3435} from "../ui/context-menu" ;
36+ import { Tooltip , TooltipContent , TooltipTrigger } from "../ui/tooltip" ;
37+ import { ConfirmationDialog } from "./dialogs/confirm-dialog" ;
3538import { EmptyState } from "./empty-state" ;
3639import { PasswordDetails } from "./password-details" ;
3740import { Sidebar } from "./sidebar" ;
38- import { Tooltip , TooltipContent , TooltipTrigger } from "../ui/tooltip" ;
3941
4042interface PasswordEntry {
4143 id : string ;
@@ -79,6 +81,11 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
7981 const [ sortBy , setSortBy ] = useState < "name" | "created" | "updated" > (
8082 "created"
8183 ) ;
84+ const [ isConfirmationDialogOpen , setIsConfirmationDialogOpen ] =
85+ useState ( false ) ;
86+ const [ passwordToDelete , setPasswordToDelete ] =
87+ useState < PasswordEntry | null > ( null ) ;
88+ const [ isDeleting , setIsDeleting ] = useState ( false ) ;
8289
8390 useEffect ( ( ) => {
8491 const ensureEncryptionKey = async ( ) => {
@@ -319,10 +326,9 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
319326 filteredAndSortedPasswords . map ( ( password ) => (
320327 < ContextMenu key = { password . id } >
321328 < ContextMenuTrigger >
322- < Button
323- variant = "ghost"
329+ < div
324330 className = { cn (
325- "w-full justify-start rounded-xl p-4 text-left transition-all hover:bg-rose-50/50 dark:hover:bg-rose-900/50" ,
331+ "flex w-full justify-between rounded-xl p-2 text-left transition-all hover:bg-rose-50/50 dark:hover:bg-rose-900/50 hover:cursor-pointer " ,
326332 selectedEntry ?. id === password . id &&
327333 "bg-rose-50 dark:bg-rose-900"
328334 ) }
@@ -347,7 +353,20 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
347353 </ div >
348354 </ div >
349355 </ div >
350- </ Button >
356+
357+ < Button
358+ variant = "ghost"
359+ size = "icon"
360+ className = "text-muted-foreground hover:text-foreground"
361+ onClick = { ( e ) => {
362+ e . stopPropagation ( ) ;
363+ setPasswordToDelete ( password ) ;
364+ setIsConfirmationDialogOpen ( true ) ;
365+ } }
366+ >
367+ < X className = "h-4 w-4" />
368+ </ Button >
369+ </ div >
351370 </ ContextMenuTrigger >
352371 < ContextMenuContent className = "rounded-xl" >
353372 < ContextMenuLabel >
@@ -413,7 +432,16 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
413432 </ ContextMenuContent >
414433 </ ContextMenu >
415434 ) ) }
416-
435+ { activeTab === "notes" && (
436+ < div className = "flex h-full items-center justify-center text-gray-500 dark:text-gray-400" >
437+ No { activeTab } available
438+ </ div >
439+ ) }
440+ { activeTab === "pins" && (
441+ < div className = "flex h-full items-center justify-center text-gray-500 dark:text-gray-400" >
442+ No { activeTab } available
443+ </ div >
444+ ) }
417445 { activeTab === "cards" && (
418446 < div className = "flex h-full items-center justify-center text-gray-500 dark:text-gray-400" >
419447 No { activeTab } available
@@ -452,6 +480,7 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
452480 ) }
453481 </ div >
454482 </ div >
483+
455484 { isEditDialogOpen && (
456485 < EditPasswordDialog
457486 isOpen = { isEditDialogOpen }
@@ -466,6 +495,7 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
466495 entry = { selectedEntry }
467496 />
468497 ) }
498+
469499 < CreatePasswordDialog
470500 open = { isCreateDialogOpen }
471501 onClose = { async ( ) => {
@@ -476,6 +506,34 @@ export const VaultPage: React.FC<VaultPageProps> = ({ user }) => {
476506 } }
477507 setSelectedEntry = { setSelectedEntry }
478508 />
509+
510+ < ConfirmationDialog
511+ open = { isConfirmationDialogOpen }
512+ onClose = { ( ) => setIsConfirmationDialogOpen ( false ) }
513+ title = "Delete Password"
514+ message = "Are you sure you want to delete this password? This action cannot be undone."
515+ onConfirm = { async ( ) => {
516+ if ( passwordToDelete ) {
517+ setIsDeleting ( true ) ;
518+ try {
519+ await deletePasswordItem ( passwordToDelete . id ) ;
520+ const updatedItems = await getPasswords ( user ?. id as string ) ;
521+ setPasswordItems ( updatedItems ?. passwordItems ) ;
522+ if ( selectedEntry ?. id === passwordToDelete . id ) {
523+ setSelectedEntry ( null ) ;
524+ }
525+ toast . success ( "Password deleted successfully" ) ;
526+ } catch {
527+ toast . error ( "Failed to delete password" ) ;
528+ } finally {
529+ setIsDeleting ( false ) ;
530+ setIsConfirmationDialogOpen ( false ) ;
531+ setPasswordToDelete ( null ) ;
532+ }
533+ }
534+ } }
535+ loading = { isDeleting }
536+ />
479537 </ div >
480538 ) ;
481539} ;
0 commit comments