Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3e57612
:art: tag auto-complete finished
TaehyeungKim Apr 8, 2024
71339c8
:sprakled: added comment dummy data
TaehyeungKim Apr 8, 2024
21d874c
:sparkles: added comment template
TaehyeungKim Apr 8, 2024
fd319f1
:sparkles: completed comment submit
TaehyeungKim Apr 8, 2024
1d8023a
:art: added custom style to comment edit button
TaehyeungKim Apr 8, 2024
45b5954
:art: finished comment edit
TaehyeungKim Apr 8, 2024
4d57667
:zap: separated new input value from data in comment edit page
TaehyeungKim Apr 8, 2024
08eeca0
:sparkles: finished week5-hw
TaehyeungKim Apr 8, 2024
fb7ea3a
:art: added selecting multiple tags in serach
TaehyeungKim Apr 8, 2024
d786c58
added the new comment data with time now
TaehyeungKim Apr 8, 2024
40d622c
:bug: fixed the input of the post-create-page to full-width
TaehyeungKim Apr 11, 2024
500e8ba
if the post is created or edited, the route to detail page
TaehyeungKim Apr 11, 2024
0d5be85
:art: edited the button to shrink-0
TaehyeungKim Apr 11, 2024
fd5137f
:art: added responsive design to homepage
TaehyeungKim Apr 11, 2024
339b555
:sparkles: added custom media query hook and implemented it to the he…
TaehyeungKim Apr 11, 2024
7e05854
:art: implemented Intl.DateTimeFormat for the comment created_at
TaehyeungKim Apr 11, 2024
7aa88af
:bug: added proper key to individual comment component
TaehyeungKim Apr 11, 2024
b22d367
modified responsive target range in the small post
TaehyeungKim Apr 11, 2024
828bb88
implemented join between comment and post id
TaehyeungKim Apr 11, 2024
39360a2
:bug: fixed the error having been occured when adding first comment t…
TaehyeungKim Apr 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lionblog-taehyeong/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const DarkModeContext = createContext(false);
export const PostsDataContext = createContext(null);

function App() {
const [darkMode, setDarkMode] = useState(false);
const [darkMode, setDarkMode] = useState(true);
Copy link

Choose a reason for hiding this comment

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

였 닀크λͺ¨λ“œ μ „ν™˜ κΈ°λŠ₯을 λ§Œλ“ κ±΄κ°€μš©..?


const darkModeToggle = () => setDarkMode(!darkMode);

Expand Down
84 changes: 84 additions & 0 deletions lionblog-taehyeong/src/components/Comment/CommentElement.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { useState, useEffect } from "react";

const CommentElement = ({ comment, handleCommentDelete }) => {
const [isEditMode, setIsEditMode] = useState(false);
const [content, setContent] = useState(comment.content);
const [editInputValue, setEditInputValue] = useState("");

// comment created_at μ „μ²˜λ¦¬
const date = new Intl.DateTimeFormat("en-CA", {
formatString: "yyyy.mm.dd",

year: "numeric",
month: "2-digit",
day: "2-digit",
})
.format(new Date(comment.created_at))
.replaceAll("-", ".");

const handleEditComment = (e) => {
e.preventDefault();
setContent(editInputValue);
setIsEditMode(false);
setEditInputValue("");
};

const toEditMode = (e) => {
e.preventDefault();
setIsEditMode(true);
};

const toShowMode = (e) => {
e.preventDefault();
setIsEditMode(false);
};

useEffect(() => {
// add api call to check if user is the author of the comment
}, []);

return (
<div className="w-full flex flex-row justify-between items-center mb-5">
<div className="w-3/4 flex flex-col gap-1">
{isEditMode ? (
<input
className="input"
defaultValue={content}
onChange={(e) => setEditInputValue(e.target.value)}
/>
) : (
<p>{content}</p>
)}

<span className="text-base text-gray-300">{date}</span>
</div>

<div className="flex flex-row items-center gap-3">
{isEditMode ? (
<>
<button className="button-no-bg" onClick={toShowMode}>
μ·¨μ†Œ
</button>
<button className="button-no-bg" onClick={handleEditComment}>
μ™„λ£Œ{" "}
</button>
</>
) : (
<>
<button
className="button-no-bg"
type="button"
onClick={handleCommentDelete(comment.id)}
>
μ‚­μ œ
</button>
<button className="button-no-bg" type="button" onClick={toEditMode}>
μˆ˜μ •
</button>
</>
)}
</div>
</div>
);
};
export default CommentElement;
83 changes: 83 additions & 0 deletions lionblog-taehyeong/src/components/Comment/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useState, useEffect } from "react";
import comments from "../../data/comment"; // dummy data
import CommentElement from "./CommentElement";

