'use client' import * as React from 'react' import { z } from 'zod' import { useT } from '@open-mercato/shared/lib/i18n/context' import { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm' import { Button } from '@open-mercato/ui/primitives/button' import MfaComplianceBadge from './MfaComplianceBadge' export type SecurityUserMethod = { type: string label?: string lastUsed?: string } export type SecurityUserFormValue = { userId: string email: string enrolled: boolean recoveryCodesRemaining: number compliant: boolean methods: SecurityUserMethod[] resetReason: string } type SecurityUserFormProps = { value: SecurityUserFormValue submitting: boolean onSubmit: (value: SecurityUserFormValue) => Promise | void onCancel: () => void } function formatMethodLastUsed(value: string | undefined, fallback: string): string { if (!value) return fallback const parsed = new Date(value) if (Number.isNaN(parsed.getTime())) return fallback return parsed.toLocaleString() } function UserSummarySection({ value }: { value: SecurityUserFormValue }) { const t = useT() return (

{t('security.admin.users.table.email', 'Email')}

{value.email}

{t('security.admin.users.detail.recoveryCodes', 'Recovery codes remaining')}

{String(value.recoveryCodesRemaining)}

{t('security.admin.users.table.compliance', 'Compliance')}

) } function MethodsSection({ methods }: { methods: SecurityUserMethod[] }) { const t = useT() if (!methods.length) { return (

{t('security.admin.users.detail.noMethods', 'No active methods.')}

) } return (
{methods.map((method, index) => (

{t('security.admin.users.detail.methodType', 'Type')}

{method.type}

{t('security.admin.users.detail.methodLabel', 'Label')}

{method.label ?? '-'}

{t('security.admin.users.detail.methodLastUsed', 'Last used')}

{formatMethodLastUsed( method.lastUsed, t('security.admin.users.lastLogin.unknown', 'Unknown'), )}

))}
) } export default function SecurityUserForm({ value, submitting, onSubmit, onCancel, }: SecurityUserFormProps) { const t = useT() const formId = 'security-user-form' const schema = React.useMemo( () => z.object({ resetReason: z .string() .trim() .min(1, t('security.admin.users.errors.reasonRequired', 'Reset reason is required.')), }), [t], ) type SecurityUserCrudValues = z.infer const fields = React.useMemo(() => [ { id: 'resetReason', label: t('security.admin.users.reset.reason', 'Reset reason'), type: 'textarea', required: true, disabled: submitting, description: t('security.admin.users.reset.reasonPlaceholder', 'Enter reason for audit trail'), }, ], [submitting, t]) const groups = React.useMemo(() => [ { id: 'summary', column: 1, component: () => , }, { id: 'methods', column: 1, component: () => , }, { id: 'reset', column: 1, fields: ['resetReason'], }, ], [value]) const handleSubmit = React.useCallback(async (values: SecurityUserCrudValues) => { await onSubmit({ ...value, resetReason: values.resetReason.trim(), }) }, [onSubmit, value]) return ( title={t('security.admin.users.detail.title', 'User MFA detail')} titleHeadingLevel={1} backHref="/backend/security/users" schema={schema} formId={formId} fields={fields} groups={groups} initialValues={{ resetReason: '' }} embedded={false} submitLabel={t('security.admin.users.actions.resetMfa', 'Reset MFA')} onSubmit={handleSubmit} extraActions={( )} /> ) }