import { Trans, useLingui } from "@lingui/react/macro"; import type { EvooPose } from "@rakazo/ui-web"; import { BotAvatar, Button } from "@rakazo/ui-web"; import { type ReactNode, useCallback, useEffect, useMemo, useState } from "react"; import { findLookCategory, LOOK_CATEGORIES, type LookCategoryId, type LookPreset, lookPresetToAvatarValue, } from "../../lib/onboarding-look-categories"; import { OoAtelierDialog } from "../OoAtelier"; import { LookPreviewCarousel } from "./LookPreviewCarousel"; export interface OnboardingEmojiConfig { pose: string; avatarValue: string; } type OnboardingOoDesignerProps = { config: OnboardingEmojiConfig; onChange: (config: OnboardingEmojiConfig) => void; onContinue: () => void; }; function categoryLabel(id: LookCategoryId): ReactNode { switch (id) { case "work": return Work; case "hobby": return Hobby; case "scene": return Scene; case "coder": return Coder; case "calm": return Calm helper; default: { const never: never = id; return never; } } } function configFromPreset(preset: LookPreset): OnboardingEmojiConfig { return { pose: preset.pose, avatarValue: lookPresetToAvatarValue(preset) }; } export function OnboardingOoDesigner({ config, onChange, onContinue }: OnboardingOoDesignerProps) { const { t } = useLingui(); const [categoryId, setCategoryId] = useState("calm"); const category = useMemo(() => findLookCategory(categoryId), [categoryId]); const [lookIndex, setLookIndex] = useState(0); const syncCategorySelection = useCallback( (nextCategoryId: LookCategoryId, index = 0) => { const nextCategory = findLookCategory(nextCategoryId); const preset = nextCategory.looks[index] ?? nextCategory.looks[0]; if (!preset) return; setCategoryId(nextCategoryId); setLookIndex(index); onChange(configFromPreset(preset)); }, [onChange], ); const [atelierOpen, setAtelierOpen] = useState(false); useEffect(() => { const match = LOOK_CATEGORIES.find((entry) => entry.looks.some((look) => look.avatar === config.avatarValue), ); if (match) { const index = match.looks.findIndex((look) => look.avatar === config.avatarValue); setCategoryId(match.id); setLookIndex(index >= 0 ? index : 0); } }, []); const handleLookIndexChange = useCallback( (index: number) => { const preset = category.looks[index]; if (!preset) return; setLookIndex(index); onChange(configFromPreset(preset)); }, [category.looks, onChange], ); function resetLook() { syncCategorySelection("calm", 0); } return ( Design your Oo Pick a vibe, swipe through looks, and watch your Oo come alive. } /> What feels like you? {LOOK_CATEGORIES.map((entry) => { const selected = entry.id === categoryId; return ( syncCategorySelection(entry.id, 0)} className={`shrink-0 rounded-full border px-4 py-2 text-sm font-medium transition-all duration-300 ${ selected ? "border-primary bg-primary text-primary-foreground shadow-sm scale-[1.02]" : "border-border bg-card text-muted-foreground hover:border-muted hover:bg-muted active:scale-95" }`} style={{ transitionTimingFunction: "cubic-bezier(0.34, 1.56, 0.64, 1)" }} > {categoryLabel(entry.id)} ); })} Reset setAtelierOpen(true)} data-testid="onboarding-oo-customize" > Customize Continue onChange({ ...config, avatarValue })} /> ); }
Pick a vibe, swipe through looks, and watch your Oo come alive.
What feels like you?