poi-plugin-quest-info-2 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/.eslintrc.js +1 -2
  2. package/build/kcQuestsData/DATA_VERSION +1 -1
  3. package/build/kcQuestsData/index.ts +1 -1
  4. package/build/kcQuestsData/quests-scn-new.json +1 -3
  5. package/build/kcQuestsData/quests-scn.json +72 -72
  6. package/build/kcanotifyGamedata/DATA_VERSION +1 -1
  7. package/build/kcanotifyGamedata/index.ts +1 -1
  8. package/build/kcanotifyGamedata/quests-en.json +12 -0
  9. package/build/kcanotifyGamedata/quests-jp.json +12 -0
  10. package/build/kcanotifyGamedata/quests-ko.json +12 -5
  11. package/build/kcanotifyGamedata/quests-scn.json +12 -0
  12. package/build/kcanotifyGamedata/quests-tcn.json +12 -0
  13. package/build/prePostQuest.json +4498 -0
  14. package/build/questCategory.json +590 -588
  15. package/build/questCodeMap.json +575 -0
  16. package/i18n/en-US.json +1 -0
  17. package/i18n/ja-JP.json +1 -0
  18. package/i18n/ko-KR.json +1 -0
  19. package/i18n/zh-CN.json +1 -0
  20. package/i18n/zh-TW.json +1 -0
  21. package/package.json +15 -15
  22. package/src/__tests__/__snapshots__/questCategory.spec.ts.snap +113 -113
  23. package/src/__tests__/kcanotifyData.spec.ts +14 -1
  24. package/src/__tests__/kcwikiData.spec.ts +11 -1
  25. package/src/__tests__/questCategory.spec.ts +4 -4
  26. package/src/components/QuestCard/MinimalQuestCard.tsx +14 -14
  27. package/src/components/QuestCard/index.tsx +90 -55
  28. package/src/components/QuestCard/styles.ts +17 -0
  29. package/src/components/QuestList.tsx +5 -8
  30. package/src/components/QuestTag.tsx +104 -0
  31. package/src/poi/hooks.ts +8 -5
  32. package/src/questHelper.ts +25 -4
  33. package/src/store/kcwiki.ts +7 -3
  34. package/src/store/quest.ts +91 -10
  35. package/src/tags.tsx +2 -2
  36. package/scripts/convertAssets.ts +0 -57
  37. package/scripts/downloadKcQuestsData.ts +0 -136
  38. package/scripts/downloadKcanotifyGamedata.ts +0 -132
  39. package/scripts/downloadSprites.ts +0 -126
  40. package/scripts/genQuestCategory.ts +0 -58
  41. package/scripts/proxyFetch.ts +0 -42
  42. package/scripts/utils.ts +0 -8
  43. package/src/components/PreTaskTag.tsx +0 -40
@@ -1,7 +1,7 @@
1
1
  import { version, QuestData } from '../../build/kcanotifyGamedata'
2
2
 
3
3
  test('should Kcanotify Game data version correct', () => {
4
- expect(version).toMatchInlineSnapshot(`"2022040401"`)
4
+ expect(version).toMatchInlineSnapshot(`"2022042601"`)
5
5
  })
6
6
 
