Skip to content

Commit 812356c

Browse files
authored
Merge pull request #11 from instytutfi/feature/language-toggler
2 parents 9d4acff + 2de179c commit 812356c

File tree

8 files changed

+117
-11
lines changed

8 files changed

+117
-11
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "estateguru-tax",
33
"private": true,
4-
"version": "1.0.2",
4+
"version": "1.1.0",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

src/common/constants.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,16 @@ const DEDUCTION_TYPES = [
1313
'Sale fee', 'Secondary Market Loss', 'Fee'
1414
] as const
1515

16+
const LANG_CODES = ['en', 'pl'] as const
17+
18+
const LANG_ICONS = {
19+
en: '🇬🇧',
20+
pl: '🇵🇱'
21+
} as const
22+
1623
export {
1724
INCOME_TYPES,
18-
DEDUCTION_TYPES
25+
DEDUCTION_TYPES,
26+
LANG_CODES,
27+
LANG_ICONS
1928
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react'
2+
3+
import { render } from '@testing-library/react'
4+
5+
import LanguageSwitcher from './LanguageSwitcher'
6+
7+
describe('LanguageSwitcher', () => {
8+
it('renders without error', async () => {
9+
render(<LanguageSwitcher />)
10+
})
11+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import React, { type FC, Fragment } from 'react'
2+
3+
import { Menu, Transition } from '@headlessui/react'
4+
import clsx from 'clsx'
5+
import { useTranslation } from 'react-i18next'
6+
7+
import { type LANG_CODES, LANG_ICONS } from 'common/constants'
8+
9+
const Item: FC<ItemProps> = ({ language }) => {
10+
const { i18n, t } = useTranslation()
11+
12+
const handleClick = async (): Promise<void> => {
13+
await i18n.changeLanguage(language)
14+
}
15+
16+
return (
17+
<Menu.Item>
18+
{({ active }) => (
19+
<button
20+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
21+
onClick={handleClick}
22+
className={clsx(
23+
'flex w-full items-center rounded-md px-4 py-2 font-medium transition-all',
24+
!active && 'text-gray-900',
25+
active && 'bg-blue-600 text-white'
26+
)}
27+
>
28+
<span className="text-xl mr-2">
29+
{LANG_ICONS[language]}
30+
</span>
31+
{t(`languageSwitcher.${i18n.language}.${language}.label`)}
32+
</button>
33+
)}
34+
</Menu.Item>
35+
)
36+
}
37+
38+
interface ItemProps {
39+
language: typeof LANG_CODES[number]
40+
}
41+
42+
const LanguageSwitcher: FC = () => {
43+
const { i18n, t } = useTranslation()
44+
45+
return (
46+
<Menu as="div" className="relative">
47+
<Menu.Button className="flex items-center text-slate-300 font-medium hover:text-blue-500 transition-all">
48+
<span className="text-xl mr-2">
49+
{LANG_ICONS[i18n.language as typeof LANG_CODES[number]]}
50+
</span>
51+
<span className="hidden sm:block">
52+
{t(`languageSwitcher.${i18n.language}.${i18n.language}.label`)}
53+
</span>
54+
</Menu.Button>
55+
<Transition
56+
as={Fragment}
57+
enter="transition ease-out duration-100"
58+
enterFrom="transform opacity-0 scale-95"
59+
enterTo="transform opacity-100 scale-100"
60+
leave="transition ease-in duration-75"
61+
leaveFrom="transform opacity-100 scale-100"
62+
leaveTo="transform opacity-0 scale-95"
63+
>
64+
<Menu.Items
65+
className="absolute right-0 mt-2 p-2 w-44 origin-top-right divide-y divide-gray-100 rounded-md bg-slate-50 shadow-2xl shadow-slate-800/40 ring-1 ring-black ring-opacity-5 focus:outline-none"
66+
>
67+
<Item language="pl" />
68+
<Item language="en" />
69+
</Menu.Items>
70+
</Transition>
71+
</Menu>
72+
)
73+
}
74+
75+
export default LanguageSwitcher
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from './LanguageSwitcher'

src/components/Navbar/Navbar.tsx

+13-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { useTranslation } from 'react-i18next'
66

77
import { GithubIcon } from 'assets/icons'
88

9+
import { LanguageSwitcher } from 'components'
10+
911
const Navbar: FC = () => {
1012
const { t } = useTranslation()
1113
const [isLogoHovered, setIsLogoHovered] = useState<boolean>(false)
@@ -26,14 +28,17 @@ const Navbar: FC = () => {
2628
{t('app.name')}
2729
</span>
2830
</a>
29-
<a
30-
target="_blank"
31-
rel="noopener noreferrer"
32-
href="https://github.com/instytutfi/estateguru-tax"
33-
className="text-slate-500 hover:text-white transition-all"
34-
>
35-
<GithubIcon className="h-6 w-6" />
36-
</a>
31+
<div className="flex items-center gap-8">
32+
<LanguageSwitcher />
33+
<a
34+
target="_blank"
35+
rel="noopener noreferrer"
36+
href="https://github.com/instytutfi/estateguru-tax"
37+
className="text-slate-500 hover:text-white transition-all"
38+
>
39+
<GithubIcon className="h-6 w-6" />
40+
</a>
41+
</div>
3742
</div>
3843
</div>
3944
</div>

src/components/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable sort-imports, import/order */
22

33
/* PLOP_INJECT_EXPORT */
4+
export { default as LanguageSwitcher } from './LanguageSwitcher'
45
export { default as Alert } from './Alert'
56
export { default as Checkbox } from './Checkbox'
67
export { default as Faq } from './Faq'

src/locale/en.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,9 @@
4040
"faq.related.answer": "No. The Estateguru Tax Calculator is not related to Estateguru. It is an independent tool created by a third party. Estateguru does not endorse the use of the Estateguru Tax Calculator, and it does not take any responsibility for the results of the calculations generated by the tool.",
4141
"footer.disclaimer": "Results rendered by the use of this tool should be treated as suggestions and are not guaranteed to be accurate calculations of the actual Estateguru investment income, nor the amount of income tax that ought to be paid. Always consult a professional accountant. The creator of this tool takes no responsibility for the calculations generated by the Estateguru Tax Calculator.",
4242
"footer.copyright": "© {year} Mateusz Ciszczoń/{fiLink}",
43-
"footer.oss": "Estateguru Tax Calculator is an open source tool. Feel free to improve it!"
43+
"footer.oss": "Estateguru Tax Calculator is an open source tool. Feel free to improve it!",
44+
"languageSwitcher.en.en.label": "English",
45+
"languageSwitcher.en.pl.label": "Polish",
46+
"languageSwitcher.pl.en.label": "angielski",
47+
"languageSwitcher.pl.pl.label": "polski"
4448
}

0 commit comments

Comments
 (0)