-
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 #485 from jisurk/part3-우지석-week15
[Week15] 우지석
- Loading branch information
Showing
59 changed files
with
1,629 additions
and
199 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 @@ | ||
export const BASE_URL = "https://bootcamp-api.codeit.kr/api"; |
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
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,73 @@ | ||
import Image from "next/image"; | ||
import styled from "styled-components"; | ||
|
||
const AddLinkBarContainer = styled.div` | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
height: 220px; | ||
width: 100%; | ||
`; | ||
const AddLinkInputBox = styled.div` | ||
background-color: #fff; | ||
position: relative; | ||
height: 70px; | ||
width: 800px; | ||
border: 1px solid #6d6afe; | ||
border-radius: 15px; | ||
padding: 16px 20px; | ||
`; | ||
const InputField = styled.input` | ||
width: 100%; | ||
height: 100%; | ||
border: none; | ||
outline: none; | ||
padding: 0; | ||
&::placeholder { | ||
text-indent: 10px; | ||
font-size: 16px; | ||
font-weight: 400; | ||
color: #9fa6b2; | ||
} | ||
`; | ||
const LinkIcon = styled(Image)` | ||
position: absolute; | ||
left: 5px; | ||
top: 50%; | ||
transform: translateY(-50%); | ||
`; | ||
const AddButton = styled.button` | ||
height: 38px; | ||
background: linear-gradient(90.99deg, #6d6afe 0.12%, #6ae3fe 101.84%); | ||
border: none; | ||
border-radius: 8px; | ||
color: #f5f5f5; | ||
padding: 10px 16px; | ||
font-size: 14px; | ||
font-weight: 600; | ||
text-align: center; | ||
right: 20px; | ||
white-space: nowrap; | ||
position: absolute; | ||
`; | ||
|
||
function AddLinkBar() { | ||
return ( | ||
<AddLinkBarContainer> | ||
<AddLinkInputBox> | ||
<InputField type="search" placeholder="링크를 추가해 보세요." /> | ||
<LinkIcon | ||
width={20} | ||
height={20} | ||
src="/icon/link.svg" | ||
alt="링크모양 아이콘" | ||
/> | ||
<AddButton>추가하기</AddButton> | ||
</AddLinkInputBox> | ||
</AddLinkBarContainer> | ||
); | ||
} | ||
|
||
export default AddLinkBar; |
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,71 @@ | ||
import { useState } from "react"; | ||
import styled from "styled-components"; | ||
|
||
interface FolderData { | ||
id: number; | ||
name: string; | ||
} | ||
|
||
interface StyledFolderButtonProps { | ||
active: boolean; | ||
} | ||
|
||
const StyledFolderButton = styled.button<StyledFolderButtonProps>` | ||
background-color: #ffffff; | ||
width: auto; | ||
height: 36px; | ||
border-radius: 5px; | ||
border: 1px solid #6d6afe; | ||
font-size: 16px; | ||
font-weight: 400; | ||
margin-top: 6px; | ||
margin-right: 10px; | ||
text-align: center; | ||
&:hover { | ||
cursor: pointer; | ||
} | ||
${({ active }) => | ||
active && | ||
` | ||
background-color: #6D6AFE; | ||
color: #ffffff; | ||
`} | ||
`; | ||
|
||
interface ButtonProps { | ||
folderData: FolderData[]; | ||
selectedFolderId: number | null; | ||
onFolderClick: (buttonId: number | null) => void; | ||
} | ||
|
||
function Button({ folderData, selectedFolderId, onFolderClick }: ButtonProps) { | ||
const [activeButton, setActiveButton] = useState<number | null>(null); | ||
|
||
const handleButtonClick = (buttonId: number | null) => { | ||
setActiveButton(buttonId); | ||
onFolderClick(buttonId); | ||
}; | ||
|
||
return ( | ||
<> | ||
<StyledFolderButton | ||
onClick={() => handleButtonClick(null)} | ||
active={activeButton === null} | ||
> | ||
전체 | ||
</StyledFolderButton> | ||
{folderData.map((data) => ( | ||
<StyledFolderButton | ||
key={data.id} | ||
onClick={() => handleButtonClick(data.id)} | ||
active={activeButton === data.id} | ||
> | ||
{data.name} | ||
</StyledFolderButton> | ||
))} | ||
</> | ||
); | ||
} | ||
export default Button; |
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,96 @@ | ||
import styled from "styled-components"; | ||
import { formatDate, generateTimeText } from "@/utils/util"; | ||
import Link from "next/link"; | ||
|
||
const StyledCard = styled.div` | ||
max-width: 340px; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: flex-start; | ||
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px; | ||
border-radius: 10px; | ||
@media (max-width: 1124px) { | ||
max-width: 340px; | ||
} | ||
`; | ||
|
||
const StyledLink = styled(Link)` | ||
display: block; | ||
width: 100%; | ||
`; | ||
|
||
const CardImg = styled.img` | ||
width: 100%; | ||
height: 200px; | ||
object-fit: cover; | ||
border-top-left-radius: 10px; | ||
border-top-right-radius: 10px; | ||
`; | ||
|
||
const CardTextSection = styled.section` | ||
width: 100%; | ||
height: 136px; | ||
padding: 10px 20px; | ||
display: grid; | ||
grid-template-rows: 1fr 2fr 1fr; | ||
grid-template-columns: 1fr; | ||
grid-template-areas: | ||
"time" | ||
"description" | ||
"date"; | ||
`; | ||
|
||
const CardDescription = styled.p` | ||
margin: 0; | ||
width: 100%; | ||
height: 50px; | ||
display: -webkit-box; | ||
-webkit-line-clamp: 3; | ||
-webkit-box-orient: vertical; | ||
overflow: hidden; | ||
text-overflow: ellipsis; | ||
grid-area: description; | ||
`; | ||
|
||
const TimeText = styled.p` | ||
margin: 0; | ||
grid-area: time; | ||
`; | ||
|
||
const DateText = styled.p` | ||
margin: 0; | ||
grid-area: date; | ||
`; | ||
export interface LinkData { | ||
id: number; | ||
created_at: string; | ||
updated_at: string; | ||
url: string; | ||
title: string; | ||
description: string; | ||
image_source: string; | ||
folder_id: number; | ||
} | ||
|
||
function Card({ linkData }: { linkData: LinkData }) { | ||
return ( | ||
<StyledCard> | ||
<StyledLink href={linkData.url} target="_blank"> | ||
<CardImg | ||
src={linkData.image_source || "/img/thumbnail.svg"} | ||
alt={linkData.title} | ||
/> | ||
</StyledLink> | ||
<CardTextSection> | ||
<TimeText>{generateTimeText(linkData.created_at)}</TimeText> | ||
<CardDescription>{linkData.description}</CardDescription> | ||
<DateText>{formatDate(linkData.created_at)}</DateText> | ||
</CardTextSection> | ||
</StyledCard> | ||
); | ||
} | ||
|
||
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,72 @@ | ||
import { useEffect, useState } from "react"; | ||
import axios from "axios"; | ||
import Card, { LinkData } from "./Card"; | ||
import { BASE_URL } from "@/api/config"; | ||
import styled from "styled-components"; | ||
|
||
const StyledCardContainer = styled.div` | ||
display: grid; | ||
grid-template-columns: repeat(3, 1fr); | ||
column-gap: 20px; | ||
row-gap: 25px; | ||
margin: 0 auto; | ||
@media (max-width: 1124px) { | ||
grid-template-columns: repeat(2, 1fr); | ||
} | ||
@media (max-width: 767px) { | ||
grid-template-columns: repeat(1, 1fr); | ||
} | ||
`; | ||
|
||
interface CardListProps { | ||
selectedFolderId: number | null; | ||
} | ||
|
||
function CardList({ selectedFolderId }: CardListProps) { | ||
const [linkData, setLinkData] = useState<LinkData[]>([]); | ||
|
||
useEffect(() => { | ||
const fetchLinkData = async () => { | ||
const accessToken = localStorage.getItem("accessToken"); | ||
|
||
if (accessToken) { | ||
try { | ||
let url = `${BASE_URL}/links`; | ||
if (selectedFolderId !== null) { | ||
url += `?folderId=${selectedFolderId}`; | ||
console.log("Id :", selectedFolderId); | ||
} | ||
const response = await axios.get(url, { | ||
headers: { | ||
Authorization: `Bearer ${accessToken}`, | ||
}, | ||
}); | ||
if (selectedFolderId === null) { | ||
setLinkData(response.data.data.folder); | ||
} else { | ||
setLinkData(response.data.data); | ||
} | ||
console.log("response : ", response.data.data); | ||
} catch (error) { | ||
console.error("에러 메세지 : ", error); | ||
} | ||
} | ||
}; | ||
|
||
fetchLinkData(); | ||
}, [selectedFolderId]); | ||
|
||
return ( | ||
<StyledCardContainer> | ||
{linkData.length > 0 ? ( | ||
linkData.map((data) => <Card key={data.id} linkData={data} />) | ||
) : ( | ||
<div>저장된 링크가 없습니다.</div> | ||
)} | ||
</StyledCardContainer> | ||
); | ||
} | ||
|
||
export default CardList; |
Oops, something went wrong.