-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #419 from sj0724/part3-박상준-week13
[박상준] Week13
- Loading branch information
Showing
98 changed files
with
4,322 additions
and
494 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"presets": ["next/babel"], | ||
"plugins": [["styled-components", { "ssr": true }]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React, { ReactElement, useEffect, useState } from 'react'; | ||
import { createPortal } from 'react-dom'; | ||
|
||
const ModalPortal = ({ children }: { children: ReactElement }) => { | ||
const [mounted, setMounted] = useState<boolean>(false); | ||
const [portalElement, setPortalElement] = useState<HTMLElement | null>(null); | ||
|
||
useEffect(() => { | ||
setPortalElement(document.getElementById('modal')); | ||
}, []); | ||
|
||
useEffect(() => { | ||
setMounted(true); | ||
return () => setMounted(false); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
{mounted && portalElement ? createPortal(children, portalElement) : null} | ||
</> | ||
); | ||
}; | ||
|
||
export default ModalPortal; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import styled from 'styled-components'; | ||
import { ButtonProps } from './Button'; | ||
|
||
const buttonSize = { | ||
xs: '4.8', | ||
sm: '10', | ||
md: '28', | ||
lg: '40', | ||
}; | ||
|
||
export const Cta = styled.span<ButtonProps>` | ||
cursor: pointer; | ||
text-decoration: none; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
border-radius: 0.8rem; | ||
background: var(--Gradient-purpleblue-to-skyblue); | ||
color: var(--Gray-cta); | ||
padding: 1.6rem 2rem; | ||
font-family: Pretendard; | ||
font-size: 1.6rem; | ||
font-style: normal; | ||
font-weight: 700; | ||
line-height: normal; | ||
width: ${({ size }) => buttonSize[size]}rem; | ||
position: relative; | ||
&:hover { | ||
opacity: 0.8; | ||
} | ||
@media (max-width: 768px) { | ||
font-size: 1.4rem; | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { ButtonHTMLAttributes } from 'react'; | ||
import * as S from './Button.styled'; | ||
|
||
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { | ||
size: 'xs' | 'sm' | 'md' | 'lg'; | ||
} | ||
|
||
export function Button({ children, size }: ButtonProps) { | ||
return ( | ||
<> | ||
<S.Cta size={size}>{children}</S.Cta> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const EmptyImg = styled.div` | ||
height: 100%; | ||
background-color: var(--EmptyArea); | ||
border-radius: 1.5rem 1.5rem 0 0; | ||
display: flex; | ||
justify-content: center; | ||
flex-direction: column; | ||
align-items: center; | ||
img { | ||
opacity: 0.2; | ||
width: 13.3rem; | ||
height: 2.4rem; | ||
} | ||
`; | ||
|
||
export const ItemImg = styled.div<{ image: string }>` | ||
height: 100%; | ||
background-image: url(${(props) => props.image}); | ||
border-radius: 1.5rem 1.5rem 0 0; | ||
background-size: cover; | ||
background-position: center; | ||
&:hover { | ||
background-size: 130%; | ||
} | ||
`; | ||
|
||
export const ItemCard = styled.div` | ||
width: 34rem; | ||
height: 33.4rem; | ||
display: flex; | ||
flex-direction: column; | ||
box-shadow: 0px 5px 25px 0px rgba(0, 0, 0, 0.08); | ||
border-radius: 1.5rem; | ||
text-decoration: none; | ||
color: #000; | ||
position: relative; | ||
font-size: 1.6rem; | ||
&:hover { | ||
background-color: var(--Background); | ||
} | ||
@media (max-width: 768px) { | ||
font-size: 1.4rem; | ||
} | ||
`; | ||
|
||
export const StarIcon = styled.img` | ||
width: 3.4rem; | ||
height: 3rem; | ||
flex-shrink: 0; | ||
position: absolute; | ||
top: 1.5rem; | ||
right: 1.5rem; | ||
z-index: 10; | ||
`; | ||
|
||
export const ItemInfo = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
padding: 1.5rem 2rem; | ||
width: 100%; | ||
height: 13.5rem; | ||
gap: 1rem; | ||
position: relative; | ||
`; | ||
|
||
export const KebabIcon = styled.img` | ||
cursor: pointer; | ||
width: 2.1rem; | ||
height: 1.7rem; | ||
flex-shrink: 0; | ||
position: absolute; | ||
right: 2rem; | ||
top: 1.5rem; | ||
`; | ||
|
||
export const ItemDate = styled.p` | ||
color: var(--Description); | ||
font-size: 1.3rem; | ||
`; | ||
|
||
export const ItemDescription = styled.p` | ||
overflow: hidden; | ||
text-overflow: ellipsis; | ||
white-space: nowrap; | ||
a { | ||
text-decoration: none; | ||
color: #000; | ||
} | ||
`; | ||
|
||
export const ItemFullDate = styled.p` | ||
font-size: 1.4rem; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { useEffect, useRef, useState } from 'react'; | ||
import { changeDate, calculateDate } from '../../util/util'; | ||
import * as S from './Card.styled'; | ||
import KebabMenu from '../KebabMenu/KebabMenu'; | ||
import { Link } from '../../hooks/useGetFolder'; | ||
import Image from 'next/image'; | ||
|
||
function Card({ item }: { item: Link }) { | ||
const [createdAt, setCreatedAt] = useState({ time: 0, result: '' }); | ||
const [fullDate, setFullDate] = useState(''); | ||
const { image_source } = item; | ||
const [kebabView, setKebaView] = useState(false); | ||
const [like, setLike] = useState(false); | ||
const kebabRef = useRef<HTMLObjectElement>(null); | ||
|
||
const { url, description } = item; | ||
|
||
const createdText = `${createdAt.time} ${createdAt.result} ago`; | ||
|
||
useEffect(() => { | ||
const nowDate = new Date(); | ||
let createdate = new Date(item.created_at); | ||
const date = (Number(nowDate) - Number(createdate)) / 1000; | ||
setCreatedAt(calculateDate(date)); | ||
setFullDate(changeDate(createdate)); | ||
}, [item]); | ||
|
||
useEffect(() => { | ||
function handleClickOutside(e: any) { | ||
if ( | ||
kebabView && | ||
kebabRef.current && | ||
!kebabRef.current.contains(e.target) | ||
) { | ||
setKebaView(false); | ||
} | ||
} | ||
|
||
document.addEventListener('mousedown', handleClickOutside); | ||
return () => { | ||
document.removeEventListener('mousedown', handleClickOutside); | ||
}; | ||
}, [kebabView]); | ||
|
||
return ( | ||
<S.ItemCard> | ||
<S.StarIcon | ||
src={like ? '/full_star.svg' : '/star.svg'} | ||
alt="별 이미지" | ||
onClick={() => { | ||
setLike(!like); | ||
}} | ||
/> | ||
{image_source ? ( | ||
<S.ItemImg image={image_source} /> | ||
) : ( | ||
<S.EmptyImg> | ||
<Image src="/logo.svg" alt="빈 이미지" width={133} height={24} /> | ||
</S.EmptyImg> | ||
)} | ||
<S.ItemInfo> | ||
<S.KebabIcon | ||
src="/kebab.svg" | ||
alt="kebabIcon" | ||
onClick={() => setKebaView(!kebabView)} | ||
/> | ||
<S.ItemDate>{createdText}</S.ItemDate> | ||
<S.ItemDescription> | ||
<a href={url} target="_blank" rel="noreferrer"> | ||
{description ? description : url} | ||
</a> | ||
</S.ItemDescription> | ||
<S.ItemFullDate>{fullDate}</S.ItemFullDate> | ||
</S.ItemInfo> | ||
{kebabView && <KebabMenu menuRef={kebabRef} />} | ||
</S.ItemCard> | ||
); | ||
} | ||
|
||
export default Card; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { ReactNode } from 'react'; | ||
import styled from 'styled-components'; | ||
|
||
const Container = styled.div<{ $empty: number }>` | ||
gap: 2rem; | ||
display: grid; | ||
grid-template-columns: ${(props) => | ||
props.$empty > 0 ? 'repeat(3, 1fr)' : 'none'}; | ||
margin: 0 auto; | ||
position: relative; | ||
@media (max-width: 1199px) { | ||
grid-template-columns: ${(props) => (props.$empty > 0 ? '1fr 1fr' : '1fr')}; | ||
} | ||
@media (max-width: 767px) { | ||
grid-template-columns: 1fr; | ||
} | ||
`; | ||
|
||
function ContentsContainer({ | ||
children, | ||
content, | ||
}: { | ||
children: ReactNode; | ||
content: number; | ||
}) { | ||
return <Container $empty={content}>{children}</Container>; | ||
} | ||
|
||
export default ContentsContainer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const FolderName = styled.span<{ $select: string | boolean }>` | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
padding: 0.8rem 1.2rem; | ||
border-radius: 0.5rem; | ||
border: 1px solid var(--Primary); | ||
background-color: ${(props) => | ||
props.$select === 'select' ? 'var(--Primary)' : '#fff'}; | ||
cursor: pointer; | ||
height: 3.5rem; | ||
font-size: 1.6rem; | ||
white-space: nowrap; | ||
color: ${(props) => (props.$select === 'select' ? '#fff' : '#000')}; | ||
@media (max-width: 768px) { | ||
font-size: 1.2rem; | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import React from 'react'; | ||
import * as S from './FolderButton.styled'; | ||
import { Folder } from '@/hooks/useGetFolderList'; | ||
|
||
function FolderButton({ | ||
item, | ||
setFolderId, | ||
setFolderName, | ||
isSelected, | ||
handleMenuClick, | ||
index, | ||
}: { | ||
item: Folder; | ||
setFolderId: React.Dispatch<React.SetStateAction<number>>; | ||
setFolderName: React.Dispatch<React.SetStateAction<string>>; | ||
isSelected: string; | ||
handleMenuClick: (index: number) => void; | ||
index: number; | ||
}) { | ||
const changeFolder = () => { | ||
setFolderId(item.id); | ||
setFolderName(item.name); | ||
handleMenuClick(index); | ||
}; | ||
|
||
return ( | ||
<S.FolderName onClick={changeFolder} $select={isSelected}> | ||
{item.name} | ||
</S.FolderName> | ||
); | ||
} | ||
|
||
export default FolderButton; |
Oops, something went wrong.