-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2907 range slider component #2938
Draft
fpigeonjr
wants to merge
36
commits into
main
Choose a base branch
from
2907-range-slider-component
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+412
−157
Draft
Changes from all commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
803b21c
Add range slider component using react-slider
maiyerlee 2377b24
Add fieldset tags to slider
maiyerlee 54e82c7
Fix key warnings
maiyerlee 3d7d7c4
Add FY budget combo box component
maiyerlee 590c995
Add FY budget range calculation
maiyerlee 767b608
refactor: adds handleChange logix (#2925)
fpigeonjr 974ce75
Merge branch 'main' into 2907-range-slider-component
fpigeonjr 4f50a34
deps: adds react-slider and styled-components
fpigeonjr 16a8a43
style: adds UX fixes
fpigeonjr 425b34a
refactor: better var names
fpigeonjr 8e54797
filtering is kinda working
fpigeonjr 9e03fd5
Merge branch 'main' into 2907-range-slider-component
fpigeonjr b0a4c15
chore: updates deps
fpigeonjr 52e27e4
Merge branch 'main' into 2907-range-slider-component
fpigeonjr 162e953
chore: updates deps
fpigeonjr e1a7a0a
wip (#2944)
fpigeonjr bbff0d9
wip: fix range text and FY values (#2946)
maiyerlee e1b856d
refactor: raises and persists budget state
fpigeonjr 7a2a802
refactor: better state
fpigeonjr 69e215d
docs: adds JSDocs
fpigeonjr 01c571e
fix: fixes reset
fpigeonjr 8ae6575
refactor: adds helper fns
fpigeonjr 6d0c622
chore: cleanup
fpigeonjr 08d5fd3
Merge branch 'main' into 2907-range-slider-component
fpigeonjr e38554a
chore: adds deps
fpigeonjr 10c9221
test: builds
fpigeonjr 301ff78
wip: bring back the linting
fpigeonjr 41a679a
chore: install deps
fpigeonjr 421239a
style: match icon color on disable state
fpigeonjr 7d54126
style: TBD for 0 value FY Budgets
fpigeonjr 9e81076
docs: adds JSDocs annotations
fpigeonjr 760f932
feat: adds pills
fpigeonjr 6696e09
chore: cleanup
fpigeonjr cc232c2
refactor: remove unneeded state
fpigeonjr dd60727
refactor: resets budget state
fpigeonjr ecc556c
chore: cleanup
fpigeonjr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,111 +1,113 @@ | ||
{ | ||
"name": "opre-ops", | ||
"version": "1.0.1", | ||
"license": "CC0-1.0", | ||
"private": true, | ||
"type": "module", | ||
"dependencies": { | ||
"@azure/storage-blob": "^12.24.0", | ||
"@fortawesome/fontawesome-svg-core": "6.5.2", | ||
"@fortawesome/free-regular-svg-icons": "6.5.2", | ||
"@fortawesome/free-solid-svg-icons": "6.5.2", | ||
"@fortawesome/react-fontawesome": "0.2.2", | ||
"@nivo/bar": "0.87.0", | ||
"@nivo/core": "0.87.0", | ||
"@nivo/pie": "0.87.0", | ||
"@reduxjs/toolkit": "2.2.8", | ||
"@uswds/uswds": "3.9.0", | ||
"axios": "1.7.7", | ||
"clsx": "2.1.1", | ||
"crypto-random-string": "5.0.0", | ||
"js-cookie": "3.0.5", | ||
"jwt-decode": "4.0.0", | ||
"lodash": "4.17.21", | ||
"react": "18.3.1", | ||
"react-currency-format": "1.1.0", | ||
"react-dom": "18.3.1", | ||
"react-markdown": "9.0.1", | ||
"react-modal": "3.16.1", | ||
"react-redux": "9.1.2", | ||
"react-router-dom": "6.27.0", | ||
"react-select": "5.8.1", | ||
"sass": "1.79.6", | ||
"sass-loader": "14.2.1", | ||
"vest": "5.4.3", | ||
"@eslint/compat": "1.2.0", | ||
"@eslint/js": "9.12.0", | ||
"@vitejs/plugin-react": "4.3.2", | ||
"eslint": "9.12.0", | ||
"eslint-config-prettier": "9.1.0", | ||
"eslint-plugin-cypress": "4.0.0", | ||
"eslint-plugin-import": "2.29.1", | ||
"eslint-plugin-jest": "28.8.3", | ||
"eslint-plugin-jsx-a11y": "6.10.0", | ||
"eslint-plugin-prettier": "5.2.1", | ||
"eslint-plugin-react": "7.37.1", | ||
"eslint-plugin-react-hooks": "5.0.0", | ||
"eslint-plugin-react-refresh": "0.4.12", | ||
"eslint-plugin-testing-library": "6.3.2", | ||
"jose": "5.9.4", | ||
"jsdom": "25.0.1", | ||
"vite": "5.4.9", | ||
"vite-jsconfig-paths": "2.0.1", | ||
"vite-plugin-babel-macros": "1.0.6", | ||
"vite-plugin-eslint": "1.8.1", | ||
"vite-plugin-svgr": "4.2.0" | ||
}, | ||
"overrides": { | ||
"rollup": "4.24.0" | ||
}, | ||
"devDependencies": { | ||
"@testing-library/jest-dom": "6.5.0", | ||
"@testing-library/react": "16.0.1", | ||
"@testing-library/user-event": "14.5.2", | ||
"@types/testing-library__jest-dom": "6.0.0", | ||
"@types/testing-library__react": "10.2.0", | ||
"@vitest/coverage-istanbul": "2.1.3", | ||
"@vitest/ui": "2.1.3", | ||
"axe-core": "4.10.1", | ||
"cypress": "13.13.3", | ||
"cypress-axe": "1.5.0", | ||
"cypress-localstorage-commands": "2.2.6", | ||
"globals": "15.9.0", | ||
"history": "5.3.0", | ||
"msw": "2.3.5", | ||
"prettier": "3.3.3", | ||
"redux-mock-store": "1.5.4", | ||
"@uswds/compile": "1.2.0", | ||
"vitest": "2.1.3" | ||
}, | ||
"scripts": { | ||
"start": "vite", | ||
"start:debug": "vite --inspect=0.0.0.0:9229", | ||
"build": "vite build", | ||
"test": "vitest", | ||
"test:coverage": "vitest --coverage", | ||
"test:ui": "vitest --ui --coverage.enabled=true", | ||
"test:e2e:interactive": "cypress open --config-file ./cypress.config.js", | ||
"test:e2e": "cypress run --config-file ./cypress.config.js --headless", | ||
"test:e2e:debug": "DEBUG=cypress:* cypress run --config-file ./cypress.config.js --headless", | ||
"lint": "eslint './src/**'", | ||
"cypress:open": "cypress open", | ||
"uswds:update": "bunx gulp compile" | ||
}, | ||
"browserslist": { | ||
"production": [ | ||
">0.2%", | ||
"not dead", | ||
"not op_mini all" | ||
], | ||
"development": [ | ||
"last 1 chrome version", | ||
"last 1 firefox version", | ||
"last 1 safari version" | ||
] | ||
}, | ||
"babelMacros": { | ||
"fontawesome-svg-core": { | ||
"license": "free" | ||
"name": "opre-ops", | ||
"version": "1.0.1", | ||
"license": "CC0-1.0", | ||
"private": true, | ||
"type": "module", | ||
"dependencies": { | ||
"@azure/storage-blob": "12.24.0", | ||
"@eslint/compat": "1.2.0", | ||
"@eslint/js": "9.12.0", | ||
"@fortawesome/fontawesome-svg-core": "6.5.2", | ||
"@fortawesome/free-regular-svg-icons": "6.5.2", | ||
"@fortawesome/free-solid-svg-icons": "6.5.2", | ||
"@fortawesome/react-fontawesome": "0.2.2", | ||
"@nivo/bar": "0.87.0", | ||
"@nivo/core": "0.87.0", | ||
"@nivo/pie": "0.87.0", | ||
"@reduxjs/toolkit": "2.2.8", | ||
"@uswds/uswds": "3.9.0", | ||
"@vitejs/plugin-react": "4.3.2", | ||
"axios": "1.7.7", | ||
"clsx": "2.1.1", | ||
"crypto-random-string": "5.0.0", | ||
"eslint": "9.12.0", | ||
"eslint-config-prettier": "9.1.0", | ||
"eslint-plugin-cypress": "4.0.0", | ||
"eslint-plugin-import": "2.29.1", | ||
"eslint-plugin-jest": "28.8.3", | ||
"eslint-plugin-jsx-a11y": "6.10.0", | ||
"eslint-plugin-prettier": "5.2.1", | ||
"eslint-plugin-react": "7.37.1", | ||
"eslint-plugin-react-hooks": "5.0.0", | ||
"eslint-plugin-react-refresh": "0.4.12", | ||
"eslint-plugin-testing-library": "6.3.2", | ||
"jose": "5.9.4", | ||
"js-cookie": "3.0.5", | ||
"jsdom": "25.0.1", | ||
"jwt-decode": "4.0.0", | ||
"lodash": "4.17.21", | ||
"react": "18.3.1", | ||
"react-currency-format": "1.1.0", | ||
"react-dom": "18.3.1", | ||
"react-markdown": "9.0.1", | ||
"react-modal": "3.16.1", | ||
"react-redux": "9.1.2", | ||
"react-router-dom": "6.27.0", | ||
"react-select": "5.8.1", | ||
"react-slider": "2.0.6", | ||
"sass": "1.79.6", | ||
"sass-loader": "14.2.1", | ||
"styled-components": "6.1.13", | ||
"vest": "5.4.3", | ||
"vite": "5.4.9", | ||
"vite-jsconfig-paths": "2.0.1", | ||
"vite-plugin-babel-macros": "1.0.6", | ||
"vite-plugin-eslint": "1.8.1", | ||
"vite-plugin-svgr": "4.2.0" | ||
}, | ||
"overrides": { | ||
"rollup": "4.24.0" | ||
}, | ||
"devDependencies": { | ||
"@testing-library/jest-dom": "6.5.0", | ||
"@testing-library/react": "16.0.1", | ||
"@testing-library/user-event": "14.5.2", | ||
"@types/testing-library__jest-dom": "6.0.0", | ||
"@types/testing-library__react": "10.2.0", | ||
"@vitest/coverage-istanbul": "2.1.3", | ||
"@vitest/ui": "2.1.3", | ||
"axe-core": "4.10.1", | ||
"cypress": "13.13.3", | ||
"cypress-axe": "1.5.0", | ||
"cypress-localstorage-commands": "2.2.6", | ||
"globals": "15.9.0", | ||
"history": "5.3.0", | ||
"msw": "2.3.5", | ||
"prettier": "3.3.3", | ||
"redux-mock-store": "1.5.4", | ||
"@uswds/compile": "1.2.0", | ||
"vitest": "2.1.3" | ||
}, | ||
"scripts": { | ||
"start": "vite", | ||
"start:debug": "vite --inspect=0.0.0.0:9229", | ||
"build": "vite build", | ||
"test": "vitest", | ||
"test:coverage": "vitest --coverage", | ||
"test:ui": "vitest --ui --coverage.enabled=true", | ||
"test:e2e:interactive": "cypress open --config-file ./cypress.config.js", | ||
"test:e2e": "cypress run --config-file ./cypress.config.js --headless", | ||
"test:e2e:debug": "DEBUG=cypress:* cypress run --config-file ./cypress.config.js --headless", | ||
"lint": "eslint './src/**'", | ||
"cypress:open": "cypress open", | ||
"uswds:update": "bunx gulp compile" | ||
}, | ||
"browserslist": { | ||
"production": [ | ||
">0.2%", | ||
"not dead", | ||
"not op_mini all" | ||
], | ||
"development": [ | ||
"last 1 chrome version", | ||
"last 1 firefox version", | ||
"last 1 safari version" | ||
] | ||
}, | ||
"babelMacros": { | ||
"fontawesome-svg-core": { | ||
"license": "free" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
frontend/src/components/CANs/CANFYBudgetRangeSlider/CANFYBudgetRangeSlider.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import React from "react"; | ||
import DoubleRangeSlider from "../../UI/DoubleRangeSlider"; | ||
import CurrencyFormat from "react-currency-format"; | ||
/** | ||
* @typedef {Object} CANFYBudgetRangeSliderProps | ||
* @property {[number, number]} fyBudgetRange - The min and max of the fiscal year budget range | ||
* @property {string} [legendClassname] - CSS class for the legend | ||
* @property {[number, number]} budget - The current budget range | ||
* @property {function([number, number]): void} setBudget - Function to update the budget | ||
*/ | ||
|
||
/** | ||
* @description CANFYBudgetRangeSlider component | ||
* @component | ||
* @param {CANFYBudgetRangeSliderProps} props | ||
* @returns {JSX.Element} - The CAN FY Budget Range Slider component | ||
*/ | ||
const CANFYBudgetRangeSlider = ({ fyBudgetRange, legendClassname = "usa-label margin-top-0", budget, setBudget }) => { | ||
const [minValue, maxValue] = budget; | ||
const [fyBudgetMin, fyBudgetMax] = fyBudgetRange; | ||
const [sliderValue, setSliderValue] = React.useState([0, 100]); | ||
/** | ||
* Calculate percentage of a value within a range | ||
* @param {number} value - The value to calculate percentage for | ||
* @param {number} min - The minimum value of the range | ||
* @param {number} max - The maximum value of the range | ||
* @returns {number} The calculated percentage | ||
*/ | ||
const calculatePercentage = (value, min, max) => { | ||
return ((value - min) / (max - min)) * 100; | ||
}; | ||
/** | ||
* Calculate value based on percentage within a range | ||
* @param {number} percentage - The percentage to calculate value for | ||
* @param {number} min - The minimum value of the range | ||
* @param {number} max - The maximum value of the range | ||
* @returns {number} The calculated value | ||
*/ | ||
const calculateValue = (percentage, min, max) => { | ||
return Math.round(min + (percentage / 100) * (max - min)); | ||
}; | ||
|
||
/** | ||
* Calculate the new budget range based on slider values | ||
* @param {[number, number]} newRange - The new range from the slider | ||
*/ | ||
const calculateBudgetRange = (newRange) => { | ||
const [minPercentage, maxPercentage] = newRange; | ||
const selectedMinFYBudget = calculateValue(minPercentage, fyBudgetMin, fyBudgetMax); | ||
const selectedMaxFYBudget = calculateValue(maxPercentage, fyBudgetMin, fyBudgetMax); | ||
|
||
setBudget([selectedMinFYBudget, selectedMaxFYBudget]); | ||
setSliderValue(newRange); | ||
}; | ||
|
||
React.useEffect(() => { | ||
const minPercentage = calculatePercentage(minValue, fyBudgetMin, fyBudgetMax); | ||
const maxPercentage = calculatePercentage(maxValue, fyBudgetMin, fyBudgetMax); | ||
|
||
setSliderValue([minPercentage, maxPercentage]); | ||
}, [budget, fyBudgetRange]); | ||
|
||
return ( | ||
<> | ||
<div className="display-flex flex-justify"> | ||
<label | ||
className={legendClassname} | ||
htmlFor="can-FY-budgey-combobox-input" | ||
> | ||
FY Budget | ||
</label> | ||
</div> | ||
<div className="padding-right-10"> | ||
<DoubleRangeSlider | ||
handleChange={calculateBudgetRange} | ||
defaultValue={[0, 100]} | ||
value={sliderValue} | ||
/> | ||
</div> | ||
|
||
<div className="margin-top-1 display-flex flex-justify-center font-12px padding-right-10"> | ||
<span> | ||
<CurrencyFormat | ||
value={minValue} | ||
decimalScale={2} | ||
thousandSeparator={true} | ||
displayType="text" | ||
prefix={"$ "} | ||
/> | ||
<span> - </span> | ||
<CurrencyFormat | ||
value={maxValue} | ||
decimalScale={2} | ||
thousandSeparator={true} | ||
displayType="text" | ||
prefix={"$ "} | ||
/> | ||
</span> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export default CANFYBudgetRangeSlider; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from "./CANFYBudgetRangeSlider.jsx"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
may consider removing this dependency in favor of css modules