poi-plugin-quest-info-2 0.5.9 → 0.6.1
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/.eslintrc.js +1 -1
- package/build/kcQuestsData/DATA_VERSION +1 -1
- package/build/kcQuestsData/index.ts +1 -1
- package/build/kcQuestsData/quests-scn.json +1121 -1100
- package/build/kcanotifyGamedata/DATA_VERSION +1 -1
- package/build/kcanotifyGamedata/index.ts +1 -1
- package/build/kcanotifyGamedata/quests-en.json +60 -36
- package/build/kcanotifyGamedata/quests-jp.json +506 -482
- package/build/kcanotifyGamedata/quests-ko.json +101 -77
- package/build/kcanotifyGamedata/quests-scn.json +274 -251
- package/build/kcanotifyGamedata/quests-tcn.json +274 -251
- package/i18n/en-US.json +2 -1
- package/i18n/ja-JP.json +2 -1
- package/i18n/ko-KR.json +1 -0
- package/i18n/zh-CN.json +2 -1
- package/i18n/zh-TW.json +1 -0
- package/package.json +2 -2
- package/scripts/convertAssets.ts +2 -7
- package/scripts/downloadKcQuestsData.ts +17 -10
- package/scripts/downloadKcanotifyGamedata.ts +14 -11
- package/scripts/downloadSprites.ts +2 -7
- package/scripts/utils.ts +8 -0
- package/src/Toolbar.tsx +42 -37
- package/src/__tests__/kcanotifyData.spec.ts +1 -1
- package/src/__tests__/kcwikiData.spec.ts +1 -1
- package/src/components/PreTaskTag.tsx +40 -0
- package/src/components/QuestCard/MinimalQuestCard.tsx +48 -0
- package/src/components/QuestCard/index.tsx +71 -0
- package/src/components/QuestCard/styles.ts +42 -0
- package/src/components/QuestCard/utils.tsx +68 -0
- package/src/components/QuestList.tsx +2 -1
- package/src/questHelper.ts +1 -0
- package/src/store/filterTags.ts +44 -0
- package/src/store/search.ts +17 -0
- package/src/store/store.tsx +25 -2
- package/src/components/QuestCard.tsx +0 -213
package/i18n/en-US.json
CHANGED
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
"In Progress": "In Progress",
|
|
21
21
|
"Completed": "Completed",
|
|
22
22
|
"TotalQuests": "Total {{count}} quests",
|
|
23
|
-
"Sync with game": "Sync with game",
|
|
23
|
+
"Sync with game": "Sync with game (Show in-game quests only)",
|
|
24
24
|
"Version": "Version: {{version}}",
|
|
25
25
|
"Data Version": "Data Version: {{version}}",
|
|
26
26
|
"View source code on GitHub": "View source code on GitHub",
|
|
27
27
|
"Restore defaults": "Restore defaults",
|
|
28
28
|
"Use Kcwiki data": "Use Kcwiki's data (Simplified Chinese only)",
|
|
29
|
+
"Requires": "Requires",
|
|
29
30
|
"": ""
|
|
30
31
|
}
|
package/i18n/ja-JP.json
CHANGED
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
"In Progress": "進行中",
|
|
21
21
|
"Completed": "完了",
|
|
22
22
|
"TotalQuests": "全て {{count}} 個の任務",
|
|
23
|
-
"Sync with game": "
|
|
23
|
+
"Sync with game": "ゲームと連動(インゲームクエストのみ表示する)",
|
|
24
24
|
"Version": "バージョン: {{version}}",
|
|
25
25
|
"Data Version": "データ バージョン: {{version}}",
|
|
26
26
|
"View source code on GitHub": "GitHubでソースコードを表示",
|
|
27
27
|
"Restore defaults": "デフォルトに戻す",
|
|
28
28
|
"Use Kcwiki data": "Kcwikiのデータを利用する(簡体字中国語のみ)",
|
|
29
|
+
"Requires": "開放条件",
|
|
29
30
|
"": ""
|
|
30
31
|
}
|
package/i18n/ko-KR.json
CHANGED
package/i18n/zh-CN.json
CHANGED
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
"In Progress": "进行中",
|
|
21
21
|
"Completed": "已完成",
|
|
22
22
|
"TotalQuests": "一共 {{count}} 个任务",
|
|
23
|
-
"Sync with game": "
|
|
23
|
+
"Sync with game": "与游戏同步(仅展示游戏内任务)",
|
|
24
24
|
"Version": "版本: {{version}}",
|
|
25
25
|
"Data Version": "数据版本: {{version}}",
|
|
26
26
|
"View source code on GitHub": "去 GitHub 查看源码",
|
|
27
27
|
"Restore defaults": "恢复默认设置",
|
|
28
28
|
"Use Kcwiki data": "使用 Kcwiki 的数据",
|
|
29
|
+
"Requires": "前置",
|
|
29
30
|
"": ""
|
|
30
31
|
}
|
package/i18n/zh-TW.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poi-plugin-quest-info-2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "show quest info",
|
|
6
6
|
"homepage": "https://github.com/lawvs/poi-plugin-quest-2/",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@babel/core": "^7.12.10",
|
|
41
|
-
"@blueprintjs/core": "^3.
|
|
41
|
+
"@blueprintjs/core": "^3.52.0",
|
|
42
42
|
"@storybook/addon-actions": "^6.3.4",
|
|
43
43
|
"@storybook/addon-essentials": "^6.3.4",
|
|
44
44
|
"@storybook/addon-links": "^6.3.4",
|
package/scripts/convertAssets.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
2
|
import path from 'path'
|
|
3
|
+
import { prepareDir } from './utils'
|
|
3
4
|
|
|
4
5
|
const ASSETS_PATH = path.resolve('assets')
|
|
5
6
|
const OUTPUT_PATH = path.resolve('build')
|
|
@@ -15,19 +16,13 @@ const HEADER = `/**
|
|
|
15
16
|
* Do not edit!
|
|
16
17
|
*/` as const
|
|
17
18
|
|
|
18
|
-
const prepare = () => {
|
|
19
|
-
if (!fs.existsSync(OUTPUT_PATH)) {
|
|
20
|
-
fs.mkdirSync(OUTPUT_PATH, { recursive: true })
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
19
|
function base64Encode(file: string) {
|
|
25
20
|
const bitmap = fs.readFileSync(file)
|
|
26
21
|
return bitmap.toString('base64')
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
function main() {
|
|
30
|
-
|
|
25
|
+
prepareDir(OUTPUT_PATH)
|
|
31
26
|
const imageData = fs
|
|
32
27
|
.readdirSync(ASSETS_PATH)
|
|
33
28
|
// exclusive ignored ext
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import
|
|
3
|
-
import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs'
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
4
3
|
import pangu from 'pangu'
|
|
4
|
+
import path from 'path'
|
|
5
5
|
import { fetch } from './proxyFetch'
|
|
6
|
+
import { prepareDir } from './utils'
|
|
6
7
|
|
|
7
8
|
// See https://github.com/kcwikizh/kcQuests
|
|
8
9
|
|
|
@@ -12,11 +13,8 @@ const URL = `https://kcwikizh.github.io/kcQuests/${FILE_NAME}`
|
|
|
12
13
|
const VERSION_URL =
|
|
13
14
|
'https://api.github.com/repos/kcwikizh/kcQuests/branches/main'
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
mkdirSync(OUTPUT_PATH, { recursive: true })
|
|
18
|
-
}
|
|
19
|
-
}
|
|
16
|
+
// expired quest: 2021 节分任务
|
|
17
|
+
const IGNORE_DATA = [329, 441, 840, 841, 842, 843] as const
|
|
20
18
|
|
|
21
19
|
const getRemoteVersion = async () => {
|
|
22
20
|
const resp = await fetch(VERSION_URL)
|
|
@@ -60,7 +58,7 @@ const genTS = (version: string) => {
|
|
|
60
58
|
const main = async () => {
|
|
61
59
|
const args = process.argv.slice(2)
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
prepareDir(OUTPUT_PATH)
|
|
64
62
|
const remoteVersion = await getRemoteVersion()
|
|
65
63
|
const localVersion = getLocalVersion()
|
|
66
64
|
if (remoteVersion === localVersion) {
|
|
@@ -82,14 +80,23 @@ const main = async () => {
|
|
|
82
80
|
text = text.trim()
|
|
83
81
|
|
|
84
82
|
const json = JSON.parse(text) as {
|
|
85
|
-
[gameId: string]: {
|
|
83
|
+
[gameId: string]: {
|
|
84
|
+
code: string
|
|
85
|
+
name: string
|
|
86
|
+
desc: string
|
|
87
|
+
memo?: string
|
|
88
|
+
}
|
|
86
89
|
}
|
|
87
90
|
for (const gameId in json) {
|
|
88
|
-
const { name, desc } = json[gameId]
|
|
91
|
+
const { name, desc, memo } = json[gameId]
|
|
89
92
|
json[gameId].name = pangu.spacing(name)
|
|
90
93
|
json[gameId].desc = pangu.spacing(desc)
|
|
94
|
+
if (memo) {
|
|
95
|
+
json[gameId].memo = pangu.spacing(memo)
|
|
96
|
+
}
|
|
91
97
|
}
|
|
92
98
|
|
|
99
|
+
IGNORE_DATA.forEach((gameId) => delete json[gameId])
|
|
93
100
|
const data = JSON.stringify(json, undefined, 2)
|
|
94
101
|
writeFileSync(`${OUTPUT_PATH}/${FILE_NAME}`, data)
|
|
95
102
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import
|
|
3
|
-
import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs'
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
4
3
|
import pangu from 'pangu'
|
|
4
|
+
import path from 'path'
|
|
5
5
|
import { fetch } from './proxyFetch'
|
|
6
|
+
import { prepareDir } from './utils'
|
|
6
7
|
|
|
7
8
|
// See https://github.com/antest1/kcanotify-gamedata
|
|
8
9
|
|
|
@@ -14,12 +15,6 @@ const DATA_URL = `${URL_PREFIX}/files`
|
|
|
14
15
|
const LANGS = ['scn', 'tcn', 'jp', 'en', 'ko'] as const
|
|
15
16
|
const LOCALES = ['zh-CN', 'zh-TW', 'ja-JP', 'en-US', 'ko-KR'] as const
|
|
16
17
|
|
|
17
|
-
const prepare = () => {
|
|
18
|
-
if (!existsSync(OUTPUT_PATH)) {
|
|
19
|
-
mkdirSync(OUTPUT_PATH, { recursive: true })
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
18
|
const getRemoteVersion = async () => {
|
|
24
19
|
const resp = await fetch(VERSION_URL)
|
|
25
20
|
if (!resp.ok) {
|
|
@@ -73,7 +68,7 @@ const genTS = (version: string) => {
|
|
|
73
68
|
const main = async () => {
|
|
74
69
|
const args = process.argv.slice(2)
|
|
75
70
|
|
|
76
|
-
|
|
71
|
+
prepareDir(OUTPUT_PATH)
|
|
77
72
|
const remoteVersion = await getRemoteVersion()
|
|
78
73
|
const localVersion = getLocalVersion()
|
|
79
74
|
if (remoteVersion === localVersion) {
|
|
@@ -102,12 +97,20 @@ const main = async () => {
|
|
|
102
97
|
text = text.trim()
|
|
103
98
|
|
|
104
99
|
const json = JSON.parse(text) as {
|
|
105
|
-
[gameId: string]: {
|
|
100
|
+
[gameId: string]: {
|
|
101
|
+
code: string
|
|
102
|
+
name: string
|
|
103
|
+
desc: string
|
|
104
|
+
memo?: string
|
|
105
|
+
}
|
|
106
106
|
}
|
|
107
107
|
for (const gameId in json) {
|
|
108
|
-
const { name, desc } = json[gameId]
|
|
108
|
+
const { name, desc, memo } = json[gameId]
|
|
109
109
|
json[gameId].name = pangu.spacing(name)
|
|
110
110
|
json[gameId].desc = pangu.spacing(desc)
|
|
111
|
+
if (memo) {
|
|
112
|
+
json[gameId].memo = pangu.spacing(memo)
|
|
113
|
+
}
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
const data = JSON.stringify(json, undefined, 2)
|
|
@@ -5,6 +5,7 @@ import crypto from 'crypto'
|
|
|
5
5
|
// See https://sharp.pixelplumbing.com/
|
|
6
6
|
import sharp from 'sharp'
|
|
7
7
|
import { fetch } from './proxyFetch'
|
|
8
|
+
import { prepareDir } from './utils'
|
|
8
9
|
|
|
9
10
|
const OUTPUT_PATH = path.resolve('build', 'dutySprites')
|
|
10
11
|
|
|
@@ -15,12 +16,6 @@ const VERSION = '5.1.2.0'
|
|
|
15
16
|
const SPRITES_URL = `${SERVER_URL}${SPRITES_PATH}?version=${VERSION}`
|
|
16
17
|
const META_URL = `${SERVER_URL}${JSON_PATH}?version=${VERSION}`
|
|
17
18
|
|
|
18
|
-
const prepare = () => {
|
|
19
|
-
if (!fs.existsSync(OUTPUT_PATH)) {
|
|
20
|
-
fs.mkdirSync(OUTPUT_PATH, { recursive: true })
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
19
|
const getFilename = (url: string) => {
|
|
25
20
|
const pathname = new URL(url).pathname
|
|
26
21
|
const index = pathname.lastIndexOf('/')
|
|
@@ -109,7 +104,7 @@ const parseSprites = (sprites: Buffer, meta: KCS2Meta) => {
|
|
|
109
104
|
}
|
|
110
105
|
|
|
111
106
|
const main = async () => {
|
|
112
|
-
|
|
107
|
+
prepareDir(OUTPUT_PATH)
|
|
113
108
|
const [
|
|
114
109
|
{ buffer: metaBuffer },
|
|
115
110
|
{ filePath: spritesPath, buffer: spritesBuffer },
|
package/scripts/utils.ts
ADDED
package/src/Toolbar.tsx
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { Button, InputGroup, Intent, Tag, Tooltip } from '@blueprintjs/core'
|
|
2
2
|
import { IconNames } from '@blueprintjs/icons'
|
|
3
|
-
import styled from 'styled-components'
|
|
4
|
-
import React, { useCallback } from 'react'
|
|
5
3
|
import type { ChangeEvent } from 'react'
|
|
4
|
+
import React, { useCallback } from 'react'
|
|
6
5
|
import { useThrottle } from 'react-use'
|
|
7
|
-
import
|
|
6
|
+
import styled from 'styled-components'
|
|
7
|
+
import { IN_POI } from './poi/env'
|
|
8
|
+
import { usePluginTranslation } from './poi/hooks'
|
|
9
|
+
import type { UnionQuest } from './questHelper'
|
|
10
|
+
import { useQuest, useSyncWithGame } from './store'
|
|
11
|
+
import { useFilterTags } from './store/filterTags'
|
|
12
|
+
import { useSearchInput } from './store/search'
|
|
8
13
|
import {
|
|
9
|
-
ALL_TYPE_TAG,
|
|
10
14
|
ALL_CATEGORY_TAG,
|
|
11
|
-
TYPE_TAGS,
|
|
12
|
-
CATEGORY_TAGS,
|
|
13
15
|
ALL_TAGS,
|
|
16
|
+
ALL_TYPE_TAG,
|
|
17
|
+
CATEGORY_TAGS,
|
|
18
|
+
TYPE_TAGS,
|
|
14
19
|
} from './tags'
|
|
15
|
-
import type { UnionQuest } from './questHelper'
|
|
16
|
-
import { usePluginTranslation } from './poi/hooks'
|
|
17
|
-
import { IN_POI } from './poi/env'
|
|
18
20
|
|
|
19
21
|
const ToolbarWrapper = styled.div`
|
|
20
22
|
display: flex;
|
|
@@ -37,18 +39,21 @@ const TagsWrapper = styled.div`
|
|
|
37
39
|
|
|
38
40
|
const SyncButton = () => {
|
|
39
41
|
const { t } = usePluginTranslation()
|
|
40
|
-
const {
|
|
41
|
-
|
|
42
|
-
updateStore,
|
|
43
|
-
} = useStore()
|
|
42
|
+
const { searchInput } = useSearchInput()
|
|
43
|
+
const { syncWithGame, toggleSyncWithGame } = useSyncWithGame()
|
|
44
44
|
const handleClick = useCallback(() => {
|
|
45
|
-
|
|
46
|
-
}, [
|
|
45
|
+
toggleSyncWithGame()
|
|
46
|
+
}, [toggleSyncWithGame])
|
|
47
|
+
const intent = syncWithGame
|
|
48
|
+
? searchInput
|
|
49
|
+
? Intent.WARNING
|
|
50
|
+
: Intent.SUCCESS
|
|
51
|
+
: Intent.NONE
|
|
47
52
|
return (
|
|
48
53
|
<Tooltip content={t('Sync with game')}>
|
|
49
54
|
<Button
|
|
50
55
|
icon={IconNames.EXCHANGE}
|
|
51
|
-
intent={
|
|
56
|
+
intent={intent}
|
|
52
57
|
disabled={!IN_POI}
|
|
53
58
|
onClick={handleClick}
|
|
54
59
|
/>
|
|
@@ -58,24 +63,30 @@ const SyncButton = () => {
|
|
|
58
63
|
|
|
59
64
|
export const SearchInput: React.FC = () => {
|
|
60
65
|
const { t } = usePluginTranslation()
|
|
61
|
-
const {
|
|
62
|
-
store: { searchInput },
|
|
63
|
-
updateStore,
|
|
64
|
-
} = useStore()
|
|
66
|
+
const { searchInput, setSearchInput } = useSearchInput()
|
|
65
67
|
|
|
66
68
|
const handleChange = useCallback(
|
|
67
69
|
(event: ChangeEvent<HTMLInputElement>) =>
|
|
68
|
-
|
|
69
|
-
[
|
|
70
|
+
setSearchInput(event.target.value),
|
|
71
|
+
[setSearchInput]
|
|
70
72
|
)
|
|
71
73
|
|
|
74
|
+
const handleClear = useCallback(() => setSearchInput(''), [setSearchInput])
|
|
75
|
+
|
|
72
76
|
return (
|
|
73
77
|
<InputGroup
|
|
74
78
|
value={searchInput}
|
|
75
79
|
onChange={handleChange}
|
|
76
80
|
placeholder={t('Search')}
|
|
77
81
|
leftIcon={IconNames.SEARCH}
|
|
78
|
-
rightElement={
|
|
82
|
+
rightElement={
|
|
83
|
+
<>
|
|
84
|
+
{!!searchInput && (
|
|
85
|
+
<Button icon={IconNames.CROSS} onClick={handleClear} />
|
|
86
|
+
)}
|
|
87
|
+
<SyncButton></SyncButton>
|
|
88
|
+
</>
|
|
89
|
+
}
|
|
79
90
|
type="text"
|
|
80
91
|
/>
|
|
81
92
|
)
|
|
@@ -83,22 +94,16 @@ export const SearchInput: React.FC = () => {
|
|
|
83
94
|
|
|
84
95
|
const Tags = () => {
|
|
85
96
|
const { t } = usePluginTranslation()
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
} = useStore()
|
|
90
|
-
const withHandleClickTag = useCallback(
|
|
91
|
-
(tagName: string, key: 'typeTags' | 'categoryTags') => () =>
|
|
92
|
-
updateStore({ [key]: { [tagName]: true } }),
|
|
93
|
-
[updateStore]
|
|
94
|
-
)
|
|
97
|
+
|
|
98
|
+
const { typeTags, categoryTags, setCategoryTags, setTypeTags } =
|
|
99
|
+
useFilterTags()
|
|
95
100
|
|
|
96
101
|
return (
|
|
97
102
|
<>
|
|
98
103
|
<TagsWrapper>
|
|
99
104
|
{CATEGORY_TAGS.map(({ name }) => (
|
|
100
105
|
<Tag
|
|
101
|
-
onClick={
|
|
106
|
+
onClick={() => setCategoryTags(name)}
|
|
102
107
|
intent={
|
|
103
108
|
categoryTags[name]
|
|
104
109
|
? name === ALL_CATEGORY_TAG.name
|
|
@@ -116,7 +121,7 @@ const Tags = () => {
|
|
|
116
121
|
<TagsWrapper>
|
|
117
122
|
{TYPE_TAGS.map(({ name }) => (
|
|
118
123
|
<Tag
|
|
119
|
-
onClick={
|
|
124
|
+
onClick={() => setTypeTags(name)}
|
|
120
125
|
intent={
|
|
121
126
|
typeTags[name]
|
|
122
127
|
? name === ALL_TYPE_TAG.name
|
|
@@ -145,9 +150,9 @@ export const Toolbar = () => {
|
|
|
145
150
|
}
|
|
146
151
|
|
|
147
152
|
const useToolbarFilter = () => {
|
|
148
|
-
const {
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
const { searchInput } = useSearchInput()
|
|
154
|
+
const { typeTags, categoryTags } = useFilterTags()
|
|
155
|
+
|
|
151
156
|
const activatedTags = { ...typeTags, ...categoryTags }
|
|
152
157
|
const activatedTagsName = ALL_TAGS.filter((tag) => activatedTags[tag.name])
|
|
153
158
|
const tagsFilter = activatedTagsName.map((tag) => tag.filter)
|
|
@@ -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(`"
|
|
4
|
+
expect(version).toMatchInlineSnapshot(`"2022020101"`)
|
|
5
5
|
})
|
|
6
6
|
|
|
7
7
|
test('should Kcanotify Game data keys correct', () => {
|
|
@@ -2,7 +2,7 @@ import { version, KcwikiQuestData } from '../../build/kcQuestsData'
|
|
|
2
2
|
|
|
3
3
|
test('should KcwikiQuestData Game data version correct', () => {
|
|
4
4
|
expect(version).toMatchInlineSnapshot(
|
|
5
|
-
`"
|
|
5
|
+
`"56b37a6d0a5ee58e8b88be58f7d7efff31ac6e28"`
|
|
6
6
|
)
|
|
7
7
|
})
|
|
8
8
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Tag } from '@blueprintjs/core'
|
|
2
|
+
import React, { useCallback } from 'react'
|
|
3
|
+
import styled from 'styled-components'
|
|
4
|
+
import { guessQuestCategory } from '../questHelper'
|
|
5
|
+
import { useFilterTags } from '../store/filterTags'
|
|
6
|
+
import { useSearchInput } from '../store/search'
|
|
7
|
+
|
|
8
|
+
const TagWrapper = styled(Tag)`
|
|
9
|
+
margin: 0 4px;
|
|
10
|
+
user-select: none;
|
|
11
|
+
|
|
12
|
+
& > span {
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
}
|
|
15
|
+
`
|
|
16
|
+
|
|
17
|
+
export const PreTaskTag = ({ code }: { code: string }) => {
|
|
18
|
+
const { setSearchInput } = useSearchInput()
|
|
19
|
+
const { setCategoryTagsAll, setTypeTagsAll } = useFilterTags()
|
|
20
|
+
|
|
21
|
+
const handleClick = useCallback(() => {
|
|
22
|
+
setSearchInput(code)
|
|
23
|
+
setCategoryTagsAll()
|
|
24
|
+
setTypeTagsAll()
|
|
25
|
+
}, [code, setCategoryTagsAll, setSearchInput, setTypeTagsAll])
|
|
26
|
+
const indicatorColor = guessQuestCategory(code).color
|
|
27
|
+
const fontColor =
|
|
28
|
+
indicatorColor === '#fff' || indicatorColor === '#87da61'
|
|
29
|
+
? 'black'
|
|
30
|
+
: 'white'
|
|
31
|
+
return (
|
|
32
|
+
<TagWrapper
|
|
33
|
+
onClick={handleClick}
|
|
34
|
+
interactive
|
|
35
|
+
style={{ color: fontColor, background: indicatorColor }}
|
|
36
|
+
>
|
|
37
|
+
{code}
|
|
38
|
+
</TagWrapper>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Elevation, Text, Tooltip } from '@blueprintjs/core'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { guessQuestCategory, QUEST_STATUS } from '../../questHelper'
|
|
4
|
+
import type { QuestCardProps } from './index'
|
|
5
|
+
import { CardBody, CardTail, CatIndicator, FlexCard } from './styles'
|
|
6
|
+
import { questStatusMap } from './utils'
|
|
7
|
+
|
|
8
|
+
export const MinimalQuestCard: React.FC<QuestCardProps> = ({
|
|
9
|
+
code,
|
|
10
|
+
name,
|
|
11
|
+
desc,
|
|
12
|
+
tips,
|
|
13
|
+
status = QUEST_STATUS.DEFAULT,
|
|
14
|
+
onClick,
|
|
15
|
+
style,
|
|
16
|
+
}) => {
|
|
17
|
+
const indicatorColor = guessQuestCategory(code).color
|
|
18
|
+
const TailIcon = questStatusMap[status]
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Tooltip
|
|
22
|
+
targetTagName="div"
|
|
23
|
+
content={
|
|
24
|
+
<>
|
|
25
|
+
{desc}
|
|
26
|
+
<br />
|
|
27
|
+
{tips}
|
|
28
|
+
</>
|
|
29
|
+
}
|
|
30
|
+
>
|
|
31
|
+
<FlexCard
|
|
32
|
+
elevation={Elevation.ZERO}
|
|
33
|
+
interactive={true}
|
|
34
|
+
onClick={onClick}
|
|
35
|
+
style={style}
|
|
36
|
+
>
|
|
37
|
+
<CatIndicator color={indicatorColor}></CatIndicator>
|
|
38
|
+
<CardBody>
|
|
39
|
+
<Text>{[code, name].filter((i) => i != undefined).join(' - ')}</Text>
|
|
40
|
+
</CardBody>
|
|
41
|
+
|
|
42
|
+
<CardTail>
|
|
43
|
+
<TailIcon></TailIcon>
|
|
44
|
+
</CardTail>
|
|
45
|
+
</FlexCard>
|
|
46
|
+
</Tooltip>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Elevation, H5, Text } from '@blueprintjs/core'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import styled from 'styled-components'
|
|
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'
|
|
8
|
+
import { questIconMap, questStatusMap } from './utils'
|
|
9
|
+
|
|
10
|
+
export type QuestCardProps = {
|
|
11
|
+
code: string
|
|
12
|
+
name: string
|
|
13
|
+
desc: string | JSX.Element
|
|
14
|
+
tips?: string
|
|
15
|
+
status?: QUEST_STATUS
|
|
16
|
+
preTask?: string[]
|
|
17
|
+
onClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void
|
|
18
|
+
style?: React.CSSProperties
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const PreTaskTagWrapper = styled.div`
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: baseline;
|
|
24
|
+
`
|
|
25
|
+
|
|
26
|
+
export const LargeQuestCard = ({
|
|
27
|
+
code,
|
|
28
|
+
name,
|
|
29
|
+
desc,
|
|
30
|
+
tips,
|
|
31
|
+
preTask,
|
|
32
|
+
status = QUEST_STATUS.DEFAULT,
|
|
33
|
+
onClick,
|
|
34
|
+
style,
|
|
35
|
+
}: QuestCardProps) => {
|
|
36
|
+
const headIcon = questIconMap[guessQuestCategory(code).type]
|
|
37
|
+
const TailIcon = questStatusMap[status]
|
|
38
|
+
const { t } = usePluginTranslation()
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<FlexCard
|
|
42
|
+
elevation={Elevation.ZERO}
|
|
43
|
+
interactive={false}
|
|
44
|
+
onClick={onClick}
|
|
45
|
+
style={style}
|
|
46
|
+
>
|
|
47
|
+
<CardMedia src={headIcon}></CardMedia>
|
|
48
|
+
<CardBody>
|
|
49
|
+
<H5>{[code, name].filter((i) => i != undefined).join(' - ')}</H5>
|
|
50
|
+
<Text>{desc}</Text>
|
|
51
|
+
{tips && <Text tagName="i">{tips}</Text>}
|
|
52
|
+
<PreTaskTagWrapper>
|
|
53
|
+
{!!preTask?.length && <Text tagName="span">{t('Requires')}</Text>}
|
|
54
|
+
{preTask?.map((i) => (
|
|
55
|
+
<PreTaskTag key={i} code={i}></PreTaskTag>
|
|
56
|
+
))}
|
|
57
|
+
</PreTaskTagWrapper>
|
|
58
|
+
</CardBody>
|
|
59
|
+
|
|
60
|
+
<CardTail>
|
|
61
|
+
<TailIcon />
|
|
62
|
+
</CardTail>
|
|
63
|
+
</FlexCard>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const QuestCard: React.FC<QuestCardProps & { gameId: string }> = ({
|
|
68
|
+
...props
|
|
69
|
+
}) => {
|
|
70
|
+
return <LargeQuestCard {...props}></LargeQuestCard>
|
|
71
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Card } from '@blueprintjs/core'
|
|
2
|
+
import styled from 'styled-components'
|
|
3
|
+
|
|
4
|
+
export const FlexCard = styled(Card)`
|
|
5
|
+
display: flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
|
|
8
|
+
& > * + * {
|
|
9
|
+
margin-left: 8px;
|
|
10
|
+
}
|
|
11
|
+
`
|
|
12
|
+
|
|
13
|
+
export const CardMedia = styled.img`
|
|
14
|
+
width: 64px;
|
|
15
|
+
height: 64px;
|
|
16
|
+
`
|
|
17
|
+
|
|
18
|
+
export const CatIndicator = styled.span<{ color: string }>`
|
|
19
|
+
height: 1em;
|
|
20
|
+
width: 4px;
|
|
21
|
+
background-color: ${({ color }) => color};
|
|
22
|
+
`
|
|
23
|
+
|
|
24
|
+
export const CardBody = styled.div`
|
|
25
|
+
display: flex;
|
|
26
|
+
flex: 1;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
|
|
29
|
+
& > * + * {
|
|
30
|
+
margin-top: 8px;
|
|
31
|
+
}
|
|
32
|
+
`
|
|
33
|
+
|
|
34
|
+
export const CardTail = styled.div`
|
|
35
|
+
display: flex;
|
|
36
|
+
justify-content: center;
|
|
37
|
+
align-items: center;
|
|
38
|
+
|
|
39
|
+
img {
|
|
40
|
+
height: 20px;
|
|
41
|
+
}
|
|
42
|
+
`
|