From f3dcdf1bf5d146b2a8a1d4d0a049f6b5f67b84c8 Mon Sep 17 00:00:00 2001 From: Jeff Bliss Date: Thu, 14 Nov 2024 10:54:29 -0500 Subject: [PATCH] basic functionality of adding self service is working --- package-lock.json | 16 +++ package.json | 3 +- src/components/Cell.jsx | 55 ++++++--- src/components/CommunityPane.jsx | 174 ++++++++++++++-------------- src/components/DropDownSelector.jsx | 153 +++++++++--------------- src/components/Section.jsx | 96 +++++++++------ src/pages/SelfServicePage.jsx | 144 +++++++++++++---------- 7 files changed, 346 insertions(+), 295 deletions(-) diff --git a/package-lock.json b/package-lock.json index d758dda..566a18b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@mui/icons-material": "^5.16.6", "@mui/material": "^5.16.6", "airtable": "^0.12.2", + "prettier": "^3.3.3", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.26.0" @@ -3906,6 +3907,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", diff --git a/package.json b/package.json index 21cc01d..b12b361 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,10 @@ "dependencies": { "@emotion/react": "^11.13.0", "@emotion/styled": "^11.13.0", - "@mui/material": "^5.16.6", "@mui/icons-material": "^5.16.6", + "@mui/material": "^5.16.6", "airtable": "^0.12.2", + "prettier": "^3.3.3", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.26.0" diff --git a/src/components/Cell.jsx b/src/components/Cell.jsx index 3ec96ba..d569110 100644 --- a/src/components/Cell.jsx +++ b/src/components/Cell.jsx @@ -1,34 +1,54 @@ +import { useContext } from 'react'; +import { Box, Button, Typography } from '@mui/material'; -import { useContext } from "react"; -import { Box, Typography } from "@mui/material"; +import { RowHoverContext, SetHoverRowContext } from './RowHoverContext'; -import { RowHoverContext, SetHoverRowContext } from "./RowHoverContext"; +import PractMatchSymbol from './svg/PractMatchSymbol'; -import PractMatchSymbol from "./svg/PractMatchSymbol" +import theme from '../theme'; -import theme from "../theme"; - -export default function Cell ({ label, type, key }) { +export default function Cell(props) { + const { label, type, key, isSelectable, handleRemove, rowToHover } = props; const hoverRow = useContext(RowHoverContext); const setHoverRow = useContext(SetHoverRowContext); let content; if (type === 'community') { - content = - { label } - + content = ( + + {label} + {isSelectable && ( + + )} + + ); } else { - content = PractMatchSymbol({ label }) + content = PractMatchSymbol({ label }); } return ( { + onMouseEnter={(e) => { setHoverRow(key); }} - onMouseLeave={ e => { + onMouseLeave={(e) => { setHoverRow(null); }} - key={ key } + key={key} sx={{ display: 'flex', flexDirection: 'column', @@ -42,8 +62,7 @@ export default function Cell ({ label, type, key }) { justifyContent: 'center', }} > - { content } - - ) + {content} + + ); } - diff --git a/src/components/CommunityPane.jsx b/src/components/CommunityPane.jsx index 9751dad..1e9e79e 100644 --- a/src/components/CommunityPane.jsx +++ b/src/components/CommunityPane.jsx @@ -1,101 +1,105 @@ -import { Typography } from "@mui/material"; -import HeaderBox from "./HeaderBox"; +import { Typography } from '@mui/material'; +import HeaderBox from './HeaderBox'; import ScoreSection from './ScoreSection'; import Pane from './Pane'; import Section from './Section'; import { Box, Stack } from '@mui/material'; import theme from '../theme'; -const getSectionData = (community, isSelectable, availableOptions, onSelectionChange) => [ - { - header: 'State', - cards: community.state, - availableSelections: isSelectable ? availableOptions?.state || [] : [], - }, - { - header: 'Activities', - cards: community.activities, - availableSelections: isSelectable ? availableOptions?.activities || [] : [], - }, - { - header: 'Sectors', - cards: community.sectors, - availableSelections: isSelectable ? availableOptions?.sectors || [] : [], - }, - { - header: 'Hazards', - cards: community.hazards, - availableSelections: isSelectable ? availableOptions?.hazards || [] : [], - }, - { - header: 'Size', - cards: community.size, - availableSelections: isSelectable ? availableOptions?.size || [] : [], - } -].map((section, index) => { - section.type = 'community' - section.key = `section${index}` - section.isSelectable = isSelectable - section.onSelectionChange = onSelectionChange - return section -}); +const getSectionData = (community, isSelectable, availableOptions, onSelectionChange) => + [ + { + header: 'State', + cards: community.state, + availableSelections: isSelectable ? availableOptions?.state || [] : [], + }, + { + header: 'Activities', + cards: community.activities, + availableSelections: isSelectable ? availableOptions?.activities || [] : [], + }, + { + header: 'Sectors', + cards: community.sectors, + availableSelections: isSelectable ? availableOptions?.sectors || [] : [], + }, + { + header: 'Hazards', + cards: community.hazards, + availableSelections: isSelectable ? availableOptions?.hazards || [] : [], + }, + { + header: 'Size', + cards: community.size, + availableSelections: isSelectable ? availableOptions?.size || [] : [], + }, + ].map((section, index) => { + section.type = 'community'; + section.key = `section${index}`; + section.rowToHover = `section${index}`; + section.isSelectable = isSelectable; + section.onSelectionChange = onSelectionChange; + return section; + }); export default function CommunityPane({ - community, - isSelectable = false, - availableOptions = {}, - onSelectionChange = () => {} - }) { + community, + isSelectable = false, + availableOptions = {}, + onSelectionChange = () => {}, +}) { const sectionData = getSectionData(community, isSelectable, availableOptions, onSelectionChange); return ( - + + + + {community.name} + + + {/* filler box to match height of "Matched Practitioners" heading */} + + + + {sectionData.map((section, index) => { + return Section(section); + })} + - - - {community.name} - - {/* filler box to match height of "Matched Practitioners" heading */} - - - - {sectionData.map((section, index) => { - return Section(section) - })} - -
Total
-
{community.totalCategories}
-
-
-
- ) +
Total
+
{community.totalCategories}
+ + + + ); } diff --git a/src/components/DropDownSelector.jsx b/src/components/DropDownSelector.jsx index 22fa504..c14cd1f 100644 --- a/src/components/DropDownSelector.jsx +++ b/src/components/DropDownSelector.jsx @@ -11,106 +11,67 @@ const DropDownSelector = ({ availableSelections, selections, setSelections, opti setIsDropdownOpen(false); }; - const handleRemove = (itemToRemove) => { - setSelections(selections.filter(item => item !== itemToRemove)); - }; - return ( -
- {/* Selected Items */} -
- {selections.map((item) => ( -
- {item} - -
- ))} -
- - {/* Add Button & Dropdown */} -
- +
+ - {isDropdownOpen && ( -
+ {availableSelections + .filter((item) => !selections.includes(item)) + .map((item) => ( + - ))} -
- )} + {item} + + ))}
-
+ )} +
); }; diff --git a/src/components/Section.jsx b/src/components/Section.jsx index 0b27455..c339ae5 100644 --- a/src/components/Section.jsx +++ b/src/components/Section.jsx @@ -1,39 +1,67 @@ -import { Typography, Box, Stack } from "@mui/material" -import Cell from "./Cell" -import DropDownSelector from "./DropDownSelector" -import theme from '../theme' +import { Typography, Box, Stack } from '@mui/material'; +import Cell from './Cell'; +import DropDownSelector from './DropDownSelector'; +import theme from '../theme'; -export default function Section({ header='', type, cards, key, isSelectable, onSelectionChange, availableSelections = [] }) { - const cells = cards.map((label, index) => Cell({ label, type, key: `${key}_row${index}` })) +export default function Section({ + header = '', + type, + cards, + key, + rowToHover, + isSelectable, + onSelectionChange, + availableSelections = [], +}) { + const handleRemove = (itemToRemove) => { + console.log('jeff', itemToRemove); + const newSelections = cards.filter((card) => card !== itemToRemove); + onSelectionChange(header.toLowerCase(), newSelections); + }; + const cells = cards.map((label, index) => + Cell({ + label, + type, + key: `${key}_row${index}`, + isSelectable, + handleRemove, + rowToHover: `${rowToHover}_row${index}`, + }) + ); return ( - - {/* Section Header */} - - {header} - + + + {header} + - {/* Selector if isSelectable */} - {isSelectable && ( - - onSelectionChange(header.toLowerCase(), newSelections)} - option={header} - /> - - )} + + {cells} + - {/* Content */} - - {cells} - - - ) -} \ No newline at end of file + {isSelectable && ( + + onSelectionChange(header.toLowerCase(), newSelections)} + option={header} + /> + + )} + + ); +} diff --git a/src/pages/SelfServicePage.jsx b/src/pages/SelfServicePage.jsx index 660a688..e097ed3 100644 --- a/src/pages/SelfServicePage.jsx +++ b/src/pages/SelfServicePage.jsx @@ -11,14 +11,13 @@ import FullPageSpinner from '../components/FullPageSpinner'; import PractitionerPane from '../components/PractitionerPane'; import CommunityPane from '../components/CommunityPane'; -import { ThemeProvider } from "@mui/material/styles"; +import { ThemeProvider } from '@mui/material/styles'; // theme import theme from '../theme'; import { RowHoverContext, SetHoverRowContext } from '../components/RowHoverContext'; -import DropDownSelector from "../components/DropDownSelector.jsx"; - +import DropDownSelector from '../components/DropDownSelector.jsx'; export default function SelfServicePage() { const [selectedOptions, setSelectedOptions] = useState({ @@ -50,8 +49,8 @@ export default function SelfServicePage() { sectors: selectedOptions.sectors, hazards: selectedOptions.hazards, size: selectedOptions.size, - totalCategories: Object.values(selectedOptions).reduce((sum, arr) => sum + arr.length, 0) - } + totalCategories: Object.values(selectedOptions).reduce((sum, arr) => sum + arr.length, 0), + }; useEffect(() => { const loadOptions = async () => { @@ -59,17 +58,19 @@ export default function SelfServicePage() { await fetchOptionsFromAirtable(setAvailableOptions); }; - loadOptions().then(() => { - setIsLoading(false); - }).catch((err) => { - setError(err); - }); + loadOptions() + .then(() => { + setIsLoading(false); + }) + .catch((err) => { + setError(err); + }); }, []); const handleSelectionChange = (category, newSelections) => { - setSelectedOptions(prev => ({ + setSelectedOptions((prev) => ({ ...prev, - [category]: newSelections + [category]: newSelections, })); }; @@ -81,60 +82,81 @@ export default function SelfServicePage() { return
Loading options...
; } + const practitionerPanes = practitioners.map((pract, index) => { + return ( + + ); + }); + return ( - - - - - - + + + + + + + + {/* Practitioners */} + + - - - {/* Practitioners */} - - + - Matched Practitioners - - - {PractitionerPane} - + Matched + {' '} + Practitioners + + + {practitionerPanes} - - - - + + + + + ); }