diff --git a/resources/js/admin/mobile/EventsPage.tsx b/resources/js/admin/mobile/EventsPage.tsx index c6563b4..805f05e 100644 --- a/resources/js/admin/mobile/EventsPage.tsx +++ b/resources/js/admin/mobile/EventsPage.tsx @@ -204,10 +204,12 @@ function EventsList({ if (!query.trim()) return filteredByStatus; const needle = query.toLowerCase(); return filteredByStatus.filter((event) => { - const hay = `${event.name ?? ''} ${event.location ?? ''}`.toLowerCase(); + const name = resolveEventSearchName(event.name, t); + const location = resolveLocation(event, t); + const hay = `${name} ${location}`.toLowerCase(); return hay.includes(needle); }); - }, [filteredByStatus, query]); + }, [filteredByStatus, query, t]); const filters: Array<{ key: EventStatusKey; label: string; count: number }> = [ { key: 'all', label: t('events.list.filters.all'), count: statusCounts.all }, @@ -474,6 +476,17 @@ function renderName(name: TenantEvent['name'], t: (key: string) => string): stri return t('events.placeholders.untitled'); } +function resolveEventSearchName(name: TenantEvent['name'], t: (key: string) => string): string { + if (typeof name === 'string') return name; + if (name && typeof name === 'object') { + const values = Object.values(name).filter((value) => typeof value === 'string'); + if (values.length > 0) { + return values.join(' '); + } + } + return t('events.placeholders.untitled'); +} + function resolveLocation(event: TenantEvent, t: (key: string) => string): string { const settings = (event.settings ?? {}) as Record; const candidate = diff --git a/resources/js/admin/mobile/__tests__/EventsPage.test.tsx b/resources/js/admin/mobile/__tests__/EventsPage.test.tsx index 4bba8d3..5379d35 100644 --- a/resources/js/admin/mobile/__tests__/EventsPage.test.tsx +++ b/resources/js/admin/mobile/__tests__/EventsPage.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { describe, expect, it, vi } from 'vitest'; -import { render, screen } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; const navigateMock = vi.fn(); const authState = { @@ -54,6 +54,13 @@ vi.mock('../../api', () => ({ event_date: '2026-02-19', settings: {}, }, + { + id: 2, + name: { en: 'Summer Gala' }, + slug: 'summer-gala', + event_date: '2026-06-01', + settings: {}, + }, ]), })); @@ -96,7 +103,7 @@ vi.mock('../components/Primitives', () => ({ })); vi.mock('../components/FormControls', () => ({ - MobileInput: (props: React.InputHTMLAttributes) => , + MobileInput: ({ compact: _compact, ...props }: React.InputHTMLAttributes) => , })); vi.mock('@tamagui/card', () => ({ @@ -171,4 +178,18 @@ describe('MobileEventsPage', () => { authState.user = { role: 'tenant_admin' }; }); + + it('filters events by search query', async () => { + render(); + + expect(await screen.findByText('Demo Event')).toBeInTheDocument(); + expect(screen.getByText('Summer Gala')).toBeInTheDocument(); + + await act(async () => { + fireEvent.change(screen.getByPlaceholderText('Select event'), { target: { value: 'Summer' } }); + }); + + expect(screen.getByText('Summer Gala')).toBeInTheDocument(); + expect(screen.queryByText('Demo Event')).not.toBeInTheDocument(); + }); });