From 8b6565a1635f9a16875b38e186a8822ff32e30bb Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 7 May 2025 08:32:15 +0700 Subject: [PATCH] delete note --- electron/main.ts | 12 +- src/apis/index.ts | 79 +++++++------ src/components/message.tsx | 7 +- src/components/settings.tsx | 10 +- src/pages/main.tsx | 230 ++++++++++++++++++++++-------------- 5 files changed, 204 insertions(+), 134 deletions(-) diff --git a/electron/main.ts b/electron/main.ts index 5ec1404..953b77f 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -4,7 +4,7 @@ import { app, BrowserWindow, ipcMain, Menu, Notification, screen } from 'electro import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { io } from 'socket.io-client'; -import { addEmail, deleteEmail, fetchEmails, fetchMessages } from '../src/apis'; +import { addEmail, deleteEmail, deleteMessage, fetchEmails, fetchMessages } from '../src/apis'; import { createMailWindow } from './windows/mails.window'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -53,8 +53,8 @@ function createWindow() { // Vị trí cửa sổ ở góc phải dưới của màn hình đã chọn win = new BrowserWindow({ - width: 600, - height: 200, + width: 400, + height: 400, x: 0, // Đặt cửa sổ ở góc phải y: 0, // Đặt cửa sổ ở góc dưới alwaysOnTop: true, // Cửa sổ luôn nằm trên các cửa sổ khác @@ -70,7 +70,7 @@ function createWindow() { win?.webContents.send('main-process-message', new Date().toLocaleString()); }); - win.setPosition(width - 600, height - 200); + win.setPosition(width - 400, height - 400); if (VITE_DEV_SERVER_URL) { win.loadURL(VITE_DEV_SERVER_URL); @@ -148,6 +148,10 @@ ipcMain.handle('del-email', async (_, id: number) => { return deleteEmail(id); }); +ipcMain.handle('del-message', async (_, id: number) => { + return deleteMessage(id); +}); + ipcMain.handle('show-notification', async (_, { title, body }) => { const notification = new Notification({ title, diff --git a/src/apis/index.ts b/src/apis/index.ts index e33c169..dba96b0 100644 --- a/src/apis/index.ts +++ b/src/apis/index.ts @@ -1,55 +1,62 @@ -import axios from '../instants/axios'; +import axios from "../instants/axios"; const API_KEY = import.meta.env.VITE_API_KEY; export const getAllNote = async () => { - try { - const response = await axios({ - method: 'GET', - url: 'getAllNotes', - }); + try { + const response = await axios({ + method: "GET", + url: "getAllNotes", + }); - return response.data; - } catch (error) { - return []; - } + return response.data; + } catch (error) { + return []; + } }; export async function fetchMessages(onError?: (error: unknown) => void) { - try { - const response = await axios.get(`getAllNotes?key=${API_KEY}`); + try { + const response = await axios.get(`getAllNotes?key=${API_KEY}`); - return response.data; - } catch (error) { - console.error('Error fetching notes:', error); - onError?.(error); - } + return response.data; + } catch (error) { + console.error("Error fetching notes:", error); + onError?.(error); + } } export async function fetchEmails(onError?: (error: unknown) => void) { - try { - const response = await axios.get(`emails?key=${API_KEY}`); - return response.data; - } catch (error) { - console.error('Error fetching emails:', error); - onError?.(error); - } + try { + const response = await axios.get(`emails?key=${API_KEY}`); + return response.data; + } catch (error) { + console.error("Error fetching emails:", error); + onError?.(error); + } } -export async function addEmail(email: string, onError?: (error: unknown) => void) { - try { - const response = await axios.post(`add-email`, { - email: email, - key: API_KEY, - }); +export async function addEmail( + email: string, + onError?: (error: unknown) => void +) { + try { + const response = await axios.post(`add-email`, { + email: email, + key: API_KEY, + }); - return response.data; - } catch (error) { - console.error('Error add email:', error); - onError?.(error); - } + return response.data; + } catch (error) { + console.error("Error add email:", error); + onError?.(error); + } } export async function deleteEmail(id: number) { - await axios.delete(`delete-email/${id}?key=${API_KEY}`); + await axios.delete(`delete-email/${id}?key=${API_KEY}`); +} + +export async function deleteMessage(id: number) { + await axios.delete(`delete-note/${id}?key=${API_KEY}`); } diff --git a/src/components/message.tsx b/src/components/message.tsx index d2c5771..0f38771 100644 --- a/src/components/message.tsx +++ b/src/components/message.tsx @@ -5,9 +5,10 @@ import { useEffect, useMemo, useState } from 'react'; export interface IMessageProps { data: IMessage; + onDelete: () => void } -export default function Message({ data }: IMessageProps) { +export default function Message({ data, onDelete }: IMessageProps) { const [show, { toggle }] = useDisclosure(false); const [animation, setAnimation] = useState(false); @@ -27,7 +28,7 @@ export default function Message({ data }: IMessageProps) { }, [animation]); useEffect(() => { - const showAnimation = new Date().getTime() - new Date(data.time).getTime() <= 3000; + const showAnimation = new Date().getTime() - new Date(data.time).getTime() <= 110000; setAnimation(showAnimation); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -51,7 +52,7 @@ export default function Message({ data }: IMessageProps) { - + diff --git a/src/components/settings.tsx b/src/components/settings.tsx index 193a4f3..cc6c534 100644 --- a/src/components/settings.tsx +++ b/src/components/settings.tsx @@ -1,11 +1,14 @@ import { Menu } from "@mantine/core"; -import { IconCode } from "@tabler/icons-react"; +import { IconCode, IconRefresh } from "@tabler/icons-react"; import { ReactNode } from "react"; export interface ISettingsProps { children: ReactNode; + funtions?: { + refresh?: () => void + } } -export default function Settings({ children }: ISettingsProps) { +export default function Settings({ children, funtions }: ISettingsProps) { const openDevtools = () => { window.ipcRenderer?.openDevTools(); }; @@ -19,6 +22,9 @@ export default function Settings({ children }: ISettingsProps) { } className="text-xs"> Devtool + } className="text-xs"> + Refresh + ); diff --git a/src/pages/main.tsx b/src/pages/main.tsx index df14669..a7ec375 100644 --- a/src/pages/main.tsx +++ b/src/pages/main.tsx @@ -1,106 +1,158 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { ActionIcon, Box, LoadingOverlay, ScrollAreaAutosize, Tooltip } from '@mantine/core'; -import { useViewportSize } from '@mantine/hooks'; // 🔥 thêm cái này -import { IconDotsVertical, IconMail } from '@tabler/icons-react'; -import { useEffect, useRef, useState } from 'react'; -import { Message, Settings } from '../components'; -import { showNotification } from '../ultils/fn'; +import { + ActionIcon, + Box, + LoadingOverlay, + ScrollAreaAutosize, + Tooltip, +} from "@mantine/core"; +import { useDisclosure, useViewportSize } from "@mantine/hooks"; // 🔥 thêm cái này +import { IconDotsVertical, IconMail } from "@tabler/icons-react"; +import { useEffect, useRef, useState } from "react"; +import { ConfirmModal, Message, Settings } from "../components"; +import { showNotification } from "../ultils/fn"; function MainPage() { - const [messages, setMessages] = useState([]); - const viewportRef = useRef(null); - const [loading, setLoading] = useState(false); + const [messages, setMessages] = useState([]); + const viewportRef = useRef(null); + const [loading, setLoading] = useState(false); + const [opened, { open, close }] = useDisclosure(false); + const { height } = useViewportSize(); // lấy kích thước cửa sổ + const [clickMessage, setClickMessage] = useState(null); + const scrollToBottom = () => { + const viewport = viewportRef.current; + if (viewport) { + viewport.scrollTo({ + top: viewport.scrollHeight, + behavior: "smooth", + }); + } + }; - const { height } = useViewportSize(); // lấy kích thước cửa sổ + const fetchMessages = async () => { + const messages = await window.ipcRenderer.invoke("fetchMessages"); - const scrollToBottom = () => { - const viewport = viewportRef.current; - if (viewport) { - viewport.scrollTo({ - top: viewport.scrollHeight, - behavior: 'smooth', - }); - } + if (!messages || !Array.isArray(messages)) { + showNotification("Lỗi fetch notes", `Error: ${JSON.stringify(messages)}`); + return; + } + + setMessages(messages); + }; + + const handleDeleteMessage = async (id?: number) => { + try { + if (!id) return; + setLoading(true); + await window.ipcRenderer.invoke("del-message", id); + + await fetchMessages(); + close(); + + showNotification("Thông báo", "Đã xóa note: " + clickMessage?.id); + setClickMessage(null) + } catch (error) { + console.log("%csrc/pages/mails.tsx:88 error", "color: #007acc;", error); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + const connectSocket = async () => { + try { + await window.ipcRenderer.invoke("connect-socket"); + setLoading(true); + await fetchMessages(); + setTimeout(scrollToBottom, 100); + } catch (error) { + console.error("Failed to connect socket", error); + } finally { + setLoading(false); + } }; - const fetchMessages = async () => { - const messages = await window.ipcRenderer.invoke('fetchMessages'); + connectSocket(); + window.ipcRenderer?.onNewNote(async (data: any) => { + console.log("Received newNote data:", data); + showNotification("Có tin nhắn mới", data.message); + await fetchMessages(); + setTimeout(() => scrollToBottom(), 100); + }); + }, []); - if (!messages || !Array.isArray(messages)) { - showNotification('Lỗi fetch notes', `Error: ${JSON.stringify(messages)}`); - return; - } + const openMailsWindow = () => { + window.ipcRenderer.invoke("open-new-window"); + }; - setMessages(messages); - }; + // 🧠 Tính chiều cao dynamic (ví dụ trừ header 80px + padding 30px) + const scrollAreaHeight = height - 70; // Bạn chỉnh số này nếu muốn - useEffect(() => { - const connectSocket = async () => { - try { - await window.ipcRenderer.invoke('connect-socket'); - setLoading(true); - await fetchMessages(); - setTimeout(scrollToBottom, 100); - } catch (error) { - console.error('Failed to connect socket', error); - } finally { - setLoading(false); - } - }; + return ( + + {/* Header */} +
+ + + + + - connectSocket(); - window.ipcRenderer?.onNewNote(async (data: any) => { - console.log('Received newNote data:', data); - showNotification('Có tin nhắn mới', data.message); - await fetchMessages(); - scrollToBottom(); - }); - }, []); +
Notes
- const openMailsWindow = () => { - window.ipcRenderer.invoke('open-new-window'); - }; + { + setLoading(true); + await fetchMessages(); + setLoading(false); + }, + }} + > + + + + + + +
- // 🧠 Tính chiều cao dynamic (ví dụ trừ header 80px + padding 30px) - const scrollAreaHeight = height - 70; // Bạn chỉnh số này nếu muốn - - return ( - - {/* Header */} -
- - - - - - -
Notes
- - - - - - - - -
- - {/* Message List */} - - - {messages.map((item) => ( - - ))} - - - - + {/* Message List */} + + + {messages.map((item) => ( + { + setClickMessage(item); + open(); + }} + key={item.message + item.id} + data={item} + /> + ))} - ); + + + + + handleDeleteMessage(clickMessage?.id)} + /> +
+ ); } export default MainPage;