Skip to content

Commit 7554134

Browse files
author
Дмитрий Никифоров
committed
feat: added 40 point task
1 parent 9229eab commit 7554134

File tree

10 files changed

+750
-174
lines changed

10 files changed

+750
-174
lines changed

.env

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
API=http://localhost:3000

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"@vkontakte/vk-bridge": "^2.0.2"
2525
},
2626
"scripts": {
27-
"start": "react-scripts start",
27+
"start": "PORT=3005 react-scripts start",
2828
"build": "react-scripts build",
2929
"test": "react-scripts test",
3030
"eject": "react-scripts eject"

src/assets/styles/main.css

+460
Large diffs are not rendered by default.

src/components/app/App.tsx

+34-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,41 @@
1-
import { View, Panel } from '@vkontakte/vkui';
1+
import { View, Panel, AdaptivityProvider, AppRoot, ConfigProvider } from '@vkontakte/vkui';
2+
import { useEffect } from 'react';
3+
import { useAppSelector } from '../../hooks/use-store';
4+
import { NotDefaultTheme } from '../../store/reducers/settingsSlice';
25
import Inbox from '../inbox/Inbox';
36

47
const App = () => {
8+
const settings = useAppSelector((state) => state.settings);
9+
10+
useEffect(() => {
11+
if (settings.notDefaultTheme) {
12+
document.body.classList.remove('vkui--vkBase--dark');
13+
if (settings.notDefaultTheme === NotDefaultTheme.MONOCHROME) {
14+
document.body.classList.remove('vkui--vkBase--light');
15+
}
16+
document.body.classList.remove('vkui--vkBase--monochrome');
17+
document.body.classList.remove('vkui--vkBase--dog');
18+
document.body.classList.remove('vkui--vkBase--cat');
19+
document.body.classList.add(`vkui--vkBase--${settings.notDefaultTheme}`);
20+
} else {
21+
document.body.classList.remove('vkui--vkBase--monochrome');
22+
document.body.classList.remove('vkui--vkBase--dog');
23+
document.body.classList.remove('vkui--vkBase--cat');
24+
}
25+
}, [settings]);
26+
527
return (
6-
<View activePanel="inbox">
7-
<Panel id="inbox">
8-
<Inbox />
9-
</Panel>
10-
</View>
28+
<ConfigProvider appearance={settings.theme}>
29+
<AdaptivityProvider>
30+
<AppRoot>
31+
<View activePanel="inbox">
32+
<Panel id="inbox">
33+
<Inbox />
34+
</Panel>
35+
</View>
36+
</AppRoot>
37+
</AdaptivityProvider>
38+
</ConfigProvider>
1139
);
1240
};
1341

src/components/inbox/Inbox.tsx

+190-151
Large diffs are not rendered by default.

src/components/menu/menu.tsx

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
1+
import { Dispatch, SetStateAction } from 'react';
12
import {
23
Icon20MailOutline,
34
Icon20BookmarkOutline,
45
Icon20ExclamationMarkOutline,
56
Icon20RoubleOutline,
6-
Icon20KeyOutline
7+
Icon20KeyOutline,
8+
Icon20FilterOutline
79
} from '@vkontakte/icons';
810
import { Panel, PanelHeader, Group, List, Cell, Caption } from '@vkontakte/vkui';
911

1012
import styles from './menu.module.css';
1113

12-
const Menu = ({ activeCategory, getMails }: { activeCategory: string; getMails: (category: string) => void }) => {
14+
const Menu = ({
15+
activeCategory,
16+
getMails,
17+
setModal
18+
}: {
19+
activeCategory: string;
20+
getMails: (category: string) => void;
21+
setModal: Dispatch<SetStateAction<string>>;
22+
}) => {
1323
return (
1424
<Panel>
1525
<PanelHeader separator={false} />
@@ -95,6 +105,14 @@ const Menu = ({ activeCategory, getMails }: { activeCategory: string; getMails:
95105
>
96106
<Caption level="1">Доверенный</Caption>
97107
</Cell>
108+
<Cell
109+
className={styles.cell}
110+
expandable
111+
before={<Icon20FilterOutline />}
112+
onClick={() => setModal('settings')}
113+
>
114+
<Caption level="1">Настройки</Caption>
115+
</Cell>
98116
</List>
99117
</Group>
100118
</Panel>

src/index.tsx

+1-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import ReactDOM from 'react-dom/client';
22
import { Provider } from 'react-redux';
3-
import { AdaptivityProvider, ConfigProvider, AppRoot } from '@vkontakte/vkui';
43
import '@vkontakte/vkui/dist/vkui.css';
54
import './assets/styles/main.css';
65
import '@vkontakte/vkui/dist/unstable.css';
@@ -13,13 +12,7 @@ const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
1312

1413
root.render(
1514
<Provider store={store}>
16-
<ConfigProvider>
17-
<AdaptivityProvider>
18-
<AppRoot>
19-
<App />
20-
</AppRoot>
21-
</AdaptivityProvider>
22-
</ConfigProvider>
15+
<App />
2316
</Provider>
2417
);
2518

src/store/index.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
import { configureStore, combineReducers } from "@reduxjs/toolkit";
1+
import { configureStore, combineReducers } from '@reduxjs/toolkit';
22

3-
import { mailsApi } from "./services/mails";
4-
import mailsSlice from "./reducers/mailsSlice";
3+
import { mailsApi } from './services/mails';
4+
import mailsSlice from './reducers/mailsSlice';
5+
import settingsSlice from './reducers/settingsSlice';
56

67
const rootReducer = combineReducers({
78
[mailsApi.reducerPath]: mailsApi.reducer,
89
mails: mailsSlice,
10+
settings: settingsSlice
911
});
1012

1113
export const store = configureStore({
1214
reducer: rootReducer,
13-
middleware: (getDefaultMiddleware) =>
14-
getDefaultMiddleware().concat(mailsApi.middleware),
15+
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(mailsApi.middleware)
1516
});
1617

1718
export type RootState = ReturnType<typeof store.getState>;

src/store/reducers/settingsSlice.ts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2+
import { Appearance } from '@vkontakte/vkui';
3+
4+
export enum NotDefaultTheme {
5+
MONOCHROME = 'monochrome',
6+
CAT = 'cat',
7+
DOG = 'dog',
8+
}
9+
10+
const initialState: { theme: Appearance; notDefaultTheme: NotDefaultTheme | undefined } = {
11+
theme: Appearance.LIGHT,
12+
notDefaultTheme: undefined
13+
};
14+
15+
export const settingsSlice = createSlice({
16+
name: 'settings',
17+
initialState,
18+
reducers: {
19+
setTheme(state, action: PayloadAction<Appearance | NotDefaultTheme>) {
20+
if (Object.values(Appearance).includes(action.payload as Appearance)) {
21+
state.theme = action.payload as Appearance;
22+
state.notDefaultTheme = initialState.notDefaultTheme;
23+
} else {
24+
state.theme = Appearance.LIGHT;
25+
state.notDefaultTheme = action.payload as NotDefaultTheme;
26+
}
27+
},
28+
resetNotDefaultTheme(state) {
29+
state.notDefaultTheme = initialState.notDefaultTheme;
30+
}
31+
}
32+
});
33+
34+
export const { setTheme, resetNotDefaultTheme } = settingsSlice.actions;
35+
36+
export default settingsSlice.reducer;

src/store/services/mails.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { mail } from '../../interface/mail';
44
export const mailsApi = createApi({
55
reducerPath: 'mailsApi',
66
baseQuery: fetchBaseQuery({
7-
baseUrl: 'http://localhost:3000'
7+
baseUrl: process.env.API || 'http://localhost:3000'
88
}),
99
endpoints: (build) => ({
1010
fetchMails: build.query<mail.Mail[], string>({

0 commit comments

Comments
 (0)