diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index b78818f..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,41 +0,0 @@
-### react ###
-.DS_*
-*.log
-logs
-**/*.backup.*
-**/*.back.*
-
-node_modules
-bower_components
-
-*.sublime*
-
-psd
-thumb
-sketch
-
-# dependencies
-/node_modules
-/.pnp
-.pnp.js
-
-# testing
-/coverage
-
-# production
-/build
-
-# misc
-.DS_Store
-.env.local
-.env.development.local
-.env.test.local
-.env.production.local
-
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-
-.DS_Store
-node_modules
-.cache
\ No newline at end of file
diff --git a/back b/back
deleted file mode 160000
index 9a425ba..0000000
--- a/back
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 9a425bafe21781ad35b47a8a9d09232c9db2a29f
diff --git a/front/.gitignore b/front/.gitignore
index b78818f..b2d9d47 100644
--- a/front/.gitignore
+++ b/front/.gitignore
@@ -1,4 +1,8 @@
### react ###
+
+# macOS 시스템 파일
+.DS_Store
+
.DS_*
*.log
logs
diff --git a/front/src/global/global.js b/front/src/global/global.js
index 5b1845e..46547f0 100644
--- a/front/src/global/global.js
+++ b/front/src/global/global.js
@@ -11,63 +11,63 @@ const GlobalStyle = createGlobalStyle`
font-family: 'Pretendard';
font-weight: 900;
font-style: normal;
- src: url(${process.env.PUBLIC_URL}/assets/fonts/pretendard/Pretendard-Black.woff2) format('woff2');
+ src: url(${process.env.PUBLIC_URL}/assets/fonts/Pretendard-Black.woff2) format('woff2');
}
@font-face {
font-family: 'Pretendard';
font-weight: 800;
font-style: normal;
- src: url(${process.env.PUBLIC_URL}/assets/fonts/pretendard/Pretendard-ExtraBold.woff2) format('woff2');
+ src: url(${process.env.PUBLIC_URL}/assets/fonts/Pretendard-ExtraBold.woff2) format('woff2');
}
@font-face {
font-family: 'Pretendard';
font-weight: 700;
font-style: normal;
- src: url(${process.env.PUBLIC_URL}/assets/fonts/pretendard/Pretendard-Bold.woff2) format('woff2');
+ src: url(${process.env.PUBLIC_URL}/assets/fonts/Pretendard-Bold.woff2) format('woff2');
}
@font-face {
font-family: 'Pretendard';
font-weight: 600;
font-style: normal;
- src: url(${process.env.PUBLIC_URL}/assets/fonts/pretendard/Pretendard-SemiBold.woff2) format('woff2');
+ src: url(${process.env.PUBLIC_URL}/assets/fonts/Pretendard-SemiBold.woff2) format('woff2');
}
@font-face {
font-family: 'Pretendard';
font-weight: 500;
font-style: normal;
- src: url(${process.env.PUBLIC_URL}/assets/fonts/pretendard/Pretendard-Medium.woff2) format('woff2');
+ src: url(${process.env.PUBLIC_URL}/assets/fonts/Pretendard-Medium.woff2) format('woff2');
}
@font-face {
font-family: 'Pretendard';
font-weight: 400;
font-style: normal;
- src: url(${process.env.PUBLIC_URL}/assets/fonts/pretendard/Pretendard-Regular.woff2) format('woff2');
+ src: url(${process.env.PUBLIC_URL}/assets/fonts/Pretendard-Regular.woff2) format('woff2');
}
@font-face {
font-family: 'Pretendard';
font-weight: 300;
font-style: normal;
- src: url(${process.env.PUBLIC_URL}/assets/fonts/pretendard/Pretendard-Light.woff2) format('woff2');
+ src: url(${process.env.PUBLIC_URL}/assets/fonts/Pretendard-Light.woff2) format('woff2');
}
@font-face {
font-family: 'Pretendard';
font-weight: 200;
font-style: normal;
- src: url(${process.env.PUBLIC_URL}/assets/fonts/pretendard/Pretendard-ExtraLight.woff2) format('woff2');
+ src: url(${process.env.PUBLIC_URL}/assets/fonts/Pretendard-ExtraLight.woff2) format('woff2');
}
@font-face {
font-family: 'Pretendard';
font-weight: 100;
font-style: normal;
- src: url(${process.env.PUBLIC_URL}/assets/fonts/pretendard/Pretendard-thin.woff2) format('woff2');
+ src: url(${process.env.PUBLIC_URL}/assets/fonts/Pretendard-thin.woff2) format('woff2');
}
/* 3) 초기 스타일 */
diff --git a/front/src/pages/archive/BookmarkTyped.jsx b/front/src/pages/archive/BookmarkTyped.jsx
index 6151f11..d8b535c 100644
--- a/front/src/pages/archive/BookmarkTyped.jsx
+++ b/front/src/pages/archive/BookmarkTyped.jsx
@@ -36,8 +36,9 @@ const BookmarkTyped = () => {
setSelectedCard(null); // 닫기
};
- const items = [
+ const [items, setItems] = useState([
{
+ id: 1,
date: "2025.06.28",
title: "끝내주는 인생",
content:
@@ -49,7 +50,27 @@ const BookmarkTyped = () => {
artist: "John Canada",
coverUrl: "/assets/images/book-img.jpeg",
},
- ];
+ ]);
+
+ // 편집 모드
+ const [isEditMode, setIsEditMode] = useState(false);
+ const [selectedIds, setSelectedIds] = useState([]);
+
+ const handleEditClick = () => {
+ setIsEditMode((prev) => !prev);
+ setSelectedIds([]); // 편집 모드 종료 시 초기화
+ };
+
+ const handleCardSelect = (id) => {
+ if (!isEditMode) return;
+ setSelectedIds((prev) => (prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]));
+ };
+
+ const handleDeleteSelected = () => {
+ const newItems = items.filter((item) => !selectedIds.includes(item.id));
+ setItems(newItems);
+ setSelectedIds([]);
+ };
return (
<>
@@ -84,13 +105,26 @@ const BookmarkTyped = () => {
)}
- 편집
+ {isEditMode ? (
+
+ 삭제
+ {selectedIds.length}개 선택됨
+
+ ) : (
+ 편집
+ )}
{/* 북마크 카드 리스트 */}
{items.map((item, idx) => (
- handleCardClick(item)} />
+ (isEditMode ? handleCardSelect(item.id) : handleCardClick(item))}
+ selected={selectedIds.includes(item.id)}
+ isEditMode={isEditMode}
+ />
))}
{/* 팝업 */}
diff --git a/front/src/pages/archive/HistoryCard.jsx b/front/src/pages/archive/HistoryCard.jsx
index 784528e..3e0b653 100644
--- a/front/src/pages/archive/HistoryCard.jsx
+++ b/front/src/pages/archive/HistoryCard.jsx
@@ -3,7 +3,7 @@ import useClickOutside from "../../modules/hooks/useClickOutside";
import Card from "./history.card.style";
import Dropdown from "./dropdown.style";
-const HistoryCard = ({ data, onClick }) => {
+const HistoryCard = ({ data, onClick, selected, isEditMode }) => {
const { date, content, title, author, music, artist } = data;
// 북마크, 좋아요 토글 버튼
@@ -16,7 +16,7 @@ const HistoryCard = ({ data, onClick }) => {
useClickOutside(dropdownRef, () => setOpenDropdown(false));
return (
-
+
{date}
e.stopPropagation()}>
diff --git a/front/src/pages/archive/bookmark.section.style.js b/front/src/pages/archive/bookmark.section.style.js
index 7f15b6a..cb23644 100644
--- a/front/src/pages/archive/bookmark.section.style.js
+++ b/front/src/pages/archive/bookmark.section.style.js
@@ -95,6 +95,7 @@ S.ScrollRightBtn = styled.button`
S.Card = styled.div`
width: 160px;
flex-shrink: 0;
+
`;
S.Image = styled.img`
diff --git a/front/src/pages/archive/bookmark.typed.style.js b/front/src/pages/archive/bookmark.typed.style.js
index 4769e2b..01ccdcf 100644
--- a/front/src/pages/archive/bookmark.typed.style.js
+++ b/front/src/pages/archive/bookmark.typed.style.js
@@ -103,6 +103,28 @@ S.CardColumn = styled.div`
gap: 16px;
`;
+// 편집 모드
+S.EditRow = styled.div`
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-top: 10px;
+`;
+
+S.DeleteButton = styled.button`
+ background: none;
+ border: none;
+ color: #f96f3d;
+ font-size: 14px;
+ cursor: pointer;
+ padding: 0;
+`;
+
+S.SelectedText = styled.span`
+ font-size: 14px;
+ color: gray;
+`;
+
// 디테일 팝업
// 전체 배경 어둡게
diff --git a/front/src/pages/archive/history.card.style.js b/front/src/pages/archive/history.card.style.js
index bbf8008..e9b4ee8 100644
--- a/front/src/pages/archive/history.card.style.js
+++ b/front/src/pages/archive/history.card.style.js
@@ -5,9 +5,11 @@ const Card = {};
Card.Card = styled.div`
background-color: #fff;
padding: 24px 22px 24px 22px;
- border: 1px solid #e0e0e0;
+ border: ${({ selected }) => (selected ? "1px solid #f96f3d" : "1px solid #e0e0e0")};
border-radius: 5px;
font-family: pretendard;
+ transition: border 0.2s ease;
+ cursor: pointer;
`;
Card.Header = styled.div`
diff --git a/front/src/pages/main/MainContainer.jsx b/front/src/pages/main/MainContainer.jsx
index c6c3164..ef66fdc 100644
--- a/front/src/pages/main/MainContainer.jsx
+++ b/front/src/pages/main/MainContainer.jsx
@@ -180,7 +180,7 @@ const MainContainer = ({isUpdate, setIsUpdate}) => {
-
+
{currentData && (
diff --git a/front/src/pages/main/main.form.style.js b/front/src/pages/main/main.form.style.js
index 4c84d51..da392c2 100644
--- a/front/src/pages/main/main.form.style.js
+++ b/front/src/pages/main/main.form.style.js
@@ -1,6 +1,6 @@
-import React from 'react';
+import React from "react";
import styled, { css } from "styled-components";
-import { justifyContentCenter, justifyContentStart } from '../../global/common';
+import { justifyContentCenter, justifyContentStart } from "../../global/common";
const sharedStyle = `
font-size: 20px;
@@ -12,8 +12,7 @@ const sharedStyle = `
white-space: pre-wrap;
`;
-
-const M = { };
+const M = {};
M.Container = styled.div`
width: 1200px;
@@ -33,18 +32,18 @@ M.Content01 = styled.div`
justify-content: space-between;
align-items: start;
display: inline-flex;
-`
+`;
M.TitleWrap = styled.div`
${justifyContentStart}
gap: 5px;
- padding-bottom: 19px
-`
+ padding-bottom: 19px;
+`;
M.TitleIconWrap = styled.div`
gap: 18px;
display: inline-flex;
-`
+`;
M.IcBtn = styled.button`
all: unset;
@@ -57,7 +56,6 @@ M.IcBtn = styled.button`
}
`;
-
// ------------------------------------------
M.Content02 = styled.div`
flex: 1;
@@ -66,7 +64,7 @@ M.Content02 = styled.div`
/* justify-content: space-between; */
gap: 21px;
overflow: hidden;
-`
+`;
// 타이핑 스피드 부분 -----------------------------
M.TypingSpeedWrap = styled.div`
@@ -74,7 +72,7 @@ M.TypingSpeedWrap = styled.div`
display: flex;
flex-direction: column;
gap: 6px;
-`
+`;
// 게이지 전체 + 퍼센트
M.ProgressBarWrapper = styled.div`
@@ -91,7 +89,7 @@ M.ProgressBarContainer = styled.div`
justify-content: flex-start;
align-items: center;
margin-right: 14px;
-`;
+`;
// 게이지 자체
M.ProgressBar = styled.div`
@@ -105,7 +103,7 @@ M.ProgressBar = styled.div`
M.ProgressTick = styled.div`
width: 1.5px;
height: 7px;
- background: ${({ $active }) => ($active ? '#F96F3D' : '#282828')};
+ background: ${({ $active }) => ($active ? "#F96F3D" : "#282828")};
opacity: ${({ $active }) => ($active ? 0.6 : 1)};
`;
@@ -113,7 +111,7 @@ M.ProgressTick = styled.div`
M.ProgressPoint = styled.div`
width: 7px;
height: 7px;
- background: ${({ $active }) => ($active ? '#F96F3D' : '#BFBFBF')};
+ background: ${({ $active }) => ($active ? "#F96F3D" : "#BFBFBF")};
`;
// 퍼센트 전체 감싸는 래퍼 (가로 74px 고정)
@@ -129,7 +127,7 @@ M.ProgressPercentWrap = styled.div`
M.Bar = styled.div`
width: 6px;
height: 30px;
- background-color: #BFBFBF;
+ background-color: #bfbfbf;
`;
// 회전된 삼각형
@@ -147,16 +145,12 @@ M.PercentText = styled.span`
font-size: 16px;
font-family: Pretendard;
font-weight: 400;
- color: #F96F3D;
+ color: #f96f3d;
line-height: 24px;
text-align: right;
padding-left: 10px;
`;
-
-
-
-
// 본문 내용 부분 --------------------------------
M.ContentBox = styled.div`
width: 100%;
@@ -183,7 +177,7 @@ M.UnderContent = styled.div`
flex-direction: column;
display: flex;
gap: 15px;
-`
+`;
// 실시간 컬러변경 -------------------------------------------------
M.TypingTextDisplay = styled.div`
@@ -196,7 +190,6 @@ M.TypingTextDisplay = styled.div`
z-index: 1;
`;
-
M.TypingOverlay = styled.div`
position: absolute;
top: 0;
@@ -237,28 +230,26 @@ M.HiddenInput = styled.textarea`
}
`;
-
-
// 음악, 출처, 버튼 -------------------------------------------------
M.Line = styled.div`
align-self: stretch;
height: 1px;
- background: #BFBFBF;
-`
+ background: #bfbfbf;
+`;
M.StyledUnder01 = styled.div`
align-self: stretch;
justify-content: space-between;
align-items: center;
display: inline-flex;
-`
+`;
M.StyledUnder02 = styled.div`
align-self: stretch;
justify-content: space-between;
align-items: flex-end;
display: inline-flex;
-`
+`;
M.SaveBtn = styled.div`
width: 150px;
@@ -275,26 +266,26 @@ M.SaveBtn = styled.div`
line-height: 30px;
&:hover {
- background-color: #F96F3D;
+ background-color: #f96f3d;
}
&:active {
- background-color: #663C2D;
+ background-color: #663c2d;
}
&:disabled {
- background-color: #BFBFBF;
+ background-color: #bfbfbf;
color: white;
cursor: not-allowed;
}
-`
+`;
M.StyledMusic = styled.div`
justify-content: flex-start;
align-items: center;
gap: 14px;
display: inline-flex;
-`
+`;
M.IconButton = styled.button`
background: none;
@@ -307,56 +298,56 @@ M.IconButton = styled.button`
height: 24px;
display: block;
}
-`
+`;
M.Album = styled.div`
${justifyContentStart}
gap: 12px;
-`
+`;
M.AlbumInfo = styled.div`
${justifyContentStart}
gap: 8px;
-`
+`;
M.AlbumImg = styled.img`
width: 39px;
height: 39px;
border-radius: 1px;
- border: 0.50px #787878 solid;
+ border: 0.5px #787878 solid;
`;
M.PlayListIconWrap = styled.div`
${justifyContentStart}
gap: 30px;
-`
+`;
M.PlayIconWrap = styled.div`
${justifyContentCenter}
gap: 10px;
-`
+`;
M.PlayIcon = styled.div`
${justifyContentCenter}
gap: 10px;
- img{
- width: 30px;
- height: 30px;
- position: relative;
- }
-`
+ img {
+ width: 30px;
+ height: 30px;
+ position: relative;
+ }
+`;
-M.PlayListWrap = styled.button`
+M.PlayListWrap = styled.div`
${justifyContentCenter}
background: none;
gap: 6px;
-`
+`;
M.ReplayBookIconWrap = styled.div`
${justifyContentStart}
gap: 14px;
-`
+`;
M.ReplayBtn = styled.button`
width: 32px;
@@ -364,34 +355,33 @@ M.ReplayBtn = styled.button`
background: none;
padding: 6px;
border-radius: 50px;
- outline: 1px #BFBFBF solid;
+ outline: 1px #bfbfbf solid;
outline-offset: -1px;
${justifyContentCenter}
gap: 10px;
-`
+`;
M.BookmarkInfoWrap = styled.div`
${justifyContentCenter}
gap: 10px;
-`
+`;
M.BookInfoWrapper = styled.div`
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
display: inline-flex;
-`
+`;
M.BookInfoWrap = styled.div`
align-self: stretch;
${justifyContentStart}
gap: 6px;
-`
+`;
M.FadeWrapper = styled.div`
- opacity: ${({ fade }) => (fade ? 1 : 0)};
+ opacity: ${({ $fade }) => ($fade ? 1 : 0)};
transition: opacity 0.3s ease-in-out;
-`
-
+`;
-export default M;
\ No newline at end of file
+export default M;
diff --git "a/front/\354\225\204\354\271\264\354\235\264\353\270\214.zip" "b/front/\354\225\204\354\271\264\354\235\264\353\270\214.zip"
new file mode 100644
index 0000000..a00743a
Binary files /dev/null and "b/front/\354\225\204\354\271\264\354\235\264\353\270\214.zip" differ