179 lines
4.7 KiB
TypeScript
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;
|