diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6f6cd89..d4b9b9f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,6 +28,20 @@ cd BeatBridge npm install ``` +- Setup Environment Variables + - Create a file `.env.local` in the root directory. + - Go to [Spotify Dashboard](https://developer.spotify.com/dashboard) and Login into your Spotify Account. + - Create an App and fill the required details like Name, Description, Website + - Make sure to add the Redirect URI to `https://localhost:5173` and check the following API + ![image](https://github.com/pooranjoyb/BeatBridge/assets/90945182/0b2e568e-20de-40bd-9f7f-b48740a1a2d4) + - Save the Details, Click on the App you just created and go to `Settings` + - Copy your `CLIENT_ID` and `CLIENT_SECRET` + - Add the following in the `.env.local` file. + - ```bash + VITE_CLIENT_ID=your_client_id + VITE_CLIENT_SECRET=your_client_secret + ``` + - Start the development server: ```bash diff --git a/README.md b/README.md index e624cec..41043e9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ # BeatBridge - A Music Player with a Recommendation Engine 🚀 +![Open Source](https://img.shields.io/badge/Open%20Source-Yes-brightgreen.svg) +![React](https://img.shields.io/badge/React-^18.2.0-blue.svg) +![Tailwind CSS](https://img.shields.io/badge/Tailwind%20CSS-^2.2.19-38B2AC.svg) +![License](https://img.shields.io/badge/License-MIT-brightgreen.svg) -This Web App is a dedicated application that'll use Spotify API to Fetch Songs and play 'em in the interactive GUI. - +This Web App is a dedicated application that'll use Spotify API to Fetch Songs and play them in the interactive GUI. It Utilizes Spotify API to fetch songs and an interactive GUI for is there for playing music with a recommendation Engine for suggesting songs.
@@ -21,11 +24,14 @@ This Web App is a dedicated application that'll use Spotify API to Fetch Songs a
- -![Open Source](https://img.shields.io/badge/Open%20Source-Yes-brightgreen.svg) -![React](https://img.shields.io/badge/React-^18.2.0-blue.svg) -![Tailwind CSS](https://img.shields.io/badge/Tailwind%20CSS-^2.2.19-38B2AC.svg) -![License](https://img.shields.io/badge/License-MIT-brightgreen.svg) + +
+ +#### Join Official Discord Server + + + +
## Table of Contents - [BeatBridge Introduction](#beatbridge---a-music-player-with-a-recommendation-engine-🚀) diff --git a/src/App.css b/src/App.css index 0149620..3bfc42f 100644 --- a/src/App.css +++ b/src/App.css @@ -1,8 +1,14 @@ -@import url("https://fonts.googleapis.com/css2?family=Jost&display=swap"); +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400&family=Raleway:wght@300&display=swap'); + @tailwind base; @tailwind components; @tailwind utilities; body{ overflow-x: hidden; + font-family: 'Raleway', sans-serif; +} + +input:focus{ + outline: none; } \ No newline at end of file diff --git a/src/Components/Features.jsx b/src/Components/Features.jsx index 99bbaba..5293887 100644 --- a/src/Components/Features.jsx +++ b/src/Components/Features.jsx @@ -51,14 +51,14 @@ export default function Features() { >
-

+

Ready to make some noise?

-
+
Bringing Harmony to Your Ears.
-
+
); -} +} \ No newline at end of file diff --git a/src/Components/Home.jsx b/src/Components/Home.jsx index 10dcc79..d0ea61d 100644 --- a/src/Components/Home.jsx +++ b/src/Components/Home.jsx @@ -5,6 +5,7 @@ import PageThree from "./PageThree"; import Features from "./Features"; import Navbar from "./Navbar"; import Footer from "./Footer"; +import { Link } from "react-router-dom"; export default function Home() { const animationControls = { @@ -19,10 +20,8 @@ export default function Home() { (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { - // When the section is in the viewport, trigger the animation animationControls.visible && sectionControls.start("visible"); } else { - // When the section is out of the viewport, reset the animation animationControls.hidden && sectionControls.start("hidden"); } }); @@ -30,8 +29,8 @@ export default function Home() { { root: null, rootMargin: "0px", - threshold: 0.5, // Adjust the threshold as needed - } + threshold: 0.5, + }, ); if (sectionRef.current) { @@ -47,23 +46,22 @@ export default function Home() { const sectionControls = useAnimation(); - return ( <> -
+ +
background img
-

Your Gateway to a World of Rhythm @@ -71,9 +69,11 @@ export default function Home() {

Welcome to BeatBridge!

- + + +
diff --git a/src/Components/Navbar.jsx b/src/Components/Navbar.jsx index e6207f1..58174e9 100644 --- a/src/Components/Navbar.jsx +++ b/src/Components/Navbar.jsx @@ -19,7 +19,7 @@ export default function Navbar() { return ( <> -
+

@@ -96,6 +96,4 @@ export default function Navbar() {

) -} - - +} \ No newline at end of file diff --git a/src/Components/PageThree.jsx b/src/Components/PageThree.jsx index 51718bc..a826cb0 100644 --- a/src/Components/PageThree.jsx +++ b/src/Components/PageThree.jsx @@ -45,7 +45,7 @@ export default function PageThree() { return (
@@ -119,4 +119,4 @@ export default function PageThree() { src={page3} alt="bg img" className="absolute right-0 w-50 top-28" style={{ zIndex: 1, filter: 'invert(1)' }} />
); -} +} \ No newline at end of file diff --git a/src/Components/Player.jsx b/src/Components/Player.jsx index 6651973..4727fb1 100644 --- a/src/Components/Player.jsx +++ b/src/Components/Player.jsx @@ -3,6 +3,14 @@ import "../App.css"; import Background from "/bag.jpg"; import Navbar from "./Navbar"; import Footer from "./Footer"; +// import Search from '../assets/search.svg'; +import HeartFill from '../assets/heart-fill.svg'; +import Pause from '../assets/pause.svg'; +import Repeat from '../assets/repeat.svg'; +import Shuffle from '../assets/shuffle.svg'; +import Previous from '../assets/previous.svg'; +import Next from '../assets/next.svg'; +import FullScreen from '../assets/full-screen.svg' export default function Player({ accessToken }) { const [searchInput, setSearchInput] = useState(""); @@ -108,130 +116,49 @@ export default function Player({ accessToken }) { })}
-
-
- Album Pic -
-
-
-
-

- A Sky Full of Stars -

-

Ghost Stories

-
-
- - - -
-
- - - -
-
- - - -
+
+
+
+

Shape of You

+ + +
+ +
+
- -
-
- - - -
-
- - - -
-
- - - -
-
- - - -
-
- - - +
+

Ed Sheeran

+
+ {clock.toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + hour12: true, + })}
-
-

0:40

-

4:20

+
+
+
+
+
+
+

02:00

+

04:00

+
+ + +
+ +
+ + +
-
diff --git a/src/Components/SongSearch.jsx b/src/Components/SongSearch.jsx new file mode 100644 index 0000000..5a8dbe0 --- /dev/null +++ b/src/Components/SongSearch.jsx @@ -0,0 +1,111 @@ +import { useEffect, useState } from "react"; +import "../App.css"; +import Background from "/bag.jpg"; +import Search from '../assets/search.svg'; +import Navbar from "./Navbar"; +import Footer from "./Footer"; + +import API_Controller from "../../utils/API_Controller"; + +export default function SongSearch() { + const [searchInput, setSearchInput] = useState("Trending"); + const [token, setToken] = useState('') + const [tracks, setTracks] = useState([]); + + const clientID = import.meta.env.VITE_CLIENT_ID; + const secret = import.meta.env.VITE_CLIENT_SECRET; + + const user = new API_Controller(clientID, secret) + + useEffect(() => { + user?.getToken().then((data) => { + setToken(data) + }) + console.log("Set token ran") + }, []) + + useEffect(() => { + getTracks(); + console.log("tracks") + }, []) + + const getTracks = async () => { + try { + await user.searchSong(searchInput, token).then((data) => { + setTracks(data.tracks.items) + }).catch((err) => { + console.log("Fetch Failed " + err) + }) + } catch (err) { + console.log(err) + } + } + + return ( + <> +
+ +
+
+ setSearchInput(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') + getTracks(); + }} + /> + +
+
+ { + tracks.map((elem, index) => { + return ( +
+
+ Album Image +
+ + + + + +
+
+
+

{elem.album.name}

+

{elem.artists[0].name}

+
+
+ ) + }) + } + + +
+ +
+
+
+ + ); +} diff --git a/src/assets/full-screen.svg b/src/assets/full-screen.svg new file mode 100644 index 0000000..4431543 --- /dev/null +++ b/src/assets/full-screen.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/assets/heart-fill.svg b/src/assets/heart-fill.svg new file mode 100644 index 0000000..aa9da55 --- /dev/null +++ b/src/assets/heart-fill.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/heart.svg b/src/assets/heart.svg new file mode 100644 index 0000000..fdc2e54 --- /dev/null +++ b/src/assets/heart.svg @@ -0,0 +1,19 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/next.svg b/src/assets/next.svg new file mode 100644 index 0000000..4ac494f --- /dev/null +++ b/src/assets/next.svg @@ -0,0 +1,19 @@ + + + + + next [#998] + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/pause.svg b/src/assets/pause.svg new file mode 100644 index 0000000..e8c03c5 --- /dev/null +++ b/src/assets/pause.svg @@ -0,0 +1,19 @@ + + + + + pause [#1006] + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/play.svg b/src/assets/play.svg new file mode 100644 index 0000000..b076268 --- /dev/null +++ b/src/assets/play.svg @@ -0,0 +1,19 @@ + + + + + play [#1000] + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/previous.svg b/src/assets/previous.svg new file mode 100644 index 0000000..942bc27 --- /dev/null +++ b/src/assets/previous.svg @@ -0,0 +1,19 @@ + + + + + previous [#999] + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/repeat.svg b/src/assets/repeat.svg new file mode 100644 index 0000000..7f8f4a4 --- /dev/null +++ b/src/assets/repeat.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/assets/search.svg b/src/assets/search.svg new file mode 100644 index 0000000..d38a17c --- /dev/null +++ b/src/assets/search.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/assets/shuffle.svg b/src/assets/shuffle.svg new file mode 100644 index 0000000..e693b56 --- /dev/null +++ b/src/assets/shuffle.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main.jsx b/src/main.jsx index 0f3f1a0..c8826e2 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -2,6 +2,7 @@ import React from "react"; import App from "./App.jsx"; import Home from "./Components/Home.jsx"; import ReactDOM from "react-dom/client"; +import SongSearch from "./Components/SongSearch.jsx"; import { createBrowserRouter, RouterProvider } from "react-router-dom"; import "./index.css"; import "./App.css"; @@ -15,6 +16,10 @@ const MyApp = createBrowserRouter([ path: "/player", element: , }, + { + path: "/search", + element: , + }, ]); ReactDOM.createRoot(document.getElementById("root")).render( diff --git a/src/tailwindcss/output.css b/src/tailwindcss/output.css index eb08161..18cd84a 100644 --- a/src/tailwindcss/output.css +++ b/src/tailwindcss/output.css @@ -1,4 +1,4 @@ -@import url("https://fonts.googleapis.com/css2?family=Jost&display=swap"); +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400&family=Raleway:wght@300&display=swap'); /* ! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com @@ -536,6 +536,10 @@ video { --tw-backdrop-sepia: ; } +.visible{ + visibility: visible; +} + .fixed{ position: fixed; } @@ -580,8 +584,22 @@ video { z-index: 50; } -.m-2{ - margin: 0.5rem; +.z-\[60\]{ + z-index: 60; +} + +.m-10{ + margin: 2.5rem; +} + +.mx-2{ + margin-left: 0.5rem; + margin-right: 0.5rem; +} + +.mx-3{ + margin-left: 0.75rem; + margin-right: 0.75rem; } .mx-auto{ @@ -589,6 +607,26 @@ video { margin-right: auto; } +.my-3{ + margin-top: 0.75rem; + margin-bottom: 0.75rem; +} + +.my-5{ + margin-top: 1.25rem; + margin-bottom: 1.25rem; +} + +.my-6{ + margin-top: 1.5rem; + margin-bottom: 1.5rem; +} + +.my-8{ + margin-top: 2rem; + margin-bottom: 2rem; +} + .mb-2{ margin-bottom: 0.5rem; } @@ -605,6 +643,10 @@ video { margin-left: 6rem; } +.ml-3{ + margin-left: 0.75rem; +} + .mr-2{ margin-right: 0.5rem; } @@ -613,36 +655,28 @@ video { margin-top: 0.25rem; } -.mt-20{ - margin-top: 5rem; +.mt-10{ + margin-top: 2.5rem; } -.mt-48{ - margin-top: 12rem; +.mt-16{ + margin-top: 4rem; } -.mt-5{ - margin-top: 1.25rem; +.mt-20{ + margin-top: 5rem; } -.mt-8{ - margin-top: 2rem; +.mt-48{ + margin-top: 12rem; } .mt-\[-2\%\]{ margin-top: -2%; } -.mt-12{ - margin-top: 3rem; -} - -.mt-3{ - margin-top: 0.75rem; -} - -.mt-32{ - margin-top: 8rem; +.block{ + display: block; } .inline{ @@ -661,10 +695,26 @@ video { display: none; } +.h-10{ + height: 2.5rem; +} + .h-12{ height: 3rem; } +.h-16{ + height: 4rem; +} + +.h-28{ + height: 7rem; +} + +.h-3{ + height: 0.75rem; +} + .h-6{ height: 1.5rem; } @@ -677,26 +727,34 @@ video { height: 2rem; } +.h-\[800px\]{ + height: 800px; +} + .h-full{ height: 100%; } -.h-screen{ - height: 100vh; +.min-h-screen{ + min-height: 100vh; } -.h-\[800px\]{ - height: 800px; +.w-10{ + width: 2.5rem; } -.h-\[1000px\]{ - height: 1000px; +.w-10\/12{ + width: 83.333333%; } .w-12{ width: 3rem; } +.w-2\/3{ + width: 66.666667%; +} + .w-6{ width: 1.5rem; } @@ -713,14 +771,30 @@ video { width: 100%; } -.w-\[50rem\]{ - width: 50rem; +.w-\[27\%\]{ + width: 27%; } .w-full{ width: 100%; } +.w-1\/3{ + width: 33.333333%; +} + +.w-1\/5{ + width: 20%; +} + +.w-2\/5{ + width: 40%; +} + +.w-1\/4{ + width: 25%; +} + .translate-x-0{ --tw-translate-x: 0px; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -731,6 +805,11 @@ video { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } +.translate-y-3{ + --tw-translate-y: 0.75rem; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + .transform{ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } @@ -743,6 +822,10 @@ video { list-style-type: disc; } +.grid-cols-1{ + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + .flex-row{ flex-direction: row; } @@ -751,10 +834,6 @@ video { flex-direction: column; } -.place-items-center{ - place-items: center; -} - .items-center{ align-items: center; } @@ -771,10 +850,22 @@ video { justify-content: space-between; } +.justify-around{ + justify-content: space-around; +} + +.justify-evenly{ + justify-content: space-evenly; +} + .gap-16{ gap: 4rem; } +.gap-4{ + gap: 1rem; +} + .gap-\[2rem\]{ gap: 2rem; } @@ -783,42 +874,85 @@ video { border-radius: 0.25rem; } +.rounded-2xl{ + border-radius: 1rem; +} + .rounded-full{ border-radius: 9999px; } -.rounded-lg{ - border-radius: 0.5rem; +.rounded-xl{ + border-radius: 0.75rem; } .border{ border-width: 1px; } -.border-y-\[1px\]{ - border-top-width: 1px; - border-bottom-width: 1px; +.border-4{ + border-width: 4px; } .border-b-4{ border-bottom-width: 4px; } +.border-black{ + --tw-border-opacity: 1; + border-color: rgb(0 0 0 / var(--tw-border-opacity)); +} + +.border-gray-100{ + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); +} + +.border-rose-400{ + --tw-border-opacity: 1; + border-color: rgb(251 113 133 / var(--tw-border-opacity)); +} + .border-white{ --tw-border-opacity: 1; border-color: rgb(255 255 255 / var(--tw-border-opacity)); } +.bg-black{ + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); +} + .bg-gray-800{ --tw-bg-opacity: 1; background-color: rgb(31 41 55 / var(--tw-bg-opacity)); } +.bg-rose-300{ + --tw-bg-opacity: 1; + background-color: rgb(253 164 175 / var(--tw-bg-opacity)); +} + .bg-slate-100{ --tw-bg-opacity: 1; background-color: rgb(241 245 249 / var(--tw-bg-opacity)); } +.bg-slate-200{ + --tw-bg-opacity: 1; + background-color: rgb(226 232 240 / var(--tw-bg-opacity)); +} + +.bg-slate-300{ + --tw-bg-opacity: 1; + background-color: rgb(203 213 225 / var(--tw-bg-opacity)); +} + +.bg-stone-100{ + --tw-bg-opacity: 1; + background-color: rgb(245 245 244 / var(--tw-bg-opacity)); +} + .bg-violet-800\/60{ background-color: rgb(91 33 182 / 0.6); } @@ -828,6 +962,18 @@ video { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } +.bg-opacity-0{ + --tw-bg-opacity: 0; +} + +.bg-opacity-10{ + --tw-bg-opacity: 0.1; +} + +.bg-opacity-40{ + --tw-bg-opacity: 0.4; +} + .bg-gradient-to-r{ background-image: linear-gradient(to right, var(--tw-gradient-stops)); } @@ -838,14 +984,44 @@ video { --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); } +.from-pink-300{ + --tw-gradient-from: #f9a8d4 var(--tw-gradient-from-position); + --tw-gradient-to: rgb(249 168 212 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.from-pink-400{ + --tw-gradient-from: #f472b6 var(--tw-gradient-from-position); + --tw-gradient-to: rgb(244 114 182 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.from-pink-500{ + --tw-gradient-from: #ec4899 var(--tw-gradient-from-position); + --tw-gradient-to: rgb(236 72 153 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + .to-\[\#FBA277\]{ --tw-gradient-to: #FBA277 var(--tw-gradient-to-position); } +.to-gray-300{ + --tw-gradient-to: #d1d5db var(--tw-gradient-to-position); +} + +.to-orange-300{ + --tw-gradient-to: #fdba74 var(--tw-gradient-to-position); +} + .bg-cover{ background-size: cover; } +.bg-clip-padding{ + background-clip: padding-box; +} + .bg-center{ background-position: center; } @@ -854,6 +1030,10 @@ video { padding: 0.5rem; } +.p-3{ + padding: 0.75rem; +} + .p-4{ padding: 1rem; } @@ -866,6 +1046,11 @@ video { padding: 2rem; } +.px-1{ + padding-left: 0.25rem; + padding-right: 0.25rem; +} + .px-6{ padding-left: 1.5rem; padding-right: 1.5rem; @@ -876,8 +1061,14 @@ video { padding-bottom: 0.5rem; } -.pb-0{ - padding-bottom: 0px; +.py-3{ + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-4{ + padding-top: 1rem; + padding-bottom: 1rem; } .pb-1{ @@ -912,10 +1103,6 @@ video { padding-top: 5rem; } -.pt-6{ - padding-top: 1.5rem; -} - .text-center{ text-align: center; } @@ -924,10 +1111,6 @@ video { font-family: Jost, sans; } -.font-serif{ - font-family: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; -} - .text-2xl{ font-size: 1.5rem; line-height: 2rem; @@ -943,11 +1126,6 @@ video { line-height: 2.5rem; } -.text-5xl{ - font-size: 3rem; - line-height: 1; -} - .text-6xl{ font-size: 3.75rem; line-height: 1; @@ -968,11 +1146,6 @@ video { line-height: 1.75rem; } -.text-sm{ - font-size: 0.875rem; - line-height: 1.25rem; -} - .text-xl{ font-size: 1.25rem; line-height: 1.75rem; @@ -982,14 +1155,6 @@ video { font-weight: 700; } -.font-medium{ - font-weight: 500; -} - -.font-normal{ - font-weight: 400; -} - .tracking-tight{ letter-spacing: -0.025em; } @@ -1002,24 +1167,29 @@ video { letter-spacing: 0.025em; } +.text-\[\#5f2917\]{ + --tw-text-opacity: 1; + color: rgb(95 41 23 / var(--tw-text-opacity)); +} + .text-\[\#9a3412\]{ --tw-text-opacity: 1; color: rgb(154 52 18 / var(--tw-text-opacity)); } -.text-gray-300{ +.text-black{ --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity)); + color: rgb(0 0 0 / var(--tw-text-opacity)); } -.text-gray-500{ +.text-custom-pink{ --tw-text-opacity: 1; - color: rgb(107 114 128 / var(--tw-text-opacity)); + color: rgb(255 134 200 / var(--tw-text-opacity)); } -.text-gray-700{ +.text-gray-500{ --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity)); + color: rgb(107 114 128 / var(--tw-text-opacity)); } .text-white{ @@ -1027,6 +1197,10 @@ video { color: rgb(255 255 255 / var(--tw-text-opacity)); } +.opacity-0{ + opacity: 0; +} + .opacity-70{ opacity: 0.7; } @@ -1043,9 +1217,29 @@ video { box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } -.outline-none{ - outline: 2px solid transparent; - outline-offset: 2px; +.backdrop-blur-md{ + --tw-backdrop-blur: blur(12px); + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); +} + +.backdrop-blur-sm{ + --tw-backdrop-blur: blur(4px); + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); +} + +.backdrop-filter{ + -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); + backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); +} + +.transition{ + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; } .transition-all{ @@ -1076,15 +1270,34 @@ video { transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } -.focus-within\:shadow-lg:focus-within{ - --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +body{ + overflow-x: hidden; + font-family: 'Raleway', sans-serif; } -.hover\:bg-gray-200:hover{ +.hover\:scale-110:hover{ + --tw-scale-x: 1.1; + --tw-scale-y: 1.1; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.hover\:scale-125:hover{ + --tw-scale-x: 1.25; + --tw-scale-y: 1.25; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.hover\:rounded-full:hover{ + border-radius: 9999px; +} + +.hover\:bg-pink-400:hover{ --tw-bg-opacity: 1; - background-color: rgb(229 231 235 / var(--tw-bg-opacity)); + background-color: rgb(244 114 182 / var(--tw-bg-opacity)); +} + +.hover\:bg-gradient-to-r:hover{ + background-image: linear-gradient(to right, var(--tw-gradient-stops)); } .hover\:text-gray-700:hover{ @@ -1098,8 +1311,90 @@ video { box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } +.hover\:transition-all:hover{ + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.group:hover .group-hover\:translate-y-0{ + --tw-translate-y: 0px; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.group:hover .group-hover\:bg-opacity-60{ + --tw-bg-opacity: 0.6; +} + +.group:hover .group-hover\:opacity-100{ + opacity: 1; +} + +@media (min-width: 640px){ + .sm\:grid-cols-4{ + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .sm\:p-4{ + padding: 1rem; + } +} + @media (min-width: 768px){ - .md\:block{ - display: block; + .md\:my-0{ + margin-top: 0px; + margin-bottom: 0px; + } + + .md\:h-10{ + height: 2.5rem; + } + + .md\:h-16{ + height: 4rem; + } + + .md\:h-full{ + height: 100%; + } + + .md\:w-1\/3{ + width: 33.333333%; + } + + .md\:w-10{ + width: 2.5rem; + } + + .md\:w-16{ + width: 4rem; + } + + .md\:w-2\/3{ + width: 66.666667%; + } + + .md\:flex-row{ + flex-direction: row; + } + + .md\:text-3xl{ + font-size: 1.875rem; + line-height: 2.25rem; + } + + .md\:text-xl{ + font-size: 1.25rem; + line-height: 1.75rem; } } + +@media (min-width: 1024px){ + .lg\:h-96{ + height: 24rem; + } + + .lg\:w-2\/3{ + width: 66.666667%; + } +} \ No newline at end of file diff --git a/utils/API_Controller.js b/utils/API_Controller.js new file mode 100644 index 0000000..192d1e2 --- /dev/null +++ b/utils/API_Controller.js @@ -0,0 +1,36 @@ +class API_Controller { + + constructor(client, secret) { + this.client = client; + this.secret = secret; + } + + getToken = async() => { + const res = await fetch('https://accounts.spotify.com/api/token', { + method: 'POST', + headers:{ + 'Content-Type': 'application/x-www-form-urlencoded', + 'Authorization': 'Basic ' + btoa( this.client + ':' + this.secret) + }, + body: 'grant_type=client_credentials' + }); + + const data = await res.json(); + return data.access_token; + } + + searchSong = async(song, token) => { + + const res = await fetch(`https://api.spotify.com/v1/search?q=${song}&type=track`, { + method: 'GET', + headers:{ + 'Authorization': 'Bearer ' + token + }, + }); + + const data = await res.json(); + return data; + } +} + +export default API_Controller; \ No newline at end of file