diff --git a/.gitignore b/.gitignore
index 1437c53..f549c3e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,5 @@ yarn-error.log*
# vercel
.vercel
+
+.vscode/
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..c43b71d
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,4 @@
+.next/
+node_modules/
+.vscode/
+.github/
\ No newline at end of file
diff --git a/README.md b/README.md
index 6a493d9..05f2182 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,3 @@
# ugra-hackathon_frontend
+
+Training project to get another members of team used to code style
diff --git a/components/ExampleComponent.jsx b/components/ExampleComponent.jsx
new file mode 100644
index 0000000..ccd8082
--- /dev/null
+++ b/components/ExampleComponent.jsx
@@ -0,0 +1,9 @@
+import React from "react";
+
+import styles from "styles/exampleComponent.module.css";
+
+const ExampleComponent = () => {
+ return ;
+};
+
+export default ExampleComponent;
diff --git a/components/PowerfulComponent/handlers.js b/components/PowerfulComponent/handlers.js
new file mode 100644
index 0000000..537bdc0
--- /dev/null
+++ b/components/PowerfulComponent/handlers.js
@@ -0,0 +1,11 @@
+// Лучше писать документацию на функции, за это будет респект от менторов
+/**
+ * Increase counter
+ * @param {SetStateAction} setCounter
+ */
+const handleCounterClick = (setCounter) => {
+ return () => setCounter((prev) => prev + 1); // Если используем контекст, тогда замыкаем всё, что нужно внутри обработчика
+};
+
+// Экспорт лучше делать отдельно, чтобы всегда знать, что мы экспортируем из файла, а что используем внутри (как с public/private методами)
+export { handleCounterClick };
diff --git a/components/PowerfulComponent/index.js b/components/PowerfulComponent/index.js
new file mode 100644
index 0000000..0fb9493
--- /dev/null
+++ b/components/PowerfulComponent/index.js
@@ -0,0 +1,26 @@
+import React, { useCallback, useContext } from "react";
+
+import { CounterContext } from "context/counterContext";
+import { handleCounterClick } from "./handlers"; // Обработчики событий лучше держать в отдельном файле или использовать кастомные хуки
+
+/**
+ * Complex component with counter with context in it
+ */
+const PowerfulComponent = () => {
+ const context = useContext(CounterContext);
+
+ console.log(context);
+
+ const handleClick = useCallback(handleCounterClick(context.setCounter), [
+ context.setCounter,
+ ]);
+
+ return (
+
+
{context?.counter}
+
+
+ );
+};
+
+export default PowerfulComponent;
diff --git a/context/counterContext.js b/context/counterContext.js
new file mode 100644
index 0000000..dec904e
--- /dev/null
+++ b/context/counterContext.js
@@ -0,0 +1,22 @@
+import React, { useEffect, useMemo, useState } from "react";
+
+const CounterContext = React.createContext(null);
+
+const initialContext = 0;
+
+const CounterProvider = ({ children }) => {
+ const [counter, setCounter] = useState(null);
+
+ useEffect(() => {
+ // Тут что-то делать для инициализации контекста
+ setCounter(initialContext); // Например
+ }, []);
+
+ const value = useMemo(() => ({ counter, setCounter }), [counter]); // На самом деле, в случе нашего проекта это мало повлияет на производительность, но в каком-то туториале советовали так делать, поэтому почему бы и нет
+
+ return (
+ {children}
+ );
+};
+
+export { CounterContext, CounterProvider };
diff --git a/hooks/counter.js b/hooks/counter.js
new file mode 100644
index 0000000..278c5d9
--- /dev/null
+++ b/hooks/counter.js
@@ -0,0 +1,21 @@
+import { useState } from "react";
+
+// Если функционал можно где-то переиспользовать или если код логики компонента занимает больше 150 строк, стоит разбить его на кастомные хуки и вынести сюда
+/**
+ * Simple counter hook
+ * @param {number} initialState
+ */
+const useCounter = (initialState = 0) => {
+ if (typeof initialState !== "number")
+ throw new Error("Initial counter state must be a number");
+
+ const [counter, setCounter] = useState(initialState);
+
+ const increaseCounter = () => {
+ setCounter((prev) => prev + 1);
+ };
+
+ return { counter, increaseCounter };
+};
+
+export { useCounter }
\ No newline at end of file
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000..499ef8b
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,8 @@
+{
+ "compilerOptions": {
+ "module": "esnext",
+ "target": "es5",
+ "baseUrl": "."
+ },
+ "exclude": ["node_modules", ".next"]
+}
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 2fc3e07..b88a9af 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -1,7 +1,15 @@
-import "../styles/globals.css";
+import React from 'react'
+
+import "styles/globals.css";
+import { CounterProvider } from "context/counterContext";
function MyApp({ Component, pageProps }) {
- return ;
+ return (
+ // Здесь компонент Component оборачиваем провайдеры глобального контекста. Если контекст используется не во всём приложении, а в каком-то определённом компоненте и его дочерних элементах, стоит занести провайдер туда
+
+
+
+ );
}
export default MyApp;
diff --git a/pages/counter.tsx b/pages/counter.tsx
new file mode 100644
index 0000000..4f3c30a
--- /dev/null
+++ b/pages/counter.tsx
@@ -0,0 +1,15 @@
+import React from "react";
+import { useCounter } from "hooks/counter";
+
+const Counter = () => {
+ const { counter, increaseCounter } = useCounter();
+
+ return (
+
+
{counter}
+
+
+ );
+};
+
+export default Counter
\ No newline at end of file
diff --git a/pages/index.tsx b/pages/index.tsx
index 6ff5373..2d122a4 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -1,3 +1,17 @@
+import React from "react";
+import Link from "next/link";
+
+import ExampleComponent from "components/ExampleComponent";
+import PowerfulComponent from "components/PowerfulComponent";
+
export default function Home() {
- return <>>;
+ return (
+ <>
+
+
+
+ Simplifyed counter
+
+ >
+ );
}
diff --git a/styles/exampleComponent.module.css b/styles/exampleComponent.module.css
new file mode 100644
index 0000000..01bc332
--- /dev/null
+++ b/styles/exampleComponent.module.css
@@ -0,0 +1,6 @@
+/* Благодаря использованию css-modules можно использовать одни и те же названия классов
+ в разных компонентах и ничего нам за это не будет, ибо при сборке к ним добавятся хеши */
+.button {
+ background-color: red;
+ color: white;
+}
diff --git a/tsconfig.json b/tsconfig.json
index 93a83a4..1ceb1ea 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -12,7 +12,8 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
- "jsx": "preserve"
+ "jsx": "preserve",
+ "baseUrl": "."
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]