diff --git a/package-lock.json b/package-lock.json index 640285a..36d8fe6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,12 +16,14 @@ "@reduxjs/toolkit": "^2.2.1", "@vitejs/plugin-react-swc": "^3.3.2", "axios": "^1.6.8", + "i18next": "^23.10.1", "modern-normalize": "^2.0.0", "normalize.css": "^8.0.1", "react": "^18.2.0", "react-datepicker": "^6.3.0", "react-dom": "^18.2.0", "react-hook-form": "^7.51.0", + "react-i18next": "^14.1.0", "react-redux": "^9.1.0", "react-responsive": "^9.0.2", "react-router-dom": "^6.15.0", @@ -5798,6 +5800,14 @@ "react-is": "^16.7.0" } }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", @@ -5846,6 +5856,28 @@ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, + "node_modules/i18next": { + "version": "23.10.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.10.1.tgz", + "integrity": "sha512-NDiIzFbcs3O9PXpfhkjyf7WdqFn5Vq6mhzhtkXzj51aOcNuPNcTwuYNuXCpHsanZGHlHKL35G7huoFeVic1hng==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -7329,6 +7361,27 @@ "react": "^16.8.0 || ^17 || ^18" } }, + "node_modules/react-i18next": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.0.tgz", + "integrity": "sha512-3KwX6LHpbvGQ+sBEntjV4sYW3Zovjjl3fpoHbUwSgFHf0uRBcbeCBLR5al6ikncI5+W0EFb71QXZmfop+J6NrQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -8657,6 +8710,14 @@ "vite": "^2.6.0 || 3 || 4" } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -12654,6 +12715,14 @@ "react-is": "^16.7.0" } }, + "html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "requires": { + "void-elements": "3.1.0" + } + }, "http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", @@ -12687,6 +12756,14 @@ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, + "i18next": { + "version": "23.10.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.10.1.tgz", + "integrity": "sha512-NDiIzFbcs3O9PXpfhkjyf7WdqFn5Vq6mhzhtkXzj51aOcNuPNcTwuYNuXCpHsanZGHlHKL35G7huoFeVic1hng==", + "requires": { + "@babel/runtime": "^7.23.2" + } + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -13687,6 +13764,15 @@ "integrity": "sha512-BggOy5j58RdhdMzzRUHGOYhSz1oeylFAv6jUSG86OvCIvlAvS7KvnRY7yoAf2pfEiPN7BesnR0xx73nEk3qIiw==", "requires": {} }, + "react-i18next": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.0.tgz", + "integrity": "sha512-3KwX6LHpbvGQ+sBEntjV4sYW3Zovjjl3fpoHbUwSgFHf0uRBcbeCBLR5al6ikncI5+W0EFb71QXZmfop+J6NrQ==", + "requires": { + "@babel/runtime": "^7.23.9", + "html-parse-stringify": "^3.0.1" + } + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -14568,6 +14654,11 @@ "@svgr/plugin-jsx": "^7.0.0" } }, + "void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index ca0241f..32fa024 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,14 @@ "@reduxjs/toolkit": "^2.2.1", "@vitejs/plugin-react-swc": "^3.3.2", "axios": "^1.6.8", + "i18next": "^23.10.1", "modern-normalize": "^2.0.0", "normalize.css": "^8.0.1", "react": "^18.2.0", "react-datepicker": "^6.3.0", "react-dom": "^18.2.0", "react-hook-form": "^7.51.0", + "react-i18next": "^14.1.0", "react-redux": "^9.1.0", "react-responsive": "^9.0.2", "react-router-dom": "^6.15.0", diff --git a/src/components/DailyNorma/DailyEdit.styled.js b/src/components/DailyNorma/DailyEdit.styled.js index 9c69903..64986ce 100644 --- a/src/components/DailyNorma/DailyEdit.styled.js +++ b/src/components/DailyNorma/DailyEdit.styled.js @@ -5,12 +5,17 @@ export const DailyWrapper = styled.div` display: flex; flex-direction: column; align-items: center; - border: 1px solid #ecf2ff; + border-radius: 10px; padding-top: 8px; gap: 12px; width: 164px; height: 74px; + + background-color: ${(props) => props.theme.dailyWrapperBackground}; + border: ${(props) => props.theme.dailyWrapperBorder}; + box-shadow: ${(props) => props.theme.dailyWrapperBoxShadow}; + @media only screen and (min-width: 768px) { margin-bottom: -45px; } diff --git a/src/components/DailyNorma/WaterRatio.styled.js b/src/components/DailyNorma/WaterRatio.styled.js index c08b8cc..c4aebbe 100644 --- a/src/components/DailyNorma/WaterRatio.styled.js +++ b/src/components/DailyNorma/WaterRatio.styled.js @@ -75,7 +75,7 @@ export const Svg = styled.svg``; export const StyledRangeInput = styled.input` -webkit-appearance: none; - /* width: 256px; */ + width: 100%; height: 8px; border-radius: 10px; diff --git a/src/components/Header/DivSetting.jsx b/src/components/Header/DivSetting.jsx new file mode 100644 index 0000000..2f55476 --- /dev/null +++ b/src/components/Header/DivSetting.jsx @@ -0,0 +1,32 @@ +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; + +const DivSetting = () => { + const { t, i18n } = useTranslation(); + const [currentLanguage, setCurrentLanguage] = useState(i18n.language); + + useEffect(() => { + const language = localStorage.getItem('language'); + if (language && language !== currentLanguage) { + i18n.changeLanguage(language); + setCurrentLanguage(language); + } + }, [i18n, currentLanguage]); + + const handleChangeLanguage = (language) => { + i18n.changeLanguage(language); + setCurrentLanguage(language); + localStorage.setItem('language', language); + }; + + return ( +
+
+ + +
+
+ ); +}; + +export default DivSetting; diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index 2f281c3..4a67670 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -11,6 +11,7 @@ import { useSelector } from 'react-redux'; import { selectUser } from '../../store/auth/selectors'; import { HeaderUserName } from './HeaderModalStyled'; import { useEffect, useState } from 'react'; +import DivSetting from './DivSetting'; const Header = () => { const userProfile = useSelector(selectUser); @@ -36,7 +37,7 @@ const Header = () => { - + {userProfile ? ( <> diff --git a/src/components/Header/HeaderModalStyled.jsx b/src/components/Header/HeaderModalStyled.jsx index eca5744..0a5e328 100644 --- a/src/components/Header/HeaderModalStyled.jsx +++ b/src/components/Header/HeaderModalStyled.jsx @@ -269,7 +269,7 @@ export const HeaderUserName = styled.span` font-size: 18px; text-align: right; - color: #2f2f2f; + padding-right: 8px; `; diff --git a/src/components/Header/ThemeStyled/SwitchTheme/MoonIcon.jsx b/src/components/Header/ThemeStyled/SwitchTheme/MoonIcon.jsx new file mode 100644 index 0000000..23ef09f --- /dev/null +++ b/src/components/Header/ThemeStyled/SwitchTheme/MoonIcon.jsx @@ -0,0 +1,13 @@ +import { withTheme } from 'styled-components'; + +function MoonIcon(props) { + return ( + + + + ); +} +export default withTheme(MoonIcon); diff --git a/src/components/Header/ThemeStyled/SwitchTheme/SunIcon.jsx b/src/components/Header/ThemeStyled/SwitchTheme/SunIcon.jsx new file mode 100644 index 0000000..7fd003e --- /dev/null +++ b/src/components/Header/ThemeStyled/SwitchTheme/SunIcon.jsx @@ -0,0 +1,16 @@ +import { useTheme } from 'styled-components'; + +function SunIcon() { + const theme = useTheme(); + + return ( + + + + ); +} + +export default SunIcon; diff --git a/src/components/Header/ThemeStyled/SwitchTheme/Switch.css b/src/components/Header/ThemeStyled/SwitchTheme/Switch.css new file mode 100644 index 0000000..be3345d --- /dev/null +++ b/src/components/Header/ThemeStyled/SwitchTheme/Switch.css @@ -0,0 +1,39 @@ +.toggle-switch { + position: relative; + display: inline-block; + width: 50px; + height: 25px; + margin: 0 0.75rem; +} +.toggle-switch input[type='checkbox'] { + display: none; +} +.toggle-switch .switch { + position: absolute; + cursor: pointer; + background-color: #b6b6b6; + border-radius: 25px; + top: 0; + right: 0; + bottom: 0; + left: 0; + transition: background-color 0.2s ease; +} +.toggle-switch .switch::before { + position: absolute; + content: ''; + left: 2px; + top: 2px; + width: 21px; + height: 21px; + background-color: #333; + border-radius: 50%; + transition: transform 0.3s ease; +} +.toggle-switch input[type='checkbox']:checked + .switch::before { + transform: translateX(25px); + background-color: #333; +} +.toggle-switch input[type='checkbox']:checked + .switch { + background-color: #2bc6ff; +} diff --git a/src/components/Header/ThemeStyled/SwitchTheme/Switch.jsx b/src/components/Header/ThemeStyled/SwitchTheme/Switch.jsx new file mode 100644 index 0000000..5b2cb9a --- /dev/null +++ b/src/components/Header/ThemeStyled/SwitchTheme/Switch.jsx @@ -0,0 +1,26 @@ +import React, { useState } from 'react'; +import './Switch.css'; +import MoonIcon from './MoonIcon'; +import SunIcon from './SunIcon'; + +function Switch({ toggleTheme, isDarkTheme }) { + const [isToggled, setIsToggled] = useState(isDarkTheme); + + const onToggle = () => { + setIsToggled(!isToggled); + toggleTheme(); + }; + + return ( + <> + + + + + ); +} + +export default Switch; diff --git a/src/components/Header/ThemeStyled/Theme.styled.jsx b/src/components/Header/ThemeStyled/Theme.styled.jsx new file mode 100644 index 0000000..6ab49bd --- /dev/null +++ b/src/components/Header/ThemeStyled/Theme.styled.jsx @@ -0,0 +1,60 @@ +import styled, { createGlobalStyle } from 'styled-components'; + +export const StyledApp = styled.div` + min-height: 100vh; + body { + background-color: ${(props) => props.theme.body}; + color: ${(props) => props.theme.colorBody}; + } +`; + +export const GlobalStyles = createGlobalStyle` + body { + background-color: ${(props) => props.theme.body}; + color: ${(props) => props.theme.colorBody}; + } +`; + +export const ThemeStyledButton = styled.button``; + +export const darkTheme = { + body: '#1c1c1c', + + colorBody: '#d5dff5;', + test: '#ee1010', + icon: '#d5dff5', + iconHeader: '#D5DFF5', + buttonBackground: '#5082f2;', + buttonColor: '#1c1d26;', + welcomeWhyDrinkDivCantainerBackground: '#1f2438;', + BottleSVG: '#1B1B21;', + + formInputBackground: '#1c1d26;', + formInputColor: '#5082f2;', + formInputColorPlaceholder: '#2f3875;', + + dailyWrapperBorder: '1px solid #1f2438;', + dailyWrapperBackground: '#1c1d26;', + dailyWrapperBoxShadow: '0 4px 14px 0 rgba(0, 0, 0, 0.2);', +}; + +export const lightTheme = { + body: '#fff;', + + colorBody: '#2f2f2f', + test: '#ee1010', + icon: '#2f2f2f', + iconHeader: '#2F2F2F', + buttonBackground: '#407bff', + buttonColor: '#fff', + welcomeWhyDrinkDivCantainerBackground: '#ecf2ff;', + BottleSVG: '#F5F5F5;', + + formInputBackground: '#fff;', + formInputColor: '#407bff;', + formInputColorPlaceholder: '#9ebbff;', + + dailyWrapperBorder: '1px solid #ecf2ff', + dailyWrapperBackground: '#fff;', + dailyWrapperBoxShadow: '0 4px 8px 0 rgba(158, 187, 255, 0.12);', +}; diff --git a/src/components/Header/en.json b/src/components/Header/en.json new file mode 100644 index 0000000..ad1002b --- /dev/null +++ b/src/components/Header/en.json @@ -0,0 +1,5 @@ +{ + "lightTheme": "Light Theme", + "darkTheme": "Dark Theme", + "waterconsumptiontracker": "Water consumption tracker" +} \ No newline at end of file diff --git a/src/components/Header/i18n.js b/src/components/Header/i18n.js new file mode 100644 index 0000000..db32b77 --- /dev/null +++ b/src/components/Header/i18n.js @@ -0,0 +1,42 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import enTranslation from './en.json'; +import ukTranslation from './uk.json'; + +i18n.use(initReactI18next).init({ + resources: { + en: { + translation: enTranslation, + }, + uk: { + translation: ukTranslation, + }, + }, + lng: 'en', + fallbackLng: 'en', + interpolation: { + escapeValue: false, + }, +}); + +export default i18n; + +// import i18n from 'i18next'; +// import { initReactI18next } from 'react-i18next'; +// import Backend from 'i18next-xhr-backend'; + +// i18n +// .use(Backend) +// .use(initReactI18next) +// .init({ +// lng: 'en', +// fallbackLng: 'en', +// interpolation: { +// escapeValue: false, +// }, +// backend: { +// loadPath: 'http://localhost:5173/byte-my-water-app/', +// }, +// }); + +// export default i18n; diff --git a/src/components/Header/uk.json b/src/components/Header/uk.json new file mode 100644 index 0000000..ee4ba48 --- /dev/null +++ b/src/components/Header/uk.json @@ -0,0 +1,5 @@ +{ + "lightTheme": "Світла тема", + "darkTheme": "Темна тема", + "waterconsumptiontracker": "Трекер споживання води" +} \ No newline at end of file diff --git a/src/components/Layout/Layout.jsx b/src/components/Layout/Layout.jsx index c90a283..33f3b43 100644 --- a/src/components/Layout/Layout.jsx +++ b/src/components/Layout/Layout.jsx @@ -3,20 +3,62 @@ import Header from '../Header/Header.jsx'; import { Container, Main } from './Layout.styled.js'; import { BackgraundContainer } from './BackgraundContainer.styled.js'; +import { + GlobalStyles, + StyledApp, + darkTheme, + lightTheme, +} from '../Header/ThemeStyled/Theme.styled.jsx'; + +import { ThemeProvider } from 'styled-components'; +import { useEffect, useState } from 'react'; +import Switch from '../Header/ThemeStyled/SwitchTheme/Switch.jsx'; + const Layout = () => { + const storedTheme = localStorage.getItem('theme'); + const [theme, setTheme] = useState(storedTheme || 'light'); + const isDarkTheme = theme === 'dark'; + + const toggleTheme = () => { + const newTheme = isDarkTheme ? 'light' : 'dark'; + setTheme(newTheme); + localStorage.setItem('theme', newTheme); + }; + + useEffect(() => { + const handleStorageChange = () => { + const storedTheme = localStorage.getItem('theme'); + if (storedTheme && storedTheme !== theme) { + setTheme(storedTheme); + } + }; + + window.addEventListener('storage', handleStorageChange); + + return () => { + window.removeEventListener('storage', handleStorageChange); + }; + }, [theme]); + return ( <> - -
- -
- -
-
- - - -
+ + + + +
+ + {/* */} +
+ +
+
+ + + +
+ + ); }; diff --git a/src/components/LoginForm/LoginForm.styled.js b/src/components/LoginForm/LoginForm.styled.js index 646de3a..9788071 100644 --- a/src/components/LoginForm/LoginForm.styled.js +++ b/src/components/LoginForm/LoginForm.styled.js @@ -61,7 +61,8 @@ export const LoginInput = styled.input` border-radius: 6px; border: 1px solid var(--primary-mediumblue); outline: none; - color: var(--blue); + background-color: ${(props) => props.theme.formInputBackground}; + color: ${(props) => props.theme.formInputColor}; &::placeholder { color: var(--primary-blue); @@ -80,15 +81,16 @@ export const Loginlabel = styled.label` `; export const LoginBtn = styled.button` margin-bottom: 16px; - background-color: var(--blue); + border: 1px solid var(--blue); - color: var(--white); + padding: 8px 30px; border-radius: 10px; box-shadow: 0 4px 8px 0 rgba(64, 123, 255, 0.34); transition: all 0.4s; - + background: ${(props) => props.theme.buttonBackground}; + color: ${(props) => props.theme.buttonColor}; &:hover, &:focus { box-shadow: 0 4px 14px 0 rgba(64, 123, 255, 0.54); diff --git a/src/components/ModalAddWater/ModalAddWater.jsx b/src/components/ModalAddWater/ModalAddWater.jsx index 598ce2a..e5df73e 100644 --- a/src/components/ModalAddWater/ModalAddWater.jsx +++ b/src/components/ModalAddWater/ModalAddWater.jsx @@ -15,11 +15,11 @@ import DatePicker from 'react-datepicker'; import 'react-datepicker/dist/react-datepicker.css'; import useCounter from '../../hooks/modalHandleUpdate.js'; import { useDispatch } from 'react-redux'; -import { addWaterThunk } from '../../store/water/operations.js'; import { - changeModalClose, - changeTodayList, -} from '../../store/water/waterSlice.js'; + addWaterThunk, + fetchAllWaterThunk, +} from '../../store/water/operations.js'; +import { changeModalClose } from '../../store/water/waterSlice.js'; import { toast } from 'react-toastify'; const ModalAddWater = () => { @@ -42,7 +42,7 @@ const ModalAddWater = () => { .unwrap() .then(() => { dispatch(changeModalClose(false)); - dispatch(changeTodayList({ ...water, _id: crypto.randomUUID() })); + dispatch(fetchAllWaterThunk()); toast.success('Water note was successfully added'); }) .catch((error) => { diff --git a/src/components/ModalAddWater/ModalAddWater.styled.js b/src/components/ModalAddWater/ModalAddWater.styled.js index 926e2c4..6476113 100644 --- a/src/components/ModalAddWater/ModalAddWater.styled.js +++ b/src/components/ModalAddWater/ModalAddWater.styled.js @@ -141,7 +141,8 @@ export const StyledModalAddInput = styled.input` border-radius: 6px; border: 1px solid var(--primary-mediumblue); padding: 12px 10px 12px 10px; - color: var(--blue); + background-color: ${(props) => props.theme.formInputBackground}; + color: ${(props) => props.theme.formInputColor}; &::placeholder { color: var(--blue); font-size: 16px; @@ -220,7 +221,8 @@ export const ModalAddDateWrap = styled.div` border-radius: 6px; border: 1px solid var(--primary-mediumblue); padding: 12px 10px 12px 10px; - color: var(--blue); + background-color: ${(props) => props.theme.formInputBackground}; + color: ${(props) => props.theme.formInputColor}; &::placeholder { color: var(--blue); font-size: 16px; diff --git a/src/components/ModalDailyNorma/ModalDailyNorma.styled.js b/src/components/ModalDailyNorma/ModalDailyNorma.styled.js index fda52f4..029ff83 100644 --- a/src/components/ModalDailyNorma/ModalDailyNorma.styled.js +++ b/src/components/ModalDailyNorma/ModalDailyNorma.styled.js @@ -149,7 +149,8 @@ export const StyledInputBox = styled.div` width: 100%; border-radius: 6px; border: 1px solid var(--primary-mediumblue); - color: var(--blue); + background-color: ${(props) => props.theme.formInputBackground}; + color: ${(props) => props.theme.formInputColor}; padding: 12px 10px 12px 10px; margin-top: 8px; margin-bottom: 16px; diff --git a/src/components/ModalDeleteWater/ModalDeleteWater.jsx b/src/components/ModalDeleteWater/ModalDeleteWater.jsx index a200cfb..7ce5557 100644 --- a/src/components/ModalDeleteWater/ModalDeleteWater.jsx +++ b/src/components/ModalDeleteWater/ModalDeleteWater.jsx @@ -20,7 +20,6 @@ import { toast } from 'react-toastify'; const ModalDeleteWater = () => { const isModalOpen = useSelector(modalDeleteOpen); const id = useSelector(modalId); - const dispatch = useDispatch(); const onSubmit = (e) => { diff --git a/src/components/ModalEditWater/ModalEditWater.styled.js b/src/components/ModalEditWater/ModalEditWater.styled.js index ca3cf54..da67812 100644 --- a/src/components/ModalEditWater/ModalEditWater.styled.js +++ b/src/components/ModalEditWater/ModalEditWater.styled.js @@ -33,7 +33,8 @@ export const StyledModalEditInput = styled.input` border-radius: 6px; border: 1px solid var(--primary-mediumblue); padding: 12px 10px 12px 10px; - color: var(--blue); + background-color: ${(props) => props.theme.formInputBackground}; + color: ${(props) => props.theme.formInputColor}; &::placeholder { color: var(--blue); font-size: 16px; @@ -64,7 +65,8 @@ export const ModalEditDateWrap = styled.div` border-radius: 6px; border: 1px solid var(--primary-mediumblue); padding: 12px 10px 12px 10px; - color: var(--blue); + background-color: ${(props) => props.theme.formInputBackground}; + color: ${(props) => props.theme.formInputColor}; &::placeholder { color: var(--blue); font-size: 16px; diff --git a/src/components/SettingModal/SettingModal.styled.js b/src/components/SettingModal/SettingModal.styled.js index cd65437..3b99472 100644 --- a/src/components/SettingModal/SettingModal.styled.js +++ b/src/components/SettingModal/SettingModal.styled.js @@ -215,6 +215,8 @@ export const InputFild = styled.input` font-family: 'Roboto', sans-serif; color: var(--blue); caret-color: var(--black); + background-color: ${(props) => props.theme.formInputBackground}; + color: ${(props) => props.theme.formInputColor}; outline: none; &::placeholder { font-size: 16px; @@ -286,13 +288,14 @@ export const SaveButton = styled.button` max-width: 392px; height: 36px; box-shadow: 0 4px 8px 0 rgba(64, 123, 255, 0.34); - background: #407bff; + font-size: 16px; font-weight: 500; line-height: 1.25; font-family: 'Roboto', sans-serif; text-align: center; - color: var(--white); + background: ${(props) => props.theme.buttonBackground}; + color: ${(props) => props.theme.buttonColor}; @media only screen and (min-width: 768px) { font-size: 18px; diff --git a/src/components/TodayElement/TodayElement.jsx b/src/components/TodayElement/TodayElement.jsx index f81b120..0297e39 100644 --- a/src/components/TodayElement/TodayElement.jsx +++ b/src/components/TodayElement/TodayElement.jsx @@ -1,4 +1,3 @@ -// import { useState } from 'react'; import { AddBtnWrapper, Amount, @@ -26,22 +25,16 @@ import { import ModalDeleteWater from '../ModalDeleteWater/ModalDeleteWater.jsx'; import { useEffect } from 'react'; import { fetchAllWaterThunk } from '../../store/water/operations.js'; -import { selectUser } from '../../store/auth/selectors.js'; import { format } from 'date-fns'; const TodayElement = () => { const isModalOpen = useSelector(modalDeleteOpen); - const isUser = useSelector(selectUser); - const waterTodayList = useSelector(selectorWaterToday); - const dispatch = useDispatch(); useEffect(() => { - if (isUser) { - dispatch(fetchAllWaterThunk()); - } - }, [dispatch, isUser]); + dispatch(fetchAllWaterThunk()); + }, [dispatch]); return ( <> @@ -67,6 +60,7 @@ const TodayElement = () => {
{ + dispatch(changeModalId(item._id)); dispatch(changeModalDeleteForm(true)); dispatch(changeModalId(item._id)); }} diff --git a/src/components/Welcome/Welcome.jsx b/src/components/Welcome/Welcome.jsx index 5d697d7..7ba05b3 100644 --- a/src/components/Welcome/Welcome.jsx +++ b/src/components/Welcome/Welcome.jsx @@ -1,3 +1,4 @@ +import { useTranslation } from 'react-i18next'; import DesctopWoter from '../../images/backgroundImg/backgraundSvg/DesctopWoter'; import TabletWoter from '../../images/backgroundImg/backgraundSvg/TabletWoter'; import SvgHabit from '../../images/svg/svgWelcome/SvgHabit'; @@ -23,9 +24,11 @@ import { } from './Welcome.styled'; const Welcome = () => { + const { t } = useTranslation(); + return ( <> - + {/* */} @@ -35,7 +38,7 @@ const Welcome = () => {
- Water consumption tracker + {t('waterconsumptiontracker')} Record daily water intake and track Tracker Benefits diff --git a/src/components/Welcome/Welcome.styled.js b/src/components/Welcome/Welcome.styled.js index 6477317..181e507 100644 --- a/src/components/Welcome/Welcome.styled.js +++ b/src/components/Welcome/Welcome.styled.js @@ -151,7 +151,7 @@ export const WelcomeWhyDrinkDivCantainer = styled.div` padding: 32px 24px; box-shadow: 0 4px 14px 0 rgba(64, 123, 255, 0.3); - background: #ecf2ff; + background: ${(props) => props.theme.welcomeWhyDrinkDivCantainerBackground}; max-width: 380px; margin-bottom: 20px; @media only screen and (min-width: 768px) { @@ -171,13 +171,15 @@ export const WelcomeNavLink = styled(NavLink)` width: 100%; box-shadow: 0 4px 8px 0 rgba(64, 123, 255, 0.34); - background: #407bff; font-weight: 500; font-size: 16px; text-align: center; - color: #fff; + + background: ${(props) => props.theme.buttonBackground}; + color: ${(props) => props.theme.buttonColor}; + border: none; @media only screen and (min-width: 768px) { max-width: 336px; diff --git a/src/images/AuthImg/BottleSVG.jsx b/src/images/AuthImg/BottleSVG.jsx index 1bfddb3..391cc2e 100644 --- a/src/images/AuthImg/BottleSVG.jsx +++ b/src/images/AuthImg/BottleSVG.jsx @@ -1,85 +1,92 @@ import * as React from 'react'; -const BottleSVG = (props) => ( - - - - - - - - - - - - - - - - - -); +import { useTheme } from 'styled-components'; + +const BottleSVG = (props) => { + const theme = useTheme(); + + return ( + + + + + + + + + + + + + + + + + + ); +}; + export default BottleSVG; diff --git a/src/images/AuthImg/BottleSVGDesktop.jsx b/src/images/AuthImg/BottleSVGDesktop.jsx index 44ae6eb..65e7354 100644 --- a/src/images/AuthImg/BottleSVGDesktop.jsx +++ b/src/images/AuthImg/BottleSVGDesktop.jsx @@ -1,90 +1,95 @@ -const BottleSVGDesktop = (props) => ( - - - - - - - - - - - - - - - - +import { useTheme } from 'styled-components'; - - - - - - -); +const BottleSVGDesktop = (props) => { + const theme = useTheme(); + return ( + + + + + + + + + + + + + + + + + + + + + + + + ); +}; export default BottleSVGDesktop; diff --git a/src/images/AuthImg/BottleSVGTablet.jsx b/src/images/AuthImg/BottleSVGTablet.jsx index edfc330..c163e40 100644 --- a/src/images/AuthImg/BottleSVGTablet.jsx +++ b/src/images/AuthImg/BottleSVGTablet.jsx @@ -1,91 +1,95 @@ import * as React from 'react'; -const BottleSVGTablet = (props) => ( - - - - - - - - - - - - - - - - +import { useTheme } from 'styled-components'; +const BottleSVGTablet = (props) => { + const theme = useTheme(); + return ( + + + + + + + + + + + + + + + + - - - - - - -); + + + + + + + ); +}; export default BottleSVGTablet; diff --git a/src/images/backgroundImg/backgraundSvg/DesctopWoter.jsx b/src/images/backgroundImg/backgraundSvg/DesctopWoter.jsx index 8a0db4d..4e53d01 100644 --- a/src/images/backgroundImg/backgraundSvg/DesctopWoter.jsx +++ b/src/images/backgroundImg/backgraundSvg/DesctopWoter.jsx @@ -1,90 +1,94 @@ -const DesctopWoter = (props) => ( - - - - - - - - - - - - - - - - +import { useTheme } from 'styled-components'; +const DesctopWoter = (props) => { + const theme = useTheme(); + return ( + + + + + + + + + + + + + + + + - - - - - - -); + + + + + + + ); +}; export default DesctopWoter; diff --git a/src/images/backgroundImg/backgraundSvg/TabletWoter.jsx b/src/images/backgroundImg/backgraundSvg/TabletWoter.jsx index 0f81b8d..472b358 100644 --- a/src/images/backgroundImg/backgraundSvg/TabletWoter.jsx +++ b/src/images/backgroundImg/backgraundSvg/TabletWoter.jsx @@ -1,84 +1,90 @@ -const TabletWoter = (props) => ( - - - - - - - - - - - - - - - - - -); +import * as React from 'react'; +import { useTheme } from 'styled-components'; + +const TabletWoter = (props) => { + const theme = useTheme(); + return ( + + + + + + + + + + + + + + + + + + ); +}; export default TabletWoter; diff --git a/src/images/svg/svgDailyNorma/BottleDesctop.jsx b/src/images/svg/svgDailyNorma/BottleDesctop.jsx index 2ea77b6..87ef8ff 100644 --- a/src/images/svg/svgDailyNorma/BottleDesctop.jsx +++ b/src/images/svg/svgDailyNorma/BottleDesctop.jsx @@ -1,6 +1,7 @@ import React from 'react'; - +import { useTheme } from 'styled-components'; function BottleDesctop() { + const theme = useTheme(); return ( ( - - - - - - - - - - - -); +import { useTheme } from 'styled-components'; + +const HeaderSVGPhoto = (props) => { + const theme = useTheme(); + + return ( + + + + + + + + + + + + ); +}; + export default HeaderSVGPhoto; +// 2F2F2F diff --git a/src/main.jsx b/src/main.jsx index e7fcf25..202f207 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,19 +1,22 @@ -import { BrowserRouter } from 'react-router-dom'; import ReactDOM from 'react-dom/client'; +import { BrowserRouter } from 'react-router-dom'; import App from './components/App/App.jsx'; import './index.css'; import { Provider } from 'react-redux'; import { persistor, store } from './store/store.js'; import { PersistGate } from 'redux-persist/integration/react'; - +import i18n from './components/Header/i18n.js'; import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; +import { I18nextProvider } from 'react-i18next'; ReactDOM.createRoot(document.getElementById('root')).render( - + + + diff --git a/src/store/water/selectors.js b/src/store/water/selectors.js index a25ab38..0d69d9f 100644 --- a/src/store/water/selectors.js +++ b/src/store/water/selectors.js @@ -5,7 +5,6 @@ export const modalIsAdd = (state) => state.waterSlice.modal?.modalAddForm; export const modalIsEdit = (state) => state.waterSlice.modal?.modalEditForm; export const isModalDayNorm = (state) => state.waterSlice.modal?.isModalDayNorm; export const modalDayNorma = (state) => state.waterSlice.modal?.modalDayNorma; -// export const modalIsDelete = (state) => state.waterSlice.modal?.modalDeleteForm; export const modalId = (state) => state.waterSlice.modal?.modalId; export const showDaysGenStats = (state) => state.waterSlice.daysGenStats; diff --git a/src/store/water/waterSlice.js b/src/store/water/waterSlice.js index 54f8160..b0affac 100644 --- a/src/store/water/waterSlice.js +++ b/src/store/water/waterSlice.js @@ -11,7 +11,6 @@ const waterSlice = createSlice({ modalEditForm: false, isModalDayNorm: false, modalDayNorma: false, - modalDeleteForm: false, modalId: '', }, daysGenStats: false, @@ -25,7 +24,6 @@ const waterSlice = createSlice({ state.modal.modalEditForm = payload; state.modal.isModalDayNorm = payload; state.modal.modalDayNorma = payload; - state.modal.modalDeleteForm = payload; state.modal.modalDeleteOpen = payload; }, changeModalAddForm: (state, { payload }) => { @@ -38,7 +36,6 @@ const waterSlice = createSlice({ }, changeModalDeleteForm: (state, { payload }) => { state.modal.modalDeleteOpen = payload; - state.modal.modalDeleteForm = payload; }, changeModalDailyNorma: (state, { payload }) => { state.modal.isModalDayNorm = payload; @@ -70,7 +67,7 @@ const waterSlice = createSlice({ extraReducers: (builder) => { builder .addCase(fetchAllWaterThunk.fulfilled, (state, { payload }) => { - state.waterTodayList.push(...payload); + state.waterTodayList = payload; }) .addCase(fetchAllWaterThunk.rejected, (state, { payload }) => { state.error = payload;