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 './Contact.css'
const Contact = props => {
return (
<div onClick={props.select} className='Contact'>
<img src={props.photo} alt="contact"/>
<div>{props.name}</div>
</div>
);
......
import React from 'react';
import {Button, Form, FormGroup, Label, Input} from 'reactstrap';
import {NavLink} from "react-router-dom";
const FormToFill = props => {
return (
......@@ -7,6 +8,7 @@ const FormToFill = props => {
<FormGroup>
<Label for="name">Name</Label>
<Input type="text"
required
name="name"
value={props.name}
onChange={props.inputHandler}
......@@ -16,6 +18,7 @@ const FormToFill = props => {
<FormGroup>
<Label for="phone">Phone</Label>
<Input type="text"
required
name="phone"
value={props.phone}
onChange={props.inputHandler}
......@@ -25,6 +28,7 @@ const FormToFill = props => {
<FormGroup>
<Label for="email">Email</Label>
<Input type="email"
required
name="email"
value={props.email}
onChange={props.inputHandler}
......@@ -34,13 +38,21 @@ const FormToFill = props => {
<FormGroup>
<Label for="photo">Photo</Label>
<Input type="text"
required
name="photo"
value={props.photo}
onChange={props.inputHandler}
id="photo"
placeholder="enter url"/>
</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>
);
}
......
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";
const Header = () => {
return (
<Navbar color="light" light expand="md mb-4">
<Navbar color="light" light expand="md mb-5">
<Container>
<NavbarBrand tag={NavLink} to="/">Contacts</NavbarBrand>
<Nav className="ml-auto" navbar>
......
......@@ -6,15 +6,11 @@ const Modal = props => {
return (
<>
<Backdrop
show={props.show}
show={props.backdrop}
clicked={props.closed}
/>
<div
className="Modal"
style={{
transform: props.show ? "translateY(0)" : "translateY(-100vh)",
opacity: props.show ? 1 : 0
}}
>
{props.children}
</div>
......
......@@ -24,13 +24,12 @@ const AddContactForm = props => {
const contact = {
...contactInfo
};
props.onContactCreated(contact)
props.onContactCreated(contact, props.history)
};
return (
<>
<h2 className='mb-4'>Add new contact</h2>
<div>
<FormToFill
inputHandler={inputHandler}
......@@ -47,7 +46,7 @@ const AddContactForm = props => {
const mapDispatchToProps = dispatch => {
return {
onContactCreated: (contact) => dispatch(createContact(contact))
onContactCreated: (contact, history) => dispatch(createContact(contact, history))
}
};
......
......@@ -2,16 +2,25 @@ import React from 'react';
import {Switch, Route} from "react-router-dom";
import {Container} from "reactstrap";
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() {
return (
<>
<Layout>
<Container>
<Switch>
<Route path='/' exact component={Contacts}/>
<Route path='/contacts' exact component={Contacts}/>
<Route path='/add-contact' exact component={AddContactForm}/>
<Route path='/contacts/:id/edit' exact component={EditContactForm}/>
</Switch>
</Container>
</Layout>
</>
);
}
......
......@@ -2,22 +2,21 @@ import React, {Component} from "react";
import {connect} from "react-redux";
import {getContacts} from "../../store/actions";
import Contact from "../../components/Contact/Contact";
import Modal from "../../components/Modal/Modal";
import {NavLink} from "react-router-dom";
import Modal from "../../components/UI/Modal/Modal";
import FullContact from "../../components/FullContact/FullContact";
class Contacts extends Component {
state = {
selectContact: null,
modalShow: false
selectContact: null
}
componentDidMount() {
this.props.getContacts()
}
selectHandler = (id) => {
this.setState({selectContact: id})
selectHandler = (value) => {
this.setState({selectContact: value})
}
printContacts = () => {
......@@ -26,8 +25,6 @@ class Contacts extends Component {
return <Contact
select={() => this.selectHandler(contact)}
name={contacts[contact].name}
email={contacts[contact].email}
phone={contacts[contact].phone}
photo={contacts[contact].photo}
key={contact}/>
})
......@@ -39,12 +36,16 @@ class Contacts extends Component {
{this.props.contacts ? <div className='Contacts'>{this.printContacts()}</div> : null}
{
this.state.selectContact ?
<Modal show={true}>
<Modal backdrop={true}>
<>
<div> {this.props.contacts[this.state.selectContact].email} </div>
<div> {this.props.contacts[this.state.selectContact].name} </div>
<div> {this.props.contacts[this.state.selectContact].phone} </div>
<NavLink to={`/contacts/edit/${this.state.selectContact}`}>edit</NavLink>
<FullContact
name={this.props.contacts[this.state.selectContact].name}
phone={this.props.contacts[this.state.selectContact].phone}
email={this.props.contacts[this.state.selectContact].email}
photo={this.props.contacts[this.state.selectContact].photo}
id={this.state.selectContact}
selectHandler={this.selectHandler}
/>
</>
</Modal>
: 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 = {
error: null,
loading: false,
contacts: {}
contacts: {},
};
const reducer = (state = initialState, action) => {
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
\ 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