Skip to content
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

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintcache
@@ -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"]
2 changes: 1 addition & 1 deletion src/App.tsx
Expand Up @@ -23,7 +23,7 @@ function App() {

useEffect(() => {
const inStorage = localStorage.getItem('theme')
const initialValue: any = inStorage ? inStorage : 'light'
const initialValue: any = inStorage ? inStorage : Theme.light
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type any?

setTheme(initialValue)
}, [])

Expand Down
2 changes: 1 addition & 1 deletion src/components/AppCard.tsx
Expand Up @@ -12,7 +12,7 @@ export const AppCard = ({ id, image, title, app }: AppType) => {

return (
<CardContainer>
<StyledLink to={urlTitle}>
<StyledLink onClick={() => document.body.style.overflow = 'hidden' } to={urlTitle}>
<Image background={image} />
{title}
</StyledLink>
Expand Down
7 changes: 6 additions & 1 deletion src/components/AppWindow/AppWindow.tsx
@@ -1,4 +1,4 @@
import React from 'react'
import React, {useEffect} from 'react'
import styled from 'styled-components'
import { CloseAppButton } from './CloseAppButton'
import { AppType } from '../../modules/appsData'
Expand All @@ -11,6 +11,11 @@ interface Props {
}

export const AppWindow = ({ title, app } : Props ) => {

useEffect(() => {
document.body.style.overflow = 'hidden'
}, [])

return (
<AppWindowWrapper>
<AppCardNav>
Expand Down
2 changes: 1 addition & 1 deletion src/components/AppWindow/CloseAppButton.tsx
Expand Up @@ -5,7 +5,7 @@ import { IoCloseCircleOutline } from 'react-icons/io5'

export const CloseAppButton = () => {
return (
<Link to="/">
<Link onClick={() => document.body.style.overflow = 'auto' } to="/">
<CloseIcon />
</Link>
)
Expand Down
75 changes: 47 additions & 28 deletions src/components/AppWindow/MenuComponents/MenuButton.tsx
@@ -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 = () => {
Copy link

Choose a reason for hiding this comment

The 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;
`
80 changes: 58 additions & 22 deletions src/components/AppWindow/MenuComponents/MenuModal.tsx
@@ -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>()
Copy link

Choose a reason for hiding this comment

The 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(() => {
Copy link

Choose a reason for hiding this comment

The 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;
}
`
@@ -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;
`
78 changes: 78 additions & 0 deletions src/components/AppWindow/MenuComponents/MenuOptions/ShareForm.tsx
@@ -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;
`