Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"baseUrl": "src"
},
"include": ["src/**/*"]
}
Binary file added screens/GitHub.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 0 additions & 8 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,3 @@
display: flex;
}

.left-nav {
flex: 1;
}

.plays {
flex: 5;
padding: 1rem;
}
19 changes: 2 additions & 17 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
import { useState } from 'react';
import { Link, Outlet } from 'react-router-dom';
import './App.css';
import { getPlaysToInclude } from './meta/play-meta';

import "App.css";
import { Outlet } from "react-router-dom";

function App() {
const [plays] = useState(getPlaysToInclude());
return (
<div className="App">
<nav className="left-nav">
<ul className="link-list">
{
plays.map((play, index) => (
<li key={index}>
<Link to={play.path}>{play.name}</Link>
</li>
))
}
</ul>
</nav>
<div className="plays">
<Outlet />
</div>
Expand Down
21 changes: 0 additions & 21 deletions src/common/Header.js

This file was deleted.

File renamed without changes.
48 changes: 48 additions & 0 deletions src/common/header/Header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import FilterPlays from 'common/search/FilterPlays';
import SearchPlays from 'common/search/SearchPlays';
import { useEffect, useState } from "react";
import { Link, useLocation } from "react-router-dom";
import './header.css';

const Header = () => {
const location = useLocation();
const pathName = location.pathname;

const [showSearch, setShowSearch] = useState(false);

useEffect(() => {
if (pathName === '/') {
setShowSearch(false);
} else {
setShowSearch(true);
}
}, [pathName]);

return (
<header className="app-header">
<span><Link to="/">React Play</Link></span>
<ul className="header-links">
{
showSearch && (
<>
<li>
<SearchPlays />
</li>
<li>
<FilterPlays />
</li>
</>
)
}
<li>
<a href="https://github.com/atapas/react-play" target="_blank" rel="noopener noreferrer">GitHub</a>
</li>
<li>
<a href="https://twitter.com/tapasadhikary" target="_blank" rel="noopener noreferrer">Twitter</a>
</li>
</ul>
</header>
);
};

export default Header;
File renamed without changes.
6 changes: 4 additions & 2 deletions src/common/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import PageNotFound from './404/PageNotFound';
import Footer from './Footer';
import Header from './Header';
import Footer from './footer/Footer';
import Header from './header/Header';
import Home from './home/Home';
import Modal from './modal';

export {
Header,
Footer,
Home,
PageNotFound,
Modal
};

15 changes: 15 additions & 0 deletions src/common/modal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import ReactDOM from "react-dom";

const Modal =({ title, show, onClose, onSubmit, children, cname })=> {
if (!show) return null;
return ReactDOM.createPortal(
<div className={`modal-${cname}`}>
<h2>{ title }</h2>
{ children }
<button onClick={ onClose }>Close</button>
<button onClick={ onSubmit }>OK</button>
</div>
,document.body);
}

export default Modal;
18 changes: 18 additions & 0 deletions src/common/playlists/PlayList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useSearchFilter } from "common/search/hooks/useSearchFilter";
import { Link } from "react-router-dom";

const PlayList = () => {
const plays = useSearchFilter();

return (
<ul>
{plays.map((play, index) => (
<li key={play.id}>
<Link to={play.path}>{play.name}</Link>
</li>
))}
</ul>
);
};

export default PlayList;
27 changes: 27 additions & 0 deletions src/common/routing/RouteDefs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import App from "App";
import { Footer, Header, Home, PageNotFound } from "common";
import PlayList from 'common/playlists/PlayList';
import { getAllPlays } from 'meta/play-meta';
import { BrowserRouter, Route, Routes } from "react-router-dom";

const RouteDefs = () => {
const plays = getAllPlays();
return (
<BrowserRouter>
<Header/>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/plays" element={<App />}>
<Route index element={<PlayList />} />
{plays.map((play, index) => (
<Route key={index} path={play.path} element={play.component()} />
))}
</Route>
<Route path="/*" element={<PageNotFound />} />
</Routes>
<Footer/>
</BrowserRouter>
);
};

export default RouteDefs;
11 changes: 11 additions & 0 deletions src/common/routing/hooks/useLocationChange.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

import { useEffect } from 'react';
import { useLocation } from "react-router-dom";

const useLocationChange = (action) => {
const location = useLocation()
useEffect(() => { action(location) }, [location, action]);
}

export { useLocationChange };

114 changes: 114 additions & 0 deletions src/common/search/FilterPlays.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { Modal } from "common";
import { getAllCreators, getAllLevels, getAllTags } from "meta/play-meta";
import { useContext, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { SearchContext } from "./search-context";
import "./search.css";

const FilterPlaysModalBody = ({filterQuery, setFilterQuery}) => {
const tags = getAllTags();
const labels = getAllLevels();
const creators = getAllCreators();

return (
<div className="filter-plays-modal">
<div className="filter-plays-modal-row">
<label>Level</label>
<select
className="filter-plays-modal-select"
onChange={(event) =>
setFilterQuery({ ...filterQuery, level: event.target.value })
}
value={filterQuery.level}
>
<option value="">All</option>
{labels.map((label) => (
<option key={label} value={label}>
{label}
</option>
))}
</select>
</div>
<div className="filter-plays-modal-row">
<label>Tags</label>
<select
className="filter-plays-modal-select"
onChange={(event) =>
setFilterQuery({ ...filterQuery, tags: [event.target.value] })
}
value={filterQuery.tags[0]}
>
<option value="">All</option>
{tags.map(tag => (
<option key={tag} value={tag}>
{tag}
</option>
))}
</select>
</div>
<div className="filter-plays-modal-row">
<label>Creator</label>
<select
className="filter-plays-modal-select"
onChange={(event) =>
setFilterQuery({ ...filterQuery, creator: event.target.value })
}
value={filterQuery.creator}
>
<option value="">All</option>
{creators.map((creator) => (
<option key={creator} value={creator}>
{creator}
</option>
))}
</select>
</div>
</div>
);
};

const FilterPlays = () => {
const location = useLocation();
const navigate = useNavigate();
const { setFilterQuery, filterQuery } =
useContext(SearchContext);
const [showModal, setShowModal] = useState(false);
const [modifiedFilterQuery, setModifiedFilterQuery] = useState({
tags: [],
labels: [],
creators: [],
});

const handleFilter = (event) => {
event.preventDefault();
console.log('filterQuery', filterQuery);
console.log('modifiedFilterQuery', modifiedFilterQuery);
setFilterQuery(modifiedFilterQuery);
if (location.pathname !== "/plays") {
navigate("/plays", { replace: true });
}
showModal && setShowModal(false);
};

return (
<div className="filter-plays">
<Modal
title="Filter Plays"
onClose={() => setShowModal(false)}
onSubmit={handleFilter}
show={showModal}
cname="filter-plays"
children={
<FilterPlaysModalBody
filterQuery={modifiedFilterQuery}
setFilterQuery={setModifiedFilterQuery}
/>
}
/>

<button onClick={() => setShowModal(true)}>F</button>
</div>
);
};

export default FilterPlays;
33 changes: 33 additions & 0 deletions src/common/search/SearchPlays.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

import { useContext } from 'react';
import { useLocation, useNavigate } from "react-router-dom";
import { SearchContext } from './search-context';
import './search.css';


const SearchPlays = () => {
const location = useLocation();
const navigate = useNavigate();
const {setSearchTerm} = useContext(SearchContext);

const handleSearch = (event) => {
event.preventDefault();
if(event.key === 'Enter') {
setSearchTerm(event.target.value);
if(location.pathname !== '/plays') {
navigate('/plays', { replace: true});
}
}
}

return (
<input
className="search-text"
type="text"
placeholder="Search for a play..."
onKeyUp={ handleSearch }
/>
);
};

export default SearchPlays;
Loading