From e6c5de2663d6017dbd13abf2eec98309eb84c132 Mon Sep 17 00:00:00 2001 From: echo Date: Sun, 7 Sep 2025 23:51:26 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[Style]=20=EA=B8=B8=EB=93=9C=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20=EB=B2=84=EC=A0=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/SearchGuild.tsx | 350 ++++++++++++++++++++++---------------- 1 file changed, 205 insertions(+), 145 deletions(-) diff --git a/src/pages/SearchGuild.tsx b/src/pages/SearchGuild.tsx index 027dd9e..8eb0d24 100644 --- a/src/pages/SearchGuild.tsx +++ b/src/pages/SearchGuild.tsx @@ -1,7 +1,7 @@ -import { FiUsers } from 'react-icons/fi' +// src/pages/SearchGuild.tsx +import { FiUsers, FiArrowLeft } from 'react-icons/fi' import Button from '../components/common/Button' import { useGuildSearch } from '../hooks/search/useGuildSearch' - import { servers } from '../data/worlds' import { MemberContainer } from '../components/guild/MemberContainer' import { Empty } from '../components/common/Empty' @@ -40,6 +40,7 @@ export const SearchGuild = () => { type: '', member: null }) + const handleSearchCharacter = (value: string) => { setSearchCharacter(value) } @@ -52,168 +53,227 @@ export const SearchGuild = () => { } return ( -
- {guildsInfo?.length === 0 ? ( -
-
-
-
- +
+ {guildsInfo === undefined ? ( +
+
+
+ {/* 헤더 */} +
+
+ +
+
+

+ 길드 검색 +

+

+ 최대 4개까지 검색 가능 +

+
-

- 길드 검색 (최대 4개 검색 가능) -

-
-
-
- - setGuildName(e.target.value)} - onKeyPress={handleGuildKeyPress} - className="flex-1 px-4 py-2.5 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 bg-white" - /> + +
+ {/* 서버 선택 */} +
+ + +
+ + {/* 길드 이름 입력 */} +
+ +
+ setGuildName(e.target.value)} + onKeyPress={handleGuildKeyPress} + className="flex-1 px-4 py-3 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 bg-white" + /> + +
+
+ + {/* 추가된 길드 목록 */} + {guildList.length > 0 && ( +
+ +
+ {guildList.map(guild => ( +
+ + {guild} + + +
+ ))} +
+
+ )} + + {/* 검색 버튼 */}
- -
-

검색할 길드 목록

-
- {guildList.map(guild => ( -
- {guild} - -
- ))} -
-
- -
) : ( -
-
-
-

길드 관리

-

길드원 정보 관리

+
+ {/* 모바일 헤더 */} +
+
+
+
+ +
+

+ 길드 관리 +

+

+ 길드원 정보 관리 +

+
+
+ +
-
-
-
-
- ({ - worldName: v.worldName, - guildName: v.guildName - })) as Guild[]) || [] - } - mainCharacterInfoSearchHandler={searchMemberInfo} - isUpdating={isUpdatingMembers} - /> -
-
-
-
- {(isLoading || isUpdatingMembers) && ( -
-
-

- 캐릭터 정보를 불러오는 중... -

-
- )} - {guildsInfo && - guildsInfo.length > 0 && - !isLoading && - !isUpdatingMembers && ( - ({ - guildName: v.guildName, - guildMasterName: v.guildMasterName, - memberDetailResponse: v.guildMember - }))} - masterName={selectedGuildMember?.guildMasterName} - guildName={selectedGuildMember?.guildName} - onSelect={handleMemberSelect} - searchCharacter={searchCharacter} - setSearchCharacter={handleSearchCharacter} + {/* 컨텐츠 */} +
+
+
+ {/* 액션 버튼 영역 */} +
+
+ ({ + worldName: v.worldName, + guildName: v.guildName + })) as Guild[]) || [] + } + mainCharacterInfoSearchHandler={searchMemberInfo} + isUpdating={isUpdatingMembers} /> - )} - {guildsInfo && guildsInfo.length === 0 && ( - - )} +
+
+ + {/* 멤버 컨테이너 */} +
+
+ {/* 로딩 상태 */} + {(isLoading || isUpdatingMembers) && ( +
+
+

+ 캐릭터 정보를 불러오는 중... +

+
+ )} + + {/* 멤버 정보 */} + {guildsInfo && + guildsInfo.length > 0 && + !isLoading && + !isUpdatingMembers && ( + ({ + guildName: v.guildName, + guildMasterName: v.guildMasterName, + memberDetailResponse: v.guildMember + }))} + masterName={selectedGuildMember?.guildMasterName} + guildName={selectedGuildMember?.guildName} + onSelect={handleMemberSelect} + searchCharacter={searchCharacter} + setSearchCharacter={handleSearchCharacter} + /> + )} + + {/* 빈 상태 */} + {guildsInfo && guildsInfo.length === 0 && ( + + )} +
+
)} + + {/* 모달 */} {activeModal === 'detailMember' && selectedMember && selectedMember.member && From 139c2a158468f6940add4912ee5433c238cb4029 Mon Sep 17 00:00:00 2001 From: echo Date: Mon, 8 Sep 2025 00:04:14 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[Style]=20=EC=BA=90=EB=A6=AD=ED=84=B0=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/character/CharacterPage.tsx | 225 +++++++++++++-------- 1 file changed, 143 insertions(+), 82 deletions(-) diff --git a/src/components/character/CharacterPage.tsx b/src/components/character/CharacterPage.tsx index 66e8d89..6d61b36 100644 --- a/src/components/character/CharacterPage.tsx +++ b/src/components/character/CharacterPage.tsx @@ -6,11 +6,9 @@ import { InventoryContainer } from './inventory/InventoryContainer' import { StatContainer } from './StatContainer' import { useCharacterData } from '../../hooks/character/useCharacterData' import { useInventory } from '../../hooks/character/useInventory' - import { useUserStore } from '../../store/userStore' import { searchCharacterOcid } from '../../apis/character/characterController' - -import { FiAlertTriangle, FiSearch } from 'react-icons/fi' +import { FiAlertTriangle, FiSearch, FiInfo } from 'react-icons/fi' import Button from '../common/Button' interface CharacterPageProps { @@ -21,11 +19,8 @@ export const CharacterPage = ({ type }: CharacterPageProps) => { const { characterStats, ability, hyperStat, basic, isLoading, error } = useCharacterData() const [characterName, setCharacterName] = useState('') - const { inventory } = useInventory() - const [showStats, setShowStats] = useState(true) - const { setCharacterOcid } = useUserStore() const [searchLoading, setSearchLoading] = useState(false) @@ -52,35 +47,13 @@ export const CharacterPage = ({ type }: CharacterPageProps) => { if (error) { return ( -
-
+
+
{type === 'character' && ( -
+
- {/* */}
@@ -114,6 +87,26 @@ export const CharacterPage = ({ type }: CharacterPageProps) => {

2023년 12월 21일 이후의 데이터만 조회할 수 있습니다.

+ + {/* 모바일용 도움말 */} + {type === 'character' && ( +
+
+ +
+

+ 본캐릭터는 넥슨 OpenAPI에서 레벨이 가장 높은 캐릭터를 + 기준으로 자동 설정됩니다. +

+

+ 정보가 정확하지 않다면{' '} + 동기화 버튼을 + 눌러주세요. +

+
+
+
+ )}
@@ -155,33 +148,63 @@ export const CharacterPage = ({ type }: CharacterPageProps) => { return (
- {/* 탭 버튼 */} -
+ {/* 모바일 헤더 (lg 미만에서만 표시) */} +
+
+ {/* 캐릭터 검색 */} +
+ setCharacterName(e.target.value)} + /> + +
+ + {/* 탭 네비게이션 */} +
+ + +
+ + {/* 도움말 (캐릭터 타입일 때만) */} + {type === 'character' && ( +
+

+ 💡 본캐는 최고레벨 캐릭터로 자동설정됩니다. 정확하지 않다면 + 동기화 버튼을 눌러주세요. +

+
+ )} +
+
+ + {/* 기존 데스크톱 탭 버튼 (lg 이상에서만 표시) */} +
{type === 'character' ? (
- {/* */}
@@ -232,7 +255,7 @@ export const CharacterPage = ({ type }: CharacterPageProps) => { placeholder="캐릭터 이름을 입력해주세요" className="flex-1 px-3 py-1.5 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white" value={characterName} - onChange={e => setCharacterName?.(e.target.value)} + onChange={e => setCharacterName(e.target.value)} /> -
-
-
-
-
- ) - } - - return ( -
- {/* 모바일 헤더 (lg 미만에서만 표시) */} -
-
- {/* 캐릭터 검색 */} -
- setCharacterName(e.target.value)} - /> - -
- - {/* 탭 네비게이션 */} -
- - -
- - {/* 도움말 (캐릭터 타입일 때만) */} - {type === 'character' && ( -
-

- 💡 본캐는 최고레벨 캐릭터로 자동설정됩니다. 정확하지 않다면 - 동기화 버튼을 눌러주세요. -

-
- )} -
-
- - {/* 기존 데스크톱 탭 버튼 (lg 이상에서만 표시) */} -
- {type === 'character' ? ( -
-
-
-
-
-
-

- 본캐릭터는 넥슨 OpenAPI에서 레벨이 가장 높은 캐릭터를 - 기준으로 자동 설정됩니다. -

-

- - 정보가 정확하지 않다면 - - 동기화 - 버튼을 눌러주세요 -

-
-
-
-
-
- ) : ( -
- )} -
- - -
- -
- setCharacterName(e.target.value)} - /> - -
-
- - {/* 콘텐츠 영역 */} - {isLoading ? ( -
- {showStats ? ( - // 데스크톱 스켈레톤 (lg 이상) -
-
-
-
-
-
-
-
-
-
-
-
- ) : ( -
-
-
- {Array.from({ length: 15 }).map((_, index) => ( -
- ))} -
-
- )} - - {/* 모바일 스켈레톤 (lg 미만) */} -
- {showStats ? ( - <> -
-
-
-
- - ) : ( - <> -
-
- {Array.from({ length: 15 }).map((_, index) => ( -
- ))} -
- - )} -
-
- ) : ( -
- {showStats ? ( - <> - {/* 데스크톱 레이아웃 (lg 이상) */} -
-
-
{basic && }
-
- {ability && } -
-
-
- {characterStats && } -
-
- {hyperStat && } -
-
- - {/* 모바일 레이아웃 (lg 미만) */} -
- {basic && ( -
- -
- )} - {ability && ( -
- -
- )} - {characterStats && ( -
- -
- )} - {hyperStat && ( -
- -
- )} -
- - ) : ( -
- {inventory && basic?.character_image && ( - - )} -
- )} -
- )} -
- ) -} diff --git a/src/components/character/containers/CharacterDesktopHeader.tsx b/src/components/character/containers/CharacterDesktopHeader.tsx new file mode 100644 index 0000000..80031c4 --- /dev/null +++ b/src/components/character/containers/CharacterDesktopHeader.tsx @@ -0,0 +1,93 @@ +interface CharacterDesktopHeaderProps { + type: 'character' | 'search' + characterName: string + setCharacterName: (name: string) => void + searchLoading: boolean + onSearch: () => void + showStats: boolean + setShowStats: (show: boolean) => void +} + +export const CharacterDesktopHeader = ({ + type, + characterName, + setCharacterName, + searchLoading, + onSearch, + showStats, + setShowStats +}: CharacterDesktopHeaderProps) => { + return ( +
+ {type === 'character' ? ( +
+
+
+
+
+
+

+ 본캐릭터는 넥슨 OpenAPI에서 레벨이 가장 높은 캐릭터를 + 기준으로 자동 설정됩니다. +

+

+ + 정보가 정확하지 않다면 + + 동기화 + 버튼을 눌러주세요 +

+
+
+
+
+
+ ) : ( +
+ )} + + {/* 탭 버튼 */} +
+ + +
+ + {/* 검색 입력 */} +
+ setCharacterName(e.target.value)} + /> + +
+
+ ) +} diff --git a/src/components/character/CharacterInfoContainer.tsx b/src/components/character/containers/CharacterInfoContainer.tsx similarity index 93% rename from src/components/character/CharacterInfoContainer.tsx rename to src/components/character/containers/CharacterInfoContainer.tsx index 340e284..2fd6cfb 100644 --- a/src/components/character/CharacterInfoContainer.tsx +++ b/src/components/character/containers/CharacterInfoContainer.tsx @@ -1,5 +1,5 @@ -import { CharacterBasic } from '../../types/character' -import { formatDate } from '../../utils/format' +import { CharacterBasic } from '../../../types/character' +import { formatDate } from '../../../utils/format' interface Props { basic: CharacterBasic diff --git a/src/components/character/containers/CharacterMobileHeader.tsx b/src/components/character/containers/CharacterMobileHeader.tsx new file mode 100644 index 0000000..c527a5e --- /dev/null +++ b/src/components/character/containers/CharacterMobileHeader.tsx @@ -0,0 +1,70 @@ +interface CharacterMobileHeaderProps { + type: 'character' | 'search' + characterName: string + setCharacterName: (name: string) => void + searchLoading: boolean + onSearch: () => void + showStats: boolean + setShowStats: (show: boolean) => void +} + +export const CharacterMobileHeader = ({ + type, + characterName, + setCharacterName, + searchLoading, + onSearch, + showStats, + setShowStats +}: CharacterMobileHeaderProps) => { + return ( +
+
+ {/* 캐릭터 검색 */} +
+ setCharacterName(e.target.value)} + /> + +
+ + {/* 탭 네비게이션 */} +
+ + +
+ + {/* 도움말 (캐릭터 타입일 때만) */} + {type === 'character' && ( +
+

+ 💡 본캐는 최고레벨 캐릭터로 자동설정됩니다. 정확하지 않다면 동기화 + 버튼을 눌러주세요. +

+
+ )} +
+
+ ) +} diff --git a/src/components/character/pages/CharacterContent.tsx b/src/components/character/pages/CharacterContent.tsx new file mode 100644 index 0000000..b098e58 --- /dev/null +++ b/src/components/character/pages/CharacterContent.tsx @@ -0,0 +1,86 @@ +import { InventoryContainer } from '../inventory/InventoryContainer' +import { + CharacterStats, + CharacterAbility, + HyperStat, + CharacterBasic +} from '../../../types/character' + +import { Inventory } from '../../../types/item' +import { CharacterInfoContainer } from '../containers/CharacterInfoContainer' +import { AbilitryContainer } from '../stats/AbilitryContainer' +import StatContainer from '../stats/StatContainer' +import { HyperStatContainer } from '../stats/HyperStatContainer' + +interface CharacterContentProps { + showStats: boolean + basic?: CharacterBasic + ability?: CharacterAbility + characterStats?: CharacterStats + hyperStat?: HyperStat + inventory?: Inventory +} + +export const CharacterContent = ({ + showStats, + basic, + ability, + characterStats, + hyperStat, + inventory +}: CharacterContentProps) => { + return ( +
+ {showStats ? ( + <> + {/* 데스크톱 레이아웃 (lg 이상) */} +
+
+
{basic && }
+
{ability && }
+
+
+ {characterStats && } +
+
+ {hyperStat && } +
+
+ + {/* 모바일 레이아웃 (lg 미만) */} +
+ {basic && ( +
+ +
+ )} + {ability && ( +
+ +
+ )} + {characterStats && ( +
+ +
+ )} + {hyperStat && ( +
+ +
+ )} +
+ + ) : ( +
+ {inventory && basic?.character_image && ( + + )} +
+ )} +
+ ) +} diff --git a/src/components/character/pages/CharacterErrorState.tsx b/src/components/character/pages/CharacterErrorState.tsx new file mode 100644 index 0000000..d440f4e --- /dev/null +++ b/src/components/character/pages/CharacterErrorState.tsx @@ -0,0 +1,138 @@ +import { useState } from 'react' +import { FiAlertTriangle, FiSearch, FiInfo } from 'react-icons/fi' +import Button from '../../common/Button' +import { searchCharacterOcid } from '../../../apis/character/characterController' +import { useUserStore } from '../../../store/userStore' + +interface CharacterErrorStateProps { + type: 'character' | 'search' +} + +export const CharacterErrorState = ({ type }: CharacterErrorStateProps) => { + const [characterName, setCharacterName] = useState('') + const [searchLoading, setSearchLoading] = useState(false) + const { setCharacterOcid } = useUserStore() + + const searchCharacterHandler = async () => { + if (characterName.trim() === '') { + alert('캐릭터 이름을 입력해주세요.') + return + } + setSearchLoading(true) + + try { + const { ocid } = await searchCharacterOcid(characterName.trim()) + if (!ocid) { + alert('캐릭터를 찾을 수 없습니다.') + return + } + setCharacterOcid(ocid) + } catch { + alert('캐릭터 검색에 실패했습니다.') + } finally { + setSearchLoading(false) + } + } + + return ( +
+
+
+
+ {type === 'character' && ( +
+
+
+
+
+
+

+ 본캐릭터는 넥슨 OpenAPI에서 레벨이 가장 높은 캐릭터를 + 기준으로 자동 설정됩니다. +

+

+ + 정보가 정확하지 않다면 + + 동기화 + + 버튼을 눌러주세요 + +

+
+
+
+
+
+ )} +
+ +
+
+ +

+ 캐릭터 정보를 불러올 수 없습니다 +

+

+ 2023년 12월 21일 이후의 데이터만 조회할 수 있습니다. +

+ + {/* 모바일용 도움말 */} + {type === 'character' && ( +
+
+ +
+

+ 본캐릭터는 넥슨 OpenAPI에서 레벨이 가장 높은 캐릭터를 + 기준으로 자동 설정됩니다. +

+

+ 정보가 정확하지 않다면{' '} + 동기화 버튼을 + 눌러주세요. +

+
+
+
+ )} +
+ + {/* 검색 폼 */} +
+
+
+
+ +
+

+ 캐릭터 검색 +

+
+
+ setCharacterName(e.target.value)} + className="w-full px-4 py-2.5 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm bg-white" + /> + +
+
+
+
+
+ ) +} diff --git a/src/components/character/pages/CharacterLoadingSkeleton.tsx b/src/components/character/pages/CharacterLoadingSkeleton.tsx new file mode 100644 index 0000000..907b84c --- /dev/null +++ b/src/components/character/pages/CharacterLoadingSkeleton.tsx @@ -0,0 +1,63 @@ +interface CharacterLoadingSkeletonProps { + showStats: boolean +} + +export const CharacterLoadingSkeleton = ({ + showStats +}: CharacterLoadingSkeletonProps) => { + return ( +
+ {showStats ? ( + <> + {/* 데스크톱 스켈레톤 (lg 이상) */} +
+
+
+
+
+
+
+
+
+
+
+
+ + {/* 모바일 스켈레톤 (lg 미만) */} +
+
+
+
+
+
+ + ) : ( + <> + {/* 데스크톱 장비 스켈레톤 */} +
+
+
+ {Array.from({ length: 15 }).map((_, index) => ( +
+ ))} +
+
+ + {/* 모바일 장비 스켈레톤 */} +
+
+
+ {Array.from({ length: 15 }).map((_, index) => ( +
+ ))} +
+
+ + )} +
+ ) +} diff --git a/src/components/character/pages/CharacterPage.tsx b/src/components/character/pages/CharacterPage.tsx new file mode 100644 index 0000000..3129eee --- /dev/null +++ b/src/components/character/pages/CharacterPage.tsx @@ -0,0 +1,92 @@ +import { useState } from 'react' +import { useCharacterData } from '../../../hooks/character/useCharacterData' +import { useInventory } from '../../../hooks/character/useInventory' +import { useUserStore } from '../../../store/userStore' +import { searchCharacterOcid } from '../../../apis/character/characterController' + +import { CharacterErrorState } from '../pages/CharacterErrorState' + +import { CharacterLoadingSkeleton } from '../pages/CharacterLoadingSkeleton' +import { CharacterContent } from '../pages/CharacterContent' +import { CharacterDesktopHeader } from '../containers/CharacterDesktopHeader' +import { CharacterMobileHeader } from '../containers/CharacterMobileHeader' + +interface CharacterPageProps { + type: 'character' | 'search' +} + +export const CharacterPage = ({ type }: CharacterPageProps) => { + const { characterStats, ability, hyperStat, basic, isLoading, error } = + useCharacterData() + const { inventory } = useInventory() + const [characterName, setCharacterName] = useState('') + const [showStats, setShowStats] = useState(true) + const [searchLoading, setSearchLoading] = useState(false) + const { setCharacterOcid } = useUserStore() + + const searchCharacterHandler = async () => { + if (characterName.trim() === '') { + alert('캐릭터 이름을 입력해주세요.') + return + } + setSearchLoading(true) + + try { + const { ocid } = await searchCharacterOcid(characterName.trim()) + if (!ocid) { + alert('캐릭터를 찾을 수 없습니다.') + return + } + setCharacterOcid(ocid) + } catch { + alert('캐릭터 검색에 실패했습니다.') + } finally { + setSearchLoading(false) + } + } + + // 에러 상태 + if (error) { + return + } + + return ( +
+ {/* 모바일 헤더 */} + + + {/* 데스크톱 헤더 */} + + + {/* 컨텐츠 */} + {isLoading ? ( + + ) : ( + + )} +
+ ) +} diff --git a/src/components/character/AbilitryContainer.tsx b/src/components/character/stats/AbilitryContainer.tsx similarity index 96% rename from src/components/character/AbilitryContainer.tsx rename to src/components/character/stats/AbilitryContainer.tsx index 98c911d..db18c1c 100644 --- a/src/components/character/AbilitryContainer.tsx +++ b/src/components/character/stats/AbilitryContainer.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { CharacterAbility } from '../../types/character' +import { CharacterAbility } from '../../../types/character' interface Props { ability: CharacterAbility diff --git a/src/components/character/DoubleStatRow.tsx b/src/components/character/stats/DoubleStatRow.tsx similarity index 100% rename from src/components/character/DoubleStatRow.tsx rename to src/components/character/stats/DoubleStatRow.tsx diff --git a/src/components/character/HyperStatContainer.tsx b/src/components/character/stats/HyperStatContainer.tsx similarity index 96% rename from src/components/character/HyperStatContainer.tsx rename to src/components/character/stats/HyperStatContainer.tsx index 11a8d6d..5e7bd65 100644 --- a/src/components/character/HyperStatContainer.tsx +++ b/src/components/character/stats/HyperStatContainer.tsx @@ -1,6 +1,7 @@ import { useState } from 'react' -import { HyperStat } from '../../types/character' + import { HyperStatTable } from './HyperStatTable' +import { HyperStat } from '../../../types/character' interface Props { hyperStat: HyperStat diff --git a/src/components/character/HyperStatTable.tsx b/src/components/character/stats/HyperStatTable.tsx similarity index 93% rename from src/components/character/HyperStatTable.tsx rename to src/components/character/stats/HyperStatTable.tsx index 00408b3..0d1e8f6 100644 --- a/src/components/character/HyperStatTable.tsx +++ b/src/components/character/stats/HyperStatTable.tsx @@ -1,4 +1,4 @@ -import { HyperStatInfo } from '../../types/character' +import { HyperStatInfo } from '../../../types/character' interface Props { hyperStat: HyperStatInfo diff --git a/src/components/character/StatContainer.tsx b/src/components/character/stats/StatContainer.tsx similarity index 97% rename from src/components/character/StatContainer.tsx rename to src/components/character/stats/StatContainer.tsx index 0d26f61..3f777a5 100644 --- a/src/components/character/StatContainer.tsx +++ b/src/components/character/stats/StatContainer.tsx @@ -1,6 +1,6 @@ -import { CharacterStats } from '../../types/character' -import { formatKoreanNumber } from '../../utils/format' -import { getStatValue } from '../../utils/getStatValue' +import { CharacterStats } from '../../../types/character' +import { formatKoreanNumber } from '../../../utils/format' +import { getStatValue } from '../../../utils/getStatValue' import StatTable from './StatTable' interface Props { diff --git a/src/components/character/StatTable.tsx b/src/components/character/stats/StatTable.tsx similarity index 100% rename from src/components/character/StatTable.tsx rename to src/components/character/stats/StatTable.tsx diff --git a/src/pages/Character.tsx b/src/pages/Character.tsx index 1ec2480..7ede4c2 100644 --- a/src/pages/Character.tsx +++ b/src/pages/Character.tsx @@ -1,4 +1,4 @@ -import { CharacterPage } from '../components/character/CharacterPage' +import { CharacterPage } from '../components/character/pages/CharacterPage' const Character = () => { return diff --git a/src/pages/SearchCharacter.tsx b/src/pages/SearchCharacter.tsx index b0a49b9..2118fe9 100644 --- a/src/pages/SearchCharacter.tsx +++ b/src/pages/SearchCharacter.tsx @@ -1,4 +1,4 @@ -import { CharacterPage } from '../components/character/CharacterPage' +import { CharacterPage } from '../components/character/pages/CharacterPage' export const SearchCharacter = () => { return diff --git a/src/pages/SearchGuild.tsx b/src/pages/SearchGuild.tsx index 8eb0d24..5a07d31 100644 --- a/src/pages/SearchGuild.tsx +++ b/src/pages/SearchGuild.tsx @@ -1,4 +1,3 @@ -// src/pages/SearchGuild.tsx import { FiUsers, FiArrowLeft } from 'react-icons/fi' import Button from '../components/common/Button' import { useGuildSearch } from '../hooks/search/useGuildSearch' From c1af97ca00788be0e5a2c1b19439765a92a5d33d Mon Sep 17 00:00:00 2001 From: echo Date: Wed, 10 Sep 2025 21:39:57 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[Feat]=20=EC=9D=B8=EB=B2=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20=EB=B0=98=EC=9D=91?= =?UTF-8?q?=ED=98=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../character/inventory/ItemInventory.tsx | 16 ++++++++-------- src/components/character/inventory/Slot.tsx | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/character/inventory/ItemInventory.tsx b/src/components/character/inventory/ItemInventory.tsx index 9a279db..9071ffa 100644 --- a/src/components/character/inventory/ItemInventory.tsx +++ b/src/components/character/inventory/ItemInventory.tsx @@ -40,10 +40,10 @@ const ItemInventory = ({ inventory, characterImg, onSelected }: Props) => { const extraSlots = ['포켓 아이템', '뱃지'] return ( -
-
+
+
{/* 왼쪽 5행 2열 */} -
+
{leftSlots.map(slot => ( {
{/* 가운데 캐릭터 + 아래 슬롯 3개 */} -
-
+
+
-
+
{bottomSlots.map(slot => ( {
{/* 오른쪽 5행 2열 */} -
+
{rightSlots.map(slot => ( {
{/* 아래 포켓, 벳지 */} -
+
{extraSlots.map(slot => ( { return (