7
7
  test('should Kcanotify Game data keys correct', () => {
@@ -15,3 +15,16 @@ Array [
15
15
  ]
16
16
  `)
17
17
  })
18
+
19
+ describe('should format correct', () => {
20
+ Object.keys(QuestData).forEach((lang) => {
21
+ test(`${lang} key format`, () => {
22
+ Object.keys(QuestData[lang as keyof typeof QuestData]).forEach((key) => {
23
+ // gameId should not extra space
24
+ expect(key.trim()).toEqual(key)
25
+ // gameId should be number
26
+ expect(String(+key)).toEqual(key)
27
+ })
28
+ })
29
+ })
30
+ })
@@ -1,9 +1,10 @@
1
1
  import { version, KcwikiQuestData } from '../../build/kcQuestsData'
2
+ import newQuestData from '../../build/kcQuestsData/quests-scn-new.json'
2
3
 
3
4
  describe('should version correct', () => {
4
5
  test('should KcwikiQuestData Game data version correct', () => {
5
6
  expect(version).toMatchInlineSnapshot(
6
- `"2b2c2222f933ff9863dec8c72fc6037fbfe375ac"`
7
+ `"cf24003d54c1b9cb2f6a76cdd670de717de0886c"`
7
8
  )
8
9
  })
9
10
 
@@ -25,4 +26,13 @@ describe('should format correct', () => {
25
26
  expect(String(+key)).toEqual(key)
26
27
  })
27
28
  })
29
+
30
+ test('new quest key format', () => {
31
+ Object.keys(newQuestData).forEach((gameId) => {
32
+ // gameId should not extra space
33
+ expect(gameId.trim()).toEqual(gameId)
34
+ // gameId should be number
35
+ expect(String(+gameId)).toEqual(gameId)
36
+ })
37
+ })
28
38
  })
@@ -9,7 +9,7 @@ describe('should questCategory correct', () => {
9
9
  expect(questCategory.monthlyQuest.length).toMatchInlineSnapshot(`11`)
10
10
  expect(questCategory.quarterlyQuest.length).toMatchInlineSnapshot(`25`)
11
11
  expect(questCategory.yearlyQuest.length).toMatchInlineSnapshot(`37`)
12
- expect(questCategory.singleQuest.length).toMatchInlineSnapshot(`475`)
12
+ expect(questCategory.singleQuest.length).toMatchInlineSnapshot(`477`)
13
13
  })
14
14
 
15
15
  test('snapshot', () => {
@@ -21,11 +21,11 @@ describe('should questCategory correct', () => {
21
21
  Object.entries(questCategory).map(([key, val]) => [
22
22
  key,
23
23
  val
24
- .sort((a, b) => +a - +b)
24
+ .sort((a, b) => a - b)
25
25
  .map((gameId) => ({
26
26
  gameId,
27
- code: mergeData[gameId as keyof typeof mergeData].code,
28
- name: mergeData[gameId as keyof typeof mergeData].name,
27
+ code: mergeData[String(gameId) as keyof typeof mergeData].code,
28
+ name: mergeData[String(gameId) as keyof typeof mergeData].name,
29
29
  })),
30
30
  ])
31
31
  )
@@ -1,19 +1,19 @@
1
- import { Elevation, Text, Tooltip } from '@blueprintjs/core'
2
- import React from 'react'
1
+ import { Card, Elevation, Text, Tooltip } from '@blueprintjs/core'
2
+ import React, { forwardRef } from 'react'
3
+ import type { StyledComponentProps } from 'styled-components'
3
4
  import { guessQuestCategory, QUEST_STATUS } from '../../questHelper'
4
5
  import type { QuestCardProps } from './index'
5
6
  import { CardBody, CardTail, CatIndicator, FlexCard } from './styles'
6
7
  import { questStatusMap } from './utils'
7
8
 
8
- export const MinimalQuestCard: React.FC<QuestCardProps> = ({
9
- code,
10
- name,
11
- desc,
12
- tip,
13
- status = QUEST_STATUS.DEFAULT,
14
- onClick,
15
- style,
16
- }) => {
9
+ /**
10
+ * @deprecated
11
+ */
12
+ export const MinimalQuestCard = forwardRef<
13
+ Card,
14
+ // eslint-disable-next-line @typescript-eslint/ban-types
15
+ QuestCardProps & StyledComponentProps<typeof Card, any, {}, never>
16
+ >(({ code, name, desc, tip, status = QUEST_STATUS.DEFAULT, ...props }, ref) => {
17
17
  const indicatorColor = guessQuestCategory(code).color
18
18
  const TailIcon = questStatusMap[status]
19
19
 
@@ -29,10 +29,10 @@ export const MinimalQuestCard: React.FC<QuestCardProps> = ({
29
29
  }
30
30
  >
31
31
  <FlexCard
32
+ ref={ref}
32
33
  elevation={Elevation.ZERO}
33
34
  interactive={true}
34
- onClick={onClick}
35
- style={style}
35
+ {...props}
36
36
  >
37
37
  <CatIndicator color={indicatorColor}></CatIndicator>
38
38
  <CardBody>
@@ -45,4 +45,4 @@ export const MinimalQuestCard: React.FC<QuestCardProps> = ({
45
45
  </FlexCard>
46
46
  </Tooltip>
47
47
  )
48
- }
48
+ })
@@ -1,74 +1,109 @@
1
- import { Elevation, H5, Text } from '@blueprintjs/core'
2
- import React from 'react'
3
- import styled from 'styled-components'
1
+ import { Card, Elevation, H5, Text } from '@blueprintjs/core'
2
+ import React, { forwardRef } from 'react'
3
+ import type { StyledComponentProps } from 'styled-components'
4
4
  import { usePluginTranslation } from '../../poi/hooks'
5
- import { guessQuestCategory, QUEST_STATUS } from '../../questHelper'
6
- import { PreTaskTag } from '../PreTaskTag'
7
- import { CardBody, CardMedia, CardTail, FlexCard } from './styles'
5
+ import {
6
+ getQuestPrePost,
7
+ guessQuestCategory,
8
+ QUEST_STATUS,
9
+ } from '../../questHelper'
10
+ import { QuestTag } from '../QuestTag'
11
+ import {
12
+ CardActionWrapper,
13
+ CardBody,
14
+ CardMedia,
15
+ CardTail,
16
+ FlexCard,
17
+ SpanText,
18
+ TagsWrapper,
19
+ } from './styles'
8
20
  import { questIconMap, questStatusMap } from './utils'
9
21
 
10
22
  export type QuestCardProps = {
23
+ gameId: number
11
24
  code: string
12
25
  name: string
13
26
  desc: string | JSX.Element
14
27
  tip?: string
15
28
  tip2?: string
16
29
  status?: QUEST_STATUS
17
- preTask?: string[]
18
- onClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void
19
- style?: React.CSSProperties
30
+ preQuest?: string[]
20
31
  }
21
32
 
22
- const PreTaskTagWrapper = styled.div`
23
- display: flex;
24
- align-items: baseline;
25
- `
26
-
27
- export const LargeQuestCard = ({
28
- code,
29
- name,
30
- desc,
31
- tip,
32
- tip2,
33
- preTask,
34
- status = QUEST_STATUS.DEFAULT,
35
- onClick,
36
- style,
37
- }: QuestCardProps) => {
38
- const headIcon = questIconMap[guessQuestCategory(code).type]
39
- const TailIcon = questStatusMap[status]
33
+ const CardAction = ({ gameId }: { gameId: number }) => {
40
34
  const { t } = usePluginTranslation()
41
35
 
36
+ const prePostQuests = getQuestPrePost(gameId)
37
+
42
38
  return (
43
- <FlexCard
44
- elevation={Elevation.ZERO}
45
- interactive={false}
46
- onClick={onClick}
47
- style={style}
48
- >
49
- <CardMedia src={headIcon}></CardMedia>
50
- <CardBody>
51
- <H5>{[code, name].filter((i) => i != undefined).join(' - ')}</H5>
52
- <Text>{desc}</Text>
53
- {tip2 && <b>{tip2}</b>}
54
- {tip && <i>{tip}</i>}
55
- <PreTaskTagWrapper>
56
- {!!preTask?.length && <span>{t('Requires')}</span>}
57
- {preTask?.map((i) => (
58
- <PreTaskTag key={i} code={i}></PreTaskTag>
59
- ))}
60
- </PreTaskTagWrapper>
61
- </CardBody>
39
+ <CardActionWrapper>
40
+ <TagsWrapper>
41
+ {!!prePostQuests.pre.length && (
42
+ <>
43
+ <SpanText>{t('Requires')}</SpanText>
44
+ {prePostQuests.pre.map((i) => (
45
+ <QuestTag key={i} code={i}></QuestTag>
46
+ ))}
47
+ </>
48
+ )}
49
+ </TagsWrapper>
62
50
 
63
- <CardTail>
64
- <TailIcon />
65
- </CardTail>
66
- </FlexCard>
51
+ <TagsWrapper>
52
+ {!!prePostQuests.post.length && (
53
+ <>
54
+ <SpanText>{t('Unlocks')}</SpanText>
55
+ {prePostQuests.post.map((i) => (
56
+ <QuestTag key={i} code={i}></QuestTag>
57
+ ))}
58
+ </>
59
+ )}
60
+ </TagsWrapper>
61
+ </CardActionWrapper>
67
62
  )
68
63
  }
69
64
 
70
- export const QuestCard: React.FC<QuestCardProps & { gameId: string }> = ({
71
- ...props
72
- }) => {
73
- return <LargeQuestCard {...props}></LargeQuestCard>
74
- }
65
+ export const QuestCard = forwardRef<
66
+ Card,
67
+ // eslint-disable-next-line @typescript-eslint/ban-types
68
+ QuestCardProps & StyledComponentProps<typeof Card, any, {}, never>
69
+ >(
70
+ (
71
+ {
72
+ gameId,
73
+ code,
74
+ name,
75
+ desc,
76
+ tip,
77
+ tip2,
78
+ status = QUEST_STATUS.DEFAULT,
79
+ ...props
80
+ },
81
+ ref
82
+ ) => {
83
+ const headIcon = questIconMap[guessQuestCategory(code).type]
84
+ const TailIcon = questStatusMap[status]
85
+
86
+ return (
87
+ <FlexCard
88
+ ref={ref}
89
+ elevation={Elevation.ZERO}
90
+ interactive={false}
91
+ {...props}
92
+ >
93
+ <CardMedia src={headIcon}></CardMedia>
94
+ <CardBody>
95
+ <H5>{[code, name].filter((i) => i != undefined).join(' - ')}</H5>
96
+ <Text>{desc}</Text>
97
+ {tip2 && <b>{tip2}</b>}
98
+ {tip && <i>{tip}</i>}
99
+
100
+ <CardAction gameId={gameId}></CardAction>
101
+ </CardBody>
102
+
103
+ <CardTail>
104
+ <TailIcon />
105
+ </CardTail>
106
+ </FlexCard>
107
+ )
108
+ }
109
+ )
@@ -40,3 +40,20 @@ export const CardTail = styled.div`
40
40
  height: 20px;
41
41
  }
42
42
  `
43
+
44
+ export const CardActionWrapper = styled.div`
45
+ display: flex;
46
+ flex-direction: column;
47
+ align-items: baseline;
48
+ `
49
+
50
+ export const TagsWrapper = styled.div`
51
+ display: flex;
52
+ flex: 1;
53
+ flex-wrap: wrap;
54
+ align-items: center;
55
+ `
56
+
57
+ export const SpanText = styled.span`
58
+ white-space: nowrap;
59
+ `
@@ -11,7 +11,6 @@ import type { ListRowProps } from 'react-virtualized'
11
11
  import styled from 'styled-components'
12
12
  import { QUEST_STATUS } from '../questHelper'
13
13
  import type { UnionQuest } from '../questHelper'
14
- import { useLargeCard } from '../store'
15
14
  import { QuestCard } from './QuestCard'
16
15
  import { useIsQuestPluginTab } from '../poi/hooks'
17
16
  import { QUEST_API_STATE } from '../poi/types'
@@ -27,7 +26,7 @@ const cache = new CellMeasurerCache({
27
26
  fixedWidth: true,
28
27
  })
29
28
 
30
- const questStateToQuestStatus = (
29
+ const questApiStateToQuestStatus = (
31
30
  state: QUEST_API_STATE | undefined
32
31
  ): QUEST_STATUS => {
33
32
  switch (state) {
@@ -48,7 +47,7 @@ const useQuestsRowRenderer = (quests: UnionQuest[]) => {
48
47
  const quest = quests[index]
49
48
  const { gameId } = quest
50
49
  const { code, name, desc, memo, memo2, pre } = quest.docQuest
51
- const questStatus = questStateToQuestStatus(quest.gameQuest?.api_state)
50
+ const questStatus = questApiStateToQuestStatus(quest.gameQuest?.api_state)
52
51
 
53
52
  return (
54
53
  <CellMeasurer
@@ -67,7 +66,7 @@ const useQuestsRowRenderer = (quests: UnionQuest[]) => {
67
66
  desc={desc}
68
67
  tip={memo}
69
68
  tip2={memo2}
70
- preTask={pre}
69
+ preQuest={pre}
71
70
  status={questStatus}
72
71
  ></QuestCard>
73
72
  </div>
@@ -80,16 +79,14 @@ const useQuestsRowRenderer = (quests: UnionQuest[]) => {
80
79
  }
81
80
 
82
81
  export const QuestList: React.FC<{ quests: UnionQuest[] }> = ({ quests }) => {
83
- const { largeCard } = useLargeCard()
84
82
  const activeTab = useIsQuestPluginTab()
85
83
  const listRef = useRef<List>(null)
86
84
  const rowRenderer: ListRowRenderer = useQuestsRowRenderer(quests)
87
85
 
88
86
  useEffect(() => {
89
- const largeCardIdx = quests.findIndex((i) => i.gameId === largeCard)
90
87
  cache.clearAll()
91
- listRef.current?.recomputeRowHeights(largeCardIdx)
92
- }, [quests, largeCard])
88
+ listRef.current?.recomputeRowHeights()
89
+ }, [quests])
93
90
 
94
91
  useEffect(() => {
95
92
  if (activeTab) {
@@ -0,0 +1,104 @@
1
+ import type { TooltipProps } from '@blueprintjs/core'
2
+ import { Tag, Tooltip } from '@blueprintjs/core'
3
+ import { IconNames } from '@blueprintjs/icons'
4
+ import React, { forwardRef, useCallback } from 'react'
5
+ import styled from 'styled-components'
6
+ import { DocQuest, guessQuestCategory, QUEST_STATUS } from '../questHelper'
7
+ import { useFilterTags } from '../store/filterTags'
8
+ import { useQuestByCode, useQuestStatus } from '../store/quest'
9
+ import { useSearchInput } from '../store/search'
10
+
11
+ const TagWrapper = styled(Tag)`
12
+ margin: 2px 4px;
13
+ user-select: ${({ interactive }) => (interactive ? 'none' : 'auto')};
14
+ overflow: visible;
15
+
16
+ & > span {
17
+ cursor: ${({ interactive }) => (interactive ? 'pointer' : 'auto')};
18
+ }
19
+ `
20
+
21
+ const QuestTooltip = forwardRef<
22
+ Tooltip,
23
+ Omit<TooltipProps, 'content'> & {
24
+ quest: DocQuest
25
+ children: React.ReactNode
26
+ }
27
+ >(({ quest, children, ...props }, ref) => {
28
+ if (!quest) {
29
+ return <>{children}</>
30
+ }
31
+ return (
32
+ <Tooltip
33
+ ref={ref}
34
+ content={
35
+ <>
36
+ <div>{`${quest.code} - ${quest.name}`}</div>
37
+ <div>{quest.desc}</div>
38
+ {quest.memo2 && <b>{quest.memo2}</b>}
39
+ {quest.memo && <i>{quest.memo}</i>}
40
+ </>
41
+ }
42
+ placement={'top'}
43
+ {...props}
44
+ >
45
+ {children}
46
+ </Tooltip>
47
+ )
48
+ })
49
+
50
+ const getTagIcon = (questStatus: QUEST_STATUS) => {
51
+ switch (questStatus) {
52
+ case QUEST_STATUS.ALREADY_COMPLETED:
53
+ return IconNames.TICK
54
+ case QUEST_STATUS.LOCKED:
55
+ return IconNames.LOCK
56
+ default:
57
+ return null
58
+ }
59
+ }
60
+
61
+ export const QuestTag = ({ code }: { code: string }) => {
62
+ const { setSearchInput } = useSearchInput()
63
+ const { setCategoryTagsAll, setTypeTagsAll } = useFilterTags()
64
+ const maybeQuest = useQuestByCode(code)
65
+ const maybeGameId = maybeQuest?.gameId ?? null
66
+ const questStatus = useQuestStatus(maybeGameId)
67
+ const tagIcon = getTagIcon(questStatus)
68
+
69
+ const handleClick = useCallback(() => {
70
+ setSearchInput(code)
71
+ setCategoryTagsAll()
72
+ setTypeTagsAll()
73
+ }, [code, setCategoryTagsAll, setSearchInput, setTypeTagsAll])
74
+ const indicatorColor = guessQuestCategory(code).color
75
+ const fontColor =
76
+ indicatorColor === '#fff' || indicatorColor === '#87da61'
77
+ ? 'black'
78
+ : 'white'
79
+
80
+ if (!maybeQuest) {
81
+ return (
82
+ <TagWrapper
83
+ icon={IconNames.HELP}
84
+ style={{ color: fontColor, background: indicatorColor }}
85
+ >
86
+ {code}
87
+ </TagWrapper>
88
+ )
89
+ }
90
+
91
+ const quest = maybeQuest.docQuest
92
+ return (
93
+ <QuestTooltip quest={quest}>
94
+ <TagWrapper
95
+ interactive
96
+ icon={tagIcon}
97
+ onClick={handleClick}
98
+ style={{ color: fontColor, background: indicatorColor }}
99
+ >
100
+ {code}
101
+ </TagWrapper>
102
+ </QuestTooltip>
103
+ )
104
+ }
package/src/poi/hooks.ts CHANGED
@@ -3,6 +3,10 @@ import { useTranslation } from 'react-i18next'
3
3
  import { observePluginStore, observePoiStore } from './store'
4
4
  import { name as PACKAGE_NAME } from '../../package.json'
5
5
  import { GameQuest, PoiQuestState, PoiState, QuestTab } from './types'
6
+ import { createGlobalState } from 'react-use'
7
+
8
+ export const activeQuestsSelector = (state: PoiState): PoiQuestState =>
9
+ state?.info?.quests?.activeQuests ?? {}
6
10
 
7
11
  export const useActiveQuest = () => {
8
12
  const [activeQuests, setActiveQuests] = useState<PoiQuestState>({})
@@ -17,20 +21,19 @@ export const useActiveQuest = () => {
17
21
  return activeQuests
18
22
  }
19
23
 
20
- export const activeQuestsSelector = (state: PoiState): PoiQuestState =>
21
- state?.info?.quests?.activeQuests ?? {}
22
-
23
24
  export const usePluginTranslation = () => {
24
25
  return useTranslation(PACKAGE_NAME)
25
26
  }
26
27
 
28
+ const useGlobalGameQuest = createGlobalState<GameQuest[]>([])
29
+
27
30
  export const useGameQuest = () => {
28
- const [quests, setQuests] = useState<GameQuest[]>([])
31
+ const [quests, setQuests] = useGlobalGameQuest()
29
32
  useEffect(() => {
30
33
  const listener = (quests: GameQuest[] | null) => setQuests(quests ?? [])
31
34
  // See reducer.ts
32
35
  return observePluginStore(listener, (i) => i?._?.questList)
33
- }, [])
36
+ }, [setQuests])
34
37
  return quests
35
38
  }
36
39
 
@@ -1,8 +1,12 @@
1
- import questCategory from '../build/questCategory.json'
1
+ import { QuestData } from '../build/kcanotifyGamedata'
2
+ import { KcwikiQuestData } from '../build/kcQuestsData'
2
3
  import newQuestData from '../build/kcQuestsData/quests-scn-new.json'
4
+ import prePostQuest from '../build/prePostQuest.json'
5
+ import questCategory from '../build/questCategory.json'
6
+ import questCodeMap from '../build/questCodeMap.json'
3
7
  import { GameQuest, QUEST_API_STATE } from './poi/types'
4
8
 
5
- type DocQuest = {
9
+ export type DocQuest = {
6
10
  code: string
7
11
  name: string
8
12
  desc: string
@@ -29,18 +33,21 @@ type DocQuest = {
29
33
  }
30
34
 
31
35
  export type UnionQuest = {
32
- gameId: string
36
+ gameId: number
33
37
  gameQuest?: GameQuest
34
38
  docQuest: DocQuest
35
39
  }
36
40
 
41
+ export const getKcwikiQuestData = () => KcwikiQuestData
42
+ export const getKcanotifyQuestData = () => QuestData
43
+
37
44
  const dailyQuest = new Set(questCategory.dailyQuest)
38
45
  const weeklyQuest = new Set(questCategory.weeklyQuest)
39
46
  const monthlyQuest = new Set(questCategory.monthlyQuest)
40
47
  const quarterlyQuest = new Set(questCategory.quarterlyQuest)
41
48
  const yearlyQuest = new Set(questCategory.yearlyQuest)
42
49
  const singleQuest = new Set(questCategory.singleQuest)
43
- const newQuest = new Set(newQuestData)
50
+ const newQuest = new Set(newQuestData.map((gameId) => +gameId))
44
51
 
45
52
  export const isInProgressQuest = (quest: GameQuest) =>
46
53
  quest.api_state === QUEST_API_STATE.IN_PROGRESS ||
@@ -196,6 +203,20 @@ export const isUnknownCategoryQuest = ({ code }: DocQuest) =>
196
203
  // Starts with unknown character
197
204
  /^[^ABCDEFG]/.test(code)
198
205
 
206
+ export const getQuestPrePost = (gameId: number) => {
207
+ if (!(gameId in prePostQuest)) {
208
+ return { pre: [], post: [] }
209
+ }
210
+ return prePostQuest[String(gameId) as keyof typeof prePostQuest]
211
+ }
212
+
213
+ export const getQuestIdByCode = (code: string) => {
214
+ if (code in questCodeMap) {
215
+ return questCodeMap[code as keyof typeof questCodeMap]
216
+ }
217
+ return null
218
+ }
219
+
199
220
  export enum QUEST_STATUS {
200
221
  LOCKED,
201
222
  DEFAULT,
@@ -1,5 +1,5 @@
1
- import { KcwikiQuestData } from '../../build/kcQuestsData'
2
1
  import { useStore } from '.'
2
+ import { getKcwikiQuestData } from '../questHelper'
3
3
 
4
4
  export const usePreferKcwiki = () => {
5
5
  const {
@@ -13,7 +13,10 @@ export const usePreferKcwiki = () => {
13
13
 
14
14
  export const checkIsKcwikiSupportedLanguages = (
15
15
  lang: string
16
- ): lang is keyof typeof KcwikiQuestData => lang in KcwikiQuestData
16
+ ): lang is keyof typeof kcwikiQuestData => {
17
+ const kcwikiQuestData = getKcwikiQuestData()
18
+ return lang in kcwikiQuestData
19
+ }
17
20
 
18
21
  export const useKcwikiData = (lang: string) => {
19
22
  const [preferKcwiki] = usePreferKcwiki()
@@ -25,5 +28,6 @@ export const useKcwikiData = (lang: string) => {
25
28
  if (!supported) {
26
29
  return null
27
30
  }
28
- return KcwikiQuestData[lang]
31
+ const kcwikiQuestData = getKcwikiQuestData()
32
+ return kcwikiQuestData[lang]
29
33
  }