Moved frontend to separate folder, added basic user context and user page
This commit is contained in:
20
front/components/User/RouteCard.tsx
Normal file
20
front/components/User/RouteCard.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import React from "react";
|
||||
|
||||
import { IRouteCard } from "types/user";
|
||||
import { formatTimeLength } from "utils";
|
||||
|
||||
const RouteCard: React.FC<IRouteCard> = ({ route }) => {
|
||||
return (
|
||||
<div>
|
||||
<h2>{route.name}</h2>
|
||||
<p>
|
||||
Данный квесты вы сможете пройти за {formatTimeLength(route.averageTime)}
|
||||
</p>
|
||||
<p>Длинна маршрута: {route.length} м</p>
|
||||
<p>Примерное время прохождения: {route.averageTime}</p>
|
||||
<p>Точка старта:</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RouteCard;
|
16
front/components/User/RouteView.tsx
Normal file
16
front/components/User/RouteView.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from "react";
|
||||
import { IRouteView } from "types/user";
|
||||
import RouteCard from "./RouteCard";
|
||||
|
||||
const RouteView: React.FC<IRouteView> = ({ header, routes }) => {
|
||||
return (
|
||||
<>
|
||||
<h1>{header}</h1>
|
||||
{routes.map((route) => (
|
||||
<RouteCard key={route.id} route={route} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default RouteView;
|
28
front/components/User/header.tsx
Normal file
28
front/components/User/header.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
import { IHeaderProps } from "types/user";
|
||||
|
||||
const Header: React.FC<IHeaderProps> = ({ points }) => {
|
||||
return (
|
||||
<header>
|
||||
<div>Очки: {points}</div>
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<Link href="/profile">
|
||||
<a>Профиль</a>
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/achivements">
|
||||
<a>Ачивки</a>
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
26
front/context/user/index.tsx
Normal file
26
front/context/user/index.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React, { useMemo, useState } from "react";
|
||||
|
||||
import { UserContextT, UserT } from "types/userContext";
|
||||
|
||||
const UserContext = React.createContext<UserContextT>(null);
|
||||
|
||||
const initialContext: UserT = {
|
||||
username: "",
|
||||
email: "",
|
||||
points: 0,
|
||||
id: 0,
|
||||
};
|
||||
|
||||
const UserProvider: React.FC = ({ children }) => {
|
||||
const [state, setState] = useState<UserT>(initialContext);
|
||||
|
||||
const value = useMemo(() => ({ userState: state, setUserState: setState }), [
|
||||
state,
|
||||
]);
|
||||
|
||||
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
|
||||
};
|
||||
|
||||
export { UserProvider, UserContext };
|
||||
|
||||
export type { UserT, UserContextT } from "../../types/userContext";
|
8
front/jsconfig.json
Normal file
8
front/jsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"baseUrl": "."
|
||||
},
|
||||
"exclude": ["node_modules", ".next"]
|
||||
}
|
7
front/layouts/EmptyLayout.tsx
Normal file
7
front/layouts/EmptyLayout.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
const EmptyLayout: React.FC = ({ children }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default EmptyLayout;
|
14
front/layouts/MainLayout.tsx
Normal file
14
front/layouts/MainLayout.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import React from "react";
|
||||
|
||||
import styles from "styles/layout.module.css";
|
||||
import { UserProvider } from "context/user";
|
||||
|
||||
const Layout: React.FC = ({ children }) => {
|
||||
return (
|
||||
<UserProvider>
|
||||
<div className={styles.content}>{children}</div>
|
||||
</UserProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Layout;
|
16
front/layouts/UserLayout.tsx
Normal file
16
front/layouts/UserLayout.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React, { useContext } from "react";
|
||||
|
||||
import Header from "components/User/header";
|
||||
import { UserContext } from "context/user";
|
||||
|
||||
const UserLayout: React.FC = ({ children }) => {
|
||||
const { userState } = useContext(UserContext);
|
||||
return (
|
||||
<>
|
||||
<Header points={userState.points} />
|
||||
<main>{children}</main>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserLayout;
|
2
front/next-env.d.ts
vendored
Normal file
2
front/next-env.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
23
front/package.json
Normal file
23
front/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "ugra-hackathon_frontend",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"format": "prettier --write \"**/*.+(js|jsx|json|css|md)\""
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "10.0.3",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-yandex-maps": "^4.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^14.14.10",
|
||||
"@types/react": "^17.0.0",
|
||||
"prettier": "^2.2.0",
|
||||
"typescript": "^4.1.2"
|
||||
}
|
||||
}
|
18
front/pages/_app.tsx
Normal file
18
front/pages/_app.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
|
||||
import "styles/globals.css";
|
||||
import Layout from "layouts/MainLayout";
|
||||
import EmptyLayout from "layouts/EmptyLayout";
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
const ComponentLayout = Component.Layout || EmptyLayout;
|
||||
return (
|
||||
<Layout>
|
||||
<ComponentLayout>
|
||||
<Component {...pageProps} />
|
||||
</ComponentLayout>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export default MyApp;
|
39
front/pages/routes/[id].tsx
Normal file
39
front/pages/routes/[id].tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import React from "react";
|
||||
import { YMaps, Map, Placemark } from "react-yandex-maps";
|
||||
import { RouteT } from "types/main";
|
||||
|
||||
const route: RouteT = {
|
||||
id: 0,
|
||||
length: 10,
|
||||
name: "Тест",
|
||||
averageTime: 10,
|
||||
startCoordinates: {
|
||||
latitude: 10,
|
||||
longitude: 10,
|
||||
},
|
||||
};
|
||||
|
||||
const Route: React.FC = () => {
|
||||
return (
|
||||
<YMaps>
|
||||
<Map
|
||||
defaultState={{
|
||||
center: [
|
||||
route.startCoordinates.latitude,
|
||||
route.startCoordinates.longitude,
|
||||
],
|
||||
zoom: 14,
|
||||
}}
|
||||
>
|
||||
<Placemark
|
||||
geometry={[
|
||||
route.startCoordinates.latitude,
|
||||
route.startCoordinates.longitude,
|
||||
]}
|
||||
/>
|
||||
</Map>
|
||||
</YMaps>
|
||||
);
|
||||
};
|
||||
|
||||
export default Route;
|
31
front/pages/user.tsx
Normal file
31
front/pages/user.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import UserLayout from "layouts/UserLayout";
|
||||
import { UserContext } from "context/user";
|
||||
import React, { useContext } from "react";
|
||||
import RouteView from "components/User/RouteView";
|
||||
import { RouteT } from "types/main";
|
||||
|
||||
const routes: RouteT[] = [
|
||||
{
|
||||
id: 0,
|
||||
name: "Пешком",
|
||||
length: 100,
|
||||
averageTime: 100,
|
||||
startCoordinates: {
|
||||
latitude: 60.977313,
|
||||
longitude: 69.039326,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const User = () => {
|
||||
const { userState, setUserState } = useContext(UserContext);
|
||||
return (
|
||||
<>
|
||||
<RouteView header={"Новые маршруты"} routes={routes} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
User.Layout = UserLayout;
|
||||
|
||||
export default User;
|
BIN
front/public/favicon.ico
Normal file
BIN
front/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
4
front/public/vercel.svg
Normal file
4
front/public/vercel.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
0
front/styles/globals.css
Normal file
0
front/styles/globals.css
Normal file
0
front/styles/layout.module.css
Normal file
0
front/styles/layout.module.css
Normal file
0
front/styles/user.module.css
Normal file
0
front/styles/user.module.css
Normal file
20
front/tsconfig.json
Normal file
20
front/tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
16
front/types/main.ts
Normal file
16
front/types/main.ts
Normal file
@ -0,0 +1,16 @@
|
||||
type RouteT = {
|
||||
id: number;
|
||||
name: string;
|
||||
length: number;
|
||||
averageTime?: number;
|
||||
userTime?: number;
|
||||
startCoordinates?: CoordinatesT;
|
||||
coordinates?: CoordinatesT[];
|
||||
};
|
||||
|
||||
type CoordinatesT = {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
};
|
||||
|
||||
export type { RouteT, CoordinatesT };
|
16
front/types/user.ts
Normal file
16
front/types/user.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { RouteT } from "./main";
|
||||
|
||||
interface IHeaderProps {
|
||||
points: number;
|
||||
}
|
||||
|
||||
interface IRouteView {
|
||||
header: string;
|
||||
routes: RouteT[];
|
||||
}
|
||||
|
||||
interface IRouteCard {
|
||||
route: RouteT;
|
||||
}
|
||||
|
||||
export type { IHeaderProps, IRouteView, IRouteCard };
|
13
front/types/userContext.ts
Normal file
13
front/types/userContext.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
|
||||
export type UserT = {
|
||||
username: string;
|
||||
email: string;
|
||||
id: number;
|
||||
points: number;
|
||||
};
|
||||
|
||||
export type UserContextT = {
|
||||
userState: UserT;
|
||||
setUserState: Dispatch<SetStateAction<UserT>>;
|
||||
};
|
5
front/utils/index.ts
Normal file
5
front/utils/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
const formatTimeLength = (minutes: number) =>
|
||||
(Math.floor(minutes / 60) > 0 ? `${Math.floor(minutes / 60)} ч. ` : "") +
|
||||
(minutes % 60 > 0 ? `${minutes % 60} мин.` : "");
|
||||
|
||||
export { formatTimeLength };
|
4138
front/yarn.lock
Normal file
4138
front/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user