Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions frontend/src/components/Dialog/DeleteFolderDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { FC } from 'react';
import { AlertTriangle } from 'lucide-react';
import { Button } from '@/components/ui/button';

import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';

interface DeleteFolderDialogProps {
isOpen: boolean;
setIsOpen: (open: boolean) => void;
onConfirm: () => void;
folderPath: string;
}

const DeleteFolderDialog: FC<DeleteFolderDialogProps> = ({
isOpen,
setIsOpen,
onConfirm,
folderPath,
}) => {
const handleConfirm = () => {
onConfirm();
setIsOpen(false);
};

return (
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<div className="flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-red-100 dark:bg-red-900/20">
<AlertTriangle className="h-5 w-5 text-red-600 dark:text-red-400" />
</div>
<DialogTitle className="text-xl">Delete Folder?</DialogTitle>
</div>
<DialogDescription className="pt-4 text-left">
<div className="space-y-3">
<p className="font-medium text-foreground">
You are about to remove this folder from your library:
</p>
<div className="rounded-md bg-muted p-3">
<code className="text-sm break-all">{folderPath}</code>
</div>
<div className="space-y-2 text-sm">
<p className="font-semibold text-yellow-700 dark:text-yellow-400">
⚠️ This action will:
</p>
<ul className="ml-4 space-y-1 list-disc text-muted-foreground">
<li>Remove the folder from your PictoPy library</li>
<li>Delete all photos in this folder from the library</li>
<li>Remove all face recognition data for these photos</li>
<li>Delete all AI-generated tags and clusters</li>
</ul>
</div>
<div className="rounded-md border border-green-300 bg-green-50 p-3 dark:border-green-700 dark:bg-green-900/20">
<p className="text-sm font-medium text-green-800 dark:text-green-300">
✓ Your actual files on disk will NOT be deleted
</p>
</div>
</div>
</DialogDescription>
</DialogHeader>

<DialogFooter className="gap-2 sm:gap-0">
<Button
variant="outline"
onClick={() => setIsOpen(false)}
className="cursor-pointer"
>
Cancel
</Button>
<Button
variant="destructive"
onClick={handleConfirm}
className="cursor-pointer"
>
Delete from Library
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};

export default DeleteFolderDialog;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { Folder, Trash2, Check } from 'lucide-react';

import { Switch } from '@/components/ui/switch';
Expand All @@ -11,6 +11,7 @@ import FolderPicker from '@/components/FolderPicker/FolderPicker';
import { useFolderOperations } from '@/hooks/useFolderOperations';
import { FolderDetails } from '@/types/Folder';
import SettingsCard from './SettingsCard';
import DeleteFolderDialog from '@/components/Dialog/DeleteFolderDialog';

/**
* Component for managing folder operations in settings
Expand All @@ -29,6 +30,24 @@ const FolderManagementCard: React.FC = () => {
(state: RootState) => state.folders.taggingStatus,
);

// Dialog state for folder deletion confirmation
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [folderToDelete, setFolderToDelete] = useState<FolderDetails | null>(
null,
);

const handleDeleteClick = (folder: FolderDetails) => {
setFolderToDelete(folder);
setDeleteDialogOpen(true);
};

const handleConfirmDelete = () => {
if (folderToDelete) {
deleteFolder(folderToDelete.folder_id);
setFolderToDelete(null);
}
};

return (
<SettingsCard
icon={Folder}
Expand Down Expand Up @@ -68,7 +87,7 @@ const FolderManagementCard: React.FC = () => {
</div>

<Button
onClick={() => deleteFolder(folder.folder_id)}
onClick={() => handleDeleteClick(folder)}
variant="outline"
size="sm"
className="h-8 w-8 cursor-pointer text-gray-500 hover:border-red-300 hover:text-red-600 dark:text-gray-400 dark:hover:text-red-400"
Expand All @@ -95,7 +114,7 @@ const FolderManagementCard: React.FC = () => {
0) >= 100 && <Check className="h-3 w-3" />}
{Math.round(
taggingStatus[folder.folder_id]?.tagging_percentage ??
0,
0,
)}
%
</span>
Expand Down Expand Up @@ -131,6 +150,14 @@ const FolderManagementCard: React.FC = () => {
<div className="border-border mt-6 border-t pt-6">
<FolderPicker />
</div>

{/* Delete Folder Confirmation Dialog */}
<DeleteFolderDialog
isOpen={deleteDialogOpen}
setIsOpen={setDeleteDialogOpen}
onConfirm={handleConfirmDelete}
folderPath={folderToDelete?.folder_path || ''}
/>
</SettingsCard>
);
};
Expand Down