diff --git a/lib/customers.js b/lib/customers.js
index bd410744..b92a110d 100644
--- a/lib/customers.js
+++ b/lib/customers.js
@@ -450,7 +450,7 @@ function batch () {
*
* @returns {array} Array of customers with it's transactions aggregations
*/
-function getCustomersList () {
+function getCustomersList (phone = null, name = null, address = null, id = null) {
const sql = `select id, authorized_override, days_suspended, is_suspended, front_camera_path, front_camera_override,
phone, sms_override, id_card_data, id_card_data_override, id_card_data_expiration,
id_card_photo_path, id_card_photo_override, us_ssn, us_ssn_override, sanctions, sanctions_at,
@@ -474,8 +474,12 @@ function getCustomersList () {
from cash_out_txs where confirmed_at is not null) t on c.id = t.customer_id
where c.id != $1
) as cl where rn = 1
+ and ($3 is null or phone = $3)
+ and ($4 is null or concat(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') = $4)
+ and ($5 is null or id_card_data::json->>'address' = $5)
+ and ($6 is null or id_card_data::json->>'documentNumber' = $6)
limit $2`
- return db.any(sql, [ anonymous.uuid, NUM_RESULTS ])
+ return db.any(sql, [ anonymous.uuid, NUM_RESULTS, phone, name, address, id ])
.then(customers => Promise.all(_.map(customer => {
return populateOverrideUsernames(customer)
.then(camelize)
diff --git a/lib/new-admin/filters.js b/lib/new-admin/filters.js
index 3e9cf658..ce3bb954 100644
--- a/lib/new-admin/filters.js
+++ b/lib/new-admin/filters.js
@@ -27,4 +27,15 @@ function transaction() {
return db.any(sql)
}
-module.exports = { transaction }
+function customer() {
+ const sql = `select distinct * from (
+ select 'phone' as type, phone as value from customers where phone is not null union
+ select 'name' as type, concat(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') as value from customers where concat(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') is not null union
+ select 'address' as type, id_card_data::json->>'address' as value from customers where id_card_data::json->>'address' is not null union
+ select 'id' as type, id_card_data::json->>'documentNumber' as value from customers where id_card_data::json->>'documentNumber' is not null
+ ) f`
+
+ return db.any(sql)
+}
+
+module.exports = { transaction, customer }
diff --git a/lib/new-admin/graphql/resolvers/customer.resolver.js b/lib/new-admin/graphql/resolvers/customer.resolver.js
index ad8cf1b9..f33c3276 100644
--- a/lib/new-admin/graphql/resolvers/customer.resolver.js
+++ b/lib/new-admin/graphql/resolvers/customer.resolver.js
@@ -1,13 +1,15 @@
const anonymous = require('../../../constants').anonymousCustomer
const customers = require('../../../customers')
+const filters = require('../../filters')
const resolvers = {
Customer: {
isAnonymous: parent => (parent.customerId === anonymous.uuid)
},
Query: {
- customers: () => customers.getCustomersList(),
- customer: (...[, { customerId }]) => customers.getCustomerById(customerId)
+ customers: (...[, { phone, name, address, id }]) => customers.getCustomersList(phone, name, address, id),
+ customer: (...[, { customerId }]) => customers.getCustomerById(customerId),
+ customerFilters: () => filters.customer()
},
Mutation: {
setCustomer: (root, { customerId, customerInput }, context, info) => {
diff --git a/lib/new-admin/graphql/types/customer.type.js b/lib/new-admin/graphql/types/customer.type.js
index bfe04a29..8ee9cdeb 100644
--- a/lib/new-admin/graphql/types/customer.type.js
+++ b/lib/new-admin/graphql/types/customer.type.js
@@ -56,8 +56,9 @@ const typeDef = gql`
}
type Query {
- customers: [Customer] @auth
+ customers(phone: String, name: String, address: String, id: String): [Customer] @auth
customer(customerId: ID!): Customer @auth
+ customerFilters: [Filter] @auth
}
type Mutation {
diff --git a/new-lamassu-admin/src/components/layout/TitleSection.js b/new-lamassu-admin/src/components/layout/TitleSection.js
index d778fd19..95c36367 100644
--- a/new-lamassu-admin/src/components/layout/TitleSection.js
+++ b/new-lamassu-admin/src/components/layout/TitleSection.js
@@ -17,13 +17,16 @@ const TitleSection = ({
error,
labels,
button,
- children
+ children,
+ appendix,
+ appendixClassName
}) => {
const classes = useStyles()
return (
{title}
+ {appendix &&
{appendix}
}
{error && (
Failed to save
)}
diff --git a/new-lamassu-admin/src/pages/Customers/Customers.js b/new-lamassu-admin/src/pages/Customers/Customers.js
index 6566fedf..c597bb85 100644
--- a/new-lamassu-admin/src/pages/Customers/Customers.js
+++ b/new-lamassu-admin/src/pages/Customers/Customers.js
@@ -1,12 +1,33 @@
import { useQuery } from '@apollo/react-hooks'
+import { makeStyles } from '@material-ui/core/styles'
import gql from 'graphql-tag'
import * as R from 'ramda'
-import React from 'react'
+import React, { useState } from 'react'
import { useHistory } from 'react-router-dom'
+import Chip from 'src/components/Chip'
+import SearchBox from 'src/components/SearchBox'
+import TitleSection from 'src/components/layout/TitleSection'
+import { P } from 'src/components/typography'
+import baseStyles from 'src/pages/Logs.styles'
+import { ReactComponent as CloseIcon } from 'src/styling/icons/action/close/zodiac.svg'
+import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
+import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
import { fromNamespace, namespaces } from 'src/utils/config'
+import { chipStyles } from '../Transactions/Transactions.styles'
+
import CustomersList from './CustomersList'
+import styles from './CustomersList.styles'
+
+const GET_CUSTOMER_FILTERS = gql`
+ query filters {
+ customerFilters {
+ type
+ value
+ }
+ }
+`
const GET_CUSTOMERS = gql`
{
@@ -28,26 +49,119 @@ const GET_CUSTOMERS = gql`
}
`
+const useStyles = makeStyles(styles)
+const useChipStyles = makeStyles(chipStyles)
+const useBaseStyles = makeStyles(baseStyles)
+
const Customers = () => {
+ const classes = useStyles()
+ const chipClasses = useChipStyles()
+ const baseStyles = useBaseStyles()
const history = useHistory()
- const { data: customersResponse, loading } = useQuery(GET_CUSTOMERS)
const handleCustomerClicked = customer =>
history.push(`/compliance/customer/${customer.id}`)
+ const [filteredCustomers, setFilteredCustomers] = useState([])
+ const [variables, setVariables] = useState({})
+ const [filters, setFilters] = useState([])
+
+ const {
+ data: customersResponse,
+ loading: customerLoading,
+ refetch
+ } = useQuery(GET_CUSTOMERS, {
+ variables,
+ onCompleted: data => setFilteredCustomers(R.path(['customers'])(data))
+ })
+
+ const { data: filtersResponse, loading: loadingFilters } = useQuery(
+ GET_CUSTOMER_FILTERS
+ )
+
const configData = R.path(['config'])(customersResponse) ?? []
const locale = configData && fromNamespace(namespaces.LOCALE, configData)
const customersData = R.sortWith([R.descend(R.prop('lastActive'))])(
- R.path(['customers'])(customersResponse) ?? []
+ filteredCustomers ?? []
)
+ const onFilterChange = filters => {
+ const filtersObject = R.compose(
+ R.mergeAll,
+ R.map(f => ({
+ [f.type]: f.value
+ }))
+ )(filters)
+
+ setFilters(filters)
+
+ setVariables({
+ phone: filtersObject.phone,
+ name: filtersObject.name,
+ address: filtersObject.address,
+ id: filtersObject.id
+ })
+
+ refetch && refetch()
+ }
+
+ const onFilterDelete = filter =>
+ setFilters(
+ R.filter(f => !R.whereEq(R.pick(['type', 'value'], f), filter))(filters)
+ )
+
+ const filterOptions = R.path(['customerFilters'])(filtersResponse)
+
return (
-
+ <>
+
+
+
+ }
+ appendixClassName={baseStyles.buttonsWrapper}
+ labels={[
+ { label: 'Cash-in', icon:
},
+ { label: 'Cash-out', icon:
}
+ ]}
+ />
+ {filters.length > 0 && (
+ <>
+
{'Filters:'}
+
+ {filters.map((f, idx) => (
+ onFilterDelete(f)}
+ deleteIcon={}
+ />
+ ))}
+ setFilters([])}
+ deleteIcon={}
+ />
+
+ >
+ )}
+
+ >
)
}
diff --git a/new-lamassu-admin/src/pages/Customers/CustomersList.js b/new-lamassu-admin/src/pages/Customers/CustomersList.js
index e65efcf1..943aadfe 100644
--- a/new-lamassu-admin/src/pages/Customers/CustomersList.js
+++ b/new-lamassu-admin/src/pages/Customers/CustomersList.js
@@ -4,7 +4,6 @@ import * as R from 'ramda'
import React from 'react'
import { MainStatus } from 'src/components/Status'
-import TitleSection from 'src/components/layout/TitleSection'
import DataTable from 'src/components/tables/DataTable'
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
@@ -74,13 +73,6 @@ const CustomersList = ({ data, locale, onClick, loading }) => {
return (
<>
-
},
- { label: 'Cash-out', icon:
}
- ]}
- />