diff --git a/src/api/firebase/searchCharacter/searchCharacter.ts b/src/api/firebase/searchCharacter/searchCharacter.ts new file mode 100644 index 0000000..c73ac61 --- /dev/null +++ b/src/api/firebase/searchCharacter/searchCharacter.ts @@ -0,0 +1,41 @@ +import { doc, getDoc, setDoc } from 'firebase/firestore' +import { firestore } from '../config' +import { getCharacterData } from '@/api/lostark/getCharacterData' +import { customDateString } from '@/utils/customDateString' + +async function searchCharacter(character: string) { + const characterRef = doc(firestore, 'characters', character) + + try { + const docSnapshot = await getDoc(characterRef) + + if (docSnapshot.exists()) { + const data = docSnapshot.data() + const lastUpdated = new Date(data.updated) + const oneDayAgo = new Date(customDateString(1)) + + if (lastUpdated < oneDayAgo) { + // 데이터가 1일 이상 지났으면 업데이트 + const newData = await getCharacterData(character) + await setDoc(characterRef, { ...newData, updated: customDateString() }) + return newData + } else { + // 데이터가 최신이면 그대로 반환 + return data // 데이터 구조에 따라 'newData' 필드가 없다면 그냥 'data'를 반환 + } + } else { + // 데이터가 없으면 새로 가져와서 저장 + const newData = await getCharacterData(character) + + if (newData) { + await setDoc(characterRef, { ...newData, updated: customDateString() }) + return newData + } else return null + } + } catch (err) { + console.error('Error in searchCharacter:', err) + throw err // 오류를 상위로 전파 + } +} + +export { searchCharacter } diff --git a/src/api/lostark/getCharacterData.ts b/src/api/lostark/getCharacterData.ts index 284fd7f..b3d1c2d 100644 --- a/src/api/lostark/getCharacterData.ts +++ b/src/api/lostark/getCharacterData.ts @@ -12,7 +12,11 @@ export const getCharacterData = async (chaName: string) => { } ) - return data.data + if (data) { + return data.data + } else { + console.log('not able to load character data:', data) + } } catch (err) { console.error(err) } diff --git a/src/app/[channelId]/schedule/[scheduleId]/page.tsx b/src/app/[channelId]/schedule/[scheduleId]/page.tsx index 80f2eee..a8e65ba 100644 --- a/src/app/[channelId]/schedule/[scheduleId]/page.tsx +++ b/src/app/[channelId]/schedule/[scheduleId]/page.tsx @@ -37,7 +37,7 @@ export default async function ScheduleDetail({ params }: Ownprops) { const userData = await getServerSession(authOptions) return ( -
+
) diff --git a/src/app/characters/page.tsx b/src/app/characters/page.tsx new file mode 100644 index 0000000..3d81106 --- /dev/null +++ b/src/app/characters/page.tsx @@ -0,0 +1,37 @@ +import Header from '@/components/landing/header/Header' +import Search from '@/components/search/Search' +import { authOptions } from '@/utils/authOptions' +import { getServerSession, Session } from 'next-auth' + +interface Ownprops { + searchParams: { + query: string + } +} + +export async function generateMetadata({ searchParams }: Ownprops) { + const characterName = searchParams.query + + if (!characterName) { + return { + title: `로레디 - 유저 검색`, + description: '로스트아크의 유저 정보를 확인할 수 있습니다.' + } + } + + return { + title: `${characterName} - 유저 검색`, + description: '로스트아크의 유저 정보를 확인할 수 있습니다.' + } +} + +export default async function Characters() { + const session = (await getServerSession(authOptions)) as Session + + return ( +
+
+ +
+ ) +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 23bfeea..31079ea 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,16 +1,20 @@ import { Metadata } from 'next' import Header from '@/components/landing/header/Header' import Hero from '@/components/landing/hero/Hero' +import { authOptions } from '@/utils/authOptions' +import { getServerSession, Session } from 'next-auth' export const metadata: Metadata = { title: '로레디 - 로스트아크 레이드 일정 관리, 공대 편성', description: '디스코드 로레디봇을 통해 만든 레이드를 구성하고 관리할 수 있는 사이트' } -export default function Home() { +export default async function Home() { + const session = (await getServerSession(authOptions)) as Session + return (
-
+
) diff --git a/src/components/landing/header/Contact.tsx b/src/components/landing/header/Contact.tsx new file mode 100644 index 0000000..9781790 --- /dev/null +++ b/src/components/landing/header/Contact.tsx @@ -0,0 +1,14 @@ +import { FaDiscord } from 'react-icons/fa' + +export default function Contact() { + return ( + + + + ) +} diff --git a/src/components/landing/header/Gnb.tsx b/src/components/landing/header/Gnb.tsx index 80323b7..e554093 100644 --- a/src/components/landing/header/Gnb.tsx +++ b/src/components/landing/header/Gnb.tsx @@ -1,30 +1,44 @@ +'use client' + import { getUserData } from '@/api/firebase' import { User } from '@/types/users' -import { getServerSession } from 'next-auth' -import { authOptions } from '@/utils/authOptions' +import { Session } from 'next-auth' import HeaderLink from './HeaderLink' +import { useEffect, useState } from 'react' + +interface Ownprops { + session: Session +} -export default async function Gnb() { - let dashboardUrl = '' - const session = await getServerSession(authOptions) +export default function Gnb({ session }: Ownprops) { + const [dashboardUrl, setDashboardUrl] = useState('') - if (session) { - const { channels } = (await getUserData(session.user.id)) as User - dashboardUrl = `${channels[0]}/dashboard` - } + useEffect(() => { + const fetchChannel = async () => { + if (session) { + const { channels } = (await getUserData(session.user.id)) as User + setDashboardUrl(`/${channels[0]}/dashboard`) + } + } + + fetchChannel() + }, []) return ( -
) -const MemberCardContent = ({ data, m, session }: { data: ChaListInterface; m: User; session: Session }) => ( +const MemberCardContent = ({ data, m, session }: { data: ArmoryProfileInterface; m: User; session: Session }) => ( <>
@@ -87,7 +87,7 @@ const MemberCard = async ({ members, session }: OwnProps) => {
    {await Promise.all( sortedMembers.map(async m => { - const data = (await getCharacterProfile(m.registeredBy)) as ChaListInterface + const data = (await getCharacterProfile(m.registeredBy)) as ArmoryProfileInterface const isCurrentUser = session.user.name === m.username const cardClassName = `rounded flex flex-col p-4 w-[16.5rem] h-[20rem] justify-between ${ diff --git a/src/components/members/SettingModal.tsx b/src/components/members/SettingModal.tsx index 9421e76..350a8bf 100644 --- a/src/components/members/SettingModal.tsx +++ b/src/components/members/SettingModal.tsx @@ -1,6 +1,6 @@ import { updateRegisteredChar } from '@/api/firebase' import { getCharacterList } from '@/api/lostark/getCharacterList' -import { ChaListInterface } from '@/types/characterList' +import { ArmoryProfileInterface } from '@/types/Equipments/armory' import { Session } from 'next-auth' import { useReducer, useEffect, useCallback, useMemo } from 'react' import { FaCheck, FaSort } from 'react-icons/fa' @@ -14,14 +14,14 @@ interface OwnProps { interface State { selected: string isDropdownOpen: boolean - charList: ChaListInterface[] + charList: ArmoryProfileInterface[] error: string | null } type Action = | { type: 'SET_SELECTED'; payload: string } | { type: 'TOGGLE_DROPDOWN' } - | { type: 'SET_CHAR_LIST'; payload: ChaListInterface[] } + | { type: 'SET_CHAR_LIST'; payload: ArmoryProfileInterface[] } | { type: 'SET_ERROR'; payload: string } const initialState: State = { @@ -135,7 +135,7 @@ export default function SettingModal({ setIsOpen, registeredBy, session }: OwnPr } interface CharacterItemProps { - character: ChaListInterface + character: ArmoryProfileInterface isSelected: boolean onClick: () => void } diff --git a/src/components/scheduleDetail/CharacterDetail/ArmoryTab.tsx b/src/components/scheduleDetail/CharacterDetail/ArmoryTab.tsx index 297443a..ae98c82 100644 --- a/src/components/scheduleDetail/CharacterDetail/ArmoryTab.tsx +++ b/src/components/scheduleDetail/CharacterDetail/ArmoryTab.tsx @@ -1,17 +1,20 @@ import { useState } from 'react' -import { CardsInterface } from '@/types/Equipments/cards' -import { EquipmentInterface } from '@/types/Equipments/equipments' -import { GemsInterface } from '@/types/Equipments/gems' import Card from './Card' import Gem from './Gem' import Equipment from './Equipment' import Engraving from './Engraving' +import { + ArmoryEquipmentInterface, + ArmoryCardsInterface, + ArmoryGemInterface, + ArmoryEngravingInterface +} from '@/types/Equipments/armory' interface Ownprops { - ArmoryEquipment: EquipmentInterface[] - ArmoryCard: CardsInterface - ArmoryGem: GemsInterface - ArmoryEngraving: any + ArmoryEquipment: ArmoryEquipmentInterface[] + ArmoryCard: ArmoryCardsInterface + ArmoryGem: ArmoryGemInterface + ArmoryEngraving: ArmoryEngravingInterface } export default function ArmoryTab({ ArmoryEquipment, ArmoryCard, ArmoryGem, ArmoryEngraving }: Ownprops) { @@ -43,7 +46,7 @@ export default function ArmoryTab({ ArmoryEquipment, ArmoryCard, ArmoryGem, Armo return (
    -
    +
    {tabArray.map((t, idx) => { return (
    -
    +
    2번 파티 {schedule.parties.party2.map((member, idx) => { return ( diff --git a/src/components/scheduleDetail/TeamAllocator/Popover.tsx b/src/components/scheduleDetail/TeamAllocator/Popover.tsx index 2bae886..0dfab3b 100644 --- a/src/components/scheduleDetail/TeamAllocator/Popover.tsx +++ b/src/components/scheduleDetail/TeamAllocator/Popover.tsx @@ -1,4 +1,3 @@ -import { ChaListInterface } from '@/types/characterList' import { FaSort, FaCheck } from 'react-icons/fa' import { addUserToRaid, deleteUserFromRaid, editPartyCharacter } from '@/api/firebase' import { useState } from 'react' @@ -10,6 +9,7 @@ import useDropdonwStore from '@/stores/dropdownStore' import { useScheduleStore } from '@/stores/scheduleStore' import useCharacterStore from '@/stores/characterStore' import { useCharacterList } from '@/hooks/useCharacterList' +import { ArmoryProfileInterface } from '@/types/Equipments/armory' interface OwnProps { isPopoverOpen: boolean @@ -20,7 +20,7 @@ interface OwnProps { userData: Session | null } -function checkCharacterRaidEligibility(characterList: ChaListInterface[], raidName: string | undefined) { +function checkCharacterRaidEligibility(characterList: ArmoryProfileInterface[], raidName: string | undefined) { switch (raidName) { case '발탄 [노말]': return characterList.filter(char => parseFloat(char.ItemAvgLevel.replace(/,/g, '')) > 1415) @@ -154,7 +154,7 @@ export default function Popover({ {isDropdownOpen && (
    {checkCharacterRaidEligibility(characterList, schedule?.raidName).map( - (character: ChaListInterface, idx: number) => ( + (character: ArmoryProfileInterface, idx: number) => ( {isDropdownOpen && ( -
    +
    {schedule?.characters.map((char, idx) => ( @@ -87,7 +85,7 @@ export default function TeamAllocator({ userData, scheduleId, isLoading }: Ownpr diff --git a/src/components/search/RecentSearches.tsx b/src/components/search/RecentSearches.tsx new file mode 100644 index 0000000..648e88a --- /dev/null +++ b/src/components/search/RecentSearches.tsx @@ -0,0 +1,74 @@ +import React, { useState } from 'react' +import { FaTimes, FaTrash, FaSearch, FaCaretUp } from 'react-icons/fa' + +interface RecentSearchesProps { + searches: string[] + onClearAll: () => void + onRemove: (search: string) => void + onSearch: (search: string) => void +} + +const RecentSearches: React.FC = ({ searches, onClearAll, onRemove, onSearch }) => { + const [fold, setFold] = useState(false) + + const handleFold = () => { + setFold(!fold) + } + + if (searches.length === 0) { + return ( +
    +
    +

    최근 검색어

    +
    +
    + ) + } + + return ( +
    +
    +

    최근 검색어

    +
    + + +
    +
    + {fold ? null : ( +
      + {searches.map(search => ( +
    • + + +
    • + ))} +
    + )} +
    + ) +} + +export default RecentSearches diff --git a/src/components/search/Search.tsx b/src/components/search/Search.tsx new file mode 100644 index 0000000..9c1c5f4 --- /dev/null +++ b/src/components/search/Search.tsx @@ -0,0 +1,19 @@ +'use client' + +import SearchInput from './SearchInput' +import SearchResult from './SearchResult' +import SearchSiblings from './SearchSiblings' + +export default function Search() { + return ( +
    +
    + + +
    +
    + +
    +
    + ) +} diff --git a/src/components/search/SearchInput.tsx b/src/components/search/SearchInput.tsx new file mode 100644 index 0000000..ad87e2a --- /dev/null +++ b/src/components/search/SearchInput.tsx @@ -0,0 +1,93 @@ +'use client' + +import { useRouter, useSearchParams } from 'next/navigation' +import { useState, useEffect } from 'react' +import { FaSearch } from 'react-icons/fa' +import RecentSearches from './RecentSearches' + +export default function SearchInput() { + const [input, setInput] = useState('') + const [recentSearches, setRecentSearches] = useState([]) + const router = useRouter() + const searchParams = useSearchParams() + + useEffect(() => { + // 컴포넌트 마운트 시 로컬 스토리지에서 최근 검색어 불러오기 + const storedSearches = localStorage.getItem('recentSearches') + if (storedSearches) { + setRecentSearches(JSON.parse(storedSearches)) + } + }, []) + + const saveRecentSearches = (searches: string[]) => { + localStorage.setItem('recentSearches', JSON.stringify(searches)) + setRecentSearches(searches) + } + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + + const characterName = input.trim().replace(/\s+/g, '') + + if (characterName) { + // 최근 검색어 업데이트 + let updatedSearches = [characterName, ...recentSearches.filter(s => s !== characterName)] + + // 최근 검색어를 5개로 제한 + if (updatedSearches.length > 5) { + updatedSearches = updatedSearches.slice(0, 5) + } + + const newSearchParams = new URLSearchParams(searchParams.toString()) + newSearchParams.set('query', characterName) + router.push(`?${newSearchParams.toString()}`, { scroll: false }) + + saveRecentSearches(updatedSearches) + } + } + + const handleClearAll = () => { + localStorage.removeItem('recentSearches') + setRecentSearches([]) + } + + const handleRemoveSearch = (searchToRemove: string) => { + const updatedSearches = recentSearches.filter(search => search !== searchToRemove) + saveRecentSearches(updatedSearches) + } + + const handleSearchClick = (search: string) => { + setInput(search) + const newSearchParams = new URLSearchParams(searchParams.toString()) + newSearchParams.set('query', search) + router.push(`?${newSearchParams.toString()}`, { scroll: false }) + } + + return ( +
    +
    + setInput(e.target.value)} + value={input} + type='text' + maxLength={12} + /> + +
    + + +
    + ) +} diff --git a/src/components/search/SearchResult.tsx b/src/components/search/SearchResult.tsx new file mode 100644 index 0000000..864dbdd --- /dev/null +++ b/src/components/search/SearchResult.tsx @@ -0,0 +1,64 @@ +'use client' + +import { useSearchStore } from '@/stores/searchStore' +import CharacterSummary from '../scheduleDetail/CharacterDetail/CharacterSummary' +import ArmoryTab from '../scheduleDetail/CharacterDetail/ArmoryTab' +import { useSearchParams } from 'next/navigation' +import { useEffect } from 'react' +import { FaSpinner } from 'react-icons/fa' +import { FaMagnifyingGlass } from 'react-icons/fa6' + +export default function SearchResult() { + const { character, error, isLoading, searchCharacter, resetSearchResult } = useSearchStore() + const searchParams = useSearchParams() + const characterName = searchParams.get('query') + + useEffect(() => { + if (characterName) { + searchCharacter(characterName.trim().replace(/\s+/g, '')) + } + + return () => { + resetSearchResult() + } + }, [characterName]) + + if (isLoading) { + return ( +
    + +
    + ) + } + + if (error) { + return
    오류가 발생했습니다: {error instanceof Error ? error.message : '알 수 없는 오류'}
    + } + + if (!character) { + return ( +
    + + 캐릭터를 검색해주세요. +
    + ) + } + + return ( + <> + + + + ) +} diff --git a/src/components/search/SearchSiblings.tsx b/src/components/search/SearchSiblings.tsx new file mode 100644 index 0000000..772d3f8 --- /dev/null +++ b/src/components/search/SearchSiblings.tsx @@ -0,0 +1,85 @@ +'use client' + +import { useSiblingsStore } from '@/stores/siblingsStore' +import { useSearchParams, useRouter } from 'next/navigation' +import { useEffect, useState } from 'react' +import { FaSpinner, FaCaretUp } from 'react-icons/fa' + +export default function SearchSiblings() { + const searchParams = useSearchParams() + const router = useRouter() + const { siblings, isLoading, searchSiblings, resetSiblings } = useSiblingsStore() + const characterName = searchParams.get('query') + const [fold, setFold] = useState(false) + + useEffect(() => { + if (characterName) { + searchSiblings(characterName) + } + return () => { + resetSiblings() + } + }, [characterName]) + + if (isLoading) { + return ( +
    + +
    + ) + } + + if (!siblings) { + return ( +
    +
    +

    원정대원 리스트

    +
    +
    + ) + } + + const handleClick = (characterName: string) => { + const newSearchParams = new URLSearchParams(searchParams.toString()) + newSearchParams.set('query', characterName) + router.push(`?${newSearchParams.toString()}`, { scroll: false }) + } + + const handleFold = () => { + setFold(!fold) + } + return ( +
    +
    +

    + {characterName}님의 원정대원 리스트 +

    + +
    + {fold ? null : ( +
      + {siblings.map(character => ( +
    • + +
    • + ))} +
    + )} +
    + ) +} diff --git a/src/hooks/useCharacterList.ts b/src/hooks/useCharacterList.ts index 0942b2e..6181634 100644 --- a/src/hooks/useCharacterList.ts +++ b/src/hooks/useCharacterList.ts @@ -1,6 +1,6 @@ import { getUserData } from '@/api/firebase' import { getCharacterList } from '@/api/lostark/getCharacterList' -import { ChaListInterface } from '@/types/characterList' +import { ArmoryProfileInterface } from '@/types/Equipments/armory' import { User } from '@/types/users' import { useQuery } from '@tanstack/react-query' @@ -15,7 +15,7 @@ export const useCharacterList = (userId: string) => { }) return { - characterList: data as ChaListInterface[], + characterList: data as ArmoryProfileInterface[], isLoading: isPending, error } diff --git a/src/stores/searchStore.ts b/src/stores/searchStore.ts new file mode 100644 index 0000000..491f708 --- /dev/null +++ b/src/stores/searchStore.ts @@ -0,0 +1,51 @@ +import { create } from 'zustand' +import { searchCharacter } from '@/api/firebase/searchCharacter/searchCharacter' +import { + ArmoryAvatarsInterface, + ArmoryCardsInterface, + ArmoryEngravingInterface, + ArmoryEquipmentInterface, + ArmoryGemInterface, + ArmoryProfileInterface, + ArmorySkillsInterface +} from '@/types/Equipments/armory' + +interface CharacterData { + ArmoryAvatars: ArmoryAvatarsInterface[] + ArmoryCard: ArmoryCardsInterface + ArmoryEngraving: ArmoryEngravingInterface + ArmoryEquipment: ArmoryEquipmentInterface[] + ArmoryGem: ArmoryGemInterface + ArmoryProfile: ArmoryProfileInterface + ArmorySkills: ArmorySkillsInterface[] +} + +interface CharacterState { + character: CharacterData | null + isLoading: boolean + error: Error | null + searchCharacter: (character: string) => Promise + resetSearchResult: () => void +} + +export const useSearchStore = create(set => ({ + character: null, + isLoading: false, + error: null, + searchCharacter: async (character: string) => { + set({ isLoading: true, error: null }) + try { + const data = await searchCharacter(character) + + if (data) { + set({ character: data as CharacterData, isLoading: false }) + } else { + throw new Error('Character data not found') + } + } catch (error) { + console.error('Error in searchCharacter:', error) + set({ error: error instanceof Error ? error : new Error('An unknown error occurred'), isLoading: false }) + } + }, + resetSearchResult: () => set({ character: null, error: null, isLoading: false }) +})) diff --git a/src/stores/siblingsStore.ts b/src/stores/siblingsStore.ts new file mode 100644 index 0000000..ecd13d5 --- /dev/null +++ b/src/stores/siblingsStore.ts @@ -0,0 +1,51 @@ +import { create } from 'zustand' +import { getCharacterList } from '@/api/lostark/getCharacterList' + +interface Siblings { + CharacterClassName: string + CharacterLevel: number + CharacterName: string + ItemAvgLevel: string + ItemMaxLevel: string + ServerName: string +} + +interface CharacterState { + siblings: Siblings[] | null + isLoading: boolean + error: Error | null + searchSiblings: (character: string) => Promise + resetSiblings: () => void +} + +function sortByItemAvgLevel(characters: Siblings[]) { + return characters.sort((a, b) => { + const levelA = parseFloat(a.ItemAvgLevel.replace(/,/g, '')) + const levelB = parseFloat(b.ItemAvgLevel.replace(/,/g, '')) + + // 내림차순 정렬 (높은 순) + return levelB - levelA + }) +} + +export const useSiblingsStore = create(set => ({ + siblings: null, + isLoading: false, + error: null, + searchSiblings: async (character: string) => { + set({ isLoading: true, error: null }) + try { + const data = (await getCharacterList(character)) as Siblings[] + + if (data) { + set({ siblings: sortByItemAvgLevel(data), isLoading: false }) + } else { + throw new Error('Character data not found') + } + } catch (error) { + console.error('Error in searchCharacter:', error) + set({ error: error instanceof Error ? error : new Error('An unknown error occurred'), isLoading: false }) + } + }, + resetSiblings: () => set({ siblings: null, error: null, isLoading: false }) +})) diff --git a/src/types/Equipments/armory.ts b/src/types/Equipments/armory.ts new file mode 100644 index 0000000..c4d6700 --- /dev/null +++ b/src/types/Equipments/armory.ts @@ -0,0 +1,85 @@ +export interface ArmoryAvatarsInterface { + Grade: string + Icon: string + isInner: boolean + isSet: boolean + Name: string + Tooltip: string + Type: string +} + +export interface ArmoryCardsInterface { + Cards: { + AwakeCount: number + AwakeTotal: number + Grade: string + Icon: string + Name: string + Slot: number + Tooltip: string + }[] + Effects: { CardSlots: number[]; Items: { Name: string; Description: string }[] }[] +} + +export interface ArmoryEngravingInterface { + ArkPassiveEffects: null + Effects: { Desciption: string; Icon: string; Name: string }[] + Engravings: { Icon: string; name: string; Slot: number; Tooltip: string }[] +} + +export interface ArmoryEquipmentInterface { + Type: string + Name: string + Icon: string + Tooltip: string + Grade: string +} + +export interface ArmoryGemInterface { + Effects: { + Description: string + Skills: { Description: string[]; GemSlot: number; Icon: string; Name: string; Option: string; Tooltip: string }[] + } + Gems: { Grade: string; Icon: string; Level: number; Name: string; Slot: number; Tooltip: string }[] +} + +export interface ArmoryProfileInterface { + ArkPassive: { iseArkPassive: false; Points: { Name: string; Tooltip: string; value: number }[] } + CharacterClassName: string + CharacterImage: string + CharacterLevel: number + CharacterName: string + ExpeditionLevel: number + GuildMemberGrade: string + GuildName: string + ItemAvgLevel: string + ItemMaxLevel: string + PvpGradeName: string + ServerName: string + Stats: { Tooltip: string[]; Type: string; Value: string }[] + Tendencies: { Type: string; Points: number; MaxPoint: number }[] + Title: string + TotalSkillPoint: number + TownLevel: number + TownName: string + UsingSkillPoint: number +} + +export interface ArmorySkillsInterface { + Icon: string + IsAwakening: boolean + Level: number + Name: string + Rune: { Grade: string; Icon: string; Name: string; Tooltip: string } | null + Tooltip: string + Tripods: { + Icon: string + IsSelected: boolean + Level: number + Name: string + Slot: number + Tier: number + Tooltip: string + }[] + Type: string +} diff --git a/src/types/Equipments/cards.ts b/src/types/Equipments/cards.ts deleted file mode 100644 index 64f2d85..0000000 --- a/src/types/Equipments/cards.ts +++ /dev/null @@ -1,25 +0,0 @@ -interface Card { - Slot: number - Name: string - Icon: string - AwakeCount: number - AwakeTotal: number - Grade: string - Tooltip: string -} - -interface EffectItem { - Name: string - Description: string -} - -interface Effect { - Index: number - CardSlots: number[] - Items: EffectItem[] -} - -export interface CardsInterface { - Cards: Card[] - Effects: Effect[] -} diff --git a/src/types/Equipments/engravings.ts b/src/types/Equipments/engravings.ts deleted file mode 100644 index 6741ddb..0000000 --- a/src/types/Equipments/engravings.ts +++ /dev/null @@ -1,17 +0,0 @@ -interface Engraving { - Slot: number - Name: string - Icon: string - Tooltip: string -} - -export interface EngravingEffect { - Icon: string - Name: string - Description: string -} - -export interface EngravingInterface { - Engravings: Engraving[] - Effects: EngravingEffect[] -} diff --git a/src/types/Equipments/equipments.ts b/src/types/Equipments/equipments.ts index d4ae90a..f17b578 100644 --- a/src/types/Equipments/equipments.ts +++ b/src/types/Equipments/equipments.ts @@ -1,11 +1,3 @@ -export interface EquipmentInterface { - Type: string - Name: string - Icon: string - Tooltip: string - Grade: string -} - interface Element { bPoint: number contentStr: string @@ -17,3 +9,48 @@ export interface StoneObjectInterface { Element_001: Element Element_002: Element } + +interface ToolTipElement { + type: string + value: string | ToolTipItemTitle | ToolTipItemPartBox | ToolTipIndentStringGroup | null +} + +export interface ToolTipIndentStringGroup { + Element_000: { + topStr: string + contentStr: StoneObjectInterface + } +} + +interface ToolTipItemTitle { + bEquip: number + leftStr0: string + leftStr2: string + qualityValue: number + rightStr0: string + slotData: { + advBookIcon: number + battleItemTypeIcon: number + cardIcon: boolean + friendship: number + iconGrade: number + iconPath: string + imagePath: string + islandIcon: number + petBorder: number + rtString: string + seal: boolean + temporary: number + town: number + trash: number + } +} + +interface ToolTipItemPartBox { + Element_000: string + Element_001: string +} + +export interface ToolTipObject { + [key: string]: ToolTipElement +} diff --git a/src/types/Equipments/gems.ts b/src/types/Equipments/gems.ts deleted file mode 100644 index 1ab98d1..0000000 --- a/src/types/Equipments/gems.ts +++ /dev/null @@ -1,71 +0,0 @@ -interface Gem { - Slot: number - Name: string - Icon: string - Level: number - Grade: string - Tooltip: string - // Tooltip: { - // Element_000: { - // type: string - // value: string - // } - // Element_001: { - // type: string - // value: { - // bEquip: number - // leftStr0: string - // leftStr2: string - // qualityValue: number - // rightStr0: string - // slotData: { - // advBookIcon: number - // battleItemTypeIcon: number - // cardIcon: boolean - // friendship: number - // iconGrade: number - // iconPath: string - // imagePath: string - // islandIcon: number - // petBorder: number - // rtString: string - // seal: boolean - // temporary: number - // town: number - // trash: number - // } - // } - // } - // Element_002: { - // type: string - // value: string - // } - // Element_003: { - // type: string - // value: string - // } - // Element_004: { - // type: string - // value: string - // } - // Element_005: { - // type: string - // value: { - // Element_000: string - // Element_001: string - // } - // } - // Element_006: { - // type: string - // value: string - // } - // Element_007: { - // type: string - // value: string - // } - // } -} - -export interface GemsInterface { - Gems: Gem[] -} diff --git a/src/types/characterList.ts b/src/types/characterList.ts deleted file mode 100644 index 2a87b9b..0000000 --- a/src/types/characterList.ts +++ /dev/null @@ -1,13 +0,0 @@ -export interface ChaListInterface { - CharacterClassName: string - CharacterLevel: number - CharacterName: string - ItemAvgLevel: string - ItemMaxLevel: string - ServerName: string - CharacterImage: string - ExpeditionLevel: number - TownName: string - GuildName: string - Title: string -} diff --git a/src/types/gameProfile.ts b/src/types/gameProfile.ts deleted file mode 100644 index 26cfabc..0000000 --- a/src/types/gameProfile.ts +++ /dev/null @@ -1,32 +0,0 @@ -interface Stat { - Type: string - Value: string - Tooltip: string[] -} - -interface Tendency { - Type: string - Point: number - MaxPoint: number -} - -export interface ProfileInterface { - CharacterImage: string - ExpeditionLevel: number - PvpGradeName: string - TownLevel: number - TownName: string - Title: string - GuildMemberGrade: string - GuildName: string - UsingSkillPoint: number - TotalSkillPoint: number - Stats: Stat[] - Tendencies: Tendency[] - ServerName: string - CharacterName: string - CharacterLevel: number - CharacterClassName: string - ItemAvgLevel: string - ItemMaxLevel: string -} diff --git a/src/utils/customDateString.ts b/src/utils/customDateString.ts index bbde36a..0fd081b 100644 --- a/src/utils/customDateString.ts +++ b/src/utils/customDateString.ts @@ -1,5 +1,7 @@ -function customDateString() { +function customDateString(daysToSubtract: number = 0) { const currentDate = new Date() + currentDate.setDate(currentDate.getDate() - daysToSubtract) + const year = currentDate.getFullYear() const month = String(currentDate.getMonth() + 1).padStart(2, '0') const day = String(currentDate.getDate()).padStart(2, '0') diff --git a/src/utils/getAccQualityAvg.ts b/src/utils/getAccQualityAvg.ts index 592cb25..067925e 100644 --- a/src/utils/getAccQualityAvg.ts +++ b/src/utils/getAccQualityAvg.ts @@ -1,6 +1,6 @@ -import { EquipmentInterface } from '@/types/Equipments/equipments' +import { ArmoryEquipmentInterface } from '@/types/Equipments/armory' -export const getAccQualityAvg = (accessories: EquipmentInterface[]) => { +export const getAccQualityAvg = (accessories: ArmoryEquipmentInterface[]) => { let sum = 0 for (let i = 0; i < accessories.length; i++) { diff --git a/src/utils/getAccStatSum.ts b/src/utils/getAccStatSum.ts index 6be1d85..0bdb16d 100644 --- a/src/utils/getAccStatSum.ts +++ b/src/utils/getAccStatSum.ts @@ -1,6 +1,6 @@ -import { EquipmentInterface } from '@/types/Equipments/equipments' +import { ArmoryEquipmentInterface } from '@/types/Equipments/armory' -export const getAccStatSum = (accessories: EquipmentInterface[]) => { +export const getAccStatSum = (accessories: ArmoryEquipmentInterface[]) => { let sum = 0 for (let i = 0; i < accessories.length; i++) { diff --git a/src/utils/getBraceletAbility.ts b/src/utils/getBraceletAbility.ts index f7cfb7a..9882626 100644 --- a/src/utils/getBraceletAbility.ts +++ b/src/utils/getBraceletAbility.ts @@ -1,6 +1,6 @@ -import { EquipmentInterface } from '@/types/Equipments/equipments' +import { ArmoryEquipmentInterface } from '@/types/Equipments/armory' -export const getBraceletAbility = (equipment: EquipmentInterface) => { +export const getBraceletAbility = (equipment: ArmoryEquipmentInterface) => { if (equipment) { const parsedObject = JSON.parse(equipment.Tooltip) const braceletJson = parsedObject.Element_004.value.Element_001 diff --git a/src/utils/getEquipmentAndAccessories.ts b/src/utils/getEquipmentAndAccessories.ts index 9eb1c9a..4679acd 100644 --- a/src/utils/getEquipmentAndAccessories.ts +++ b/src/utils/getEquipmentAndAccessories.ts @@ -1,6 +1,6 @@ -import { EquipmentInterface } from '@/types/Equipments/equipments' +import { ArmoryEquipmentInterface } from '@/types/Equipments/armory' -export const getEquipmentAndAccessories = (ArmoryEquipment: EquipmentInterface[]) => { +export const getEquipmentAndAccessories = (ArmoryEquipment: ArmoryEquipmentInterface[]) => { const equipments = [] const accessories = [] const braceletAndStone = [] diff --git a/src/utils/getSetOption.ts b/src/utils/getSetOption.ts index c9accd3..adc320d 100644 --- a/src/utils/getSetOption.ts +++ b/src/utils/getSetOption.ts @@ -1,10 +1,10 @@ -import { EquipmentInterface } from '@/types/Equipments/equipments' +import { ArmoryEquipmentInterface } from '@/types/Equipments/armory' interface Result { [key: string]: number[] } -export const getSetOption = (armoryEquipment: EquipmentInterface[]) => { +export const getSetOption = (armoryEquipment: ArmoryEquipmentInterface[]) => { const result: Result = {} // 정규식 패턴