-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(addresscapture): container for AddressForm & AddressReview
- Loading branch information
Showing
6 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
113 changes: 113 additions & 0 deletions
113
package/src/components/AddressCapture/v1/AddressCapture.js
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import React, { Component } from "react"; | ||
import PropTypes from "prop-types"; | ||
import { withComponents } from "@reactioncommerce/components-context"; | ||
import { CustomPropTypes } from "../../../utils"; | ||
|
||
class AddressCapture extends Component { | ||
static propTypes = { | ||
addressFormProps: PropTypes.shape({ | ||
addressNamePlaceholder: PropTypes.string, | ||
shouldShowAddressNameField: PropTypes.bool, | ||
shouldShowIsCommercialField: PropTypes.bool, | ||
value: CustomPropTypes.address | ||
}), | ||
addressReviewProps: PropTypes.shape({ | ||
addressEntered: CustomPropTypes.address, | ||
addressSuggestion: CustomPropTypes.address, | ||
value: PropTypes.string | ||
}), | ||
/** | ||
* You can provide a `className` prop that will be applied to the outermost DOM element | ||
* rendered by this component. We do not recommend using this for styling purposes, but | ||
* it can be useful as a selector in some situations. | ||
*/ | ||
className: PropTypes.string, | ||
/** | ||
* If you've set up a components context using | ||
* [@reactioncommerce/components-context](https://github.com/reactioncommerce/components-context) | ||
* (recommended), then this prop will come from there automatically. If you have not | ||
* set up a components context or you want to override one of the components in a | ||
* single spot, you can pass in the components prop directly. | ||
*/ | ||
components: PropTypes.shape({ | ||
/** | ||
* Pass either the Reaction AddressForm component or your own component that is | ||
* compatible with the AddressForm spec. | ||
*/ | ||
AddressForm: CustomPropTypes.component.isRequired, | ||
/** | ||
* Pass either the Reaction AddressReview component or your own component that is | ||
* compatible with AddressReview spec. | ||
*/ | ||
AddressReview: CustomPropTypes.component.isRequired | ||
}).isRequired, | ||
isSaving: PropTypes.bool, | ||
name: PropTypes.string, | ||
onAddressValidation: PropTypes.func, | ||
onSubmit: PropTypes.func | ||
}; | ||
|
||
static defaultProps = { | ||
addressFormProps: {}, | ||
addressReviewProps: { | ||
addressSuggestion: null | ||
}, | ||
isSaving: false | ||
}; | ||
|
||
_form = null; | ||
|
||
/** | ||
* | ||
* @name submit | ||
* @summary Instance method that submits the form, this allows a parent component access to the Form submit event. | ||
* @return {Undefined} - Nothing | ||
*/ | ||
submit = () => { | ||
this._form.submit(); | ||
}; | ||
|
||
handleSubmit = async (address) => { | ||
const { onAddressValidation, onSubmit } = this.props; | ||
if (onAddressValidation && !address.isValid) { | ||
await onAddressValidation(address); | ||
} else { | ||
await onSubmit(address); | ||
} | ||
}; | ||
|
||
renderForm() { | ||
const { addressFormProps, components: { AddressForm }, isSaving } = this.props; | ||
return ( | ||
<AddressForm | ||
{...addressFormProps} | ||
ref={(el) => { | ||
this._form = el; | ||
}} | ||
isSaving={isSaving} | ||
onSubmit={this.handleSubmit} | ||
/> | ||
); | ||
} | ||
|
||
renderReview() { | ||
const { addressReviewProps, components: { AddressReview }, isSaving } = this.props; | ||
return ( | ||
<AddressReview | ||
{...addressReviewProps} | ||
ref={(el) => { | ||
this._form = el; | ||
}} | ||
isSaving={isSaving} | ||
onSubmit={this.handleSubmit} | ||
/> | ||
); | ||
} | ||
|
||
render() { | ||
const { addressReviewProps: { addressSuggestion }, className } = this.props; | ||
return <div className={className}>{addressSuggestion ? this.renderReview() : this.renderForm()}</div>; | ||
} | ||
} | ||
|
||
export default withComponents(AddressCapture); |
141 changes: 141 additions & 0 deletions
141
package/src/components/AddressCapture/v1/AddressCapture.md
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
### Overview | ||
|
||
### Usage | ||
|
||
#### Add an address | ||
```jsx | ||
initialState = { isProcessing: false, savedAddress: null }; | ||
let _form = null; | ||
|
||
const handleSubmit = (value) => new Promise((resolve, reject) => { | ||
setState({ isProcessing: true }); | ||
setTimeout(async () => { | ||
console.log("Address saved", value); | ||
setState({ isProcessing: false, savedAddress: value }); | ||
resolve(value) | ||
}, 2000); | ||
}); | ||
|
||
const props = { | ||
addressFormProps: { | ||
shouldShowIsCommercialField: true, | ||
value: state.savedAddress | ||
}, | ||
name: "example", | ||
onSubmit: handleSubmit | ||
}; | ||
|
||
state.savedAddress ? <Address address={state.savedAddress} /> : <div> | ||
<AddressCapture {...props} ref={(formEl) => { _form = formEl; }} /> | ||
<Button onClick={() => { _form.submit() }} isWaiting={state.isProcessing}>Capture</Button> | ||
</div> | ||
``` | ||
|
||
#### Edit an address | ||
```jsx | ||
initialState = { | ||
isProcessing: false, | ||
updatedAddress: null, | ||
savedAddress: { | ||
address1: "2110 Main Street", | ||
address2: "Suite 207", | ||
country: "US", | ||
city: "Santa Monica", | ||
fullName: "Reaction Commerce, Inc.", | ||
postal: "90405", | ||
region: "CA", | ||
phone: "123-123-1234", | ||
isCommercial: true | ||
} | ||
}; | ||
let _form = null; | ||
|
||
const handleSubmit = (value) => new Promise((resolve, reject) => { | ||
setState({ isProcessing: true }); | ||
setTimeout(async () => { | ||
console.log("Address saved", value); | ||
setState({ isProcessing: false, updatedAddress: value }); | ||
resolve(value) | ||
}, 2000); | ||
}); | ||
|
||
const props = { | ||
addressFormProps: { | ||
shouldShowIsCommercialField: true, | ||
value: state.updatedAddress || state.savedAddress | ||
}, | ||
name: "example", | ||
onSubmit: handleSubmit | ||
}; | ||
|
||
console.log("whats the saved address", state.savedAddress); | ||
|
||
state.updatedAddress ? <Address address={state.updatedAddress} /> : <div> | ||
<AddressCapture {...props} ref={(formEl) => { _form = formEl; }} /> | ||
<Button onClick={() => { _form.submit() }} isWaiting={state.isProcessing}>Edit</Button> | ||
</div> | ||
``` | ||
|
||
#### Validate an address | ||
```jsx | ||
initialState = { isProcessing: false, savedAddress: null, submittedAddress: null, validationResults: null }; | ||
let _form = null; | ||
|
||
const handleSubmit = (value) => new Promise((resolve, reject) => { | ||
setState({ isProcessing: true }); | ||
setTimeout(async () => { | ||
console.log("Address saved", value); | ||
setState({ isProcessing: false, savedAddress: value }); | ||
resolve(value) | ||
}, 2000); | ||
}); | ||
|
||
const handleAddressValidation = (value) => new Promise((resolve, reject) => { | ||
setState({ isProcessing: true, submittedAddress: value }); | ||
setTimeout(async () => { | ||
console.log("Address validated", value); | ||
const validationResults = { | ||
suggestedAddresses: [{ | ||
...value, | ||
address1: "Corrected " + value.address1, | ||
postal: "90210", | ||
isValid: true | ||
}], | ||
validationErrors: [{ | ||
summary: "Address Not Found", | ||
details: "The address as submitted could not be found. Please check for excessive abbreviations in " + | ||
"the street address line or in the City name.", | ||
source: "USPS", | ||
type: "error" | ||
}] | ||
}; | ||
setState({ isProcessing: false, validationResults }); | ||
resolve(value); | ||
}, 2000); | ||
}); | ||
|
||
const props = { | ||
addressFormProps: { | ||
shouldShowIsCommercialField: true, | ||
value: state.submittedAddress | ||
}, | ||
addressReviewProps: { | ||
addressEntered: state.submittedAddress, | ||
addressSuggestion: state.validationResults && state.validationResults.suggestedAddresses[0] || null | ||
}, | ||
name: "example", | ||
onSubmit: handleSubmit, | ||
onAddressValidation: handleAddressValidation | ||
}; | ||
|
||
state.savedAddress ? <Address address={state.savedAddress} /> : <div> | ||
<AddressCapture {...props} ref={(formEl) => { _form = formEl; }} /> | ||
<Button onClick={() => { _form.submit() }} isWaiting={state.isProcessing}>{state.validationResults ? "Capture" : "Validate"}</Button> | ||
</div> | ||
``` | ||
|
||
### Theme | ||
|
||
Assume that any theme prop that does not begin with "rui" is within `rui_components`. See [Theming Components](./#!/Theming%20Components). | ||
|
||
| Theme Prop | Default | Description | |
11 changes: 11 additions & 0 deletions
11
package/src/components/AddressCapture/v1/AddressCapture.test.js
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import React from "react"; | ||
import renderer from "react-test-renderer"; | ||
import mockComponents from "../../../tests/mockComponents"; | ||
import AddressCapture from "./AddressCapture"; | ||
|
||
test("basic snapshot", () => { | ||
const component = renderer.create(<AddressCapture components={mockComponents} />); | ||
|
||
const tree = component.toJSON(); | ||
expect(tree).toMatchSnapshot(); | ||
}); |
9 changes: 9 additions & 0 deletions
9
package/src/components/AddressCapture/v1/__snapshots__/AddressCapture.test.js.snap
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`basic snapshot 1`] = ` | ||
<div | ||
className={undefined} | ||
> | ||
AddressForm(undefined) | ||
</div> | ||
`; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from "./AddressCapture"; |
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