RL
Rahul Lokhande

Search Dropdown - Copy this React, Tailwind Component to your project

"use client"; import { useEffect, useState } from "react"; import DjangoConfig from "@/config/config"; import { useRouter, useSearchParams } from 'next/navigation'; import '../app/globals.css'; export default function EditGroup() { const router = useRouter(); const searchParams = useSearchParams(); const id = searchParams.get('id'); const [groups, setGroups] = useState([]); const [users, setUsers] = useState([]); const [groupData, setGroupData] = useState({ group_name: "", members: [], admins: [], type: true, group_image: null, // This will store the selected image }); const [editingGroupId, setEditingGroupId] = useState(null); const [currentUser, setCurrentUser] = useState(""); const [message, setMessage] = useState(""); useEffect(() => { const storedUser = localStorage.getItem("username"); setCurrentUser(storedUser); handleGetGroup(); fetchUsers(); }, [id]); const fetchUsers = async () => { try { const response = await fetch(`${DjangoConfig.apiUrl}get_users`, { credentials: "include", }); if (response.ok) { const data = await response.json(); setUsers(data); } } catch (error) { console.error("Error fetching users:", error); } }; const handleMemberClick = (user) => { if (user.username === currentUser) return; // Prevent adding current user setGroupData((prev) => ({ ...prev, members: prev.members.includes(user.id) ? prev.members.filter((id) => id !== user.id) : [...prev.members, user.id], })); console.log(groupData) }; const handleAdminClick = (user) => { if (user.username === currentUser) return; // Prevent adding current user setGroupData((prev) => ({ ...prev, admins: prev.admins.includes(user.id) ? prev.admins.filter((id) => id !== user.id) : [...prev.admins, user.id], })); console.log(groupData) }; const handleGetGroup = async () => { const group_id = id; try { const response = await fetch(`${DjangoConfig.apiUrl}edit_group/${group_id}`); if (response.ok) { const data = await response.json(); setGroupData({ group_name: data.group_name, members: data.members.filter((a) => a.username !== currentUser).map((m) => m.id), admins: data.admins.filter((a) => a.username !== currentUser).map((a) => a.id), type: data.type, group_image: data.group_image || null, // Use existing image from the backend if available }); } } catch (error) { console.error("Error fetching group:", error); } }; const handleImageChange = (e) => { const file = e.target.files[0]; setGroupData((prev) => ({ ...prev, group_image: file, // Store the file object in state })); }; const handleUpdateGroup = async () => { const group_id = id; console.log(groupData) const formData = new FormData(); formData.append("group_name", groupData.group_name); formData.append("type", groupData.type); formData.append("members", JSON.stringify(groupData.members)); formData.append("admins", JSON.stringify(groupData.admins)); console.log(formData); if (groupData.group_image) { formData.append("group_image", groupData.group_image); // Append image if exists } try { const response = await fetch(`${DjangoConfig.apiUrl}edit_group/${group_id}/`, { method: "POST", headers: { "Accept": "application/json" }, credentials: "include", body: formData, }); if (response.ok) { setMessage("Group updated successfully!"); setTimeout(() => router.push(`/groups/${group_id}`), 2000); // Redirect after success } else { setMessage("Error updating group."); } } catch (error) { console.error("Error updating group:", error); setMessage("Error updating group."); } }; return ( <div className="bg slate 200 h auto top 0 absolute w full"> <div className="max w 2xl mx auto mt 10 p 6 bg slate 100 rounded lg shadow lg"> <h1 className="text 3xl font bold text gray 800 mb 6">Edit Group</h1> {/* Group Name Input */} <input type="text" name="group_name" value={groupData.group_name} onChange={(e) => setGroupData({ ...groupData, group_name: e.target.value })} placeholder="Group Name" className="w full p 3 mb 4 border border gray 300 rounded lg focus:outline none focus:ring 2 focus:ring blue 500" /> {/* Group Image Upload */} <div className="mb 4"> <label htmlFor="group_image" className="block text lg font semibold text gray 700 mb 2">Group Image:</label> <input type="file" id="group_image" onChange={handleImageChange} className="w full p 3 border border gray 300 rounded lg focus:outline none focus:ring 2 focus:ring blue 500" /> {groupData.group_image && ( <div className="mt 4"> <img src={`${DjangoConfig.profile_picture_url}${groupData.group_image}`} alt="Group Image Preview" className="w 32 h 32 object cover rounded md" /> </div> )} </div> {/* Member Selection */} <label className="block text lg font semibold text gray 700 mb 2">Select Members:</label> <div className="flex flex wrap gap 2 p 3 border border gray 300 rounded lg bg gray 50"> {users.map((user) => ( <div key={user.id} className={`cursor pointer px 4 py 2 rounded full transition colors ${groupData.members.includes(user.id) ? "bg blue 500 text white hover:bg blue 600" : "bg gray 200 hover:bg gray 300" } ${user.username === currentUser ? "bg gray 400 cursor not allowed" : ""}`} onClick={() => handleMemberClick(user)} > {user.username} {user.username === currentUser && "(You)"} </div> ))} </div> {/* Selected Members */} <div className="mt 4"> <p className="text lg font semibold text gray 700 mb 2">Selected Members:</p> <div className="flex flex wrap gap 2"> <div className="bg blue 500 text white px 4 py 2 rounded full flex items center gap 2 hover:bg blue 600 transition colors cursor pointer" > you <span className="text sm">✖</span> </div> {groupData.members.map((memberId) => { const member = users.find((u) => u.id === memberId); return ( <div key={memberId} className="bg blue 500 text white px 4 py 2 rounded full flex items center gap 2 hover:bg blue 600 transition colors cursor pointer" onClick={() => handleMemberClick(member)} > {member?.username} <span className="text sm">✖</span> </div> ); })} </div> </div> {/* Admin Selection */} <label className="block text lg font semibold text gray 700 mt 4 mb 2">Select Admins:</label> <div className="flex flex wrap gap 2 p 3 border border gray 300 rounded lg bg gray 50"> {users.map((user) => ( <div key={user.id} className={`cursor pointer px 4 py 2 rounded full transition colors ${groupData.admins.includes(user.id) ? "bg green 500 text white hover:bg green 600" : "bg gray 200 hover:bg gray 300" } ${user.username === currentUser ? "bg gray 400 cursor not allowed" : ""}`} onClick={() => handleAdminClick(user)} > {user.username} {user.username === currentUser && "(You)"} </div> ))} </div> {/* Selected Admins */} <div className="mt 4"> <p className="text lg font semibold text gray 700 mb 2">Selected Admins:</p> <div className="flex flex wrap gap 2"> <div className="bg green 500 text white px 4 py 2 rounded full flex items center gap 2 hover:bg green 600 transition colors cursor pointer" > you <span className="text sm">✖</span> </div> {groupData.admins.map((adminId) => { const admin = users.find((u) => u.id === adminId); return ( <div key={adminId} className="bg green 500 text white px 4 py 2 rounded full flex items center gap 2 hover:bg green 600 transition colors cursor pointer" onClick={() => handleAdminClick(admin)} > {admin?.username} <span className="text sm">✖</span> </div> ); })} </div> </div> {/* Admin Only Message Toggle */} <label className="flex items center mt 4 space x 3"> <input type="checkbox" checked={groupData.type} onChange={(e) => setGroupData({ ...groupData, type: e.target.checked })} className="w 5 h 5 text blue 500 border gray 300 rounded focus:ring blue 500" /> <span className="text gray 700">Only admins can send messages</span> </label> {/* Create Group Button */} <button onClick={handleUpdateGroup} className="w full bg blue 500 text white py 3 rounded lg mt 6 font semibold hover:bg blue 600 transition colors" > Edit Group </button> {message && <p className="mt 4 text red 500">{message}</p>} </div> </div> ); } "Create a dropdown menu for 'Selected Members' or 'Select Admins' that opens when a button is clicked. The dropdown should include a search option, allowing users to search for and select members manually. Do not make changes to any other fields. Include comments explaining each part of the code to help me understand and modify the functionality if needed."

Prompt
Component Preview

About

SearchDropdown - Create a searchable dropdown for selecting members or admins in your group. Built with React and Tailwind. Access free code!

Share

Last updated 1 month ago