Commit 59934c59 authored by zarina's avatar zarina 🌊

#3, реализована возможность редактирования контактов

parent 198840b7
.Contact{
max-width: 500px;
border: 10px solid #f8f9fa;
margin: 10px auto;
display: flex;
min-height: 100px;
padding: 15px;
font-size: 20px;
font-weight: bold;
align-items: center;
color: rgba(0,0,0,.9);
cursor: pointer;
}
.Contact:hover{
border-color: rgba(0,0,0,.2);
}
.Contact img {
width: 25%;
font-size: 15px;
margin-right: 20px;
}
import React from "react"; import React from "react";
import './Contact.css'
const Contact = props => { const Contact = props => {
return ( return (
<div onClick={props.select} className='Contact'> <div onClick={props.select} className='Contact'>
<img src={props.photo} alt="contact"/>
<div>{props.name}</div> <div>{props.name}</div>
</div> </div>
); );
......
import React from 'react'; import React from 'react';
import {Button, Form, FormGroup, Label, Input} from 'reactstrap'; import {Button, Form, FormGroup, Label, Input} from 'reactstrap';
import {NavLink} from "react-router-dom";
const FormToFill = props => { const FormToFill = props => {
return ( return (
...@@ -7,6 +8,7 @@ const FormToFill = props => { ...@@ -7,6 +8,7 @@ const FormToFill = props => {
<FormGroup> <FormGroup>
<Label for="name">Name</Label> <Label for="name">Name</Label>
<Input type="text" <Input type="text"
required
name="name" name="name"
value={props.name} value={props.name}
onChange={props.inputHandler} onChange={props.inputHandler}
...@@ -16,6 +18,7 @@ const FormToFill = props => { ...@@ -16,6 +18,7 @@ const FormToFill = props => {
<FormGroup> <FormGroup>
<Label for="phone">Phone</Label> <Label for="phone">Phone</Label>
<Input type="text" <Input type="text"
required
name="phone" name="phone"
value={props.phone} value={props.phone}
onChange={props.inputHandler} onChange={props.inputHandler}
...@@ -25,6 +28,7 @@ const FormToFill = props => { ...@@ -25,6 +28,7 @@ const FormToFill = props => {
<FormGroup> <FormGroup>
<Label for="email">Email</Label> <Label for="email">Email</Label>
<Input type="email" <Input type="email"
required
name="email" name="email"
value={props.email} value={props.email}
onChange={props.inputHandler} onChange={props.inputHandler}
...@@ -34,13 +38,21 @@ const FormToFill = props => { ...@@ -34,13 +38,21 @@ const FormToFill = props => {
<FormGroup> <FormGroup>
<Label for="photo">Photo</Label> <Label for="photo">Photo</Label>
<Input type="text" <Input type="text"
required
name="photo" name="photo"
value={props.photo} value={props.photo}
onChange={props.inputHandler} onChange={props.inputHandler}
id="photo" id="photo"
placeholder="enter url"/> placeholder="enter url"/>
</FormGroup> </FormGroup>
<Button >Submit</Button> {props.photo ?
<div>
<h6>Photo preview</h6>
<img src={props.photo} width='300' className='mb-4' alt="contact"/>
</div> : null
}
<Button color='success' className='mr-3'>Submit</Button>
<Button color='info' tag={NavLink} to={`/`}>Back to contacts</Button>
</Form> </Form>
); );
} }
......
import React from "react";
import {NavLink} from "react-router-dom";
import {Button} from "reactstrap";
const FullContact = props => {
return (
<div className='FullContact d-flex justify-content-around p-5'>
<div>
<img src={props.photo} alt="contact"/>
</div>
<div>
<div> name: {props.name} </div>
<div> email: {props.email} </div>
<div> phone: {props.phone} </div>
<div className='mt-3'>
<Button color='info' className='mr-3' tag={NavLink} to={`/contacts/${props.id}/edit`}>edit</Button>
<Button onClick={() => props.selectHandler(null)} color='danger'>cancel</Button>
</div>
</div>
</div>
);
};
export default FullContact;
...@@ -5,7 +5,7 @@ import Container from "reactstrap/es/Container"; ...@@ -5,7 +5,7 @@ import Container from "reactstrap/es/Container";
const Header = () => { const Header = () => {
return ( return (
<Navbar color="light" light expand="md mb-4"> <Navbar color="light" light expand="md mb-5">
<Container> <Container>
<NavbarBrand tag={NavLink} to="/">Contacts</NavbarBrand> <NavbarBrand tag={NavLink} to="/">Contacts</NavbarBrand>
<Nav className="ml-auto" navbar> <Nav className="ml-auto" navbar>
......
...@@ -6,15 +6,11 @@ const Modal = props => { ...@@ -6,15 +6,11 @@ const Modal = props => {
return ( return (
<> <>
<Backdrop <Backdrop
show={props.show} show={props.backdrop}
clicked={props.closed} clicked={props.closed}
/> />
<div <div
className="Modal" className="Modal"
style={{
transform: props.show ? "translateY(0)" : "translateY(-100vh)",
opacity: props.show ? 1 : 0
}}
> >
{props.children} {props.children}
</div> </div>
......
...@@ -24,13 +24,12 @@ const AddContactForm = props => { ...@@ -24,13 +24,12 @@ const AddContactForm = props => {
const contact = { const contact = {
...contactInfo ...contactInfo
}; };
props.onContactCreated(contact) props.onContactCreated(contact, props.history)
}; };
return ( return (
<> <>
<h2 className='mb-4'>Add new contact</h2>
<div> <div>
<FormToFill <FormToFill
inputHandler={inputHandler} inputHandler={inputHandler}
...@@ -47,7 +46,7 @@ const AddContactForm = props => { ...@@ -47,7 +46,7 @@ const AddContactForm = props => {
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
onContactCreated: (contact) => dispatch(createContact(contact)) onContactCreated: (contact, history) => dispatch(createContact(contact, history))
} }
}; };
......
...@@ -2,18 +2,27 @@ import React from 'react'; ...@@ -2,18 +2,27 @@ import React from 'react';
import {Switch, Route} from "react-router-dom"; import {Switch, Route} from "react-router-dom";
import {Container} from "reactstrap"; import {Container} from "reactstrap";
import './App.css'; import './App.css';
import Layout from "../components/Layout/Layout";
import AddContactForm from "./AddContactForm/AddContactForm";
import Contacts from "./Contacts/Contacts";
import EditContactForm from "./EditContactForm/EditContactForm";
function App() { function App() {
return ( return (
<> <>
<Container> <Layout>
<Switch> <Container>
<Switch>
</Switch> <Route path='/' exact component={Contacts}/>
</Container> <Route path='/contacts' exact component={Contacts}/>
</> <Route path='/add-contact' exact component={AddContactForm}/>
); <Route path='/contacts/:id/edit' exact component={EditContactForm}/>
</Switch>
</Container>
</Layout>
</>
);
} }
export default App; export default App;
......
...@@ -2,22 +2,21 @@ import React, {Component} from "react"; ...@@ -2,22 +2,21 @@ import React, {Component} from "react";
import {connect} from "react-redux"; import {connect} from "react-redux";
import {getContacts} from "../../store/actions"; import {getContacts} from "../../store/actions";
import Contact from "../../components/Contact/Contact"; import Contact from "../../components/Contact/Contact";
import Modal from "../../components/Modal/Modal"; import Modal from "../../components/UI/Modal/Modal";
import {NavLink} from "react-router-dom"; import FullContact from "../../components/FullContact/FullContact";
class Contacts extends Component { class Contacts extends Component {
state = { state = {
selectContact: null, selectContact: null
modalShow: false
} }
componentDidMount() { componentDidMount() {
this.props.getContacts() this.props.getContacts()
} }
selectHandler = (id) => { selectHandler = (value) => {
this.setState({selectContact: id}) this.setState({selectContact: value})
} }
printContacts = () => { printContacts = () => {
...@@ -26,8 +25,6 @@ class Contacts extends Component { ...@@ -26,8 +25,6 @@ class Contacts extends Component {
return <Contact return <Contact
select={() => this.selectHandler(contact)} select={() => this.selectHandler(contact)}
name={contacts[contact].name} name={contacts[contact].name}
email={contacts[contact].email}
phone={contacts[contact].phone}
photo={contacts[contact].photo} photo={contacts[contact].photo}
key={contact}/> key={contact}/>
}) })
...@@ -39,12 +36,16 @@ class Contacts extends Component { ...@@ -39,12 +36,16 @@ class Contacts extends Component {
{this.props.contacts ? <div className='Contacts'>{this.printContacts()}</div> : null} {this.props.contacts ? <div className='Contacts'>{this.printContacts()}</div> : null}
{ {
this.state.selectContact ? this.state.selectContact ?
<Modal show={true}> <Modal backdrop={true}>
<> <>
<div> {this.props.contacts[this.state.selectContact].email} </div> <FullContact
<div> {this.props.contacts[this.state.selectContact].name} </div> name={this.props.contacts[this.state.selectContact].name}
<div> {this.props.contacts[this.state.selectContact].phone} </div> phone={this.props.contacts[this.state.selectContact].phone}
<NavLink to={`/contacts/edit/${this.state.selectContact}`}>edit</NavLink> email={this.props.contacts[this.state.selectContact].email}
photo={this.props.contacts[this.state.selectContact].photo}
id={this.state.selectContact}
selectHandler={this.selectHandler}
/>
</> </>
</Modal> </Modal>
: null : null
......
import React, {useEffect, useState} from "react";
import FormToFill from "../../components/FormToFill/FormToFill";
import {createContact, editContact} from "../../store/actions";
import {connect} from "react-redux";
const EditContactForm = props => {
const [contactInfo, setContactInfo] = useState({
name: '',
phone: '',
email: '',
photo: ''
});
useEffect(() => {
let id = props.match.params.id
setContactInfo(props.contacts[id])
}, [props.match.params.id, props.contacts])
const inputHandler = (e) => {
setContactInfo({
...contactInfo,
[e.target.name]: e.target.value
})
};
const addContact = e => {
e.preventDefault();
const contact = {
...contactInfo
};
props.onEditContact(props.match.params.id, props.history, contact)
};
return (
<>
<h2 className='mb-4'>Edit contact</h2>
<div>
<FormToFill
inputHandler={inputHandler}
name={contactInfo.name}
phone={contactInfo.phone}
email={contactInfo.email}
photo={contactInfo.photo}
submit={addContact}
/>
</div>
</>
);
};
const mapStateToProps = state => {
return {
contacts: state.contacts
}
};
const mapDispatchToProps = dispatch => {
return {
onEditContact: (id, history, contact ) => dispatch(editContact(id, history, contact))
}
};
export default connect(mapStateToProps, mapDispatchToProps)(EditContactForm);
export const FETCH_REQUEST = 'FETCH_REQUEST';
export const FETCH_ERROR = 'FETCH_ERROR';
export const FETCH_SUCCESS = 'FETCH_SUCCESS'
export const FETCH_GET_CONTACTS_SUCCESS = 'FETCH_GET_CONTACTS_SUCCESS'
\ No newline at end of file
import {
FETCH_ERROR,
FETCH_GET_CONTACTS_SUCCESS,
FETCH_REQUEST, FETCH_SUCCESS
} from "./actionTypes";
import axios from '../axios-contacts'
const fetchRequest = () => {
return {type: FETCH_REQUEST};
};
const fetchError = error => {
return {type: FETCH_ERROR, error};
};
const fetchSuccess = () => {
return {type: FETCH_SUCCESS}
};
const fetchGetContactsSuccess = (contacts) => {
return {type: FETCH_GET_CONTACTS_SUCCESS, contacts}
}
export const createContact = (contact, history) => {
return dispatch => {
dispatch(fetchRequest());
axios.post("/contacts.json", contact)
.then(() => {
dispatch(fetchSuccess());
history.push('/')
})
.catch(err => {
dispatch(fetchError(err));
});
}
};
export const getContacts = () => {
return dispatch => {
dispatch(fetchRequest());
axios.get("/contacts.json")
.then((response) => {
dispatch(fetchGetContactsSuccess(response.data));
})
.catch(err => {
dispatch(fetchError(err));
});
}
}
export const editContact = (id, history, contact) => {
return dispatch => {
dispatch(fetchRequest());
axios.put(`/contacts/${id}.json`, contact)
.then((response) => {
console.log(response)
history.push('/')
fetchSuccess()
})
.catch(err => {
dispatch(fetchError(err));
});
}
}
import {FETCH_ERROR, FETCH_GET_CONTACTS_SUCCESS, FETCH_REQUEST, FETCH_SUCCESS} from "./actionTypes";
const initialState = { const initialState = {
error: null, error: null,
loading: false, loading: false,
contacts: {} contacts: {},
}; };
const reducer = (state = initialState, action) => { const reducer = (state = initialState, action) => {
return state switch (action.type) {
case FETCH_REQUEST: {
return {...state, loading: true}
}
case FETCH_ERROR: {
return {...state, loading: false, error: action.error}
}
case FETCH_SUCCESS: {
return {...state, loading: false}
}
case FETCH_GET_CONTACTS_SUCCESS: {
return {...state, contacts: action.contacts, loading: false}
}
default: {
return state
}
}
}; };
export default reducer export default reducer
\ No newline at end of file
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