mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 19:01:47 +00:00
feat(reports): melhora notas, calendario e analises
This commit is contained in:
@@ -8,15 +8,11 @@ import {
|
||||
RiInboxUnarchiveLine,
|
||||
RiPencilLine,
|
||||
} from "@remixicon/react";
|
||||
import { useMemo } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardFooter } from "@/components/ui/card";
|
||||
import { buildNoteDisplayTitle } from "@/lib/notes/formatters";
|
||||
import { type Note, sortTasksByStatus } from "./types";
|
||||
|
||||
const DATE_FORMATTER = new Intl.DateTimeFormat("pt-BR", {
|
||||
dateStyle: "medium",
|
||||
});
|
||||
|
||||
interface NoteCardProps {
|
||||
note: Note;
|
||||
onEdit?: (note: Note) => void;
|
||||
@@ -34,20 +30,10 @@ export function NoteCard({
|
||||
onArquivar,
|
||||
isArquivadas = false,
|
||||
}: NoteCardProps) {
|
||||
const { displayTitle } = useMemo(() => {
|
||||
const resolvedTitle = note.title.trim().length
|
||||
? note.title
|
||||
: "Anotação sem título";
|
||||
|
||||
return {
|
||||
displayTitle: resolvedTitle,
|
||||
formattedDate: DATE_FORMATTER.format(new Date(note.createdAt)),
|
||||
};
|
||||
}, [note.createdAt, note.title]);
|
||||
|
||||
const displayTitle = buildNoteDisplayTitle(note.title);
|
||||
const isTask = note.type === "tarefa";
|
||||
const tasks = note.tasks || [];
|
||||
const sortedTasks = useMemo(() => sortTasksByStatus(tasks), [tasks]);
|
||||
const sortedTasks = sortTasksByStatus(tasks);
|
||||
const completedCount = tasks.filter((t) => t.completed).length;
|
||||
const totalCount = tasks.length;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { RiCheckLine } from "@remixicon/react";
|
||||
import { useMemo } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
@@ -13,14 +12,13 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import {
|
||||
buildNoteDisplayTitle,
|
||||
formatNoteCreatedAtLong,
|
||||
} from "@/lib/notes/formatters";
|
||||
import { Card } from "../ui/card";
|
||||
import { type Note, sortTasksByStatus } from "./types";
|
||||
|
||||
const DATE_FORMATTER = new Intl.DateTimeFormat("pt-BR", {
|
||||
dateStyle: "long",
|
||||
timeStyle: "short",
|
||||
});
|
||||
|
||||
interface NoteDetailsDialogProps {
|
||||
note: Note | null;
|
||||
open: boolean;
|
||||
@@ -32,26 +30,14 @@ export function NoteDetailsDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
}: NoteDetailsDialogProps) {
|
||||
const { formattedDate, displayTitle } = useMemo(() => {
|
||||
if (!note) {
|
||||
return { formattedDate: "", displayTitle: "" };
|
||||
}
|
||||
|
||||
const title = note.title.trim().length ? note.title : "Anotação sem título";
|
||||
|
||||
return {
|
||||
formattedDate: DATE_FORMATTER.format(new Date(note.createdAt)),
|
||||
displayTitle: title,
|
||||
};
|
||||
}, [note]);
|
||||
|
||||
const tasks = note?.tasks || [];
|
||||
const sortedTasks = useMemo(() => sortTasksByStatus(tasks), [tasks]);
|
||||
|
||||
if (!note) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const formattedDate = formatNoteCreatedAtLong(note.createdAt) ?? "";
|
||||
const displayTitle = buildNoteDisplayTitle(note.title);
|
||||
const tasks = note.tasks || [];
|
||||
const sortedTasks = sortTasksByStatus(tasks);
|
||||
const isTask = note.type === "tarefa";
|
||||
const completedCount = tasks.filter((t) => t.completed).length;
|
||||
const totalCount = tasks.length;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { RiAddCircleLine, RiTodoLine } from "@remixicon/react";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
arquivarAnotacaoAction,
|
||||
deleteNoteAction,
|
||||
} from "@/app/(dashboard)/anotacoes/actions";
|
||||
import { ConfirmActionDialog } from "@/components/confirm-action-dialog";
|
||||
import { ConfirmActionDialog } from "@/components/shared/confirm-action-dialog";
|
||||
import { EmptyState } from "@/components/shared/empty-state";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
@@ -34,76 +34,78 @@ export function NotesPage({ notes, archivedNotes }: NotesPageProps) {
|
||||
const [arquivarOpen, setArquivarOpen] = useState(false);
|
||||
const [noteToArquivar, setNoteToArquivar] = useState<Note | null>(null);
|
||||
|
||||
const sortNotes = useCallback(
|
||||
(list: Note[]) =>
|
||||
[...list].sort(
|
||||
const sortedNotes = useMemo(
|
||||
() =>
|
||||
[...notes].sort(
|
||||
(a, b) =>
|
||||
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
|
||||
),
|
||||
[],
|
||||
[notes],
|
||||
);
|
||||
|
||||
const sortedNotes = useMemo(() => sortNotes(notes), [notes, sortNotes]);
|
||||
const sortedArchivedNotes = useMemo(
|
||||
() => sortNotes(archivedNotes),
|
||||
[archivedNotes, sortNotes],
|
||||
() =>
|
||||
[...archivedNotes].sort(
|
||||
(a, b) =>
|
||||
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
|
||||
),
|
||||
[archivedNotes],
|
||||
);
|
||||
|
||||
const isArquivadas = activeTab === "arquivadas";
|
||||
|
||||
const handleCreateOpenChange = useCallback((open: boolean) => {
|
||||
const handleCreateOpenChange = (open: boolean) => {
|
||||
setCreateOpen(open);
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleEditOpenChange = useCallback((open: boolean) => {
|
||||
const handleEditOpenChange = (open: boolean) => {
|
||||
setEditOpen(open);
|
||||
if (!open) {
|
||||
setNoteToEdit(null);
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleDetailsOpenChange = useCallback((open: boolean) => {
|
||||
const handleDetailsOpenChange = (open: boolean) => {
|
||||
setDetailsOpen(open);
|
||||
if (!open) {
|
||||
setNoteDetails(null);
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleRemoveOpenChange = useCallback((open: boolean) => {
|
||||
const handleRemoveOpenChange = (open: boolean) => {
|
||||
setRemoveOpen(open);
|
||||
if (!open) {
|
||||
setNoteToRemove(null);
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleArquivarOpenChange = useCallback((open: boolean) => {
|
||||
const handleArquivarOpenChange = (open: boolean) => {
|
||||
setArquivarOpen(open);
|
||||
if (!open) {
|
||||
setNoteToArquivar(null);
|
||||
}
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleEditRequest = useCallback((note: Note) => {
|
||||
const handleEditRequest = (note: Note) => {
|
||||
setNoteToEdit(note);
|
||||
setEditOpen(true);
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleDetailsRequest = useCallback((note: Note) => {
|
||||
const handleDetailsRequest = (note: Note) => {
|
||||
setNoteDetails(note);
|
||||
setDetailsOpen(true);
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleRemoveRequest = useCallback((note: Note) => {
|
||||
const handleRemoveRequest = (note: Note) => {
|
||||
setNoteToRemove(note);
|
||||
setRemoveOpen(true);
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleArquivarRequest = useCallback((note: Note) => {
|
||||
const handleArquivarRequest = (note: Note) => {
|
||||
setNoteToArquivar(note);
|
||||
setArquivarOpen(true);
|
||||
}, []);
|
||||
};
|
||||
|
||||
const handleArquivarConfirm = useCallback(async () => {
|
||||
const handleArquivarConfirm = async () => {
|
||||
if (!noteToArquivar) {
|
||||
return;
|
||||
}
|
||||
@@ -120,9 +122,9 @@ export function NotesPage({ notes, archivedNotes }: NotesPageProps) {
|
||||
|
||||
toast.error(result.error);
|
||||
throw new Error(result.error);
|
||||
}, [noteToArquivar, isArquivadas]);
|
||||
};
|
||||
|
||||
const handleRemoveConfirm = useCallback(async () => {
|
||||
const handleRemoveConfirm = async () => {
|
||||
if (!noteToRemove) {
|
||||
return;
|
||||
}
|
||||
@@ -136,7 +138,7 @@ export function NotesPage({ notes, archivedNotes }: NotesPageProps) {
|
||||
|
||||
toast.error(result.error);
|
||||
throw new Error(result.error);
|
||||
}, [noteToRemove]);
|
||||
};
|
||||
|
||||
const removeTitle = noteToRemove
|
||||
? noteToRemove.title.trim().length
|
||||
|
||||
Reference in New Issue
Block a user