import { Trans, useLingui } from "@lingui/react/macro"; import type { UserFactCategory, UserFactSource, UserProfileState } from "@rakazo/contracts"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Button, } from "@rakazo/ui-web"; import { XIcon } from "lucide-react"; import type { ReactNode } from "react"; import { useEffect, useId, useState } from "react"; import { getActiveUiLocale } from "../lib/i18n"; import { rpc } from "../lib/rpc"; import type { ProfileField } from "../lib/user-profile-view"; import { CLEARED_PROFILE_FIELD, displayLanguageTag, displayRegionTag, filledProfileFields, groupUserFacts, } from "../lib/user-profile-view"; function Row({ value, detail, actions, testId, status, }: { value: string; detail: string; actions: (describedBy: string) => ReactNode; testId: string; status?: string; }) { const valueId = useId(); return (
  • {value}

    {detail}

    {actions(valueId)}
  • ); } /** Everything the user's bots know about the user, with consent and forget controls. */ export function UserProfileSettings() { const { t } = useLingui(); const [state, setState] = useState(null); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); const [forgetOpen, setForgetOpen] = useState(false); useEffect(() => { let cancelled = false; rpc.profile .get() .then((next) => { if (!cancelled) setState(next); }) .catch((err: unknown) => { if (!cancelled) setError(err instanceof Error ? err.message : t`Couldn't load`); }); return () => { cancelled = true; }; }, [t]); async function apply(change: () => Promise) { if (busy) return; setBusy(true); setError(null); try { setState(await change()); } catch (err) { setError(err instanceof Error ? err.message : t`Couldn't save`); } finally { setBusy(false); } } const categoryLabels: Record = { identity: t`Identity`, work: t`Work`, goals: t`Goals`, people: t`People`, health: t`Health`, values: t`Values`, habits: t`Habits`, preferences: t`Preferences`, tools: t`Tools`, }; const sourceLabels: Record = { onboarding: t`Onboarding`, user: t`You`, conversation: t`Chat`, consolidation: t`Chat history`, connector: t`Connected app`, }; const fieldLabels: Record = { timeZone: t`Time zone`, language: t`Language`, locale: t`Region`, communicationStyle: t`Communication style`, summary: t`Summary`, }; const fields = state ? filledProfileFields(state.profile) : []; const groups = state ? groupUserFacts(state.facts) : []; const uiLocale = getActiveUiLocale(); const deleteButton = (describedBy: string, onClick: () => void) => ( ); return (
    {error ? (

    {error}

    ) : null} {state && fields.length === 0 && groups.length === 0 ? (

    Nothing yet

    ) : null} {fields.length > 0 ? (
      {fields.map(({ field, value }) => ( deleteButton( describedBy, () => void apply(() => rpc.profile.update(CLEARED_PROFILE_FIELD[field])), ) } /> ))}
    ) : null} {groups.map((group) => (

    {categoryLabels[group.category]}

      {group.facts.map((fact) => ( ( <> {fact.status === "pending" ? ( ) : null} {deleteButton( describedBy, () => void apply(() => rpc.profile.forget({ factIds: [fact.id] })), )} )} /> ))}
    ))} {fields.length > 0 || groups.length > 0 ? ( ) : null} Forget everything about you? Cancel { setForgetOpen(false); void apply(() => rpc.profile.forget({ all: true })); }} > Forget
    ); }