poi-plugin-quest-info-2 0.8.9 → 0.9.2
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.
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/CHANGELOG.md +26 -0
- package/README.md +3 -2
- package/build/kcQuestsData/DATA_VERSION +1 -1
- package/build/kcQuestsData/index.ts +1 -1
- package/build/kcQuestsData/quests-scn-new.json +8 -1
- package/build/kcQuestsData/quests-scn.json +116 -16
- package/build/kcanotifyGamedata/DATA_VERSION +1 -1
- package/build/kcanotifyGamedata/index.ts +1 -1
- package/build/prePostQuest.json +85 -5
- package/build/questCategory.json +7 -1
- package/build/questCodeMap.json +12 -2
- package/i18n/en-US.json +8 -3
- package/i18n/index.ts +23 -4
- package/i18n/ja-JP.json +3 -3
- package/i18n/ko-KR.json +3 -2
- package/i18n/zh-CN.json +3 -3
- package/i18n/zh-TW.json +3 -3
- package/package.json +5 -2
- package/shims/globals.d.ts +6 -0
- package/src/Settings.tsx +67 -7
- package/src/Toolbar.tsx +53 -33
- package/src/__tests__/fixtures/firstLoginWithOneComplete.json +72 -0
- package/src/__tests__/fixtures/questList.json +338 -0
- package/src/__tests__/kcanotifyData.spec.ts +1 -1
- package/src/__tests__/kcwikiData.spec.ts +1 -1
- package/src/__tests__/questCategory.spec.ts +1 -1
- package/src/components/QuestCard/index.tsx +3 -3
- package/src/components/QuestCard/utils.tsx +3 -3
- package/src/patch.ts +3 -4
- package/src/poi/env.ts +4 -0
- package/src/poi/hooks.ts +55 -2
- package/src/poi/store.ts +25 -8
- package/src/poi/utils.ts +50 -0
- package/src/store/filterTags.ts +34 -13
- package/src/store/gameQuest.tsx +108 -5
- package/src/store/quest.ts +27 -83
- package/src/store/store.tsx +25 -19
- package/src/tags.tsx +83 -24
- package/tsconfig.json +1 -1
package/src/store/filterTags.ts
CHANGED
|
@@ -2,13 +2,8 @@ import { useCallback } from 'react'
|
|
|
2
2
|
import { useUpdateEffect } from 'react-use'
|
|
3
3
|
import { useGameTab } from '../poi/hooks'
|
|
4
4
|
import { QuestTab } from '../poi/types'
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
ALL_TYPE_TAG,
|
|
8
|
-
CATEGORY_TAGS,
|
|
9
|
-
TYPE_TAGS,
|
|
10
|
-
} from '../tags'
|
|
11
|
-
import { useStore, useSyncWithGame } from './store'
|
|
5
|
+
import { CATEGORY_TAGS, TYPE_TAGS } from '../tags'
|
|
6
|
+
import { ALL_CATEGORY_TAG, ALL_TYPE_TAG, PROGRESS_TAG, useStore } from './store'
|
|
12
7
|
|
|
13
8
|
export const useFilterTags = () => {
|
|
14
9
|
const {
|
|
@@ -32,7 +27,7 @@ export const useFilterTags = () => {
|
|
|
32
27
|
},
|
|
33
28
|
[updateStore]
|
|
34
29
|
)
|
|
35
|
-
const
|
|
30
|
+
const setMultiTypeTags = useCallback(
|
|
36
31
|
(data: Record<string, boolean>) => {
|
|
37
32
|
updateStore({ typeTags: data })
|
|
38
33
|
},
|
|
@@ -49,18 +44,44 @@ export const useFilterTags = () => {
|
|
|
49
44
|
setCategoryTags,
|
|
50
45
|
setCategoryTagsAll,
|
|
51
46
|
setTypeTags,
|
|
52
|
-
|
|
47
|
+
setMultiTypeTags,
|
|
53
48
|
setTypeTagsAll,
|
|
54
49
|
}
|
|
55
50
|
}
|
|
56
51
|
|
|
52
|
+
export const useFilterProgressTag = () => {
|
|
53
|
+
const {
|
|
54
|
+
store: { progressTag },
|
|
55
|
+
updateStore,
|
|
56
|
+
} = useStore()
|
|
57
|
+
|
|
58
|
+
const toggleTag = useCallback(
|
|
59
|
+
(tag: PROGRESS_TAG) => {
|
|
60
|
+
if (progressTag === tag) {
|
|
61
|
+
updateStore({ progressTag: PROGRESS_TAG.All })
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
updateStore({ progressTag: tag })
|
|
65
|
+
},
|
|
66
|
+
[progressTag, updateStore]
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
progressTag,
|
|
71
|
+
toggleTag,
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @deprecated Should not update state when render
|
|
77
|
+
*/
|
|
57
78
|
export const useSyncGameTagEffect = () => {
|
|
58
|
-
const {
|
|
79
|
+
const { progressTag } = useFilterProgressTag()
|
|
59
80
|
const filterTags = useFilterTags()
|
|
60
81
|
const tab = useGameTab()
|
|
61
82
|
|
|
62
83
|
useUpdateEffect(() => {
|
|
63
|
-
if (
|
|
84
|
+
if (progressTag !== PROGRESS_TAG.Unlocked) {
|
|
64
85
|
return
|
|
65
86
|
}
|
|
66
87
|
switch (tab) {
|
|
@@ -80,7 +101,7 @@ export const useSyncGameTagEffect = () => {
|
|
|
80
101
|
filterTags.setTypeTags('In Progress')
|
|
81
102
|
break
|
|
82
103
|
case QuestTab.OTHERS:
|
|
83
|
-
filterTags.
|
|
104
|
+
filterTags.setMultiTypeTags({ Quarterly: true, Yearly: true })
|
|
84
105
|
break
|
|
85
106
|
case QuestTab.ONCE:
|
|
86
107
|
filterTags.setTypeTags('One-time')
|
|
@@ -88,5 +109,5 @@ export const useSyncGameTagEffect = () => {
|
|
|
88
109
|
default:
|
|
89
110
|
break
|
|
90
111
|
}
|
|
91
|
-
}, [
|
|
112
|
+
}, [tab])
|
|
92
113
|
}
|
package/src/store/gameQuest.tsx
CHANGED
|
@@ -1,20 +1,123 @@
|
|
|
1
|
-
import React, { createContext, useContext } from 'react'
|
|
2
1
|
import type { ReactNode } from 'react'
|
|
3
|
-
import {
|
|
2
|
+
import React, { createContext, useContext } from 'react'
|
|
4
3
|
import { useGameQuest } from '../poi/hooks'
|
|
4
|
+
import { GameQuest } from '../poi/types'
|
|
5
|
+
import {
|
|
6
|
+
getCompletedQuest,
|
|
7
|
+
getLockedQuest,
|
|
8
|
+
questApiStateToQuestStatus,
|
|
9
|
+
QUEST_STATUS,
|
|
10
|
+
} from '../questHelper'
|
|
5
11
|
|
|
6
|
-
export const GameQuestContext = createContext<
|
|
12
|
+
export const GameQuestContext = createContext<{
|
|
13
|
+
gameQuest: GameQuest[]
|
|
14
|
+
questStatusQuery: (gameId: number) => QUEST_STATUS
|
|
15
|
+
lockedQuestNum: number
|
|
16
|
+
unlockedQuestNum: number
|
|
17
|
+
completedQuestNum: number
|
|
18
|
+
alreadyCompletedQuestNum: number
|
|
19
|
+
}>({
|
|
20
|
+
gameQuest: [],
|
|
21
|
+
questStatusQuery: () => QUEST_STATUS.UNKNOWN,
|
|
22
|
+
lockedQuestNum: 0,
|
|
23
|
+
unlockedQuestNum: 0,
|
|
24
|
+
completedQuestNum: 0,
|
|
25
|
+
alreadyCompletedQuestNum: 0,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const useQuestStatusQuery = (inProgressQuests: GameQuest[]) => {
|
|
29
|
+
const gameQuestIds = inProgressQuests.map((quest) => quest.api_no)
|
|
30
|
+
const unlockedGameQuest = Object.fromEntries(
|
|
31
|
+
inProgressQuests.map((quest) => [quest.api_no, quest])
|
|
32
|
+
)
|
|
33
|
+
const alreadyCompletedQuest = getCompletedQuest(gameQuestIds)
|
|
34
|
+
const lockedQuest = getLockedQuest(gameQuestIds)
|
|
35
|
+
const completedQuest = inProgressQuests
|
|
36
|
+
.map((quest) => questApiStateToQuestStatus(quest.api_state))
|
|
37
|
+
.filter((status) => status === QUEST_STATUS.COMPLETED)
|
|
38
|
+
return {
|
|
39
|
+
lockedQuestNum: Object.keys(lockedQuest).length,
|
|
40
|
+
unlockedQuestNum: Object.keys(unlockedGameQuest).length,
|
|
41
|
+
completedQuestNum: completedQuest.length,
|
|
42
|
+
alreadyCompletedQuestNum: Object.keys(alreadyCompletedQuest).length,
|
|
43
|
+
questStatusQuery: (gameId: number) => {
|
|
44
|
+
const theGameQuest = unlockedGameQuest[gameId]
|
|
45
|
+
if (theGameQuest) {
|
|
46
|
+
// the quest is in game
|
|
47
|
+
return questApiStateToQuestStatus(theGameQuest.api_state)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (gameId in lockedQuest) {
|
|
51
|
+
return QUEST_STATUS.LOCKED
|
|
52
|
+
}
|
|
53
|
+
if (gameId in alreadyCompletedQuest) {
|
|
54
|
+
return QUEST_STATUS.ALREADY_COMPLETED
|
|
55
|
+
}
|
|
56
|
+
return QUEST_STATUS.UNKNOWN
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
}
|
|
7
60
|
|
|
8
61
|
export const GameQuestProvider = ({ children }: { children?: ReactNode }) => {
|
|
9
62
|
const gameQuest = useGameQuest()
|
|
63
|
+
const {
|
|
64
|
+
lockedQuestNum,
|
|
65
|
+
unlockedQuestNum,
|
|
66
|
+
completedQuestNum,
|
|
67
|
+
alreadyCompletedQuestNum,
|
|
68
|
+
questStatusQuery,
|
|
69
|
+
} = useQuestStatusQuery(gameQuest)
|
|
70
|
+
|
|
10
71
|
return (
|
|
11
|
-
<GameQuestContext.Provider
|
|
72
|
+
<GameQuestContext.Provider
|
|
73
|
+
value={{
|
|
74
|
+
gameQuest,
|
|
75
|
+
questStatusQuery,
|
|
76
|
+
lockedQuestNum,
|
|
77
|
+
unlockedQuestNum,
|
|
78
|
+
completedQuestNum,
|
|
79
|
+
alreadyCompletedQuestNum,
|
|
80
|
+
}}
|
|
81
|
+
>
|
|
12
82
|
{children}
|
|
13
83
|
</GameQuestContext.Provider>
|
|
14
84
|
)
|
|
15
85
|
}
|
|
16
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Get the questList from poi.
|
|
89
|
+
*
|
|
90
|
+
* Same as {@link useGameQuest}, but singleton
|
|
91
|
+
*/
|
|
17
92
|
export const useGlobalGameQuest = () => {
|
|
18
|
-
const gameQuest = useContext(GameQuestContext)
|
|
93
|
+
const { gameQuest } = useContext(GameQuestContext)
|
|
19
94
|
return gameQuest
|
|
20
95
|
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Get the questList from poi.
|
|
99
|
+
*
|
|
100
|
+
* Same as {@link useQuestStatusQuery}, but singleton
|
|
101
|
+
*/
|
|
102
|
+
export const useGlobalQuestStatusQuery = () => {
|
|
103
|
+
const { questStatusQuery } = useContext(GameQuestContext)
|
|
104
|
+
return questStatusQuery
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get the number of quests in different states.
|
|
109
|
+
*/
|
|
110
|
+
export const useGlobalQuestStatusNum = () => {
|
|
111
|
+
const {
|
|
112
|
+
lockedQuestNum,
|
|
113
|
+
unlockedQuestNum,
|
|
114
|
+
completedQuestNum,
|
|
115
|
+
alreadyCompletedQuestNum,
|
|
116
|
+
} = useContext(GameQuestContext)
|
|
117
|
+
return {
|
|
118
|
+
lockedQuestNum,
|
|
119
|
+
unlockedQuestNum,
|
|
120
|
+
completedQuestNum,
|
|
121
|
+
alreadyCompletedQuestNum,
|
|
122
|
+
}
|
|
123
|
+
}
|
package/src/store/quest.ts
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
|
-
import { useCallback } from 'react'
|
|
2
1
|
import { usePluginTranslation } from '../poi/hooks'
|
|
3
2
|
import {
|
|
4
3
|
DocQuest,
|
|
5
|
-
getCategory,
|
|
6
|
-
getCompletedQuest,
|
|
7
4
|
getKcanotifyQuestData,
|
|
8
|
-
getLockedQuest,
|
|
9
5
|
getQuestIdByCode,
|
|
10
|
-
questApiStateToQuestStatus,
|
|
11
6
|
QUEST_STATUS,
|
|
12
7
|
UnionQuest,
|
|
13
8
|
} from '../questHelper'
|
|
14
|
-
import { useGlobalGameQuest } from './gameQuest'
|
|
9
|
+
import { useGlobalGameQuest, useGlobalQuestStatusQuery } from './gameQuest'
|
|
15
10
|
import { checkIsKcwikiSupportedLanguages, useKcwikiData } from './kcwiki'
|
|
16
|
-
import { useStore, useSyncWithGame } from './store'
|
|
17
11
|
|
|
18
12
|
const DEFAULT_LANG = 'ja-JP'
|
|
19
13
|
|
|
@@ -53,40 +47,27 @@ const useQuestMap = (): Record<string, DocQuest> => {
|
|
|
53
47
|
export const useQuest = (): UnionQuest[] => {
|
|
54
48
|
const docQuestMap = useQuestMap()
|
|
55
49
|
const gameQuest = useGlobalGameQuest()
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
desc: quest.api_detail,
|
|
78
|
-
},
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
} else {
|
|
82
|
-
// Return all recorded quests
|
|
83
|
-
return Object.entries(docQuestMap).map(([gameId, val]) => ({
|
|
84
|
-
gameId: +gameId,
|
|
85
|
-
// Maybe empty
|
|
86
|
-
gameQuest: gameQuest.find((quest) => quest.api_no === Number(gameId))!,
|
|
87
|
-
docQuest: val,
|
|
88
|
-
}))
|
|
89
|
-
}
|
|
50
|
+
// TODO extract new quest from game quest
|
|
51
|
+
// Not yet recorded quest
|
|
52
|
+
// May be a new quest
|
|
53
|
+
// if (!(gameId in docQuestMap)) {
|
|
54
|
+
// return {
|
|
55
|
+
// gameId,
|
|
56
|
+
// gameQuest: quest,
|
|
57
|
+
// docQuest: {
|
|
58
|
+
// code: `${getCategory(quest.api_category).wikiSymbol}?`,
|
|
59
|
+
// name: quest.api_title,
|
|
60
|
+
// desc: quest.api_detail,
|
|
61
|
+
// },
|
|
62
|
+
// }
|
|
63
|
+
// }
|
|
64
|
+
// Return all recorded quests
|
|
65
|
+
return Object.entries(docQuestMap).map(([gameId, val]) => ({
|
|
66
|
+
gameId: +gameId,
|
|
67
|
+
// Maybe empty
|
|
68
|
+
gameQuest: gameQuest.find((quest) => quest.api_no === Number(gameId))!,
|
|
69
|
+
docQuest: val,
|
|
70
|
+
}))
|
|
90
71
|
}
|
|
91
72
|
|
|
92
73
|
export const useQuestByCode = (code: string) => {
|
|
@@ -101,50 +82,13 @@ export const useQuestByCode = (code: string) => {
|
|
|
101
82
|
return null
|
|
102
83
|
}
|
|
103
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Get the completion status of a specific game quest
|
|
87
|
+
*/
|
|
104
88
|
export const useQuestStatus = (gameId: number | null) => {
|
|
105
|
-
const
|
|
106
|
-
|
|
89
|
+
const searcher = useGlobalQuestStatusQuery()
|
|
107
90
|
if (!gameId) {
|
|
108
91
|
return QUEST_STATUS.UNKNOWN
|
|
109
92
|
}
|
|
110
|
-
|
|
111
|
-
if (theGameQuest) {
|
|
112
|
-
// the quest is in game
|
|
113
|
-
return questApiStateToQuestStatus(theGameQuest.api_state)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const gameQuestId = gameQuest.map((quest) => quest.api_no)
|
|
117
|
-
const completedQuest = getCompletedQuest(gameQuestId)
|
|
118
|
-
const lockedQuest = getLockedQuest(gameQuestId)
|
|
119
|
-
|
|
120
|
-
if (gameId in lockedQuest) {
|
|
121
|
-
return QUEST_STATUS.LOCKED
|
|
122
|
-
}
|
|
123
|
-
if (gameId in completedQuest) {
|
|
124
|
-
return QUEST_STATUS.ALREADY_COMPLETED
|
|
125
|
-
}
|
|
126
|
-
return QUEST_STATUS.UNKNOWN
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* @deprecated Not large card now
|
|
131
|
-
*/
|
|
132
|
-
export const useLargeCard = () => {
|
|
133
|
-
const {
|
|
134
|
-
store: { largeCard },
|
|
135
|
-
updateStore,
|
|
136
|
-
} = useStore()
|
|
137
|
-
const setLarge = useCallback(
|
|
138
|
-
(gameId: string) => updateStore({ largeCard: gameId }),
|
|
139
|
-
[updateStore]
|
|
140
|
-
)
|
|
141
|
-
const setMinimal = useCallback(
|
|
142
|
-
() => updateStore({ largeCard: null }),
|
|
143
|
-
[updateStore]
|
|
144
|
-
)
|
|
145
|
-
return {
|
|
146
|
-
largeCard,
|
|
147
|
-
setLarge,
|
|
148
|
-
setMinimal,
|
|
149
|
-
}
|
|
93
|
+
return searcher(gameId)
|
|
150
94
|
}
|
package/src/store/store.tsx
CHANGED
|
@@ -7,10 +7,24 @@ import React, {
|
|
|
7
7
|
useState,
|
|
8
8
|
} from 'react'
|
|
9
9
|
import { useMount, useUpdateEffect } from 'react-use'
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { PACKAGE_NAME } from '../poi/env'
|
|
11
|
+
import { noop, yes } from '../utils'
|
|
12
12
|
import { GameQuestProvider } from './gameQuest'
|
|
13
13
|
|
|
14
|
+
export const ALL_CATEGORY_TAG = {
|
|
15
|
+
name: 'All',
|
|
16
|
+
filter: yes,
|
|
17
|
+
} as const
|
|
18
|
+
|
|
19
|
+
export const ALL_TYPE_TAG = ALL_CATEGORY_TAG
|
|
20
|
+
|
|
21
|
+
export enum PROGRESS_TAG {
|
|
22
|
+
All = 'All',
|
|
23
|
+
Unlocked = 'Unlocked',
|
|
24
|
+
Locked = 'Locked',
|
|
25
|
+
AlreadyCompleted = 'AlreadyCompleted',
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
export const initialState = {
|
|
15
29
|
searchInput: '',
|
|
16
30
|
typeTags: {
|
|
@@ -19,8 +33,8 @@ export const initialState = {
|
|
|
19
33
|
categoryTags: {
|
|
20
34
|
[ALL_CATEGORY_TAG.name]: true,
|
|
21
35
|
} as Record<string, boolean>,
|
|
22
|
-
|
|
23
|
-
syncWithGame: false,
|
|
36
|
+
progressTag: PROGRESS_TAG.All,
|
|
37
|
+
syncWithGame: false as const,
|
|
24
38
|
preferKcwikiData: true,
|
|
25
39
|
}
|
|
26
40
|
|
|
@@ -39,7 +53,7 @@ const useStorage = <T,>(initialValue: T) => {
|
|
|
39
53
|
return
|
|
40
54
|
}
|
|
41
55
|
const parsedStorage: T = JSON.parse(stringStore)
|
|
42
|
-
setState(parsedStorage)
|
|
56
|
+
setState({ ...initialState, ...parsedStorage })
|
|
43
57
|
} catch (error) {
|
|
44
58
|
console.error('Failed to load storage', error)
|
|
45
59
|
}
|
|
@@ -97,22 +111,14 @@ export const useRemoveStorage = () => {
|
|
|
97
111
|
}
|
|
98
112
|
}
|
|
99
113
|
|
|
114
|
+
/**
|
|
115
|
+
* @deprecated Use progress tag
|
|
116
|
+
*/
|
|
100
117
|
export const useSyncWithGame = () => {
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
updateStore,
|
|
104
|
-
} = useStore()
|
|
105
|
-
const setSyncWithGame = useCallback(
|
|
106
|
-
(value: boolean) => {
|
|
107
|
-
updateStore({ syncWithGame: value })
|
|
108
|
-
},
|
|
109
|
-
[updateStore]
|
|
110
|
-
)
|
|
111
|
-
const toggleSyncWithGame = useCallback(() => {
|
|
112
|
-
setSyncWithGame(!syncWithGame)
|
|
113
|
-
}, [setSyncWithGame, syncWithGame])
|
|
118
|
+
const setSyncWithGame = noop
|
|
119
|
+
const toggleSyncWithGame = noop
|
|
114
120
|
return {
|
|
115
|
-
syncWithGame,
|
|
121
|
+
syncWithGame: false as const,
|
|
116
122
|
setSyncWithGame,
|
|
117
123
|
toggleSyncWithGame,
|
|
118
124
|
}
|
package/src/tags.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Tag } from '@blueprintjs/core'
|
|
2
|
+
import { IconNames } from '@blueprintjs/icons'
|
|
2
3
|
import React from 'react'
|
|
3
4
|
import styled from 'styled-components'
|
|
4
|
-
import { IN_POI } from './poi/env'
|
|
5
5
|
import { useGameTab, usePluginTranslation } from './poi/hooks'
|
|
6
6
|
import { GameQuest, QuestTab } from './poi/types'
|
|
7
7
|
import type { UnionQuest } from './questHelper'
|
|
@@ -25,17 +25,14 @@ import {
|
|
|
25
25
|
isYearlyQuest,
|
|
26
26
|
newQuestNumber,
|
|
27
27
|
} from './questHelper'
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
} as const
|
|
37
|
-
|
|
38
|
-
export const ALL_TYPE_TAG = ALL_CATEGORY_TAG
|
|
28
|
+
import {
|
|
29
|
+
ALL_CATEGORY_TAG,
|
|
30
|
+
ALL_TYPE_TAG,
|
|
31
|
+
PROGRESS_TAG,
|
|
32
|
+
useSyncWithGame,
|
|
33
|
+
} from './store'
|
|
34
|
+
import { useFilterProgressTag, useFilterTags } from './store/filterTags'
|
|
35
|
+
import { useGlobalGameQuest, useGlobalQuestStatusNum } from './store/gameQuest'
|
|
39
36
|
|
|
40
37
|
const withDocQuest =
|
|
41
38
|
<T,>(filterFn: (q: UnionQuest['docQuest']) => T) =>
|
|
@@ -78,9 +75,9 @@ export const TYPE_TAGS = [
|
|
|
78
75
|
{ name: 'Yearly', filter: isYearlyQuest },
|
|
79
76
|
] as const
|
|
80
77
|
|
|
81
|
-
// TODO tag Lock / Completed
|
|
82
|
-
|
|
83
78
|
const TagsWrapper = styled.div`
|
|
79
|
+
display: flex;
|
|
80
|
+
flex-wrap: wrap;
|
|
84
81
|
margin-left: -4px;
|
|
85
82
|
margin-right: -4px;
|
|
86
83
|
|
|
@@ -89,10 +86,61 @@ const TagsWrapper = styled.div`
|
|
|
89
86
|
}
|
|
90
87
|
`
|
|
91
88
|
|
|
92
|
-
export const
|
|
89
|
+
export const ProgressTags = () => {
|
|
93
90
|
const { t } = usePluginTranslation()
|
|
91
|
+
const { progressTag, toggleTag } = useFilterProgressTag()
|
|
92
|
+
const {
|
|
93
|
+
lockedQuestNum,
|
|
94
|
+
unlockedQuestNum,
|
|
95
|
+
completedQuestNum,
|
|
96
|
+
alreadyCompletedQuestNum,
|
|
97
|
+
} = useGlobalQuestStatusNum()
|
|
98
|
+
const completedQuestSuffix =
|
|
99
|
+
completedQuestNum > 0
|
|
100
|
+
? `${alreadyCompletedQuestNum} + ${completedQuestNum}`
|
|
101
|
+
: alreadyCompletedQuestNum
|
|
102
|
+
return (
|
|
103
|
+
<>
|
|
104
|
+
<Tag
|
|
105
|
+
onClick={() => {
|
|
106
|
+
toggleTag(PROGRESS_TAG.Locked)
|
|
107
|
+
}}
|
|
108
|
+
intent={progressTag === PROGRESS_TAG.Locked ? 'success' : 'none'}
|
|
109
|
+
interactive={true}
|
|
110
|
+
>
|
|
111
|
+
{t('Locked', { number: lockedQuestNum })}
|
|
112
|
+
</Tag>
|
|
113
|
+
<Tag
|
|
114
|
+
icon={IconNames.EXCHANGE}
|
|
115
|
+
onClick={() => {
|
|
116
|
+
toggleTag(PROGRESS_TAG.Unlocked)
|
|
117
|
+
}}
|
|
118
|
+
intent={progressTag === PROGRESS_TAG.Unlocked ? 'success' : 'none'}
|
|
119
|
+
interactive={true}
|
|
120
|
+
>
|
|
121
|
+
{t('Unlocked', { number: unlockedQuestNum })}
|
|
122
|
+
</Tag>
|
|
123
|
+
<Tag
|
|
124
|
+
onClick={() => {
|
|
125
|
+
toggleTag(PROGRESS_TAG.AlreadyCompleted)
|
|
126
|
+
}}
|
|
127
|
+
intent={
|
|
128
|
+
progressTag === PROGRESS_TAG.AlreadyCompleted ? 'success' : 'none'
|
|
129
|
+
}
|
|
130
|
+
interactive={true}
|
|
131
|
+
>
|
|
132
|
+
{t('Already Completed', {
|
|
133
|
+
number: completedQuestSuffix,
|
|
134
|
+
})}
|
|
135
|
+
</Tag>
|
|
136
|
+
</>
|
|
137
|
+
)
|
|
138
|
+
}
|
|
94
139
|
|
|
140
|
+
export const CategoryTags = () => {
|
|
141
|
+
const { t } = usePluginTranslation()
|
|
95
142
|
const { categoryTags, setCategoryTags } = useFilterTags()
|
|
143
|
+
|
|
96
144
|
return (
|
|
97
145
|
<TagsWrapper>
|
|
98
146
|
{CATEGORY_TAGS.map(({ name }) => (
|
|
@@ -111,6 +159,8 @@ export const CategoryTags = () => {
|
|
|
111
159
|
{t(name)}
|
|
112
160
|
</Tag>
|
|
113
161
|
))}
|
|
162
|
+
|
|
163
|
+
<ProgressTags />
|
|
114
164
|
</TagsWrapper>
|
|
115
165
|
)
|
|
116
166
|
}
|
|
@@ -120,6 +170,8 @@ export const TypeTags = () => {
|
|
|
120
170
|
const gameTab = useGameTab()
|
|
121
171
|
const { syncWithGame } = useSyncWithGame()
|
|
122
172
|
const gameQuests = useGlobalGameQuest()
|
|
173
|
+
const { progressTag } = useFilterProgressTag()
|
|
174
|
+
|
|
123
175
|
const inProgressQuest = gameQuests.filter((gameQuest) =>
|
|
124
176
|
isInProgressQuest(gameQuest)
|
|
125
177
|
)
|
|
@@ -136,15 +188,22 @@ export const TypeTags = () => {
|
|
|
136
188
|
>
|
|
137
189
|
{t('All')}
|
|
138
190
|
</Tag>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
191
|
+
|
|
192
|
+
<Tag
|
|
193
|
+
intent={
|
|
194
|
+
typeTags['In Progress']
|
|
195
|
+
? progressTag === PROGRESS_TAG.AlreadyCompleted ||
|
|
196
|
+
progressTag === PROGRESS_TAG.Locked
|
|
197
|
+
? 'warning'
|
|
198
|
+
: 'primary'
|
|
199
|
+
: 'none'
|
|
200
|
+
}
|
|
201
|
+
interactive={true}
|
|
202
|
+
onClick={() => setTypeTags('In Progress')}
|
|
203
|
+
>
|
|
204
|
+
{t('In Progress', { number: inProgressQuest.length })}
|
|
205
|
+
</Tag>
|
|
206
|
+
|
|
148
207
|
{hasNewQuest && (
|
|
149
208
|
<Tag
|
|
150
209
|
intent={typeTags['New'] ? 'primary' : 'none'}
|
package/tsconfig.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
] /* Specify library files to be included in the compilation. */,
|
|
14
14
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
|
15
15
|
// "checkJs": true, /* Report errors in .js files. */
|
|
16
|
-
"jsx": "
|
|
16
|
+
"jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
|
17
17
|
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
|
18
18
|
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
|
19
19
|
// "sourceMap": true, /* Generates corresponding '.map' file. */
|