Last active
September 27, 2017 14:27
-
-
Save mc-funk/45d796a72e9066a39c7b72619a685ccb to your computer and use it in GitHub Desktop.
Contact Form ideas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// routes/configure.js | |
/* I've been working so long in a react-router app that I'll have to spend more timein the docs | |
* to actually set it up. But here's what I'm used to doing. Please note that we have been using a really | |
* old version of react-router and I'm fully intending to get up to date on the new one. | |
*/ | |
import React from 'react'; | |
import { Route } from 'react-router'; | |
import MenuTabs from './MenuTabs'; | |
import contact from './contact'; | |
export default function configureRoutes(store) { | |
// We're petending that MenuTabs, which whould really be called App or something, contains the nav elements and will render its children. | |
return ( | |
<Route path="" component={MenuTabs} > | |
<Route path="contact" component={contact.ContactContainer} /> | |
</Route> | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import actionTypes from './actionTypes'; | |
const { | |
SUBMIT_CONTACT_ATTEMPT, | |
SUBMIT_CONTACT_FAILED, | |
SUBMIT_CONTACT_SUCCEEDED, | |
} = actionTypes; | |
function submitContactAttempt(values) { | |
return { | |
type: SUBMIT_CONTACT_ATTEMPT, | |
values, | |
}; | |
} | |
function submitContactFailed(error) { | |
return { | |
type: SUBMIT_CONTACT_FAILED, | |
error, | |
}; | |
} | |
function submitContactSucceeded() { | |
return { | |
type: SUBMIT_CONTACT_SUCCEEDED, | |
} | |
} | |
export default { | |
submitContactAttempt, | |
submitContactFailed, | |
submitContactSucceeded, | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const SUBMIT_CONTACT_ATTEMPT = 'SUBMIT_CONTACT_ATTEMPT'; | |
const SUBMIT_CONTACT_FAILED = 'SUBMIT_CONTACT_FAILED'; | |
const SUBMIT_CONTACT_SUCCEEDED = 'SUBMIT_CONTACT_SUCCEEDED'; | |
export default { | |
SUBMIT_CONTACT_ATTEMPT, | |
SUBMIT_CONTACT_FAILED, | |
SUBMIT_CONTACT_SUCCEEDED, | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// api/contact.js | |
const ourHeaders = { | |
// just throwing some things in here, assume there's no auth | |
Accept: 'application/json', | |
'Content-Type': 'application/json', | |
} | |
function handleResponse(response) { | |
if (response.status === 200) { | |
// I'm more used to seeing a 201 in this case | |
// I'm going to assume in this case there is no response object | |
Promise.resolve(); | |
} | |
if (response.status === 422) { | |
/* I'm going to assume that in this case, if there is a 422 there isn't anything that the user can | |
* do about it. I hadn't seen 422s before, so I looked it up and it sounds like this would be a case | |
* where somehow what we sent to the server was correct but had some sort of syntax error. | |
* We're not sending code, so if there's a 422 it seems like the user just needs to try again later, | |
* maybe after we have fixed our bug. :) | |
*/ | |
const error = new Error(response.statusText); | |
Promise.reject(error); | |
} | |
} | |
function postContact(body) { | |
const path='https://ourApi.io/contact'; | |
const jsonBody = JSON.stringify(body); | |
const fetchData = { | |
method: 'POST', | |
body: jsonBody, | |
headers: ourHeaders, | |
} | |
return fetch(path, fetchData).then(handleResponse); | |
} | |
export default { | |
postContact, | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import connect from 'react-redux'; | |
import bindActionCreators from 'redux'; | |
import Paper from 'material-ui/Paper'; | |
import ContactForm from './ContactForm'; | |
import actions from './actions'; | |
import validateForm from './validate'; | |
export class ContactContainer extends React.Component { | |
componentWillMount() { | |
console.log('hey friends!'); | |
} | |
handleSubmit(values) { | |
const { submitContactAttempt } = this.props; | |
const errors = validateForm(values); | |
if (Object.keys(errors).length) return; | |
submitContactAttempt(values); | |
} | |
render() { | |
const { statusMessage } = this.props; | |
// I am so ready to return arrays in React 16 | |
return ( | |
<div> | |
<h1>Contact Us!</h1> | |
<ContactForm /> | |
{statusMessage && | |
<Paper style={{ backgroundColor: '#f00abc'}}> | |
{statusMessage} | |
</Paper> | |
} | |
</div> | |
); | |
} | |
} | |
/* declaring PropTypes this way is actualy deprecated, but I still | |
need to learn the new ways :)*/ | |
ContactContainer.propTypes = { | |
statusMessage: React.PropTypes.string, | |
submitContactAttempt: React.PropTypes.func.isRequired, | |
} | |
export function mapStateToProps(state) { | |
return { | |
postingData: state.contact.postingData, | |
statusMessage: state.contact.statusMessage, | |
} | |
} | |
export function mapDispatchToProps(dispatch) { | |
return bindActionCreators({ | |
submitContactAttempt: actions.submitContactAttempt, | |
}) | |
} | |
export default connect(mapStateToProps, mapDispatchToProps)(ContactContainer); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { reduxForm } from 'redux-form'; | |
import validate from './validate'; | |
// Caution: Really Old Redux-Form | |
function ContactForm({ | |
handleSubmit, | |
disableSubmit, | |
fields: { | |
firstName, | |
lastName, | |
email, | |
phone, | |
comments, | |
} | |
}) { | |
return ( | |
<form id="contactForm" onSubmit={handleSubmit} > | |
<p><strong>First Name</strong><span className="red">*</span></p> | |
<input | |
{...firstName} | |
type="text" | |
/> | |
<p className="red">{firstName.touched && firstName.error}</p> | |
<p><strong>Last Name</strong><span className="red">*</span></p> | |
<input | |
{...lastName} | |
type="text" | |
/> | |
<p className="red">{lastName.touched && lastName.error}</p> | |
<p><strong>Email Address</strong><span className="red">*</span></p> | |
<input | |
{...email} | |
type="text" | |
/> | |
<p className="red">{email.touched && email.error}</p> | |
<p><strong>Phone Number</strong><span className="red">*</span></p> | |
<input | |
{...phone} | |
type="text" | |
/> | |
<p className="red">{phone.touched && phone.error}</p> | |
<p><strong>Comments</strong></p> | |
<input | |
{...comments} | |
type="text" | |
/> | |
<button | |
disabled={!!disableSubmit} | |
onClick={handleSubmit} | |
>Submit</button> | |
</form> | |
) | |
} | |
/* propTypes */ | |
export default reduxForm({ | |
form: 'CONTACT_FORM', | |
fields: [ | |
'firstName', | |
'lastName', | |
'email', | |
'phone', | |
'comments', | |
], | |
validate, | |
})(ContactForm); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import actionTypes from './actionTypes'; | |
const { | |
SUBMIT_CONTACT_ATTEMPT, | |
SUBMIT_CONTACT_FAILED, | |
SUBMIT_CONTACT_SUCCEEDED, | |
} = actionTypes; | |
const initialState = { | |
postingData: false, | |
statusMessage: null, | |
} | |
export default function contact(state = initialState, action) { | |
switch(action.type) { | |
case SUBMIT_CONTACT_ATTEMPT: { | |
return Object.assign({}, state, { | |
postingData: true, | |
}); | |
} | |
case SUBMIT_CONTACT_FAILED: { | |
return Object.assign({}, state, { | |
postingData: false, | |
statusMessage: `Sorry, we couldn't process your information at this time. Please try again later.`, | |
}); | |
} | |
case SUBMIT_CONTACT_SUCCEEDED: { | |
return Object.assign({}, state, { | |
postingData: false, | |
statusMessage: 'Thank you for your message! We will get back to you in the next 48 hours.', | |
}); | |
} | |
default: | |
return state; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { takeLatest } from 'redux-saga'; | |
import { call, put }from 'redux-saga/effects'; | |
import { postContact } from '../api/contact'; | |
import { | |
submitContactFailed, | |
submitContactSucceeded | |
} from './actions'; | |
import { | |
SUBMIT_CONTACT_ATTEMPT, | |
} from './actionTypes'; | |
export function* submitContactSaga({ values }) { | |
try { | |
yield call(postContact, values); | |
yield put(submitContactSucceeded); | |
} catch (e) { | |
yield submitContactFailed(e); | |
} | |
} | |
export function* watchSubmitContactSaga() { | |
yield call(takeLatest, SUBMIT_CONTACT_ATTEMPT, submitContactSaga); | |
} | |
export default [ | |
watchSubmitContactSaga, | |
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// pretend validators use regex.test(string) | |
import isInvalidEmail from '../pretendRegexValidators/isInvalidEmail'; | |
import isInvalidName from '../pretendRegexValidators/isInvalidName'; | |
import isInvalidPhoneNumber from '../pretendRegexValidators/isInvalidPhoneNumber'; | |
export default function contactFormValidator(values) { | |
const errors = {}; | |
const { | |
firstName, | |
lastName, | |
email, | |
phone, | |
} = values; | |
// Really I'd prefer to pull all the undefined checks into a function. Or use validate-this :) | |
if (firstName === undefined) { | |
errors.firstName = `First Name is Required.`; | |
} else if (isInvalidName(firstName)) { | |
errors.firstName = `First Name cannot contain the characters we said it can't`; | |
} | |
if (lastName === undefined) { | |
errors.lastName = `Last Name is Required.`; | |
} else if (isInvalidName(lastName)) { | |
errors.lastName = `Last Name cannot contain the characters we said it can't`; | |
} | |
if (email === undefined) { | |
errors.email = `Email is Required.`; | |
} else if (isInvalidEmail(email)) { | |
errors.email = 'Must be a valid email.'; | |
} | |
if (phone === undefined) { | |
errors.phone = `Phone is Required.`; | |
} else if (isInvalidPhoneNumber(phone)) { | |
errors.phone = 'Must be a valid phone number.'; | |
} | |
return errors; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment