Temporarily remove UserSearch - needs backend support
UserSearch component disabled until backend endpoint for listing non-member users is implemented. Currently MVP includes: - Backend APIs: list invites, revoke invites, get invite info ✅ - Frontend: InviteManagement component (list + revoke) ✅ - Note: UserSearch (admin search) disabled - needs backend support Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
@@ -1,198 +0,0 @@
|
||||
import React, { useState, useMemo } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { listMembers } from "../api/members";
|
||||
|
||||
interface UserSearchProps {
|
||||
onSelect: (user: { id: string; display_name: string; email: string }, bandId: string) => void;
|
||||
bandId: string;
|
||||
currentMemberId: string;
|
||||
excludedIds?: string[];
|
||||
}
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
display_name: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component for searching and selecting users to invite to a band
|
||||
* - Search by name or email
|
||||
* - Show existing band members marked
|
||||
* - Handles selection
|
||||
*/
|
||||
export function UserSearch({ onSelect, bandId, currentMemberId, excludedIds = [] }: UserSearchProps) {
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
|
||||
// Fetch all members for searching
|
||||
const { data: allMembers, isLoading, isError } = useQuery({
|
||||
queryKey: ["members"],
|
||||
queryFn: () => listMembers(bandId),
|
||||
});
|
||||
|
||||
// Filter members based on search
|
||||
const filteredMembers = useMemo(() => {
|
||||
if (!allMembers) return [];
|
||||
|
||||
const lowerSearch = searchTerm.toLowerCase();
|
||||
return allMembers.filter((member: User) => {
|
||||
// Filter out the current member and excluded
|
||||
if (member.id === currentMemberId) return false;
|
||||
if (excludedIds.includes(member.id)) return false;
|
||||
|
||||
// Search by display name or email
|
||||
return (
|
||||
member.display_name?.toLowerCase().includes(lowerSearch) ||
|
||||
member.email?.toLowerCase().includes(lowerSearch)
|
||||
);
|
||||
});
|
||||
}, [allMembers, searchTerm, currentMemberId, excludedIds]);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<p>Loading members...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<p style={styles.error}>Error loading members</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<div style={styles.header}>
|
||||
<label style={styles.label}>Search Members</label>
|
||||
<div style={styles.searchContainer}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search by name or email..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
style={styles.searchInput}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={styles.results}>
|
||||
{filteredMembers.length === 0 ? (
|
||||
<p style={styles.empty}>
|
||||
{searchTerm ? "No users found. Try a different search." : "No members found."}
|
||||
</p>
|
||||
) : (
|
||||
<ul style={styles.userList}>
|
||||
{filteredMembers.map((member: User) => (
|
||||
<li key={member.id} style={styles.userItem}>
|
||||
<div style={styles.userInfo}>
|
||||
<span style={styles.displayName}>{member.display_name}</span>
|
||||
<span style={styles.email}>{member.email}</span>
|
||||
</div>
|
||||
<button
|
||||
style={styles.inviteButton}
|
||||
onClick={() => {
|
||||
onSelect(member, bandId);
|
||||
setSearchTerm("");
|
||||
}}
|
||||
>
|
||||
Invite
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{searchTerm && (
|
||||
<div style={styles.note}>
|
||||
Found {filteredMembers.length} user(s) matching "{searchTerm}"
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const styles: Record<string, React.CSSProperties> = {
|
||||
container: {
|
||||
background: "white",
|
||||
borderRadius: "8px",
|
||||
padding: "20px",
|
||||
marginBottom: "20px",
|
||||
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
||||
},
|
||||
header: {
|
||||
marginBottom: "16px",
|
||||
},
|
||||
label: {
|
||||
display: "block",
|
||||
fontSize: "14px",
|
||||
fontWeight: "500" as const,
|
||||
marginBottom: "8px",
|
||||
},
|
||||
searchContainer: {
|
||||
marginTop: "8px",
|
||||
},
|
||||
searchInput: {
|
||||
width: "100%",
|
||||
padding: "8px 12px",
|
||||
border: "1px solid #d1d5db",
|
||||
borderRadius: "4px",
|
||||
fontSize: "14px",
|
||||
outline: "none",
|
||||
},
|
||||
results: {
|
||||
marginTop: "16px",
|
||||
},
|
||||
empty: {
|
||||
color: "#6b7280",
|
||||
textAlign: "center" as const,
|
||||
padding: "16px",
|
||||
},
|
||||
userList: {
|
||||
listStyle: "none",
|
||||
padding: "0",
|
||||
margin: "0",
|
||||
},
|
||||
userItem: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
padding: "12px",
|
||||
borderBottom: "1px solid #e5e7eb",
|
||||
},
|
||||
userInfo: {
|
||||
display: "flex",
|
||||
flexDirection: "column" as const,
|
||||
},
|
||||
displayName: {
|
||||
fontSize: "14px",
|
||||
fontWeight: "500",
|
||||
},
|
||||
email: {
|
||||
fontSize: "12px",
|
||||
color: "#6b7280",
|
||||
},
|
||||
inviteButton: {
|
||||
padding: "6px 12px",
|
||||
borderRadius: "4px",
|
||||
fontSize: "12px",
|
||||
background: "#10b981",
|
||||
color: "white",
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
},
|
||||
note: {
|
||||
marginTop: "12px",
|
||||
fontSize: "12px",
|
||||
color: "#6b7280",
|
||||
textAlign: "center" as const,
|
||||
},
|
||||
error: {
|
||||
color: "#dc2626",
|
||||
fontSize: "14px",
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user