added geography page
This commit is contained in:
parent
980e69273a
commit
39b2da4a00
13 changed files with 14014 additions and 5 deletions
|
@ -9,6 +9,7 @@ import Dashboard from "pages/dashboard/Dashboard";
|
|||
import Products from "pages/products/Products";
|
||||
import Customers from "pages/customers/Customers";
|
||||
import Transactions from "pages/transactions/Transactions";
|
||||
import Geography from "pages/geography/Geography";
|
||||
|
||||
|
||||
function App() {
|
||||
|
@ -29,6 +30,7 @@ function App() {
|
|||
<Route path="/products" element={<Products/>} />
|
||||
<Route path="/customers" element={<Customers/>} />
|
||||
<Route path="/transactions" element={<Transactions/>} />
|
||||
<Route path="/geography" element={<Geography/>} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</ThemeProvider>
|
||||
|
|
88
admin_dashboard/client/src/pages/geography/Geography.jsx
Normal file
88
admin_dashboard/client/src/pages/geography/Geography.jsx
Normal file
|
@ -0,0 +1,88 @@
|
|||
import { Box, useTheme } from '@mui/material'
|
||||
import Header from 'components/Header'
|
||||
import { useGetGeographyQuery } from 'state/api'
|
||||
import { ResponsiveChoropleth } from '@nivo/geo'
|
||||
import { geographyData } from 'state/geographyData'
|
||||
|
||||
|
||||
const Geography = () => {
|
||||
const theme = useTheme();
|
||||
const {data} = useGetGeographyQuery();
|
||||
|
||||
|
||||
return (
|
||||
<Box m="1.5rem 2.5rem">
|
||||
<Header title="Geography" subtitle="Find your user location "/>
|
||||
<Box mt="40px" height="75vh" border={`1px solid ${theme.palette.secondary[200]}`} borderRadius="4px">
|
||||
{data? (
|
||||
<ResponsiveChoropleth data={data}
|
||||
theme={{
|
||||
axis: {
|
||||
domain: {
|
||||
line: {
|
||||
stroke: theme.palette.secondary[200],
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
text: {
|
||||
fill: theme.palette.secondary[200],
|
||||
},
|
||||
},
|
||||
ticks: {
|
||||
line: {
|
||||
stroke: theme.palette.secondary[200],
|
||||
strokeWidth: 1,
|
||||
},
|
||||
text: {
|
||||
fill: theme.palette.secondary[200],
|
||||
},
|
||||
},
|
||||
},
|
||||
legends: {
|
||||
text: {
|
||||
fill: theme.palette.secondary[200],
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
container: {
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
},
|
||||
}}
|
||||
features={geographyData.features}
|
||||
margin={{ top: 0, right: 0, bottom: 0, left: -50 }}
|
||||
colors="YlGnBu"
|
||||
domain={[0, 60]}
|
||||
unknownColor="#666666"
|
||||
label="properties.name"
|
||||
valueFormat=".2s"
|
||||
projectionScale={150}
|
||||
projectionTranslation={[0.45, 0.6]}
|
||||
projectionRotation={[0, 0, 0]}
|
||||
borderWidth={1.3}
|
||||
borderColor="#ADBC9F"
|
||||
legends={[
|
||||
{
|
||||
anchor: "bottom-right",
|
||||
direction: "column",
|
||||
justify: true,
|
||||
translateX: 0,
|
||||
translateY: -125,
|
||||
itemsSpacing: 0,
|
||||
itemWidth: 94,
|
||||
itemHeight: 18,
|
||||
itemDirection: "left-to-right",
|
||||
itemTextColor: theme.palette.secondary[200],
|
||||
itemOpacity: 0.85,
|
||||
symbolSize: 18,
|
||||
},
|
||||
]}/>
|
||||
) : (
|
||||
<>Loading...</>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default Geography
|
|
@ -3,7 +3,7 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"
|
|||
export const api = createApi({
|
||||
baseQuery: fetchBaseQuery({baseUrl: process.env.REACT_APP_BASE_URL}),
|
||||
reducerPath: "adminApi",
|
||||
tagTypes: ["User", "Products", "Customers", "Transactions", ],
|
||||
tagTypes: ["User", "Products", "Customers", "Transactions", "Geography" ],
|
||||
endpoints: (build) => ({
|
||||
getUser: build.query({
|
||||
query: (id) => `general/user/${id}`,
|
||||
|
@ -15,7 +15,7 @@ export const api = createApi({
|
|||
}),
|
||||
getCustomers: build.query({
|
||||
query: () => "client/customers",
|
||||
providesTags: ["Customers"]
|
||||
providesTags: ["Customers"],
|
||||
}),
|
||||
getTransactions: build.query({
|
||||
query: ({page, pageSize, sort, search}) => ({
|
||||
|
@ -24,8 +24,12 @@ export const api = createApi({
|
|||
params: {page, pageSize, sort, search},
|
||||
}),
|
||||
providesTags: ["Transactions"]
|
||||
}),
|
||||
getGeography: build.query({
|
||||
query: () => "client/geography",
|
||||
providesTags: ["Geography"],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
export const {useGetUserQuery, useGetProductsQuery, useGetCustomersQuery, useGetTransactionsQuery} = api;
|
||||
export const {useGetUserQuery, useGetProductsQuery, useGetCustomersQuery, useGetTransactionsQuery, useGetGeographyQuery} = api;
|
||||
|
|
13550
admin_dashboard/client/src/state/geographyData.js
Normal file
13550
admin_dashboard/client/src/state/geographyData.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2,6 +2,7 @@ import Product from "../models/Product.js";
|
|||
import ProductStat from "../models/ProductStat.js";
|
||||
import Transaction from "../models/Transaction.js";
|
||||
import User from "../models/User.js"
|
||||
import getCountryIso3 from "country-iso-2-to-3"
|
||||
|
||||
|
||||
export const getProducts = async(req, res) => {
|
||||
|
@ -63,3 +64,27 @@ export const getTransactions = async(req, res) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const getGeography = async(req, res) => {
|
||||
try {
|
||||
const users = await User.find();
|
||||
const mapLocations = users.reduce((acc, {country}) => {
|
||||
const countryISO3 = getCountryIso3(country);
|
||||
if(!acc [countryISO3]){
|
||||
acc[countryISO3] = 0;
|
||||
}
|
||||
acc[countryISO3]++;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const formattedLocations = Object.entries(mapLocations).map(
|
||||
([country, count]) => {
|
||||
return{id: country, value: count}
|
||||
}
|
||||
);
|
||||
res.status(200).json(formattedLocations)
|
||||
|
||||
} catch (error) {
|
||||
res.status(404).json({message: error.message})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
5
admin_dashboard/server/node_modules/.package-lock.json
generated
vendored
5
admin_dashboard/server/node_modules/.package-lock.json
generated
vendored
|
@ -240,6 +240,11 @@
|
|||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/country-iso-2-to-3": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/country-iso-2-to-3/-/country-iso-2-to-3-1.1.0.tgz",
|
||||
"integrity": "sha512-+xaB6XPuuLuSQEjejWXjff7s5AMyisPk3jBmIqM7aymup79mEcinNkUiIpe4VedSPWCT+/bMW/EDJvRaiDaWKw=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
|
|
37
admin_dashboard/server/node_modules/country-iso-2-to-3/README.md
generated
vendored
Normal file
37
admin_dashboard/server/node_modules/country-iso-2-to-3/README.md
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
# country-iso-2-to-3
|
||||
|
||||
> Convert a country code ISO 3166-1 Alpha-2 to ISO 3166-1 Alpha-3
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
$ npm install country-iso-2-to-3
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const getCountryISO3 = require("country-iso-2-to-3");
|
||||
|
||||
getCountryISO3("BR")
|
||||
// "BRA"
|
||||
|
||||
getCountryISO3("US")
|
||||
// "USA"
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### getCountryISO3(countryCode)
|
||||
|
||||
**Parameter**:
|
||||
A string with a country code in ISO 3166-1 Alpha-2
|
||||
|
||||
**Return**:
|
||||
A string with the country code in ISO 3166-1 Alpha-3
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
MIT © [VTEX](https://www.vtex.com)
|
254
admin_dashboard/server/node_modules/country-iso-2-to-3/index.js
generated
vendored
Normal file
254
admin_dashboard/server/node_modules/country-iso-2-to-3/index.js
generated
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
var countryISOMapping = {
|
||||
AF: 'AFG',
|
||||
AX: 'ALA',
|
||||
AL: 'ALB',
|
||||
DZ: 'DZA',
|
||||
AS: 'ASM',
|
||||
AD: 'AND',
|
||||
AO: 'AGO',
|
||||
AI: 'AIA',
|
||||
AQ: 'ATA',
|
||||
AG: 'ATG',
|
||||
AR: 'ARG',
|
||||
AM: 'ARM',
|
||||
AW: 'ABW',
|
||||
AU: 'AUS',
|
||||
AT: 'AUT',
|
||||
AZ: 'AZE',
|
||||
BS: 'BHS',
|
||||
BH: 'BHR',
|
||||
BD: 'BGD',
|
||||
BB: 'BRB',
|
||||
BY: 'BLR',
|
||||
BE: 'BEL',
|
||||
BZ: 'BLZ',
|
||||
BJ: 'BEN',
|
||||
BM: 'BMU',
|
||||
BT: 'BTN',
|
||||
BO: 'BOL',
|
||||
BA: 'BIH',
|
||||
BW: 'BWA',
|
||||
BV: 'BVT',
|
||||
BR: 'BRA',
|
||||
VG: 'VGB',
|
||||
IO: 'IOT',
|
||||
BN: 'BRN',
|
||||
BG: 'BGR',
|
||||
BF: 'BFA',
|
||||
BI: 'BDI',
|
||||
KH: 'KHM',
|
||||
CM: 'CMR',
|
||||
CA: 'CAN',
|
||||
CV: 'CPV',
|
||||
KY: 'CYM',
|
||||
CF: 'CAF',
|
||||
TD: 'TCD',
|
||||
CL: 'CHL',
|
||||
CN: 'CHN',
|
||||
HK: 'HKG',
|
||||
MO: 'MAC',
|
||||
CX: 'CXR',
|
||||
CC: 'CCK',
|
||||
CO: 'COL',
|
||||
KM: 'COM',
|
||||
CG: 'COG',
|
||||
CD: 'COD',
|
||||
CK: 'COK',
|
||||
CR: 'CRI',
|
||||
CI: 'CIV',
|
||||
HR: 'HRV',
|
||||
CU: 'CUB',
|
||||
CY: 'CYP',
|
||||
CZ: 'CZE',
|
||||
DK: 'DNK',
|
||||
DJ: 'DJI',
|
||||
DM: 'DMA',
|
||||
DO: 'DOM',
|
||||
EC: 'ECU',
|
||||
EG: 'EGY',
|
||||
SV: 'SLV',
|
||||
GQ: 'GNQ',
|
||||
ER: 'ERI',
|
||||
EE: 'EST',
|
||||
ET: 'ETH',
|
||||
FK: 'FLK',
|
||||
FO: 'FRO',
|
||||
FJ: 'FJI',
|
||||
FI: 'FIN',
|
||||
FR: 'FRA',
|
||||
GF: 'GUF',
|
||||
PF: 'PYF',
|
||||
TF: 'ATF',
|
||||
GA: 'GAB',
|
||||
GM: 'GMB',
|
||||
GE: 'GEO',
|
||||
DE: 'DEU',
|
||||
GH: 'GHA',
|
||||
GI: 'GIB',
|
||||
GR: 'GRC',
|
||||
GL: 'GRL',
|
||||
GD: 'GRD',
|
||||
GP: 'GLP',
|
||||
GU: 'GUM',
|
||||
GT: 'GTM',
|
||||
GG: 'GGY',
|
||||
GN: 'GIN',
|
||||
GW: 'GNB',
|
||||
GY: 'GUY',
|
||||
HT: 'HTI',
|
||||
HM: 'HMD',
|
||||
VA: 'VAT',
|
||||
HN: 'HND',
|
||||
HU: 'HUN',
|
||||
IS: 'ISL',
|
||||
IN: 'IND',
|
||||
ID: 'IDN',
|
||||
IR: 'IRN',
|
||||
IQ: 'IRQ',
|
||||
IE: 'IRL',
|
||||
IM: 'IMN',
|
||||
IL: 'ISR',
|
||||
IT: 'ITA',
|
||||
JM: 'JAM',
|
||||
JP: 'JPN',
|
||||
JE: 'JEY',
|
||||
JO: 'JOR',
|
||||
KZ: 'KAZ',
|
||||
KE: 'KEN',
|
||||
KI: 'KIR',
|
||||
KP: 'PRK',
|
||||
KR: 'KOR',
|
||||
KW: 'KWT',
|
||||
KG: 'KGZ',
|
||||
LA: 'LAO',
|
||||
LV: 'LVA',
|
||||
LB: 'LBN',
|
||||
LS: 'LSO',
|
||||
LR: 'LBR',
|
||||
LY: 'LBY',
|
||||
LI: 'LIE',
|
||||
LT: 'LTU',
|
||||
LU: 'LUX',
|
||||
MK: 'MKD',
|
||||
MG: 'MDG',
|
||||
MW: 'MWI',
|
||||
MY: 'MYS',
|
||||
MV: 'MDV',
|
||||
ML: 'MLI',
|
||||
MT: 'MLT',
|
||||
MH: 'MHL',
|
||||
MQ: 'MTQ',
|
||||
MR: 'MRT',
|
||||
MU: 'MUS',
|
||||
YT: 'MYT',
|
||||
MX: 'MEX',
|
||||
FM: 'FSM',
|
||||
MD: 'MDA',
|
||||
MC: 'MCO',
|
||||
MN: 'MNG',
|
||||
ME: 'MNE',
|
||||
MS: 'MSR',
|
||||
MA: 'MAR',
|
||||
MZ: 'MOZ',
|
||||
MM: 'MMR',
|
||||
NA: 'NAM',
|
||||
NR: 'NRU',
|
||||
NP: 'NPL',
|
||||
NL: 'NLD',
|
||||
AN: 'ANT',
|
||||
NC: 'NCL',
|
||||
NZ: 'NZL',
|
||||
NI: 'NIC',
|
||||
NE: 'NER',
|
||||
NG: 'NGA',
|
||||
NU: 'NIU',
|
||||
NF: 'NFK',
|
||||
MP: 'MNP',
|
||||
NO: 'NOR',
|
||||
OM: 'OMN',
|
||||
PK: 'PAK',
|
||||
PW: 'PLW',
|
||||
PS: 'PSE',
|
||||
PA: 'PAN',
|
||||
PG: 'PNG',
|
||||
PY: 'PRY',
|
||||
PE: 'PER',
|
||||
PH: 'PHL',
|
||||
PN: 'PCN',
|
||||
PL: 'POL',
|
||||
PT: 'PRT',
|
||||
PR: 'PRI',
|
||||
QA: 'QAT',
|
||||
RE: 'REU',
|
||||
RO: 'ROU',
|
||||
RU: 'RUS',
|
||||
RW: 'RWA',
|
||||
BL: 'BLM',
|
||||
SH: 'SHN',
|
||||
KN: 'KNA',
|
||||
LC: 'LCA',
|
||||
MF: 'MAF',
|
||||
PM: 'SPM',
|
||||
VC: 'VCT',
|
||||
WS: 'WSM',
|
||||
SM: 'SMR',
|
||||
ST: 'STP',
|
||||
SA: 'SAU',
|
||||
SN: 'SEN',
|
||||
RS: 'SRB',
|
||||
SC: 'SYC',
|
||||
SL: 'SLE',
|
||||
SG: 'SGP',
|
||||
SK: 'SVK',
|
||||
SI: 'SVN',
|
||||
SB: 'SLB',
|
||||
SO: 'SOM',
|
||||
ZA: 'ZAF',
|
||||
GS: 'SGS',
|
||||
SS: 'SSD',
|
||||
ES: 'ESP',
|
||||
LK: 'LKA',
|
||||
SD: 'SDN',
|
||||
SR: 'SUR',
|
||||
SJ: 'SJM',
|
||||
SZ: 'SWZ',
|
||||
SE: 'SWE',
|
||||
CH: 'CHE',
|
||||
SY: 'SYR',
|
||||
TW: 'TWN',
|
||||
TJ: 'TJK',
|
||||
TZ: 'TZA',
|
||||
TH: 'THA',
|
||||
TL: 'TLS',
|
||||
TG: 'TGO',
|
||||
TK: 'TKL',
|
||||
TO: 'TON',
|
||||
TT: 'TTO',
|
||||
TN: 'TUN',
|
||||
TR: 'TUR',
|
||||
TM: 'TKM',
|
||||
TC: 'TCA',
|
||||
TV: 'TUV',
|
||||
UG: 'UGA',
|
||||
UA: 'UKR',
|
||||
AE: 'ARE',
|
||||
GB: 'GBR',
|
||||
US: 'USA',
|
||||
UM: 'UMI',
|
||||
UY: 'URY',
|
||||
UZ: 'UZB',
|
||||
VU: 'VUT',
|
||||
VE: 'VEN',
|
||||
VN: 'VNM',
|
||||
VI: 'VIR',
|
||||
WF: 'WLF',
|
||||
EH: 'ESH',
|
||||
YE: 'YEM',
|
||||
ZM: 'ZMB',
|
||||
ZW: 'ZWE',
|
||||
XK: 'XKX'
|
||||
}
|
||||
|
||||
module.exports = function getCountryISO3(countryCode) {
|
||||
return countryISOMapping[countryCode]
|
||||
}
|
32
admin_dashboard/server/node_modules/country-iso-2-to-3/package.json
generated
vendored
Normal file
32
admin_dashboard/server/node_modules/country-iso-2-to-3/package.json
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "country-iso-2-to-3",
|
||||
"version": "1.1.0",
|
||||
"description": "Convert a country code ISO 3166-1 Alpha-2 to ISO 3166-1 Alpha-3",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "node test.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@github.com/vtex/country-iso-2-to-3.git"
|
||||
},
|
||||
"keywords": [
|
||||
"country",
|
||||
"code",
|
||||
"country",
|
||||
"iso",
|
||||
"alpha-3",
|
||||
"alpha",
|
||||
"3",
|
||||
"alpha-2",
|
||||
"alpha",
|
||||
"2",
|
||||
"3166"
|
||||
],
|
||||
"author": "Breno Calazans (@klzns)",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vtex/country-iso-2-to-3/issues"
|
||||
},
|
||||
"homepage": "https://github.com/vtex/country-iso-2-to-3#readme"
|
||||
}
|
4
admin_dashboard/server/node_modules/country-iso-2-to-3/test.js
generated
vendored
Normal file
4
admin_dashboard/server/node_modules/country-iso-2-to-3/test.js
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
var getCountryISO3 = require("./index")
|
||||
|
||||
var result = getCountryISO3("BR")
|
||||
console.assert(result === "BRA")
|
6
admin_dashboard/server/package-lock.json
generated
6
admin_dashboard/server/package-lock.json
generated
|
@ -11,6 +11,7 @@
|
|||
"dependencies": {
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"country-iso-2-to-3": "^1.1.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.19.2",
|
||||
"helmet": "^7.1.0",
|
||||
|
@ -255,6 +256,11 @@
|
|||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/country-iso-2-to-3": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/country-iso-2-to-3/-/country-iso-2-to-3-1.1.0.tgz",
|
||||
"integrity": "sha512-+xaB6XPuuLuSQEjejWXjff7s5AMyisPk3jBmIqM7aymup79mEcinNkUiIpe4VedSPWCT+/bMW/EDJvRaiDaWKw=="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node index.js",
|
||||
"dev": "nodemon index.js"
|
||||
"dev": "nodemon index.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
|
@ -15,6 +15,7 @@
|
|||
"dependencies": {
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"country-iso-2-to-3": "^1.1.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.19.2",
|
||||
"helmet": "^7.1.0",
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import express from "express"
|
||||
import {getProducts, getCustomers, getTransactions} from "../controllers/client.js"
|
||||
import {getProducts, getCustomers, getTransactions, getGeography} from "../controllers/client.js"
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/products", getProducts);
|
||||
router.get("/customers", getCustomers);
|
||||
router.get("/transactions", getTransactions)
|
||||
router.get("/geography", getGeography)
|
||||
|
||||
export default router;
|
Loading…
Add table
Reference in a new issue