simplified code, removed wrapper component, and tweaked clear date reset button

This commit is contained in:
Kim, Jimin 2021-09-29 12:51:03 +09:00
parent bb944472b4
commit 1d6f470a5e

View file

@ -27,6 +27,13 @@ interface TagsData {
label: string label: string
} }
interface Query {
from: string
to: string
tags: string[]
query: string
}
const StyledSearch = styled.div` const StyledSearch = styled.div`
text-align: center; text-align: center;
` `
@ -90,6 +97,17 @@ const StyledReactTagsContainer = styled.div`
width: 100%; width: 100%;
` `
const ClearDateButton = styled.button`
width: 100%;
line-height: 2.5rem;
border: none;
cursor: pointer;
background-color: tomato; /* 🍅 mmm tomato 🍅 */
color: white;
font-weight: bold;
`
const options: TagsData[] = [ const options: TagsData[] = [
...map.meta.tags.map((elem) => ({ value: elem, label: elem })), ...map.meta.tags.map((elem) => ({ value: elem, label: elem })),
] ]
@ -130,12 +148,7 @@ function isSelectedTagsInPost(
} }
// Search doesn't work on url change if component is not wrapped // Search doesn't work on url change if component is not wrapped
// todo: find ways to get rid of wrapper component and use class component export default () => {
export default function Search() {
return <_Search />
}
function _Search() {
const inputRef = useRef<HTMLInputElement>(null) const inputRef = useRef<HTMLInputElement>(null)
const _history = useHistory() const _history = useHistory()
@ -144,7 +157,7 @@ function _Search() {
// todo: handle duplicate/missing keys // todo: handle duplicate/missing keys
const _query = queryString.parse(_location.search) const _query = queryString.parse(_location.search)
const query = { const query: Query = {
from: _query.from ? _query.from?.toString() : "", from: _query.from ? _query.from?.toString() : "",
to: _query.to ? _query.to?.toString() : "", to: _query.to ? _query.to?.toString() : "",
tags: _query.tags ? _query.tags.toString().split(",") : [], tags: _query.tags ? _query.tags.toString().split(",") : [],
@ -153,7 +166,7 @@ function _Search() {
const defaultDateRange = [ const defaultDateRange = [
{ {
startDate: new Date(0), startDate: undefined,
endDate: undefined, endDate: undefined,
key: "selection", key: "selection",
}, },
@ -228,6 +241,58 @@ function _Search() {
return () => clearTimeout(delayDebounceFn) return () => clearTimeout(delayDebounceFn)
}, [searchInput]) }, [searchInput])
function clearDate() {
_history.push({
pathname: "/search",
search: queryString.stringify({
...(query.query && {
query: query.query,
}),
...(query.tags.length > 0 && {
tags: query.tags.join(","),
}),
}),
})
setDateRange(defaultDateRange)
}
function onDateRangeChange(item: OnDateRangeChangeProps) {
const historyToPush = {
...(query.query && {
query: query.query,
}),
...(query.from && {
from: query.from,
}),
...(query.to && {
to: query.to,
}),
...(query.tags.length > 0 && {
tags: query.tags.join(","),
}),
}
console.log(item)
// convert Date to YYYY-MM-DD string if it exists
if (item.selection.startDate != null)
historyToPush.from = item.selection.startDate
.toISOString()
.split("T")[0]
if (item.selection.endDate != null)
historyToPush.to = item.selection.endDate
.toISOString()
.split("T")[0]
_history.push({
pathname: "/search",
search: queryString.stringify(historyToPush),
})
setDateRange([item.selection])
}
return ( return (
<> <>
<Helmet> <Helmet>
@ -238,51 +303,21 @@ function _Search() {
<h1>Search</h1> <h1>Search</h1>
<StyledSearchContainer> <StyledSearchContainer>
<StyledDateRange <div>
editableDateInputs={true} <ClearDateButton onClick={clearDate}>
moveRangeOnFirstSelection={false} Reset range
retainEndDateOnFirstSelection={true} </ClearDateButton>
ranges={dateRange} <StyledDateRange
onChange={(item: OnDateRangeChangeProps) => { editableDateInputs
const historyToPush = { retainEndDateOnFirstSelection
...(query.query && { moveRangeOnFirstSelection={false}
query: query.query, ranges={dateRange}
}), onChange={onDateRangeChange}
...(query.from && { />
from: query.from, </div>
}),
...(query.to && {
to: query.to,
}),
...(query.tags.length > 0 && {
tags: query.tags.join(","),
}),
}
// convert Date to YYYY-MM-DD string if it exists
if (item.selection.startDate != null)
historyToPush.from = item.selection.startDate
.toISOString()
.split("T")[0]
if (item.selection.endDate != null)
historyToPush.to = item.selection.endDate
.toISOString()
.split("T")[0]
_history.push({
pathname: "/search",
search: queryString.stringify(historyToPush),
})
setDateRange([item.selection])
}}
/>
<StyledSearchControlContainer <StyledSearchControlContainer
onSubmit={(event) => { onSubmit={(event) => event.preventDefault()}
event.preventDefault()
}}
> >
<StyledSearchBar <StyledSearchBar
autoFocus autoFocus
@ -291,9 +326,9 @@ function _Search() {
value={searchInput} value={searchInput}
autoComplete="off" autoComplete="off"
placeholder="Search" placeholder="Search"
onChange={(event) => { onChange={(event) =>
setSearchInput(event.target.value) setSearchInput(event.target.value)
}} }
onKeyPress={(event) => { onKeyPress={(event) => {
event.key === "Enter" && event.key === "Enter" &&
searchInput && searchInput &&
@ -302,186 +337,12 @@ function _Search() {
/> />
{postCards.length}{" "} {postCards.length}{" "}
{postCards.length > 1 ? "results" : "result"} {postCards.length > 1 ? "results" : "result"}
<h3>Filters</h3> <h3>Tags</h3>
<StyledReactTagsContainer> <TagSelect
<ThemeConsumer> query={query}
{(currentTheme) => ( selectedTags={selectedTags}
<Select setSelectedOption={setSelectedOption}
theme={(theme) => ({ />
...theme,
colors: {
...theme.colors,
neutral0: theming
.theme(
currentTheme.currentTheme,
{
light: theming.light
.backgroundColor1,
dark: theming.dark
.backgroundColor1,
}
)
.toString(),
neutral5: "hsl(0, 0%, 20%)",
neutral10: "hsl(0, 0%, 30%)",
neutral20: "hsl(0, 0%, 40%)",
neutral30: "hsl(0, 0%, 50%)",
neutral40: "hsl(0, 0%, 60%)",
neutral50: "hsl(0, 0%, 70%)",
neutral60: "hsl(0, 0%, 80%)",
neutral70: "hsl(0, 0%, 90%)",
neutral80: "hsl(0, 0%, 95%)",
neutral90: "hsl(0, 0%, 100%)",
primary25: "hotpink",
primary: "black",
},
})}
styles={{
option: (styles) => ({
...styles,
backgroundColor: theming
.theme(
currentTheme.currentTheme,
{
light: theming.light
.backgroundColor1,
dark: theming.dark
.backgroundColor1,
}
)
.toString(),
color: theming
.theme(
currentTheme.currentTheme,
{
light: theming.light
.color1,
dark: theming.dark
.color1,
}
)
.toString(),
cursor: "pointer",
padding: 10,
":hover": {
backgroundColor: theming
.theme(
currentTheme.currentTheme,
{
light: theming
.light
.backgroundColor0,
dark: theming
.dark
.backgroundColor0,
}
)
.toString(),
},
}),
control: (styles) => ({
...styles,
backgroundColor: theming
.theme(
currentTheme.currentTheme,
{
light: theming.light
.backgroundColor1,
dark: theming.dark
.backgroundColor1,
}
)
.toString(),
border: theming.theme(
currentTheme.currentTheme,
{
light: "1px solid #ccc",
dark: "1px solid #555",
}
),
}),
multiValue: (styles) => ({
...styles,
color: "white",
backgroundColor:
theming.color.linkColor,
borderRadius: "5px",
}),
multiValueLabel: (styles) => ({
...styles,
marginLeft: "0.2rem",
marginRight: "0.2rem",
}),
multiValueRemove: (styles) => ({
...styles,
marginLeft: "0.2rem",
":hover": {
backgroundColor: "white",
color: theming.color
.linkColor,
},
}),
}}
defaultValue={selectedTags}
onChange={(newSelectedTags) => {
setSelectedOption(
newSelectedTags as TagsData[]
)
_history.push({
pathname: "/search",
search: queryString.stringify({
...(query.query && {
query: query.query,
}),
...(query.from && {
from: query.from,
}),
...(query.to && {
to: query.to,
}),
tags:
newSelectedTags
.map(
(elem) =>
elem.value
)
.join(",") ||
undefined,
}),
})
}}
options={options}
isMulti
/>
)}
</ThemeConsumer>
</StyledReactTagsContainer>
<br />
date from: {query.from}
<br />
date to: {query.to}
<br />
<button
onClick={() => {
_history.push({
pathname: "/search",
search: queryString.stringify({
...(query.query && {
query: query.query,
}),
...(query.tags.length > 0 && {
tags: query.tags.join(","),
}),
}),
})
setDateRange(defaultDateRange)
}}
>
Clear date
</button>
<br />
</StyledSearchControlContainer> </StyledSearchControlContainer>
</StyledSearchContainer> </StyledSearchContainer>
</StyledSearch> </StyledSearch>
@ -489,3 +350,138 @@ function _Search() {
</> </>
) )
} }
interface TagSelectProps {
query: Query
selectedTags: TagsData[] | null
setSelectedOption: React.Dispatch<React.SetStateAction<TagsData[] | null>>
}
const TagSelect = (props: TagSelectProps) => {
const _history = useHistory()
return (
<StyledReactTagsContainer>
<ThemeConsumer>
{(currentTheme) => (
<Select
theme={(theme) => ({
...theme,
colors: {
...theme.colors,
neutral0: theming
.theme(currentTheme.currentTheme, {
light: theming.light.backgroundColor1,
dark: theming.dark.backgroundColor1,
})
.toString(),
neutral5: "hsl(0, 0%, 20%)",
neutral10: "hsl(0, 0%, 30%)",
neutral20: "hsl(0, 0%, 40%)",
neutral30: "hsl(0, 0%, 50%)",
neutral40: "hsl(0, 0%, 60%)",
neutral50: "hsl(0, 0%, 70%)",
neutral60: "hsl(0, 0%, 80%)",
neutral70: "hsl(0, 0%, 90%)",
neutral80: "hsl(0, 0%, 95%)",
neutral90: "hsl(0, 0%, 100%)",
primary25: "hotpink",
primary: "black",
},
})}
styles={{
option: (styles) => ({
...styles,
backgroundColor: theming
.theme(currentTheme.currentTheme, {
light: theming.light.backgroundColor1,
dark: theming.dark.backgroundColor1,
})
.toString(),
color: theming
.theme(currentTheme.currentTheme, {
light: theming.light.color1,
dark: theming.dark.color1,
})
.toString(),
cursor: "pointer",
padding: 10,
":hover": {
backgroundColor: theming
.theme(currentTheme.currentTheme, {
light: theming.light
.backgroundColor0,
dark: theming.dark.backgroundColor0,
})
.toString(),
},
}),
control: (styles) => ({
...styles,
backgroundColor: theming
.theme(currentTheme.currentTheme, {
light: theming.light.backgroundColor1,
dark: theming.dark.backgroundColor1,
})
.toString(),
border: theming.theme(
currentTheme.currentTheme,
{
light: "1px solid #ccc",
dark: "1px solid #555",
}
),
}),
multiValue: (styles) => ({
...styles,
color: "white",
backgroundColor: theming.color.linkColor,
borderRadius: "5px",
}),
multiValueLabel: (styles) => ({
...styles,
marginLeft: "0.2rem",
marginRight: "0.2rem",
}),
multiValueRemove: (styles) => ({
...styles,
marginLeft: "0.2rem",
":hover": {
backgroundColor: "white",
color: theming.color.linkColor,
},
}),
}}
defaultValue={props.selectedTags}
onChange={(newSelectedTags) => {
props.setSelectedOption(
newSelectedTags as TagsData[]
)
_history.push({
pathname: "/search",
search: queryString.stringify({
...(props.query.query && {
query: props.query.query,
}),
...(props.query.from && {
from: props.query.from,
}),
...(props.query.to && {
to: props.query.to,
}),
tags:
newSelectedTags
.map((elem) => elem.value)
.join(",") || undefined,
}),
})
}}
options={options}
isMulti
/>
)}
</ThemeConsumer>
</StyledReactTagsContainer>
)
}