Jack Mallers
7 years ago
12 changed files with 472 additions and 9 deletions
@ -0,0 +1,61 @@ |
|||||
|
import React from 'react' |
||||
|
import PropTypes from 'prop-types' |
||||
|
import ReactModal from 'react-modal' |
||||
|
|
||||
|
import StepOne from './StepOne' |
||||
|
import Footer from './Footer' |
||||
|
|
||||
|
import styles from './ChannelForm.scss' |
||||
|
|
||||
|
const ChannelForm = ({ |
||||
|
channelform, |
||||
|
closeChannelForm, |
||||
|
changeStep, |
||||
|
setNodeKey, |
||||
|
channelFormHeader, |
||||
|
channelFormProgress, |
||||
|
peers |
||||
|
}) => { |
||||
|
const renderStep = () => { |
||||
|
const { step } = channelform |
||||
|
console.log('setNodeKey: ', setNodeKey) |
||||
|
|
||||
|
switch (step) { |
||||
|
case 1: |
||||
|
return <StepOne peers={peers} changeStep={changeStep} setNodeKey={setNodeKey} /> |
||||
|
case 2: |
||||
|
return 'Step Two' |
||||
|
case 3: |
||||
|
return 'Step 3' |
||||
|
default: |
||||
|
return 'Confirm Step' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<ReactModal |
||||
|
isOpen={channelform.isOpen} |
||||
|
ariaHideApp |
||||
|
shouldCloseOnOverlayClick |
||||
|
contentLabel='No Overlay Click Modal' |
||||
|
onRequestClose={closeChannelForm} |
||||
|
parentSelector={() => document.body} |
||||
|
className={styles.modal} |
||||
|
> |
||||
|
<header className={styles.header}> |
||||
|
<h3>{channelFormHeader}</h3> |
||||
|
<div className={styles.progress} style={{ width: `${channelFormProgress}%` }}></div> |
||||
|
</header> |
||||
|
|
||||
|
<div className={styles.content}> |
||||
|
{renderStep()} |
||||
|
</div> |
||||
|
|
||||
|
<Footer step={channelform.step} /> |
||||
|
</ReactModal> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
ChannelForm.propTypes = {} |
||||
|
|
||||
|
export default ChannelForm |
@ -0,0 +1,36 @@ |
|||||
|
@import '../../variables.scss'; |
||||
|
|
||||
|
.modal { |
||||
|
width: 40%; |
||||
|
min-height: 500px; |
||||
|
margin: 50px auto; |
||||
|
position: absolute; |
||||
|
top: auto; |
||||
|
left: 20%; |
||||
|
right: 0; |
||||
|
bottom: auto; |
||||
|
background: $white; |
||||
|
outline: none; |
||||
|
z-index: -2; |
||||
|
border: 1px solid $darkgrey; |
||||
|
} |
||||
|
|
||||
|
.header { |
||||
|
padding: 20px; |
||||
|
background: $lightgrey; |
||||
|
text-align: center; |
||||
|
font-family: 'Jigsaw Light'; |
||||
|
text-transform: uppercase; |
||||
|
position: relative; |
||||
|
z-index: -2; |
||||
|
} |
||||
|
|
||||
|
.progress { |
||||
|
transition: all 0.2s ease; |
||||
|
background: $main; |
||||
|
position: absolute; |
||||
|
height: 100%; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
z-index: -1; |
||||
|
} |
@ -0,0 +1,27 @@ |
|||||
|
import React from 'react' |
||||
|
import PropTypes from 'prop-types' |
||||
|
import { FaArrowLeft, FaArrowRight } from 'react-icons/lib/fa' |
||||
|
import styles from './Footer.scss' |
||||
|
|
||||
|
const Footer = ({ step }) => { |
||||
|
if ( step === 1 ) { return null } |
||||
|
|
||||
|
return ( |
||||
|
<div className={styles.footer}> |
||||
|
<div className='buttonContainer circleContainer'> |
||||
|
<div className='buttonPrimary circle'> |
||||
|
<FaArrowLeft /> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div className='buttonContainer circleContainer'> |
||||
|
<div className='buttonPrimary circle'> |
||||
|
<FaArrowRight /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
Footer.propTypes = {} |
||||
|
|
||||
|
export default Footer |
@ -0,0 +1,8 @@ |
|||||
|
.footer { |
||||
|
text-align: center; |
||||
|
padding-bottom: 30px; |
||||
|
|
||||
|
div { |
||||
|
margin: 0 5px; |
||||
|
} |
||||
|
} |
@ -0,0 +1,48 @@ |
|||||
|
import React from 'react' |
||||
|
import PropTypes from 'prop-types' |
||||
|
import { MdSearch } from 'react-icons/lib/md' |
||||
|
import styles from './StepOne.scss' |
||||
|
|
||||
|
const StepOne = ({ peers, changeStep, setNodeKey }) => { |
||||
|
const peerClicked = (peer) => { |
||||
|
setNodeKey(peer.pub_key) |
||||
|
changeStep(2) |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<div className={styles.search}> |
||||
|
<label className={`${styles.label} ${styles.input}`} htmlFor='peersSearch'> |
||||
|
<MdSearch /> |
||||
|
</label> |
||||
|
<input |
||||
|
value={''} |
||||
|
onChange={event => console.log('event: ', event)} |
||||
|
className={`${styles.text} ${styles.input}`} |
||||
|
placeholder='Search your peers by their public key' |
||||
|
type='text' |
||||
|
id='peersSearch' |
||||
|
/> |
||||
|
</div> |
||||
|
|
||||
|
<ul className={styles.peers}> |
||||
|
{peers.length && |
||||
|
peers.map(peer => ( |
||||
|
<li |
||||
|
key={peer.peer_id} |
||||
|
className={styles.peer} |
||||
|
onClick={() => peerClicked(peer)} |
||||
|
> |
||||
|
<h4>{peer.address}</h4> |
||||
|
<h1>{peer.pub_key}</h1> |
||||
|
</li> |
||||
|
) |
||||
|
)} |
||||
|
</ul> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
StepOne.propTypes = {} |
||||
|
|
||||
|
export default StepOne |
@ -0,0 +1,76 @@ |
|||||
|
@import '../../variables.scss'; |
||||
|
|
||||
|
.peers { |
||||
|
// margin-bottom: 50px; |
||||
|
|
||||
|
h2 { |
||||
|
text-transform: uppercase; |
||||
|
font-weight: 200; |
||||
|
padding: 10px 0; |
||||
|
border-bottom: 1px solid $grey; |
||||
|
color: $darkestgrey; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.search { |
||||
|
height: 50px; |
||||
|
padding: 2px; |
||||
|
border-bottom: 1px solid $darkgrey; |
||||
|
|
||||
|
.input { |
||||
|
display: inline-block; |
||||
|
vertical-align: top; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
.label { |
||||
|
width: 5%; |
||||
|
line-height: 50px; |
||||
|
font-size: 16px; |
||||
|
text-align: center; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.text { |
||||
|
width: 95%; |
||||
|
outline: 0; |
||||
|
padding: 0; |
||||
|
border: 0; |
||||
|
border-radius: 0; |
||||
|
height: 50px; |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.peer { |
||||
|
position: relative; |
||||
|
background: $white; |
||||
|
padding: 10px; |
||||
|
border-top: 1px solid $grey; |
||||
|
cursor: pointer; |
||||
|
transition: all 0.25s; |
||||
|
|
||||
|
&:hover { |
||||
|
opacity: 0.5; |
||||
|
} |
||||
|
|
||||
|
&:first-child { |
||||
|
border: none; |
||||
|
} |
||||
|
|
||||
|
h4, h1 { |
||||
|
margin: 10px 0; |
||||
|
} |
||||
|
|
||||
|
h4 { |
||||
|
font-size: 12px; |
||||
|
font-weight: bold; |
||||
|
color: $black; |
||||
|
} |
||||
|
|
||||
|
h1 { |
||||
|
font-size: 14px; |
||||
|
font-weight: 200; |
||||
|
color: $main; |
||||
|
} |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
import ChannelForm from './ChannelForm' |
||||
|
|
||||
|
export default ChannelForm |
@ -0,0 +1,106 @@ |
|||||
|
import { createSelector } from 'reselect' |
||||
|
|
||||
|
// Initial State
|
||||
|
const initialState = { |
||||
|
isOpen: false, |
||||
|
node_key: '', |
||||
|
local_amt: '', |
||||
|
push_amt: '', |
||||
|
|
||||
|
step: 1 |
||||
|
} |
||||
|
|
||||
|
// Constants
|
||||
|
// ------------------------------------
|
||||
|
export const OPEN_CHANNEL_FORM = 'OPEN_CHANNEL_FORM' |
||||
|
export const CLOSE_CHANNEL_FORM = 'CLOSE_CHANNEL_FORM' |
||||
|
|
||||
|
export const SET_NODE_KEY = 'SET_NODE_KEY' |
||||
|
|
||||
|
export const CHANGE_STEP = 'CHANGE_STEP' |
||||
|
|
||||
|
export const RESET_CHANNEL_FORM = 'RESET_CHANNEL_FORM' |
||||
|
|
||||
|
// ------------------------------------
|
||||
|
// Actions
|
||||
|
// ------------------------------------
|
||||
|
export function openChannelForm() { |
||||
|
return { |
||||
|
type: OPEN_CHANNEL_FORM |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export function closeChannelForm() { |
||||
|
return { |
||||
|
type: CLOSE_CHANNEL_FORM |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export function setNodeKey(node_key) { |
||||
|
return { |
||||
|
type: SET_NODE_KEY, |
||||
|
node_key |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export function changeStep(step) { |
||||
|
return { |
||||
|
type: CHANGE_STEP, |
||||
|
step |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export function resetChannelForm() { |
||||
|
return { |
||||
|
type: RESET_CHANNEL_FORM |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// ------------------------------------
|
||||
|
// Action Handlers
|
||||
|
// ------------------------------------
|
||||
|
const ACTION_HANDLERS = { |
||||
|
[OPEN_CHANNEL_FORM]: state => ({ ...state, isOpen: true }), |
||||
|
[CLOSE_CHANNEL_FORM]: state => ({ ...state, isOpen: false }), |
||||
|
|
||||
|
[SET_NODE_KEY]: (state, { node_key }) => ({ ...state, node_key }), |
||||
|
|
||||
|
[CHANGE_STEP]: (state, { step }) => ({ ...state, step }), |
||||
|
|
||||
|
[RESET_CHANNEL_FORM]: () => (initialState) |
||||
|
} |
||||
|
|
||||
|
const channelFormSelectors = {} |
||||
|
const channelFormStepSelector = state => state.channelform.step |
||||
|
|
||||
|
channelFormSelectors.channelFormHeader = createSelector( |
||||
|
channelFormStepSelector, |
||||
|
step => { |
||||
|
switch (step) { |
||||
|
case 1: |
||||
|
return 'Choose a peer' |
||||
|
case 2: |
||||
|
return 'Choose your local amount' |
||||
|
case 3: |
||||
|
return 'Choose your push amount' |
||||
|
default: |
||||
|
return 'Confirm' |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
channelFormSelectors.channelFormProgress = createSelector( |
||||
|
channelFormStepSelector, |
||||
|
step => (step / 4) * 100 |
||||
|
) |
||||
|
|
||||
|
export { channelFormSelectors } |
||||
|
|
||||
|
// ------------------------------------
|
||||
|
// Reducer
|
||||
|
// ------------------------------------
|
||||
|
export default function channelFormReducer(state = initialState, action) { |
||||
|
const handler = ACTION_HANDLERS[action.type] |
||||
|
|
||||
|
return handler ? handler(state, action) : state |
||||
|
} |
Loading…
Reference in new issue