diff --git a/CHANGELOG.md b/CHANGELOG.md index 98f423b..4b772ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR - Calculadora arrastável via drag handle no header do dialog - Callback `onSelectValue` na calculadora para inserir valor diretamente no campo de lançamento +- Aba "Changelog" em Ajustes com histórico de versões parseado do CHANGELOG.md ### Alterado diff --git a/app/(dashboard)/ajustes/page.tsx b/app/(dashboard)/ajustes/page.tsx index 890f0b8..21f2d0f 100644 --- a/app/(dashboard)/ajustes/page.tsx +++ b/app/(dashboard)/ajustes/page.tsx @@ -1,6 +1,7 @@ import { headers } from "next/headers"; import { redirect } from "next/navigation"; +import { ChangelogTab } from "@/components/ajustes/changelog-tab"; import { CompanionTab } from "@/components/ajustes/companion-tab"; import { DeleteAccountForm } from "@/components/ajustes/delete-account-form"; import { PreferencesForm } from "@/components/ajustes/preferences-form"; @@ -10,6 +11,7 @@ import { UpdatePasswordForm } from "@/components/ajustes/update-password-form"; import { Card } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { auth } from "@/lib/auth/config"; +import { parseChangelog } from "@/lib/changelog/parse-changelog"; import { fetchAjustesPageData } from "./data"; @@ -28,6 +30,8 @@ export default async function Page() { const { authProvider, userPreferences, userApiTokens } = await fetchAjustesPageData(session.user.id); + const changelogVersions = parseChangelog(); + return (
@@ -37,6 +41,7 @@ export default async function Page() { Alterar nome Alterar senha Alterar e-mail + Changelog Deletar conta @@ -114,6 +119,10 @@ export default async function Page() { + + + +
diff --git a/components/ajustes/changelog-tab.tsx b/components/ajustes/changelog-tab.tsx new file mode 100644 index 0000000..8208c87 --- /dev/null +++ b/components/ajustes/changelog-tab.tsx @@ -0,0 +1,54 @@ +import { Badge } from "@/components/ui/badge"; +import { Card } from "@/components/ui/card"; +import type { ChangelogVersion } from "@/lib/changelog/parse-changelog"; + +const sectionBadgeVariant: Record< + string, + "success" | "info" | "destructive" | "secondary" +> = { + Adicionado: "success", + Alterado: "info", + Corrigido: "destructive", + Removido: "secondary", +}; + +function getSectionVariant(type: string) { + return sectionBadgeVariant[type] ?? "secondary"; +} + +export function ChangelogTab({ versions }: { versions: ChangelogVersion[] }) { + return ( +
+ {versions.map((version) => ( + +
+

v{version.version}

+ + {version.date} + +
+
+ {version.sections.map((section) => ( +
+ + {section.type} + +
    + {section.items.map((item) => ( +
  • + + {item} +
  • + ))} +
+
+ ))} +
+
+ ))} +
+ ); +} diff --git a/lib/changelog/parse-changelog.ts b/lib/changelog/parse-changelog.ts new file mode 100644 index 0000000..9e9a317 --- /dev/null +++ b/lib/changelog/parse-changelog.ts @@ -0,0 +1,60 @@ +import fs from "node:fs"; +import path from "node:path"; + +export type ChangelogSection = { + type: string; + items: string[]; +}; + +export type ChangelogVersion = { + version: string; + date: string; + sections: ChangelogSection[]; +}; + +export function parseChangelog(): ChangelogVersion[] { + const filePath = path.join(process.cwd(), "CHANGELOG.md"); + const content = fs.readFileSync(filePath, "utf-8"); + const lines = content.split("\n"); + + const versions: ChangelogVersion[] = []; + let currentVersion: ChangelogVersion | null = null; + let currentSection: ChangelogSection | null = null; + + for (const line of lines) { + const versionMatch = line.match(/^## \[(.+?)\] - (.+)$/); + if (versionMatch) { + if (currentSection && currentVersion) { + currentVersion.sections.push(currentSection); + } + currentVersion = { + version: versionMatch[1], + date: versionMatch[2], + sections: [], + }; + versions.push(currentVersion); + currentSection = null; + continue; + } + + const sectionMatch = line.match(/^### (.+)$/); + if (sectionMatch && currentVersion) { + if (currentSection) { + currentVersion.sections.push(currentSection); + } + currentSection = { type: sectionMatch[1], items: [] }; + continue; + } + + const itemMatch = line.match(/^- (.+)$/); + if (itemMatch && currentSection) { + currentSection.items.push(itemMatch[1]); + } + } + + if (currentSection && currentVersion) { + currentVersion.sections.push(currentSection); + } + + return versions; +}