From ed925895d1d24f0c3194db5b44f14d2e5abece0e Mon Sep 17 00:00:00 2001 From: Swarup Bhise Date: Wed, 15 May 2024 13:25:27 +0530 Subject: [PATCH] Feat: #94 complete Search Page Component --- backend/index.js | 73 ++-- frontend/package-lock.json | 12 + frontend/package.json | 1 + frontend/src/App.css | 110 +++--- frontend/src/App.jsx | 357 ++++++++++-------- frontend/src/Pages/SearchResultPage.jsx | 117 ++++++ frontend/src/Pages/Style.css | 111 ++++++ frontend/src/components/Share_UI/Header.jsx | 30 ++ .../src/components/Share_UI/MusicCard.jsx | 30 ++ frontend/src/components/Share_UI/Sidebar.jsx | 105 ++++++ frontend/src/components/Share_UI/Style.css | 192 ++++++++++ 11 files changed, 887 insertions(+), 251 deletions(-) create mode 100644 frontend/src/Pages/SearchResultPage.jsx create mode 100644 frontend/src/Pages/Style.css create mode 100644 frontend/src/components/Share_UI/Header.jsx create mode 100644 frontend/src/components/Share_UI/MusicCard.jsx create mode 100644 frontend/src/components/Share_UI/Sidebar.jsx create mode 100644 frontend/src/components/Share_UI/Style.css diff --git a/backend/index.js b/backend/index.js index 5f39d60..77e51f8 100644 --- a/backend/index.js +++ b/backend/index.js @@ -14,50 +14,47 @@ app.use(bodyParser.urlencoded({ extended: true })); app.use(cors()); app.get("/", (req, res) => { - res.send("Welcome to the music search API"); + res.send("Welcome to the music search API"); }); app.get("/search", async (req, res) => { - name = req.query.song; - console.log("Name is", name); - try { - if (cache.has(name)) { - console.log("Fetching from cache..."); - const music = cache.get(name); - res.json(music); - } else { - const response = await axios.get( - `https://jio-savaan-private.vercel.app/api/search/songs?query=${name}` - ); - if ( - response.data.data.results && - response.data.data.results.length > 0 - ) { - const musicArray = response.data.data.results.map((result) => ({ - url: result.downloadUrl[4]?.url || "", - name: result.name || "", - year: result.year || "", - artist: - result.artists.primary[0]?.name.replace( - /&/g, - "&" - ) || "", - img: result.image[2]?.url || "", - })); - cache.set(name, musicArray); - res.json(musicArray); - } else { - res.json([]); - } - } - } catch (error) { - console.error("Failed to make request:", error.message); - res.status(500).json({ - error: "Error fetching song. Please try again later.", + name = req.query.song; + console.log("Name is", name); + try { + if (cache.has(name)) { + console.log("Fetching from cache..."); + const music = cache.get(name); + res.json(music); + } else { + const response = await axios.get( + `https://jio-savaan-private.vercel.app/api/search/songs?query=${name}` + ); + if (response.data.data.results && response.data.data.results.length > 0) { + const musicArray = response.data.data.results.map((result) => { + return { + id: result.id, + url: result.downloadUrl[4]?.url || "", + name: result.name || "", + year: result.year || "", + artist: + result.artists.primary[0]?.name.replace(/&/g, "&") || "", + img: result.image[2]?.url || "", + }; }); + cache.set(name, musicArray); + res.json(musicArray); + } else { + res.json([]); + } } + } catch (error) { + console.error("Failed to make request:", error.message); + res.status(500).json({ + error: "Error fetching song. Please try again later.", + }); + } }); app.listen(PORT, () => { - console.log(`Server is running on port ${port}`); + console.log(`Server is running on port ${PORT}`); }); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f0608e8..9918d93 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "axios": "^1.6.8", "he": "^1.2.0", + "phosphor-react": "^1.4.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-h5-audio-player": "^3.9.1" @@ -4012,6 +4013,17 @@ "node": "14 || >=16.14" } }, + "node_modules/phosphor-react": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/phosphor-react/-/phosphor-react-1.4.1.tgz", + "integrity": "sha512-gO5j7U0xZrdglTAYDYPACU4xDOFBTJmptrrB/GeR+tHhCZF3nUMyGmV/0hnloKjuTrOmpSFlbfOY78H39rgjUQ==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 1ee49f9..829e388 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,7 @@ "dependencies": { "axios": "^1.6.8", "he": "^1.2.0", + "phosphor-react": "^1.4.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-h5-audio-player": "^3.9.1" diff --git a/frontend/src/App.css b/frontend/src/App.css index be66066..9d6f919 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -27,7 +27,6 @@ /* --color-bg: rgba(230, 230, 235, 0.648); */ /* --color-bg: rgb(255 255 255 / 89%); */ - --color-bg: rgb(249 249 249 / 93%); --transition: all 300ms ease; @@ -45,14 +44,10 @@ --radius-3: 1rem; } - - html { scroll-behavior: smooth; } - - a { color: var(--color-gray-700); text-decoration: none; @@ -86,7 +81,6 @@ h5 { line-height: 1.4; } - /* Firefox (uncomment to work in Firefox, although other properties will not work!) */ /** { scrollbar-width: thin; @@ -100,29 +94,29 @@ h5 { } *::-webkit-scrollbar-track { border-radius: 5px; - background-color: #B8C0C2; + background-color: #b8c0c2; } *::-webkit-scrollbar-track:hover { - background-color: #B8C0C2; + background-color: #b8c0c2; } *::-webkit-scrollbar-track:active { - background-color: #B8C0C2; + background-color: #b8c0c2; } *::-webkit-scrollbar-thumb { border-radius: 10px; - background-color: #1D1E75; - border: 2px solid #0B3A86; + background-color: #1d1e75; + border: 2px solid #0b3a86; } *::-webkit-scrollbar-thumb:hover { - background-color: #1916A3; + background-color: #1916a3; } *::-webkit-scrollbar-thumb:active { - background-color: #1B2AA3; + background-color: #1b2aa3; } body { @@ -130,7 +124,7 @@ body { justify-content: center; align-items: center; min-height: 100vh; - background-color: #d9dbe6; + background-color: #000000; font-family: "Poppins", sans-serif; font-size: 1.6; @@ -138,7 +132,7 @@ body { } .player { - height: 90vh; + height: 90vh; padding: 20px 14px 8px 14px; border: none; border-top-left-radius: 15px; @@ -147,26 +141,25 @@ body { flex-direction: column; background-color: #f1f4f5; justify-content: space-evenly; - } .search-box { width: 50vh; height: 90vh; - max-height: 90vh; + max-height: 90vh; padding: 20px 14px 8px 14px; border: none; border-top-right-radius: 15px; border-bottom-right-radius: 15px; - background-color:#e8ecef; + background-color: #e8ecef; display: flex; flex-direction: column; } -.st p{ +.st p { font-size: xx-large; } -.imgBx{ +.imgBx { display: flex; justify-content: center; align-items: center; @@ -178,7 +171,8 @@ body { border: none; border-radius: 10px; align-items: center; - box-shadow: rgba(0, 0, 0, 0.25) 0px 14px 28px, rgba(0, 0, 0, 0.22) 0px 10px 10px; + box-shadow: rgba(0, 0, 0, 0.25) 0px 14px 28px, + rgba(0, 0, 0, 0.22) 0px 10px 10px; } .player audio { @@ -249,8 +243,6 @@ li { margin-top: 10px; } - - input[type="range"] { color: #3a86ff; --thumb-height: 1.125em; @@ -289,14 +281,14 @@ input[type="range"] { border-radius: 50%; width: 40px; height: 40px; - margin-top: 10px; + margin-top: 10px; } #next, #previous { width: 50px; height: 50px; - margin-top: 15px; + margin-top: 15px; } #seekForward, @@ -306,13 +298,13 @@ input[type="range"] { border-radius: 50%; width: 40px; height: 40px; - margin-top: 19px; + margin-top: 19px; } .btn-cntrl { display: flex; flex-direction: row; - gap: 5px + gap: 5px; } .ui { @@ -334,7 +326,6 @@ input[type="range"] { align-items: center; } - .songresult { display: flex; align-items: center; @@ -387,7 +378,6 @@ input[type="range"] { } } - input[type="range"] { position: relative; background: #fff0; @@ -422,23 +412,27 @@ input[type="range"]::-webkit-slider-thumb { --clip-top: calc((var(--thumb-height) - var(--track-height)) * 0.5 - 0.5px); --clip-bottom: calc(var(--thumb-height) - var(--clip-top)); --clip-further: calc(100% + 1px); - --box-fill: calc(-100vmax - var(--thumb-width, var(--thumb-height))) 0 0 100vmax currentColor; + --box-fill: calc(-100vmax - var(--thumb-width, var(--thumb-height))) 0 0 + 100vmax currentColor; width: var(--thumb-width, var(--thumb-height)); - background: linear-gradient(currentColor 0 0) scroll no-repeat left center / 50% calc(var(--track-height) + 1px); + background: linear-gradient(currentColor 0 0) scroll no-repeat left center / + 50% calc(var(--track-height) + 1px); background-color: currentColor; box-shadow: var(--box-fill); border-radius: var(--thumb-width, var(--thumb-height)); filter: brightness(100%); - clip-path: polygon(100% -1px, - var(--clip-edges) -1px, - 0 var(--clip-top), - -100vmax var(--clip-top), - -100vmax var(--clip-bottom), - 0 var(--clip-bottom), - var(--clip-edges) 100%, - var(--clip-further) var(--clip-further)); + clip-path: polygon( + 100% -1px, + var(--clip-edges) -1px, + 0 var(--clip-top), + -100vmax var(--clip-top), + -100vmax var(--clip-bottom), + 0 var(--clip-bottom), + var(--clip-edges) 100%, + var(--clip-further) var(--clip-further) + ); } input[type="range"]:hover::-webkit-slider-thumb { @@ -452,7 +446,8 @@ input[type="range"]:active::-webkit-slider-thumb { } input[type="range"]::-webkit-slider-runnable-track { - background: linear-gradient(var(--track-color) 0 0) scroll no-repeat center / 100% calc(var(--track-height) + 1px); + background: linear-gradient(var(--track-color) 0 0) scroll no-repeat center / + 100% calc(var(--track-height) + 1px); } input[type="range"]:disabled::-webkit-slider-thumb { @@ -521,11 +516,10 @@ input[type="range"]:disabled::-moz-range-thumb { cursor: not-allowed; } -#get{ -background-color: #5773ff; +#get { + background-color: #5773ff; } - .btn-cntrl button, #get, .result-item { @@ -546,23 +540,22 @@ background-color: #5773ff; box-shadow: 0 0 5px rgba(0, 0, 0, 0.5); } -.box{ +.box { gap: 10px; } -#song{ +#song { width: 70%; } -.name{ +.name { width: 300px; } - -@media(max-width: 1450px) { +@media (max-width: 1450px) { .player { width: 50vh; - height: 80vh; + height: 80vh; padding: 20px 14px 8px 14px; border: none; border-top-left-radius: 15px; @@ -576,21 +569,21 @@ background-color: #5773ff; .search-box { width: 35vh; height: 80vh; - max-height: 90vh; + max-height: 90vh; padding: 20px 14px 8px 14px; border: none; border-top-right-radius: 15px; border-bottom-right-radius: 15px; - background-color:#e8ecef; + background-color: #e8ecef; display: flex; flex-direction: column; } } -@media(max-width: 1200px) { +@media (max-width: 1200px) { .player { width: 40vh; - height: 60vh; + height: 60vh; padding: 20px 14px 8px 14px; border: none; border-top-left-radius: 15px; @@ -604,18 +597,18 @@ background-color: #5773ff; .search-box { width: 30vh; height: 60vh; - max-height: 90vh; + max-height: 90vh; padding: 20px 14px 8px 14px; border: none; border-top-right-radius: 15px; border-bottom-right-radius: 15px; - background-color:#e8ecef; + background-color: #e8ecef; display: flex; flex-direction: column; } } -@media(max-width: 980px) { +@media (max-width: 980px) { .ui { width: 100vw; padding: 5vh 4vw; @@ -635,8 +628,9 @@ background-color: #5773ff; border-bottom-left-radius: 15px; border-top-right-radius: 0px; } - - .player, .search-box { + + .player, + .search-box { height: 600px; width: 40vh; width: 100%; diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 3706019..ffb5584 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -4,178 +4,225 @@ import "react-h5-audio-player/lib/styles.css"; import "./App.css"; import axios from "axios"; import he from "he"; +import SearchResultPage from "./Pages/SearchResultPage"; const App = () => { - const [data, setData] = useState(null); - const [searchQuery, setSearchQuery] = useState(""); - const [totalTime, setTotalTime] = useState(0); - const [timePassed, setTimePassed] = useState(0); - const [currplaying, setCurrplaying] = useState(0); - - const decodeEntities = (str) => { - return he.decode(str); - }; + const [data, setData] = useState(null); + const [searchQuery, setSearchQuery] = useState(""); + const [totalTime, setTotalTime] = useState(0); + const [timePassed, setTimePassed] = useState(0); + const [currplaying, setCurrplaying] = useState(0); - const fetchSongData = async () => { - try { - const response = await axios.get(import.meta.env.VITE_BACKEND_URL, { - params: { song: searchQuery }, - }); - setData(response.data); - } catch (error) { - console.error(error); - } - }; + const decodeEntities = (str) => { + return he.decode(str); + }; - // Function to shuffle the playlist - const shufflePlaylist = () => { - if (data) { - const shuffledData = [...data]; - for (let i = shuffledData.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [shuffledData[i], shuffledData[j]] = [ - shuffledData[j], - shuffledData[i], - ]; - } - setData(shuffledData); - setCurrplaying(0); - } - }; + // OFr Development Mode + // const fetchSongData = async () => { + // try { + // const response = await axios.get( + // `${import.meta.env.VITE_BACKEND_URL}search`, + // { + // params: { song: searchQuery }, + // } + // ); + // console.log(response.data); + // setData(response.data); + // } catch (error) { + // console.error(error); + // } + // }; - const nextPlay = () => { - setCurrplaying(currplaying + 1 >= data.length ? 0 : currplaying + 1); - }; + // For Produiction mode + const fetchSongData = async () => { + try { + const response = await axios.get(import.meta.env.VITE_BACKEND_URL, { + params: { song: searchQuery }, + }); + setData(response.data); + } catch (error) { + console.error(error); + } + }; + + // Function to shuffle the playlist + const shufflePlaylist = () => { + if (data) { + const shuffledData = [...data]; + for (let i = shuffledData.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [shuffledData[i], shuffledData[j]] = [shuffledData[j], shuffledData[i]]; + } + setData(shuffledData); + setCurrplaying(0); + } + }; + + const nextPlay = () => { + setCurrplaying(currplaying + 1 >= data.length ? 0 : currplaying + 1); + }; + + const previousPlay = () => { + setCurrplaying(currplaying - 1 < 0 ? data.length - 1 : currplaying - 1); + }; - const previousPlay = () => { - setCurrplaying(currplaying - 1 < 0 ? data.length - 1 : currplaying - 1); + const playSong = (index) => { + setCurrplaying(index); + }; + + const [currentPage, setCurrentPage] = useState(""); + + useEffect(() => { + // Listen for changes in the URL + const handleRouteChange = () => { + const path = window.location.pathname; + setCurrentPage(path); }; - const playSong = (index) => { - setCurrplaying(index); + // Add event listener for route changes + window.addEventListener("popstate", handleRouteChange); + + // Initial route setup + handleRouteChange(); + + // Cleanup + return () => { + window.removeEventListener("popstate", handleRouteChange); }; + }, []); + console.log(data); + if (currentPage === "/search") { + return ; + } else { return ( + <> +
-
-
- {data && data.length > 0 ? ( - - ) : ( - "Choose a song to play" - )} -
-
    -
  • - {data && - data.length > 0 && - data[currplaying] && - decodeEntities(data[currplaying].name)} -
  • -
  • - {data && - data.length > 0 && - data[currplaying] && - decodeEntities(data[currplaying].artist)}{" "} - {data && - data.length > 0 && - data[currplaying] && - data[currplaying].year} -
  • -
