Member tiers implementation intact. Icons updated to be Lucide React. Create/edit member tiers. Display member badge. Transaction history now in My profile dashboard. Adjusted Icons for badges. Added badges on my profile page

This commit is contained in:
2026-01-27 16:30:26 -06:00
parent 0d7e3a1286
commit 4ad1997bd5
9 changed files with 646 additions and 82 deletions

View File

@@ -15,9 +15,10 @@ import {
} from '../../components/ui/dialog';
import { User, Search, Mail, MapPin, Phone, Heart, Facebook, Instagram, Twitter, Linkedin, UserCircle, Calendar } from 'lucide-react';
import { useToast } from '../../hooks/use-toast';
import StatusBadge from '@/components/StatusBadge';
import MemberCard from '../../components/MemberCard';
import MemberBadge from '../../components/MemberBadge';
import useMembers from '../../hooks/use-members';
import useMemberTiers from '../../hooks/use-member-tiers';
const MembersDirectory = () => {
const [selectedMember, setSelectedMember] = useState(null);
@@ -25,7 +26,27 @@ const MembersDirectory = () => {
const { toast } = useToast();
const [currentPage, setCurrentPage] = useState(1);
const pageSize = 12;
const { tiers } = useMemberTiers();
const allowedRoles = useMemo(() => [], []);
const normalizeStatus = useCallback((status) => {
if (typeof status === 'string') {
return status.toLowerCase();
}
return status;
}, []);
const normalizeMembers = useCallback(
(data) => {
const list = Array.isArray(data)
? data
: data?.members || data?.results || data?.items || data?.data || [];
return list.map((member) => ({
...member,
status: normalizeStatus(member.status ?? member.membership_status ?? member.member_status),
}));
},
[normalizeStatus]
);
const searchAccessor = useCallback(
(member) => [
`${member.first_name} ${member.last_name}`,
@@ -47,12 +68,14 @@ const MembersDirectory = () => {
loading,
searchQuery,
setSearchQuery,
filterValue,
} = useMembers({
endpoint: '/members/directory',
initialFilter: 'active',
initialFilter: 'all',
filterKey: 'status',
allowedRoles,
searchAccessor,
transform: normalizeMembers,
fetchErrorMessage: 'Failed to load members directory. Please try again.',
onFetchError: handleFetchError
});
@@ -67,7 +90,12 @@ const MembersDirectory = () => {
const paginatedMembers = filteredMembers.slice(pageStart, pageStart + pageSize);
const totalMembers = members.length;
const totalMembers = useMemo(() => {
if (!filterValue || filterValue === 'all') {
return members.length;
}
return members.filter((member) => member.status === filterValue).length;
}, [members, filterValue]);
@@ -158,7 +186,7 @@ const MembersDirectory = () => {
) : filteredMembers.length > 0 ? (
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{paginatedMembers.map((member) => (
<MemberCard key={member.id} member={member} onViewProfile={handleViewProfile} />
<MemberCard key={member.id} member={member} onViewProfile={handleViewProfile} tiers={tiers} />
))}
</div>
) : (
@@ -210,7 +238,7 @@ const MembersDirectory = () => {
<DialogHeader>
<DialogTitle className="text-3xl font-semibold text-[var(--purple-ink)] flex items-center justify-between mr-8" style={{ fontFamily: "'Inter', sans-serif" }}>
{selectedMember.first_name} {selectedMember.last_name}
<StatusBadge status={selectedMember.membership_status || selectedMember.status} />
<MemberBadge memberSince={selectedMember.member_since || selectedMember.created_at} tiers={tiers} />
</DialogTitle>
{selectedMember.directory_partner_name && (
<DialogDescription className="flex items-center gap-2 text-lg" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>