mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-03-10 04:51:47 +00:00
feat(changelog): implementar funcionalidades de leitura de atualizações
- Adiciona funções para marcar atualizações como lidas - Implementa a lógica para marcar todas as atualizações como lidas - Adiciona suporte a logs de atualizações lidas no banco de dados - Cria funções utilitárias para manipulação de changelog - Gera changelog a partir de commits do Git - Salva changelog em formato JSON na pasta pública perf: adicionar índices de banco de dados para otimização de queries - Cria 14 índices compostos em tabelas principais (lancamentos, contas, etc) - Adiciona índice user_id + period em lancamentos, faturas e orçamentos - Adiciona índices para séries de parcelas e transferências
This commit is contained in:
76
lib/changelog/actions.ts
Normal file
76
lib/changelog/actions.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
"use server";
|
||||
|
||||
import { userUpdateLog } from "@/db/schema";
|
||||
import { successResult, type ActionResult } from "@/lib/actions/types";
|
||||
import { getUser } from "@/lib/auth/server";
|
||||
import { db } from "@/lib/db";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { handleActionError } from "../actions/helpers";
|
||||
|
||||
export async function markUpdateAsRead(
|
||||
updateId: string
|
||||
): Promise<ActionResult> {
|
||||
try {
|
||||
const user = await getUser();
|
||||
|
||||
// Check if already marked as read
|
||||
const existing = await db
|
||||
.select()
|
||||
.from(userUpdateLog)
|
||||
.where(
|
||||
and(
|
||||
eq(userUpdateLog.userId, user.id),
|
||||
eq(userUpdateLog.updateId, updateId)
|
||||
)
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (existing.length > 0) {
|
||||
return successResult("Já marcado como lido");
|
||||
}
|
||||
|
||||
await db.insert(userUpdateLog).values({
|
||||
userId: user.id,
|
||||
updateId,
|
||||
});
|
||||
|
||||
return successResult("Marcado como lido");
|
||||
} catch (error) {
|
||||
return handleActionError(error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function markAllUpdatesAsRead(
|
||||
updateIds: string[]
|
||||
): Promise<ActionResult> {
|
||||
try {
|
||||
const user = await getUser();
|
||||
|
||||
// Get existing read updates
|
||||
const existing = await db
|
||||
.select()
|
||||
.from(userUpdateLog)
|
||||
.where(eq(userUpdateLog.userId, user.id));
|
||||
|
||||
const existingIds = new Set(existing.map((log) => log.updateId));
|
||||
|
||||
// Filter out already read updates
|
||||
const newUpdateIds = updateIds.filter((id) => !existingIds.has(id));
|
||||
|
||||
if (newUpdateIds.length === 0) {
|
||||
return successResult("Todos já marcados como lidos");
|
||||
}
|
||||
|
||||
// Insert new read logs
|
||||
await db.insert(userUpdateLog).values(
|
||||
newUpdateIds.map((updateId) => ({
|
||||
userId: user.id,
|
||||
updateId,
|
||||
}))
|
||||
);
|
||||
|
||||
return successResult("Todas as atualizações marcadas como lidas");
|
||||
} catch (error) {
|
||||
return handleActionError(error);
|
||||
}
|
||||
}
|
||||
75
lib/changelog/data.ts
Normal file
75
lib/changelog/data.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { db } from "@/lib/db";
|
||||
import { userUpdateLog } from "@/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
export interface ChangelogEntry {
|
||||
id: string;
|
||||
type: string;
|
||||
title: string;
|
||||
date: string;
|
||||
icon: string;
|
||||
category: string;
|
||||
}
|
||||
|
||||
export interface Changelog {
|
||||
version: string;
|
||||
generatedAt: string;
|
||||
entries: ChangelogEntry[];
|
||||
}
|
||||
|
||||
export function getChangelog(): Changelog {
|
||||
try {
|
||||
const changelogPath = path.join(process.cwd(), "public", "changelog.json");
|
||||
|
||||
if (!fs.existsSync(changelogPath)) {
|
||||
return {
|
||||
version: "1.0.0",
|
||||
generatedAt: new Date().toISOString(),
|
||||
entries: [],
|
||||
};
|
||||
}
|
||||
|
||||
const content = fs.readFileSync(changelogPath, "utf-8");
|
||||
return JSON.parse(content);
|
||||
} catch (error) {
|
||||
console.error("Error reading changelog:", error);
|
||||
return {
|
||||
version: "1.0.0",
|
||||
generatedAt: new Date().toISOString(),
|
||||
entries: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function getUnreadUpdates(userId: string) {
|
||||
const changelog = getChangelog();
|
||||
|
||||
if (changelog.entries.length === 0) {
|
||||
return {
|
||||
unreadCount: 0,
|
||||
unreadEntries: [],
|
||||
allEntries: [],
|
||||
};
|
||||
}
|
||||
|
||||
// Get read updates from database
|
||||
const readLogs = await db
|
||||
.select()
|
||||
.from(userUpdateLog)
|
||||
.where(eq(userUpdateLog.userId, userId));
|
||||
|
||||
const readUpdateIds = new Set(readLogs.map((log) => log.updateId));
|
||||
|
||||
// Filter unread entries
|
||||
const unreadEntries = changelog.entries.filter(
|
||||
(entry) => !readUpdateIds.has(entry.id)
|
||||
);
|
||||
|
||||
return {
|
||||
unreadCount: unreadEntries.length,
|
||||
unreadEntries,
|
||||
allEntries: changelog.entries,
|
||||
};
|
||||
}
|
||||
29
lib/changelog/utils.ts
Normal file
29
lib/changelog/utils.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { ChangelogEntry } from "./data";
|
||||
|
||||
export function getCategoryLabel(category: string): string {
|
||||
const labels: Record<string, string> = {
|
||||
feature: "Novidades",
|
||||
bugfix: "Correções",
|
||||
performance: "Performance",
|
||||
documentation: "Documentação",
|
||||
style: "Interface",
|
||||
refactor: "Melhorias",
|
||||
test: "Testes",
|
||||
chore: "Manutenção",
|
||||
other: "Outros",
|
||||
};
|
||||
return labels[category] || "Outros";
|
||||
}
|
||||
|
||||
export function groupEntriesByCategory(entries: ChangelogEntry[]) {
|
||||
return entries.reduce(
|
||||
(acc, entry) => {
|
||||
if (!acc[entry.category]) {
|
||||
acc[entry.category] = [];
|
||||
}
|
||||
acc[entry.category].push(entry);
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, ChangelogEntry[]>
|
||||
);
|
||||
}
|
||||
2
lib/utils.ts
Normal file
2
lib/utils.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// Re-export from lib/utils/ui.ts for shadcn compatibility
|
||||
export { cn } from "./utils/ui";
|
||||
Reference in New Issue
Block a user