@aclymatepackages/modules 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -0
- package/babel.config.json +18 -0
- package/dist/components/CompaniesAutocomplete.js +126 -0
- package/dist/components/CompanyOnboardingInput.js +116 -0
- package/dist/components/ComparisonChart.js +200 -0
- package/dist/components/CustomTooltipDisplayRow.js +59 -0
- package/dist/components/EmissionsChart.js +467 -0
- package/dist/components/EmissionsCustomTooltip.js +181 -0
- package/dist/components/EmissionsPieChart.js +130 -0
- package/dist/components/EmissionsReductionGraph.js +118 -0
- package/dist/components/FootprintEquivalencies.js +181 -0
- package/dist/components/FootprintVideo.js +262 -0
- package/dist/components/FuelTypesSelect.js +36 -0
- package/dist/components/IndustryAutocomplete.js +58 -0
- package/dist/components/PlacesAutocomplete.js +173 -0
- package/dist/components/StripeElements.js +95 -0
- package/dist/components/YesNoQuestion.js +88 -0
- package/dist/components/stripeInput.js +293 -0
- package/dist/components/useChartWarningLabels.js +143 -0
- package/dist/index.js +118 -0
- package/package.json +74 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +43 -0
- package/public/logo192.png +0 -0
- package/public/logo512.png +0 -0
- package/public/manifest.json +25 -0
- package/public/robots.txt +3 -0
- package/src/components/CompaniesAutocomplete.js +125 -0
- package/src/components/CompanyOnboardingInput.js +113 -0
- package/src/components/ComparisonChart.js +236 -0
- package/src/components/CustomTooltipDisplayRow.js +41 -0
- package/src/components/EmissionsChart.js +579 -0
- package/src/components/EmissionsCustomTooltip.js +146 -0
- package/src/components/EmissionsPieChart.js +120 -0
- package/src/components/EmissionsReductionGraph.js +107 -0
- package/src/components/FootprintEquivalencies.js +203 -0
- package/src/components/FootprintVideo.js +328 -0
- package/src/components/FuelTypesSelect.js +29 -0
- package/src/components/IndustryAutocomplete.js +56 -0
- package/src/components/PlacesAutocomplete.js +174 -0
- package/src/components/StripeElements.js +95 -0
- package/src/components/YesNoQuestion.js +68 -0
- package/src/components/stripeInput.js +288 -0
- package/src/components/useChartWarningLabels.js +139 -0
- package/src/index.js +35 -0
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aclymatepackages/modules",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Aclymate modules",
|
|
5
|
+
"author": "William Loopesko",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@aclymatepackages/array-immutability-helpers": "^1.0.0",
|
|
9
|
+
"@aclymatepackages/atoms": "^1.0.21",
|
|
10
|
+
"@aclymatepackages/chart-helpers": "^1.0.0",
|
|
11
|
+
"@aclymatepackages/constants": "^1.0.10",
|
|
12
|
+
"@aclymatepackages/converters": "^1.1.2",
|
|
13
|
+
"@aclymatepackages/date-helpers": "^1.0.7",
|
|
14
|
+
"@aclymatepackages/fetch-aclymate-api": "^1.0.2",
|
|
15
|
+
"@aclymatepackages/formatters": "^1.1.4",
|
|
16
|
+
"@aclymatepackages/lists": "^1.1.1",
|
|
17
|
+
"@aclymatepackages/multi-part-form": "2.0.17",
|
|
18
|
+
"@aclymatepackages/other-helpers": "^0.1.19",
|
|
19
|
+
"@aclymatepackages/reg-exp": "^1.0.3",
|
|
20
|
+
"@aclymatepackages/themes": "^4.0.5",
|
|
21
|
+
"@babel/preset-react": "^7.16.7",
|
|
22
|
+
"@emotion/react": "^11.11.1",
|
|
23
|
+
"@emotion/styled": "^11.11.0",
|
|
24
|
+
"@fortawesome/react-fontawesome": "^0.1.18",
|
|
25
|
+
"@mui/icons-material": "^5.11.16",
|
|
26
|
+
"@mui/lab": "^5.0.0-alpha.134",
|
|
27
|
+
"@mui/material": "^5.13.6",
|
|
28
|
+
"@mui/styles": "^5.13.2",
|
|
29
|
+
"@stripe/react-stripe-js": "^2.1.0",
|
|
30
|
+
"@stripe/stripe-js": "^1.53.0",
|
|
31
|
+
"autosuggest-highlight": "^3.2.1",
|
|
32
|
+
"dayjs": "^1.11.7",
|
|
33
|
+
"npm": "^8.19.4",
|
|
34
|
+
"peopledatalabs": "^5.0.4",
|
|
35
|
+
"react-cookie": "^6.1.0",
|
|
36
|
+
"react-countup": "^4.4.0",
|
|
37
|
+
"recharts": "^2.10.4",
|
|
38
|
+
"typewriter-effect": "^2.18.2"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"react": "^17.0.0 || ^18.2.0",
|
|
42
|
+
"react-dom": "^17.0.2 || ^18.2.0",
|
|
43
|
+
"react-scripts": ">=5.0.0"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"start": "react-scripts start",
|
|
47
|
+
"build": "rm -rf dist && NODE_ENV=production babel src --out-dir dist --copy-files",
|
|
48
|
+
"test": "react-scripts test",
|
|
49
|
+
"eject": "react-scripts eject"
|
|
50
|
+
},
|
|
51
|
+
"eslintConfig": {
|
|
52
|
+
"extends": [
|
|
53
|
+
"react-app",
|
|
54
|
+
"react-app/jest"
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"browserslist": {
|
|
58
|
+
"production": [
|
|
59
|
+
">0.2%",
|
|
60
|
+
"not dead",
|
|
61
|
+
"not op_mini all"
|
|
62
|
+
],
|
|
63
|
+
"development": [
|
|
64
|
+
"last 1 chrome version",
|
|
65
|
+
"last 1 firefox version",
|
|
66
|
+
"last 1 safari version"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@babel/cli": "^7.17.10",
|
|
71
|
+
"@babel/core": "^7.17.10",
|
|
72
|
+
"@babel/preset-env": "^7.17.10"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<meta name="theme-color" content="#000000" />
|
|
8
|
+
<meta
|
|
9
|
+
name="description"
|
|
10
|
+
content="Web site created using create-react-app"
|
|
11
|
+
/>
|
|
12
|
+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
|
13
|
+
<!--
|
|
14
|
+
manifest.json provides metadata used when your web app is installed on a
|
|
15
|
+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
16
|
+
-->
|
|
17
|
+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
18
|
+
<!--
|
|
19
|
+
Notice the use of %PUBLIC_URL% in the tags above.
|
|
20
|
+
It will be replaced with the URL of the `public` folder during the build.
|
|
21
|
+
Only files inside the `public` folder can be referenced from the HTML.
|
|
22
|
+
|
|
23
|
+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
24
|
+
work correctly both with client-side routing and a non-root public URL.
|
|
25
|
+
Learn how to configure a non-root public URL by running `npm run build`.
|
|
26
|
+
-->
|
|
27
|
+
<title>React App</title>
|
|
28
|
+
</head>
|
|
29
|
+
<body>
|
|
30
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
31
|
+
<div id="root"></div>
|
|
32
|
+
<!--
|
|
33
|
+
This HTML file is a template.
|
|
34
|
+
If you open it directly in the browser, you will see an empty page.
|
|
35
|
+
|
|
36
|
+
You can add webfonts, meta tags, or analytics to this file.
|
|
37
|
+
The build step will place the bundled scripts into the <body> tag.
|
|
38
|
+
|
|
39
|
+
To begin the development, run `npm start` or `yarn start`.
|
|
40
|
+
To create a production bundle, use `npm run build` or `yarn build`.
|
|
41
|
+
-->
|
|
42
|
+
</body>
|
|
43
|
+
</html>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"short_name": "React App",
|
|
3
|
+
"name": "Create React App Sample",
|
|
4
|
+
"icons": [
|
|
5
|
+
{
|
|
6
|
+
"src": "favicon.ico",
|
|
7
|
+
"sizes": "64x64 32x32 24x24 16x16",
|
|
8
|
+
"type": "image/x-icon"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"src": "logo192.png",
|
|
12
|
+
"type": "image/png",
|
|
13
|
+
"sizes": "192x192"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"src": "logo512.png",
|
|
17
|
+
"type": "image/png",
|
|
18
|
+
"sizes": "512x512"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"start_url": ".",
|
|
22
|
+
"display": "standalone",
|
|
23
|
+
"theme_color": "#000000",
|
|
24
|
+
"background_color": "#ffffff"
|
|
25
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React, { useState, useMemo } from "react";
|
|
2
|
+
import PDLJS from "peopledatalabs";
|
|
3
|
+
|
|
4
|
+
import { LinearProgress, TextField, Autocomplete, Grid } from "@mui/material";
|
|
5
|
+
|
|
6
|
+
import { ucFirstLetters } from "@aclymatepackages/formatters";
|
|
7
|
+
import { incorrectNameCheck } from "@aclymatepackages/other-helpers";
|
|
8
|
+
|
|
9
|
+
const CompaniesAutocomplete = ({
|
|
10
|
+
setCompanyName,
|
|
11
|
+
onSelectCompany,
|
|
12
|
+
label,
|
|
13
|
+
variant = "outlined",
|
|
14
|
+
size = "medium",
|
|
15
|
+
disabled,
|
|
16
|
+
helperText = "",
|
|
17
|
+
id,
|
|
18
|
+
style,
|
|
19
|
+
textFieldProps,
|
|
20
|
+
pdlApiKey,
|
|
21
|
+
}) => {
|
|
22
|
+
const [nextStepIsLoading, setNextStepIsLoading] = useState(false);
|
|
23
|
+
const [inputValue, setInputValue] = useState("");
|
|
24
|
+
const [options, setOptions] = useState([]);
|
|
25
|
+
|
|
26
|
+
const pdlClient = useMemo(
|
|
27
|
+
() =>
|
|
28
|
+
new PDLJS({
|
|
29
|
+
apiKey: pdlApiKey,
|
|
30
|
+
}),
|
|
31
|
+
[pdlApiKey]
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const fetchCompanies = async (value) => {
|
|
35
|
+
setNextStepIsLoading(true);
|
|
36
|
+
const autocompleteParamsObj = {
|
|
37
|
+
field: "company",
|
|
38
|
+
text: value || inputValue,
|
|
39
|
+
size: 10,
|
|
40
|
+
pretty: true,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return await pdlClient
|
|
44
|
+
.autocomplete(autocompleteParamsObj)
|
|
45
|
+
.then(({ data }) => {
|
|
46
|
+
const capitalizedCompanyNamesOptions = data.map(
|
|
47
|
+
({ name, ...otherProps }) => ({
|
|
48
|
+
name: ucFirstLetters(name),
|
|
49
|
+
...otherProps,
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
setNextStepIsLoading(false);
|
|
53
|
+
setOptions(capitalizedCompanyNamesOptions);
|
|
54
|
+
return data;
|
|
55
|
+
})
|
|
56
|
+
.catch(() => setOptions([]));
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const onInputChange = (_, newInputValue) => {
|
|
60
|
+
if (newInputValue === "I don't see my company") {
|
|
61
|
+
setNextStepIsLoading(false);
|
|
62
|
+
return setCompanyName(inputValue);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setNextStepIsLoading(false);
|
|
66
|
+
setInputValue(newInputValue);
|
|
67
|
+
if (newInputValue === "") {
|
|
68
|
+
return setOptions([]);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return fetchCompanies();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const isError = !!inputValue && incorrectNameCheck(inputValue, 60);
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Grid container spacing={1} direction="column">
|
|
78
|
+
<Grid item>
|
|
79
|
+
<Autocomplete
|
|
80
|
+
id={id || "companies-autocomplete"}
|
|
81
|
+
freeSolo
|
|
82
|
+
options={[...options, "I don't see my company"]}
|
|
83
|
+
getOptionLabel={(option) =>
|
|
84
|
+
typeof option === "string" ? option : option.name || ""
|
|
85
|
+
}
|
|
86
|
+
filterOptions={(option) => option}
|
|
87
|
+
autoComplete
|
|
88
|
+
includeInputInList
|
|
89
|
+
disabled={disabled}
|
|
90
|
+
renderInput={(params) => (
|
|
91
|
+
<TextField
|
|
92
|
+
id="companies-autocomplete-input"
|
|
93
|
+
{...params}
|
|
94
|
+
label={label}
|
|
95
|
+
variant={variant}
|
|
96
|
+
error={isError}
|
|
97
|
+
size={size}
|
|
98
|
+
autoComplete="off"
|
|
99
|
+
helperText={
|
|
100
|
+
isError ? "This company name is not valid" : helperText || ""
|
|
101
|
+
}
|
|
102
|
+
style={style}
|
|
103
|
+
{...textFieldProps}
|
|
104
|
+
/>
|
|
105
|
+
)}
|
|
106
|
+
getOptionSelected={(option, value) =>
|
|
107
|
+
option === "" || option.name === value.name || option === value
|
|
108
|
+
}
|
|
109
|
+
value={inputValue}
|
|
110
|
+
onChange={(_, newValue) => {
|
|
111
|
+
setOptions(newValue ? [newValue, ...options] : options);
|
|
112
|
+
return onSelectCompany(newValue);
|
|
113
|
+
}}
|
|
114
|
+
onInputChange={onInputChange}
|
|
115
|
+
/>
|
|
116
|
+
</Grid>
|
|
117
|
+
{nextStepIsLoading && (
|
|
118
|
+
<Grid item>
|
|
119
|
+
<LinearProgress />
|
|
120
|
+
</Grid>
|
|
121
|
+
)}
|
|
122
|
+
</Grid>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
export default CompaniesAutocomplete;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { Container, Grid } from "@mui/material";
|
|
4
|
+
|
|
5
|
+
import { TextField } from "@aclymatepackages/atoms";
|
|
6
|
+
import { editObjectData } from "@aclymatepackages/array-immutability-helpers";
|
|
7
|
+
import { numbersRegExpTest } from "@aclymatepackages/reg-exp";
|
|
8
|
+
import { MultiPartFormLayout } from "@aclymatepackages/multi-part-form";
|
|
9
|
+
import mainTheme from "@aclymatepackages/themes";
|
|
10
|
+
|
|
11
|
+
import IndustryAutocomplete from "./IndustryAutocomplete";
|
|
12
|
+
import YesNoQuestion from "./YesNoQuestion";
|
|
13
|
+
import PlacesAutocompleteModule from "./PlacesAutocomplete";
|
|
14
|
+
|
|
15
|
+
const CompanyOnboardingInput = ({
|
|
16
|
+
companyName,
|
|
17
|
+
header,
|
|
18
|
+
onFormComplete,
|
|
19
|
+
PlacesAutocomplete,
|
|
20
|
+
theme,
|
|
21
|
+
}) => {
|
|
22
|
+
const [inputData, setInputData] = useState({ name: companyName });
|
|
23
|
+
|
|
24
|
+
const editInputData = (field) => (value) =>
|
|
25
|
+
editObjectData(setInputData, field, value);
|
|
26
|
+
|
|
27
|
+
const { location, industry, employeeCount, isRemote, name } = inputData;
|
|
28
|
+
|
|
29
|
+
const PlacesAutocompleteComponent =
|
|
30
|
+
PlacesAutocomplete || PlacesAutocompleteModule;
|
|
31
|
+
|
|
32
|
+
const nonPeopleDataLabsCompanyInputs = [
|
|
33
|
+
{
|
|
34
|
+
label: "How many employees work for your company?",
|
|
35
|
+
value: employeeCount,
|
|
36
|
+
editData: editInputData("employeeCount"),
|
|
37
|
+
error:
|
|
38
|
+
!numbersRegExpTest(employeeCount) ||
|
|
39
|
+
employeeCount < 0 ||
|
|
40
|
+
employeeCount > 10000 ||
|
|
41
|
+
!Number.isInteger(Number(employeeCount)),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
value: industry,
|
|
45
|
+
input: (
|
|
46
|
+
<IndustryAutocomplete
|
|
47
|
+
label="Choose your company's industry"
|
|
48
|
+
industry={industry}
|
|
49
|
+
setIndustry={editInputData("industry")}
|
|
50
|
+
helperText="We'll use this to estimate your emissions and benchmark to other similar companies"
|
|
51
|
+
/>
|
|
52
|
+
),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
value: location,
|
|
56
|
+
input: (
|
|
57
|
+
<PlacesAutocompleteComponent
|
|
58
|
+
place={location}
|
|
59
|
+
editPlace={editInputData("location")}
|
|
60
|
+
size="small"
|
|
61
|
+
label="What's your company's primary address?"
|
|
62
|
+
helperText="We only need your physical address, not your suite number"
|
|
63
|
+
id="company-address-autocomplete"
|
|
64
|
+
/>
|
|
65
|
+
),
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
value: isRemote !== undefined,
|
|
69
|
+
input: (
|
|
70
|
+
<YesNoQuestion
|
|
71
|
+
question="Does your company only work remotely?"
|
|
72
|
+
value={isRemote}
|
|
73
|
+
setValue={editInputData("isRemote")}
|
|
74
|
+
lightBackground
|
|
75
|
+
/>
|
|
76
|
+
),
|
|
77
|
+
onNextStep: () => onFormComplete(inputData),
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
const formInputArray = nonPeopleDataLabsCompanyInputs.map((input) => ({
|
|
82
|
+
...input,
|
|
83
|
+
form: "onboarding",
|
|
84
|
+
}));
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<Container maxWidth="sm">
|
|
88
|
+
<Grid container direction="column" spacing={2}>
|
|
89
|
+
{header}
|
|
90
|
+
<Grid item>
|
|
91
|
+
<TextField
|
|
92
|
+
value={name}
|
|
93
|
+
setValue={editInputData("name")}
|
|
94
|
+
variant="standard"
|
|
95
|
+
label="What is your company's name?"
|
|
96
|
+
/>
|
|
97
|
+
</Grid>
|
|
98
|
+
<Grid item xs={12}>
|
|
99
|
+
<MultiPartFormLayout
|
|
100
|
+
forms={[{ name: "onboarding", label: "Onboarding" }]}
|
|
101
|
+
rows={formInputArray}
|
|
102
|
+
confirmClose={false}
|
|
103
|
+
theme={theme || mainTheme}
|
|
104
|
+
styleProps={{ padding: 0 }}
|
|
105
|
+
p={0}
|
|
106
|
+
noGutter
|
|
107
|
+
/>
|
|
108
|
+
</Grid>
|
|
109
|
+
</Grid>
|
|
110
|
+
</Container>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
export default CompanyOnboardingInput;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { Box, Grid, Typography, Tooltip } from "@mui/material";
|
|
4
|
+
import { ThemeProvider } from "@mui/material/styles";
|
|
5
|
+
|
|
6
|
+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
7
|
+
|
|
8
|
+
import { tonsToLbs } from "@aclymatepackages/converters";
|
|
9
|
+
import { formatDecimal } from "@aclymatepackages/formatters";
|
|
10
|
+
import {
|
|
11
|
+
mergeDarkTheme,
|
|
12
|
+
useLayoutHelpers,
|
|
13
|
+
isColorDarkTheme,
|
|
14
|
+
mergeMainTheme,
|
|
15
|
+
} from "@aclymatepackages/themes";
|
|
16
|
+
|
|
17
|
+
const GraphBar = ({
|
|
18
|
+
color,
|
|
19
|
+
categoryMaxTons,
|
|
20
|
+
dataCategoryTons,
|
|
21
|
+
left,
|
|
22
|
+
isUnitsTons,
|
|
23
|
+
}) => {
|
|
24
|
+
const { theme, isMobile } = useLayoutHelpers();
|
|
25
|
+
|
|
26
|
+
const displayColor = theme.palette[color].main;
|
|
27
|
+
|
|
28
|
+
const maxPercentage = dataCategoryTons / categoryMaxTons;
|
|
29
|
+
|
|
30
|
+
const barPercentage = maxPercentage * 100;
|
|
31
|
+
|
|
32
|
+
const barSize = isMobile ? 40 : 50;
|
|
33
|
+
|
|
34
|
+
const dataCategoryDisplayValue = isUnitsTons
|
|
35
|
+
? dataCategoryTons
|
|
36
|
+
: Math.round(tonsToLbs(dataCategoryTons));
|
|
37
|
+
|
|
38
|
+
const SmallBarAnnotation = () => (
|
|
39
|
+
<Box
|
|
40
|
+
style={{
|
|
41
|
+
height: barSize - 10,
|
|
42
|
+
width: barSize - 10,
|
|
43
|
+
backgroundColor: "white",
|
|
44
|
+
borderRadius: "50%",
|
|
45
|
+
border: `${displayColor} solid thin`,
|
|
46
|
+
color: displayColor,
|
|
47
|
+
}}
|
|
48
|
+
display="flex"
|
|
49
|
+
alignItems="center"
|
|
50
|
+
justifyContent="center"
|
|
51
|
+
>
|
|
52
|
+
<Typography
|
|
53
|
+
variant={isMobile ? "caption" : "subtitle1"}
|
|
54
|
+
align="center"
|
|
55
|
+
color={isColorDarkTheme(displayColor) ? "secondary" : "textPrimary"}
|
|
56
|
+
>
|
|
57
|
+
{formatDecimal(dataCategoryDisplayValue)}
|
|
58
|
+
</Typography>
|
|
59
|
+
</Box>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const barPercentageMobileBreakPoint = isMobile ? 25 : 15;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<ThemeProvider
|
|
66
|
+
theme={isColorDarkTheme(displayColor) ? mergeDarkTheme : mergeMainTheme}
|
|
67
|
+
>
|
|
68
|
+
<Box
|
|
69
|
+
display="flex"
|
|
70
|
+
justifyContent={left ? "flex-end" : "flex-start"}
|
|
71
|
+
alignItems="center"
|
|
72
|
+
>
|
|
73
|
+
{barPercentage < barPercentageMobileBreakPoint && left && (
|
|
74
|
+
<SmallBarAnnotation />
|
|
75
|
+
)}
|
|
76
|
+
<Box
|
|
77
|
+
style={{
|
|
78
|
+
width: `${barPercentage > 100 ? 100 : barPercentage}%`,
|
|
79
|
+
height: `${barSize}px`,
|
|
80
|
+
backgroundColor: displayColor,
|
|
81
|
+
borderRadius: left ? "25px 0 0 25px" : "0 25px 25px 0",
|
|
82
|
+
}}
|
|
83
|
+
display="flex"
|
|
84
|
+
alignItems="center"
|
|
85
|
+
justifyContent="center"
|
|
86
|
+
>
|
|
87
|
+
{barPercentage > barPercentageMobileBreakPoint && (
|
|
88
|
+
<div>
|
|
89
|
+
<Typography
|
|
90
|
+
variant={isMobile ? "subtitle1" : "h6"}
|
|
91
|
+
color="textPrimary"
|
|
92
|
+
align="center"
|
|
93
|
+
>
|
|
94
|
+
{`${formatDecimal(dataCategoryDisplayValue)}`}
|
|
95
|
+
</Typography>
|
|
96
|
+
</div>
|
|
97
|
+
)}
|
|
98
|
+
</Box>
|
|
99
|
+
{barPercentage < barPercentageMobileBreakPoint && !left && (
|
|
100
|
+
<SmallBarAnnotation />
|
|
101
|
+
)}
|
|
102
|
+
</Box>
|
|
103
|
+
</ThemeProvider>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const GraphRow = ({
|
|
108
|
+
category,
|
|
109
|
+
idx,
|
|
110
|
+
individualData,
|
|
111
|
+
comparisonData,
|
|
112
|
+
categories,
|
|
113
|
+
isUnitsTons,
|
|
114
|
+
}) => {
|
|
115
|
+
const { theme, isMobile } = useLayoutHelpers();
|
|
116
|
+
|
|
117
|
+
const { color, title, icon, type, categoryMaxTons } = category;
|
|
118
|
+
|
|
119
|
+
const individualTons = individualData[`${type}Tons`] || 0;
|
|
120
|
+
const comparisonTons = comparisonData[`${type}Tons`];
|
|
121
|
+
const barDisplayMaxTons =
|
|
122
|
+
categoryMaxTons > individualTons ? categoryMaxTons : individualTons;
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<Grid
|
|
126
|
+
item
|
|
127
|
+
container
|
|
128
|
+
justifyContent="center"
|
|
129
|
+
alignItems="center"
|
|
130
|
+
wrap="nowrap"
|
|
131
|
+
>
|
|
132
|
+
<Grid item xs={5}>
|
|
133
|
+
<GraphBar
|
|
134
|
+
{...category}
|
|
135
|
+
categoryMaxTons={barDisplayMaxTons}
|
|
136
|
+
dataCategoryTons={individualTons}
|
|
137
|
+
isUnitsTons={isUnitsTons}
|
|
138
|
+
left
|
|
139
|
+
/>
|
|
140
|
+
</Grid>
|
|
141
|
+
<Grid item xs="auto">
|
|
142
|
+
<Box
|
|
143
|
+
style={{
|
|
144
|
+
height: isMobile ? "65px" : "85px",
|
|
145
|
+
width: isMobile ? "65px" : "85px",
|
|
146
|
+
backgroundColor: theme.palette.backgroundGray.dark,
|
|
147
|
+
borderRadius: !idx
|
|
148
|
+
? "8px 8px 0 0"
|
|
149
|
+
: idx === categories.length - 1
|
|
150
|
+
? "0 0 8px 8px"
|
|
151
|
+
: 0,
|
|
152
|
+
}}
|
|
153
|
+
display="flex"
|
|
154
|
+
alignItems="center"
|
|
155
|
+
justifyContent="center"
|
|
156
|
+
>
|
|
157
|
+
<Tooltip
|
|
158
|
+
title={title}
|
|
159
|
+
key={`comparison-graphic-category-icon-${idx}`}
|
|
160
|
+
>
|
|
161
|
+
<Box
|
|
162
|
+
style={{
|
|
163
|
+
backgroundColor: theme.palette[color].main,
|
|
164
|
+
height: isMobile ? "50px" : "70px",
|
|
165
|
+
width: isMobile ? "50px" : "70px",
|
|
166
|
+
borderRadius: "50%",
|
|
167
|
+
}}
|
|
168
|
+
display="flex"
|
|
169
|
+
alignItems="center"
|
|
170
|
+
justifyContent="center"
|
|
171
|
+
>
|
|
172
|
+
<FontAwesomeIcon
|
|
173
|
+
icon={icon}
|
|
174
|
+
size={isMobile ? "1x" : "2x"}
|
|
175
|
+
style={{ color: "white" }}
|
|
176
|
+
/>
|
|
177
|
+
</Box>
|
|
178
|
+
</Tooltip>
|
|
179
|
+
</Box>
|
|
180
|
+
</Grid>
|
|
181
|
+
<Grid item xs={5}>
|
|
182
|
+
<GraphBar
|
|
183
|
+
{...category}
|
|
184
|
+
categoryMaxTons={barDisplayMaxTons}
|
|
185
|
+
dataCategoryTons={comparisonTons}
|
|
186
|
+
isUnitsTons={isUnitsTons}
|
|
187
|
+
/>
|
|
188
|
+
</Grid>
|
|
189
|
+
</Grid>
|
|
190
|
+
);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const ComparisonChart = ({
|
|
194
|
+
individualData,
|
|
195
|
+
comparisonData,
|
|
196
|
+
categories,
|
|
197
|
+
youTitle = "You",
|
|
198
|
+
comparisonTitle = "US Average",
|
|
199
|
+
isUnitsTons,
|
|
200
|
+
}) => {
|
|
201
|
+
const { isMobile } = useLayoutHelpers();
|
|
202
|
+
|
|
203
|
+
return (
|
|
204
|
+
<Grid container direction="column">
|
|
205
|
+
<Grid item container alignItems="flex-end">
|
|
206
|
+
<Grid item xs={5}>
|
|
207
|
+
<Typography variant={isMobile ? "subtitle1" : "h5"} align="center">
|
|
208
|
+
{youTitle}
|
|
209
|
+
</Typography>
|
|
210
|
+
</Grid>
|
|
211
|
+
<Grid item xs={2}>
|
|
212
|
+
<Typography variant={isMobile ? "h5" : "h3"} align="center">
|
|
213
|
+
VS
|
|
214
|
+
</Typography>
|
|
215
|
+
</Grid>
|
|
216
|
+
<Grid item xs={5}>
|
|
217
|
+
<Typography variant={isMobile ? "subtitle1" : "h5"} align="center">
|
|
218
|
+
{comparisonTitle}
|
|
219
|
+
</Typography>
|
|
220
|
+
</Grid>
|
|
221
|
+
</Grid>
|
|
222
|
+
{categories.map((category, idx) => (
|
|
223
|
+
<GraphRow
|
|
224
|
+
idx={idx}
|
|
225
|
+
key={`comparison-graph-row-${idx}`}
|
|
226
|
+
individualData={individualData}
|
|
227
|
+
comparisonData={comparisonData}
|
|
228
|
+
categories={categories}
|
|
229
|
+
category={category}
|
|
230
|
+
isUnitsTons={isUnitsTons}
|
|
231
|
+
/>
|
|
232
|
+
))}
|
|
233
|
+
</Grid>
|
|
234
|
+
);
|
|
235
|
+
};
|
|
236
|
+
export default ComparisonChart;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { Grid, Typography, Avatar } from "@mui/material";
|
|
4
|
+
|
|
5
|
+
import { ucFirstLetters } from "@aclymatepackages/formatters";
|
|
6
|
+
|
|
7
|
+
const CustomTooltipDisplayRow = ({
|
|
8
|
+
category,
|
|
9
|
+
Icon,
|
|
10
|
+
icon,
|
|
11
|
+
customAvatar,
|
|
12
|
+
color,
|
|
13
|
+
name,
|
|
14
|
+
subtitle,
|
|
15
|
+
}) => (
|
|
16
|
+
<Grid item container spacing={1} wrap="nowrap" alignItems="center">
|
|
17
|
+
<Grid item>
|
|
18
|
+
{customAvatar || (
|
|
19
|
+
<Avatar style={{ backgroundColor: color, color: "white" }}>
|
|
20
|
+
{icon}
|
|
21
|
+
{Icon && <Icon style={{ color: "inherit" }} />}
|
|
22
|
+
</Avatar>
|
|
23
|
+
)}
|
|
24
|
+
</Grid>
|
|
25
|
+
<Grid item container direction="column" wrap="nowrap">
|
|
26
|
+
<Grid item xs={12}>
|
|
27
|
+
<Typography
|
|
28
|
+
variant="subtitle1"
|
|
29
|
+
color="textPrimary"
|
|
30
|
+
noWrap
|
|
31
|
+
>{`${ucFirstLetters(name || category)}`}</Typography>
|
|
32
|
+
</Grid>
|
|
33
|
+
<Grid item xs={12}>
|
|
34
|
+
<Typography variant="caption" color="textSecondary">
|
|
35
|
+
{subtitle}
|
|
36
|
+
</Typography>
|
|
37
|
+
</Grid>
|
|
38
|
+
</Grid>
|
|
39
|
+
</Grid>
|
|
40
|
+
);
|
|
41
|
+
export default CustomTooltipDisplayRow;
|