Add validation to RSVP field
Add fade in/out of bg image Clean up layout
This commit is contained in:
@@ -21,7 +21,7 @@ class Html extends React.Component {
|
||||
<meta name="description" content={description} />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Poppins:500|Yesteryear" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Palanquin+Dark|Yesteryear" />
|
||||
{style && <style id="css" dangerouslySetInnerHTML={{ __html: style }} />}
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
}
|
||||
|
||||
.rsvpGroup {
|
||||
width: 60%;
|
||||
width: 65%;
|
||||
}
|
||||
|
||||
.rsvpButtonGroup {
|
||||
@@ -64,6 +64,27 @@
|
||||
box-shadow: 0 0 4px #fff;
|
||||
}
|
||||
|
||||
.inputInvalid {
|
||||
animation: shake 0.5s linear;
|
||||
}
|
||||
|
||||
.invalidMsg {
|
||||
display: none;
|
||||
padding: 10px 16px;
|
||||
border: 4px solid var(--colour-red);
|
||||
border-radius: 14px;
|
||||
background: transparent;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
line-height: 1.3333333;
|
||||
transition: opacity ease-in-out 0.25s, box-shadow ease-in-out 0.25s;
|
||||
}
|
||||
|
||||
.invalidMsgVisible {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
@@ -89,3 +110,28 @@
|
||||
opacity: 1;
|
||||
box-shadow: 0 0 4px #fff;
|
||||
}
|
||||
|
||||
@keyframes shake {
|
||||
8%,
|
||||
41% {
|
||||
transform: translateX(-10px);
|
||||
}
|
||||
|
||||
25%,
|
||||
58% {
|
||||
transform: translateX(10px);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: translateX(-5px);
|
||||
}
|
||||
|
||||
92% {
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import React from 'react';
|
||||
import React, { PropTypes } from 'react';
|
||||
import withStyles from 'isomorphic-style-loader/lib/withStyles';
|
||||
import s from './RsvpButton.css';
|
||||
import fetch from '../../core/fetch';
|
||||
|
||||
class RsvpButton extends React.Component {
|
||||
static propTypes = {
|
||||
focusCallback: PropTypes.func,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -13,7 +17,45 @@ class RsvpButton extends React.Component {
|
||||
this.setState({ showRsvpForm: true });
|
||||
setTimeout(() => {
|
||||
this.rsvpInput.focus();
|
||||
}, 250);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
handleRsvpFocus = () => {
|
||||
if (this.props.focusCallback) {
|
||||
this.props.focusCallback(true);
|
||||
}
|
||||
this.setState({ inputError: false });
|
||||
}
|
||||
|
||||
handleRsvpBlur = () => {
|
||||
if (this.props.focusCallback) {
|
||||
this.props.focusCallback(false);
|
||||
}
|
||||
}
|
||||
|
||||
handleFormSubmit = (event) => {
|
||||
event.preventDefault();
|
||||
fetch(`rsvp/${this.rsvpInput.value}`)
|
||||
.then(data => {
|
||||
if (data.status === 200) {
|
||||
location.href = data.url;
|
||||
} else {
|
||||
this.setState({
|
||||
inputInvalid: true,
|
||||
inputInvalidMsg: 'Sorry, that RSVP code is invalid.',
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
inputInvalid: false,
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
}).catch(() => {
|
||||
this.setState({
|
||||
inputInvalid: true,
|
||||
inputInvalidMsg: 'Sorry, there was a problem validating your RSVP code, please try again later.',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -35,14 +77,19 @@ class RsvpButton extends React.Component {
|
||||
this.state.showRsvpForm ? s.rsvpFormVisible : null,
|
||||
].join(' ')}
|
||||
>
|
||||
<form method="post" action="/rsvp">
|
||||
<form method="post" action="/rsvp" onSubmit={this.handleFormSubmit}>
|
||||
<div className={[s.formGroup, s.rsvpGroup].join(' ')}>
|
||||
<label className={s.label} htmlFor="code">
|
||||
Enter your RSVP code
|
||||
</label>
|
||||
<input
|
||||
className={s.input}
|
||||
className={[
|
||||
s.input,
|
||||
this.state.inputInvalid ? s.inputInvalid : null,
|
||||
].join(' ')}
|
||||
ref={(input) => { this.rsvpInput = input; }}
|
||||
onFocus={this.handleRsvpFocus}
|
||||
onBlur={this.handleRsvpBlur}
|
||||
id="code"
|
||||
type="text"
|
||||
name="code"
|
||||
@@ -55,6 +102,15 @@ class RsvpButton extends React.Component {
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div
|
||||
className={[
|
||||
s.invalidMsg,
|
||||
this.state.inputInvalidMsg ? s.invalidMsgVisible : null,
|
||||
].join(' ')}
|
||||
role="alert"
|
||||
>
|
||||
{this.state.inputInvalidMsg}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user