Skip to content

Commit

Permalink
Weekly Timebox Frontend Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
jedtan committed Sep 19, 2023
2 parents 9d12600 + 51473f4 commit 31f3d59
Show file tree
Hide file tree
Showing 11 changed files with 257 additions and 15 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
"next-transpile-modules": "^8.0.0",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-color": "^2.19.3",
"react-countdown": "^2.3.5",
"react-dom": "^17.0.2",
"react-firebaseui": "^5.0.2",
"react-relay": "^12.0.0",
Expand Down
71 changes: 71 additions & 0 deletions src/components/BackgroundColorPicker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useCallback, useState } from 'react'
import { makeStyles } from '@material-ui/core/styles'
import { SketchPicker } from 'react-color'
import { Typography } from '@material-ui/core'
import PropTypes from 'prop-types'

const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
flexWrap: 'wrap',
},
gridList: {
display: 'flex',
flexDirection: 'row',
width: '100%',
},
previewContainer: {
marginTop: 0,
margin: theme.spacing(2),
width: '100%',
height: '60%',
},
header: {
paddingLeft: 0,
},
divider: {
marginBottom: 10,
},
}))
const BackgroundColorPicker = ({ user, onBackgroundColorSelection }) => {
const classes = useStyles()
const [selectedColor, setSelectedColor] = useState(
user.backgroundColor || '#000'
)

const onColorChanged = useCallback(
(color) => {
setSelectedColor(color.hex)
onBackgroundColorSelection(color.hex)
},
[onBackgroundColorSelection]
)

return (
<div className={classes.root}>
<Typography>Select your color</Typography>
<div className={classes.gridList}>
<SketchPicker
color={selectedColor}
disableAlpha
onChangeComplete={onColorChanged}
/>
<div
className={classes.previewContainer}
style={{
backgroundColor: selectedColor,
}}
/>
</div>
</div>
)
}

BackgroundColorPicker.propTypes = {
user: PropTypes.shape({
backgroundColor: PropTypes.string.isRequired,
}).isRequired,
onBackgroundColorSelection: PropTypes.func.isRequired,
}

export default BackgroundColorPicker
37 changes: 37 additions & 0 deletions src/components/BackgroundColorPicker.stories.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react'
import { makeStyles } from '@material-ui/core/styles'
import blue from '@material-ui/core/colors/blue'
import BackgroundColorPicker from './BackgroundColorPicker'

export default {
title: 'Components/BackgroundColorPicker',
component: BackgroundColorPicker,
}

const useStyles = makeStyles(() => ({
templateContainer: {
background: blue['200'],
height: 700,
},
}))

// eslint-disable-next-line react/jsx-props-no-spreading
const Template = (args) => {
const classes = useStyles()
return (
<div className={classes.templateContainer}>
<BackgroundColorPicker {...args} />
</div>
)
}

export const normal = Template.bind({})
normal.args = {
user: {
backgroundColor: '#138',
},
onBackgroundColorSelection: () => {
// eslint-disable-next-line no-console
console.log('onBackgroundColorSelection')
},
}
40 changes: 40 additions & 0 deletions src/components/__tests__/BackgroundColorPicker.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react'
import { shallow } from 'enzyme'
import { SketchPicker } from 'react-color'

jest.mock('react-color')

const mockOnBackgroundColorSelection = jest.fn()
const mockProps = {
user: {
backgroundColor: '#FF0000',
},
onBackgroundColorSelection: mockOnBackgroundColorSelection,
}

afterEach(() => {
jest.clearAllMocks()
})

