Skip to content

Commit 6af996c

Browse files
authored
Merge pull request #7 from seondal/develop
v0.1.1
2 parents dfd6dd7 + 00ad0cc commit 6af996c

File tree

12 files changed

+144
-33
lines changed

12 files changed

+144
-33
lines changed

next.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/** @type {import('next').NextConfig} */
22
const nextConfig = {
33
images: {
4-
domains: ["i.ibb.co", "k.kakaocdn.net"],
4+
domains: ["i.ibb.co", "k.kakaocdn.net", "img1.kakaocdn.net"],
55
},
66
};
77

src/app/(main)/SearchBar.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,19 @@ export default function SearchBar() {
1414
const router = useRouter();
1515
const [keyword, setKeyword] = useState<string>("");
1616

17+
function getDisplayedKeyword() {
18+
if (keywordQuery) return keywordQuery;
19+
if (userid) return `@${userid}`;
20+
if (categoryQuery) {
21+
const categoryArray = categoryQuery.split(",").map((item) => `#${item}`);
22+
return categoryArray.join(" ");
23+
}
24+
return "";
25+
}
26+
1727
useEffect(() => {
18-
setKeyword(keywordQuery ?? userid ? `@${userid}` : "");
28+
setKeyword(getDisplayedKeyword());
29+
// eslint-disable-next-line react-hooks/exhaustive-deps
1930
}, [params]);
2031

2132
const [categoryActive, setCategoryActive] = useState(false);
@@ -32,6 +43,15 @@ export default function SearchBar() {
3243
return router.push(`/?userid=${tmpUserid}`);
3344
}
3445

46+
if (keyword.startsWith("#")) {
47+
const searchedCategoreis = keyword
48+
.split(" ")
49+
.filter((item) => item.startsWith("#"))
50+
.map((item) => item.substring(1));
51+
const categoryQueryString = searchedCategoreis.join(",");
52+
return router.push(`/?category=${categoryQueryString}`);
53+
}
54+
3555
return router.push(`/?keyword=${keyword}`);
3656
}
3757