const Comment = ({ postId }) => {
const [commentsData, setCommentsData] = useState([]);
const [commentInputValue, setCommentInputValue] = useState("");

const handleCommentInputChange = (e) => {
const { value } = e.target;
setCommentInputValue(value);
};

const handleCommentSubmit = (e) => {
e.preventDefault();
if (commentInputValue.length === 0) return;

const newId =
commentsData.length > 0
? commentsData.sort((a, b) => a.id - b.id)[commentsData.length - 1].id +
1
: 1;

setCommentsData([
...commentsData,
{
id: newId,
content: commentInputValue,
created_at: new Date(),
post: 1,
author: {
id: 2,
username: "user2",
},
},
]);

setCommentInputValue("");
};

const handleCommentDelete = (commentId) => (e) => {
e.preventDefault();
const updatedComments = commentsData.filter(
(comment) => comment.id !== commentId
);
setCommentsData([...updatedComments]);
console.log(commentId);
};

useEffect(() => {
setCommentsData(
comments.filter((comment) => comment.post === parseInt(postId))
);
}, [postId]);

return (
<div className="w-full mt-5 self-start mb-8">
<h1 className="text-3xl font-bold my-5">Comments</h1>
{commentsData &&
commentsData.map((comment) => (
<CommentElement
key={comment.id}
comment={comment}
handleCommentDelete={handleCommentDelete}
/>
))}
<form className="flex flex-row items-center justify-center mt-10 gap-2">
<input
type="text"
className="input"
placeholder="λŒ“κΈ€μ„ μž…λ ₯ν•΄μ£Όμ„Έμš”."
onChange={handleCommentInputChange}
value={commentInputValue}
/>
<button className="button" type="submit" onClick={handleCommentSubmit}>
μž‘μ„±
</button>
</form>
</div>
);
};

export default Comment;
62 changes: 42 additions & 20 deletions lionblog-taehyeong/src/components/Header/index.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import { Link } from "react-router-dom";
import { useContext } from "react";
import { useContext, useState, useEffect } from "react";
import { DarkModeContext } from "../../App";
import { useMediaQuery } from "../../hooks/useMediaQuery";

import lion from "../../assets/images/lion.jpeg";

