95 lines
2.8 KiB
TypeScript
95 lines
2.8 KiB
TypeScript
import { useState } from "react";
|
|
import { View, Text } from "react-native";
|
|
import { Dialog, IconButton } from "react-native-paper";
|
|
|
|
import { DialogContainer } from "@/components/ui/DialogContainer";
|
|
import { Todo } from "@/store/models/Todo.model";
|
|
import { Button } from "@/components/ui/Button";
|
|
import { LoadingSpinner } from "@/components/ui/LoadingSpinner";
|
|
import { AppSnackbar } from "@/components/ui/AppSnackbar";
|
|
|
|
interface DeleteTodoModalProps {
|
|
visible: boolean;
|
|
todo: Todo | null;
|
|
onDismiss: () => void;
|
|
onDelete: (todo: Todo) => void;
|
|
isLoading?: boolean;
|
|
}
|
|
|
|
export const DeleteTodoModal = ({
|
|
visible,
|
|
todo,
|
|
onDismiss,
|
|
onDelete,
|
|
isLoading = false,
|
|
}: DeleteTodoModalProps) => {
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [snackbarVisible, setSnackbarVisible] = useState(false);
|
|
const [snackbarMessage, setSnackbarMessage] = useState("");
|
|
const showSnackbar = (message: string) => {
|
|
setSnackbarMessage(message);
|
|
setSnackbarVisible(true);
|
|
};
|
|
|
|
if (!todo) return null;
|
|
|
|
const handleDelete = () => {
|
|
try {
|
|
setError(null);
|
|
onDelete(todo);
|
|
} catch {
|
|
showSnackbar("Failed to delete todo. Please try again.");
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<DialogContainer visible={visible} onDismiss={onDismiss}>
|
|
<Dialog.Title>
|
|
<View className="w-full flex-row items-center justify-between">
|
|
<View className="flex-1">
|
|
<Text className="pr-3">Delete Todo</Text>
|
|
</View>
|
|
|
|
<View style={{ alignSelf: "flex-start" }}>
|
|
<IconButton
|
|
icon="close"
|
|
size={20}
|
|
onPress={onDismiss}
|
|
disabled={isLoading}
|
|
accessibilityLabel="Close dialog"
|
|
style={{ margin: 0 }}
|
|
/>
|
|
</View>
|
|
</View>
|
|
</Dialog.Title>
|
|
<Dialog.Content>
|
|
<Text>Are you sure you want to delete {todo.title}?</Text>
|
|
{error && <Text className="text-highRisk mt-2">{error}</Text>}
|
|
</Dialog.Content>
|
|
<Dialog.Actions>
|
|
<Button className="!ml-2" onPress={handleDelete} disabled={isLoading}>
|
|
Delete
|
|
</Button>
|
|
</Dialog.Actions>
|
|
{isLoading && (
|
|
<View
|
|
className="absolute inset-0 bg-gray-500/30 flex items-center justify-center"
|
|
pointerEvents="auto"
|
|
style={{ zIndex: 1000, top: 0, right: 0, bottom: 0, left: 0 }}
|
|
>
|
|
<LoadingSpinner size={16} />
|
|
</View>
|
|
)}
|
|
</DialogContainer>
|
|
<AppSnackbar
|
|
visible={snackbarVisible}
|
|
onDismiss={() => setSnackbarVisible(false)}
|
|
action={{ label: "Close", onPress: () => setSnackbarVisible(false) }}
|
|
>
|
|
{snackbarMessage}
|
|
</AppSnackbar>
|
|
</>
|
|
);
|
|
};
|