@@ -42,7 +62,7 @@ export default function SearchBar() {
4262
<input
4363
name="keyword"
4464
type="search"
45-
placeholder="키워드로 검색하기"
65+
placeholder="키워드,@사용자,#카테고리 검색"
4666
value={keyword}
4767
onChange={(e) => setKeyword(e.target.value)}
4868
/>

src/app/api/recipe/route.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ export async function GET(req: NextRequest, res: NextResponse) {
4848
const filteredDocs: DocumentData[] = [];
4949
snapshot.forEach((doc) => {
5050
const data = doc.data();
51-
if (data.description && data.description.includes(keyword)) {
51+
if (
52+
data.title.includes(keyword) ||
53+
(data.description && data.description.includes(keyword))
54+
) {
5255
filteredDocs.push(data);
5356
}
5457
});

src/app/api/auth/signin/route.ts renamed to src/app/api/signin/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NextRequest, NextResponse } from "next/server";
2-
import { kakaoApi } from "../../instance";
32
import { KAKAO_CLIENT_ID, KAKAO_REDIRECT_URI } from "@/constants/env";
3+
import { kakaoApi } from "../instance";
44
interface PostKakaoTokenI {
55
access_token: string;
66
token_type: string;

src/app/auth/signin/page.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
import { useEffect } from "react";
44
import { useRouter } from "next/navigation";
55
import { myApi } from "@/app/api/instance";
6-
import { auth } from "@/firebase";
6+
import { auth, db } from "@/firebase";
77
import {
88
browserLocalPersistence,
99
OAuthProvider,
1010
setPersistence,
1111
signInWithCredential,
1212
} from "firebase/auth";
13+
import { doc, setDoc } from "firebase/firestore";
1314

1415
interface SigninPageI {
1516
searchParams: { code: string };
@@ -23,7 +24,7 @@ export default function SigninPage({ searchParams }: SigninPageI) {
2324
const signIn = async () => {
2425
try {
2526
// API 호출
26-
const res = await myApi.get(`/auth/signin`, { params: { code: code } });
27+
const res = await myApi.get(`/signin`, { params: { code: code } });
2728
const data = res.data;
2829

2930
// OAuth provider 설정
@@ -35,16 +36,30 @@ export default function SigninPage({ searchParams }: SigninPageI) {
3536
// Firebase 인증 설정 및 로그인
3637
await setPersistence(auth, browserLocalPersistence);
3738
const fbRes = await signInWithCredential(auth, credential);
39+
const fbData = fbRes.user;
40+
41+
console.log("🚀 ~ signIn ~ fbData:", fbData);
42+
// 유저 정보 저장
43+
const newRef = doc(db, "user", fbData.uid);
44+
const newDoc = {
45+
name: fbData.displayName,
46+
email: fbData.email,
47+
phoneNumber: fbData.phoneNumber,
48+
photoURL: fbData.photoURL,
49+
providerId: fbData.providerId,
50+
providerData: fbData.providerData,
51+
};
52+
await setDoc(newRef, newDoc);
3853

3954
// 로그인 성공 후 리디렉션
40-
router.replace("/mypage");
55+
alert(`${fbData.displayName}님, 로그인에 성공했어요`);
56+
router.replace("/");
4157
} catch (error) {
4258
console.error("Error during sign-in:", error);
4359
}
4460
};
4561

4662
signIn();
4763
}, [code, router]);
48-
4964
return <div>로그인중...</div>;
5065
}

src/app/mypage/layout.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { usePathname, useRouter } from "next/navigation";
77
import { LayoutI } from "@/interface/page";
88
import { auth } from "@/firebase";
99
import Image from "next/image";
10+
import copyToClipboard from "@/utils/copyToClipboard";
1011

1112
const MYPAGE = [
1213
{ text: "업로드한 레시피", path: "/mypage" },
@@ -17,8 +18,9 @@ export default function MypageLayout({ children }: LayoutI) {
1718
const router = useRouter();
1819

1920
const data = auth.currentUser;
21+
console.log("🚀 ~ MypageLayout ~ data:", data);
2022
async function signIn() {
21-
router.replace(KAKAO_AUTHORIZE);
23+
router.push(KAKAO_AUTHORIZE);
2224
}
2325

2426
function signOut() {
@@ -28,12 +30,7 @@ export default function MypageLayout({ children }: LayoutI) {
2830

2931
async function handleCopyUserid() {
3032
if (data) {
31-
try {
32-
await navigator.clipboard.writeText(data?.uid);
33-
alert("내 아이디가 복사되었어요");
34-
} catch (error) {
35-
alert("내 아이디 복사에 실패했어요. 다시 시도해주세요");
36-
}
33+
copyToClipboard(data.uid, "내 아이디가 복사되었어요");
3734
}
3835
}
3936

src/app/mypage/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { auth } from "@/firebase";
99

1010
export default function Page() {
1111
const data = auth.currentUser;
12+
console.log("🚀 ~ Page ~ data:", data);
1213
const [recipeData, setRecipeData] = useState<RecipeI[]>();
1314

1415
async function fetchFeed() {

src/app/upload/page.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ export default function UploadPage() {
1414
useState(NO_SELECTION);
1515
const [beforeImage, setBeforeImage] = useState<File>();
1616
const [afterImage, setAfterImage] = useState<File>();
17+
const [loading, setLoading] = useState(false);
1718

1819
const isSubmitActive =
20+
!loading &&
1921
beforeImage !== null &&
2022
afterImage !== null &&
2123
selectedMainCategory !== NO_SELECTION;
@@ -39,12 +41,17 @@ export default function UploadPage() {
3941
}
4042
}
4143

44+
function handleSubmit() {
45+
setLoading(true);
46+
}
47+
4248
return (
4349
<form
4450
encType="multipart/form-data"
4551
method="POST"
4652
action={`/api/recipe?userid=${data?.uid}`}
47-
onKeyDown={handleKeyDownOnForm}>
53+
onKeyDown={handleKeyDownOnForm}
54+
onSubmit={handleSubmit}>
4855
<label>
4956
*레시피 이름
5057
<input
@@ -128,7 +135,14 @@ export default function UploadPage() {
128135
<label>
129136
설명 <textarea maxLength={300} name="description" />
130137
</label>
131-
<input type="submit" value="레시피 등록하기" disabled={!isSubmitActive} />
138+
139+
<button
140+
type="submit"
141+
disabled={!isSubmitActive}
142+
aria-busy={loading}
143+
aria-label="업로드 중입니다...">
144+
레시피 등록하기
145+
</button>
132146
</form>
133147
);
134148
}

src/components/Category.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export default function Category({ open, onClose }: CategoryI) {
1515
return searchParam.has({ category: name }) !== undefined;
1616
}
1717

18-
function handleSelectCategory(name: string) {
18+
function handleSelectCategory(e: ChangeEvent<HTMLInputElement>) {
19+
const name = e.target.id;
1920
const param = { category: name };
2021
if (searchParam.has(param)) {
2122
searchParam.del(param);
@@ -40,21 +41,23 @@ export default function Category({ open, onClose }: CategoryI) {
4041
<div key={main.text} className="flex gap-4 mb-4">
4142
<label className="min-w-fit">
4243
<input
44+
id={main.text}
4345
type="checkbox"
4446
name="main"
45-
onChange={() => handleSelectCategory(main.text)}
46-
defaultChecked={isChecked(main.text)}
47+
onChange={(e) => handleSelectCategory(e)}
48+
checked={isChecked(main.text)}
4749
/>
4850
<strong>{main.text}</strong>
4951
</label>
5052
<div className="flex flex-wrap gap-x-4">
5153
{main.sub.map((sub) => (
5254
<label key={sub}>
5355
<input
56+
id={sub}
5457
type="checkbox"
5558
name="sub"
56-
onClick={() => handleSelectCategory(sub)}
57-
defaultChecked={isChecked(sub)}
59+
onChange={(e) => handleSelectCategory(e)}
60+
checked={isChecked(sub)}
5861
/>
5962
{sub}
6063
</label>

src/components/Header.tsx

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { auth } from "@/firebase";
44
import {
55
ArrowUpTrayIcon,
66
Bars3Icon,
7+
UserCircleIcon,
78
XMarkIcon,
8-
} from "@heroicons/react/24/outline";
9+
} from "@heroicons/react/24/solid";
910
import { usePathname, useRouter } from "next/navigation";
1011

1112
export default function Header() {
@@ -24,7 +25,12 @@ export default function Header() {
2425

2526
return (
2627
<nav className="px-4 items-center">
27-
<h2 style={{ marginBottom: "0px" }}>Filter Recipe</h2>
28+
<h2
29+
style={{ marginBottom: "0px" }}
30+
className="cursor-pointer"
31+
onClick={() => router.push("/")}>
32+
Filter Recipe
33+
</h2>
2834
{isMain ? (
2935
<nav className="gap-4">
3036
<button
@@ -33,10 +39,15 @@ export default function Header() {
3339
<ArrowUpTrayIcon className="icon-text" />
3440
레시피 등록
3541
</button>
36-
<Bars3Icon
37-
className="icon-button"
38-
onClick={() => router.push("/mypage")}
39-
/>
42+
<div
43+
className="cursor-pointer"
44+
onClick={() => router.push("/mypage")}>
45+
{data ? (
46+
<UserCircleIcon className="icon-button" />
47+
) : (
48+
<Bars3Icon className="icon-button" />
49+
)}
50+
</div>
4051
</nav>
4152
) : (
4253
<XMarkIcon onClick={() => router.back()} className="icon-button" />

0 commit comments

Comments
 (0)