Skip to content

Commit

Permalink
feat: add search functionality and user profile display; update UI co…
Browse files Browse the repository at this point in the history
…mponents
  • Loading branch information
pranshu05 committed Dec 7, 2024
1 parent 3e97b90 commit 3ec043d
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 7 deletions.
9 changes: 9 additions & 0 deletions src/components/(layout)/NavBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import SearchBar from "@/components/(layout)/SearchBar";

export default function Navbar() {
return (
<nav className="bg-black p-3 flex item-center justify-center w-full">
<SearchBar />
</nav>
);
}
18 changes: 18 additions & 0 deletions src/components/(layout)/SearchBar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useState } from 'react';
import { useRouter } from 'next/router';

export default function SearchBar() {
const [query, setQuery] = useState('');
const router = useRouter();

const handleSearch = (e) => {
e.preventDefault();
if (query.trim()) { router.push(`/search?query=${query}`); }
};

return (
<form onSubmit={handleSearch} className="w-11/12 md:w-3/4 lg:w-1/2">
<input type="text" value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search users by name" className="py-3 px-5 bg-[#121212] rounded-full w-full" />
</form>
);
}
10 changes: 10 additions & 0 deletions src/components/(search)/UserSearchProfile.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* eslint-disable @next/next/no-img-element */
export default function UserSearchProfile({ user }) {
return (
<div className="flex flex-col items-center bg-[#121212] p-3 rounded-lg gap-2">
<img src={user.image === 'unknown' ? 'https://github.com/user-attachments/assets/bf57cb96-b259-4290-b35b-0ede9d618802' : user.image} alt={user.name} className="w-32 h-32 rounded-full" />
<h3 className="text-xl font-bold">{user.name}</h3>
<a href={`/user/${user.spotifyId}`} className="px-4 py-2 bg-[#121212] border-[2px] border-[#333] rounded-md">View Profile</a>
</div>
);
}
2 changes: 1 addition & 1 deletion src/components/(user)/NowPlaying.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default function NowPlaying({ userId, onIsPlayingChange }) {

if (song) {
return (
<div className="relative h-full rounded-lg" style={{ backgroundImage: `url(${song.image})`, backgroundSize: "cover", backgroundPosition: "center", minHeight: "300px" }}>
<div className="relative h-full rounded-lg" style={{ backgroundImage: `url(${song.image})`, backgroundSize: "cover", backgroundPosition: "center", minHeight: "290px" }}>
<div className="absolute inset-0 bg-black bg-opacity-50 backdrop-blur-lg rounded-lg"></div>
<div className="absolute inset-0 flex items-center justify-center z-10">
<a href={song.songUrl} target="_blank" rel="noreferrer" className="w-full p-3 text-center">
Expand Down
2 changes: 1 addition & 1 deletion src/components/(user)/TopGenres.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default function TopGenres({ userId }) {
<div className="flex gap-2 justify-center">
<button onClick={() => handleTimeRangeChange("short_term")} className={`px-3 py-1 rounded-md ${timeRange === "short_term" ? "bg-[#1DB954]" : "bg-[#1F1F1F]"}`}>Last Month</button>
<button onClick={() => handleTimeRangeChange("medium_term")} className={`px-3 py-1 rounded-md ${timeRange === "medium_term" ? "bg-[#1DB954]" : "bg-[#1F1F1F]"}`}>Last 6 Months</button>
<button onClick={() => handleTimeRangeChange("long_term")} className={`px-3 py-1 rounded-md ${timeRange === "long_term" ? "bg-[#1DB954]" : "bg-[#1F1F1F]"}`}>Last Yeart</button>
<button onClick={() => handleTimeRangeChange("long_term")} className={`px-3 py-1 rounded-md ${timeRange === "long_term" ? "bg-[#1DB954]" : "bg-[#1F1F1F]"}`}>Last Year</button>
</div>
</div>
<div className="flex flex-col gap-3">
Expand Down
5 changes: 3 additions & 2 deletions src/components/(user)/UserData.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
import { signOut } from "next-auth/react";

export default function UserData({ session, user, userId }) {
console.log(user)
return (
<div className="flex flex-col items-center w-full p-3 bg-[#121212] rounded-lg">
<img src={user.image === 'unknown' ? 'https://github.com/user-attachments/assets/bf57cb96-b259-4290-b35b-0ede9d618802' : user.image} alt={user.name} className="w-32 h-32 lg:w-52 lg:h-52 rounded-full mb-4 object-cover" />
<h1 className="text-2xl lg:text-3xl font-bold mb-4">{user.name}</h1>
<p className="text-sm lg:text-base text-[#888] mb-4">{user.points} TuneStats Points</p>
<h1 className="text-2xl lg:text-3xl font-bold mb-3">{user.name}</h1>
<p className="text-sm lg:text-base text-[#888] mb-3">{user.points} TuneStats Points</p>
<div className="w-full flex justify-center gap-2 text-sm">
<a href={`https://open.spotify.com/user/${userId}`} target="_blank" rel="noreferrer" className="px-4 py-2 bg-[#1DB954] rounded-md">Spotify</a>
{session?.user?.id === userId && (<button onClick={() => signOut()} className="px-4 py-2 bg-[#121212] border-[2px] border-[#333] rounded-md">Sign Out</button>)}
Expand Down
5 changes: 3 additions & 2 deletions src/pages/api/auth/[...nextauth].js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import NextAuth from "next-auth";
import SpotifyProvider from "next-auth/providers/spotify";
import { db } from "@/lib/firebaseConfig";
import { doc, setDoc } from "firebase/firestore";
import { doc, updateDoc } from "firebase/firestore";

export default NextAuth({
providers: [
Expand All @@ -26,7 +26,8 @@ export default NextAuth({
async signIn({ user, account }) {
if (account.provider === "spotify") {
const userRef = doc(db, "users", user.id);
await setDoc(userRef, {

await updateDoc(userRef, {
email: user.email || "unknown",
name: user.name || "unknown",
spotifyId: user.id || "unknown",
Expand Down
1 change: 0 additions & 1 deletion src/pages/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export default function Home() {
<>
<h1 className="text-xl lg:text-4xl font-bold mb-4">Welcome, {session.user.name}!</h1>
<a href={`/user/${session.user.id}`} className="mb-4">Go to your profile.</a>
<button onClick={() => signOut()} className="px-2 py-1 lg:px-4 lg:py-2 bg-[#121212] border-[2px] border-[#333] rounded-md">Sign Out</button>
</>
)}
</div>
Expand Down
66 changes: 66 additions & 0 deletions src/pages/search/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { db } from '@/lib/firebaseConfig';
import { collection, getDocs } from 'firebase/firestore';
import Navbar from '@/components/(layout)/NavBar';
import UserSearchProfile from '@/components/(search)/UserSearchProfile';

export default function Search() {
const router = useRouter();
const { query: searchQuery } = router.query;
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
if (!searchQuery) return;

const fetchUsers = async () => {
setLoading(true);
try {
const querySnapshot = await getDocs(collection(db, 'users'));
const usersList = querySnapshot.docs.map(doc => doc.data());

const filteredUsers = usersList.filter(user => user.name.toLowerCase().includes(searchQuery.toLowerCase()));

setUsers(filteredUsers);
} catch (error) {
console.error('Error fetching users:', error);
} finally {
setLoading(false);
}
};

fetchUsers();
}, [searchQuery]);

if (!searchQuery) {
return (
<div className="w-full h-screen">
<Navbar />
<h2 className="text-2xl text-center mt-10">Please enter a search query.</h2>
</div>
);
}

return (
<div className="w-full min-h-screen">
<Navbar />
<div className="w-full p-4">
<h2 className="text-2xl font-bold mb-6">Search Results</h2>
{loading ? (
<p>Loading...</p>
) : (
users.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
{users.map((user) => (
<UserSearchProfile key={user.spotifyId} user={user} />
))}
</div>
) : (
<p>No users found</p>
)
)}
</div>
</div>
);
}

0 comments on commit 3ec043d

Please sign in to comment.