Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ services:
context: .
environment:
NODE_ENV: production
ports:
- "3000:3000"
volumes:
- ./:/app/result_build/
nginx:
Expand All @@ -15,4 +13,4 @@ services:
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./build:/usr/share/nginx/html/
# - ../docs/:/usr/share/nginx/html/api/docs/
- ./docs/:/usr/share/nginx/html/api/docs/
6 changes: 5 additions & 1 deletion nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ server {
location /admin/ {
proxy_pass https://hellchicken.ru;
}
location /api/docs/ {
root /usr/share/nginx/html;
try_files $uri $uri/redoc.html;
}
location /django_static/ {
proxy_pass https://hellchicken.ru;
}
location /django_media/ {
proxy_pass https://hellchicken.ru;
}
location / {
proxy_pass https://hellchicken.ru
proxy_pass http://localhost:3000;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
Expand Down
177 changes: 164 additions & 13 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,176 @@
import {BrowserRouter, Route, Routes} from 'react-router-dom';
import React from 'react';
import {BrowserRouter, Route, Routes, useNavigate} from 'react-router-dom';
import React, {useEffect, useState} from 'react';
import './App.css';
import styles from "./styles.module.css";
import {MainPage, SignUp, SingleCard} from "./pages";
import {Footer, Header} from "./components";
import {authApi, recipesApi, usersApi} from "./shared/api";
import {SignupResponse} from "./shared/api/users/models";
import {AuthContext, UserContext} from "./contexts";


function App() {
const [loggedIn, setLoggedIn] = useState<boolean>(false);
const [user, setUser] = useState<SignupResponse | null>(null)
const [orders, setOrders] = useState<number>(0)

const navigate = useNavigate();

const onSignOut = () => {
console.log("Выход из системы")
};
authApi.logout()
.then(res => {
localStorage.removeItem('token')
setLoggedIn(false)
})
.catch(err => {
const errors = Object.values(err)
if (errors) {
alert(errors.join(', '))
}
})
}
const registration = (
{
email,
password,
username,
first_name,
last_name
}: usersApi.SignUpRequest) => {
usersApi.signUp({email, password, username, first_name, last_name})
.then(res => {
navigate('/signin')
})
.catch(err => {
const errors = Object.values(err)
if (errors) {
alert(errors.join(', '))
}
setLoggedIn(false);
})
}

const getOrders = () => {
recipesApi
.getRecipes({
is_in_shopping_cart: Number(true),
})
.then(res => {
const {count} = res
setOrders(count)
})
}
useEffect(() => {
if (loggedIn) {
navigate('/recipes')
}
}, [loggedIn])

const authorization = (
{
email, password
}: authApi.LoginRequest) => {
authApi.login({
email, password
}).then(res => {
if (res.auth_token) {
localStorage.setItem('token', res.auth_token)
usersApi.getMe()
.then(res => {
setUser(res)
setLoggedIn(true)
getOrders()
})
.catch(err => {
setLoggedIn(false)
navigate('/signin')
})
} else {
setLoggedIn(false)
}
})
.catch(err => {
const errors = Object.values(err)
if (errors) {
alert(errors.join(', '))
}
setLoggedIn(false)
})
}

const updateOrders = (add: boolean) => {
if (!add && orders <= 0) {
return
}
if (add) {
setOrders(orders + 1)
} else {
setOrders(orders - 1)
}
}

useEffect((): any => {
const token = localStorage.getItem('token')
if (token) {
return usersApi.getMe()
.then(res => {
setUser(res)
setLoggedIn(true)
getOrders()
})
.catch(err => {
setLoggedIn(false)
navigate('/signin')
})
}
setLoggedIn(false)
}, [])

return (
<BrowserRouter>
<Header loggedIn={false} onSignOut={onSignOut}></Header>
<Routes>
<Route path="/" element={<MainPage/>}/>
<Route path="/recipes/:id" element={<SingleCard/>}/>
<Route path="/signup" element={<SignUp/>}/>
</Routes>
<Footer/>
</BrowserRouter>
<AuthContext.Provider value={loggedIn}>
<UserContext.Provider value={user}>
<BrowserRouter>
<Header loggedIn={loggedIn} onSignOut={onSignOut}/>
<Routes>
<Route path="/" element={<MainPage updateOrders={updateOrders}/>}/>
<Route
path='/recipes/:id'
>
<SingleCard
updateOrders={updateOrders}
/>
</Route>

<Route path='/recipes'>
<MainPage
updateOrders={updateOrders}
/>
</Route>
{/*<Route path='/signin'>*/}
{/* <SignIn*/}
{/* onSignIn={authorization}*/}
{/* />*/}
{/*</Route>*/}
{/*<Route path='/signup'>*/}
{/* <SignUp*/}
{/* onSignUp={registration}*/}
{/* />*/}
{/*</Route>*/}
<Route path='/'>
{/*{loggedIn ? <MainPage*/}
{/* updateOrders={updateOrders}*/}
{/*/> : <SignIn*/}
{/* onSignIn={authorization}*/}
{/*/>}*/}
<MainPage
updateOrders={updateOrders}
/>
</Route>
</Routes>
<Footer/>
</BrowserRouter>
</UserContext.Provider>
</AuthContext.Provider>
);
}

Expand Down
16 changes: 16 additions & 0 deletions src/components/protected-route/protected-route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {ReactNode} from 'react';
import {useNavigate} from "react-router-dom";

interface Props {
children: ReactNode;
}

export default function ProtectedRoute({children}: Props): ReactNode {
const navigate = useNavigate();
if (localStorage.getItem("token") === null) {
navigate('/signin')
}
return (
children
)
}
34 changes: 22 additions & 12 deletions src/components/tag/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import styles from './style.module.css';

interface TagProps {
name: string;
color?: string;
import styles from './styles.module.css'

interface Props {
name: string
color: string
}

const hexToRgb = (hex: string, alpha: number = 1): any => {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
return result ? `rgba(${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}, ${alpha}` : null
}


const Tag = ({name, color = '#8775D2'}: Props) => {
const background = hexToRgb(color, 0.1)
return <div className={styles.tag} style={{
backgroundColor: background,
color
}}>
{name}
</div>
}

export default function Tag({name, color = '#8775D2'}: TagProps) {
const background = `${color}1A`;
return (
<div className={styles.tag} style={{backgroundColor: background, color}}>
{name}
</div>
);
};
export default Tag
25 changes: 25 additions & 0 deletions src/components/tag/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.tag {
display: inline-block;
padding: 4px 12px;
font-weight: 500;
font-family: Montserrat, Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1;
border-radius: 24px;
margin-right: 8px;
}

.tag_type_orange {
background: rgba(234, 146, 99, 0.12);
color: #E26C2D;
}

.tag_type_green {
background: rgba(73, 182, 78, 0.1);
color: #49B64E;
}

.tag_type_violet {
background: rgba(135,117,210,0.1);
color: #8775D2;
}
37 changes: 18 additions & 19 deletions src/components/tags-container/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
import styles from './style.module.css';
import {Tag} from '../index';

interface TagData {
id: string;
color: string;
name: string;
}
import styles from './styles.module.css'
import {Tag as TagDTO} from "../../shared/api/tags/models";
import {Tag} from "../index";

interface TagDataProps {
tags: TagData[]
interface Props {
tags?: TagDTO[]
}

export default function TagsContainer({tags}: TagDataProps) {
const TagsContainer = ({tags}: Props) => {
if (!tags) {
return null;
return null
}
return <div className={styles['tags-container']}>
{tags.map(tag => {
return <Tag
key={tag.id}
color={tag.color}
name={tag.name}
/>
})}
</div>
}

return (
<div className={styles['tags-container']}>
{tags.map(tag => (
<Tag key={tag.id} color={tag.color} name={tag.name}/>
))}
</div>
);
};
export default TagsContainer
3 changes: 3 additions & 0 deletions src/components/tags-container/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.tags-container {
margin-bottom: 20px;
}
2 changes: 1 addition & 1 deletion src/contexts/auth-context.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import React from 'react'

export default React.createContext<any>
export default React.createContext<any>(undefined);
9 changes: 6 additions & 3 deletions src/contexts/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React from "react";
import AuthContext from "./auth-context";
import RecipesContext from "./recipes-context";
import UserContext from "./user-context";

const AuthContext = React.createContext(undefined);
export {
AuthContext
AuthContext,
RecipesContext,
UserContext,
}
3 changes: 3 additions & 0 deletions src/contexts/recipes-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import {createContext} from "react";

export default createContext<any>(undefined);
3 changes: 3 additions & 0 deletions src/contexts/user-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import {createContext} from "react";

export default createContext<any>(undefined);
Loading