zulip-notes-app/src/pages/mails.tsx

179 lines
4.7 KiB
TypeScript

import {
ActionIcon,
Box,
Button,
Container,
LoadingOverlay,
Paper,
ScrollArea,
Text,
TextInput,
} from "@mantine/core";
import { useForm, zodResolver } from "@mantine/form";
import { useDisclosure } from "@mantine/hooks";
import { IconMail, IconTrash } from "@tabler/icons-react"; // Icon xóa
import { nanoid } from "nanoid"; // Để tạo ID cho mỗi email mới
import { useEffect, useRef, useState } from "react";
import { z } from "zod";
import { ConfirmModal } from "../components";
import { showNotification } from "../ultils/fn";
const schema = z.object({
email: z.string().email("Invalid email"),
});
function MailsPage() {
const viewport = useRef<HTMLDivElement>(null);
const [opened, { open, close }] = useDisclosure(false);
const [clickEmail, setClickEmail] = useState<IEmail | null>(null);
const [emails, setEmails] = useState<IEmail[]>([]); // Dùng để lưu danh sách email
const [loading, setLoading] = useState(false);
const form = useForm({
initialValues: {
email: "",
},
validate: zodResolver(schema),
});
const scrollToBottom = () =>
viewport.current!.scrollTo({
top: viewport.current!.scrollHeight,
behavior: "smooth",
});
// Hàm thêm email vào danh sách
const handleAddEmail = async ({ email }: { email: string }) => {
if (email.trim() !== "") {
try {
setLoading(true);
const response = await window.ipcRenderer.invoke("add-email", email);
if (!response) return;
console.log("%csrc/pages/mails.tsx:40 {response}", "color: #007acc;", {
response,
});
await fetchEmails();
showNotification("Thành công", "Đã thêm email mới");
scrollToBottom();
setClickEmail(null);
form.reset();
} catch (error) {
console.log("%csrc/pages/mails.tsx:65 error", "color: #007acc;", error);
} finally {
setLoading(false);
}
}
};
const handleDeleteEmail = async (id: number | undefined) => {
try {
if (!id) return;
setLoading(true);
await window.ipcRenderer.invoke("del-email", id);
await fetchEmails();
close();
showNotification("Thông báo", "Đã xóa email");
} catch (error) {
console.log("%csrc/pages/mails.tsx:88 error", "color: #007acc;", error);
} finally {
setLoading(false);
}
};
const fetchEmails = async () => {
try {
await window.ipcRenderer.invoke("connect-socket");
setLoading(true);
const mails = await window.ipcRenderer.invoke("fetchEmails");
console.log("%csrc/App.tsx:29 {mails}", "color: #007acc;", {
mails,
});
setEmails(mails);
} catch (error) {
console.error("Failed to connect socket", error);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchEmails();
return () => {
// window.ipcRenderer.removeListener("new-note", handleNewNote);
};
}, []);
return (
<Container style={{ paddingTop: 20 }} className="overflow-hidden">
<Paper shadow="xs" p="md" style={{ marginBottom: 20 }}>
<form onSubmit={form.onSubmit(handleAddEmail)}>
<TextInput
{...form.getInputProps("email")}
label="Enter Email"
placeholder="example@example.com"
/>
<Button type="submit" fullWidth style={{ marginTop: 10 }}>
Add Email
</Button>
</form>
</Paper>
<ScrollArea viewportRef={viewport} h={200} type="auto" pb={"lg"}>
<Box
className="flex flex-col gap-4"
size="sm"
style={{ marginTop: 20 }}
>
{emails.length > 0 ? (
emails.map((item) => (
<Box key={nanoid()} className="flex items-center">
<ActionIcon size={"md"} variant="outline" className="mr-3">
<IconMail size={18} />
</ActionIcon>
<Text style={{ flexGrow: 1 }}>{item.email}</Text>
<ActionIcon
onClick={() => {
setClickEmail(item);
open();
}}
color="red"
size="md"
variant="light"
>
<IconTrash size={16} />
</ActionIcon>
</Box>
))
) : (
<Text className="!text-gray-500">No emails added yet.</Text>
)}
</Box>
</ScrollArea>
<LoadingOverlay visible={loading} />
<ConfirmModal
title="Warning"
message="Caaj"
opened={opened}
onCancel={close}
onConfirm={() => handleDeleteEmail(clickEmail?.id)}
/>
</Container>
);
}
export default MailsPage;