feat: amplia opcoes de fontes e normaliza preferencias

This commit is contained in:
Felipe Coutinho
2026-03-06 13:59:12 +00:00
parent 09923ece0a
commit 0e4dbe6a3f
19 changed files with 74 additions and 130 deletions

View File

@@ -10,6 +10,7 @@ import { account, pagadores, tokensApi } from "@/db/schema";
import { auth } from "@/lib/auth/config"; import { auth } from "@/lib/auth/config";
import { db, schema } from "@/lib/db"; import { db, schema } from "@/lib/db";
import { PAGADOR_ROLE_ADMIN } from "@/lib/pagadores/constants"; import { PAGADOR_ROLE_ADMIN } from "@/lib/pagadores/constants";
import { DEFAULT_FONT_KEY, FONT_KEYS } from "@/public/fonts/font_index";
type ActionResponse<T = void> = { type ActionResponse<T = void> = {
success: boolean; success: boolean;
@@ -52,28 +53,12 @@ const deleteAccountSchema = z.object({
}), }),
}); });
const VALID_FONTS = [
"ai-sans",
"anthropic-sans",
"fira-code",
"fira-sans",
"geist",
"ibm-plex-mono",
"inter",
"jetbrains-mono",
"reddit-sans",
"roboto",
"sf-pro-display",
"sf-pro-rounded",
"ubuntu",
] as const;
const updatePreferencesSchema = z.object({ const updatePreferencesSchema = z.object({
disableMagnetlines: z.boolean(), disableMagnetlines: z.boolean(),
extratoNoteAsColumn: z.boolean(), extratoNoteAsColumn: z.boolean(),
lancamentosColumnOrder: z.array(z.string()).nullable(), lancamentosColumnOrder: z.array(z.string()).nullable(),
systemFont: z.enum(VALID_FONTS).default("ai-sans"), systemFont: z.enum(FONT_KEYS).default(DEFAULT_FONT_KEY),
moneyFont: z.enum(VALID_FONTS).default("ai-sans"), moneyFont: z.enum(FONT_KEYS).default(DEFAULT_FONT_KEY),
}); });
// Actions // Actions

View File