const Header = ({ darkModeToggle }) => {
const darkMode = useContext(DarkModeContext);
const isMobile = useMediaQuery("(max-width: 640px)");

const [isUserLoggedIn, setIsUserLoggedIn] = useState(false); // 둜그인 μ—¬λΆ€ μƒνƒœ, μš°μ„  false둜 μ΄ˆκΈ°ν™”

const handleSignOut = () => {
// TODO: 이후 api μ—°κ²° μ‹œ token 제거
};

useEffect(() => {
// TODO: 이후 api μ—°κ²° μ‹œ μœ νš¨ν•œ token이 μžˆλ‹€λ©΄ setIsUserLoggedIn(true)둜 μƒνƒœ λ³€κ²½ν•˜λŠ” μ½”λ“œ μž‘μ„±
}, []);

return (
<div
Expand All @@ -15,25 +27,35 @@ const Header = ({ darkModeToggle }) => {
<img src={lion} alt="lion" className="max-h-16 rounded-full" />
<div className="text-xl">SNULION BLOG</div>
</Link>
<div className="flex">
<Link to="/signin" className="mr-10 p-3 uppercase text-lg">
sign in
</Link>
<Link to="/signup" className="mr-10 p-3 uppercase text-lg">
sign up
</Link>
<button onClick={darkModeToggle}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
className={`bi bi-moon ${darkMode ? "fill-white" : "fill-black"}`}
viewBox="0 0 16 16"
>
<path d="M6 .278a.77.77 0 0 1 .08.858 7.2 7.2 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277q.792-.001 1.533-.16a.79.79 0 0 1 .81.316.73.73 0 0 1-.031.893A8.35 8.35 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.75.75 0 0 1 6 .278M4.858 1.311A7.27 7.27 0 0 0 1.025 7.71c0 4.02 3.279 7.276 7.319 7.276a7.32 7.32 0 0 0 5.205-2.162q-.506.063-1.029.063c-4.61 0-8.343-3.714-8.343-8.29 0-1.167.242-2.278.681-3.286" />
</svg>
</button>
</div>
{isMobile ? null : (
<div className="flex">
{isUserLoggedIn ? (
<Link to="/" className="mr-10 p-3 uppercase text-lg">
sign out
</Link>
) : (
<>
<Link to="/signin" className="mr-10 p-3 uppercase text-lg">
sign in
</Link>
<Link to="/signup" className="mr-10 p-3 uppercase text-lg">
sign up
</Link>
</>
)}
<button onClick={darkModeToggle}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
className={`bi bi-moon ${darkMode ? "fill-white" : "fill-black"}`}
viewBox="0 0 16 16"
>
<path d="M6 .278a.77.77 0 0 1 .08.858 7.2 7.2 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277q.792-.001 1.533-.16a.79.79 0 0 1 .81.316.73.73 0 0 1-.031.893A8.35 8.35 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.75.75 0 0 1 6 .278M4.858 1.311A7.27 7.27 0 0 0 1.025 7.71c0 4.02 3.279 7.276 7.319 7.276a7.32 7.32 0 0 0 5.205-2.162q-.506.063-1.029.063c-4.61 0-8.343-3.714-8.343-8.29 0-1.167.242-2.278.681-3.286" />
</svg>
</button>
</div>
)}
</div>
);
};
Expand Down
22 changes: 9 additions & 13 deletions lionblog-taehyeong/src/components/PostWriteTemplate/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,27 @@ export const PostWriteTemplate = ({ initial, mode }) => {
const darkMode = useContext(DarkModeContext);
const posts = useContext(PostsDataContext);

// const updateTempTag = (e) => setPost({ ...post, temp_tag: e.target.value });
const updateTags = () => {
const data = { ...post };
const validTags = data.tags.filter((tag) => !!tag);
const tagSorted = validTags.sort((a, b) => a.id - b.id);

data.tags.push({
id: tagSorted.length === 0 ? 1 : tagSorted[tagSorted.length - 1].id + 1,
content: post.temp_tag,
content: tagInputValue,
});
data.temp_tag = "";
setPost(data);
setTagInputValue("");
};

const updateTitle = (e) => setPost({ ...post, title: e.target.value });
const updateContent = (e) => setPost({ ...post, content: e.target.value });
const deleteTag = (tagId) => {
const data = { ...post };
const afterDeleted = data.tags.filter((tag) => tag && tag.id !== tagId);
setPost({ ...post, tags: afterDeleted });
// data.tags.forEach((tag, index, array) => {
// if (tag && tag.id === tagId) array[index] = null;
// });
};

// tag autoComplete

const onSumbitMethod = (mode) => {
if (mode === "μž‘μ„±") {
alert("κ²Œμ‹œλ¬Όμ„ λ“±λ‘ν•©λ‹ˆλ‹€.");
Expand All @@ -82,16 +77,17 @@ export const PostWriteTemplate = ({ initial, mode }) => {
posts.push({
...post,
id: newId,
author: author,
created_at: created_at,
author,
created_at,
});
navigate(`/${newId}`);
} else if (mode === "μˆ˜μ •") {
alert("κ²Œμ‹œλ¬Όμ„ μˆ˜μ •ν•©λ‹ˆλ‹€.");
posts.forEach((p, i, arr) => {
if (p && p.id === post.id) arr[i] = { ...post };
});
navigate(`/${initial.id}`);
}
navigate("/");
};

useEffect(() => {
Expand All @@ -102,7 +98,6 @@ export const PostWriteTemplate = ({ initial, mode }) => {
}, new Set());
const tagList = [...duplicatedTagList];
setTags([...tagList]);
console.log("tagList", tagList);
}, []);

useEffect(() => {
Expand Down Expand Up @@ -159,13 +154,14 @@ export const PostWriteTemplate = ({ initial, mode }) => {
μΆ”κ°€
</button>
</div>
<div className="flex mt-2 bg-black border-gray-500 rounded-2xl w-full">
<div className="flex mt-2 border-gray-500 rounded-2xl w-full">
{autoCompletes &&
autoCompletes.map((autoComplete) => (
<button
className="tag rounded-2xl text-start border-gray-500 py-2 px-3 text-white focus:bg-gray"
key={autoComplete}
onClick={() => handleAutoCompletes(autoComplete)}
type="button"
>
#{autoComplete}
</button>
Expand Down
35 changes: 35 additions & 0 deletions lionblog-taehyeong/src/data/comment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// dummy data
const comments = [
{
id: 1,
content: "μƒˆν•΄ 볡 많이 λ°›μœΌμ„Έμš”^^",
created_at: "2024-01-01T15:09:43Z",
post: 1,
author: {
id: 2,
username: "user2",
},
},
{
id: 2,
content: "좕ꡬ 2λŒ€ 0;;;",
created_at: "2024-02-07T15:09:43Z",
post: 1,
author: {
id: 3,
username: "user3",
},
},
{
id: 3,
content: "망할 κ°œκ°•μ΄μ•Ό...",
created_at: "2024-03-02T15:09:43Z",
post: 1,
author: {
id: 4,
username: "user4",
},
},
];

export default comments;
24 changes: 24 additions & 0 deletions lionblog-taehyeong/src/hooks/useMediaQuery.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useState, useEffect, useCallback } from "react";

const getQueryMatches = (query) => {
if (typeof window !== "undefined") return window.matchMedia(query).matches;
return false;
};

export const useMediaQuery = (query) => {
const [matches, setMatches] = useState(getQueryMatches(query));

const handleChange = useCallback(() => {
setMatches(getQueryMatches(query));
}, []);

useEffect(() => {
const matchMedia = window.matchMedia(query);

matchMedia.addEventListener("change", handleChange);

return () => matchMedia.removeEventListener("change", handleChange);
}, [query]);

return matches;
};
Loading