feat: adicionar página de anotações arquivadas e componente de notificação
- Implementa a página de anotações arquivadas, que busca as notas arquivadas do usuário e as exibe utilizando o componente NotesPage. - Cria o componente NotificationBell para gerenciar e exibir notificações de pagamentos, incluindo a formatação de datas e valores monetários. O componente também apresenta um sistema de tooltip e dropdown para interação do usuário.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
"use server";
|
||||
|
||||
import { anotacoes } from "@/db/schema";
|
||||
import { type ActionResult, handleActionError } from "@/lib/actions/helpers";
|
||||
import { revalidateForEntity } from "@/lib/actions/helpers";
|
||||
import { handleActionError, revalidateForEntity } from "@/lib/actions/helpers";
|
||||
import type { ActionResult } from "@/lib/actions/types";
|
||||
import { uuidSchema } from "@/lib/schemas/common";
|
||||
import { db } from "@/lib/db";
|
||||
import { getUser } from "@/lib/auth/server";
|
||||
@@ -142,3 +142,45 @@ export async function deleteNoteAction(
|
||||
return handleActionError(error);
|
||||
}
|
||||
}
|
||||
|
||||
const arquivarNoteSchema = z.object({
|
||||
id: uuidSchema("Anotação"),
|
||||
arquivada: z.boolean(),
|
||||
});
|
||||
|
||||
type NoteArquivarInput = z.infer<typeof arquivarNoteSchema>;
|
||||
|
||||
export async function arquivarAnotacaoAction(
|
||||
input: NoteArquivarInput
|
||||
): Promise<ActionResult> {
|
||||
try {
|
||||
const user = await getUser();
|
||||
const data = arquivarNoteSchema.parse(input);
|
||||
|
||||
const [updated] = await db
|
||||
.update(anotacoes)
|
||||
.set({
|
||||
arquivada: data.arquivada,
|
||||
})
|
||||
.where(and(eq(anotacoes.id, data.id), eq(anotacoes.userId, user.id)))
|
||||
.returning({ id: anotacoes.id });
|
||||
|
||||
if (!updated) {
|
||||
return {
|
||||
success: false,
|
||||
error: "Anotação não encontrada.",
|
||||
};
|
||||
}
|
||||
|
||||
revalidateForEntity("anotacoes");
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: data.arquivada
|
||||
? "Anotação arquivada com sucesso."
|
||||
: "Anotação desarquivada com sucesso."
|
||||
};
|
||||
} catch (error) {
|
||||
return handleActionError(error);
|
||||
}
|
||||
}
|
||||
|
||||
14
app/(dashboard)/anotacoes/arquivadas/page.tsx
Normal file
14
app/(dashboard)/anotacoes/arquivadas/page.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { NotesPage } from "@/components/anotacoes/notes-page";
|
||||
import { getUserId } from "@/lib/auth/server";
|
||||
import { fetchArquivadasForUser } from "../data";
|
||||
|
||||
export default async function ArquivadasPage() {
|
||||
const userId = await getUserId();
|
||||
const notes = await fetchArquivadasForUser(userId);
|
||||
|
||||
return (
|
||||
<main className="flex flex-col items-start gap-6">
|
||||
<NotesPage notes={notes} isArquivadas={true} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { anotacoes, type Anotacao } from "@/db/schema";
|
||||
import { db } from "@/lib/db";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
|
||||
export type Task = {
|
||||
id: string;
|
||||
@@ -14,12 +14,13 @@ export type NoteData = {
|
||||
description: string;
|
||||
type: "nota" | "tarefa";
|
||||
tasks?: Task[];
|
||||
arquivada: boolean;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
export async function fetchNotesForUser(userId: string): Promise<NoteData[]> {
|
||||
const noteRows = await db.query.anotacoes.findMany({
|
||||
where: eq(anotacoes.userId, userId),
|
||||
where: and(eq(anotacoes.userId, userId), eq(anotacoes.arquivada, false)),
|
||||
orderBy: (note: typeof anotacoes.$inferSelect, { desc }: { desc: (field: unknown) => unknown }) => [desc(note.createdAt)],
|
||||
});
|
||||
|
||||
@@ -42,6 +43,38 @@ export async function fetchNotesForUser(userId: string): Promise<NoteData[]> {
|
||||
description: (note.description ?? "").trim(),
|
||||
type: (note.type ?? "nota") as "nota" | "tarefa",
|
||||
tasks,
|
||||
arquivada: note.arquivada,
|
||||
createdAt: note.createdAt.toISOString(),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchArquivadasForUser(userId: string): Promise<NoteData[]> {
|
||||
const noteRows = await db.query.anotacoes.findMany({
|
||||
where: and(eq(anotacoes.userId, userId), eq(anotacoes.arquivada, true)),
|
||||
orderBy: (note: typeof anotacoes.$inferSelect, { desc }: { desc: (field: unknown) => unknown }) => [desc(note.createdAt)],
|
||||
});
|
||||
|
||||
return noteRows.map((note: Anotacao) => {
|
||||
let tasks: Task[] | undefined;
|
||||
|
||||
// Parse tasks if they exist
|
||||
if (note.tasks) {
|
||||
try {
|
||||
tasks = JSON.parse(note.tasks);
|
||||
} catch (error) {
|
||||
console.error("Failed to parse tasks for note", note.id, error);
|
||||
tasks = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: note.id,
|
||||
title: (note.title ?? "").trim(),
|
||||
description: (note.description ?? "").trim(),
|
||||
type: (note.type ?? "nota") as "nota" | "tarefa",
|
||||
tasks,
|
||||
arquivada: note.arquivada,
|
||||
createdAt: note.createdAt.toISOString(),
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user