diff --git a/.eslintcache b/.eslintcache new file mode 100644 index 0000000..0e35028 --- /dev/null +++ b/.eslintcache @@ -0,0 +1 @@ +[{"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\index.js":"1","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\reportWebVitals.js":"2","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\App.js":"3","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\ButtonAppBar.js":"4","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\stores\\clientsStore.js":"5","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\Analytics.js":"6","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\TopEmployeeChart.js":"7","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\ClientPie.js":"8","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\SalesSince.js":"9","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\SalesSortedBy.js":"10","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\Badges.js":"11","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\Badge.js":"12","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Actions\\Actions.js":"13","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Actions\\AddClient.js":"14","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Actions\\UpdateClient.js":"15","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Clients\\Clients.js":"16","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Clients\\UpdatePopover.js":"17"},{"size":594,"mtime":1610576289369,"results":"18","hashOfConfig":"19"},{"size":375,"mtime":1610576289372,"results":"20","hashOfConfig":"19"},{"size":707,"mtime":1610576289234,"results":"21","hashOfConfig":"19"},{"size":1107,"mtime":1610576289324,"results":"22","hashOfConfig":"19"},{"size":5722,"mtime":1610576289379,"results":"23","hashOfConfig":"19"},{"size":872,"mtime":1610576289265,"results":"24","hashOfConfig":"19"},{"size":853,"mtime":1610576289321,"results":"25","hashOfConfig":"19"},{"size":593,"mtime":1610576289313,"results":"26","hashOfConfig":"19"},{"size":1282,"mtime":1610576289316,"results":"27","hashOfConfig":"19"},{"size":1910,"mtime":1610643859479,"results":"28","hashOfConfig":"19"},{"size":617,"mtime":1610576289271,"results":"29","hashOfConfig":"19"},{"size":798,"mtime":1610576289268,"results":"30","hashOfConfig":"19"},{"size":293,"mtime":1610576289254,"results":"31","hashOfConfig":"19"},{"size":2852,"mtime":1610643656494,"results":"32","hashOfConfig":"19"},{"size":4031,"mtime":1610643461001,"results":"33","hashOfConfig":"19"},{"size":3545,"mtime":1610641187927,"results":"34","hashOfConfig":"19"},{"size":3067,"mtime":1610640799501,"results":"35","hashOfConfig":"19"},{"filePath":"36","messages":"37","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},"13s5xby",{"filePath":"39","messages":"40","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"41","messages":"42","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"43","messages":"44","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"45","usedDeprecatedRules":"38"},{"filePath":"46","messages":"47","errorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":"48","usedDeprecatedRules":"38"},{"filePath":"49","messages":"50","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"51","messages":"52","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"53","messages":"54","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"55","messages":"56","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"57","messages":"58","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"59","messages":"60","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"61","messages":"62","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"63"},{"filePath":"64","messages":"65","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"66","messages":"67","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"68","messages":"69","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"70","messages":"71","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"38"},{"filePath":"72","messages":"73","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"74","usedDeprecatedRules":"38"},"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\index.js",[],["75","76"],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\reportWebVitals.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\App.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\ButtonAppBar.js",["77"],"import React, {useState, useEffect} from 'react';\r\nimport { useHistory } from \"react-router-dom\";\r\nimport {AppBar,Tabs, Tab} from '@material-ui/core';\r\nimport { makeStyles } from '@material-ui/core/styles';\r\n\r\nconst useStyles = makeStyles((theme) => ({\r\n root: {\r\n flexGrow: 1,\r\n },\r\n}));\r\n\r\nexport default function ButtonAppBar() {\r\n const classes = useStyles();\r\n const [tab, setTab] = useState(0)\r\n const history = useHistory();\r\n\r\n const handleClick = (event) => {\r\n const tabID = parseInt(event.target.id || event.target.parentElement.id)\r\n setTab(tabID)\r\n }\r\n\r\n useEffect(() => {\r\n const route = tab === 0 ? \"/clients\" : (tab === 1 ? \"/actions\" : \"/analytics\")\r\n history.length < 3 ? history.push(route): history.replace(route)\r\n }, [tab])\r\n \r\n return ( \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n );\r\n}\r\n","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\stores\\clientsStore.js",["78","79","80","81","82","83"],"import { makeObservable, observable, action} from 'mobx'\r\nimport moment from 'moment'\r\nimport axios from 'axios'\r\n\r\n\r\nexport class ClientsStore {\r\n constructor() {\r\n this.getData()\r\n this.getAnalytics()\r\n this.clients = []\r\n this.owners = []\r\n this.countries = []\r\n this.emailTypes = []\r\n this.groupOwner = []\r\n this.groupCountry = []\r\n this.groupEmail = []\r\n this.groupMonth = []\r\n\r\n makeObservable(this, {\r\n clients: observable,\r\n owners: observable,\r\n countries: observable,\r\n emailTypes: observable,\r\n getData: action,\r\n getClients: action,\r\n getAnalytics: action,\r\n updateClient: action,\r\n addClient: action,\r\n findClient: action,\r\n TransferOwnership: action,\r\n declareSale: action,\r\n sendEmail: action,\r\n })\r\n }\r\n\r\n async getData(){\r\n try {\r\n const dbResults = (await axios.get(\"http://localhost:4200/dbData\")).data\r\n this.clients = dbResults[3]\r\n this.owners = dbResults[0]\r\n this.countries = dbResults[1]\r\n this.emailTypes = dbResults[2]\r\n } catch (error) {\r\n console.log(error.toString())\r\n }\r\n }\r\n\r\n async getClients(){\r\n try {\r\n this.clients = (await axios.get(\"http://localhost:4200/clientsData\")).data\r\n await this.getAnalytics()\r\n } catch (error) {\r\n console.log(error.toString())\r\n }\r\n }\r\n\r\n async getAnalytics(){\r\n try {\r\n const results = (await axios.get(\"http://localhost:4200/categorizedData\")).data\r\n this.groupCountry = this.reduceResults(results[0])\r\n this.groupEmail = this.reduceResults(results[1])\r\n this.groupMonth = this.reduceResults(results[2])\r\n this.groupOwner = this.reduceResults(results[3])\r\n } catch (error) {\r\n console.log(error.toString())\r\n }\r\n }\r\n\r\n async updateClient(id, first, last, countryId){ \r\n try {\r\n const result = await axios.put(\"http://localhost:4200/client\", {first, last, country_id: countryId, id})\r\n await this.getClients()\r\n return `${first} ${last} was updated`\r\n } catch (error) {\r\n return error\r\n }\r\n }\r\n\r\n async addClient(first, last, country, owner){\r\n try {\r\n const date = new Date().toLocaleDateString()\r\n const client = {first, last, country, owner, date}\r\n const id = (await axios.post(\"http://localhost:4200/client\" , client)).data\r\n await this.getClients()\r\n return `${first} ${last} was added`\r\n } catch (error) {\r\n return error\r\n }\r\n }\r\n\r\n findClient(id){\r\n return this.clients.find(c => c.id === id)\r\n }\r\n\r\n async TransferOwnership(id, owner_id, owner){\r\n try {\r\n const result = await axios.put(\"http://localhost:4200/client\", {id, owner_id})\r\n await this.getClients()\r\n return `The client ownership was transferred to ${owner}`\r\n } catch (error) {\r\n return error\r\n }\r\n }\r\n\r\n async declareSale(id){\r\n try {\r\n const result = await axios.put(\"http://localhost:4200/client\", {id, sold: '1' })\r\n await this.getClients()\r\n return 'The action was done successfully '\r\n } catch (error) {\r\n return error\r\n }\r\n }\r\n\r\n async sendEmail(id, email_type_id){\r\n try {\r\n const result = await axios.put(\"http://localhost:4200/client\", {id, email_type_id})\r\n await this.getClients()\r\n return 'The email was sent successfully'\r\n } catch (error) {\r\n return error\r\n }\r\n }\r\n\r\n newClients(){\r\n return this.clients.filter(c => moment().isSame(c.date, 'month')).length\r\n }\r\n\r\n emailsSent(){\r\n return this.clients.filter(c => c.email_type != null).length\r\n }\r\n\r\n outstandingClients(){\r\n return this.clients.filter(c => !c.sold).length\r\n }\r\n \r\n hottestCountry(){\r\n return this.groupCountry.length ? this.groupCountry[0][0] : \"\"\r\n }\r\n\r\n getBadgesData(){ //0 header, 1 paragraph, 2 color\r\n const newClient = [this.newClients(), `New ${moment().format('MMMM')} Clients`, '#2ecc71']\r\n const emails = [this.emailsSent(), 'Emails Sent', '#3498db']\r\n const outstanding= [this.outstandingClients() , 'Outstanding Clients', '#e74c3c']\r\n const country = [this.hottestCountry(), 'HottestCountry', '#f1c40f']\r\n return [newClient, emails, outstanding, country]\r\n }\r\n\r\n reduceResults(arr){\r\n const result = arr.reduce((total, c)=>{\r\n total[0].push(c.category)\r\n total[1].push(c.sum)\r\n return total\r\n }, [[], []])\r\n return result\r\n }\r\n\r\n topThreeEmployees(){\r\n if(this.groupOwner.length){\r\n const labels = this.groupOwner[0].slice(0, 3)\r\n const data = this.groupOwner[1].slice(0, 3)\r\n return [labels, data]\r\n }else{\r\n return [[], []]\r\n }\r\n }\r\n\r\n get30days(){\r\n let fromDate = moment().subtract(30, 'days');\r\n const toDate = moment()\r\n const dates = []\r\n const values = []\r\n while(fromDate <= toDate){\r\n dates.push(moment(fromDate).format('MM/DD'))\r\n values.push(this.clients.filter(c => moment(c.date).isSame(fromDate, 'day')).length)\r\n fromDate = moment(fromDate).add(1,'days')\r\n }\r\n return [dates, values]\r\n }\r\n}","C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\Analytics.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\TopEmployeeChart.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\ClientPie.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\SalesSince.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\SalesSortedBy.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\Badges.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Analytics\\Badge.js",[],["84","85"],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Actions\\Actions.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Actions\\AddClient.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Actions\\UpdateClient.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Clients\\Clients.js",[],"C:\\Users\\user\\Desktop\\code\\projects\\CRM\\crm\\src\\components\\Clients\\UpdatePopover.js",["86"],"import React, {useState} from 'react'\r\nimport Select from 'react-select'\r\nimport { observer, inject } from 'mobx-react'\r\nimport {TextField, Popover, Button} from '@material-ui/core';\r\nimport { useSnackbar } from 'notistack';\r\n\r\nfunction UpdatePopover(props) {\r\n\r\n const { id, first, last, country, countryId} = props.clientInfo\r\n const [client, setClient] = useState({first, last , countryId, country})\r\n const { enqueueSnackbar } = useSnackbar();\r\n\r\n const handleClose = () => {\r\n props.setOpen(false)\r\n };\r\n\r\n const update = async () => {\r\n const { first, last, countryId, country } = client\r\n if(first && last && countryId){\r\n const response = await props.ClientsStore.updateClient(id, first, last, countryId)\r\n handleClose()\r\n const {text, variant} = (response && response.stack && response.message) ? {text:`Oops, The Client wasn't updated`, variant: 'error'} : {text: response, variant: 'success'}\r\n enqueueSnackbar(text, { variant })\r\n }else{\r\n enqueueSnackbar('some fields are missing', { variant: 'warning' })\r\n }\r\n }\r\n\r\n const updateInput = (event) => {\r\n const {id, value} = event.target\r\n setClient({...client, [id]: value})\r\n }\r\n\r\n const updateSelect = (event) => setClient({...client, countryId: event ? event.value : null})\r\n \r\n\r\n const options = props.ClientsStore.countries.map(c => { return {label: c.country, value: c.id} })\r\n\r\n return (\r\n
\r\n \r\n
\r\n \r\n \r\n setCountry(event ? {countryId: event.value, country: event.label} : {...country, countryId: -1})} + isClearable="true" id="selectCountry" + placeholder= "Select Country" + /> + + {client.id && <> + setEmailType(event ? {emailTypeId: event.value} : {emailTypeId: null})} + isClearable="true" id="selectEmail" + placeholder= "Select Email Type" + /> + + {!client.sold && } + } +
+
+ ) +} + +export default inject("ClientsStore")(observer(UpdateClient)) diff --git a/src/components/Analytics/Analytics.js b/src/components/Analytics/Analytics.js new file mode 100644 index 0000000..b77b652 --- /dev/null +++ b/src/components/Analytics/Analytics.js @@ -0,0 +1,32 @@ +import React from 'react' +import {Grid} from '@material-ui/core'; +import Badges from './Badges'; +import TopEmployeeChart from './TopEmployeeChart'; +import ClientPie from './ClientPie' +import SalesSince from './SalesSince'; +import SalesSortedBy from './SalesSortedBy' + + +function Analytics() { + return ( +
+ + + + + + + + + + + + + + + +
+ ) +} + +export default Analytics diff --git a/src/components/Analytics/Badge.js b/src/components/Analytics/Badge.js new file mode 100644 index 0000000..b6f77e0 --- /dev/null +++ b/src/components/Analytics/Badge.js @@ -0,0 +1,23 @@ +import React from 'react' +import { faChartLine, faEnvelope, faUserCircle, faGlobeAmericas } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +function Badge(props) { + const {header, p, color, id} = props + const icon = id === 0 ? faChartLine : id === 1 ? faEnvelope : id === 2 ? faUserCircle : faGlobeAmericas + return ( +
+
+ +
+
+

{header}

+

{p}

+
+ +
+ + ) +} + +export default Badge diff --git a/src/components/Analytics/Badges.js b/src/components/Analytics/Badges.js new file mode 100644 index 0000000..82c6315 --- /dev/null +++ b/src/components/Analytics/Badges.js @@ -0,0 +1,22 @@ +import React from 'react' +import { Grid } from '@material-ui/core'; +import { observer, inject } from 'mobx-react' +import Badge from './Badge' + +function Badges(props) { + const badgesData = props.ClientsStore.getBadgesData() + return ( + <> + {badgesData.map((b, i)=> { + return ( + + + + ) + } + )} + + ) +} + +export default inject("ClientsStore")(observer(Badges)) diff --git a/src/components/Analytics/ClientPie.js b/src/components/Analytics/ClientPie.js new file mode 100644 index 0000000..b4b2250 --- /dev/null +++ b/src/components/Analytics/ClientPie.js @@ -0,0 +1,26 @@ +import React from 'react' +import {Pie} from 'react-chartjs-2'; + +function ClientPie() { + const data = { + labels: [ + 'Last month', + '6-12 months', + '>12 months' + ], + datasets: [{ + data: [302, 131, 22], + backgroundColor: ['#795548', '#34495e', '#95a5a6'], + hoverBackgroundColor: ['#795548', '#34495e', '#95a5a6'] + }] + }; + + return ( +
+

Client Acquisition

+ +
+ ) +} + +export default ClientPie diff --git a/src/components/Analytics/SalesSince.js b/src/components/Analytics/SalesSince.js new file mode 100644 index 0000000..326f825 --- /dev/null +++ b/src/components/Analytics/SalesSince.js @@ -0,0 +1,42 @@ +import React from 'react' +import {Line} from 'react-chartjs-2'; +import { observer, inject } from 'mobx-react' + + +function SalesSince(props) { + const dates = props.ClientsStore.get30days() + const data = { + labels: dates[0], + datasets: [ + { + label: 'Sales last 30 days', + fill: false, + lineTension: 0.1, + backgroundColor: 'rgba(255,110,84,1)', + borderColor: 'rgba(255,110,84,1)', + borderCapStyle: 'butt', + borderDash: [], + borderDashOffset: 0.0, + borderJoinStyle: 'miter', + pointBorderColor: 'rgba(255,110,84,1)', + pointBackgroundColor: '#fff', + pointBorderWidth: 2, + pointHoverRadius: 5, + pointHoverBackgroundColor: 'rgba(255,110,84,1)', + pointHoverBorderColor: 'rgba(255,110,84,1)', + pointHoverBorderWidth: 2, + pointRadius: 1, + pointHitRadius: 10, + data:dates[1] + } + ] + }; + return ( +
+

Sales Since 30 days

+ +
+ ) +} + +export default inject("ClientsStore")(observer(SalesSince)) diff --git a/src/components/Analytics/SalesSortedBy.js b/src/components/Analytics/SalesSortedBy.js new file mode 100644 index 0000000..e3ec08f --- /dev/null +++ b/src/components/Analytics/SalesSortedBy.js @@ -0,0 +1,64 @@ +import React, {useState} from 'react' +import {Bar} from 'react-chartjs-2'; +import { observer, inject } from 'mobx-react' +import Select from 'react-select' + +function SalesSortedBy(props) { + const [option, setOption] = useState({label: "country" , value: 1 }) + const [filteredData, setFilteredData] = useState(props.ClientsStore.groupCountry) + + const sortBy = [ + {label: "Country" , value: 1 }, + {label: "Email" , value: 2 }, + {label: "Month" , value: 3 }, + {label: "Owner" , value: 4 } + ] + + const handleChange = (event) => { + if(event){ + const {label, value} = event + setOption({label, value}) + setFilteredData(props.ClientsStore[`group${label}`]) + } + } + + let data = { + labels: filteredData[0], + datasets: [ + { + label: 'salesBy', + backgroundColor: 'rgba(149,81,150,0.8)', + borderColor: 'rgba(149,81,150,8)', + borderWidth: 1, + hoverBackgroundColor: 'rgba(149,81,150,1)', + hoverBorderColor: 'rgba(149,81,150,1)', + data: filteredData[1] + } + ] + }; + return ( +
+
+

Sales By

+ event && setOption({label: event.label, value: event.value})} + isClearable="true" id="selectSearchOption" + placeholder= "Select Search Category" + defaultValue={option} + /> +
+ + {open && } +
+ ) +} + +export default inject("ClientsStore")(observer(Clients)) diff --git a/src/components/Clients/UpdatePopover.js b/src/components/Clients/UpdatePopover.js new file mode 100644 index 0000000..4978c25 --- /dev/null +++ b/src/components/Clients/UpdatePopover.js @@ -0,0 +1,79 @@ +import React, {useState} from 'react' +import Select from 'react-select' +import { observer, inject } from 'mobx-react' +import {TextField, Popover, Button} from '@material-ui/core'; +import { useSnackbar } from 'notistack'; + +function UpdatePopover(props) { + + const { id, first, last, country, countryId} = props.clientInfo + const [client, setClient] = useState({first, last , countryId, country}) + const { enqueueSnackbar } = useSnackbar(); + + const handleClose = () => { + props.setOpen(false) + }; + + const update = async () => { + const { first, last, countryId, country } = client + if(first && last && countryId){ + const response = await props.ClientsStore.updateClient(id, first, last, countryId) + handleClose() + const {text, variant} = (response && response.stack && response.message) ? {text:`Oops, The Client wasn't updated`, variant: 'error'} : {text: response, variant: 'success'} + enqueueSnackbar(text, { variant }) + }else{ + enqueueSnackbar('some fields are missing', { variant: 'warning' }) + } + } + + const updateInput = (event) => { + const {id, value} = event.target + setClient({...client, [id]: value}) + } + + const updateSelect = (event) => setClient({...client, countryId: event ? event.value : null}) + + + const options = props.ClientsStore.countries.map(c => { return {label: c.country, value: c.id} }) + + return ( +
+ +
+ + +