poi-plugin-quest-info-2 0.5.12 → 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/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.12",
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",
@@ -80,12 +80,20 @@ const main = async () => {
80
80
  text = text.trim()
81
81
 
82
82
  const json = JSON.parse(text) as {
83
- [gameId: string]: { code: string; name: string; desc: string }
83
+ [gameId: string]: {
84
+ code: string
85
+ name: string
86
+ desc: string
87
+ memo?: string
88
+ }
84
89
  }
85
90
  for (const gameId in json) {
86
- const { name, desc } = json[gameId]
91
+ const { name, desc, memo } = json[gameId]
87
92
  json[gameId].name = pangu.spacing(name)
88
93
  json[gameId].desc = pangu.spacing(desc)
94
+ if (memo) {
95
+ json[gameId].memo = pangu.spacing(memo)
96
+ }
89
97
  }
90
98
 
91
99
  IGNORE_DATA.forEach((gameId) => delete json[gameId])
@@ -97,12 +97,20 @@ const main = async () => {
97
97
  text = text.trim()
98
98
 
99
99
  const json = JSON.parse(text) as {
100
- [gameId: string]: { code: string; name: string; desc: string }
100
+ [gameId: string]: {
101
+ code: string
102
+ name: string
103
+ desc: string
104
+ memo?: string
105
+ }
101
106
  }
102
107
  for (const gameId in json) {
103
- const { name, desc } = json[gameId]
108
+ const { name, desc, memo } = json[gameId]
104
109
  json[gameId].name = pangu.spacing(name)
105
110
  json[gameId].desc = pangu.spacing(desc)
111
+ if (memo) {
112
+ json[gameId].memo = pangu.spacing(memo)
113
+ }
106
114
  }
107
115
 
108
116
  const data = JSON.stringify(json, undefined, 2)
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(`"2022012402"`)
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
- `"1ad9f7a5373ab65fc6abea972b571dc6c44d5492"`
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
+ `
@@ -0,0 +1,68 @@
1
+ import { Icon, Tooltip } from '@blueprintjs/core'
2
+ import { IconNames } from '@blueprintjs/icons'
3
+ import React from 'react'
4
+ import {
5
+ IconArsenal,
6
+ IconCompleted,
7
+ IconComposition,
8
+ IconExercise,
9
+ IconExpedition,
10
+ IconInProgress,
11
+ IconModernization,
12
+ IconSortie,
13
+ IconSupplyDocking,
14
+ } from '../../../build/assets'
15
+ import { usePluginTranslation } from '../../poi/hooks'
16
+ import { QUEST_CATEGORY, QUEST_STATUS } from '../../questHelper'
17
+
18
+ export const questStatusMap: Record<QUEST_STATUS, React.FC> = {
19
+ [QUEST_STATUS.LOCKED]: function Locked() {
20
+ const { t } = usePluginTranslation()
21
+ return (
22
+ <Tooltip content={t('Locked')}>
23
+ <Icon icon={IconNames.LOCK} iconSize={Icon.SIZE_LARGE}></Icon>
24
+ </Tooltip>
25
+ )
26
+ },
27
+ // Display nothing
28
+ [QUEST_STATUS.DEFAULT]: () => null,
29
+ [QUEST_STATUS.IN_PROGRESS]: function InProgress() {
30
+ const { t } = usePluginTranslation()
31
+ return (
32
+ <Tooltip content={t('In Progress')}>
33
+ <img src={IconInProgress}></img>
34
+ </Tooltip>
35
+ )
36
+ },
37
+ [QUEST_STATUS.COMPLETED]: function Completed() {
38
+ const { t } = usePluginTranslation()
39
+ return (
40
+ <Tooltip content={t('Completed')}>
41
+ <img src={IconCompleted}></img>
42
+ </Tooltip>
43
+ )
44
+ },
45
+ [QUEST_STATUS.ALREADY_COMPLETED]: function AlreadyCompleted() {
46
+ const { t } = usePluginTranslation()
47
+ return (
48
+ <Tooltip content={t('Already Completed')}>
49
+ <Icon icon={IconNames.TICK} iconSize={Icon.SIZE_LARGE}></Icon>
50
+ </Tooltip>
51
+ )
52
+ },
53
+ }
54
+
55
+ // transparent GIF pixel
56
+ const PLACEHOLDER =
57
+ 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
58
+
59
+ export const questIconMap = {
60
+ [QUEST_CATEGORY.Composition]: IconComposition,
61
+ [QUEST_CATEGORY.Sortie]: IconSortie,
62
+ [QUEST_CATEGORY.Exercise]: IconExercise,
63
+ [QUEST_CATEGORY.Expedition]: IconExpedition,
64
+ [QUEST_CATEGORY.SupplyOrDocking]: IconSupplyDocking,
65
+ [QUEST_CATEGORY.Arsenal]: IconArsenal,
66
+ [QUEST_CATEGORY.Modernization]: IconModernization,
67
+ [QUEST_CATEGORY.Unknown]: PLACEHOLDER,
68
+ } as const
@@ -47,7 +47,7 @@ const useQuestsRowRenderer = (quests: UnionQuest[]) => {
47
47
  ({ key, index, style, parent }: ListRowProps) => {
48
48
  const quest = quests[index]
49
49
  const { gameId } = quest
50
- const { code, name, desc, memo } = quest.docQuest
50
+ const { code, name, desc, memo, pre } = quest.docQuest
51
51
  const questStatus = questStateToQuestStatus(quest.gameQuest?.api_state)
52
52
 
53
53
  return (
@@ -66,6 +66,7 @@ const useQuestsRowRenderer = (quests: UnionQuest[]) => {
66
66
  name={name}
67
67
  desc={desc}
68
68
  tips={memo}
69
+ preTask={pre}
69
70
  status={questStatus}
70
71
  ></QuestCard>
71
72
  </div>
@@ -8,6 +8,7 @@ type DocQuest = {
8
8
  memo?: string
9
9
  unlock?: number[]
10
10
  tracking?: number[][]
11
+ pre?: string[]
11
12
  }
12
13
 
13
14
  export type UnionQuest = {
@@ -0,0 +1,44 @@
1
+ import { useCallback } from 'react'
2
+ import {
3
+ ALL_CATEGORY_TAG,
4
+ ALL_TYPE_TAG,
5
+ CATEGORY_TAGS,
6
+ TYPE_TAGS,
7
+ } from '../tags'
8
+ import { useStore } from './store'
9
+
10
+ export const useFilterTags = () => {
11
+ const {
12
+ store: { categoryTags, typeTags },
13
+ updateStore,
14
+ } = useStore()
15
+ const setCategoryTags = useCallback(
16
+ (tagName: typeof CATEGORY_TAGS[number]['name']) => {
17
+ updateStore({ categoryTags: { [tagName]: true } })
18
+ },
19
+ [updateStore]
20
+ )
21
+
22
+ const setCategoryTagsAll = useCallback(() => {
23
+ setCategoryTags(ALL_CATEGORY_TAG.name)
24
+ }, [setCategoryTags])
25
+
26
+ const setTypeTags = useCallback(
27
+ (tagName: typeof TYPE_TAGS[number]['name']) => {
28
+ updateStore({ typeTags: { [tagName]: true } })
29
+ },
30
+ [updateStore]
31
+ )
32
+ const setTypeTagsAll = useCallback(() => {
33
+ setTypeTags(ALL_TYPE_TAG.name)
34
+ }, [setTypeTags])
35
+
36
+ return {
37
+ categoryTags,
38
+ typeTags,
39
+ setCategoryTags,
40
+ setCategoryTagsAll,
41
+ setTypeTags,
42
+ setTypeTagsAll,
43
+ }
44
+ }
@@ -0,0 +1,17 @@
1
+ import { useCallback } from 'react'
2
+ import { useStore } from './store'
3
+
4
+ export const useSearchInput = () => {
5
+ const {
6
+ store: { searchInput },
7
+ updateStore,
8
+ } = useStore()
9
+ const setSearchInput = useCallback(
10
+ (value: string) => updateStore({ searchInput: value }),
11
+ [updateStore]
12
+ )
13
+ return {
14
+ searchInput,
15
+ setSearchInput,
16
+ }
17
+ }