Merge pull request #11 from innocuous-symmetry/search-refactor

Search refactor
This commit is contained in:
Mikayla Dobson
2022-02-06 11:10:47 -06:00
committed by GitHub
7 changed files with 114 additions and 42 deletions

View File

@@ -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 {

View File

@@ -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>

View File

@@ -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

View File

@@ -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;

View File

@@ -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>
</> </>
); );
} }

View File

@@ -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;
} }

View File

@@ -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>
); );