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 { db, schema } from "@/lib/db";
import { PAGADOR_ROLE_ADMIN } from "@/lib/pagadores/constants";
import { DEFAULT_FONT_KEY, FONT_KEYS } from "@/public/fonts/font_index";
type ActionResponse<T = void> = {
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({
disableMagnetlines: z.boolean(),
extratoNoteAsColumn: z.boolean(),
lancamentosColumnOrder: z.array(z.string()).nullable(),
systemFont: z.enum(VALID_FONTS).default("ai-sans"),
moneyFont: z.enum(VALID_FONTS).default("ai-sans"),
systemFont: z.enum(FONT_KEYS).default(DEFAULT_FONT_KEY),
moneyFont: z.enum(FONT_KEYS).default(DEFAULT_FONT_KEY),
});
// Actions

View File

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

View File

@@ -12,6 +12,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 { DEFAULT_FONT_KEY } from "@/public/fonts/font_index";
import { fetchAjustesPageData } from "./data";
export default async function Page() {
@@ -75,8 +76,8 @@ export default async function Page() {
lancamentosColumnOrder={
userPreferences?.lancamentosColumnOrder ?? null
}
systemFont={userPreferences?.systemFont ?? "ai-sans"}
moneyFont={userPreferences?.moneyFont ?? "ai-sans"}
systemFont={userPreferences?.systemFont ?? DEFAULT_FONT_KEY}
moneyFont={userPreferences?.moneyFont ?? DEFAULT_FONT_KEY}
/>
</div>
</Card>

View File

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

View File

@@ -1,15 +1,20 @@
import { eq } from "drizzle-orm";
import { cache } from "react";
import { db, schema } from "@/lib/db";
import {
DEFAULT_FONT_KEY,
type FontKey,
normalizeFontKey,
} from "@/public/fonts/font_index";
export type FontPreferences = {
systemFont: string;
moneyFont: string;
systemFont: FontKey;
moneyFont: FontKey;
};
const DEFAULT_FONT_PREFS: FontPreferences = {
systemFont: "ai-sans",
moneyFont: "ai-sans",
systemFont: DEFAULT_FONT_KEY,
moneyFont: DEFAULT_FONT_KEY,
};
export const fetchUserFontPreferences = cache(
@@ -26,8 +31,8 @@ export const fetchUserFontPreferences = cache(
if (!result[0]) return DEFAULT_FONT_PREFS;
return {
systemFont: result[0].systemFont,
moneyFont: result[0].moneyFont,
systemFont: normalizeFontKey(result[0].systemFont),
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({
src: [
{
path: "./AISans-Regular.woff2",
path: "./ai-sans-regular.woff2",
weight: "400",
style: "normal",
},
{
path: "./AISans-Semibold.woff2",
path: "./ai-sans-semibold.woff2",
weight: "700",
style: "normal",
},
@@ -28,66 +28,29 @@ const ai_sans = localFont({
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({
src: "./anthropicSans.woff2",
src: "./anthropic-sans.woff2",
display: "swap",
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({
subsets: ["latin"],
display: "swap",
@@ -145,14 +108,10 @@ const ibm_plex_mono = IBM_Plex_Mono({
variable: "--font-ibm-plex-mono",
});
export type FontOption = {
key: string;
label: string;
variable: string;
};
export const DEFAULT_FONT_KEY = "ai-sans";
export const FONT_OPTIONS: FontOption[] = [
{ key: "ai-sans", label: "AI Sans", variable: "var(--font-ai-sans)" },
export const FONT_OPTIONS = [
{ key: "ai-sans", label: "Open AI Sans", variable: "var(--font-ai-sans)" },
{
key: "anthropic-sans",
label: "Anthropic Sans",
@@ -164,6 +123,11 @@ export const FONT_OPTIONS: FontOption[] = [
label: "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: "ibm-plex-mono",
@@ -182,29 +146,21 @@ export const FONT_OPTIONS: FontOption[] = [
variable: "var(--font-reddit-sans)",
},
{ 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)" },
] 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 */
export const SYSTEM_FONT_OPTIONS = FONT_OPTIONS;
/** @deprecated Use FONT_OPTIONS */
export const MONEY_FONT_OPTIONS = FONT_OPTIONS;
const VALID_FONT_KEY_SET = new Set<string>(FONT_KEYS);
const allFonts = [
ai_sans,
anthropic_sans,
sf_pro_display,
sf_pro_rounded,
inter,
geist_sans,
roboto,
@@ -214,15 +170,21 @@ const allFonts = [
jetbrains_mono,
fira_code,
ibm_plex_mono,
itau,
];
export const allFontVariables = allFonts.map((f) => f.variable).join(" ");
// Backward compatibility
export const main_font = ai_sans;
export const money_font = ai_sans;
function isValidFontKey(value: string): value is FontKey {
return VALID_FONT_KEY_SET.has(value);
}
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 {
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.