Skip to content

Commit 276457a

Browse files
authored
[Feat] : metadata 추가 (#55)
* ✨ [Feat] : 이메일 인증 및 리프레시 토큰 완료 * 🚑 [Fix] : api 호출 버튼 빠르게 눌렀을 때 문제 해결, 파비콘 임시변경 * 🔧[Chore] : console.log 삭제 * 🚑 [Bug&Fix] : 게시글 수정 부분 작성자 확인 핫픽스 * 🎨 [Style] : login, main, search 반응형 웹 수정 * [Feat] : 게시글 수정버튼 연속으로 눌렀을 때 에러 수정 * 🎨 [Style] : search cursor pointer처리 * 🚑 [Fix] : 회원가입 버튼 빠르게 눌렀을 때 문제 해결 * 🚑 [Fix] : 게시글 작성 버그 수정 * [Chore] : 로그아웃에 알림 추가 * 🔧 [Chore] : SEO 향상을 위한 meta data 추가 * 🔧 [Chore] : metadata 추가 및 lighthouse 점수 개선
1 parent c40d415 commit 276457a

File tree

6 files changed

+336
-297
lines changed

6 files changed

+336
-297
lines changed

pages/_app.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ReactQueryDevtools } from "react-query/devtools";
1010
import { styleTagsState } from "@/utils/atoms";
1111
import { apiInstance } from "./api/api";
1212
import InfoAlert from "./components/InfoAlert";
13+
import Head from "next/head";
1314

1415
// import Cookies from 'js-cookie'
1516

