Skip to content

Commit

Permalink
feat: enhance search functionality and user profile display; add Frie…
Browse files Browse the repository at this point in the history
…ndButton component
  • Loading branch information
pranshu05 committed Dec 7, 2024
1 parent 3ec043d commit f8f8fb0
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 40 deletions.
22 changes: 14 additions & 8 deletions src/components/(layout)/SearchBar.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { useState } from 'react';
import { useRouter } from 'next/router';
import { useState } from "react";
import { useRouter } from "next/router";

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

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

if (value.trim()) {
router.push(`/search?query=${encodeURIComponent(value)}`, undefined, { shallow: true });
} else {
router.push(`/search`, undefined, { shallow: true });
}
};

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 className="w-11/12 md:w-3/4 lg:w-1/2">
<input type="text" value={query} onChange={handleInputChange} placeholder="Search users by name" className="py-3 px-5 bg-[#121212] rounded-full w-full" />
</form>
);
}
64 changes: 64 additions & 0 deletions src/components/(user)/FriendButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useState, useEffect } from "react";
import { doc, updateDoc, arrayUnion, arrayRemove, getDoc } from "firebase/firestore";
import { db } from "@/lib/firebaseConfig";

export default function FriendButton({ currentUserId, userId }) {
const [isFriend, setIsFriend] = useState(false);
const [loading, setLoading] = useState(false);

useEffect(() => {
const checkFriendshipStatus = async () => {
try {
const currentUserRef = doc(db, "users", currentUserId);
const currentUserDoc = await getDoc(currentUserRef);

if (currentUserDoc.exists()) {
const currentUserData = currentUserDoc.data();
setIsFriend(currentUserData.friends?.includes(userId) || false);
}
} catch (error) {
console.error("Error checking friendship status:", error);
}
};

checkFriendshipStatus();
}, [currentUserId, userId]);

const handleAddFriend = async () => {
setLoading(true);
try {
const currentUserRef = doc(db, "users", currentUserId);
await updateDoc(currentUserRef, {
friends: arrayUnion(userId),
});
setIsFriend(true);
} catch (error) {
console.error("Error adding friend:", error);
} finally {
setLoading(false);
}
};

const handleRemoveFriend = async () => {
setLoading(true);
try {
const currentUserRef = doc(db, "users", currentUserId);
await updateDoc(currentUserRef, {
friends: arrayRemove(userId),
});
setIsFriend(false);
} catch (error) {
console.error("Error removing friend:", error);
} finally {
setLoading(false);
}
};

if (currentUserId === userId) return null;

return (
<button onClick={isFriend ? handleRemoveFriend : handleAddFriend} disabled={loading} className={`px-4 py-2 bg-[#121212] border-[2px] border-[#333] rounded-md`}>
{loading ? "Processing..." : isFriend ? "Remove Friend" : "Add Friend"}
</button>
);
}
12 changes: 10 additions & 2 deletions src/components/(user)/UserData.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
/* eslint-disable @next/next/no-img-element */
import { signOut } from "next-auth/react";
import FriendButton from "@/components/(user)/FriendButton";

export default function UserData({ session, user, userId }) {
console.log(user)
const currentUserId = session?.user?.id;

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-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>)}
{session?.user?.id === userId ?
(
<button onClick={() => signOut()} className="px-4 py-2 bg-[#121212] border-[2px] border-[#333] rounded-md">Sign Out</button>
) : (
<FriendButton currentUserId={currentUserId} userId={userId} />
)
}
</div>
</div>
)
Expand Down
2 changes: 0 additions & 2 deletions src/pages/api/updatePoints/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ export default async function handler(req, res) {

const usersSnapshot = await getDocs(usersQuery);

console.log(`Batch size fetched: ${usersSnapshot.size}`);

if (usersSnapshot.empty) break;

const users = usersSnapshot.docs.map(doc => ({
Expand Down
47 changes: 19 additions & 28 deletions src/pages/search/index.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
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';
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();
Expand All @@ -17,14 +17,18 @@ export default function Search() {
const fetchUsers = async () => {
setLoading(true);
try {
const querySnapshot = await getDocs(collection(db, 'users'));
const usersList = querySnapshot.docs.map(doc => doc.data());
const usersRef = collection(db, "users");
const querySnapshot = await getDocs(usersRef);

const filteredUsers = usersList.filter(user => user.name.toLowerCase().includes(searchQuery.toLowerCase()));
const filteredUsers = querySnapshot.docs
.map((doc) => doc.data())
.filter((user) =>
user.name.toLowerCase().includes(searchQuery.toLowerCase())
);

setUsers(filteredUsers);
} catch (error) {
console.error('Error fetching users:', error);
console.error("Error fetching users:", error);
} finally {
setLoading(false);
}
Expand All @@ -33,32 +37,19 @@ export default function Search() {
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>
) : (
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>
)
<p>No users found</p>
)}
</div>
</div>
Expand Down

0 comments on commit f8f8fb0

Please sign in to comment.