@@ -1,13 +1,14 @@
import { desc, eq } from "drizzle-orm"; import { desc, eq } from "drizzle-orm";
import { tokensApi } from "@/db/schema"; import { tokensApi } from "@/db/schema";
import { db, schema } from "@/lib/db"; import { db, schema } from "@/lib/db";
import { type FontKey, normalizeFontKey } from "@/public/fonts/font_index";
export interface UserPreferences { export interface UserPreferences {
disableMagnetlines: boolean; disableMagnetlines: boolean;
extratoNoteAsColumn: boolean; extratoNoteAsColumn: boolean;
lancamentosColumnOrder: string[] | null; lancamentosColumnOrder: string[] | null;
systemFont: string; systemFont: FontKey;
moneyFont: string; moneyFont: FontKey;
} }
export interface ApiToken { export interface ApiToken {
@@ -43,7 +44,13 @@ export async function fetchUserPreferences(
.where(eq(schema.preferenciasUsuario.userId, userId)) .where(eq(schema.preferenciasUsuario.userId, userId))
.limit(1); .limit(1);
return result[0] || null; if (!result[0]) return null;
return {
...result[0],
systemFont: normalizeFontKey(result[0].systemFont),
moneyFont: normalizeFontKey(result[0].moneyFont),
};
} }
export async function fetchApiTokens(userId: string): Promise<ApiToken[]> { export async function fetchApiTokens(userId: string): Promise<ApiToken[]> {

View File

@@ -12,6 +12,7 @@ import { UpdatePasswordForm } from "@/components/ajustes/update-password-form";
import { Card } from "@/components/ui/card"; import { Card } from "@/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { auth } from "@/lib/auth/config"; import { auth } from "@/lib/auth/config";
import { DEFAULT_FONT_KEY } from "@/public/fonts/font_index";
import { fetchAjustesPageData } from "./data"; import { fetchAjustesPageData } from "./data";
export default async function Page() { export default async function Page() {
@@ -75,8 +76,8 @@ export default async function Page() {
lancamentosColumnOrder={ lancamentosColumnOrder={
userPreferences?.lancamentosColumnOrder ?? null userPreferences?.lancamentosColumnOrder ?? null
} }
systemFont={userPreferences?.systemFont ?? "ai-sans"} systemFont={userPreferences?.systemFont ?? DEFAULT_FONT_KEY}
moneyFont={userPreferences?.moneyFont ?? "ai-sans"} moneyFont={userPreferences?.moneyFont ?? DEFAULT_FONT_KEY}
/> />
</div> </div>
</Card> </Card>

View File

@@ -36,7 +36,7 @@ import {
DEFAULT_LANCAMENTOS_COLUMN_ORDER, DEFAULT_LANCAMENTOS_COLUMN_ORDER,
LANCAMENTOS_COLUMN_LABELS, LANCAMENTOS_COLUMN_LABELS,
} from "@/lib/lancamentos/column-order"; } from "@/lib/lancamentos/column-order";
import { FONT_OPTIONS, getFontVariable } from "@/public/fonts/font_index"; import { FONT_OPTIONS } from "@/public/fonts/font_index";
interface PreferencesFormProps { interface PreferencesFormProps {
disableMagnetlines: boolean; disableMagnetlines: boolean;
@@ -189,14 +189,6 @@ export function PreferencesForm({
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
<p
className="text-sm text-muted-foreground pt-1"
style={{
fontFamily: getFontVariable(selectedSystemFont),
}}
>
Suas finanças em um lugar
</p>
</div> </div>
{/* Fonte de valores */} {/* Fonte de valores */}
@@ -223,14 +215,6 @@ export function PreferencesForm({
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
<p
className="text-sm text-muted-foreground pt-1 tabular-nums"
style={{
fontFamily: getFontVariable(selectedMoneyFont),
}}
>
R$ 1.234,56
</p>
</div> </div>
</section> </section>

View File

@@ -1,15 +1,20 @@
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
import { cache } from "react"; import { cache } from "react";
import { db, schema } from "@/lib/db"; import { db, schema } from "@/lib/db";
import {
DEFAULT_FONT_KEY,
type FontKey,
normalizeFontKey,
} from "@/public/fonts/font_index";
export type FontPreferences = { export type FontPreferences = {
systemFont: string; systemFont: FontKey;
moneyFont: string; moneyFont: FontKey;
}; };
const DEFAULT_FONT_PREFS: FontPreferences = { const DEFAULT_FONT_PREFS: FontPreferences = {
systemFont: "ai-sans", systemFont: DEFAULT_FONT_KEY,
moneyFont: "ai-sans", moneyFont: DEFAULT_FONT_KEY,
}; };
export const fetchUserFontPreferences = cache( export const fetchUserFontPreferences = cache(
@@ -26,8 +31,8 @@ export const fetchUserFontPreferences = cache(
if (!result[0]) return DEFAULT_FONT_PREFS; if (!result[0]) return DEFAULT_FONT_PREFS;
return { return {
systemFont: result[0].systemFont, systemFont: normalizeFontKey(result[0].systemFont),
moneyFont: result[0].moneyFont, moneyFont: normalizeFontKey(result[0].moneyFont),
}; };
}, },
); );

Binary file not shown.

Binary file not shown.

View File

@@ -14,12 +14,12 @@ import localFont from "next/font/local";
const ai_sans = localFont({ const ai_sans = localFont({
src: [ src: [
{ {
path: "./AISans-Regular.woff2", path: "./ai-sans-regular.woff2",
weight: "400", weight: "400",
style: "normal", style: "normal",
}, },
{ {
path: "./AISans-Semibold.woff2", path: "./ai-sans-semibold.woff2",
weight: "700", weight: "700",
style: "normal", style: "normal",
}, },
@@ -28,66 +28,29 @@ const ai_sans = localFont({
variable: "--font-ai-sans", variable: "--font-ai-sans",
}); });
const itau = localFont({
src: [
{
path: "./itau-text-regular.woff2",
weight: "400",
style: "normal",
},
{
path: "./itau-text-bold.woff2",
weight: "700",
style: "normal",
},
],
display: "swap",
variable: "--font-itau",
});
const anthropic_sans = localFont({ const anthropic_sans = localFont({
src: "./anthropicSans.woff2", src: "./anthropic-sans.woff2",
display: "swap", display: "swap",
variable: "--font-anthropic-sans", variable: "--font-anthropic-sans",
}); });
const sf_pro_display = localFont({
src: [
{
path: "./SF-Pro-Display-Regular.otf",
weight: "400",
style: "normal",
},
{
path: "./SF-Pro-Display-Medium.otf",
weight: "500",
style: "normal",
},
{
path: "./SF-Pro-Display-Semibold.otf",
weight: "600",
style: "normal",
},
{
path: "./SF-Pro-Display-Bold.otf",
weight: "700",
style: "normal",
},
],
display: "swap",
variable: "--font-sf-pro-display",
});
const sf_pro_rounded = localFont({
src: [
{
path: "./SF-Pro-Rounded-Regular.otf",
weight: "400",
style: "normal",
},
{
path: "./SF-Pro-Rounded-Medium.otf",
weight: "500",
style: "normal",
},
{
path: "./SF-Pro-Rounded-Semibold.otf",
weight: "600",
style: "normal",
},
{
path: "./SF-Pro-Rounded-Bold.otf",
weight: "700",
style: "normal",
},
],
display: "swap",
variable: "--font-sf-pro-rounded",
});
const inter = Inter({ const inter = Inter({
subsets: ["latin"], subsets: ["latin"],
display: "swap", display: "swap",
@@ -145,14 +108,10 @@ const ibm_plex_mono = IBM_Plex_Mono({
variable: "--font-ibm-plex-mono", variable: "--font-ibm-plex-mono",
}); });
export type FontOption = { export const DEFAULT_FONT_KEY = "ai-sans";
key: string;
label: string;
variable: string;
};
export const FONT_OPTIONS: FontOption[] = [ export const FONT_OPTIONS = [
{ key: "ai-sans", label: "AI Sans", variable: "var(--font-ai-sans)" }, { key: "ai-sans", label: "Open AI Sans", variable: "var(--font-ai-sans)" },
{ {
key: "anthropic-sans", key: "anthropic-sans",
label: "Anthropic Sans", label: "Anthropic Sans",
@@ -164,6 +123,11 @@ export const FONT_OPTIONS: FontOption[] = [
label: "Fira Sans", label: "Fira Sans",
variable: "var(--font-fira-sans)", variable: "var(--font-fira-sans)",
}, },
{
key: "itau",
label: "Itaú Sans",
variable: "var(--font-itau)",
},
{ key: "geist", label: "Geist Sans", variable: "var(--font-geist)" }, { key: "geist", label: "Geist Sans", variable: "var(--font-geist)" },
{ {
key: "ibm-plex-mono", key: "ibm-plex-mono",
@@ -182,29 +146,21 @@ export const FONT_OPTIONS: FontOption[] = [
variable: "var(--font-reddit-sans)", variable: "var(--font-reddit-sans)",
}, },
{ key: "roboto", label: "Roboto", variable: "var(--font-roboto)" }, { key: "roboto", label: "Roboto", variable: "var(--font-roboto)" },
{
key: "sf-pro-display",
label: "SF Pro Display",
variable: "var(--font-sf-pro-display)",
},
{
key: "sf-pro-rounded",
label: "SF Pro Rounded",
variable: "var(--font-sf-pro-rounded)",
},
{ key: "ubuntu", label: "Ubuntu", variable: "var(--font-ubuntu)" }, { key: "ubuntu", label: "Ubuntu", variable: "var(--font-ubuntu)" },
] as const;
export type FontKey = (typeof FONT_OPTIONS)[number]["key"];
export const FONT_KEYS = FONT_OPTIONS.map((option) => option.key) as [
FontKey,
...FontKey[],
]; ];
/** @deprecated Use FONT_OPTIONS */ const VALID_FONT_KEY_SET = new Set<string>(FONT_KEYS);
export const SYSTEM_FONT_OPTIONS = FONT_OPTIONS;
/** @deprecated Use FONT_OPTIONS */
export const MONEY_FONT_OPTIONS = FONT_OPTIONS;
const allFonts = [ const allFonts = [
ai_sans, ai_sans,
anthropic_sans, anthropic_sans,
sf_pro_display,
sf_pro_rounded,
inter, inter,
geist_sans, geist_sans,
roboto, roboto,
@@ -214,15 +170,21 @@ const allFonts = [
jetbrains_mono, jetbrains_mono,
fira_code, fira_code,
ibm_plex_mono, ibm_plex_mono,
itau,
]; ];
export const allFontVariables = allFonts.map((f) => f.variable).join(" "); export const allFontVariables = allFonts.map((f) => f.variable).join(" ");
// Backward compatibility function isValidFontKey(value: string): value is FontKey {
export const main_font = ai_sans; return VALID_FONT_KEY_SET.has(value);
export const money_font = ai_sans; }
export function normalizeFontKey(value: string | null | undefined): FontKey {
if (!value) return DEFAULT_FONT_KEY;
return isValidFontKey(value) ? value : DEFAULT_FONT_KEY;
}
export function getFontVariable(key: string): string { export function getFontVariable(key: string): string {
const option = FONT_OPTIONS.find((o) => o.key === key); const option = FONT_OPTIONS.find((o) => o.key === key);
return option?.variable ?? "var(--font-ai-sans)"; return option?.variable ?? `var(--font-${DEFAULT_FONT_KEY})`;
} }

Binary file not shown.

Binary file not shown.