Skip to content

Commit e6cad88

Browse files
authored
Merge pull request #6 from Team-Stracker/feature/5-signin-login
Feature/5 signin login
2 parents 91221c7 + 6048ccb commit e6cad88

File tree

20 files changed

+7444
-1115
lines changed

20 files changed

+7444
-1115
lines changed

apps/web/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ yarn-error.log*
3939
# typescript
4040
*.tsbuildinfo
4141
next-env.d.ts
42+
stracker-f4063-firebase-adminsdk-fbsvc-674bfb32c4.json

apps/web/firebase.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Import the functions you need from the SDKs you need
2+
import { initializeApp } from "firebase/app";
3+
import { getAuth } from "firebase/auth";
4+
import { getFirestore } from "firebase/firestore";
5+
6+
const firebaseConfig = {
7+
apiKey: "AIzaSyA3blhKo9IqKm2jQ1fsxhHrO0IAxzs_Owg",
8+
authDomain: "stracker-f4063.firebaseapp.com",
9+
projectId: "stracker-f4063",
10+
storageBucket: "stracker-f4063.firebasestorage.app",
11+
messagingSenderId: "227885045962",
12+
appId: "1:227885045962:web:438fedd95199df6cd8fc33",
13+
measurementId: "G-F0WYN2556J",
14+
};
15+
16+
// Initialize Firebase
17+
export const app = initializeApp(firebaseConfig);
18+
19+
export const auth = getAuth(app);
20+
export const db = getFirestore(app);

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"dependencies": {
1313
"@stracker/design-token": "workspace:^",
1414
"clsx": "^2.1.1",
15+
"firebase": "^11.9.0",
1516
"next": "^14.1.0",
1617
"tailwindcss": "^3.4.1"
1718
},

apps/web/src/apis/getMajorTechs.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { getFirestore, doc, getDoc } from "firebase/firestore";
2+
import { app } from "../../firebase";
3+
4+
const db = getFirestore(app);
5+
6+
export const getMajorTechs = async (major: string): Promise<string[]> => {
7+
try {
8+
const docRef = doc(db, "majors", major);
9+
const docSnap = await getDoc(docRef);
10+
11+
if (!docSnap.exists()) {
12+
console.warn("해당 전공이 존재하지 않습니다:", major);
13+
return [];
14+
}
15+
16+
const data = docSnap.data();
17+
console.log("Firestore에서 가져온 데이터:", data);
18+
19+
// techs 대신 stacks 필드 사용
20+
const stacks = data?.stacks;
21+
22+
if (!stacks) {
23+
console.warn("stacks 필드가 없습니다.");
24+
return [];
25+
}
26+
27+
if (!Array.isArray(stacks)) {
28+
console.warn("stacks 필드가 배열이 아닙니다:", stacks);
29+
return [];
30+
}
31+
32+
return stacks;
33+
} catch (error) {
34+
console.error("getMajorTechs 에러:", error);
35+
return [];
36+
}
37+
};

