feat: search all entries
This commit is contained in:
@@ -1,15 +1,15 @@
|
|||||||
asset-manifest.json,1553884046206,ab1a2f7317faa41861e422ef229575fe3ecbb17d1c2f975e88efb9d78e511376
|
asset-manifest.json,1554736332025,df5343ebe8ed04ae9e0eb3b32e838f56c18dfaf98ffca952c101cd9d712b1608
|
||||||
|
index.html,1554736332025,a6f9531c2850d3e7f5eb795a03b2a2a4414e302e81a92545416344c89e644a64
|
||||||
manifest.json,1553879304430,52afe5ad7170b2b50e3ac04262420481b529c8c3009d93599bd41e3c44367f78
|
manifest.json,1553879304430,52afe5ad7170b2b50e3ac04262420481b529c8c3009d93599bd41e3c44367f78
|
||||||
index.html,1553884046205,42891bf67643a2a8a638791bf6c4ee99e205be5c3b1c63c7ad1ba18706eb45c8
|
|
||||||
precache-manifest.d45de78050e7934587aed923200cf920.js,1553884046206,af20162c7c52cc330fba328fa78d181cd2e9295171b003d9360eb1c9970e9eb4
|
|
||||||
service-worker.js,1553884046205,fc351de1a559cf9b70e3022b895c738f94d83d8ccac4992c75e89ef7bb881248
|
|
||||||
static/css/main.1a707a0f.chunk.css,1553884046207,31f97c61456faf692f2920be106bc1ee08170c1e86a531eb225b32acfb8359ce
|
|
||||||
reactfavicon.ico,1553876850033,b72f7455f00e4e58792d2bca892abb068e2213838c0316d6b7a0d6d16acd1955
|
reactfavicon.ico,1553876850033,b72f7455f00e4e58792d2bca892abb068e2213838c0316d6b7a0d6d16acd1955
|
||||||
static/css/main.1a707a0f.chunk.css.map,1553884046251,28865d6e3616355a7fbb38dfc7ed97029ed4b5c5e5c61afbe5d433204e76f9ff
|
service-worker.js,1554736332025,77a2d280be8aa608763f3e7ce0d5e3c9d5a0a8fca4d0a2f585e4197785170a90
|
||||||
static/js/runtime~main.a8a9905a.js,1553884046254,e1af5f94fdd13901b2e433d0d7607e27c01458151c35b1fe4b7feda2a32b7aa9
|
static/css/main.1a707a0f.chunk.css.map,1554736332065,28865d6e3616355a7fbb38dfc7ed97029ed4b5c5e5c61afbe5d433204e76f9ff
|
||||||
|
precache-manifest.9a4f81b9fa21bd7215c42e286df1195f.js,1554736332025,3879fcf815575e6ec42ee5ba6c0de64a533475f4bad65088aa85885aa94694d8
|
||||||
|
static/css/main.1a707a0f.chunk.css,1554736332026,31f97c61456faf692f2920be106bc1ee08170c1e86a531eb225b32acfb8359ce
|
||||||
favicon.ico,1553876855791,229055d54fe1f70f3d835e9d723ea2fef78f2af82ed7ce45efa2f4623c1c1131
|
favicon.ico,1553876855791,229055d54fe1f70f3d835e9d723ea2fef78f2af82ed7ce45efa2f4623c1c1131
|
||||||
static/js/runtime~main.a8a9905a.js.map,1553884046250,c337bf8b58896da637a6e50ab8cfc779eb1ec42c55f8ec429030a03454a549db
|
static/js/main.66ce8d8f.chunk.js,1554736332068,668635c6cccab3a4ad7c8d03121baa8553aad7f93ea2945f2d9dc7d3a0fccda3
|
||||||
static/js/main.4752fead.chunk.js,1553884046253,31c047c091eb527f5bade96d426368d9e05689355d6d9ce29d5539621024cb58
|
static/js/runtime~main.a8a9905a.js,1554736332036,e1af5f94fdd13901b2e433d0d7607e27c01458151c35b1fe4b7feda2a32b7aa9
|
||||||
static/js/main.4752fead.chunk.js.map,1553884046254,f9eb4c273c0fcfd32f6ff8113afb509584adaf92667564c6e4ecc30023740cb4
|
static/js/runtime~main.a8a9905a.js.map,1554736332065,c337bf8b58896da637a6e50ab8cfc779eb1ec42c55f8ec429030a03454a549db
|
||||||
static/js/2.ad8c616b.chunk.js,1553884046253,e9ea391f6951d55e960b05d0353cf46c42a39af282058927141d20876cd5640e
|
static/js/main.66ce8d8f.chunk.js.map,1554736332064,620038709bdf8ee7c0fc8ad271d61ead41ebcaff4f82652fe19eb65c4dbe998c
|
||||||
static/js/2.ad8c616b.chunk.js.map,1553884046252,6896a6400a6836fc179167478961bf4c211614d2afcf220caf6c80afd11e8967
|
static/js/2.45d1e149.chunk.js,1554736332065,3b8f973757d4cc2ee88c12af9a97a786c0233909ee6f72d903157257572cccfe
|
||||||
|
static/js/2.45d1e149.chunk.js.map,1554736332067,5642dc89fcfbc41772fcb04c680e26db61d946042f08eb73c2fd838b1f7ff262
|
||||||
|
|||||||
11
src/App.js
11
src/App.js
@@ -13,6 +13,7 @@ import Month from "./components/screens/Month"
|
|||||||
import Year from "./components/screens/Year"
|
import Year from "./components/screens/Year"
|
||||||
import User from "./components/screens/User"
|
import User from "./components/screens/User"
|
||||||
import Login from "./components/screens/Login"
|
import Login from "./components/screens/Login"
|
||||||
|
import Search from "./components/screens/Search"
|
||||||
import Register from "./components/screens/Register"
|
import Register from "./components/screens/Register"
|
||||||
import Start from "./components/screens/Start"
|
import Start from "./components/screens/Start"
|
||||||
import PrivateRoute from "./components/PrivateRoute"
|
import PrivateRoute from "./components/PrivateRoute"
|
||||||
@@ -20,6 +21,9 @@ import PrivateRoute from "./components/PrivateRoute"
|
|||||||
import { withAuthentication } from "./components/session"
|
import { withAuthentication } from "./components/session"
|
||||||
import { withFirebase } from "./components/firebase"
|
import { withFirebase } from "./components/firebase"
|
||||||
|
|
||||||
|
const FullscreenLayout = styled.div`
|
||||||
|
background-color: ${props => props.theme.colors.bodyBackground};
|
||||||
|
`
|
||||||
const RouteLayout = styled.div`
|
const RouteLayout = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -42,9 +46,9 @@ class App extends Component {
|
|||||||
|
|
||||||
onChangeTheme = () => {
|
onChangeTheme = () => {
|
||||||
const { selectedTheme } = this.state
|
const { selectedTheme } = this.state
|
||||||
const root = document.documentElement
|
const body = document.body
|
||||||
const newTheme = selectedTheme === "LIGHT" ? "DARK" : "LIGHT"
|
const newTheme = selectedTheme === "LIGHT" ? "DARK" : "LIGHT"
|
||||||
root.style.setProperty(
|
body.style.setProperty(
|
||||||
"background-color",
|
"background-color",
|
||||||
theme[newTheme].colors.bodyBackground
|
theme[newTheme].colors.bodyBackground
|
||||||
)
|
)
|
||||||
@@ -73,6 +77,7 @@ class App extends Component {
|
|||||||
return (
|
return (
|
||||||
<ThemeProvider theme={currentTheme}>
|
<ThemeProvider theme={currentTheme}>
|
||||||
<Router>
|
<Router>
|
||||||
|
<FullscreenLayout>
|
||||||
<Navbar toggleTheme={this.onChangeTheme} />
|
<Navbar toggleTheme={this.onChangeTheme} />
|
||||||
<RouteLayout>
|
<RouteLayout>
|
||||||
<PrivateRoute
|
<PrivateRoute
|
||||||
@@ -95,9 +100,11 @@ class App extends Component {
|
|||||||
/>
|
/>
|
||||||
<Route path="/user" component={User} exact />
|
<Route path="/user" component={User} exact />
|
||||||
<Route path="/login" component={Login} exact />
|
<Route path="/login" component={Login} exact />
|
||||||
|
<Route path="/search" component={Search} exact />
|
||||||
<Route path="/register" component={Register} exact />
|
<Route path="/register" component={Register} exact />
|
||||||
<Route path="/" component={Start} exact />
|
<Route path="/" component={Start} exact />
|
||||||
</RouteLayout>
|
</RouteLayout>
|
||||||
|
</FullscreenLayout>
|
||||||
</Router>
|
</Router>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
Edit2,
|
Edit2,
|
||||||
LogIn,
|
LogIn,
|
||||||
Moon,
|
Moon,
|
||||||
|
Search,
|
||||||
Sun,
|
Sun,
|
||||||
User,
|
User,
|
||||||
} from "react-feather"
|
} from "react-feather"
|
||||||
@@ -53,6 +54,7 @@ const Icon = ({ name, tabindex, label, ...rest }) => (
|
|||||||
{name === "Edit2" && <Edit2 />}
|
{name === "Edit2" && <Edit2 />}
|
||||||
{name === "LogIn" && <LogIn />}
|
{name === "LogIn" && <LogIn />}
|
||||||
{name === "Moon" && <Moon />}
|
{name === "Moon" && <Moon />}
|
||||||
|
{name === "Search" && <Search />}
|
||||||
{name === "Sun" && <Sun />}
|
{name === "Sun" && <Sun />}
|
||||||
{name === "User" && <User />}
|
{name === "User" && <User />}
|
||||||
</IconBase>
|
</IconBase>
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ const Navbar = ({ authUser, theme, toggleTheme }) => (
|
|||||||
<Link to={yearUrl()}>
|
<Link to={yearUrl()}>
|
||||||
<Icon name="Calendar" />
|
<Icon name="Calendar" />
|
||||||
</Link>
|
</Link>
|
||||||
|
<Link to={"/search"}>
|
||||||
|
<Icon name="Search" />
|
||||||
|
</Link>
|
||||||
<Link to={"/user"}>
|
<Link to={"/user"}>
|
||||||
<Icon name="User" />
|
<Icon name="User" />
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const H1 = styled.h1`
|
|||||||
`
|
`
|
||||||
|
|
||||||
export const Input = styled.input`
|
export const Input = styled.input`
|
||||||
|
color: ${props => props.colors.primary};
|
||||||
background-color: ${props => props.colors.headerBackground};
|
background-color: ${props => props.colors.headerBackground};
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ class Day extends Component {
|
|||||||
day: Number(day),
|
day: Number(day),
|
||||||
year: Number(year),
|
year: Number(year),
|
||||||
month: Number(month),
|
month: Number(month),
|
||||||
|
userId: authUser.uid,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
merge: true,
|
merge: true,
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class RegisterFormBase extends Component {
|
|||||||
email: user.email,
|
email: user.email,
|
||||||
theme: "LIGHT",
|
theme: "LIGHT",
|
||||||
})
|
})
|
||||||
this.props.history.push("/home")
|
this.props.history.push("/")
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.setState({ error })
|
this.setState({ error })
|
||||||
|
|||||||
165
src/components/screens/Search/Search.js
Normal file
165
src/components/screens/Search/Search.js
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
import React, { Component } from "react"
|
||||||
|
import { withRouter, Link } from "react-router-dom"
|
||||||
|
/** @jsx jsx */
|
||||||
|
import { jsx, css, keyframes } from "@emotion/core"
|
||||||
|
import styled from "@emotion/styled"
|
||||||
|
import { compose } from "recompose"
|
||||||
|
import { withTheme } from "emotion-theming"
|
||||||
|
import { BeatLoader } from "react-spinners"
|
||||||
|
|
||||||
|
import { Input } from "../../elements"
|
||||||
|
import { pad } from "../../../utils/date"
|
||||||
|
|
||||||
|
import { withFirebase } from "../../firebase"
|
||||||
|
import { withAuthentication } from "../../session"
|
||||||
|
|
||||||
|
const SearchGrid = styled.div`
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-gap: 10px;
|
||||||
|
`
|
||||||
|
const SearchLayout = styled.div`
|
||||||
|
width: 100%;
|
||||||
|
align-self: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const SearchResult = styled.div`
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: ${props => props.theme.colors.primary};
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: ${props => props.theme.colors.quarternary};
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
border-color: ${props => props.theme.colors.tertiary};
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const fadeKeyFrames = keyframes`
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
const LoadingSpinner = styled(BeatLoader)`
|
||||||
|
opacity: 0;
|
||||||
|
`
|
||||||
|
|
||||||
|
class Search extends Component {
|
||||||
|
state = {
|
||||||
|
entries: [],
|
||||||
|
allEntries: [],
|
||||||
|
searchInput: "",
|
||||||
|
loading: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const entries = this.getEntries()
|
||||||
|
console.log(entries)
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange = event => {
|
||||||
|
const searchInput = event.target.value
|
||||||
|
this.setState({ searchInput })
|
||||||
|
this.filterEntries(searchInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
filterEntries = searchTerm => {
|
||||||
|
const { allEntries } = this.state
|
||||||
|
if (searchTerm == "") {
|
||||||
|
this.setState({ entries: allEntries })
|
||||||
|
} else {
|
||||||
|
const filteredEntries = allEntries.filter(entry => {
|
||||||
|
return entry.text.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
|
})
|
||||||
|
this.setState({ entries: filteredEntries })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getEntries = async _ => {
|
||||||
|
const { firebase, authUser } = this.props
|
||||||
|
const entriesRef = await firebase.db
|
||||||
|
.collection("entries")
|
||||||
|
.where("userId", "==", authUser.uid)
|
||||||
|
.get()
|
||||||
|
const entries = entriesRef.docs.map(doc => doc.data())
|
||||||
|
console.log(entries)
|
||||||
|
// const sortedEntries = entries.sort((a, b) => {
|
||||||
|
// return (
|
||||||
|
// new Date(b.year, b.month - 1, b.day) -
|
||||||
|
// new Date(a.year, a.month - 1, a.day)
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
// console.log(sortedEntries)
|
||||||
|
this.setState({ entries, allEntries: entries, loading: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { entries, searchInput, loading } = this.state
|
||||||
|
const { theme } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SearchLayout>
|
||||||
|
<SearchGrid>
|
||||||
|
<Input
|
||||||
|
value={searchInput}
|
||||||
|
onChange={e => this.onChange(e)}
|
||||||
|
type="text"
|
||||||
|
placeholder="Search..."
|
||||||
|
colors={theme.colors}
|
||||||
|
/>
|
||||||
|
{loading ? (
|
||||||
|
<div style={{ marginTop: 10, margin: "0 auto" }}>
|
||||||
|
<LoadingSpinner
|
||||||
|
color={theme.colors.quarternary}
|
||||||
|
size={10}
|
||||||
|
margin="4px"
|
||||||
|
css={css`
|
||||||
|
animation: ${fadeKeyFrames} 1s ease-in;
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
entries.map((entry, index) => (
|
||||||
|
<Link
|
||||||
|
key={index}
|
||||||
|
to={`${entry.year}/${pad(entry.month)}/${pad(entry.day)}`}
|
||||||
|
style={{ textDecoration: "none" }}
|
||||||
|
>
|
||||||
|
<SearchResult
|
||||||
|
css={css`
|
||||||
|
animation: ${fadeKeyFrames} 0.2s ease-in;
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
css={css`
|
||||||
|
font-style: italic;
|
||||||
|
color: ${theme.colors.secondary};
|
||||||
|
margin-bottom: 5px;
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{entry.day}/{entry.month}/{entry.year}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{entry.text.substring(0, 128)}
|
||||||
|
{entry.text.length >= 128 && "..."}
|
||||||
|
</div>
|
||||||
|
</SearchResult>
|
||||||
|
</Link>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</SearchGrid>
|
||||||
|
</SearchLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withFirebase,
|
||||||
|
withTheme,
|
||||||
|
withAuthentication
|
||||||
|
)(Search)
|
||||||
2
src/components/screens/Search/index.js
Normal file
2
src/components/screens/Search/index.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import Search from "./Search"
|
||||||
|
export default Search
|
||||||
Reference in New Issue
Block a user