Skip to content

Commit 97bc47c

Browse files
committed
migrate settings to typescript
1 parent 4b4ee46 commit 97bc47c

9 files changed

Lines changed: 148 additions & 57 deletions

File tree

craco.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
const path = require('path')
2+
const webpack = require('webpack')
23

34
function isDevelopmentEnv() {
45
return process.env.NODE_ENV === 'development'
56
}
67

78
module.exports = {
89
webpack: {
10+
plugins: {
11+
add: [
12+
new webpack.DefinePlugin({
13+
process: { env: {} },
14+
}),
15+
],
16+
},
917
alias: {
1018
'@': path.resolve(__dirname, 'src'),
1119
},

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"react-modal": "^3.12.1",
2727
"react-pro-sidebar": "^0.6.0",
2828
"react-scripts": "4.0.1",
29-
"react-select": "^4.0.2",
29+
"react-select": "^5.0.1",
3030
"react-spinners": "^0.10.4",
3131
"react-toggle": "^4.1.1",
3232
"react-tooltip": "^4.2.21",
@@ -68,6 +68,8 @@
6868
"@types/node": "^18.11.0",
6969
"@types/react": "^18.0.21",
7070
"@types/react-dom": "^18.0.6",
71+
"@types/react-modal": "^3.13.1",
72+
"@types/react-toggle": "^4.0.3",
7173
"@typescript-eslint/eslint-plugin": "^5.40.1",
7274
"@typescript-eslint/parser": "^5.40.1",
7375
"eslint-config-airbnb": "19.0.4",

src/components/Header.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { BsFillBookmarksFill } from 'react-icons/bs'
55
import { ReactComponent as HackertabLogo } from '../logo.svg'
66
import UserTags from './UserTags'
77
import { SUPPORTED_SEARCH_ENGINES } from '../Constants'
8-
import SettingsModal from '../settings/SettingsModal'
8+
import { SettingsModal } from 'src/features/settings'
99
import { BsMoon } from 'react-icons/bs'
1010
import { IoMdSunny } from 'react-icons/io'
1111
import { trackSearchEngineUse } from 'src/lib/analytics'
@@ -15,7 +15,7 @@ import { GoSearch } from 'react-icons/go'
1515
function SearchBar({ state }) {
1616
const keywordsInputRef = React.useRef(null)
1717
const userSearchEngine = SUPPORTED_SEARCH_ENGINES.find(
18-
(engine) => engine.label == state.searchEngine
18+
(engine) => engine.label === state.searchEngine
1919
)
2020

2121
const handleSubmit = (e) => {

src/settings/SettingsModal.js renamed to src/features/settings/components/SettingsModal.tsx

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import React, { useContext, useState } from "react";
2-
import ReactModal from 'react-modal';
3-
import "react-toggle/style.css"
4-
import { VscClose } from "react-icons/vsc"
5-
import Select from 'react-select'
1+
import React, { useContext, useState } from 'react'
2+
import ReactModal from 'react-modal'
3+
import 'react-toggle/style.css'
4+
import { VscClose } from 'react-icons/vsc'
5+
import Select, { ActionMeta, MultiValue, SingleValue } from 'react-select'
6+
import { SearchEngineType } from 'src/types'
67
import Toggle from 'react-toggle'
7-
import '../App.css';
8-
import './settings.css';
9-
import PreferencesContext from '../preferences/PreferencesContext';
10-
import ConfigurationContext from '../configuration/ConfigurationContext';
11-
import { SUPPORTED_CARDS, SUPPORTED_SEARCH_ENGINES, APP } from '../Constants'
8+
import './settings.css'
9+
import PreferencesContext from 'src/preferences/PreferencesContext'
10+
import ConfigurationContext from 'src/configuration/ConfigurationContext'
11+
import { SUPPORTED_CARDS, SUPPORTED_SEARCH_ENGINES, APP } from 'src/Constants'
1212
import {
1313
trackLanguageAdd,
1414
trackLanguageRemove,
@@ -19,7 +19,17 @@ import {
1919
trackTabTarget,
2020
} from 'src/lib/analytics'
2121

22-
function SettingsModal({ showSettings, setShowSettings }) {
22+
type SettingsModalProps = {
23+
showSettings: boolean
24+
setShowSettings: (show: boolean) => void
25+
}
26+
27+
type OptionType = {
28+
value: string
29+
label: string
30+
}
31+
32+
export const SettingsModal = ({ showSettings, setShowSettings }: SettingsModalProps) => {
2333
const { supportedTags } = useContext(ConfigurationContext)
2434
const preferences = useContext(PreferencesContext)
2535
const { dispatcher, cards, userSelectedTags, openLinksNewTab, listingMode, theme, searchEngine } =
@@ -30,32 +40,41 @@ function SettingsModal({ showSettings, setShowSettings }) {
3040
setShowSettings(false)
3141
}
3242

33-
const onTagsSelectChange = (tags, metas) => {
43+
const onTagsSelectChange = (tags: MultiValue<OptionType>, metas: ActionMeta<OptionType>) => {
3444
switch (metas.action) {
3545
case 'select-option':
36-
trackLanguageAdd(metas.option.label)
46+
if (metas.option?.label) {
47+
trackLanguageAdd(metas.option.label)
48+
}
3749
break
3850
case 'remove-value':
39-
trackLanguageRemove(metas.removedValue.label)
51+
if (metas.removedValue?.label) {
52+
trackLanguageRemove(metas.removedValue.label)
53+
}
54+
4055
break
4156
}
4257

4358
dispatcher({ type: 'setUserSelectedTags', value: tags })
4459
}
4560

46-
const onlistingModeChange = (e) => {
61+
const onlistingModeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
4762
const value = e.target.checked ? 'compact' : 'normal'
4863
trackListingModeSelect(value)
4964
dispatcher({ type: 'changelistingMode', value })
5065
}
5166

52-
const onCardSelectChange = (cards, metas) => {
67+
const onCardSelectChange = (cards: MultiValue<OptionType>, metas: ActionMeta<OptionType>) => {
5368
switch (metas.action) {
5469
case 'select-option':
55-
trackSourceAdd(metas.option.label)
70+
if (metas.option?.label) {
71+
trackSourceAdd(metas.option.label)
72+
}
5673
break
5774
case 'remove-value':
58-
trackSourceRemove(metas.removedValue.label)
75+
if (metas.removedValue?.label) {
76+
trackSourceRemove(metas.removedValue.label)
77+
}
5978
break
6079
}
6180

@@ -66,18 +85,22 @@ function SettingsModal({ showSettings, setShowSettings }) {
6685
dispatcher({ type: 'setCards', value: newCards })
6786
}
6887

69-
const onSearchEngineSelectChange = (value) => {
88+
const onSearchEngineSelectChange = (value: SingleValue<SearchEngineType>) => {
89+
if (!value) {
90+
return
91+
}
92+
7093
trackSearchEngineSelect(value.label)
7194
dispatcher({ type: 'setSearchEngine', value })
7295
}
7396

74-
const onOpenLinksNewTabChange = (e) => {
97+
const onOpenLinksNewTabChange = (e: React.ChangeEvent<HTMLInputElement>) => {
7598
const checked = e.target.checked
7699
trackTabTarget(checked)
77100
dispatcher({ type: 'setOpenLinksNewTab', value: checked })
78101
}
79102

80-
const onDarkModeChange = (e) => {
103+
const onDarkModeChange = () => {
81104
dispatcher({ type: 'toggleTheme' })
82105
}
83106

@@ -127,7 +150,7 @@ function SettingsModal({ showSettings, setShowSettings }) {
127150
<Select
128151
options={SUPPORTED_CARDS}
129152
value={selectedCards.map((c) => ({
130-
label: SUPPORTED_CARDS.find((c2) => c.name == c2.value).label,
153+
label: SUPPORTED_CARDS.find((c2) => c.name === c2.value)?.label || '',
131154
value: c.name,
132155
}))}
133156
onChange={onCardSelectChange}
@@ -138,7 +161,7 @@ function SettingsModal({ showSettings, setShowSettings }) {
138161
/>
139162
<p className="settingHint">
140163
Missing a cool data source? create an issue{' '}
141-
<a href="#" onClick={(e) => window.open(APP.supportLink, '_blank')}>
164+
<a href="#" onClick={(_e) => window.open(APP.supportLink, '_blank')}>
142165
here
143166
</a>
144167
</p>
@@ -163,7 +186,7 @@ function SettingsModal({ showSettings, setShowSettings }) {
163186
<p className="settingTitle">Compact mode</p>
164187
<div className="settingContent">
165188
<Toggle
166-
checked={listingMode == 'compact'}
189+
checked={listingMode === 'compact'}
167190
icons={false}
168191
onChange={onlistingModeChange}
169192
/>
@@ -175,7 +198,7 @@ function SettingsModal({ showSettings, setShowSettings }) {
175198
<div className="settingContent">
176199
<Select
177200
options={SUPPORTED_SEARCH_ENGINES}
178-
value={SUPPORTED_SEARCH_ENGINES.find((e) => e.label == searchEngine)}
201+
value={SUPPORTED_SEARCH_ENGINES.find((e) => e.label === searchEngine)}
179202
isMulti={false}
180203
isClearable={false}
181204
isSearchable={false}
@@ -193,6 +216,5 @@ function SettingsModal({ showSettings, setShowSettings }) {
193216
</div>
194217
</ReactModal>
195218
)
219+
return <div></div>
196220
}
197-
198-
export default SettingsModal
File renamed without changes.

src/features/settings/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./components/SettingsModal"

src/preferences/PreferencesContext.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,33 @@
11
import React from 'react'
22

3-
const PreferencesContext = React.createContext({
4-
userSelectedTags: [],
5-
dispatcher: null,
6-
changelogMeta: {
7-
shown: false,
8-
version: "",
9-
}
3+
type PreferencesContextProps = {
4+
userSelectedTags: any[],
5+
cards: any[],
6+
openLinksNewTab: boolean,
7+
listingMode: string,
8+
searchEngine: string,
9+
theme: string,
10+
dispatcher: (value: any) => void;
11+
changelogMeta: {
12+
shown: boolean,
13+
version: string
14+
}
15+
}
16+
17+
const PreferencesContext = React.createContext<PreferencesContextProps>({
18+
userSelectedTags: [],
19+
listingMode: '',
20+
theme: '',
21+
searchEngine: '',
22+
cards: [],
23+
dispatcher: (value: any) => {
24+
console.log("Not implemented")
25+
},
26+
changelogMeta: {
27+
shown: false,
28+
version: "",
29+
},
30+
openLinksNewTab: false,
1031
});
1132

1233

src/types/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export type SearchEngineType = {
2+
url: string
3+
label: string
4+
}

0 commit comments

Comments
 (0)