Commit 19351291 authored by zarina's avatar zarina 🌊

#8, #9, #10, сайдбар перенесен в контейнер с цитатами, добавлены цитаты в базу,…

#8, #9, #10,  сайдбар перенесен в контейнер с цитатами, добавлены цитаты в базу,  формы разделены на разные контейнеры
parent ce569a5d
import React from 'react';
import { Button, Form, FormGroup, Label, Input, FormText } from 'reactstrap';
import { Button, Form, FormGroup, Label, Input } from 'reactstrap';
import CATEGORIES from "../../quotes-categories";
const FormToFill = (props) => {
......
import React from 'react';
import { Card, Button, CardFooter, CardBody,
import { Card, Button, CardBody,
CardTitle, CardText } from 'reactstrap';
import {NavLink} from "react-router-dom";
......@@ -9,12 +9,11 @@ const Quote = props => {
<div className='Quote mb-3'>
<Card>
<CardBody>
<CardTitle className='text-uppercase font-weight-bold'>{props.author}</CardTitle>
<CardText>{props.text}</CardText>
<CardTitle className='text-uppercase font-weight-bold'>"{props.text}"</CardTitle>
<CardText>- {props.author}</CardText>
<Button onClick={props.delete} className='mr-3' color='danger'>Delete</Button>
<Button tag={NavLink} to={`/quotes/${props.id}/edit`} color='info'>Edit</Button>
</CardBody>
<CardFooter className='text-muted'>{props.category}</CardFooter>
</Card>
</div>
);
......
import React from "react";
import {Container, Nav, Navbar, NavbarBrand, NavItem} from "reactstrap";
import {Nav, Navbar, NavItem} from "reactstrap";
import {NavLink} from "react-router-dom";
import CATEGORIES from "../../quotes-categories";
const Sidebar = () => {
const printCategories = () => {
return CATEGORIES.map(category => {
return <NavItem key={`sidebar_${category.id}` }>
<NavLink className="nav-link" to={'/quotes/' + category.id} >{category.title}</NavLink>
</NavItem>
})
};
return (
......
.overlay {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
background: rgba(255, 255, 255, 0.6);
}
.Loader {
position: absolute;
left: 50%;
top: 50%;
z-index: 100;
margin-top: -1.5rem;
margin-left: -1.5rem;
}
import React from "react";
import {Spinner} from "reactstrap";
import "./Loader.css";
const Loader = () => {
return (
<div className="overlay">
<Spinner
style={{ width: '3rem', height: '3rem' }}
className="Loader"
color="primary"
/>
</div>
);
};
export default Loader;
import React, {useEffect, useState} from "react";
import React, { useState} from "react";
import axios from '../../axios-quote'
import FormToFill from "../../components/FormToFill/FormToFill";
import CATEGORIES from "../../quotes-categories";
import Loader from "../../components/UI/Loader/Loader";
const QuoteForm = props => {
const AddForm = props => {
const [quoteInfo, setQuoteInfo] = useState({
author: '',
category: CATEGORIES[0].id,
text: ''
});
useEffect(() => {
if (props.match.params.id) {
axios.get(`quotes/${props.match.params.id}.json`)
.then(
response => {
setQuoteInfo(response.data)
}
)
}
else{
let resetQuoteInfo = {
author: '',
category: CATEGORIES[0].id,
text: ''
};
setQuoteInfo(resetQuoteInfo)
}
},[props.match.params.id]);
const [loading, setLoading] = useState(false);
const startLoading = () => {
setLoading(true);
};
const stopLoading = () => {
setLoading(false);
};
const inputHandler = (e) => {
setQuoteInfo({
......@@ -37,20 +29,24 @@ const QuoteForm = props => {
})
};
const submitQuote = () => {
if (!quoteInfo.text || !quoteInfo.category || !quoteInfo.author) {
alert('все поля должны быть заполнены');
return
}
startLoading();
axios.post('/quotes.json', quoteInfo).then(
()=> {
props.history.push('./')
}
)
axios.post('/quotes.json', quoteInfo).then(
() => {
props.history.push('/')
})
.catch(error => {
console.log(error);
stopLoading()
})
};
return (
<div className='QuoteForm'>
<FormToFill submitQuote={submitQuote}
......@@ -59,9 +55,12 @@ const QuoteForm = props => {
category={quoteInfo.category}
author={quoteInfo.author}
/>
{loading ? <Loader/> : null}
</div>
)
};
export default QuoteForm
\ No newline at end of file
export default AddForm
\ No newline at end of file
.App_wrapper {
display: flex;
justify-content: space-between;
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App_sidebar{
flex-basis: 20%;
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App_switches {
flex-basis: 73%;
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
\ No newline at end of file
......@@ -2,29 +2,23 @@ import React from 'react';
import {Switch, Route} from "react-router-dom";
import {Container} from "reactstrap";
import './App.css';
import QuoteForm from "./QuoteForm/QuoteForm";
import AddForm from "./AddForm/AddForm";
import Quotes from "./Quotes/Quotes";
import Header from "../components/Header/Header";
import Sidebar from "../components/Sidebar/Sidebar";
import EditForm from "./EditForm/EditForm";
function App() {
return (
<>
<Header/>
<Container className='App_wrapper'>
<div className="App_sidebar">
<Sidebar/>
</div>
<div className="App_switches">
<Container>
<Switch>
<Route path="/add-quote" exact component={QuoteForm}/>
<Route path="/add-quote" exact component={AddForm}/>
<Route path="/" exact component={Quotes}/>
<Route path="/quotes/" exact component={Quotes}/>
<Route path="/quotes/:id/edit" exact component={EditForm}/>
<Route path="/quotes/:category" exact component={Quotes}/>
<Route path="/quotes/:id/edit" exact component={QuoteForm}/>
</Switch>
</div>
</Container>
</>
);
......
import React, {useEffect, useState} from "react";
import axios from '../../axios-quote'
import FormToFill from "../../components/FormToFill/FormToFill";
import Loader from "../../components/UI/Loader/Loader";
const EditForm = props => {
const [quoteInfo, setQuoteInfo] = useState({
author: '',
category: '',
text: ''
});
const [loading, setLoading] = useState(false);
const startLoading = () => {
setLoading(true);
};
const stopLoading = () => {
setLoading(false);
};
useEffect(() => {
startLoading();
axios.get(`quotes/${props.match.params.id}.json`)
.then(
response => {
setQuoteInfo(response.data);
}
)
.catch(error => {
console.log(error)
})
.finally(stopLoading)
}, [props.match.params.id]);
const inputHandler = (e) => {
setQuoteInfo({
...quoteInfo,
[e.target.name]: e.target.value
})
};
const submitQuote = () => {
if (!quoteInfo.text || !quoteInfo.category || !quoteInfo.author) {
alert('все поля должны быть заполнены');
return
}
startLoading();
axios.put(`quotes/${props.match.params.id}.json`, quoteInfo)
.then((response) => {
props.history.push('/');
})
.catch(error => {
stopLoading();
console.log(error)
})
};
return (
<div className='QuoteForm'>
<FormToFill submitQuote={submitQuote}
inputHandler={inputHandler}
text={quoteInfo.text}
category={quoteInfo.category}
author={quoteInfo.author}
/>
{loading ? <Loader/> : null}
</div>
)
};
export default EditForm
\ No newline at end of file
.Quotes {
display: flex;
}
.Quotes_items {
flex-basis: 73%;
}
.Quotes_sidebar{
flex-basis: 25%;
}
\ No newline at end of file
import React, {useEffect, useState} from "react";
import axios from '../../axios-quote'
import Quote from "../../components/Quote/Quote";
import Loader from "../../components/UI/Loader/Loader";
import Sidebar from "../../components/Sidebar/Sidebar";
import './Quotes.css'
const Quotes = props => {
const [quotes, setQuotes] = useState({});
const [loading, setLoading] = useState(false);
const startLoading = () => {
setLoading(true);
};
const stopLoading = () => {
setLoading(false);
};
useEffect(() => {
startLoading();
axios.get(
props.match.params.category ?
`/quotes.json?orderBy="category"&equalTo="${props.match.params.category}"` :
......@@ -18,26 +30,29 @@ const Quotes = props => {
.catch(error => {
console.log(error)
})
.finally(stopLoading)
}
, [props.match.params.category]);
const deleteQuote = (id) => {
startLoading();
axios.delete(`/quotes/${id}.json`)
.then(() => {
let allQuotes = {...quotes};
delete allQuotes[id];
setQuotes(allQuotes)
})
}
.catch(error => {
console.log(error)
})
.finally(stopLoading)
};
const printQuotes = () => {
return Object.keys(quotes).map(quote => {
return <Quote author={quotes[quote].author}
text={quotes[quote].text}
category={quotes[quote].category}
key={quote}
delete={() => deleteQuote(quote)}
id={quote}
......@@ -45,15 +60,18 @@ const Quotes = props => {
})
};
return (
<div className='Quotes'>
{
Object.keys(quotes).length > 0 ? printQuotes() : 'Please add quotes'
}
</div>
<>
<div className='Quotes'>
<div className="Quotes_sidebar">
<Sidebar/>
</div>
<div className="Quotes_items">
{Object.keys(quotes).length > 0 ? printQuotes() : 'Please add quotes'}
{loading ? <Loader/> : null}
</div>
</div>
</>
)
};
......
......@@ -3,7 +3,7 @@ const CATEGORIES = [
{title: 'Motivational', id: 'motivational'},
{title: 'Famous people', id: 'famous-people'},
{title: 'Saying', id: 'saying'},
{title: 'Humour', id: 'humour'},
{title: 'About humour', id: 'humour'},
];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment