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