diff --git a/src/components/guild/MemberContainer.tsx b/src/components/guild/MemberContainer.tsx index f61fe83..c3bfae7 100644 --- a/src/components/guild/MemberContainer.tsx +++ b/src/components/guild/MemberContainer.tsx @@ -7,6 +7,7 @@ import { IoHelpCircleOutline, IoGridOutline } from 'react-icons/io5' +import { MemberCard } from './member/MemberCard' interface MemberContainerProps { members?: Member[] @@ -42,6 +43,8 @@ export const MemberContainer = ({ const [gridSize, setGridSize] = useState(2) + const [showPart, setShowPart] = useState(false) // 분류해서 보기 + const dropdownRef = useRef(null) if (!members) return null @@ -54,49 +57,72 @@ export const MemberContainer = ({ setShowMenu(false) } - const filteredMembers = members - .filter(member => { - const searchMatch = member.name - .toLowerCase() - .includes(searchCharacter?.toLowerCase() || '') + const allMember = allMembers?.flatMap(m => m.memberDetailResponse) || [] + const filteredMembers = showPart + ? allMember + .filter( + (member): member is Member => + member !== undefined && + member !== null && + member.type === '본캐' && + member.name + .toLowerCase() + .includes(searchCharacter?.toLowerCase() || '') + ) + .map(mainChar => { + // 부캐 찾기 + const subChars = allMember.filter( + (sub): sub is Member => + sub !== undefined && + sub !== null && + sub.type === '부캐' && + sub.mainCharacterInfo?.name === mainChar.name + ) + + return { + ...mainChar, + subCharacters: subChars + } + }) + : members + .filter(member => { + const searchMatch = member.name + .toLowerCase() + .includes(searchCharacter?.toLowerCase() || '') + + if (selectedType === '모두 보기' || selectedType === '캐릭터 분류') + return searchMatch - if (selectedType === '모두 보기' || selectedType === '캐릭터 분류') - return searchMatch + if (selectedType === '본캐') + return member.type === '본캐' && searchMatch - if (selectedType === '본캐') return member.type === '본캐' && searchMatch + if (selectedType === '부캐') + return member.type === '부캐' && searchMatch - if (selectedType === '부캐') - return ( - member.type === '부캐' && - allMembers?.find(m => - m.memberDetailResponse?.find( - m => m.name === member.mainCharacterInfo?.name + if (selectedType === '외부 부캐') + return ( + member.type === '부캐' && + !allMembers?.find(m => + m.memberDetailResponse?.find( + m => m.name === member.mainCharacterInfo?.name + ) + ) ) - ) && - searchMatch - ) - if (selectedType === '특이사항') return member.description && searchMatch + if (selectedType === '특이사항') + return member.description && searchMatch - return ( - member.type === '부캐' && - !allMembers?.find(m => - m.memberDetailResponse?.find( - m => m.name === member.mainCharacterInfo?.name - ) - ) && - searchMatch - ) - }) - .sort((a, b) => { - if (sortType === '이름순') { - return a.name.localeCompare(b.name) - } - if (sortType === '레벨순') { - return Number(b.level) - Number(a.level) - } - return 0 - }) + return false + }) + .sort((a, b) => { + if (sortType === '이름순') { + return a.name.localeCompare(b.name) + } + if (sortType === '레벨순') { + return Number(b.level) - Number(a.level) + } + return 0 + }) return (
@@ -320,126 +346,71 @@ export const MemberContainer = ({ {gridSize}개 보기
+
+ +
-
- {filteredMembers.map(member => ( -
onSelect?.(member.type, member) - : member.type === '부캐' && member.mainCharacterInfo - ? () => { - const found = allMembers - ?.flatMap(g => g.memberDetailResponse) - .find( - m => - m?.name === member.mainCharacterInfo!.name && - m.type === '본캐' - ) - - if (found) { - onSelect?.(found.type, found) - } - } - : () => onSelect?.(member.type, member) - } - className="bg-gray-50 rounded-lg hover:bg-gray-100 transition-all duration-200 cursor-pointer group overflow-hidden border border-gray-100"> +
+ {showPart ? ( + (filteredMembers as Member[]).map(member => (
- {member.name} -
-

- {member.name} -

-

{member.job}

-
-
-
- - Lv.{member.level} - - {masterName && ( - - m.memberDetailResponse?.find( - m => - m.name === - member.mainCharacterInfo?.name - ) - ) - ? 'bg-yellow-100 text-yellow-700' - : 'bg-gray-100 text-gray-700' - }`}> - {member.name === masterName && ( - - - - )} - {member.name === masterName - ? '마스터' - : member.type === '본캐' - ? '본캐' - : member.type === '부캐' && - allMembers?.find(m => - m.memberDetailResponse?.find( - m => - m.name === - member.mainCharacterInfo?.name - ) - ) - ? '부캐' - : member.mainCharacterInfo === null - ? '' - : '외부 부캐'} - - )} -
- {member.type === '부캐' && - !allMembers?.find(m => - m.memberDetailResponse?.find( - m => m.name === member.mainCharacterInfo?.name - ) - ) && ( - - 외부 길드에 {member.mainCharacterInfo?.name}님의 - 부캐입니다. - - )} -
+ key={member.name} + className="flex gap-4 items-start border-b border-gray-100 pb-8"> +
+ +
+
+
+ {member.subCharacters?.map(subChar => ( + + ))}
+ )) + ) : ( +
+ {(filteredMembers as Member[]).map(member => ( + + ))}
- ))} + )}
diff --git a/src/components/guild/member/MemberCard.tsx b/src/components/guild/member/MemberCard.tsx new file mode 100644 index 0000000..a6def4d --- /dev/null +++ b/src/components/guild/member/MemberCard.tsx @@ -0,0 +1,121 @@ +import { Member, NexonMembers } from '../../../types/guild' + +interface MemberCardProps { + member: Member + onSelect: (type: string, member: Member) => void + allMembers: NexonMembers[] + gridSize: number + masterName: string +} + +export const MemberCard = ({ + member, + onSelect, + allMembers, + gridSize, + masterName +}: MemberCardProps) => { + return ( +
onSelect?.(member.type, member) + : member.type === '부캐' && member.mainCharacterInfo + ? () => { + const found = allMembers + ?.flatMap(g => g.memberDetailResponse) + .find( + m => + m?.name === member.mainCharacterInfo!.name && + m.type === '본캐' + ) + + if (found) { + onSelect?.(found.type, found) + } + } + : () => onSelect?.(member.type, member) + } + className="bg-gray-50 rounded-lg hover:bg-gray-100 transition-all duration-200 cursor-pointer group overflow-hidden border border-gray-100"> +
+ {member.name} +
+

+ {member.name} +

+

{member.job}

+
+
+
+ Lv.{member.level} + {masterName && ( + + m.memberDetailResponse?.find( + m => m.name === member.mainCharacterInfo?.name + ) + ) + ? 'bg-yellow-100 text-yellow-700' + : 'bg-gray-100 text-gray-700' + }`}> + {member.name === masterName && ( + + + + )} + {member.name === masterName + ? '마스터' + : member.type === '본캐' + ? '본캐' + : member.type === '부캐' && + allMembers?.find(m => + m.memberDetailResponse?.find( + m => m.name === member.mainCharacterInfo?.name + ) + ) + ? '부캐' + : member.mainCharacterInfo === null + ? '' + : '외부 부캐'} + + )} +
+ {member.type === '부캐' && + !allMembers?.find(m => + m.memberDetailResponse?.find( + m => m.name === member.mainCharacterInfo?.name + ) + ) && ( + + 외부 길드에 {member.mainCharacterInfo?.name}님의 부캐입니다. + + )} +
+
+
+
+
+ ) +} diff --git a/src/types/guild.ts b/src/types/guild.ts index fc11312..ded1e9c 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -60,6 +60,13 @@ export interface Member { job: string imagePath: string } + subCharacters?: { + name: string + job: string + level: string + type: string + imagePath: string + }[] } export interface Detect {