apps/web/src/apis/getUserTech.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { getFirestore, doc, getDoc } from "firebase/firestore";
2+
import { User } from "firebase/auth"; // User 타입 받을거임
3+
4+
export const getUserTech = async (user: User) => {
5+
const db = getFirestore();
6+
const userDocRef = doc(db, "users", user.uid);
7+
const userDoc = await getDoc(userDocRef);
8+
9+
if (!userDoc.exists()) {
10+
throw new Error("유저 문서 없음");
11+
}
12+
13+
const data = userDoc.data();
14+
return data.tech;
15+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import axios from "axios";
2+
3+
const apiKey = "AIzaSyDuV_hSFc-6-C1uq4sBxnvlyE4J3vVpkuk";
4+
const cx = "25ec413420f26414b";
5+
6+
export const googleSearchAPI = async (query: string) => {
7+
const url = `https://www.googleapis.com/customsearch/v1?key=${apiKey}&cx=${cx}&q=${query}`;
8+
9+
try {
10+
const res = await axios.get(url);
11+
const items = res.data.items || [];
12+
13+
// 결과 출력 (샘플)
14+
return items.map((item: any) => ({
15+
title: item.title,
16+
link: item.link,
17+
snippet: item.snippet,
18+
}));
19+
} catch (err) {
20+
console.error("구글 검색 에러:", err);
21+
return [];
22+
}
23+
};

apps/web/src/apis/logIn.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { signInWithEmailAndPassword } from "firebase/auth";
2+
import { auth } from "../../firebase";
3+
4+
export const logIn = async ({
5+
email,
6+
password,
7+
}: {
8+
email: string;
9+
password: string;
10+
}) => {
11+
try {
12+
const userCredential = await signInWithEmailAndPassword(
13+
auth,
14+
email,
15+
password,
16+
);
17+
const user = userCredential.user;
18+
19+
console.log("로그인 성공");
20+
} catch (err) {
21+
console.error("로그인 실패:", err);
22+
throw err;
23+
}
24+
};

apps/web/src/apis/logOut.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { signOut } from "firebase/auth";
2+
import { auth } from "../../firebase";
3+
4+
export const logOut = async () => {
5+
try {
6+
await signOut(auth);
7+
console.log("로그아웃 성공");
8+
} catch (err) {
9+
console.error("로그아웃 실패:", err);
10+
}
11+
};

apps/web/src/apis/signIn.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { createUserWithEmailAndPassword } from "firebase/auth";
2+
import { doc, setDoc } from "firebase/firestore";
3+
import { auth } from "../../firebase";
4+
import { db } from "../../firebase";
5+
6+
interface SignUpParams {
7+
email: string;
8+
password: string;
9+
id: string;
10+
tech: string;
11+
}
12+
13+
export const signIn = async ({ email, password, id, tech }: SignUpParams) => {
14+
try {
15+
const userCredential = await createUserWithEmailAndPassword(
16+
auth,
17+
email,
18+
password,
19+
);
20+
const user = userCredential.user;
21+
22+
await setDoc(doc(db, "users", user.uid), {
23+
uid: user.uid,
24+
email: user.email,
25+
id,
26+
tech,
27+
createdAt: new Date(),
28+
});
29+
30+
console.log("회원가입 및 유저 정보 저장 완료");
31+
} catch (err) {
32+
console.error("회원가입 실패:", err);
33+
throw err;
34+
}
35+
};

apps/web/src/app/login/page.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,49 @@
1+
"use client";
12
import { Button, Input } from "@web/components";
3+
import { useState } from "react";
4+
import { logIn } from "@web/apis/logIn";
5+
import { useRouter } from "next/navigation";
26

37
const loginPage = () => {
8+
const [email, setEmail] = useState("");
9+
const [password, setPassword] = useState("");
10+
11+
const router = useRouter();
12+
13+
const onSubmit = () => {
14+
logIn({ email, password });
15+
router.push("/");
16+
};
17+
418
return (
519
<div className="flex flex-col items-center justify-center h-screen">
620
<div className="border border-solid border-zinc-200 w-[30rem] h-au rounded-3xl flex flex-col gap-10 px-6 pt-5 pb-4">
721
<div className="flex flex-col gap-8">
822
<img src="/assets/Logo.svg" className="w-[6rem]" />
923
<div className="flex flex-col items-center justify-center gap-4">
1024
<Input
11-
label="아이디"
12-
placeholder="아이디를 입력해주세요.."
25+
label="이메일"
26+
placeholder="이메일을 입력해주세요.."
1327
type="text"
28+
onChange={(e) => setEmail(e.target.value)}
29+
value={email}
1430
/>
1531
<Input
1632
label="비밀번호"
1733
placeholder="비밀번호를 입력해주세요.."
1834
type="password"
35+
onChange={(e) => setPassword(e.target.value)}
36+
value={password}
1937
/>
2038
</div>
2139
</div>
2240
<div className="flex flex-col items-center justify-center gap-5">
23-
<Button size="large" backColor="blue" borderColor="blue">
41+
<Button
42+
size="large"
43+
backColor="blue"
44+
borderColor="blue"
45+
onClick={onSubmit}
46+
>
2447
로그인
2548
</Button>
2649
<div className="text-b1 flex items-center">

0 commit comments

Comments
 (0)