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
Share option #8
Share option #8
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
[{"/Users/aberllin/Desktop/react-apps-dashboard/src/App.tsx":"1","/Users/aberllin/Desktop/react-apps-dashboard/src/modules/Dashboard.tsx":"2","/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/ToDoApp.tsx":"3","/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/AppWindow.tsx":"4","/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/Form.tsx":"5"},{"size":1052,"mtime":1611424355792,"results":"6","hashOfConfig":"7"},{"size":1895,"mtime":1610534270435,"results":"8","hashOfConfig":"7"},{"size":726,"mtime":1610531654982,"results":"9","hashOfConfig":"7"},{"size":913,"mtime":1611424611949,"results":"10","hashOfConfig":"7"},{"size":2132,"mtime":1611424664138,"results":"11","hashOfConfig":"7"},{"filePath":"12","messages":"13","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1qhk1of",{"filePath":"14","messages":"15","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"16","messages":"17","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"18","messages":"19","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"20","messages":"21","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/aberllin/Desktop/react-apps-dashboard/src/App.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/modules/Dashboard.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/ToDoApp.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/AppWindow.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/Form.tsx",[]] | ||
[{"/Users/aberllin/Desktop/react-apps-dashboard/src/App.tsx":"1","/Users/aberllin/Desktop/react-apps-dashboard/src/modules/Dashboard.tsx":"2","/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/ToDoApp.tsx":"3","/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/AppWindow.tsx":"4","/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/Form.tsx":"5","/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuButton.tsx":"6","/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuModal.tsx":"7","/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/ToDoList.tsx":"8","/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppCard.tsx":"9","/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/CloseAppButton.tsx":"10","/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuOptions/ShareForm.tsx":"11","/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuOptions/ShareModal.tsx":"12","/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuOptions/FormSuccess.tsx":"13","/Users/aberllin/Desktop/react-apps-dashboard/src/reportWebVitals.js":"14"},{"size":1056,"mtime":1611651201740,"results":"15","hashOfConfig":"16"},{"size":1895,"mtime":1611172327188,"results":"17","hashOfConfig":"16"},{"size":1131,"mtime":1611647392781,"results":"18","hashOfConfig":"16"},{"size":1001,"mtime":1611485389653,"results":"19","hashOfConfig":"16"},{"size":2132,"mtime":1611425181899,"results":"20","hashOfConfig":"16"},{"size":1276,"mtime":1611910508870,"results":"21","hashOfConfig":"16"},{"size":1340,"mtime":1611910425784,"results":"22","hashOfConfig":"16"},{"size":1505,"mtime":1611649133862,"results":"23","hashOfConfig":"16"},{"size":1435,"mtime":1611654798387,"results":"24","hashOfConfig":"16"},{"size":474,"mtime":1611484518005,"results":"25","hashOfConfig":"16"},{"size":1522,"mtime":1611751982722,"results":"26","hashOfConfig":"16"},{"size":2464,"mtime":1611910529439,"results":"27","hashOfConfig":"16"},{"size":330,"mtime":1611910425788,"results":"28","hashOfConfig":"16"},{"size":362,"mtime":1610528537626,"results":"29","hashOfConfig":"16"},{"filePath":"30","messages":"31","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"32"},"1qhk1of",{"filePath":"33","messages":"34","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"35","messages":"36","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"37","messages":"38","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"39","messages":"40","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"41","messages":"42","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"43","messages":"44","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"45","messages":"46","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"47","messages":"48","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"49","messages":"50","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"51","messages":"52","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"53","messages":"54","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"55","messages":"56","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"57","messages":"58","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/aberllin/Desktop/react-apps-dashboard/src/App.tsx",[],["59","60"],"/Users/aberllin/Desktop/react-apps-dashboard/src/modules/Dashboard.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/ToDoApp.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/AppWindow.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/Form.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuButton.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuModal.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/apps/ToDoApp/ToDoList.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppCard.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/CloseAppButton.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuOptions/ShareForm.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuOptions/ShareModal.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/components/AppWindow/MenuComponents/MenuOptions/FormSuccess.tsx",[],"/Users/aberllin/Desktop/react-apps-dashboard/src/reportWebVitals.js",[],{"ruleId":"61","replacedBy":"62"},{"ruleId":"63","replacedBy":"64"},"no-native-reassign",["65"],"no-negated-in-lhs",["66"],"no-global-assign","no-unsafe-negation"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,55 @@ | ||
import React, {useState} from 'react' | ||
import {HiOutlineDotsCircleHorizontal} from 'react-icons/hi' | ||
import {MenuModal} from './MenuModal' | ||
import React, { useState } from 'react' | ||
import { HiOutlineDotsCircleHorizontal } from 'react-icons/hi' | ||
import { MenuModal } from './MenuModal' | ||
import styled from 'styled-components' | ||
|
||
|
||
|
||
import { ShareModal } from './MenuOptions/ShareModal' | ||
export const MenuButton = () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How is this a reusable component? According to the task it should be Add a Menu button to each App with an ability to provide different menu options" |
||
const [showMenu, setShowMenu ] = useState(false) | ||
const [showMenu, setShowMenu] = useState<boolean>(false) | ||
const [showShareModal, setShowShareModal] = useState<boolean>(false) | ||
|
||
const openMenu = () => { | ||
setShowMenu(prev => !prev) | ||
} | ||
const openMenu = () => { | ||
setShowMenu(true) | ||
} | ||
|
||
return ( | ||
<div> | ||
<div onClick={openMenu}><MenuIcon /></div> | ||
<MenuModal showMenu={showMenu} setShowMenu={setShowMenu} /> | ||
</div> | ||
) | ||
return ( | ||
<MenuWrapper> | ||
<div onClick={openMenu}> | ||
<MenuIcon active={showMenu} /> | ||
</div> | ||
<MenuModal | ||
openShareModal={() => setShowShareModal(true)} | ||
open={showMenu} | ||
onClose={() => setShowMenu(false)} | ||
/> | ||
<ShareModal | ||
isOpen={showShareModal} | ||
setShowShareModal={setShowShareModal} | ||
/> | ||
</MenuWrapper> | ||
) | ||
} | ||
|
||
const MenuIcon = styled(HiOutlineDotsCircleHorizontal)` | ||
display: flex; | ||
justify-content: flex-start; | ||
align-items: flex-end; | ||
margin: 180px 60px; | ||
color: ${({ theme }) => theme.textColor}; | ||
transition: ease 0.2s; | ||
cursor: pointer; | ||
|
||
const MenuIcon = styled(HiOutlineDotsCircleHorizontal)<{ active: boolean }>` | ||
position: fixed; | ||
bottom: 60px; | ||
left: 60px; | ||
color: ${({ theme }) => theme.textColor}; | ||
transition: ease 0.2s; | ||
cursor: pointer; | ||
|
||
&:hover { | ||
color: #1ccbb1; | ||
${(props) => { | ||
if (props.active) { | ||
return ` | ||
color: #1ccbb1; | ||
` | ||
} | ||
` | ||
}} | ||
|
||
&:hover { | ||
color: #1ccbb1; | ||
} | ||
` | ||
|
||
const MenuWrapper = styled.div` | ||
position: relative; | ||
` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,66 @@ | ||
import React from 'react' | ||
import React, { useEffect, useCallback } from 'react' | ||
import styled from 'styled-components' | ||
|
||
interface Props { | ||
open: boolean | ||
onClose: () => void | ||
openShareModal: () => void | ||
} | ||
|
||
export const MenuModal = ({ open, onClose, openShareModal }: Props) => { | ||
const modalRef = React.createRef<HTMLInputElement>() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not useRef? |
||
const onClickOutside = useCallback( | ||
(e: Event) => { | ||
if (modalRef.current && modalRef.current.contains(e.target as Node)) { | ||
return | ||
} | ||
if (open) return onClose() | ||
}, | ||
[modalRef, onClose, open], | ||
) | ||
|
||
useEffect(() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to have it as a separate hook something like useOutsideClick |
||
if (open) { | ||
document.addEventListener('click', onClickOutside) | ||
} | ||
|
||
export const MenuModal = ({showMenu, setShowMenu}: any) => { | ||
return ( | ||
<> | ||
{showMenu ? | ||
<Background> | ||
<ul> | ||
<li>Share</li> | ||
<li>Edit</li> | ||
<li>Delete</li> | ||
</ul> | ||
<div onClick={() => setShowMenu}></div> | ||
</Background> | ||
: null} | ||
</> | ||
) | ||
return () => { | ||
document.removeEventListener('click', onClickOutside) | ||
} | ||
}, [onClickOutside, open]) | ||
|
||
return ( | ||
<> | ||
{open ? ( | ||
<Background ref={modalRef}> | ||
<StyledUL> | ||
<li onClick={openShareModal}>Share</li> | ||
</StyledUL> | ||
<div onClick={onClose}></div> | ||
</Background> | ||
) : null} | ||
</> | ||
) | ||
} | ||
|
||
const Background = styled.div` | ||
position: fixed; | ||
position: fixed; | ||
border: 1px solid #c4c4c4; | ||
z-index: 4; | ||
left: 0; | ||
top: 0; | ||
width: 100%; | ||
height: 100%; | ||
left: 105px; | ||
top: 570px; | ||
overflow: auto; | ||
` | ||
list-style-type: none; | ||
font-size: 20px; | ||
width: 110px; | ||
height: 140px; | ||
` | ||
|
||
const StyledUL = styled.ul` | ||
margin: 5px; | ||
cursor: pointer; | ||
|
||
&:hover { | ||
background: gray; | ||
} | ||
` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import React from 'react' | ||
import catSentMessage from './../../../../images/catSentMessage.gif' | ||
import styled from 'styled-components' | ||
|
||
export const FormSuccess = () => { | ||
return ( | ||
<div> | ||
<Image src={catSentMessage} alt="cat sent message" /> | ||
</div> | ||
) | ||
} | ||
|
||
const Image = styled.img` | ||
height: 170px; | ||
width: 300px; | ||
` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import React from 'react' | ||
import styled from 'styled-components' | ||
|
||
interface Props { | ||
onSubmitButton: ( | ||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>, | ||
) => void | ||
onInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void | ||
value: string | ||
setShowShareModal: (value: boolean) => void | ||
errors: string | ||
} | ||
|
||
export const ShareForm = ({ | ||
value, | ||
onInputChange, | ||
onSubmitButton, | ||
setShowShareModal, | ||
errors, | ||
}: Props) => { | ||
return ( | ||
<form> | ||
<StyledInput | ||
name="email" | ||
type="email" | ||
placeholder="Enter email to send your Todo List" | ||
value={value} | ||
onChange={onInputChange} | ||
/> | ||
{errors ? <ErrorMessage>{errors}</ErrorMessage> : null} | ||
<ButtonsWrapper> | ||
<Button onClick={() => setShowShareModal(false)}>Cancel</Button> | ||
<Button type="submit" onClick={onSubmitButton}> | ||
Send | ||
</Button> | ||
</ButtonsWrapper> | ||
</form> | ||
) | ||
} | ||
|
||
const ButtonsWrapper = styled.div` | ||
display: flex; | ||
padding: 25px 0; | ||
justify-content: center; | ||
` | ||
|
||
const Button = styled.button` | ||
outline: none; | ||
border: none; | ||
padding: 7px 18px; | ||
margin: 0 35px; | ||
|
||
&:hover { | ||
background: gray; | ||
color: white; | ||
} | ||
|
||
&:focus { | ||
color: green; | ||
} | ||
` | ||
|
||
const StyledInput = styled.input` | ||
outline: 0; | ||
border: 2px solid #c4c4c4; | ||
width: 70%; | ||
height: 48px; | ||
box-sizing: border-box; | ||
font-size: 14px; | ||
padding: 15px; | ||
margin-top: 15px; | ||
` | ||
|
||
const ErrorMessage = styled.p` | ||
font-size: 10px; | ||
margin-top: 0.5rem; | ||
color: #f00e0e; | ||
` |
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.
Type
any
?