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.
Files changed (36) hide show
  1. package/.eslintrc.js +1 -1
  2. package/build/kcQuestsData/DATA_VERSION +1 -1
  3. package/build/kcQuestsData/index.ts +1 -1
  4. package/build/kcQuestsData/quests-scn.json +1121 -1100
  5. package/build/kcanotifyGamedata/DATA_VERSION +1 -1
  6. package/build/kcanotifyGamedata/index.ts +1 -1
  7. package/build/kcanotifyGamedata/quests-en.json +60 -36
  8. package/build/kcanotifyGamedata/quests-jp.json +506 -482
  9. package/build/kcanotifyGamedata/quests-ko.json +101 -77
  10. package/build/kcanotifyGamedata/quests-scn.json +274 -251
  11. package/build/kcanotifyGamedata/quests-tcn.json +274 -251
  12. package/i18n/en-US.json +2 -1
  13. package/i18n/ja-JP.json +2 -1
  14. package/i18n/ko-KR.json +1 -0
  15. package/i18n/zh-CN.json +2 -1
  16. package/i18n/zh-TW.json +1 -0
  17. package/package.json +2 -2
  18. package/scripts/convertAssets.ts +2 -7
  19. package/scripts/downloadKcQuestsData.ts +17 -10
  20. package/scripts/downloadKcanotifyGamedata.ts +14 -11
  21. package/scripts/downloadSprites.ts +2 -7
  22. package/scripts/utils.ts +8 -0
  23. package/src/Toolbar.tsx +42 -37
  24. package/src/__tests__/kcanotifyData.spec.ts +1 -1
  25. package/src/__tests__/kcwikiData.spec.ts +1 -1
  26. package/src/components/PreTaskTag.tsx +40 -0
  27. package/src/components/QuestCard/MinimalQuestCard.tsx +48 -0
  28. package/src/components/QuestCard/index.tsx +71 -0
  29. package/src/components/QuestCard/styles.ts +42 -0
  30. package/src/components/QuestCard/utils.tsx +68 -0
  31. package/src/components/QuestList.tsx +2 -1
  32. package/src/questHelper.ts +1 -0
  33. package/src/store/filterTags.ts +44 -0
  34. package/src/store/search.ts +17 -0
  35. package/src/store/store.tsx +25 -2
  36. 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
@@ -11,5 +11,6 @@
11
11
  "View source code on GitHub": "GitHub에서 소스코드를 알아보세요",
12
12
  "Restore defaults": "기본값 복원",
13
13
  "Use Kcwiki data": "Kcwiki의 데이터 사용(중국어 간체만 해당)",
14
+ "Requires": "필요",
14
15
  "": ""
15
16
  }
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
@@ -26,5 +26,6 @@
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poi-plugin-quest-info-2",
3
- "version": "0.5.9",
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.38.0",
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",
@@ -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
- prepare()
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 path from 'path'
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
- const prepare = () => {
16
- if (!existsSync(OUTPUT_PATH)) {
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
- prepare()
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]: { code: string; name: string; desc: 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 path from 'path'
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
- prepare()
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]: { code: string; name: string; desc: 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
- prepare()
107
+ prepareDir(OUTPUT_PATH)
113
108
  const [
114
109
  { buffer: metaBuffer },
115
110
  { filePath: spritesPath, buffer: spritesBuffer },
@@ -0,0 +1,8 @@
1
+ import { existsSync, mkdirSync } from 'fs'
2
+ import type { PathLike } from 'fs'
3
+
4
+ export const prepareDir = (dir: PathLike) => {
5
+ if (!existsSync(dir)) {
6
+ mkdirSync(dir, { recursive: true })
7
+ }
8
+ }
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 { useQuest, useStore } from './store'
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
- store: { syncWithGame },
42
- updateStore,
43
- } = useStore()
42
+ const { searchInput } = useSearchInput()
43
+ const { syncWithGame, toggleSyncWithGame } = useSyncWithGame()
44
44
  const handleClick = useCallback(() => {
45
- updateStore({ syncWithGame: !syncWithGame })
46
- }, [syncWithGame, updateStore])
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={syncWithGame ? Intent.SUCCESS : Intent.NONE}
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
- updateStore({ searchInput: event.target.value }),
69
- [updateStore]
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={<SyncButton></SyncButton>}
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
- const {
87
- store: { typeTags, categoryTags },
88
- updateStore,
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={withHandleClickTag(name, 'categoryTags')}
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={withHandleClickTag(name, 'typeTags')}
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
- store: { searchInput, typeTags, categoryTags },
150
- } = useStore()
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(`"2021122901"`)
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
- `"7e8ee6c176e45f71c6af4c10d66c708d40d938e2"`
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
+ `