@@ -271,6 +271,7 @@ import {
271271} from " @/components/ui/alert-dialog" ;
272272import type { Company } from " @/dto/companies" ;
273273import type { Speaker } from " @/dto/speakers" ;
274+ import createFuzzySearch from " @nozbe/microfuzz" ;
274275
275276type SelectedItem = Company | Speaker ;
276277
@@ -315,10 +316,15 @@ const highlightedIndex = ref(-1);
315316
316317// Detect platform for keyboard shortcut
317318const isMac = computed (() => {
318- return (
319- typeof navigator !== " undefined" &&
320- navigator .platform .toUpperCase ().indexOf (" MAC" ) >= 0
321- );
319+ if (typeof navigator === " undefined" ) return false ;
320+
321+ const uaData = navigator .userAgentData ;
322+ if (uaData && typeof uaData .platform === " string" ) {
323+ return uaData .platform === " macOS" ;
324+ }
325+
326+ const ua = navigator .userAgent || " " ;
327+ return / \b Macintosh\b | \b Mac OS X\b / .test (ua );
322328});
323329
324330// Companies query
@@ -339,41 +345,51 @@ const isLoading = computed(
339345 () => companiesLoading .value || speakersLoading .value ,
340346);
341347
348+ const companyFuzzy = computed (() => {
349+ const list = companiesData .value ?.data ?? [];
350+ if (! list .length ) return null ;
351+
352+ return createFuzzySearch (list , {
353+ // match on multiple fields
354+ getText : (company : Company ) => [company .name , company .description ?? " " ],
355+ });
356+ });
357+
358+ const speakerFuzzy = computed (() => {
359+ const list = speakersData .value ?.data ?? [];
360+ if (! list .length ) return null ;
361+
362+ return createFuzzySearch (list , {
363+ getText : (speaker : Speaker ) => [speaker .name , speaker .companyName ?? " " ],
364+ });
365+ });
366+
342367const filteredCompanies = computed (() => {
343- if (! companiesData .value ?.data ) return [];
368+ const list = companiesData .value ?.data ?? [];
369+ const term = searchTerm .value .trim ();
344370
345- const term = searchTerm .value .toLowerCase ();
371+ // Show recent companies when no search term
372+ if (! term ) return list .slice (0 , 5 );
346373
347- if (! term ) {
348- // Show recent companies when no search term
349- return companiesData .value .data .slice (0 , 5 );
350- }
374+ const fuzzy = companyFuzzy .value ;
375+ if (! fuzzy ) return [];
351376
352- return companiesData .value .data
353- .filter (
354- (company : Company ) =>
355- company .name .toLowerCase ().includes (term ) ||
356- company .description ?.toLowerCase ().includes (term ),
357- )
377+ return fuzzy (term )
378+ .map ((res ) => res .item )
358379 .slice (0 , 5 ); // Limit to 5 results
359380});
360381
361382const filteredSpeakers = computed (() => {
362- if (! speakersData .value ?.data ) return [];
383+ const list = speakersData .value ?.data ?? [];
384+ const term = searchTerm .value .trim ();
363385
364- const term = searchTerm . value . toLowerCase ( );
386+ if ( ! term ) return list . slice ( 0 , 5 );
365387
366- if (! term ) {
367- // Show recent speakers when no search term
368- return speakersData .value .data .slice (0 , 5 );
369- }
388+ const fuzzy = speakerFuzzy .value ;
389+ if (! fuzzy ) return [];
370390
371- return speakersData .value .data
372- .filter (
373- (speaker : Speaker ) =>
374- speaker .name .toLowerCase ().includes (term ) ||
375- speaker .companyName ?.toLowerCase ().includes (term ),
376- )
391+ return fuzzy (term )
392+ .map ((res ) => res .item )
377393 .slice (0 , 5 ); // Limit to 5 results
378394});
379395
0 commit comments