Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QF-993 Search as you type #2251

Open
wants to merge 26 commits into
base: testing
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ac540f9
Search as you type POC
osamasayed Oct 15, 2024
648469c
Merge branch 'testing' into QF-993-search-as-you-type-POC
osamasayed Nov 25, 2024
bdfc793
Merge branch 'testing' into QF-993-search-as-you-type-POC
osamasayed Nov 25, 2024
8dc1805
Remove comments
osamasayed Dec 1, 2024
0233f06
QF 1272 search autocomplete (#2250)
osamasayed Dec 1, 2024
0cbafb3
Merge branch 'testing' into QF-993-search-as-you-type-POC
osamasayed Dec 20, 2024
6204f4e
Fix merge issue
osamasayed Dec 20, 2024
ba67d2f
Merge branch 'testing' into QF-993-search-as-you-type-POC
osamasayed Dec 20, 2024
45c77cd
Search UI Updates (#2268)
osamasayed Dec 23, 2024
555f002
Updates
osamasayed Dec 28, 2024
5ef3dc0
Updates
osamasayed Dec 30, 2024
0ce30ca
Updates
osamasayed Dec 30, 2024
52bcdd9
Move navigation to the bottom
osamasayed Dec 31, 2024
2e38972
Handle autofill state
osamasayed Dec 31, 2024
076d95f
Fix navigation
osamasayed Dec 31, 2024
af92c08
Fix wrong icons
osamasayed Jan 1, 2025
83ff402
Fix autofill color
osamasayed Jan 8, 2025
e0d945a
Open search drawer when on mobile
osamasayed Jan 9, 2025
c073a30
Limit quick search results to 10 (#2283)
osamasayed Jan 23, 2025
e865ca9
Call API Gateway for search (#2253)
osamasayed Jan 25, 2025
8645887
Merge branch 'testing' into QF-993-search-as-you-type-POC
osamasayed Jan 27, 2025
4440ae1
Close voice search when clicking outside (#2290)
osamasayed Jan 30, 2025
f0b1095
Redirect to full search when pressing enter
osamasayed Feb 8, 2025
0fac936
Merge branch 'testing' into QF-993-search-as-you-type-POC
osamasayed Feb 8, 2025
b8bc372
Add user selectedTranslations to search query
osamasayed Feb 13, 2025
80965c8
Add enterKeyHint
osamasayed Feb 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions src/components/CommandBar/CommandBarBody/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CommandsList, { Command } from '../CommandsList';

import styles from './CommandBarBody.module.scss';

import { getNewSearchResults } from '@/api';
import DataFetcher from '@/components/DataFetcher';
import TarteelAttribution from '@/components/TarteelAttribution/TarteelAttribution';
import VoiceSearchBodyContainer from '@/components/TarteelVoiceSearch/BodyContainer';
Expand All @@ -18,8 +19,9 @@ import useDebounce from '@/hooks/useDebounce';
import IconSearch from '@/icons/search.svg';
import { selectRecentNavigations } from '@/redux/slices/CommandBar/state';
import { selectIsCommandBarVoiceFlowStarted } from '@/redux/slices/voiceSearch';
import { SearchMode } from '@/types/Search/SearchRequestParams';
import SearchQuerySource from '@/types/SearchQuerySource';
import { makeSearchResultsUrl } from '@/utils/apiPaths';
import { makeNewSearchResultsUrl } from '@/utils/apiPaths';
import { areArraysEqual } from '@/utils/array';
import { logButtonClick, logTextSearchQuery } from '@/utils/eventLogger';
import { SearchResponse } from 'types/ApiResponses';
Expand All @@ -28,27 +30,27 @@ import { SearchNavigationType } from 'types/SearchNavigationResult';
const NAVIGATE_TO = [
{
name: 'Juz 1',
key: 1,
key: '1',
resultType: SearchNavigationType.JUZ,
},
{
name: 'Hizb 1',
key: 1,
key: '1',
resultType: SearchNavigationType.HIZB,
},
{
name: 'Rub el Hizb 1',
key: 1,
key: '1',
resultType: SearchNavigationType.RUB_EL_HIZB,
},
{
name: 'Page 1',
key: 1,
key: '1',
resultType: SearchNavigationType.PAGE,
},
{
name: 'Surah Yasin',
key: 36,
key: '36',
resultType: SearchNavigationType.SURAH,
},
{
Expand Down Expand Up @@ -112,6 +114,15 @@ const CommandBarBody: React.FC = () => {
[recentNavigations, t],
);

const quickSearchFetcher = useCallback(() => {
return getNewSearchResults({
mode: SearchMode.Quick,
query: searchQuery,
getText: 1,
highlight: 1,
});
}, [searchQuery]);

/**
* This function will be used by DataFetcher and will run only when there is no API error
* or the connections is offline. When we receive the response from DataFetcher,
Expand Down Expand Up @@ -198,8 +209,18 @@ const CommandBarBody: React.FC = () => {
<VoiceSearchBodyContainer isCommandBar />
) : (
<DataFetcher
queryKey={searchQuery ? makeSearchResultsUrl({ query: searchQuery }) : null}
queryKey={
searchQuery
? makeNewSearchResultsUrl({
mode: SearchMode.Quick,
query: searchQuery,
getText: 1,
highlight: 1,
})
: null
}
render={dataFetcherRender}
fetcher={quickSearchFetcher}
/>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,26 @@ $itemHeight: calc(1.5 * var(--spacing-mega));
display: flex;
align-items: center;
justify-content: space-between;
height: $itemHeight;
min-height: $itemHeight;
font-size: var(--font-size-normal);
padding-block-start: 0;
padding-block-end: 0;
padding-inline-start: var(--spacing-xsmall);
padding-inline-end: var(--spacing-xsmall);
cursor: pointer;
color: var(--color-text-faded);
white-space: nowrap;
// white-space: nowrap;
osamasayed marked this conversation as resolved.
Show resolved Hide resolved
position: relative;
z-index: var(--z-index-default);
&.selected {
color: var(--color-text-default);
background: var(--color-background-alternative-faint);
}
}

.highlight {
transition: transform var(--transition-fast);
height: $itemHeight;
min-height: $itemHeight;
width: 100%;
position: absolute;
border-radius: var(--border-radius-rounded);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
}

.name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
// white-space: nowrap;
// overflow: hidden;
// text-overflow: ellipsis;
osamasayed marked this conversation as resolved.
Show resolved Hide resolved
em {
font-weight: var(--font-weight-bold);
text-decoration: underline;
}
}
44 changes: 34 additions & 10 deletions src/components/CommandBar/CommandsList/CommandPrefix/index.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,55 @@
import React from 'react';
/* eslint-disable react/no-danger */
import React, { useContext } from 'react';

import useTranslation from 'next-translate/useTranslation';

import styles from './CommandPrefix.module.scss';

import DataContext from '@/contexts/DataContext';
import NavigateIcon from '@/icons/east.svg';
import { getSearchNavigationResult } from '@/utils/search';
import { SearchNavigationType } from 'types/SearchNavigationResult';

interface Props {
name: string;
type: SearchNavigationType;
isVoiceSearch: boolean;
navigationKey: string | number;
}

const CommandPrefix: React.FC<Props> = ({ name, type }) => {
const { t } = useTranslation('common');
const CommandPrefix: React.FC<Props> = ({ name, type, isVoiceSearch, navigationKey }) => {
const { t, lang } = useTranslation('common');
const chapterData = useContext(DataContext);
const getName = () => {
if (isVoiceSearch) return name;

if (type === SearchNavigationType.SEARCH_PAGE) {
return t('search-for', {
searchQuery: name,
});
}

const navigation = getSearchNavigationResult(
chapterData,
{ resultType: type, key: navigationKey, name },
t,
lang,
true,
);
return navigation?.name;
};

return (
<div className={styles.container}>
<span className={styles.commandPrefix}>
<NavigateIcon />
</span>
<p className={styles.name}>
{type === SearchNavigationType.SEARCH_PAGE
? t('search-for', {
searchQuery: name,
})
: name}
</p>
<p
dangerouslySetInnerHTML={{
__html: getName(),
}}
className={styles.name}
/>
</div>
);
};
Expand Down
20 changes: 13 additions & 7 deletions src/components/CommandBar/CommandsList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ import { SearchNavigationResult } from 'types/SearchNavigationResult';

export interface Command extends SearchNavigationResult {
group: string;
name: string;
index?: number;
isClearable?: boolean;
isVoiceSearch?: boolean;
}

interface Props {
Expand Down Expand Up @@ -133,7 +135,6 @@ const CommandsList: React.FC<Props> = ({ commandGroups: { groups, numberOfComman
return (
<ul role="listbox">
<div
className={styles.highlight}
style={{
transform: highlightOffset ? `translateY(${highlightOffset}px)` : `translateY(100%)`,
}}
Expand All @@ -147,24 +148,29 @@ const CommandsList: React.FC<Props> = ({ commandGroups: { groups, numberOfComman
</div>
<ul role="group" aria-labelledby={commandGroup}>
{groups[commandGroup].map((command) => {
const { name, resultType } = command;
const isSelected = selectedCommandIndex === command.index;
const { name, resultType, key, index, isVoiceSearch } = command;
const isSelected = selectedCommandIndex === index;
return (
<li
ref={isSelected ? selectedItemRef : null}
role="option"
aria-selected={isSelected}
key={command.index}
key={index}
className={classNames(styles.command, { [styles.selected]: isSelected })}
onClick={() => navigateToLink(command)}
onMouseOver={() => setSelectedCommandIndex(command.index)}
onMouseOver={() => setSelectedCommandIndex(index)}
>
<CommandPrefix name={name} type={resultType} />
<CommandPrefix
navigationKey={key}
isVoiceSearch={isVoiceSearch}
name={name}
type={resultType}
/>
<div className={styles.keyboardInputContainer}>
<CommandControl
isClearable={command.isClearable}
isSelected={isSelected}
commandKey={command.key}
commandKey={key}
onRemoveCommandClicked={onRemoveCommandClicked}
/>
</div>
Expand Down
40 changes: 25 additions & 15 deletions src/components/Navbar/SearchDrawer/SearchDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@ import { shallowEqual, useDispatch, useSelector } from 'react-redux';

import SearchDrawerHeader from './Header';

import { getNewSearchResults } from '@/api';
import Drawer, { DrawerType } from '@/components/Navbar/Drawer';
import Spinner from '@/dls/Spinner/Spinner';
import useDebounce from '@/hooks/useDebounce';
import useFocus from '@/hooks/useFocusElement';
import { selectNavbar } from '@/redux/slices/navbar';
import { selectSelectedTranslations } from '@/redux/slices/QuranReader/translations';
import { selectIsSearchDrawerVoiceFlowStarted } from '@/redux/slices/voiceSearch';
import { SearchMode } from '@/types/Search/SearchRequestParams';
import SearchService from '@/types/Search/SearchService';
import SearchQuerySource from '@/types/SearchQuerySource';
import { areArraysEqual } from '@/utils/array';
import { logButtonClick } from '@/utils/eventLogger';
import { addToSearchHistory, searchGetResults } from '@/utils/search';
import { logButtonClick, logTextSearchQuery } from '@/utils/eventLogger';
import { addToSearchHistory } from '@/utils/search';
import { SearchResponse } from 'types/ApiResponses';

const SearchBodyContainer = dynamic(() => import('@/components/Search/SearchBodyContainer'), {
Expand All @@ -33,8 +36,6 @@ const VoiceSearchBodyContainer = dynamic(
},
);

const FIRST_PAGE_NUMBER = 1;
const PAGE_SIZE = 10;
const DEBOUNCING_PERIOD_MS = 1000;

const SearchDrawer: React.FC = () => {
Expand All @@ -60,17 +61,26 @@ const SearchDrawer: React.FC = () => {
// only when the search query has a value we call the API.
if (debouncedSearchQuery) {
addToSearchHistory(dispatch, debouncedSearchQuery, SearchQuerySource.SearchDrawer);
searchGetResults(
SearchQuerySource.SearchDrawer,
debouncedSearchQuery,
FIRST_PAGE_NUMBER,
PAGE_SIZE,
setIsSearching,
setHasError,
setSearchResult,
null,
selectedTranslations?.length && selectedTranslations.join(','),
);
setIsSearching(true);
logTextSearchQuery(debouncedSearchQuery, SearchQuerySource.SearchDrawer);
getNewSearchResults({
mode: SearchMode.Quick,
query: debouncedSearchQuery,
getText: 1,
highlight: 1,
})
.then((response) => {
setSearchResult({
...response,
service: SearchService.KALIMAT,
});
})
.catch(() => {
setHasError(true);
})
.finally(() => {
setIsSearching(false);
});
}
}, [debouncedSearchQuery, selectedTranslations, dispatch]);

Expand Down
16 changes: 15 additions & 1 deletion src/components/Search/NavigationItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/* eslint-disable react/no-danger */
import React, { useContext } from 'react';

import useTranslation from 'next-translate/useTranslation';

import KalimatNavigationSearchResultItem from '../SearchResults/KalimatNavigationSearchResultItem';

import DataContext from '@/contexts/DataContext';
import Button from '@/dls/Button/Button';
import SearchService from '@/types/Search/SearchService';
Expand Down Expand Up @@ -33,7 +36,7 @@ const NavigationItem: React.FC<Props> = ({
);

const result = isKalimatService
? getSearchNavigationResult(chaptersData, navigation, t, lang)
? getSearchNavigationResult(chaptersData, navigation, t, lang, true)
: navigation;
const getKalimatResultSuffix = () => {
if (navigation.resultType === SearchNavigationType.SURAH) {
Expand All @@ -57,6 +60,17 @@ const NavigationItem: React.FC<Props> = ({
});
};

if (isKalimatService && result.resultType === SearchNavigationType.AYAH) {
return (
<KalimatNavigationSearchResultItem
key={result.key}
name={result.name}
resultKey={result.key}
source={isSearchDrawer ? SearchQuerySource.SearchDrawer : SearchQuerySource.SearchPage}
/>
);
}

return (
<Button onClick={onNavigationItemClicked} href={url} suffix={suffix}>
{result.name}
Expand Down
Loading