Implemented basic site layout, filtering via search, and added popup preview

pull/2/head
Joshua Sigona 5 years ago
parent ffd2558750
commit 0396da7c26
  1. 2
      app.js
  2. 3
      itunes/public/index.html
  3. 15
      itunes/src/App.css
  4. 80
      itunes/src/App.js
  5. 9
      itunes/src/index.js

@ -116,7 +116,7 @@ app.post("/:kind/add",(req,res)=>{
} }
}) })
const port = 3001 const port = 3002
app.listen(port, () => console.log(`Listening at http://localhost:${port}`)) app.listen(port, () => console.log(`Listening at http://localhost:${port}`))
/* /*

@ -15,6 +15,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
--> -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build. It will be replaced with the URL of the `public` folder during the build.
@ -24,7 +25,7 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>React App</title> <title>iTunes App</title>
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

@ -28,6 +28,21 @@
color: #61dafb; color: #61dafb;
} }
.gradient {
background-image: radial-gradient(#DDDDFF,#F0F0F0);
}
.gradient:hover {
background-image: radial-gradient(#DDDDFF,#FFFFDD);
}
.shadow {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.bottomright {
position:"absolute";
right:80vw;
bottom:80vh;
}
@keyframes App-logo-spin { @keyframes App-logo-spin {
from { from {
transform: rotate(0deg); transform: rotate(0deg);

@ -1,32 +1,53 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import './App.css'; import './App.css';
const playerWidth=320;
const PreviewWindow = (props) => {
return (props.src!==null)?<div>
<iframe style={{position:"absolute",
left:(window.innerWidth-playerWidth)+"px",bottom:-window.scrollY+"px"}} className="bottomright" id="previewWindow" src={props.src}/>
</div>:<React.Fragment/>;
}
const RadioButton = (props) => {
const RadioButton = (props) => {
return ( return (
<React.Fragment> <React.Fragment>
<br></br> <label for={props.name} className="ml-4">{props.displayName}</label>
<label for={props.name}>{props.name}</label>
<input type='radio' name="media-selection" value={props.name} id={props.name} <input type='radio' name="media-selection" value={props.name} id={props.name}
onClick={() => props.setMediaType(props.name)}/> onClick={() => props.setMediaType(props.name)} checked={props.mediaType===props.name}/>
</React.Fragment> </React.Fragment>
) )
} }
const MediaContainer = (props) => { const MediaContainer = (props) => {
const [previewOn, setPreviewOn] = useState(false) const togglePreview = (setPreview,sourceUrl) => {
//console.log(setPreview+","+sourceUrl)
const togglePreview = (counter, sourceUrl) => { setPreview(sourceUrl);
document.getElementById(counter).innerHTML = "<iframe src='" + sourceUrl + "'></iframe>"
} }
return ( return (
<div> <div>
{props.data.map((media, counter) => <div><img src={media.artworkUrl100} alt={media.artistName} /><span>{media.trackName} </span> {props.data.map((media, counter) =>
<span>{media.trackId} </span> <span>{media.collectionName} </span> <span>{media.collectionId} </span> <React.Fragment>
<span>{media.artistId} </span> <span>{media.artistName} </span> <button type='button' onClick={() => togglePreview(counter, media.previewUrl)}>Toggle Preview</button> <div className="card pt-3 gradient">
<div id={counter}></div><hr/></div>)} <div className="row">
<div className="offset-md-2 col-md-6">
<h4>{media.trackName}</h4>
<b>{media.artistName} </b>: <span>{media.collectionName} </span>
</div>
<div className="col-md-3 text-center">
<img className="shadow" src={media.artworkUrl100} alt={media.artistName}/>
</div>
</div>
<div className="row mb-3">
<div className="offset-md-8 col-md-3 text-center">
<button type='button' onClick={() => togglePreview(props.setPreview,media.previewUrl)}>Show Preview</button>
</div>
</div>
</div>
</React.Fragment>)}
</div>) </div>)
} }
@ -34,19 +55,38 @@ const MediaContainer = (props) => {
const App = () => { const App = () => {
const [mediaType, setMediaType] = useState("song") const [mediaType, setMediaType] = useState("song")
const [currentData, setCurrentData] = useState([]) const [currentData, setCurrentData] = useState([])
const [currentPreview, setPreview] = useState(null)
const [searchQuery, setSearchQuery] = useState("")
useEffect(() => {fetch(`http://localhost:3001/${mediaType}`) useEffect(() => {fetch(`http://localhost:3002/${mediaType}`)
.then(response => response.json()) .then(response => response.json())
.then(data => {console.log(data); setCurrentData(data)})}, [mediaType]) .then(data => {/*console.log(data);*/ setCurrentData(data)})}, [mediaType])
function setSearch(e){
setSearchQuery(e.target.value)
//console.log(e.target.value);
}
return ( return (
<React.Fragment> <React.Fragment>
Current media type: {mediaType} <div className="container">
<RadioButton name="song" setMediaType={setMediaType} /> <div className="row">
<RadioButton name="music-video" setMediaType={setMediaType} /> <div className="text-center col-md-12">
<RadioButton name="feature-movie" setMediaType={setMediaType} /> Search Title/Artist/Album: <input style={{"width":"480px","height":"32px"}} type="text" onChange={(e)=>{setSearch(e)}}/>
</div>
<MediaContainer data={currentData}/> </div>
<div className="row">
<div className="offset-md-2 col-md-8">
<RadioButton displayName="Songs" mediaType={mediaType} name="song" setMediaType={setMediaType} />
<RadioButton displayName="Music Videos" mediaType={mediaType} name="music-video" setMediaType={setMediaType} />
<RadioButton displayName="Movies" mediaType={mediaType} name="feature-movie" setMediaType={setMediaType} />
</div>
</div>
<MediaContainer data={(searchQuery.length>0)?currentData.filter((song)=>{
return (song.trackName.toLowerCase().includes(searchQuery.toLowerCase())||song.collectionName.toLowerCase().includes(searchQuery.toLowerCase())||song.artistName.toLowerCase().includes(searchQuery.toLowerCase()))
}):currentData} setPreview={setPreview}/>
<PreviewWindow src={currentPreview}/>
</div>
</React.Fragment> </React.Fragment>
) )
} }

@ -4,6 +4,15 @@ import './index.css';
import App from './App'; import App from './App';
import * as serviceWorker from './serviceWorker'; import * as serviceWorker from './serviceWorker';
document.addEventListener("scroll",()=>{
var obj = document.getElementById("previewWindow");
if (obj) {
obj.style.position="absolute";
obj.style.right=window.scrollX+"px";
obj.style.bottom=-window.scrollY+"px";
}
})
ReactDOM.render( ReactDOM.render(
<React.StrictMode> <React.StrictMode>
<App /> <App />

Loading…
Cancel
Save