- {data && ( - { - console.log("Error :", error); - }} - /> - )} +
+
+ {data && data.length > 0 ? ( + + ) : ( + "Choose a song to play" + )} +
+
    +
  • + {data && + data.length > 0 && + data[currplaying] && + decodeEntities(data[currplaying].name)} +
  • +
  • + {data && + data.length > 0 && + data[currplaying] && + decodeEntities(data[currplaying].artist)}{" "} + {data && + data.length > 0 && + data[currplaying] && + data[currplaying].year} +
  • +
+ {data && ( + { + console.log("Error :", error); + }} + /> + )} +
+ +
+
+
+ { + e.preventDefault(); + setSearchQuery(e.target.value); + }} + /> + + +
-
-
-
- { - e.preventDefault(); - setSearchQuery(e.target.value); - }} - /> - - -
-
- -
- {data !== null && - data !== undefined && - data.map((element, index) => ( -
playSong(index)} - > -
- {element.name} -
-

- {decodeEntities(element.name)} -

-

- {decodeEntities(element.artist)} -{" "} - {element.year} -

-
-
-
- ))} -
+
+ {data !== null && + data !== undefined && + data.map((element, index) => ( +
playSong(index)} + > +
+ {element.name} +
+

{decodeEntities(element.name)}

+

+ {decodeEntities(element.artist)} - {element.year} +

+
+
+
+ ))}
+
- //{" "} - //
+ ); + } }; export default App; diff --git a/frontend/src/Pages/SearchResultPage.jsx b/frontend/src/Pages/SearchResultPage.jsx new file mode 100644 index 0000000..07d55a2 --- /dev/null +++ b/frontend/src/Pages/SearchResultPage.jsx @@ -0,0 +1,117 @@ +import axios from "axios"; +import React, { useEffect, useState } from "react"; +import "./Style.css"; +import Sidebar from "../components/Share_UI/Sidebar"; +import Header from "../components/Share_UI/Header"; +import MusicCard from "../components/Share_UI/MusicCard"; +import { CircleDashed } from "phosphor-react"; + +const SearchResultPage = () => { + const [data, setData] = useState([]); + const [loading, setloading] = useState(false); + const [currentSongUrl, setCurrentSongUrl] = useState(null); + const [audio, setAudio] = useState(null); + const [audioid, setAudioid] = useState(null); + const [searchQuery, setSearchQuery] = useState(""); + const [toggleSidebar, settoggleSidebar] = useState(false); + + // For the Developement mode + // const fetchSongData = async () => { + // settoggleSidebar(false); + // setloading(true); + // try { + // const response = await axios.get( + // `${import.meta.env.VITE_BACKEND_URL}search`, + // { + // params: { song: searchQuery }, + // } + // ); + // setData(response.data); + // } catch (error) { + // console.error(error); + // } + // setloading(false); + // }; + + // For Produiction mode + const fetchSongData = async () => { + try { + const response = await axios.get(import.meta.env.VITE_BACKEND_URL, { + params: { song: searchQuery }, + }); + setData(response.data); + } catch (error) { + console.error(error); + } + }; + + const handlePlay = (songUrl, songId) => { + if (audioid == songId) { + setAudioid(null); + } else { + setAudioid(songId); + } + + if (currentSongUrl === songUrl && audio) { + if (audio.paused) { + audio.play(); + } else { + audio.pause(); + } + } else { + if (audio) { + audio.pause(); // Pause the current audio + } + const newAudio = new Audio(songUrl); + console.log(newAudio); + newAudio.play(); + setAudio(newAudio); + setCurrentSongUrl(songUrl); + } + }; + + return ( +
+
+
+ +
+ + +
+
+ +
+

Search Result

+
+ {data.length > 0 ? ( + data?.map((song) => ( + handlePlay(song.url, song.id)} + /> + )) + ) : loading ? ( +
+ +
+ ) : ( +

No Song

+ )} +
+
+
+
+
+ ); +}; + +export default SearchResultPage; diff --git a/frontend/src/Pages/Style.css b/frontend/src/Pages/Style.css new file mode 100644 index 0000000..2b01283 --- /dev/null +++ b/frontend/src/Pages/Style.css @@ -0,0 +1,111 @@ +.main { + position: relative; + width: 100vw; + height: 100vh; + color: #fff !important; + overflow-x: hidden; +} + +.gradient { + width: 800px; + height: 0px; + color: #fff; + position: absolute; + left: 0; + top: 50%; + transform: rotate(20deg); + -webkit-box-shadow: 0px 0px 300px 53px rgba(255, 46, 252, 0.849); + -moz-box-shadow: 0px 0px 300px 53px rgba(255, 46, 252, 0.936); + box-shadow: 0px 0px 300px 153px rgb(248, 11, 244); + z-index: 2; +} + +.blue { + width: 1000px; + top: 40%; + transform: rotate(25deg); + z-index: 1; + -webkit-box-shadow: 0px 0px 300px 53px rgba(46, 81, 255, 0.475); + -moz-box-shadow: 0px 0px 300px 53px rgba(46, 98, 255, 0.295); + box-shadow: 0px 0px 300px 103px rgba(46, 49, 255, 0.65); +} + +.content { + width: 100%; + height: 100%; + position: fixed; + inset: 0; + z-index: 4; + display: flex; +} + +/* Hro Section */ + +.hero { + padding: 0 10px; + width: 100%; + height: 100%; +} + +/* search-content */ + +.search-content { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + padding-bottom: 20px; +} +.search-content h1 { + font-size: 30px; + color: #fff; + font-weight: 600; + margin-bottom: 20px; +} + +.result-grid { + position: relative; + width: 100%; + height: 80%; + display: flex; + flex-wrap: wrap; + gap: 30px; + justify-content: space-between; + align-items: flex-start; + padding: 10px 20px; + overflow-y: scroll; + background: #0000007b; + backdrop-filter: blur(20px); + border: 1px solid #ffffff45; + border-radius: 28px; +} +.result-grid .loading, +.no { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} +.loading .i { + animation: c 3s infinite linear; + font-size: 50px; +} + +@keyframes c { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +.result-grid::-webkit-scrollbar { + display: none; +} +@media screen and (max-width: 500px) { + .result-grid { + justify-content: center; + align-items: center; + } +} diff --git a/frontend/src/components/Share_UI/Header.jsx b/frontend/src/components/Share_UI/Header.jsx new file mode 100644 index 0000000..7daede3 --- /dev/null +++ b/frontend/src/components/Share_UI/Header.jsx @@ -0,0 +1,30 @@ +import React from "react"; +import "./Style.css"; +import { + BellSimpleRinging, + CaretLeft, + CaretRight, + List, + UserCircle, +} from "phosphor-react"; +export default function Header({ settoggleSidebar }) { + return ( +
+
+ + +
+ +
+ + + { + settoggleSidebar((prev) => !prev); + }} + /> +
+
+ ); +} diff --git a/frontend/src/components/Share_UI/MusicCard.jsx b/frontend/src/components/Share_UI/MusicCard.jsx new file mode 100644 index 0000000..0e7d8ff --- /dev/null +++ b/frontend/src/components/Share_UI/MusicCard.jsx @@ -0,0 +1,30 @@ +import React from "react"; +import "./Style.css"; +import { Pause, Play } from "phosphor-react"; + +const MusicCard = ({ song, isPlaying, handlePlay }) => { + return ( +
+ name +
+
+

+ {song?.name.length > 20 + ? song.name.substring(0, 20) + "..." + : song.name} +

+ + {song.artist.length > 20 + ? song.artist.substring(0, 20) + "..." + : song.artist} + +
+ +
+
+ ); +}; + +export default MusicCard; diff --git a/frontend/src/components/Share_UI/Sidebar.jsx b/frontend/src/components/Share_UI/Sidebar.jsx new file mode 100644 index 0000000..67047cb --- /dev/null +++ b/frontend/src/components/Share_UI/Sidebar.jsx @@ -0,0 +1,105 @@ +import React from "react"; +import "./Style.css"; +import { + MagnifyingGlass, + House, + Image, + MusicNotesPlus, + SmileyWink, + Playlist, + Trash, + X, +} from "phosphor-react"; +const data = [ + { + heading: "Menu", + data: [ + { + icon: , + text: "Home", + }, + ], + }, + { + heading: "LIBRARY", + data: [ + { + icon: , + text: "Albums", + }, + { + icon: , + text: "Songs", + }, + { + icon: , + text: "Artist", + }, + ], + }, + { + heading: "PLAYLIST", + data: [ + { + icon: , + text: "Playlist1", + deleteicon: , + }, + { + icon: , + text: "Playlist2", + deleteicon: , + }, + ], + }, +]; +export default function Sidebar({ + fetchSongData, + searchQuery, + setSearchQuery, + toggleSidebar, + settoggleSidebar, +}) { + const handleSearch = (e) => { + if (e.code === "Enter") { + fetchSongData(); + } + }; + return ( +
+ { + settoggleSidebar((prev) => !prev); + }} + /> + +
+
+ + setSearchQuery(e.target.value)} + value={searchQuery} + onKeyDown={handleSearch} + type="text" + placeholder="Search..." + /> +
+
+
+ {data.map((ele) => ( +
+

{ele.heading}

+ {ele.data.map((el) => ( +
+ {el.icon} + {el.text} + {el?.deleteicon && el?.deleteicon} +
+ ))} +
+ ))} +
+
+ ); +} diff --git a/frontend/src/components/Share_UI/Style.css b/frontend/src/components/Share_UI/Style.css new file mode 100644 index 0000000..9cd262d --- /dev/null +++ b/frontend/src/components/Share_UI/Style.css @@ -0,0 +1,192 @@ +.sidebar { + width: 250px; + border-right: 2px solid #848484d3; + height: 100%; + background: #4141415e; + backdrop-filter: blur(20px); + display: flex; + justify-content: flex-start; + align-items: flex-start; + flex-direction: column; + padding: 40px 5px; + gap: 30%; + color: #fff !important; +} + +.search { + width: 100%; + position: relative; +} + +.search-container .search-icon { + position: absolute; + top: 50%; + left: 3%; + transform: translateY(-50%); +} + +.search-container input { + width: 100%; + height: 30px; + background: transparent; + padding: 23px; + border: 1px solid #fff; + outline: none; + border-radius: 16px; + color: #fff; + padding-left: 18%; +} + +.menu { + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + gap: 15px; + color: #fff; + padding: 10px; +} + +.menu h1 { + color: #ffffffa2; + font-size: 20px; + margin: 10px 0; +} +.menu .menu-card { + width: 100%; +} + +.menu .menu-icons { + width: 100%; + display: flex; + justify-content: flex-start; + align-items: center; + gap: 10px; + margin: 5px 0; + cursor: pointer; +} + +.menu .menu-icons span { + font-size: 17px; + width: 70%; + color: #ffffffc7; +} +.i { + color: #ffffffb9; + transition: all 0.4s ease; + font-size: 22px; +} +.menu .menu-icons:hover > .i { + color: rgb(255, 255, 255); +} + +.menu .menu-icons:hover > span { + color: rgb(255, 255, 255); +} + +/* Header + */ + +.header { + width: 100%; + padding: 30px 0; + display: flex; + justify-content: space-between; + align-items: center; +} + +.header-icons { + display: flex; + justify-content: center; + align-items: center; + gap: 10px; +} + +.header-icons .i { + font-size: 40px; + background: #ffffff59; + padding: 5px; + border-radius: 50%; +} + +.music-card { + width: 200px; + height: 250px; +} + +.music-card img { + width: 200px; + height: 200px; + object-fit: cover; + border-radius: 10px; + margin: 0 auto; +} + +.music-card .song-details { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 2px; + padding: 2px 5px; +} + +.music-card .song-details .text p { + font-size: 15px; +} +.music-card .song-details .text span { + font-size: 14px; + color: #ffffff96; +} + +.music-card .song-details .i { + font-size: 40px; + background: rgb(212, 1, 212); + padding: 8px; + border: 0.5px solid #ffffff5e; + border-radius: 100%; + color: #000000; + font-weight: 800; + backdrop-filter: blur(30px); +} +.music-card .song-details .i:hover { + color: #ffffff; +} + +.hambergure { + display: none; +} + +.close { + position: absolute; + right: 5%; + top: 7.3%; + font-size: 33px; + display: none; +} + +@media screen and (max-width: 700px) { + .sidebar { + position: absolute; + z-index: 5; + width: 100%; + left: -100%; + transition: all 0.5s ease; + } + .search { + width: 70%; + } + .menu { + width: 70%; + margin: 0 auto; + } + .hambergure { + display: block; + } + .sidebar--active { + left: 0; + } + .close { + display: block; + } +}