Add a bunch of modal dialogs

This commit is contained in:
Justin Edmund 2020-09-14 18:29:07 -07:00
parent 68d3136f39
commit 99ec936fd1
10 changed files with 281 additions and 0 deletions

View file

@ -0,0 +1,22 @@
import React from 'react'
import Portal from '../../Portal'
import Modal from '../Modal/Modal'
import Overlay from '../Overlay/Overlay'
const LoginModal = ({ close }) => {
return (
<Portal>
<div>
<Modal>
<input className="Input" name="email" type="text" placeholder="Email address" />
<input className="Input" name="password" type="password" placeholder="Password" />
<button className="Button">Log in</button>
</Modal>
<Overlay onClick={close} />
</div>
</Portal>
)
}
export default LoginModal

View file

@ -0,0 +1,57 @@
.ModalContainer {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.Modal {
background: #f5f5f5;
border-radius: 8px;
display: flex;
flex-direction: column;
max-height: 600px;
min-width: 360px;
max-width: 480px;
padding: 24px;
position: relative;
z-index: 10;
}
.Modal > .Input {
-webkit-font-smoothing: antialiased;
border: none;
background-color: white;
border-radius: 6px;
color: #555;
display: block;
font-size: 18px;
margin-bottom: 8px;
padding: 12px 0;
text-align: center;
}
.Modal > .Button {
background: #61B3FF;
color: #315E87;
display: block;
min-height: 45px;
text-align: center;
}
.Modal > .Button:hover {
background: #4B9BE5;
color: #233E56;
}
::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
color: #a9a9a9 !important;
opacity: 1; /* Firefox */
}

View file

@ -0,0 +1,22 @@
import React from 'react'
import classnames from 'classnames'
import './Modal.css'
interface Props {
styleName?: string
}
class Modal extends React.Component<Props> {
render() {
return (
<div className="ModalContainer">
<div className={classnames("Modal", this.props.styleName)}>
{this.props.children}
</div>
</div>
)
}
}
export default Modal

View file

@ -0,0 +1,12 @@
.Overlay {
background: black;
position: absolute;
opacity: 0.28;
height: 100%;
width: 100%;
top: 0;
left: 0;
z-index: 2;
}

View file

@ -0,0 +1,8 @@
import React from 'react'
import './Overlay.css'
const Overlay = ({ onClick }) => (
<div className="Overlay" onClick={onClick} />
)
export default Overlay

View file

@ -0,0 +1,9 @@
.SearchModal {
min-height: 320px;
min-width: 600px;
}
.SearchModal > .Input {
padding: 12px 8px;
text-align: left;
}

View file

@ -0,0 +1,94 @@
import React from 'react'
import { v1 as uuidv1 } from 'uuid'
import Portal from '../../Portal'
import Modal from '../Modal/Modal'
import Overlay from '../Overlay/Overlay'
import './SearchModal.css'
interface Props {
close: () => void
placeholderText: string
}
interface State {
query: string,
results: { [key: string]: any }
isLoaded: boolean
message: string
}
class SearchModal extends React.Component<Props, State> {
searchQuery
constructor(props) {
super(props)
this.state = {
query: '',
results: {},
isLoaded: false,
message: ''
}
}
fetchResults = (query) => {
fetch(`http://127.0.0.1:3000/api/v1/search?query=${query}`)
.then(res => res.json())
.then((result) => {
// console.log("hello world!")
console.log(result)
// this.setState({
// isLoaded: true,
// results: result
// })
}, (error) => {
// this.setState({
// isLoaded: true,
// message: error
// })
})
}
inputChanged = (event) => {
const query = this.searchQuery.value
if (query.length > 2) {
console.log(query)
this.fetchResults(query)
}
// if (query) {
// this.setState({ query, isLoaded: true, message: '' }, () => {
// // this.fetchResults(query)
// })
// } else {
// this.setState({ query, results: {}, message: '' })
// }
}
render() {
const { query, isLoaded, message } = this.state
return (
<Portal key="search_portal">
<Modal styleName="SearchModal" key="search_modal">
<input
className="Input"
defaultValue={query}
id="SearchInput"
name="query"
key="search_input_key"
type="text"
ref={el => this.searchQuery = el}
onChange={this.inputChanged}
placeholder={this.props.placeholderText}
/>
</Modal>
<Overlay onClick={this.props.close} />
</Portal>
)
}
}
export default SearchModal

View file

@ -0,0 +1,24 @@
import React from 'react'
import Portal from '../../Portal'
import Modal from '../Modal/Modal'
import Overlay from '../Overlay/Overlay'
const SignupModal = ({ close }) => {
return (
<Portal>
<div>
<Modal>
<input className="Input" name="username" type="text" placeholder="Username" />
<input className="Input" name="email" type="text" placeholder="Email address" />
<input className="Input" name="password" type="password" placeholder="Password" />
<input className="Input" name="confirm_password" type="password" placeholder="Password (again)" />
<button className="Button">Sign up</button>
</Modal>
<Overlay onClick={close} />
</div>
</Portal>
)
}
export default SignupModal

View file

@ -1,8 +1,15 @@
import React from 'react'
import './UnauthMenu.css'
import LoginModal from '../LoginModal/LoginModal'
import SignupModal from '../SignupModal/SignupModal'
import { useModal as useSignupModal } from '../../useModal'
import { useModal as useLoginModal } from '../../useModal'
function UnauthMenu() {
const { open: signupOpen, openModal: openSignupModal, closeModal: closeSignupModal } = useSignupModal()
const { open: loginOpen, openModal: openLoginModal, closeModal: closeLoginModal } = useLoginModal()
return (
<ul className="Menu">
@ -12,7 +19,16 @@ function UnauthMenu() {
</div>
<div className="MenuGroup">
<li className="MenuItem" onClick={openLoginModal}>Log in</li>
{loginOpen ? (
<LoginModal
close={closeLoginModal}
/>
) : null}
<li className="MenuItem" onClick={openSignupModal}>Sign up</li>
{signupOpen ? (
<SignupModal
close={closeSignupModal}
/>
) : null}
</div>
</ul>

17
src/useModal.ts Normal file
View file

@ -0,0 +1,17 @@
import { useState } from 'react'
export const useModal = () => {
const [open, onOpenModal] = useState(false)
const [close, onCloseModal] = useState(false)
const openModal = () => {
onOpenModal(true)
}
const closeModal = () => {
onCloseModal(true)
onOpenModal(false)
}
return { open, close, openModal, closeModal }
}