Files
Momento/memento-note/app/(main)/settings/profile/profile-form.tsx
Antigravity 1446463f04 design: apply Architectural Minimalist style to all Settings pages
- settings/layout: serif h1 title + uppercase tracking subtitle, matching Agents page
- SettingsNav: uppercase tracking-wider tabs with foreground underline on active
- All settings pages (general, ai, appearance, profile, mcp, about, data):
  remove duplicate h1 (now in layout header), replace with uppercase section label
- notes.ts: decouple history guards from global userAISettings
- note-document-info-panel: add 'Save version' button with loading feedback
2026-05-09 07:39:35 +00:00

92 lines
4.7 KiB
TypeScript

'use client'
import { useState, useEffect } from 'react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { updateProfile, changePassword } from '@/app/actions/profile'
import { toast } from 'sonner'
import { useLanguage } from '@/lib/i18n'
import { User, Lock } from 'lucide-react'
export function ProfileForm({ user, userAISettings }: { user: any; userAISettings?: any }) {
const { t } = useLanguage()
return (
<div className="space-y-8">
<p className="text-[11px] font-bold uppercase tracking-[0.2em] text-muted-foreground">
{t('profile.description')}
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Profile info card */}
<div className="bg-card rounded-lg border border-border p-6 shadow-sm flex flex-col gap-4">
<div className="flex items-center gap-3 mb-2">
<div className="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary shrink-0">
<User className="h-5 w-5" />
</div>
<div>
<h3 className="font-semibold text-foreground">{t('profile.title')}</h3>
<p className="text-sm text-muted-foreground">{t('profile.description')}</p>
</div>
</div>
<form action={async (formData) => {
const result = await updateProfile({ name: formData.get('name') as string })
if (result?.error) toast.error(t('profile.updateFailed'))
else toast.success(t('profile.updateSuccess'))
}} className="space-y-4">
<div className="space-y-1.5">
<label htmlFor="name" className="text-sm font-medium text-foreground">{t('profile.displayName')}</label>
<Input id="name" name="name" defaultValue={user.name} className="bg-muted border-border focus:border-primary" />
</div>
<div className="space-y-1.5">
<label htmlFor="email" className="text-sm font-medium text-foreground">{t('profile.email')}</label>
<Input id="email" value={user.email} disabled className="bg-muted border-border opacity-60" />
</div>
<Button type="submit" className="w-full mt-2">{t('general.save')}</Button>
</form>
</div>
{/* Password card */}
<div className="bg-card rounded-lg border border-border p-6 shadow-sm flex flex-col gap-4">
<div className="flex items-center gap-3 mb-2">
<div className="w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center text-primary shrink-0">
<Lock className="h-5 w-5" />
</div>
<div>
<h3 className="font-semibold text-foreground">{t('profile.changePassword')}</h3>
<p className="text-sm text-muted-foreground">{t('profile.changePasswordDescription')}</p>
</div>
</div>
<form action={async (formData) => {
const result = await changePassword(formData)
if (result?.error) {
const msg = '_form' in result.error
? result.error._form[0]
: result.error.currentPassword?.[0] || result.error.newPassword?.[0] || result.error.confirmPassword?.[0] || t('profile.passwordChangeFailed')
toast.error(msg)
} else {
toast.success(t('profile.passwordChangeSuccess'))
const form = document.querySelector('form#password-form') as HTMLFormElement
form?.reset()
}
}} id="password-form" className="space-y-4">
<div className="space-y-1.5">
<label htmlFor="currentPassword" className="text-sm font-medium text-foreground">{t('profile.currentPassword')}</label>
<Input id="currentPassword" name="currentPassword" type="password" required className="bg-muted border-border focus:border-primary" />
</div>
<div className="space-y-1.5">
<label htmlFor="newPassword" className="text-sm font-medium text-foreground">{t('profile.newPassword')}</label>
<Input id="newPassword" name="newPassword" type="password" required minLength={6} className="bg-muted border-border focus:border-primary" />
</div>
<div className="space-y-1.5">
<label htmlFor="confirmPassword" className="text-sm font-medium text-foreground">{t('profile.confirmPassword')}</label>
<Input id="confirmPassword" name="confirmPassword" type="password" required minLength={6} className="bg-muted border-border focus:border-primary" />
</div>
<Button type="submit" className="w-full mt-2">{t('profile.updatePassword')}</Button>
</form>
</div>
</div>
</div>
)
}