Implemented basic site layout, filtering via search, and added popup preview
This commit is contained in:
parent
ffd2558750
commit
0396da7c26
2
app.js
2
app.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}`))
|
||||
|
||||
/*
|
||||
|
@ -15,6 +15,7 @@
|
||||
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="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.
|
||||
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.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
<title>iTunes App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
@ -28,6 +28,21 @@
|
||||
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 {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
|
@ -1,52 +1,92 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
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) => {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<br></br>
|
||||
<label for={props.name}>{props.name}</label>
|
||||
<label for={props.name} className="ml-4">{props.displayName}</label>
|
||||
<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>
|
||||
)
|
||||
}
|
||||
|
||||
const MediaContainer = (props) => {
|
||||
const [previewOn, setPreviewOn] = useState(false)
|
||||
|
||||
const togglePreview = (counter, sourceUrl) => {
|
||||
document.getElementById(counter).innerHTML = "<iframe src='" + sourceUrl + "'></iframe>"
|
||||
const togglePreview = (setPreview,sourceUrl) => {
|
||||
//console.log(setPreview+","+sourceUrl)
|
||||
setPreview(sourceUrl);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{props.data.map((media, counter) => <div><img src={media.artworkUrl100} alt={media.artistName} /><span>{media.trackName} </span>
|
||||
<span>{media.trackId} </span> <span>{media.collectionName} </span> <span>{media.collectionId} </span>
|
||||
<span>{media.artistId} </span> <span>{media.artistName} </span> <button type='button' onClick={() => togglePreview(counter, media.previewUrl)}>Toggle Preview</button>
|
||||
<div id={counter}></div><hr/></div>)}
|
||||
</div>)
|
||||
{props.data.map((media, counter) =>
|
||||
<React.Fragment>
|
||||
<div className="card pt-3 gradient">
|
||||
<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>)
|
||||
}
|
||||
|
||||
|
||||
const App = () => {
|
||||
const [mediaType, setMediaType] = useState("song")
|
||||
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(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 (
|
||||
<React.Fragment>
|
||||
Current media type: {mediaType}
|
||||
<RadioButton name="song" setMediaType={setMediaType} />
|
||||
<RadioButton name="music-video" setMediaType={setMediaType} />
|
||||
<RadioButton name="feature-movie" setMediaType={setMediaType} />
|
||||
|
||||
<MediaContainer data={currentData}/>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="text-center col-md-12">
|
||||
Search Title/Artist/Album: <input style={{"width":"480px","height":"32px"}} type="text" onChange={(e)=>{setSearch(e)}}/>
|
||||
</div>
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
@ -4,6 +4,15 @@ import './index.css';
|
||||
import App from './App';
|
||||
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(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
|
Loading…
x
Reference in New Issue
Block a user