diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..324a37d
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,3 @@
+SPOTIFY_CLIENT_ID=
+SPOTIFY_CLIENT_SECRET=
+SPOTIFY_REFRESH_TOKEN=
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 62190d7..194b389 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,4 +34,5 @@ yarn-error.log*
*.tsbuildinfo
next-env.d.ts
-.env
\ No newline at end of file
+.env
+.env.local
\ No newline at end of file
diff --git a/app/(root)/page.jsx b/app/(root)/page.jsx
index ab4628b..bb9cb4f 100644
--- a/app/(root)/page.jsx
+++ b/app/(root)/page.jsx
@@ -1,7 +1,7 @@
"use client";
import ReactFullpage from "@fullpage/react-fullpage";
import Image from "next/legacy/image";
-import "../globals.css";
+// import "../globals.css";
import { motion } from "framer-motion";
import Link from "next/link";
diff --git a/app/about/(spotify)/animation.jsx b/app/about/(spotify)/animation.jsx
new file mode 100644
index 0000000..769fc77
--- /dev/null
+++ b/app/about/(spotify)/animation.jsx
@@ -0,0 +1,25 @@
+import { motion } from "framer-motion";
+
+const PlayingAnimation = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+export default PlayingAnimation;
diff --git a/app/about/(spotify)/card.jsx b/app/about/(spotify)/card.jsx
new file mode 100644
index 0000000..735c674
--- /dev/null
+++ b/app/about/(spotify)/card.jsx
@@ -0,0 +1,78 @@
+import React, { useEffect, useState } from "react";
+import getNowPlayingItem from "./fetch";
+import PlayingAnimation from "./animation";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faSpotify } from "@fortawesome/free-brands-svg-icons";
+import Image from "next/image";
+
+const Card = () => {
+ const [loading, setLoading] = useState(true);
+ const [result, setResult] = useState({});
+
+useEffect(() => {
+ const fetchData = async () => {
+ const results = await Promise.all([getNowPlayingItem()]);
+ console.log(results);
+ setResult(results[0]);
+ setLoading(false);
+ };
+ fetchData(); // Fetch data immediately on component mount
+
+ const intervalId = setInterval(fetchData, 60 * 1000); // ! Fetch data every minute: temporary
+
+ return () => clearInterval(intervalId);
+}, []);
+
+ return (
+
+ {loading ? (
+
+ {/* Replace this with your own loading spinner */}
+
+
+ ) : (
+
+
+
+
+
+ {result.isPlaying
+ ? "Now playing"
+ : "Currently offline"}
+
+ {result.isPlaying &&
}
+
+ {result.isPlaying && (
+
+ )}
+
+ )}
+
+ );
+};
+
+export default Card;
+
diff --git a/app/about/(spotify)/fetch.js b/app/about/(spotify)/fetch.js
new file mode 100644
index 0000000..2866dcf
--- /dev/null
+++ b/app/about/(spotify)/fetch.js
@@ -0,0 +1,53 @@
+import querystring from "querystring";
+const TOKEN_ENDPOINT = `https://accounts.spotify.com/api/token`;
+const NOW_PLAYING_ENDPOINT = `https://api.spotify.com/v1/me/player/currently-playing`;
+const client_id = process.env.NEXT_PUBLIC_SPOTIFY_CLIENT_ID;
+const client_secret = process.env.NEXT_PUBLIC_SPOTIFY_CLIENT_SECRET;
+const refresh_token = process.env.NEXT_PUBLIC_SPOTIFY_REFRESH_TOKEN;
+
+const basic = Buffer.from(`${client_id}:${client_secret}`).toString("base64");
+const getAccessToken = async () => {
+ const response = await fetch(TOKEN_ENDPOINT, {
+ method: "POST",
+ headers: {
+ Authorization: `Basic ${basic}`,
+ "Content-Type": "application/x-www-form-urlencoded",
+ },
+ body: querystring.stringify({
+ grant_type: "refresh_token",
+ refresh_token,
+ }),
+ });
+
+ return response.json();
+};
+
+export const getNowPlaying = async () => {
+ const { access_token } = await getAccessToken();
+ return fetch(NOW_PLAYING_ENDPOINT, {
+ headers: {
+ Authorization: `Bearer ${access_token}`,
+ },
+ });
+};
+
+export default async function getNowPlayingItem() {
+ const response = await getNowPlaying();
+ if (response.status === 204 || response.status > 400) {
+ return false;
+ }
+ const song = await response.json();
+ const albumImageUrl = song.item.album.images[0].url;
+ const artist = song.item.artists.map((_artist) => _artist.name).join(", ");
+ const isPlaying = song.is_playing;
+ const songUrl = song.item.external_urls.spotify;
+ const title = song.item.name;
+
+ return {
+ albumImageUrl,
+ artist,
+ isPlaying,
+ songUrl,
+ title,
+ };
+}
\ No newline at end of file
diff --git a/app/about/page.jsx b/app/about/page.jsx
index bd8b1d2..7d8b095 100644
--- a/app/about/page.jsx
+++ b/app/about/page.jsx
@@ -1,6 +1,5 @@
"use client";
import { useEffect } from "react";
-import Link from "next/link";
import { motion } from "framer-motion";
import Button from "@/components/Button";
import Image from "next/legacy/image";
@@ -8,19 +7,19 @@ import FixedButon from "@/components/FixedButton";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronLeft } from "@fortawesome/free-solid-svg-icons";
-
+import Card from "./(spotify)/card.jsx";
// images
import Me1 from "@/public/img/me1.jpg";
import Me2 from "@/public/img/me2.jpg";
import Me3 from "@/public/img/me3.jpg";
import Hr from "@/components/Hr";
+
export default function Page() {
useEffect(() => {
window.scrollTo(0, 0);
}, []);
-
const handleBack = () => {
window.location.href = "/";
};
@@ -207,6 +206,7 @@ export default function Page() {
connect and explore this ever-evolving world of tech
together!
+
diff --git a/next.config.js b/next.config.js
index d30af7d..47f6ef3 100644
--- a/next.config.js
+++ b/next.config.js
@@ -3,6 +3,9 @@ const withBundleAnalyzer = require("@next/bundle-analyzer")({
});
module.exports = withBundleAnalyzer({
// your Next.js configuration
+ images: {
+ domains: ["i.scdn.co"],
+ },
webpack: (config, options) => {
config.module.rules.push({
test: /\.pdf$/i,