Skip to content

Commit

Permalink
feat(ui): replace alert with modal window
Browse files Browse the repository at this point in the history
  • Loading branch information
Valik3201 committed Jan 23, 2024
1 parent b228177 commit 5021491
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 52 deletions.
126 changes: 74 additions & 52 deletions src/components/ContactForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Component } from 'react';
import { nanoid } from 'nanoid';
import PropTypes from 'prop-types';

import { ModalAlert } from './ModalAlert';

import { Form, Row, Col, Button, FloatingLabel } from 'react-bootstrap';

/**
Expand All @@ -14,10 +16,12 @@ export class ContactForm extends Component {
this.state = {
name: '',
number: '',
modalShow: false,
};

this.handleChange = this.handleChange.bind(this);
this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.setModalShow = this.setModalShow.bind(this);
}

/**
Expand All @@ -28,6 +32,16 @@ export class ContactForm extends Component {
this.setState({ [e.target.name]: e.target.value });
}

/**
* Sets the state for displaying or hiding the modal.
* @param {boolean} value - A flag indicating whether to show (true) or hide (false) the modal.
* @param {string} name - The name of the contact to be displayed in the modal.
*/
setModalShow = (value, name) => {
// Set the new state with the provided values
this.setState({ modalShow: value, name });
};

/**
* Handle form submission for adding a new contact.
* @param {Object} e - The event object.
Expand All @@ -39,7 +53,7 @@ export class ContactForm extends Component {
const { contacts, addContact } = this.props;

if (contacts.some(contact => contact.name === name)) {
alert(`Contact with name "${name}" already exists!`);
this.setModalShow(true, name, number);
return;
}

Expand All @@ -55,59 +69,67 @@ export class ContactForm extends Component {
}

render() {
const { name, number } = this.state;
const { name, number, modalShow } = this.state;

return (
<Form onSubmit={this.handleFormSubmit} autoComplete="off">
<Row>
<Col>
<FloatingLabel
controlId="floatingInput"
label="Name"
className="mb-3"
>
<Form.Control
type="text"
name="name"
value={name}
onChange={this.handleChange}
autoComplete="off"
pattern="^[a-zA-Zа-яА-Я]+(([' -][a-zA-Zа-яА-Я ])?[a-zA-Zа-яА-Я]*)*$"
title="Name may contain only letters, apostrophe, dash and spaces. For example Adrian, Jacob Mercer, Charles de Batz de Castelmore d'Artagnan"
placeholder="Name"
required
/>
</FloatingLabel>
</Col>
<Col>
<FloatingLabel
controlId="floatingInput"
label="Number"
className="mb-3"
>
<Form.Control
type="tel"
name="number"
value={number}
onChange={this.handleChange}
autoComplete="off"
pattern="\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}"
title="Phone number must be digits and can contain spaces, dashes, parentheses and can start with +"
placeholder="+48 123-456-789"
required
/>
</FloatingLabel>
</Col>
</Row>

<Row className="justify-content-end">
<Col xs={12} lg={4}>
<Button variant="primary" type="submit" className="w-100">
Add Contact
</Button>
</Col>
</Row>
</Form>
<>
<Form onSubmit={this.handleFormSubmit} autoComplete="off">
<Row>
<Col>
<FloatingLabel
controlId="floatingInput"
label="Name"
className="mb-3"
>
<Form.Control
type="text"
name="name"
value={name}
onChange={this.handleChange}
autoComplete="off"
pattern="^[a-zA-Zа-яА-Я]+(([' -][a-zA-Zа-яА-Я ])?[a-zA-Zа-яА-Я]*)*$"
title="Name may contain only letters, apostrophe, dash and spaces. For example Adrian, Jacob Mercer, Charles de Batz de Castelmore d'Artagnan"
placeholder="Name"
required
/>
</FloatingLabel>
</Col>
<Col>
<FloatingLabel
controlId="floatingInput"
label="Number"
className="mb-3"
>
<Form.Control
type="tel"
name="number"
value={number}
onChange={this.handleChange}
autoComplete="off"
pattern="\+?\d{1,4}?[-.\s]?\(?\d{1,3}?\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}"
title="Phone number must be digits and can contain spaces, dashes, parentheses and can start with +"
placeholder="+48 123-456-789"
required
/>
</FloatingLabel>
</Col>
</Row>

<Row className="justify-content-end">
<Col xs={12} lg={4}>
<Button variant="primary" type="submit" className="w-100">
Add Contact
</Button>
</Col>
</Row>
</Form>

<ModalAlert
show={modalShow}
name={name}
onHide={() => this.setModalShow(false, '')}
/>
</>
);
}
}
Expand Down
32 changes: 32 additions & 0 deletions src/components/ModalAlert.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import PropTypes from 'prop-types';
import { Modal, Button } from 'react-bootstrap';

/**
* Functional component for rendering an alert modal.
* @param {Object} props - Component properties.
* @param {string} props.name - The name of the contact displayed in the modal.
* @param {Function} props.onHide - Callback function to handle modal hiding.
* @param {boolean} props.show - A flag indicating whether the modal should be visible or hidden.
* @returns {JSX.Element} - The rendered ModalAlert component.
*/
export const ModalAlert = ({ name, onHide, show }) => {
return (
<Modal show={show} centered onHide={onHide}>
<Modal.Header closeButton />
<Modal.Body>
Contact with name <span className="fw-bold">{name} </span> already
exists!
</Modal.Body>
<Modal.Footer>
<Button onClick={onHide}>Close</Button>
</Modal.Footer>
</Modal>
);
};

// PropTypes
ModalAlert.propTypes = {
name: PropTypes.string.isRequired,
onHide: PropTypes.func.isRequired,
show: PropTypes.bool.isRequired,
};

0 comments on commit 5021491

Please sign in to comment.