diff --git a/app/app.global.scss b/app/app.global.scss
index 2fac4bf3..aebe8940 100644
--- a/app/app.global.scss
+++ b/app/app.global.scss
@@ -21,4 +21,17 @@ body {
-webkit-font-smoothing: antialiased;
-webkit-tap-highlight-color: rgba(255,255,255,0);
font-family: 'Roboto';
+}
+
+.ReactModal__Overlay {
+ transition: opacity 500ms ease-in-out;
+ opacity: 0;
+
+ &--after-open {
+ opacity: 1;
+ }
+
+ &--before-close {
+ opacity: 0;
+ }
}
\ No newline at end of file
diff --git a/app/reducers/invoice.js b/app/reducers/invoice.js
index fb92c33f..1aa72630 100644
--- a/app/reducers/invoice.js
+++ b/app/reducers/invoice.js
@@ -1,8 +1,11 @@
+import { createSelector } from 'reselect'
import { callApi } from '../api'
import { btc, usd } from '../utils'
// ------------------------------------
// Constants
// ------------------------------------
+export const SET_INVOICE = 'SET_INVOICE'
+
export const GET_INVOICE = 'GET_INVOICE'
export const RECEIVE_INVOICE = 'RECEIVE_INVOICE'
@@ -17,6 +20,13 @@ export const INVOICE_FAILED = 'INVOICE_FAILED'
// ------------------------------------
// Actions
// ------------------------------------
+export function setInvoice(invoice) {
+ return {
+ type: SET_INVOICE,
+ invoice
+ }
+}
+
export function getInvoice() {
return {
type: GET_INVOICE
@@ -104,6 +114,8 @@ export function invoiceFailed() {
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
+ [SET_INVOICE]: (state, { invoice }) => ({ ...state, invoice }),
+
[GET_INVOICE]: (state) => ({ ...state, invoiceLoading: true }),
[RECEIVE_INVOICE]: (state, { data }) => ({ ...state, invoiceLoading: false, data }),
@@ -115,13 +127,23 @@ const ACTION_HANDLERS = {
[INVOICE_FAILED]: (state) => ({ ...state, invoiceLoading: false, data: null })
}
+const invoiceSelectors = {}
+const modalInvoiceSelector = state => state.invoice.invoice
+
+invoiceSelectors.invoiceModalOpen = createSelector(
+ modalInvoiceSelector,
+ invoice => invoice ? true : false
+)
+
+export { invoiceSelectors }
+
// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
invoiceLoading: false,
invoices: [],
- invoice: {},
+ invoice: null,
data: {}
}
diff --git a/app/reducers/payment.js b/app/reducers/payment.js
index fa2055a9..32c26730 100644
--- a/app/reducers/payment.js
+++ b/app/reducers/payment.js
@@ -1,8 +1,11 @@
+import { createSelector } from 'reselect'
import { callApi } from '../api'
import { btc } from '../utils'
// ------------------------------------
// Constants
// ------------------------------------
+export const SET_PAYMENT = 'SET_PAYMENT'
+
export const GET_PAYMENTS = 'GET_PAYMENTS'
export const RECEIVE_PAYMENTS = 'RECEIVE_PAYMENTS'
@@ -13,6 +16,13 @@ export const PAYMENT_FAILED = 'PAYMENT_FAILED'
// ------------------------------------
// Actions
// ------------------------------------
+export function setPayment(payment) {
+ return {
+ type: SET_PAYMENT,
+ payment
+ }
+}
+
export function getPayments() {
return {
type: GET_PAYMENTS
@@ -76,16 +86,28 @@ export const payInvoice = (payment_request) => async (dispatch) => {
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
+ [SET_PAYMENT]: (state, { payment }) => ({ ...state, payment }),
[GET_PAYMENTS]: (state) => ({ ...state, paymentLoading: true }),
[RECEIVE_PAYMENTS]: (state, { payments }) => ({ ...state, paymentLoading: false, payments })
}
+const paymentSelectors = {}
+const modalPaymentSelector = state => state.payment.payment
+
+paymentSelectors.paymentModalOpen = createSelector(
+ modalPaymentSelector,
+ payment => payment ? true : false
+)
+
+export { paymentSelectors }
+
// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
paymentLoading: false,
- payments: []
+ payments: [],
+ payment: null
}
export default function paymentReducer(state = initialState, action) {
diff --git a/app/reducers/ticker.js b/app/reducers/ticker.js
index 501e1756..64e18d16 100644
--- a/app/reducers/ticker.js
+++ b/app/reducers/ticker.js
@@ -1,3 +1,4 @@
+import { createSelector } from 'reselect'
import { requestTicker } from '../api'
// ------------------------------------
// Constants
@@ -43,7 +44,7 @@ export const fetchTicker = () => async (dispatch) => {
const ACTION_HANDLERS = {
[SET_CURRENCY]: (state, { currency }) => ({ ...state, currency }),
[GET_TICKER]: (state) => ({ ...state, tickerLoading: true }),
- [RECIEVE_TICKER]: (state, { ticker }) => ({...state, btcTicker: ticker[0] })
+ [RECIEVE_TICKER]: (state, { ticker }) => ({...state, tickerLoading: false, btcTicker: ticker[0] })
}
// ------------------------------------
diff --git a/app/routes/activity/components/Activity.js b/app/routes/activity/components/Activity.js
index f4dd163e..12643861 100644
--- a/app/routes/activity/components/Activity.js
+++ b/app/routes/activity/components/Activity.js
@@ -10,7 +10,7 @@ class Activity extends Component {
constructor(props, context) {
super(props, context)
this.state = {
- tab: 1
+ tab: 2
}
}
@@ -25,10 +25,14 @@ class Activity extends Component {
const { tab } = this.state
const {
ticker,
- invoice: { invoices, invoiceLoading },
- payment: { payments, paymentLoading }
+ invoice: { invoice, invoices, invoiceLoading },
+ payment: { payment, payments, paymentLoading },
+ setPayment,
+ setInvoice,
+ paymentModalOpen,
+ invoiceModalOpen
} = this.props
-
+
if (invoiceLoading || paymentLoading) { return
Loading...
}
return (
@@ -62,9 +66,23 @@ class Activity extends Component {
>
{
tab === 1 ?
-
+
:
-
+
}
diff --git a/app/routes/activity/components/components/Invoices.js b/app/routes/activity/components/components/Invoices.js
index 8c4f2a9e..36191b08 100644
--- a/app/routes/activity/components/components/Invoices.js
+++ b/app/routes/activity/components/components/Invoices.js
@@ -2,28 +2,71 @@
import React, { Component } from 'react'
import Moment from 'react-moment'
import 'moment-timezone'
+import { FaBitcoin, FaDollar } from 'react-icons/lib/fa'
+import Modal from './Modal'
import { btc } from '../../../../utils'
import styles from './Invoices.scss'
class Invoices extends Component {
render() {
- const { invoices, ticker } = this.props
+ const {
+ invoice,
+ invoices,
+ ticker,
+ setInvoice,
+ invoiceModalOpen
+ } = this.props
+
return (
-
- -
-
-
-
-
- {
- invoices.map((invoice, index) => (
- -
+
+
+ {
+ invoice ?
+
+
{invoice.memo}
+
{invoice.payment_request}
+
+ {
+ ticker.currency === 'btc' ?
+
+ :
+
+ }
+
+ {
+ ticker.currency === 'btc' ?
+ btc.satoshisToBtc(invoice.value)
+ :
+ btc.satoshisToUsd(invoice.value, ticker.btcTicker.price_usd)
+ }
+
+
+
+ Created on
+
+ {invoice.creation_date * 1000}
+
+
+
+ :
+ null
+ }
+
+
+ -
+
+
+
+
+ {
+ invoices.map((invoice, index) =>
+ - setInvoice(invoice)}>
{`${invoice.payment_request.substring(0, 75)}...`}
@@ -42,11 +85,11 @@ class Invoices extends Component {
)
- )
- }
-
+ }
+
+
)
}
}
-export default Invoices
\ No newline at end of file
+export default Invoices
diff --git a/app/routes/activity/components/components/Invoices.scss b/app/routes/activity/components/components/Invoices.scss
index c7aeaaea..9e8bbf59 100644
--- a/app/routes/activity/components/components/Invoices.scss
+++ b/app/routes/activity/components/components/Invoices.scss
@@ -1,5 +1,44 @@
@import '../../../../variables.scss';
+.invoiceModal {
+ padding: 40px;
+
+ h3 {
+ font-size: 24px;
+ color: $black;
+ font-weight: bold;
+ text-align: center;
+ margin-bottom: 10px;
+ }
+
+ .paymentRequest {
+ text-align: center;
+ font-size: 8px;
+ }
+
+ h1 {
+ text-align: center;
+ color: $main;
+ margin: 60px 30px 60px 0;
+
+ svg {
+ font-size: 30px;
+ }
+
+ .value {
+ font-size: 80px;
+ }
+ }
+
+ .date {
+ text-align: center;
+
+ time {
+ margin-left: 3px;
+ }
+ }
+}
+
.invoices {
width: 75%;
margin: 0 auto;
@@ -41,3 +80,11 @@
font-weight: bold;
}
}
+
+.invoice {
+ cursor: pointer;
+
+ &:hover {
+ background: lighten($grey, 5%);
+ }
+}
diff --git a/app/routes/activity/components/components/Modal.js b/app/routes/activity/components/components/Modal.js
new file mode 100644
index 00000000..a69dfd0b
--- /dev/null
+++ b/app/routes/activity/components/components/Modal.js
@@ -0,0 +1,45 @@
+// @flow
+import React, { Component } from 'react'
+import ReactModal from 'react-modal'
+import Moment from 'react-moment'
+import 'moment-timezone'
+
+const customStyles = {
+ overlay: {
+ cursor: 'pointer'
+ },
+ content : {
+ top: 'auto',
+ left: '20%',
+ right: '0',
+ bottom: 'auto',
+ width: '40%',
+ margin: '50px auto'
+ }
+}
+
+class Modal extends Component {
+ render() {
+ const {
+ isOpen,
+ resetObject,
+ children
+ } = this.props
+
+ return (
+ resetObject(null)}
+ parentSelector={() => document.body}
+ style={customStyles}
+ >
+ {children}
+
+ )
+ }
+}
+
+export default Modal
\ No newline at end of file
diff --git a/app/routes/activity/components/components/Payments.js b/app/routes/activity/components/components/Payments.js
index 3e7bc8f1..e1539a8a 100644
--- a/app/routes/activity/components/components/Payments.js
+++ b/app/routes/activity/components/components/Payments.js
@@ -2,65 +2,112 @@
import React, { Component } from 'react'
import Moment from 'react-moment'
import 'moment-timezone'
+import { FaBitcoin, FaDollar } from 'react-icons/lib/fa'
+import Modal from './Modal'
import { btc } from '../../../../utils'
import styles from './Payments.scss'
class Payments extends Component {
render() {
- const { payments, ticker } = this.props
+ const {
+ payment,
+ payments,
+ ticker,
+ setPayment,
+ paymentModalOpen
+ } = this.props
+
return (
-
- -
-
-
-
-
-
- {
- payments.map((payment, index) =>
- -
-
-
{payment.path[0]}
+
+
+ {
+ payment ?
+
+
{payment.payment_hash}
+
+ {
+ ticker.currency === 'btc' ?
+
+ :
+
+ }
+
+ {
+ ticker.currency === 'btc' ?
+ btc.satoshisToBtc(payment.value)
+ :
+ btc.satoshisToUsd(payment.value, ticker.btcTicker.price_usd)
+ }
+
+
+
+ - Fee
+ - {payment.fee}
+ - Date
+ -
+
+ {payment.creation_date * 1000}
+
+
-
-
-
{payment.creation_date * 1000}
+ :
+ null
+ }
+
+
+
+ -
+
+
+
+
+
+ {
+ payments.map((payment, index) =>
+ - setPayment(payment)}>
+
-
-
-
- {
- ticker.currency === 'btc' ?
- btc.satoshisToBtc(payment.fee)
- :
- btc.satoshisToUsd(payment.fee, ticker.btcTicker.price_usd)
- }
-
-
-
-
+
+
+ {payment.creation_date * 1000}
+
+
+
+
{
ticker.currency === 'btc' ?
- btc.satoshisToBtc(payment.value)
+ btc.satoshisToBtc(payment.fee)
:
- btc.satoshisToUsd(payment.value, ticker.btcTicker.price_usd)
+ btc.satoshisToUsd(payment.fee, ticker.btcTicker.price_usd)
}
-
-
-
- )
- }
-
+
+
+
+
+ {
+ ticker.currency === 'btc' ?
+ btc.satoshisToBtc(payment.value)
+ :
+ btc.satoshisToUsd(payment.value, ticker.btcTicker.price_usd)
+ }
+
+
+
+ )
+ }
+
+
)
}
}
-export default Payments
\ No newline at end of file
+export default Payments
diff --git a/app/routes/activity/components/components/Payments.scss b/app/routes/activity/components/components/Payments.scss
index d20aa96c..ff906cb1 100644
--- a/app/routes/activity/components/components/Payments.scss
+++ b/app/routes/activity/components/components/Payments.scss
@@ -1,5 +1,48 @@
@import '../../../../variables.scss';
+.paymentModal {
+ padding: 40px;
+
+ h1 {
+ text-align: center;
+ color: $main;
+ margin: 60px 30px 60px 0;
+
+ svg {
+ font-size: 30px;
+ }
+
+ .value {
+ font-size: 80px;
+ }
+ }
+
+ h3 {
+ font-size: 14px;
+ text-align: center;
+ color: $black;
+ font-weight: bold;
+ }
+
+ dt {
+ text-align: left;
+ float: left;
+ clear: left;
+ font-weight: 500;
+ padding: 20px 35px 19px 0;
+ color: $black;
+ font-weight: bold;
+ }
+
+ dd {
+ text-align: right;
+ font-weight: 400;
+ padding: 19px 0;
+ margin-left: 0;
+ border-top: 1px solid $darkgrey;
+ }
+}
+
.payments {
width: 75%;
margin: 0 auto;
diff --git a/app/routes/activity/containers/ActivityContainer.js b/app/routes/activity/containers/ActivityContainer.js
index f3feac7e..88efd907 100644
--- a/app/routes/activity/containers/ActivityContainer.js
+++ b/app/routes/activity/containers/ActivityContainer.js
@@ -1,9 +1,11 @@
import { connect } from 'react-redux'
-import { fetchInvoices } from '../../../reducers/invoice'
-import { fetchPayments } from '../../../reducers/payment'
+import { fetchInvoices, setInvoice, invoiceSelectors } from '../../../reducers/invoice'
+import { setPayment, fetchPayments, paymentSelectors } from '../../../reducers/payment'
import Activity from '../components/Activity'
const mapDispatchToProps = {
+ setPayment,
+ setInvoice,
fetchPayments,
fetchInvoices
}
@@ -12,7 +14,9 @@ const mapStateToProps = (state) => ({
activity: state.activity,
payment: state.payment,
invoice: state.invoice,
- ticker: state.ticker
+ ticker: state.ticker,
+ paymentModalOpen: paymentSelectors.paymentModalOpen(state),
+ invoiceModalOpen: invoiceSelectors.invoiceModalOpen(state)
})
export default connect(mapStateToProps, mapDispatchToProps)(Activity)
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 20f53f20..566cc3bf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12988,6 +12988,11 @@
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
"dev": true
},
+ "reselect": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-3.0.1.tgz",
+ "integrity": "sha1-79qpjqdFEyTQkrKyFjpqHXqaIUc="
+ },
"resolve": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz",
diff --git a/package.json b/package.json
index 9b0c1e1f..55ff2e8d 100644
--- a/package.json
+++ b/package.json
@@ -203,6 +203,7 @@
"react-svg": "^2.1.21",
"redux": "^3.7.1",
"redux-thunk": "^2.2.0",
+ "reselect": "^3.0.1",
"satoshi-bitcoin": "^1.0.4",
"source-map-support": "^0.4.15"
},