diff --git a/src/api/types.ts b/src/api/types.ts index f75edad..8cbabc0 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -27,6 +27,7 @@ export interface Goal { accountId: string transactionIds: string[] tagIds: string[] + icon: string | null } export interface Tag { diff --git a/src/ui/features/goalmanager/GoalManager.tsx b/src/ui/features/goalmanager/GoalManager.tsx index 0779dda..63bdeb8 100644 --- a/src/ui/features/goalmanager/GoalManager.tsx +++ b/src/ui/features/goalmanager/GoalManager.tsx @@ -1,5 +1,5 @@ import { faCalendarAlt } from '@fortawesome/free-regular-svg-icons' -import { faDollarSign, IconDefinition } from '@fortawesome/free-solid-svg-icons' +import { faDollarSign, faSmile, IconDefinition } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { MaterialUiPickersDate } from '@material-ui/pickers/typings/date' import 'date-fns' @@ -11,6 +11,29 @@ import { selectGoalsMap, updateGoal as updateGoalRedux } from '../../../store/go import { useAppDispatch, useAppSelector } from '../../../store/hooks' import DatePicker from '../../components/DatePicker' import { Theme } from '../../components/Theme' +import EmojiPicker from '../../components/EmojiPicker' +import { BaseEmoji } from 'emoji-mart' +import { TransparentButton } from '../../components/TransparentButton' +import GoalIcon from './GoalIcon' + +type EmojiPickerContainerProps = { isOpen: boolean; hasIcon: boolean } +type AddIconButtonContainerProps = { hasIcon: boolean } +type GoalIconContainerProps = { shouldShow: boolean } + +const GoalIconContainer = styled.div` + display: ${(props) => (props.shouldShow ? 'flex' : 'none')}; +` + +const AddIconButtonContainer = styled.div` + display: ${(props) => (props.hasIcon ? 'none' : 'flex')}; +` + +const EmojiPickerContainer = styled.div` + display: ${(props) => (props.isOpen ? 'flex' : 'none')}; + position: absolute; + top: ${(props) => (props.hasIcon ? '10rem' : '2rem')}; + left: 0; +` type Props = { goal: Goal } export function GoalManager(props: Props) { @@ -21,22 +44,29 @@ export function GoalManager(props: Props) { const [name, setName] = useState(null) const [targetDate, setTargetDate] = useState(null) const [targetAmount, setTargetAmount] = useState(null) + const [icon, setIcon] = useState(null) useEffect(() => { setName(props.goal.name) setTargetDate(props.goal.targetDate) setTargetAmount(props.goal.targetAmount) + setIcon(props.goal.icon) }, [ props.goal.id, props.goal.name, props.goal.targetDate, props.goal.targetAmount, + props.goal.icon, ]) useEffect(() => { setName(goal.name) }, [goal.name]) + useEffect(() => { + setIcon(goal.icon) + }, [props.goal.id, goal.icon]) + const updateNameOnChange = (event: React.ChangeEvent) => { const nextName = event.target.value setName(nextName) @@ -75,6 +105,32 @@ export function GoalManager(props: Props) { } } + const [emojiPickerIsOpen, setEmojiPickerIsOpen] = useState(false) + const hasIcon = () => icon != null + + const addIconOnClick = (event: React.MouseEvent) => { + event.stopPropagation() + setEmojiPickerIsOpen(true) + } + + const pickEmojiOnClick = (emoji: BaseEmoji, event: React.MouseEvent) => { + event.stopPropagation() + + setIcon(emoji.native) + setEmojiPickerIsOpen(false) + + const updatedGoal: Goal = { + ...props.goal, + icon: emoji.native ?? props.goal.icon, + name: name ?? props.goal.name, + targetDate: targetDate ?? props.goal.targetDate, + targetAmount: targetAmount ?? props.goal.targetAmount, + } + + dispatch(updateGoalRedux(updatedGoal)) + updateGoalApi(props.goal.id, updatedGoal) + } + return ( @@ -106,14 +162,30 @@ export function GoalManager(props: Props) { {new Date(props.goal.created).toLocaleDateString()} + + + + + + + + + Add icon + + + + event.stopPropagation()} + > + + ) } type FieldProps = { name: string; icon: IconDefinition } -type AddIconButtonContainerProps = { shouldShow: boolean } -type GoalIconContainerProps = { shouldShow: boolean } -type EmojiPickerContainerProps = { isOpen: boolean; hasIcon: boolean } const Field = (props: FieldProps) => ( @@ -182,3 +254,10 @@ const StringInput = styled.input` const Value = styled.div` margin-left: 2rem; ` + +const AddIconButtonText = styled.h1` + font-size: 1.8rem; + margin-left: 1rem; + color: rgba(174, 174, 174, 1); + font-weight: normal; +`