describe('Background color picker component', () => {
it('renders without error', () => {
const BackgroundColorPicker =
require('src/components/BackgroundColorPicker').default
expect(() =>
shallow(<BackgroundColorPicker {...mockProps} />)
).not.toThrow()
})

it('calls onBackgroundColorSelection callback when the color changes', () => {
const BackgroundColorPicker =
require('src/components/BackgroundColorPicker').default
const wrapper = shallow(<BackgroundColorPicker {...mockProps} />)

// Mock that our color picker fires its change callback
const colorData = {
hex: '#CDCDCD',
}
wrapper.find(SketchPicker).prop('onChangeComplete')(colorData)
expect(mockOnBackgroundColorSelection).toHaveBeenCalledWith('#CDCDCD')
})
})
16 changes: 12 additions & 4 deletions src/components/groupImpactComponents/GroupGoalNotification.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ArrowForwardIos } from '@material-ui/icons'
import { GROUP_IMPACT_SIDEBAR_STATE } from 'src/utils/constants'
import gtag from 'ga-gtag'
import Handlebars from 'handlebars'
import moment from 'moment'
import Notification from '../Notification'

const useStyles = makeStyles((theme) => ({
Expand Down Expand Up @@ -64,6 +65,7 @@ const GroupGoalNotification = ({
onGoalStarted,
impactTitle,
impactCountPerMetric,
dateStarted,
}) => {
const impactTitleTemplate = Handlebars.compile(impactTitle)
const impactTitleCompiled = impactTitleTemplate({
Expand Down Expand Up @@ -93,6 +95,10 @@ const GroupGoalNotification = ({
onGoalStarted()
}, [mode, onGoalStarted])

const dateStartedMoment = dateStarted && moment(dateStarted).format('l')
const startingString = `${
mode === GROUP_IMPACT_SIDEBAR_STATE.COMPLETED ? 'COMPLETED' : 'GOAL STARTED'
}${dateStarted ? ` - Week of ${dateStartedMoment}` : ''}`
return (
<div className={classes.wrapper}>
<Notification
Expand All @@ -101,10 +107,7 @@ const GroupGoalNotification = ({
open={open}
text={
<Typography className={classes.notificationText} variant="body2">
{mode === GROUP_IMPACT_SIDEBAR_STATE.COMPLETED
? 'COMPLETED'
: 'GOAL STARTED'}
: {impactTitleCompiled}
{startingString}: {impactTitleCompiled}
</Typography>
}
buttons={
Expand Down Expand Up @@ -151,6 +154,11 @@ GroupGoalNotification.propTypes = {
onGoalStarted: PropTypes.func.isRequired,
impactTitle: PropTypes.string.isRequired,
impactCountPerMetric: PropTypes.number.isRequired,
dateStarted: PropTypes.string,
}

GroupGoalNotification.defaultProps = {
dateStarted: null,
}

export default GroupGoalNotification
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ started.args = {
mode: GROUP_IMPACT_SIDEBAR_STATE.NEW,
impactTitle: 'Fund {{count}} visits from a community healthworker',
impactCountPerMetric: 3,
dateStarted: '2020-01-10T10:00:00.000Z',
}
15 changes: 13 additions & 2 deletions src/components/groupImpactComponents/GroupImpact.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,14 @@ const GroupImpact = ({ user }) => {
GROUP_IMPACT_SIDEBAR_STATE.NORMAL
)
const [sidebarOpen, setSidebarOpen] = useState(false)
const { id, dollarGoal, dollarProgressFromSearch, impactMetric } =
groupImpactMetric
const {
id,
dollarGoal,
dollarProgressFromSearch,
impactMetric,
dateStarted,
dateExpires,
} = groupImpactMetric
const { impactTitle, impactCountPerMetric, whyValuableDescription } =
impactMetric

Expand Down Expand Up @@ -192,6 +198,7 @@ const GroupImpact = ({ user }) => {
onNextGoal={beginNewGoal}
onGoalStarted={onGoalStarted}
impactCountPerMetric={impactCountPerMetric}
dateStarted={dateExpires ? dateStarted : null}
/>
</div>
</Fade>
Expand All @@ -215,6 +222,8 @@ GroupImpact.propTypes = {
whyValuableDescription: PropTypes.string.isRequired,
impactCountPerMetric: PropTypes.number.isRequired,
}),
dateStarted: PropTypes.string,
dateExpires: PropTypes.string,
}).isRequired,
groupImpactMetricCount: PropTypes.number,
}).isRequired,
Expand Down Expand Up @@ -260,6 +269,8 @@ GroupImpactWrapper.propTypes = {
whyValuableDescription: PropTypes.string.isRequired,
impactCountPerMetric: PropTypes.number,
}),
dateStarted: PropTypes.string,
dateExpires: PropTypes.string,
}),
groupImpactMetricCount: PropTypes.number,
}).isRequired,
Expand Down
2 changes: 2 additions & 0 deletions src/components/groupImpactComponents/GroupImpact.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ standardView.args = {
'Community health workers provide quality health care to those who might not otherwise have access.',
impactCountPerMetric: 3,
},
dateStarted: '2020-01-10T10:00:00.000Z',
dateExpires: '2020-07-10T10:00:00.000Z',
},
},
},
Expand Down
2 changes: 2 additions & 0 deletions src/components/groupImpactComponents/GroupImpactContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export default createFragmentContainer(GroupImpact, {
whyValuableDescription
impactCountPerMetric
}
dateStarted
dateExpires
}
groupImpactMetricCount
}
Expand Down
27 changes: 24 additions & 3 deletions src/components/groupImpactComponents/GroupImpactSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import SearchIcon from '@material-ui/icons/Search'
import TabIcon from '@material-ui/icons/Tab'
import ToggleButton from '@material-ui/lab/ToggleButton'
import ToggleButtonGroup from '@material-ui/lab/ToggleButtonGroup'
import Countdown from 'react-countdown'
import VerticalLinearProgress from '../VerticalLinearProgress'
import GroupImpactLeaderboard from './GroupImpactLeaderboard'
import GroupImpactContributionWidget from './GroupImpactContributionWidget'
Expand Down Expand Up @@ -253,8 +254,15 @@ const GroupImpactSidebar = ({
setSelectedMode(newValue)
event.stopPropagation()
}
const { dollarProgress, dollarGoal, dollarProgressFromSearch, impactMetric } =
displayingOldGoal ? lastGroupImpactMetric : groupImpactMetric

const {
dollarProgress,
dollarGoal,
dollarProgressFromSearch,
impactMetric,
dateExpires,
} = displayingOldGoal ? lastGroupImpactMetric : groupImpactMetric

const { impactTitle, whyValuableDescription, impactCountPerMetric } =
impactMetric
const classes = useStyles()
Expand Down Expand Up @@ -406,7 +414,7 @@ const GroupImpactSidebar = ({
<div className={classes.sidebarText}>
<div className={classes.goalText}>
<Typography className={classes.robotoBold} variant="h5">
GROUP GOAL
{`${dateExpires ? 'WEEKLY ' : ''}GROUP GOAL`}
</Typography>
{groupImpactSidebarState ? (
<span className={classes.badge}>
Expand All @@ -422,6 +430,19 @@ const GroupImpactSidebar = ({
</Button>
)}
</div>
{dateExpires && (
<Countdown

Check warning on line 434 in src/components/groupImpactComponents/GroupImpactSidebar.js

View check run for this annotation

Codecov / codecov/patch

src/components/groupImpactComponents/GroupImpactSidebar.js#L434

Added line #L434 was not covered by tests
date={dateExpires}
intervalDelay={0}
precision={3}
renderer={({ hours, days }) => (
<Typography>
`${days > 0 ? `${days}days` : ``} $
{hours > 0 ? `${hours}hours` : ``}`

Check warning on line 441 in src/components/groupImpactComponents/GroupImpactSidebar.js

View check run for this annotation

Codecov / codecov/patch

src/components/groupImpactComponents/GroupImpactSidebar.js#L439-L441

Added lines #L439 - L441 were not covered by tests
</Typography>
)}
/>
)}
<Typography variant="body2">{impactTitleCompiled}</Typography>
<Typography className={classes.robotoBold} variant="h3">
{absoluteProgress}%
Expand Down
Loading

0 comments on commit 31f3d59

Please sign in to comment.