From 2f01eb9cb084feee9ac1ca005d0ffb33a573033d Mon Sep 17 00:00:00 2001 From: Oier Bravo Urtasun Date: Tue, 19 May 2026 03:19:56 +0200 Subject: [PATCH] feat(fase-19): wire EmojiPicker into 4 integration sites + EP-E specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the four legacy hardcoded emoji arrays (settings avatar, onboarding-create, CreateCollectiveModal, manage-collective rename) with ``. The shared component delivers ~280 codepoints across 4 tabs instead of the previous 8–24 per surface, with consistent layout and behaviour. Backwards-incompatible testid change on the manage page: the old `collective-emoji-option-{e}` per-cell testid is gone — every cell now lives under the picker's `emoji-picker-cell-{e}` namespace. Two existing specs (onboarding O-02 + rename MC-01a) are updated to drive the new tab → cell flow. New e2e file `tests/e2e/emoji-picker.test.ts` covers EP-E-01..02: - EP-E-01 — Ana on /settings picks 🍎 from "Comida"; DB row updates. - EP-E-02 — Eva on /onboarding creates a collective with 🐱 from "Animales"; sidebar reflects the choice. Co-Authored-By: Claude Opus 4.7 --- .../components/CreateCollectiveModal.svelte | 23 +--- .../(app)/collective/manage/+page.svelte | 27 ++-- .../src/routes/(app)/settings/+page.svelte | 21 +--- apps/web/src/routes/onboarding/+page.svelte | 26 ++-- apps/web/tests/e2e/emoji-picker.test.ts | 116 ++++++++++++++++++ apps/web/tests/e2e/onboarding.test.ts | 4 +- apps/web/tests/e2e/rename-collective.test.ts | 6 +- 7 files changed, 150 insertions(+), 73 deletions(-) create mode 100644 apps/web/tests/e2e/emoji-picker.test.ts diff --git a/apps/web/src/lib/components/CreateCollectiveModal.svelte b/apps/web/src/lib/components/CreateCollectiveModal.svelte index e40c6a8..ad04277 100644 --- a/apps/web/src/lib/components/CreateCollectiveModal.svelte +++ b/apps/web/src/lib/components/CreateCollectiveModal.svelte @@ -3,15 +3,14 @@ import { getSupabase } from '$lib/supabase'; import { currentCollective, userCollectives } from '$lib/stores/collective'; import Spinner from './Spinner.svelte'; + import EmojiPicker from './EmojiPicker.svelte'; import * as m from '$lib/paraglide/messages'; let { onClose }: { onClose: () => void } = $props(); - const EMOJI_OPTIONS = [ - '🏠', '🏡', '🏢', '🏣', '🏤', '🏥', '🏦', '🏨', - '🏩', '🏪', '🏫', '🏬', '🏭', '🏯', '🏰', '🗼', - '🌆', '🌇', '🌃', '🌉', '🏙️', '⛺', '🌴', '🌵' - ]; + // Fase 19 — emoji catalog moved into the shared `EmojiPicker`. The 24 + // hardcoded city/house glyphs the old `EMOJI_OPTIONS` array shipped are + // covered by the new "objects" tab. let name = $state(''); let emoji = $state('🏠'); @@ -73,19 +72,7 @@

{m.onboarding_collective_emoji()}

-
- {#each EMOJI_OPTIONS as e} - - {/each} -
+ (emoji = e)} /> {#if error} diff --git a/apps/web/src/routes/(app)/collective/manage/+page.svelte b/apps/web/src/routes/(app)/collective/manage/+page.svelte index 719808c..b7cc8ba 100644 --- a/apps/web/src/routes/(app)/collective/manage/+page.svelte +++ b/apps/web/src/routes/(app)/collective/manage/+page.svelte @@ -5,6 +5,7 @@ import { currentUser } from '$lib/stores/auth'; import { currentCollective, collectiveMembers, userCollectives } from '$lib/stores/collective'; import Avatar from '$lib/components/Avatar.svelte'; + import EmojiPicker from '$lib/components/EmojiPicker.svelte'; import Spinner from '$lib/components/Spinner.svelte'; import type { FeatureFlags, SectionKey, ItemFrequency } from '@colectivo/types'; import { SECTION_KEYS } from '@colectivo/types'; @@ -174,11 +175,9 @@ let nameSaved = $state(false); let emojiPickerOpen = $state(false); - const EMOJI_OPTIONS = [ - '🏠', '🏡', '🏢', '🏣', '🏤', '🏥', '🏦', '🏨', - '🏩', '🏪', '🏫', '🏬', '🏭', '🏯', '🏰', '🗼', - '🌆', '🌇', '🌃', '🌉', '🏙️', '⛺', '🌴', '🌵' - ]; + // Fase 19 — emoji catalog moved into the shared `EmojiPicker` component. + // `selectEmoji` (admin-write path) is still local because it includes + // the closed-state toggle + the persistence round-trip. // Keep nameDraft in sync with $currentCollective. $effect(() => { @@ -635,19 +634,11 @@ {#if emojiPickerOpen} -
- {#each EMOJI_OPTIONS as e} - - {/each} +
+ void selectEmoji(e)} + />
{/if} diff --git a/apps/web/src/routes/(app)/settings/+page.svelte b/apps/web/src/routes/(app)/settings/+page.svelte index cc48546..2189c4b 100644 --- a/apps/web/src/routes/(app)/settings/+page.svelte +++ b/apps/web/src/routes/(app)/settings/+page.svelte @@ -7,6 +7,7 @@ import { logout } from '$lib/auth'; import Avatar from '$lib/components/Avatar.svelte'; import ImageCropper from '$lib/components/ImageCropper.svelte'; + import EmojiPicker from '$lib/components/EmojiPicker.svelte'; import ThemeToggle from '$lib/components/ThemeToggle.svelte'; import SyncConflictsPanel from '$lib/components/SyncConflictsPanel.svelte'; import TagChip from '$lib/components/TagChip.svelte'; @@ -51,12 +52,9 @@ let cropperFile = $state(null); let uploading = $state(false); - const EMOJI_GRID = [ - '😀','😎','🥳','🤓','👻','🐱','🐶','🦊', - '🐸','🦁','🐻','🐼','🐨','🐯','🦄','🐧', - '🦋','🌈','⭐','🌙','☀️','🌊','🌴','🌺', - '🍕','🍦','🎸','🎯','🚀','⚽','🎮','🎨' - ]; + // Fase 19 — emoji avatars expansion. The legacy `EMOJI_GRID` hardcoded + // array (8 faces + 24 others) is replaced by the tabbed `EmojiPicker` + // component which surfaces ~280 codepoints across 4 categories. const keycloakAccountUrl = `${PUBLIC_KEYCLOAK_URL}/realms/${PUBLIC_KEYCLOAK_REALM}/account`; @@ -413,16 +411,7 @@
{#if avatarType === 'emoji'} -
- {#each EMOJI_GRID as e} - - {/each} -
+ {:else if avatarType === 'upload'}