From b72c3e01b1e57a444c32d2870162a6847f99c26e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EB=B0=95=EC=A4=80=EC=84=B1?=
<137983583+juncastle97@users.noreply.github.com>
Date: Thu, 11 Jan 2024 21:20:56 +0900
Subject: [PATCH] =?UTF-8?q?[=EB=B0=95=EC=A4=80=EC=84=B1]=20Week7=20(#273)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* fix: hover transition ease-out
* feat: router 설치
* fix: api.js fetchProfile fetchLinks 사용
* feat:SharePage&FolderPage 나누기(커밋 누락)
feat&stlye: AddLink 컴포넌트 생성 및 input css 구현
* Fix: AddLink Button을 input 오른쪽에 고정
* Fix: api 분리
* Refactor: Search & CardInput 컨포넌트 분리
* Feat: FolderPage api로 profile 가져오기
* Feat: Card 컴포넌트를 페이지별 분리 및 시간 기능 구현
* Feat: 케밥 버튼, 별 버튼 넣기
* Fix: 데이터 없을 때 수정
* Feat: Kebab Button 모달창 만들기
* Feat: 폴더 목록 누를 시 목록 이름 나오기
---
package-lock.json | 39 ++++
package.json | 1 +
src/Main.js | 18 ++
src/api.js | 65 +++++-
src/assets/delete.svg | 8 +
src/assets/editimg.svg | 5 +
src/assets/kebab.svg | 5 +
src/assets/link.svg | 4 +
src/assets/noneimg.svg | 13 ++
src/assets/shareimg.svg | 11 +
src/assets/star.svg | 10 +
src/components/AddLink.js | 14 ++
src/components/App.js | 17 --
src/components/Card-folder.js | 53 +++++
src/components/Card-shared.js | 51 +++++
src/components/Card.js | 19 --
src/components/CardInput-folder.js | 14 ++
src/components/CardInput-shared.js | 14 ++
src/components/FolderList.js | 44 ++++
src/components/Header-folder.js | 28 +++
.../{Header.js => Header-shared.js} | 23 +--
src/components/KebabModal.js | 13 ++
src/components/ListButton.js | 17 ++
src/components/Main.js | 38 ----
src/components/Search.js | 15 ++
src/components/Style.css | 190 +++++++++++++++++-
src/components/Title.js | 26 +--
src/index.js | 4 +-
src/pages/FolderPage.js | 54 +++++
src/pages/SharedPage.js | 51 +++++
src/time.js | 34 ++++
31 files changed, 772 insertions(+), 126 deletions(-)
create mode 100644 src/Main.js
create mode 100644 src/assets/delete.svg
create mode 100644 src/assets/editimg.svg
create mode 100644 src/assets/kebab.svg
create mode 100644 src/assets/link.svg
create mode 100644 src/assets/noneimg.svg
create mode 100644 src/assets/shareimg.svg
create mode 100644 src/assets/star.svg
create mode 100644 src/components/AddLink.js
delete mode 100644 src/components/App.js
create mode 100644 src/components/Card-folder.js
create mode 100644 src/components/Card-shared.js
delete mode 100644 src/components/Card.js
create mode 100644 src/components/CardInput-folder.js
create mode 100644 src/components/CardInput-shared.js
create mode 100644 src/components/FolderList.js
create mode 100644 src/components/Header-folder.js
rename src/components/{Header.js => Header-shared.js} (51%)
create mode 100644 src/components/KebabModal.js
create mode 100644 src/components/ListButton.js
delete mode 100644 src/components/Main.js
create mode 100644 src/components/Search.js
create mode 100644 src/pages/FolderPage.js
create mode 100644 src/pages/SharedPage.js
create mode 100644 src/time.js
diff --git a/package-lock.json b/package-lock.json
index a1e590ee6..07f62f2f0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-router-dom": "^6.20.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}
@@ -3241,6 +3242,14 @@
}
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.13.1.tgz",
+ "integrity": "sha512-so+DHzZKsoOcoXrILB4rqDkMDy7NLMErRdOxvzvOKb507YINKUP4Di+shbTZDhSE/pBZ+vr7XGIpcOO0VLSA+Q==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -14671,6 +14680,36 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.20.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.20.1.tgz",
+ "integrity": "sha512-ccvLrB4QeT5DlaxSFFYi/KR8UMQ4fcD8zBcR71Zp1kaYTC5oJKYAp1cbavzGrogwxca+ubjkd7XjFZKBW8CxPA==",
+ "dependencies": {
+ "@remix-run/router": "1.13.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.20.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.20.1.tgz",
+ "integrity": "sha512-npzfPWcxfQN35psS7rJgi/EW0Gx6EsNjfdJSAk73U/HqMEJZ2k/8puxfwHFgDQhBGmS3+sjnGbMdMSV45axPQw==",
+ "dependencies": {
+ "@remix-run/router": "1.13.1",
+ "react-router": "6.20.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/react-scripts": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
diff --git a/package.json b/package.json
index 7ff0d6b58..38c6f3fa1 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-router-dom": "^6.20.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
diff --git a/src/Main.js b/src/Main.js
new file mode 100644
index 000000000..fe9a6fb1e
--- /dev/null
+++ b/src/Main.js
@@ -0,0 +1,18 @@
+import { BrowserRouter, Routes, Route } from "react-router-dom";
+import SharedPage from "./pages/SharedPage";
+import FolderPage from "./pages/FolderPage";
+import Footer from "./components/Footer";
+
+function Main() {
+ return (
+
+
+ }/>
+ }/>
+
+
+
+ );
+}
+
+export default Main;
diff --git a/src/api.js b/src/api.js
index 59040648f..14e301b10 100644
--- a/src/api.js
+++ b/src/api.js
@@ -1,6 +1,59 @@
-// export async function getProfile() {
-// const response = await fetch ('https://bootcamp-api.codeit.kr/api/sample/user')
-// const body = await response.json();
-// return body;
-// }
-// 사용하고 싶은데 사용하지 못해서 남겨둠..
\ No newline at end of file
+export async function fetchProfile() {
+ try {
+ const response = await fetch(
+ "https://bootcamp-api.codeit.kr/api/sample/user"
+ );
+ const body = await response.json();
+ return body;
+ } catch (err) {
+ console.log(err.message);
+ }
+}
+
+export async function fetchLinks() {
+ try {
+ const response = await fetch(
+ "https://bootcamp-api.codeit.kr/api/sample/folder"
+ );
+ const body = await response.json();
+ return body;
+ } catch (err) {
+ console.log(err.message);
+ }
+}
+
+export async function getUser() {
+ try {
+ const response = await fetch(
+ "https://bootcamp-api.codeit.kr/api/users/1"
+ )
+ const body = await response.json();
+ return body;
+ } catch (err) {
+ console.log(err.message);
+ }
+}
+
+export async function getUserFolder() {
+ try {
+ const response = await fetch(
+ "https://bootcamp-api.codeit.kr/api/users/1/folders"
+ )
+ const body = await response.json();
+ return body;
+ } catch (err) {
+ console.log(err.message);
+ }
+}
+
+export async function getUserLink() {
+ try {
+ const response = await fetch(
+ "https://bootcamp-api.codeit.kr/api/users/1/links"
+ )
+ const body = await response.json();
+ return body;
+ } catch (err) {
+ console.log(err.message);
+ }
+}
\ No newline at end of file
diff --git a/src/assets/delete.svg b/src/assets/delete.svg
new file mode 100644
index 000000000..768b0b398
--- /dev/null
+++ b/src/assets/delete.svg
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/src/assets/editimg.svg b/src/assets/editimg.svg
new file mode 100644
index 000000000..0132ba66e
--- /dev/null
+++ b/src/assets/editimg.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/src/assets/kebab.svg b/src/assets/kebab.svg
new file mode 100644
index 000000000..f68de3fc2
--- /dev/null
+++ b/src/assets/kebab.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/src/assets/link.svg b/src/assets/link.svg
new file mode 100644
index 000000000..728d6ba93
--- /dev/null
+++ b/src/assets/link.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/src/assets/noneimg.svg b/src/assets/noneimg.svg
new file mode 100644
index 000000000..ccedf5a0f
--- /dev/null
+++ b/src/assets/noneimg.svg
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/src/assets/shareimg.svg b/src/assets/shareimg.svg
new file mode 100644
index 000000000..74c58297b
--- /dev/null
+++ b/src/assets/shareimg.svg
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/src/assets/star.svg b/src/assets/star.svg
new file mode 100644
index 000000000..9d4544be4
--- /dev/null
+++ b/src/assets/star.svg
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/src/components/AddLink.js b/src/components/AddLink.js
new file mode 100644
index 000000000..6889c0844
--- /dev/null
+++ b/src/components/AddLink.js
@@ -0,0 +1,14 @@
+
+
+function AddLink() {
+ return (
+
+ );
+}
+
+export default AddLink;
\ No newline at end of file
diff --git a/src/components/App.js b/src/components/App.js
deleted file mode 100644
index 359e42ff6..000000000
--- a/src/components/App.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import Header from "./Header";
-import Main from "./Main";
-import Footer from "./Footer";
-import Title from "./Title";
-
-function App() {
- return (
-
-
-
-
-
-
- );
-}
-
-export default App;
\ No newline at end of file
diff --git a/src/components/Card-folder.js b/src/components/Card-folder.js
new file mode 100644
index 000000000..85b31d7a9
--- /dev/null
+++ b/src/components/Card-folder.js
@@ -0,0 +1,53 @@
+import noneImg from "../assets/noneimg.svg";
+import { timeAgo } from "../time";
+import { useState } from "react";
+import KebabModal from "./KebabModal";
+import { Link } from "react-router-dom";
+
+function formatDate(value) {
+ const date = new Date(value);
+ return `${date.getFullYear()}. ${date.getMonth() + 1}. ${date.getDate()}`;
+}
+
+function Card({ data }) {
+ const [modalOpen, setModalOpen] = useState(Array(data).fill(false));
+ const showModal = (index) => {
+ const newModalOpen = [...modalOpen];
+ newModalOpen[index] = !newModalOpen[index];
+ setModalOpen(newModalOpen);
+ }
+
+ return (
+
+ {data ? (data.map((data, index) => (
+
+
+
+
+
+
+
+
+ {modalOpen[index] &&
}
+
+
{timeAgo(data.created_at)}
+
+ {data.description || "no description"}
+
+
{formatDate(data.created_at)}
+
+
+ ))) : (
+
"저장된 링크가 없습니다"
+ )}
+
+
+ );
+}
+
+export default Card;
diff --git a/src/components/Card-shared.js b/src/components/Card-shared.js
new file mode 100644
index 000000000..863997f57
--- /dev/null
+++ b/src/components/Card-shared.js
@@ -0,0 +1,51 @@
+import noneImg from "../assets/noneimg.svg";
+import { timeAgo } from "../time";
+import KebabModal from "./KebabModal";
+import { useState } from "react";
+import { Link } from "react-router-dom";
+
+function formatDate(value) {
+ const date = new Date(value);
+ return `${date.getFullYear()}. ${date.getMonth() + 1}. ${date.getDate()}`;
+}
+
+function Card({ data }) {
+ const [modalOpen, setModalOpen] = useState(Array(data).fill(false));
+ const showModal = (index) => {
+ const newModalOpen = [...modalOpen];
+ newModalOpen[index] = !newModalOpen[index];
+ setModalOpen(newModalOpen);
+ }
+
+ return (
+
+ {data &&
+ data.map((data, index) => (
+
+
+
+
+
+
+
+
+
+ {modalOpen[index] &&
}
+
{timeAgo(data.createdAt)}
+
+ {data.description || "no description"}
+
+
{formatDate(data.createdAt)}
+
+
+ ))}
+
+ );
+}
+
+export default Card;
diff --git a/src/components/Card.js b/src/components/Card.js
deleted file mode 100644
index 235d094d1..000000000
--- a/src/components/Card.js
+++ /dev/null
@@ -1,19 +0,0 @@
-function Card({ data }) {
- return (
-
- {data && data.map((data) =>
-
-
-
-
-
-
{data.description}
-
{data.createdAt}
-
-
- )}
-
- );
-}
-
-export default Card;
diff --git a/src/components/CardInput-folder.js b/src/components/CardInput-folder.js
new file mode 100644
index 000000000..26ca91fdf
--- /dev/null
+++ b/src/components/CardInput-folder.js
@@ -0,0 +1,14 @@
+import "./Style.css";
+import Card from "./Card-folder";
+
+function CardInput({ linksData }) {
+ return (
+
+ );
+}
+
+export default CardInput;
diff --git a/src/components/CardInput-shared.js b/src/components/CardInput-shared.js
new file mode 100644
index 000000000..28782e451
--- /dev/null
+++ b/src/components/CardInput-shared.js
@@ -0,0 +1,14 @@
+import "./Style.css";
+import Card from "./Card-shared";
+
+function CardInput({ linksData }) {
+ return (
+
+ );
+}
+
+export default CardInput;
diff --git a/src/components/FolderList.js b/src/components/FolderList.js
new file mode 100644
index 000000000..9fa506bb7
--- /dev/null
+++ b/src/components/FolderList.js
@@ -0,0 +1,44 @@
+import ListButton from "./ListButton";
+import "./Style.css";
+import { useState } from "react";
+
+function FolderList({ lists }) {
+ const [toggleList, setToggleList] = useState(0);
+
+ return (
+ <>
+
+
+
+ {lists?.map((list) => {
+ return (
+ setToggleList(list.name)}
+ />
+ );
+ })}
+
+
+ {toggleList === 0 ? (
+ ""
+ ) : (
+
{toggleList}
+ )}
+ {toggleList !== 0 && (
+
+
+
+
+
+ )}
+
+
+ >
+ );
+}
+
+export default FolderList;
diff --git a/src/components/Header-folder.js b/src/components/Header-folder.js
new file mode 100644
index 000000000..923f1e5d7
--- /dev/null
+++ b/src/components/Header-folder.js
@@ -0,0 +1,28 @@
+import logoImg from "../assets/logo.svg";
+import "./Style.css";
+
+function Header({profile}) {
+ return (
+
+
+
+
+ );
+}
+
+export default Header;
\ No newline at end of file
diff --git a/src/components/Header.js b/src/components/Header-shared.js
similarity index 51%
rename from src/components/Header.js
rename to src/components/Header-shared.js
index 42b58fc4c..4bfa2fa07 100644
--- a/src/components/Header.js
+++ b/src/components/Header-shared.js
@@ -1,26 +1,9 @@
import logoImg from "../assets/logo.svg";
import "./Style.css";
-import { useEffect, useState } from "react";
-// import { getProfile } from "../api";
-
-function Header() {
- const [profile, setProfile] = useState(null);
- const fetchProfile = async () => {
- try {
- const response = await fetch('https://bootcamp-api.codeit.kr/api/sample/user');
- const data = await response.json();
- setProfile(data);
- } catch (error) {
- console.error('프로필 데이터를 불러오는 중 에러 발생:', error);
- }
- };
-
- useEffect(() => {
- fetchProfile();
- },[]);
+function Header({profile}) {
return (
-
+