Merge pull request #11 from innocuous-symmetry/search-refactor
Search refactor
This commit is contained in:
15
src/App.css
15
src/App.css
@@ -31,7 +31,7 @@
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-title {
|
.nav-title-mobile {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
z-index: 9;
|
z-index: 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-title {
|
.nav-title-desktop {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
color: orchid;
|
color: orchid;
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
.sidebar {
|
.sidebar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 12rem;
|
width: 13.5rem;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
color: white;
|
color: white;
|
||||||
@@ -234,17 +234,20 @@
|
|||||||
position: static;
|
position: static;
|
||||||
}
|
}
|
||||||
|
|
||||||
.desktop-title {
|
.nav-title-desktop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-title {
|
.nav-title-mobile {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
color: orchid;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
font-family: 'Open Sans', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-searchbar {
|
.nav-searchbar {
|
||||||
width: 12rem;
|
width: 12rem;
|
||||||
right: 12rem;
|
right: 7rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-button {
|
.sidebar-button {
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ export default function Navbar() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="navbar">
|
<div className="navbar">
|
||||||
<h1 className="nav-title desktop-title">Reddit, but it's all cats</h1>
|
<h1 className="nav-title-desktop">Reddit, but it's all cats</h1>
|
||||||
<h1 className="nav-title mobile-title">Cat Reddit</h1>
|
<h1 className="nav-title-mobile">Cat Reddit</h1>
|
||||||
<SearchBar />
|
<SearchBar />
|
||||||
<button className="sidebar-button" onClick={handleCollapse}>Sidebar</button>
|
<button className="sidebar-button" onClick={handleCollapse}>Sidebar</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -29,11 +29,32 @@ export const fetchComments = createAsyncThunk(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const searchByActive = createAsyncThunk(
|
||||||
|
'posts/searchByActive',
|
||||||
|
async(obj) => {
|
||||||
|
const { sub, term } = obj;
|
||||||
|
try {
|
||||||
|
let fulfilledResponse;
|
||||||
|
const myRequest = new Request(`https://www.reddit.com/${sub}/search.json?q=${term}&restrict_sr=1&sr_nsfw=`);
|
||||||
|
let response = await fetch(myRequest);
|
||||||
|
if (response.ok) {
|
||||||
|
let searchData = await response.json();
|
||||||
|
fulfilledResponse = searchData;
|
||||||
|
}
|
||||||
|
return fulfilledResponse;
|
||||||
|
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
export const postsSlice = createSlice({
|
export const postsSlice = createSlice({
|
||||||
name: 'posts',
|
name: 'posts',
|
||||||
initialState: {
|
initialState: {
|
||||||
posts: [],
|
posts: [],
|
||||||
activeComments: [],
|
activeComments: [],
|
||||||
|
searchResults: [],
|
||||||
requestsPending: false,
|
requestsPending: false,
|
||||||
requestDenied: false,
|
requestDenied: false,
|
||||||
},
|
},
|
||||||
@@ -43,7 +64,7 @@ export const postsSlice = createSlice({
|
|||||||
},
|
},
|
||||||
updatePosts(state,action) {
|
updatePosts(state,action) {
|
||||||
state.posts = action.payload;
|
state.posts = action.payload;
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
builder.addCase(fetchBySub.pending, (state,action) => {
|
builder.addCase(fetchBySub.pending, (state,action) => {
|
||||||
@@ -75,12 +96,28 @@ export const postsSlice = createSlice({
|
|||||||
state.requestDenied = false;
|
state.requestDenied = false;
|
||||||
state.activeComments.push(action.payload);
|
state.activeComments.push(action.payload);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
builder.addCase(searchByActive.pending, (state,action) => {
|
||||||
|
state.requestsPending = true;
|
||||||
|
state.requestDenied = false;
|
||||||
|
})
|
||||||
|
builder.addCase(searchByActive.rejected, (state,action) => {
|
||||||
|
state.requestsPending = false;
|
||||||
|
state.requestDenied = true;
|
||||||
|
})
|
||||||
|
builder.addCase(searchByActive.fulfilled, (state,action) => {
|
||||||
|
state.requestsPending = false;
|
||||||
|
state.requestDenied = false;
|
||||||
|
state.searchResults = action.payload;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default postsSlice.reducer;
|
export default postsSlice.reducer;
|
||||||
export const selectPosts = state => state.postsSlice.posts;
|
export const selectPosts = state => state.postsSlice.posts;
|
||||||
export const isPending = state => state.postsSlice.requestsPending;
|
export const isPending = state => state.postsSlice.requestsPending;
|
||||||
|
export const selectSearchResults = state => state.postsSlice.searchResults;
|
||||||
export const { filterPosts, updatePosts } = postsSlice.actions;
|
export const { filterPosts, updatePosts } = postsSlice.actions;
|
||||||
// exports also includes fetchBySub (takes argument of a sub)
|
// exports also includes fetchBySub (takes argument of a sub)
|
||||||
// exports also includes fetchComments (takes argument of a post permalink)
|
// exports also includes fetchComments (takes argument of a post permalink)
|
||||||
|
// exports also includes searchByActive
|
||||||
@@ -62,6 +62,7 @@ export const redditSlice = createSlice({
|
|||||||
isSelected: true
|
isSelected: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
formattedActive: []
|
||||||
},
|
},
|
||||||
reducers: {
|
reducers: {
|
||||||
updateSubVisibility(state,action) { // receives a subreddit name as action.payload
|
updateSubVisibility(state,action) { // receives a subreddit name as action.payload
|
||||||
@@ -69,29 +70,29 @@ export const redditSlice = createSlice({
|
|||||||
},
|
},
|
||||||
getActiveSubs(state,action) {
|
getActiveSubs(state,action) {
|
||||||
let activeSubs = [];
|
let activeSubs = [];
|
||||||
let allSubs = state.redditSlice.subreddits;
|
for (let sub in state.subreddits) {
|
||||||
for (let sub in allSubs) {
|
sub.isSelected && activeSubs.push(sub.name);
|
||||||
if (sub.isSelected) {
|
|
||||||
activeSubs.push(sub);
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
state.formattedActive = activeSubs;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extraReducers: {},
|
extraReducers: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const selectAllSubs = state => state.redditSlice.subreddits;
|
export const selectAllSubs = state => state.redditSlice.subreddits;
|
||||||
export const selectActiveSubs = state => {
|
export const selectActive = state => {
|
||||||
|
let subs = [];
|
||||||
|
for (let sub in state.redditSlice.subreddits) {
|
||||||
|
subs.push(sub);
|
||||||
|
}
|
||||||
|
|
||||||
let activeSubs = [];
|
let activeSubs = [];
|
||||||
for (let it in state.redditSlice.subreddits) {
|
for (let each of subs) {
|
||||||
if (it.isSelected) {
|
if (each.isSelected) {
|
||||||
activeSubs.push(it);
|
activeSubs.push(each);
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return activeSubs;
|
return activeSubs;
|
||||||
}
|
}
|
||||||
export const { updateSubVisibility, getActiveSubs } = redditSlice.actions;
|
export const { updateSubVisibility, getActiveSubs } = redditSlice.actions;
|
||||||
|
|||||||
@@ -1,24 +1,53 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { searchByActive, selectSearchResults } from '../posts/postsSlice';
|
||||||
|
import { selectActive, selectAllSubs } from "../reddit/redditSlice";
|
||||||
|
|
||||||
export default function SearchBar() {
|
export default function SearchBar() {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const selectedSubs = useSelector(selectAllSubs);
|
||||||
|
const activeSubs = useSelector(selectActive);
|
||||||
|
|
||||||
const [term, setTerm] = useState('');
|
const [term, setTerm] = useState('');
|
||||||
|
const [results, setResults] = useState(null);
|
||||||
|
const searchData = useSelector(selectSearchResults);
|
||||||
|
|
||||||
const handleChange = (e) => {
|
const handleChange = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setTerm(e.target.value);
|
setTerm(e.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
const handleSubmit = () => {
|
||||||
if (term) {
|
if (term && activeSubs) {
|
||||||
// dispatch an action which filters content by {term}
|
let extracted = [];
|
||||||
} else {
|
for (let sub in activeSubs) {
|
||||||
return;
|
extracted.push(sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(extracted);
|
||||||
|
let mapped = extracted.map((sub) => dispatch(searchByActive({sub, term})));
|
||||||
|
Promise.all([...mapped]).then((data) => setResults(data));
|
||||||
}
|
}
|
||||||
}, [term])
|
}
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let active = true;
|
||||||
|
|
||||||
|
if (results && active) {
|
||||||
|
console.log(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
}, [results, activeSubs]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<input type="text" className="nav-searchbar" placeholder="Search posts" value={term ? term : ''} onChange={handleChange} />
|
<input type="text" className="nav-searchbar" placeholder="Search posts" value={term ? term : ''} onChange={handleChange} />
|
||||||
|
<input type="submit" onClick={handleSubmit}></input>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,14 @@
|
|||||||
margin: 0.8rem 0;
|
margin: 0.8rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.individual-sub button {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.individual-sub label {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
.search-sub-input {
|
.search-sub-input {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,17 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
// import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
// import { updateSubVisibility } from "../reddit/redditSlice";
|
import { updateSubVisibility } from "../reddit/redditSlice";
|
||||||
|
|
||||||
export default function SidebarItem({sub}) {
|
export default function SidebarItem({sub}) {
|
||||||
const [visible, setVisible] = useState('hide'); // dispatch will be used to dispatch updateSubVisibility on change in state
|
const dispatch = useDispatch();
|
||||||
// const dispatch = useDispatch(); // this will likely be within a useEffect hook
|
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (visible === 'hide') {
|
dispatch(updateSubVisibility(sub));
|
||||||
setVisible('show');
|
|
||||||
} else if (visible === 'show') {
|
|
||||||
setVisible('hide');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="individual-sub">
|
<div className="individual-sub">
|
||||||
{/* <input type="checkbox" id={sub} checked={checked} onChange={handleClick}></input> */}
|
<button id={sub} onClick={handleClick}>toggle</button>
|
||||||
<button id={sub} onClick={handleClick}>{visible}</button>
|
|
||||||
<label id={sub}>{sub}</label>
|
<label id={sub}>{sub}</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user