@@ -49,12 +50,20 @@ export default function App({ Component, pageProps }: AppPropsWithLayout) {
4950
const getLayout =
5051
Component.getLayout ||
5152
((page) => (
52-
<div className="wrap">
53-
<div className="container">
54-
<Navbar />
55-
{page}
53+
<>
54+
<Head>
55+
<meta name="viewport" content="width=device-width, initial-scale=1" />
56+
<meta charSet="UTF-8" />
57+
<meta name="theme-color" content="#317EFB" />
58+
<title>#찰칵</title>
59+
</Head>
60+
<div className="wrap">
61+
<div className="container">
62+
<Navbar />
63+
{page}
64+
</div>
5665
</div>
57-
</div>
66+
</>
5867
));
5968

6069
return (

pages/components/Navbar.tsx

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import Link from "next/link";
33
import { useRouter } from "next/router";
44
import Cookies from "js-cookie";
55
import Image from "next/image";
6-
import { accessTokenState, userState, userinfoState } from "@/utils/atoms";
7-
import { useRecoilState, useResetRecoilState } from "recoil";
6+
import { accessTokenState, alertState, userState, userinfoState } from "@/utils/atoms";
7+
import { useRecoilState, useResetRecoilState, useSetRecoilState } from "recoil";
88
import { parseCookies } from "nookies";
99
import { useEffect, useState } from "react";
10+
import InfoAlert from "./InfoAlert";
1011
export default function Navbar() {
1112
const router = useRouter();
1213
const [, setActoken] = useRecoilState(accessTokenState);
@@ -15,6 +16,7 @@ export default function Navbar() {
1516
const [login, setLogin] = useState(false);
1617
const [profileImg, setProfileImg] = useState("");
1718
const [cookies, setCookies] = useState({});
19+
const setAlert = useSetRecoilState(alertState);
1820
const cookieNames = ["isLoggedIn", "accessToken", "userId", "myKeywords", "refreshToken", "profileImg"];
1921
const userId = Cookies.get("userId");
2022
const handleLogout = async () => {
@@ -27,7 +29,7 @@ export default function Navbar() {
2729
setCookies(parseCookies());
2830
resetUserInfo();
2931
router.push("/");
30-
alert("로그아웃 되었습니다.");
32+
setAlert({ open: true, message: "로그아웃 되었습니다!" });
3133
} catch (error) {
3234
console.log("fail");
3335
}
@@ -60,7 +62,7 @@ export default function Navbar() {
6062
<>
6163
<div className="h-[50px] navbar bg-base-100">
6264
<div className="flex-1">
63-
<div className="relative w-20 h-8 cursor-pointer" onClick={() => router.push("/main")}>
65+
<div className="relative w-[90.2px] h-8 cursor-pointer" onClick={() => router.push("/main")}>
6466
<Image src={"/images/chalkakLogo.png"} layout="fill" alt="logo_Image" />
6567
</div>
6668
</div>
@@ -72,6 +74,7 @@ export default function Navbar() {
7274
height="1.6em"
7375
viewBox="0 0 512 512"
7476
className="mt-[6px] text-base"
77+
aria-label="Search"
7578
>
7679
<path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z" />
7780
</svg>
@@ -95,40 +98,41 @@ export default function Navbar() {
9598
{login ? (
9699
<>
97100
<li>
98-
<a
101+
<div
99102
onClick={() => {
100103
router.push(`/userinfo/${userId}`);
101104
}}
102105
>
103106
userinfo
104-
</a>
107+
</div>
105108
</li>
106109
<li>
107-
<a
110+
<div
108111
onClick={() => {
109112
handleLogout();
110113
router.push("/main");
111114
}}
112115
>
113116
Logout
114-
</a>
117+
</div>
115118
</li>
116119
</>
117120
) : (
118121
<li>
119-
<a
122+
<div
120123
onClick={() => {
121124
router.push("/login");
122125
}}
123126
>
124127
Login
125-
</a>
128+
</div>
126129
</li>
127130
)}
128131
</ul>
129132
</div>
130133
</div>
131134
</div>
135+
<InfoAlert />
132136
<div className="flex items-center justify-start pb-2"></div>
133137
</>
134138
);

pages/postEditor/index.tsx

Lines changed: 103 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import InfoAlert from "../components/InfoAlert";
2222
import Cookies from "js-cookie";
2323
import router, { useRouter } from "next/router";
2424
import { GetServerSidePropsContext } from "next";
25+
import Head from "next/head";
2526

2627
interface StyleTag {
2728
id: number;
@@ -443,108 +444,114 @@ const HomePage = ({ initialPostData }: HomePageProps) => {
443444
};
444445

445446
return (
446-
<div className="w-full m-auto">
447-
<div>
448-
<GoogleMapsComponent />
449-
</div>
450-
<Divider width="w-full" />
451-
<div className="mb-5">
452-
<ImageUpload />
453-
</div>
454-
<textarea
455-
placeholder="내용 입력"
456-
className="textarea textarea-bordered focus:outline-none leading-tight textarea-sm resize-none w-full max-w-2xl py-2 my-5 h-[70px]"
457-
value={content}
458-
onChange={handleContentChange}
459-
></textarea>
460-
<div className="mb-4">
461-
<h2 className="mr-3 mb-3 font-medium">체형 공개</h2>
462-
<div className="flex items-center">
463-
<label className="flex items-center">
464-
<div>공개</div>
465-
<input
466-
type="checkbox"
467-
checked={privacyHeight}
468-
onChange={handlePublicCheck}
469-
className="checkbox checkbox-xs mr-5 ml-1 mt-[1.5px]"
470-
/>
471-
</label>
472-
<label className="flex items-center">
473-
<div>비공개</div>
474-
<input
475-
type="checkbox"
476-
checked={!privacyHeight}
477-
onChange={handlePrivateCheck}
478-
className="checkbox checkbox-xs ml-1 mt-[1.5px]"
479-
/>
480-
</label>
447+
<>
448+
<Head>
449+
<title>#찰칵 - 게시글 작성</title>
450+
<meta name="description" content="게시글 작성 페이지입니다." />
451+
</Head>
452+
<div className="w-full m-auto">
453+
<div>
454+
<GoogleMapsComponent />
481455
</div>
482-
</div>
483-
<Divider width="w-full" />
484-
<div className="mb-5">
485-
{dynamicKeywords.map((keyword) => (
486-
<div key={keyword} className="inline-block">
487-
<div className="flex m-1 text-blue-400">
488-
#{keyword}
489-
<AiOutlineClose
490-
className="flex items-center text-gray-300 cursor-pointer text-xs mt-[3px]"
491-
onClick={() => removeDynamicKeyword(keyword)}
456+
<Divider width="w-full" />
457+
<div className="mb-5">
458+
<ImageUpload />
459+
</div>
460+
<textarea
461+
placeholder="내용 입력"
462+
className="textarea textarea-bordered focus:outline-none leading-tight textarea-sm resize-none w-full max-w-2xl py-2 my-5 h-[70px]"
463+
value={content}
464+
onChange={handleContentChange}
465+
></textarea>
466+
<div className="mb-4">
467+
<h2 className="mr-3 mb-3 font-medium">체형 공개</h2>
468+
<div className="flex items-center">
469+
<label className="flex items-center">
470+
<div>공개</div>
471+
<input
472+
type="checkbox"
473+
checked={privacyHeight}
474+
onChange={handlePublicCheck}
475+
className="checkbox checkbox-xs mr-5 ml-1 mt-[1.5px]"
492476
/>
493-
</div>
494-
</div>
495-
))}
496-
{styleKeywords.map((keyword) => (
497-
<div key={keyword} className="inline-block m-1">
498-
#{keyword}
499-
</div>
500-
))}
501-
{seasonKeywords.map((keyword) => (
502-
<div key={keyword} className="inline-block m-1">
503-
#{keyword}
504-
</div>
505-
))}
506-
{weatherKeywords.map((keyword) => (
507-
<div key={keyword} className="inline-block m-1">
508-
#{keyword}
477+
</label>
478+
<label className="flex items-center">
479+
<div>비공개</div>
480+
<input
481+
type="checkbox"
482+
checked={!privacyHeight}
483+
onChange={handlePrivateCheck}
484+
className="checkbox checkbox-xs ml-1 mt-[1.5px]"
485+
/>
486+
</label>
509487
</div>
510-
))}
511-
</div>
512-
<div>
513-
<h2 className="mb-2 font-medium">Tag</h2>
514-
<input
515-
type="text"
516-
className="border-b border-gray-200 focus:border-gray-700 transition-colors ease-in duration-100 w-full mb-7 py-2"
517-
placeholder="키워드를 입력하세요"
518-
value={dynamicKeywordInput}
519-
onChange={handleDynamicKeywordChange}
520-
onKeyUp={handleDynamicKeywordSubmit}
521-
/>
522-
<input type="text" className="hidden" />
523-
</div>
524-
<div className="w-full mb-5">
525-
<h2 className="mb-2 font-medium">Style</h2>
488+
</div>
489+
<Divider width="w-full" />
490+
<div className="mb-5">
491+
{dynamicKeywords.map((keyword) => (
492+
<div key={keyword} className="inline-block">
493+
<div className="flex m-1 text-blue-400">
494+
#{keyword}
495+
<AiOutlineClose
496+
className="flex items-center text-gray-300 cursor-pointer text-xs mt-[3px]"
497+
onClick={() => removeDynamicKeyword(keyword)}
498+
/>
499+
</div>
500+
</div>
501+
))}
502+
{styleKeywords.map((keyword) => (
503+
<div key={keyword} className="inline-block m-1">
504+
#{keyword}
505+
</div>
506+
))}
507+
{seasonKeywords.map((keyword) => (
508+
<div key={keyword} className="inline-block m-1">
509+
#{keyword}
510+
</div>
511+
))}
512+
{weatherKeywords.map((keyword) => (
513+
<div key={keyword} className="inline-block m-1">
514+
#{keyword}
515+
</div>
516+
))}
517+
</div>
518+
<div>
519+
<h2 className="mb-2 font-medium">Tag</h2>
520+
<input
521+
type="text"
522+
className="border-b border-gray-200 focus:border-gray-700 transition-colors ease-in duration-100 w-full mb-7 py-2"
523+
placeholder="키워드를 입력하세요"
524+
value={dynamicKeywordInput}
525+
onChange={handleDynamicKeywordChange}
526+
onKeyUp={handleDynamicKeywordSubmit}
527+
/>
528+
<input type="text" className="hidden" />
529+
</div>
526530
<div className="w-full mb-5">
527-
<div className="flex flex-wrap">{styleKeywordCheckboxes}</div>
528-
<div className="flex">{tpoKeywordCheckboxes}</div>
531+
<h2 className="mb-2 font-medium">Style</h2>
532+
<div className="w-full mb-5">
533+
<div className="flex flex-wrap">{styleKeywordCheckboxes}</div>
534+
<div className="flex">{tpoKeywordCheckboxes}</div>
535+
</div>
529536
</div>
537+
<div className="mb-5">
538+
<h2 className="mb-2 font-medium">Season*</h2>
539+
<div className="flex ">{seasonKeywordCheckboxes}</div>
540+
</div>
541+
<div>
542+
<h2 className="mb-2 font-medium">Weather*</h2>
543+
<div className="flex ">{weatherKeywordCheckboxes}</div>
544+
</div>
545+
{userouter.query.id
546+
? renderButton(
547+
(imageIds.length > 0 || uploadedImageUrls.length > 0) &&
548+
seasonKeywords.length > 0 &&
549+
weatherKeywords.length > 0,
550+
)
551+
: renderButton(uploadedImageUrls.length > 0 && seasonKeywords.length > 0 && weatherKeywords.length > 0)}
552+
<InfoAlert />
530553
</div>
531-
<div className="mb-5">
532-
<h2 className="mb-2 font-medium">Season*</h2>
533-
<div className="flex ">{seasonKeywordCheckboxes}</div>
534-
</div>
535-
<div>
536-
<h2 className="mb-2 font-medium">Weather*</h2>
537-
<div className="flex ">{weatherKeywordCheckboxes}</div>
538-
</div>
539-
{userouter.query.id
540-
? renderButton(
541-
(imageIds.length > 0 || uploadedImageUrls.length > 0) &&
542-
seasonKeywords.length > 0 &&
543-
weatherKeywords.length > 0,
544-
)
545-
: renderButton(uploadedImageUrls.length > 0 && seasonKeywords.length > 0 && weatherKeywords.length > 0)}
546-
<InfoAlert />
547-
</div>
554+
</>
548555
);
549556
};
550557

pages/posts/CommentSection.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ const CommentsSection: React.FC<CommentsSectionProps> = ({ postId }) => {
104104
{comment.comment}
105105
</div>
106106
</div>
107-
<div className="md:text-xs text-[0.5rem] text-gray-400 ml-1 mt-1">
107+
<div className="md:text-xs text-[0.5rem] text-gray-500 ml-1 mt-1">
108108
{formatDateToRelativeTime(comment.createAt)}
109109
</div>
110110
</div>
@@ -113,7 +113,7 @@ const CommentsSection: React.FC<CommentsSectionProps> = ({ postId }) => {
113113
</div>
114114
))}
115115
{totalComments > 3 && (
116-
<div className="text-gray-400 cursor-pointer text-xs md:text-sm" onClick={openCommentsModal}>
116+
<div className="text-gray-500 cursor-pointer text-xs md:text-sm" onClick={openCommentsModal}>
117117
댓글 더 보기...
118118
</div>
119119
)}

pages/posts/[postId].tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import WarningAlert from "../components/WarningAlert";
1919
import { useSetRecoilState } from "recoil";
2020
import { alertState } from "@/utils/atoms";
2121
import InfoAlert from "../components/InfoAlert";
22+
import Head from "next/head";
2223
import SkeletonPost from "../components/SkeletonPost";
2324
interface Writer {
2425
height: number;
@@ -335,6 +336,9 @@ const HomePage = () => {
335336

336337
return (
337338
<>
339+
<Head>
340+
<meta name="description" content="게시글 페이지입니다." />
341+
</Head>
338342
<Alert open={alertOepn} setOpen={setAlertOpen} message={alertMessage} />
339343
<div className=" flex flex-col mt-6">
340344
<div className=" flex items-center w-full mx-auto">
@@ -460,7 +464,7 @@ const HomePage = () => {
460464
<HeartsModal isOpen={heartsModalIsOpen} closeModal={closeHeartsModal} postId={postId} />
461465
<div className=" mb-36">
462466
<CommentsSection postId={postId} />
463-
<div className="text-xs text-gray-400 mr-7 mt-2 text-end">
467+
<div className="text-xs text-gray-500 mr-7 mt-2 text-end">
464468
{postData?.createdAt ? formatDateToRelativeTime(postData.createdAt) : ""}
465469
</div>
466470
<Divider width="11rem" />

0 commit comments

Comments
 (0)