mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 11:01:45 +00:00
chore(configurações): redesign visual da página de configurações
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { RiArrowRightSLine } from "@remixicon/react";
|
import { RiAndroidLine, RiArrowRightSLine } from "@remixicon/react";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ import { UpdateNameForm } from "@/features/settings/components/update-name-form"
|
|||||||
import { UpdatePasswordForm } from "@/features/settings/components/update-password-form";
|
import { UpdatePasswordForm } from "@/features/settings/components/update-password-form";
|
||||||
import { fetchSettingsPageData } from "@/features/settings/queries";
|
import { fetchSettingsPageData } from "@/features/settings/queries";
|
||||||
import { Card } from "@/shared/components/ui/card";
|
import { Card } from "@/shared/components/ui/card";
|
||||||
|
import { Separator } from "@/shared/components/ui/separator";
|
||||||
import {
|
import {
|
||||||
Tabs,
|
Tabs,
|
||||||
TabsContent,
|
TabsContent,
|
||||||
@@ -64,12 +65,13 @@ export default async function Page() {
|
|||||||
<Card className="p-6">
|
<Card className="p-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-bold mb-1">Preferências</h2>
|
<h2 className="text-xl font-bold mb-1">Preferências</h2>
|
||||||
<p className="text-sm text-muted-foreground mb-4">
|
<p className="text-sm text-muted-foreground">
|
||||||
Personalize sua experiência no OpenMonetis ajustando as
|
Personalize sua experiência no OpenMonetis ajustando as
|
||||||
configurações de acordo com suas necessidades.
|
configurações de acordo com suas necessidades.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<Separator />
|
||||||
<PreferencesForm
|
<PreferencesForm
|
||||||
statementNoteAsColumn={
|
statementNoteAsColumn={
|
||||||
userPreferences?.statementNoteAsColumn ?? false
|
userPreferences?.statementNoteAsColumn ?? false
|
||||||
@@ -77,25 +79,46 @@ export default async function Page() {
|
|||||||
transactionsColumnOrder={
|
transactionsColumnOrder={
|
||||||
userPreferences?.transactionsColumnOrder ?? null
|
userPreferences?.transactionsColumnOrder ?? null
|
||||||
}
|
}
|
||||||
|
attachmentMaxSizeMb={userPreferences?.attachmentMaxSizeMb ?? 50}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="companion" className="mt-4">
|
<TabsContent value="companion" className="mt-4">
|
||||||
<CompanionTab tokens={userApiTokens} />
|
<Card className="p-6">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center gap-2 mb-1">
|
||||||
|
<h2 className="text-xl font-bold">OpenMonetis Companion</h2>
|
||||||
|
<span className="inline-flex items-center gap-1 rounded-full bg-success/10 px-2 py-0.5 text-xs font-medium text-success dark:bg-success/10">
|
||||||
|
<RiAndroidLine className="h-3 w-3" />
|
||||||
|
Android
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Capture notificações de transações dos seus apps de banco
|
||||||
|
(Nubank, Itaú, Bradesco, Inter, C6 e outros) e envie para sua
|
||||||
|
caixa de entrada.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Separator />
|
||||||
|
<CompanionTab tokens={userApiTokens} />
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value="nome" className="mt-4">
|
<TabsContent value="nome" className="mt-4">
|
||||||
<Card className="p-6">
|
<Card className="p-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-bold mb-1">Alterar nome</h2>
|
<h2 className="text-xl font-bold mb-1">Alterar nome</h2>
|
||||||
<p className="text-sm text-muted-foreground mb-4">
|
<p className="text-sm text-muted-foreground">
|
||||||
Atualize como seu nome aparece no OpenMonetis. Esse nome pode
|
Atualize como seu nome aparece no OpenMonetis. Esse nome pode
|
||||||
ser exibido em diferentes seções do app e em comunicações.
|
ser exibido em diferentes seções do app e em comunicações.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<Separator />
|
||||||
<UpdateNameForm currentName={userName} />
|
<UpdateNameForm currentName={userName} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -105,12 +128,13 @@ export default async function Page() {
|
|||||||
<Card className="p-6">
|
<Card className="p-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-bold mb-1">Alterar senha</h2>
|
<h2 className="text-xl font-bold mb-1">Alterar senha</h2>
|
||||||
<p className="text-sm text-muted-foreground mb-4">
|
<p className="text-sm text-muted-foreground">
|
||||||
Defina uma nova senha para sua conta. Guarde-a em local
|
Defina uma nova senha para sua conta. Guarde-a em local
|
||||||
seguro.
|
seguro.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<Separator />
|
||||||
<UpdatePasswordForm authProvider={authProvider} />
|
<UpdatePasswordForm authProvider={authProvider} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -120,12 +144,13 @@ export default async function Page() {
|
|||||||
<Card className="p-6">
|
<Card className="p-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-bold mb-1">Passkeys</h2>
|
<h2 className="text-xl font-bold mb-1">Passkeys</h2>
|
||||||
<p className="text-sm text-muted-foreground mb-4">
|
<p className="text-sm text-muted-foreground">
|
||||||
Passkeys permitem login sem senha, usando biometria (Face ID,
|
Passkeys permitem login sem senha, usando biometria (Face ID,
|
||||||
Touch ID, Windows Hello) ou chaves de segurança.
|
Touch ID, Windows Hello) ou chaves de segurança.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<Separator />
|
||||||
<PasskeysForm />
|
<PasskeysForm />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -135,13 +160,14 @@ export default async function Page() {
|
|||||||
<Card className="p-6">
|
<Card className="p-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-bold mb-1">Alterar e-mail</h2>
|
<h2 className="text-xl font-bold mb-1">Alterar e-mail</h2>
|
||||||
<p className="text-sm text-muted-foreground mb-4">
|
<p className="text-sm text-muted-foreground">
|
||||||
Atualize o e-mail associado à sua conta. Você precisará
|
Atualize o e-mail associado à sua conta. Você precisará
|
||||||
confirmar os links enviados para o novo e também para o e-mail
|
confirmar os links enviados para o novo e também para o e-mail
|
||||||
atual (quando aplicável) para concluir a alteração.
|
atual (quando aplicável) para concluir a alteração.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<Separator />
|
||||||
<UpdateEmailForm
|
<UpdateEmailForm
|
||||||
currentEmail={userEmail}
|
currentEmail={userEmail}
|
||||||
authProvider={authProvider}
|
authProvider={authProvider}
|
||||||
@@ -154,14 +180,15 @@ export default async function Page() {
|
|||||||
<Card className="p-6">
|
<Card className="p-6">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-bold mb-1 text-destructive">
|
<h2 className="text-xl font-bold mb-1 text-destructive">
|
||||||
Ações perigosas
|
Ações perigosas
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-sm text-muted-foreground mb-4">
|
<p className="text-sm text-muted-foreground">
|
||||||
Você pode zerar os dados do OpenMonetis e manter seu acesso,
|
Você pode zerar os dados do OpenMonetis e manter seu acesso,
|
||||||
ou excluir sua conta inteira de forma irreversível.
|
ou excluir sua conta inteira de forma irreversível.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<Separator />
|
||||||
<DeleteAccountForm />
|
<DeleteAccountForm />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RiAndroidLine,
|
|
||||||
RiDownload2Line,
|
RiDownload2Line,
|
||||||
RiExternalLinkLine,
|
RiExternalLinkLine,
|
||||||
RiNotification3Line,
|
RiNotification3Line,
|
||||||
@@ -9,7 +8,6 @@ import {
|
|||||||
RiShieldCheckLine,
|
RiShieldCheckLine,
|
||||||
} from "@remixicon/react";
|
} from "@remixicon/react";
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import { Card } from "@/shared/components/ui/card";
|
|
||||||
import { ApiTokensForm } from "./api-tokens-form";
|
import { ApiTokensForm } from "./api-tokens-form";
|
||||||
|
|
||||||
interface ApiToken {
|
interface ApiToken {
|
||||||
@@ -69,49 +67,28 @@ const steps: {
|
|||||||
|
|
||||||
export function CompanionTab({ tokens }: CompanionTabProps) {
|
export function CompanionTab({ tokens }: CompanionTabProps) {
|
||||||
return (
|
return (
|
||||||
<Card className="p-6">
|
<div className="space-y-6">
|
||||||
<div className="space-y-6">
|
{/* Steps */}
|
||||||
{/* Header */}
|
<div className="grid grid-cols-2 gap-x-4 gap-y-3 sm:grid-cols-4">
|
||||||
<div>
|
{steps.map((step, index) => (
|
||||||
<div className="flex items-center gap-2 mb-1">
|
<div key={step.title} className="flex items-start gap-2">
|
||||||
<h2 className="text-lg font-bold">OpenMonetis Companion</h2>
|
<div className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground">
|
||||||
<span className="inline-flex items-center gap-1 rounded-full bg-success/10 px-2 py-0.5 text-xs font-medium text-success dark:bg-success/10">
|
<step.icon className="h-4 w-4" />
|
||||||
<RiAndroidLine className="h-3 w-3" />
|
|
||||||
Android
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
Capture notificações de transações dos seus apps de banco (Nubank,
|
|
||||||
Itaú, Bradesco, Inter, C6 e outros) e envie para sua caixa de
|
|
||||||
entrada.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Steps */}
|
|
||||||
<div className="grid grid-cols-2 gap-x-4 gap-y-3 sm:grid-cols-4">
|
|
||||||
{steps.map((step, index) => (
|
|
||||||
<div key={step.title} className="flex items-start gap-2">
|
|
||||||
<div className="flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground">
|
|
||||||
<step.icon className="h-4 w-4" />
|
|
||||||
</div>
|
|
||||||
<div className="min-w-0">
|
|
||||||
<p className="text-sm font-medium leading-tight">
|
|
||||||
{index + 1}. {step.title}
|
|
||||||
</p>
|
|
||||||
<p className="text-xs text-muted-foreground">
|
|
||||||
{step.description}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
<div className="min-w-0">
|
||||||
</div>
|
<p className="text-sm font-medium leading-tight">
|
||||||
|
{index + 1}. {step.title}
|
||||||
{/* Divider */}
|
</p>
|
||||||
<div className="border-t" />
|
<p className="text-xs text-muted-foreground">
|
||||||
|
{step.description}
|
||||||
{/* Devices */}
|
</p>
|
||||||
<ApiTokensForm tokens={tokens} />
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
|
||||||
|
{/* Devices */}
|
||||||
|
<ApiTokensForm tokens={tokens} />
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,9 @@ export function PasskeysForm() {
|
|||||||
const { data, error: fetchError } =
|
const { data, error: fetchError } =
|
||||||
await authClient.passkey.listUserPasskeys();
|
await authClient.passkey.listUserPasskeys();
|
||||||
if (fetchError) {
|
if (fetchError) {
|
||||||
setError((fetchError.message as string) || "Erro ao carregar passkeys.");
|
setError(
|
||||||
|
(fetchError.message as string) || "Erro ao carregar passkeys.",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setPasskeys(
|
setPasskeys(
|
||||||
@@ -134,7 +136,9 @@ export function PasskeysForm() {
|
|||||||
name: editName.trim(),
|
name: editName.trim(),
|
||||||
});
|
});
|
||||||
if (renameError) {
|
if (renameError) {
|
||||||
setError((renameError.message as string) || "Erro ao renomear passkey.");
|
setError(
|
||||||
|
(renameError.message as string) || "Erro ao renomear passkey.",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setEditingId(null);
|
setEditingId(null);
|
||||||
|
|||||||
Reference in New Issue
Block a user