Skip to content

Commit

Permalink
searchTypeSelector, searchParams
Browse files Browse the repository at this point in the history
Added and styled search type selector, added the logic of setting search params
  • Loading branch information
AliceBondMe committed Feb 4, 2024
1 parent 901b2bf commit 852443e
Show file tree
Hide file tree
Showing 13 changed files with 260 additions and 40 deletions.
14 changes: 14 additions & 0 deletions src/components/MainTitle/MainTitle.styled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import styled from 'styled-components';

export const PageTitle = styled.h2`
font-weight: 600;
font-size: 28px;
@media screen and (min-width: 768px) {
font-size: 32px;
}
@media screen and (min-width: 1440px) {
font-size: 44px;
}
`;
3 changes: 2 additions & 1 deletion src/components/MainTitle/MainTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { FC } from 'react';
import { IMainTitleProps } from './mainTitleTypes';
import { PageTitle } from './MainTitle.styled';

const MainTitle: FC<IMainTitleProps> = ({ title }) => {
return <h2>{title}</h2>;
return <PageTitle>{title}</PageTitle>;
};

export default MainTitle;
10 changes: 9 additions & 1 deletion src/components/Search/SearchBar/SearchBar.styled.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
export {};
import styled from 'styled-components';

export const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
gap: 24px;
margin-top: 50px;
`;
5 changes: 3 additions & 2 deletions src/components/Search/SearchBar/SearchBar.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { FC } from 'react';
import SearchForm from 'components/SearchForm';
import SearchTypeSelector from '../SearchTypeSelector';
import { Container } from './SearchBar.styled';

const SearchBar: FC = () => {
return (
<div>
<Container>
<SearchForm />
<SearchTypeSelector />
</div>
</Container>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,119 @@
export {};
import styled from 'styled-components';
import { FaAngleDown } from 'react-icons/fa6';

interface SelectProps {
$theme: string;
}

export const SelectWrap = styled.div`
display: flex;
align-items: center;
gap: 15px;
@media screen and (min-width: 768px) {
gap: 32px;
}
@media screen and (min-width: 1440px) {
gap: 18px;
}
`;

export const SelectName = styled.p`
font-weight: 500;
font-size: 12px;
line-height: 133%;
@media screen and (min-width: 768px) {
font-size: 14px;
}
@media screen and (min-width: 1440px) {
font-size: 18px;
}
`;

export const Select = styled.div<SelectProps>`
display: flex;
justify-content: space-between;
align-items: center;
width: 146px;
height: 34px;
border: ${({ $theme }) =>
$theme === 'light' ? 'none' : '1px solid var(--heroInput)'};
background-color: ${({ $theme }) =>
$theme === 'light' ? '#d9d9d928' : 'transparent'};
color: ${({ $theme }) => ($theme === 'light' ? '#23262a80' : '#fafafa7f')};
border-radius: 6px;
padding: 8px 14px;
font-size: 12px;
@media screen and (min-width: 768px) {
width: 175px;
height: 41px;
font-size: 14px;
padding: 10px 14px;
}
@media screen and (min-width: 1440px) {
width: 198px;
height: 49px;
padding: 14px;
}
`;

export const SelectContainer = styled.div`
position: relative;
`;

export const Options = styled.ul`
position: absolute;
top: 100%;
left: 0;
width: 100%;
background-color: var(--selectBg);
border-radius: 6px;
font-size: 12px;
padding: 8px 14px;
@media screen and (min-width: 768px) {
font-size: 14px;
padding: 10px 14px;
}
@media screen and (min-width: 1440px) {
padding: 14px;
}
`;

export const Option = styled.li`
display: flex;
align-items: center;
height: 23px;
opacity: 0.5;
transition: all 200ms ease-in-out;
&:hover {
opacity: 1;
}
@media screen and (min-width: 768px) {
height: 27px;
}
@media screen and (min-width: 1440px) {
height: 25px;
}
`;

export const ArrowDown = styled(FaAngleDown)`
color: var(--accentGreen);
width: 14px;
@media screen and (min-width: 768px) {
width: 20px;
}
@media screen and (min-width: 1440px) {
}
`;
59 changes: 57 additions & 2 deletions src/components/Search/SearchTypeSelector/SearchTypeSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,62 @@
import { FC } from 'react';
import { FC, useState } from 'react';
import {
ArrowDown,
Option,
Options,
Select,
SelectContainer,
SelectName,
SelectWrap,
} from './SearchTypeSelector.styled';
import { useDispatch, useSelector } from 'react-redux';
import { updateSearchTypeAction } from '../../../redux/search/slice';
import { selectSearchType } from '../../../redux/search/selectors';
import useTheme from 'hooks/useTheme';

const SearchTypeSelector: FC = () => {
return <div></div>;
const dispatch = useDispatch();
const searchType = useSelector(selectSearchType);
const { theme } = useTheme();

const [isOpen, setIsOpen] = useState(false);

const onSearchTypeChange = (event: React.MouseEvent<HTMLLIElement>) => {
const value = event.currentTarget.dataset.value;

dispatch(updateSearchTypeAction(value));
closeDropdown();
};

const openDropdown = () => {
setIsOpen(true);
};

const closeDropdown = () => {
setIsOpen(false);
};

return (
<SelectWrap>
<SelectName>Search by:</SelectName>
<SelectContainer>
<Select onClick={openDropdown} $theme={theme}>
{searchType === 'query' ? 'Title' : 'Ingredients'}
<ArrowDown />
</Select>

{isOpen && (
<Options>
<Option data-value="query" onClick={onSearchTypeChange}>
Title
</Option>
<Option data-value="ingredient" onClick={onSearchTypeChange}>
Ingredients
</Option>
</Options>
)}
</SelectContainer>
</SelectWrap>
);
};

export default SearchTypeSelector;
9 changes: 5 additions & 4 deletions src/components/SearchForm/SearchForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { Formik } from 'formik';
import useTheme from 'hooks/useTheme';
import { SearchButton, SearchInput, StyledForm } from './SearchForm.styled';
import { useDispatch, useSelector } from 'react-redux';
import { selectSearchQuery } from '../../redux/searchQuery/selectors';
import { updateSearchQueryAction } from '../../redux/searchQuery/slice';
import { selectSearchQuery } from '../../redux/search/selectors';
import { updateSearchQueryAction } from '../../redux/search/slice';

const SearchForm: FC = () => {
const { theme } = useTheme();
Expand All @@ -15,14 +15,15 @@ const SearchForm: FC = () => {
const dispatch = useDispatch();

const handleSearch = () => {
if (pathname === '/main' && query.trim().length) {
if (pathname === '/main' && query.length) {
navigate('/search');
}

console.log(query);
};

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
dispatch(updateSearchQueryAction(event.target.value));
dispatch(updateSearchQueryAction(event.target.value.trim()));
};

return (
Expand Down
17 changes: 16 additions & 1 deletion src/pages/SearchPage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import MainTitle from 'components/MainTitle/MainTitle';
import SearchBar from 'components/Search/SearchBar';
import { FC } from 'react';
import { FC, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { useSearchParams } from 'react-router-dom';
import { selectSearchQuery, selectSearchType } from '../redux/search/selectors';

const SearchPage: FC = () => {
const query = useSelector(selectSearchQuery);
const type = useSelector(selectSearchType);
const [searchParams, setSearchParams] = useSearchParams();

useEffect(() => {
if (!query.length) {
setSearchParams({});
} else {
setSearchParams({ [type]: query, page: '1' });
}
}, [query, type, setSearchParams]);

return (
<>
<MainTitle title={'Search'} />
Expand Down
5 changes: 5 additions & 0 deletions src/redux/search/selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { RootState } from 'redux/store';

export const selectSearchQuery = (state: RootState) => state.search.searchQuery;

export const selectSearchType = (state: RootState) => state.search.searchType;
28 changes: 28 additions & 0 deletions src/redux/search/slice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { createSlice } from '@reduxjs/toolkit';

export interface SearchState {
searchQuery: string;
searchType: 'query' | 'ingredient';
}

const searchInitialState: SearchState = {
searchQuery: '',
searchType: 'query',
};

const searchSlice = createSlice({
name: 'search',
initialState: searchInitialState,
reducers: {
updateSearchQueryAction(state, action) {
state.searchQuery = action.payload;
},
updateSearchTypeAction(state, action) {
state.searchType = action.payload;
},
},
});

export const { updateSearchQueryAction, updateSearchTypeAction } =
searchSlice.actions;
export const searchReducer = searchSlice.reducer;
4 changes: 0 additions & 4 deletions src/redux/searchQuery/selectors.ts

This file was deleted.

22 changes: 0 additions & 22 deletions src/redux/searchQuery/slice.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/redux/store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import { authReducer } from './auth/slice';
import { searchQueryReducer } from './searchQuery/slice';
import { searchReducer } from './search/slice';

const authPersistConfig = {
key: 'auth',
Expand All @@ -22,7 +22,7 @@ const authPersistConfig = {
const persistedReducer = persistReducer(authPersistConfig, authReducer);
const rootReducer = combineReducers({
auth: persistedReducer,
searchQuery: searchQueryReducer,
search: searchReducer,
});

export const store = configureStore({
Expand Down

0 comments on commit 852443e

Please sign in to comment.