feat(ST-507): add email input to settings and surface in user menu

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-04-26 19:37:51 +02:00
parent 5ed3645ecb
commit 0dc907b75c
5 changed files with 29 additions and 10 deletions

View file

@ -8,6 +8,7 @@ import { Textarea } from '@/components/ui/textarea'
import { updateProfileAction } from '@/actions/profile'
interface ProfileEditorProps {
email: string | null
bio: string | null
bioDetail: string | null
hasAvatar: boolean
@ -17,7 +18,7 @@ interface ProfileEditorProps {
const ALLOWED = ['image/jpeg', 'image/png', 'image/webp']
const MAX_BYTES = 12 * 1024 * 1024
export function ProfileEditor({ bio, bioDetail, hasAvatar, avatarVersion }: ProfileEditorProps) {
export function ProfileEditor({ email, bio, bioDetail, hasAvatar, avatarVersion }: ProfileEditorProps) {
const [state, formAction, isPending] = useActionState(updateProfileAction, null)
const [avatarSrc, setAvatarSrc] = useState<string | null>(
hasAvatar ? `/api/profile/avatar?v=${avatarVersion}` : null
@ -107,6 +108,23 @@ export function ProfileEditor({ bio, bioDetail, hasAvatar, avatarVersion }: Prof
</div>
<form action={formAction} className="space-y-4">
<div className="space-y-1.5">
<label htmlFor="email" className="text-xs font-medium text-foreground">
E-mailadres
</label>
<Input
id="email"
name="email"
type="email"
defaultValue={email ?? ''}
placeholder="jij@voorbeeld.nl"
maxLength={254}
disabled={isPending}
autoComplete="email"
/>
<p className="text-xs text-muted-foreground">Optioneel wordt getoond in je accountmenu</p>
</div>
<div className="space-y-1.5">
<label htmlFor="bio" className="text-xs font-medium text-foreground">
Korte omschrijving

View file

@ -14,10 +14,10 @@ interface NavBarProps {
roles: string[]
userId: string
username: string
bio: string | null
email: string | null
}
export function NavBar({ isDemo, roles, userId, username, bio }: NavBarProps) {
export function NavBar({ isDemo, roles, userId, username, email }: NavBarProps) {
const pathname = usePathname()
const currentProduct = useProductStore(s => s.currentProduct)
@ -97,7 +97,7 @@ export function NavBar({ isDemo, roles, userId, username, bio }: NavBarProps) {
{/* Rechts: account-menu */}
<div className="flex items-center gap-2 flex-1 justify-end">
<UserMenu userId={userId} username={username} bio={bio} roles={roles} />
<UserMenu userId={userId} username={username} email={email} roles={roles} />
</div>
</header>
)

View file

@ -23,14 +23,14 @@ const ROLE_LABELS: Record<string, string> = {
interface UserMenuProps {
userId: string
username: string
bio: string | null
email: string | null
roles: string[]
}
export function UserMenu({ userId, username, bio, roles }: UserMenuProps) {
export function UserMenu({ userId, username, email, roles }: UserMenuProps) {
const initials = username.slice(0, 2).toUpperCase()
const roleLabels = roles.map((r) => ROLE_LABELS[r]).filter(Boolean)
const subtitle = bio?.trim() ? bio.trim() : 'Lokaal account'
const subtitle = email?.trim() ? email.trim() : 'Lokaal account'
return (
<DropdownMenu>