From 07481367357415b4b7fc72bf8bbe5a73fe94969c Mon Sep 17 00:00:00 2001 From: echo Date: Thu, 10 Jul 2025 12:11:20 +0900 Subject: [PATCH 1/4] =?UTF-8?q?style=20:=20=EC=BA=90=EB=A6=AD=ED=84=B0=20?= =?UTF-8?q?=EB=B6=84=EB=A5=98=ED=95=B4=EC=84=9C=20=EB=B3=B4=EA=B8=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/guild/MemberContainer.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/components/guild/MemberContainer.tsx b/src/components/guild/MemberContainer.tsx index f61fe83..ba1922b 100644 --- a/src/components/guild/MemberContainer.tsx +++ b/src/components/guild/MemberContainer.tsx @@ -42,6 +42,8 @@ export const MemberContainer = ({ const [gridSize, setGridSize] = useState(2) + const [showPart, setShowPart] = useState(false) // 분류해서 보기 + const dropdownRef = useRef(null) if (!members) return null @@ -320,6 +322,17 @@ export const MemberContainer = ({ {gridSize}개 보기 +
+ +
Date: Thu, 10 Jul 2025 14:30:58 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat=20:=20=EB=B3=B8=EC=BA=90=EB=A6=AD?= =?UTF-8?q?=ED=84=B0=20=EB=B6=80=EC=BA=90=EB=A6=AD=ED=84=B0=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=95=84=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/guild/MemberContainer.tsx | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/components/guild/MemberContainer.tsx b/src/components/guild/MemberContainer.tsx index ba1922b..6278188 100644 --- a/src/components/guild/MemberContainer.tsx +++ b/src/components/guild/MemberContainer.tsx @@ -62,6 +62,61 @@ export const MemberContainer = ({ .toLowerCase() .includes(searchCharacter?.toLowerCase() || '') + if (showPart) { + const mainCharacter: { + name: string + job: string + level: string + type: string + imagePath: string + subCharacters: { + name: string + job: string + level: string + type: string + imagePath: string + }[] + }[] = [] + + // 먼저 본캐들을 찾아서 추가 + allMembers?.forEach(guild => { + guild.memberDetailResponse?.forEach(character => { + if (character.type === '본캐') { + mainCharacter.push({ + name: character.name, + job: character.job, + level: character.level, + type: character.type, + imagePath: character.imagePath, + subCharacters: [] + }) + } + }) + }) + + // 그 다음 부캐들을 해당하는 본캐에 추가 + allMembers?.forEach(guild => { + guild.memberDetailResponse?.forEach(character => { + if (character.type === '부캐') { + const mainChar = mainCharacter.find( + main => character.mainCharacterInfo?.name === main.name + ) + if (mainChar) { + mainChar.subCharacters.push({ + name: character.name, + job: character.job, + level: character.level, + type: character.type, + imagePath: character.imagePath + }) + } + } + }) + }) + + return searchMatch + } + if (selectedType === '모두 보기' || selectedType === '캐릭터 분류') return searchMatch From e3833c9523a6b57e39cf98e7519bb2c0c7350f89 Mon Sep 17 00:00:00 2001 From: echo Date: Thu, 10 Jul 2025 16:17:16 +0900 Subject: [PATCH 3/4] =?UTF-8?q?style=20:=20=EB=B3=B8=EC=BA=90=20=EB=B6=80?= =?UTF-8?q?=EC=BA=90=20=EC=B6=9C=EB=A0=A5=20=EC=8A=A4=ED=83=80=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/guild/MemberContainer.tsx | 244 +++++++-------------- src/components/guild/member/MemberCard.tsx | 121 ++++++++++ src/types/guild.ts | 7 + 3 files changed, 207 insertions(+), 165 deletions(-) create mode 100644 src/components/guild/member/MemberCard.tsx diff --git a/src/components/guild/MemberContainer.tsx b/src/components/guild/MemberContainer.tsx index 6278188..347d3e3 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[] @@ -63,58 +64,27 @@ export const MemberContainer = ({ .includes(searchCharacter?.toLowerCase() || '') if (showPart) { - const mainCharacter: { - name: string - job: string - level: string - type: string - imagePath: string - subCharacters: { - name: string - job: string - level: string - type: string - imagePath: string - }[] - }[] = [] - - // 먼저 본캐들을 찾아서 추가 - allMembers?.forEach(guild => { - guild.memberDetailResponse?.forEach(character => { - if (character.type === '본캐') { - mainCharacter.push({ - name: character.name, - job: character.job, - level: character.level, - type: character.type, - imagePath: character.imagePath, - subCharacters: [] - }) - } - }) - }) - - // 그 다음 부캐들을 해당하는 본캐에 추가 - allMembers?.forEach(guild => { - guild.memberDetailResponse?.forEach(character => { - if (character.type === '부캐') { - const mainChar = mainCharacter.find( - main => character.mainCharacterInfo?.name === main.name - ) - if (mainChar) { - mainChar.subCharacters.push({ - name: character.name, - job: character.job, - level: character.level, - type: character.type, - imagePath: character.imagePath - }) - } - } - }) - }) + // 본캐들만 먼저 찾아서 반환 + if (member.type === '본캐') { + // 해당 본캐의 부캐들 찾기 + const subCharacters = members + .filter( + m => + m.type === '부캐' && m.mainCharacterInfo?.name === member.name + ) + .map(m => ({ + name: m.name, + job: m.job, + level: m.level, + type: m.type, + imagePath: m.imagePath + })) - return searchMatch + // 본캐에 부캐 정보 추가 + member.subCharacters = subCharacters + return searchMatch + } + return false } if (selectedType === '모두 보기' || selectedType === '캐릭터 분류') @@ -154,7 +124,7 @@ export const MemberContainer = ({ } return 0 }) - + console.log(filteredMembers) return (
{guildName && ( @@ -390,124 +360,68 @@ export const MemberContainer = ({
-
- {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.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"> + {/* 본캐 카드 */} +
+ +
+ + {/* 부캐 목록 */} +
+
+ {members + ?.filter( + m => + m.type === '부캐' && + m.mainCharacterInfo?.name === member.name + ) + .map(subChar => ( + + ))}
+ )) + ) : ( + // 기존 그리드 뷰 +
+ {filteredMembers.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 { From b1cf83585358e264cbca9aa579a0d11720acf503 Mon Sep 17 00:00:00 2001 From: echo Date: Fri, 11 Jul 2025 12:42:45 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix=20:=20=EB=B3=B8=EC=BA=90=20=EB=B6=80?= =?UTF-8?q?=EC=BA=90=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EA=B8=B8=EB=93=9C=EC=97=90=EC=84=9C=20=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/guild/MemberContainer.tsx | 153 +++++++++++------------ 1 file changed, 71 insertions(+), 82 deletions(-) diff --git a/src/components/guild/MemberContainer.tsx b/src/components/guild/MemberContainer.tsx index 347d3e3..c3bfae7 100644 --- a/src/components/guild/MemberContainer.tsx +++ b/src/components/guild/MemberContainer.tsx @@ -57,74 +57,73 @@ 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 + ) - if (showPart) { - // 본캐들만 먼저 찾아서 반환 - if (member.type === '본캐') { - // 해당 본캐의 부캐들 찾기 - const subCharacters = members - .filter( - m => - m.type === '부캐' && m.mainCharacterInfo?.name === member.name - ) - .map(m => ({ - name: m.name, - job: m.job, - level: m.level, - type: m.type, - imagePath: m.imagePath - })) + return { + ...mainChar, + subCharacters: subChars + } + }) + : members + .filter(member => { + const searchMatch = member.name + .toLowerCase() + .includes(searchCharacter?.toLowerCase() || '') - // 본캐에 부캐 정보 추가 - member.subCharacters = subCharacters - return searchMatch - } - return false - } + 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 false + }) + .sort((a, b) => { + if (sortType === '이름순') { + return a.name.localeCompare(b.name) + } + if (sortType === '레벨순') { + return Number(b.level) - Number(a.level) + } + return 0 + }) - 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 - }) - console.log(filteredMembers) return (
{guildName && ( @@ -362,11 +361,10 @@ export const MemberContainer = ({
{showPart ? ( - filteredMembers.map(member => ( + (filteredMembers as Member[]).map(member => (
- {/* 본캐 카드 */}
- - {/* 부캐 목록 */}
- {members - ?.filter( - m => - m.type === '부캐' && - m.mainCharacterInfo?.name === member.name - ) - .map(subChar => ( - - ))} + {member.subCharacters?.map(subChar => ( + + ))}
)) ) : ( - // 기존 그리드 뷰
- {filteredMembers.map(member => ( + {(filteredMembers as Member[]).map(member => (