diff --git a/functions/src/routers/goalRouter.ts b/functions/src/routers/goalRouter.ts index 8c6666e..612ebe4 100644 --- a/functions/src/routers/goalRouter.ts +++ b/functions/src/routers/goalRouter.ts @@ -9,20 +9,22 @@ const db = admin.firestore(); router.get("/", async (req: Request, res: Response) => { try { const goalSnapshot = await db.collection("goal").get(); + if (goalSnapshot.empty) { return res.status(404).json({ message: "No goals found" }); } - const goals = goalSnapshot.docs.map((doc) => { + const goalData: Goal[] = goalSnapshot.docs.map((doc) => { const data = doc.data(); return { - id: doc.id, - ...data, + goalId: doc.id, deadline: new Date(data.deadline._seconds * 1000), + userId: data.userId, + text: data.text, }; }); - return res.json(goals); + return res.json(goalData); } catch (error) { return res.status(500).json({ message: "Error fetching goals" }); } @@ -46,12 +48,13 @@ router.get("/:userId", async (req: Request, res: Response) => { return res.status(404).json({ message: "No goals found for this user" }); } - const goals = goalSnapshot.docs.map((doc) => { + const goals: Goal[] = goalSnapshot.docs.map((doc) => { const data = doc.data(); return { - id: doc.id, - ...data, + goalId: doc.id, + userId: data.userId, deadline: new Date(data.deadline._seconds * 1000), + text: data.text, }; }); @@ -113,12 +116,17 @@ router.put("/:goalId", async (req: Request, res: Response) => { const updateData: Partial> & { deadline?: admin.firestore.Timestamp; } = {}; - if (userId) updateData.userId = userId; - if (deadline) + if (userId) { + updateData.userId = userId; + } + if (deadline) { updateData.deadline = admin.firestore.Timestamp.fromDate( new Date(deadline) ); - if (text) updateData.text = text; + } + if (text) { + updateData.text = text; + } try { await db.collection("goal").doc(goalId).update(updateData); diff --git a/functions/src/routers/postRouter.ts b/functions/src/routers/postRouter.ts index 8457438..09846a3 100644 --- a/functions/src/routers/postRouter.ts +++ b/functions/src/routers/postRouter.ts @@ -9,22 +9,25 @@ const db = admin.firestore(); router.get("/", async (req: Request, res: Response) => { try { const postSnapshot = await db.collection("post").get(); + if (postSnapshot.empty) { return res.status(404).json({ message: "No posts found" }); } - const posts = postSnapshot.docs.map((doc) => { + const postData: Post[] = postSnapshot.docs.map((doc) => { const data = doc.data(); return { - id: doc.id, - ...data, + postId: doc.id, + userId: data.userId, + storedId: data.storedId, + text: data.text, + goalId: data.goalId, submittedAt: new Date(data.submittedAt._seconds * 1000), }; }); - return res.json(posts); + return res.json(postData); } catch (error) { - console.log(error); return res.status(500).json({ message: "Error fetching posts" }); } }); @@ -49,8 +52,11 @@ router.get("/:userId", async (req: Request, res: Response) => { const posts = postSnapshot.docs.map((doc) => { const data = doc.data(); return { - id: doc.id, - ...data, + postId: doc.id, + userId: data.userId, + storedId: data.storedId, + text: data.text, + goalId: data.goalId, submittedAt: new Date(data.submittedAt._seconds * 1000), }; }); @@ -82,6 +88,7 @@ router.post("/", async (req: Request, res: Response) => { message: "userId, storedId, text, goalId, and submittedAt are required", }); } + if (!text) { text = ""; } @@ -110,16 +117,24 @@ router.put("/:postId", async (req: Request, res: Response) => { const { userId, storedId, text, goalId }: Partial = req.body; if (!userId && !storedId && !text && !goalId) { - return res - .status(400) - .json({ message: "At least one field is required to update" }); + return res.status(400).json({ + message: "At least one of userId, storedId, text, or goalId is required", + }); } const updateData: Partial = {}; - if (userId) updateData.userId = userId; - if (storedId) updateData.storedId = storedId; - if (text) updateData.text = text; - if (goalId) updateData.goalId = goalId; + if (userId) { + updateData.userId = userId; + } + if (storedId) { + updateData.storedId = storedId; + } + if (text) { + updateData.text = text; + } + if (goalId) { + updateData.goalId = goalId; + } try { await db.collection("post").doc(postId).update(updateData); diff --git a/functions/src/routers/types.ts b/functions/src/routers/types.ts index f1f8f5d..430f965 100644 --- a/functions/src/routers/types.ts +++ b/functions/src/routers/types.ts @@ -1,6 +1,7 @@ export interface User { name: string; streak: number; + fcmToken?: string; } export interface Goal { diff --git a/functions/src/routers/userRouter.ts b/functions/src/routers/userRouter.ts index 636ea3d..2126ecf 100644 --- a/functions/src/routers/userRouter.ts +++ b/functions/src/routers/userRouter.ts @@ -14,10 +14,14 @@ router.get("/", async (req: Request, res: Response) => { return res.status(404).json({ message: "No users found" }); } - const userData = userSnapshot.docs.map((doc) => ({ - uid: doc.id, - ...doc.data(), - })); + const userData: User[] = userSnapshot.docs.map((doc) => { + const data = doc.data(); + return { + userId: doc.id, + name: data.name, + streak: data.streak, + }; + }); return res.json(userData); } catch (error) { @@ -35,10 +39,20 @@ router.get("/id/:userId", async (req: Request, res: Response) => { try { const userDoc = await getUserFromId(userId); + if (!userDoc.exists) { return res.status(404).json({ message: "User not found" }); } - return res.json({ uid: userDoc.id, ...userDoc.data() }); + + const data = userDoc.data(); + + const userData: User & { userId: string } = { + userId: userDoc.id, + name: data?.name || "", + streak: data?.streak || 0, + }; + + return res.json(userData); } catch (error) { return res.status(500).json({ message: "Error fetching user data" }); } @@ -54,16 +68,21 @@ router.get("/name/:userName", async (req: Request, res: Response) => { try { const userSnapshot = await getUserFromName(userName); + if (userSnapshot.empty) { return res.status(404).json({ message: "User not found" }); } - const userData = userSnapshot.docs.map((doc) => ({ - uid: doc.id, - ...doc.data(), - })); + const userData: User[] = userSnapshot.docs.map((doc) => { + const data = doc.data(); + return { + userId: doc.id, + name: data.name, + streak: data.streak, + }; + }); - return res.json(userData[0]); + return res.json(userData); } catch (error) { return res.status(500).json({ message: "Error fetching user data" }); } @@ -71,27 +90,31 @@ router.get("/name/:userName", async (req: Request, res: Response) => { // POST: 新しいユーザーを登録 router.post("/", async (req: Request, res: Response) => { + let userId: string; let name: User["name"]; - let uid: string; let streak: User["streak"]; + let fcmToken: User["fcmToken"]; try { - ({ name, uid, streak = 0 } = req.body); + ({ name, userId, streak = 0, fcmToken = "" } = req.body); } catch (error) { return res.status(400).json({ message: "Invalid request body" }); } - if (!name || !uid) { - return res.status(400).json({ message: "name and uid are required" }); + if (!name || !userId) { + return res.status(400).json({ message: "name and userId are required" }); } try { - await db.collection("user").doc(uid).set({ + await db.collection("user").doc(userId).set({ name: name, streak: streak, + fcmToken: fcmToken, }); - return res.status(201).json({ message: "User created successfully", uid }); + return res + .status(201) + .json({ message: "User created successfully", userId }); } catch (error) { return res.status(500).json({ message: "Error creating user" }); } @@ -100,17 +123,24 @@ router.post("/", async (req: Request, res: Response) => { // PUT: ユーザー情報を更新 router.put("/:userId", async (req: Request, res: Response) => { const userId = req.params.userId; - const { name, streak }: Partial = req.body; + const { name, streak, fcmToken }: Partial = req.body; - if (!name && streak === undefined) { - return res - .status(400) - .json({ message: "At least one of name or streak is required" }); + if (!name && !streak && !fcmToken) { + return res.status(400).json({ + message: "At least one of name, streak, or fcmToken is required", + }); } const updateData: Partial = {}; - if (name) updateData.name = name; - if (streak !== undefined) updateData.streak = streak; + if (!name) { + updateData.name = name; + } + if (!streak) { + updateData.streak = streak; + } + if (fcmToken !== undefined) { + updateData.fcmToken = fcmToken; + } try { await db.collection("user").doc(userId).update(updateData); diff --git a/functions/src/tasks.ts b/functions/src/tasks.ts index 5246298..27ea7cb 100644 --- a/functions/src/tasks.ts +++ b/functions/src/tasks.ts @@ -149,8 +149,11 @@ const getUserFcmToken = async (userId: string) => { if (!userData) { throw new Error(`No user data found for userId:, ${userId}`); } - if (!userData.fcmToken) { + if (!userData.fcmToke) { throw new Error(`No FCM token found for userId:, ${userId}`); } + if (userData.fcmToken === "") { + throw new Error(`FCM token is not stored for userId:, ${userId}`); + } return userData.fcmToken; }; diff --git a/src/Components/GoalModal/GoalModal.tsx b/src/Components/GoalModal/GoalModal.tsx index 2f2eadf..b951fbb 100644 --- a/src/Components/GoalModal/GoalModal.tsx +++ b/src/Components/GoalModal/GoalModal.tsx @@ -25,7 +25,7 @@ export default function GoalModal() { event.preventDefault(); const postData: Goal = { - userId: user?.uid as string, + userId: user?.userId as string, text: text, deadline: new Date(dueDate), }; diff --git a/src/Components/NameUpdate/NameUpdate.tsx b/src/Components/NameUpdate/NameUpdate.tsx index a916584..e747acd 100644 --- a/src/Components/NameUpdate/NameUpdate.tsx +++ b/src/Components/NameUpdate/NameUpdate.tsx @@ -25,7 +25,7 @@ export default function NameUpdate({ const handleNameUpdate = async (event: React.FormEvent) => { event.preventDefault(); - const response = await fetch(`${functionsEndpoint}/user/${user?.uid}`, { + const response = await fetch(`${functionsEndpoint}/user/${user?.userId}`, { method: "PUT", headers: { "X-Firebase-AppCheck": appCheckToken, diff --git a/src/Components/PostModal/PostModal.tsx b/src/Components/PostModal/PostModal.tsx index 11fc9a8..dbc08fc 100644 --- a/src/Components/PostModal/PostModal.tsx +++ b/src/Components/PostModal/PostModal.tsx @@ -54,7 +54,7 @@ export default function PostModal({ goalId }: { goalId: string }) { (errorMsg) => setError(errorMsg), async (url) => { const postData: Post = { - userId: user?.uid as string, + userId: user?.userId as string, storedId: url, text: text, goalId: goalId, diff --git a/src/Components/Progress/Progress.tsx b/src/Components/Progress/Progress.tsx index a9f9b4b..54bf8a7 100644 --- a/src/Components/Progress/Progress.tsx +++ b/src/Components/Progress/Progress.tsx @@ -192,7 +192,7 @@ const pendingStep = (result: GoalWithId, userName: string, user: UserData) => { resultType="pending" /> {/* 自分の作成した目標の場合のみ投稿可能にする */} - {result.userId === user?.uid && } + {result.userId === user?.userId && } ); diff --git a/src/app/mycontent/page.tsx b/src/app/mycontent/page.tsx index e4d798f..1f4f6cb 100644 --- a/src/app/mycontent/page.tsx +++ b/src/app/mycontent/page.tsx @@ -40,9 +40,9 @@ export default function MyContent() { {value == "pending" ? ( - + ) : ( - + )} ); diff --git a/src/types/types.ts b/src/types/types.ts index f79bb22..da6204e 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -1,5 +1,5 @@ export interface UserData { - uid: string; + userId: string; name: string; streak: number; loginType: LoginType; diff --git a/src/utils/API/createUser.ts b/src/utils/API/createUser.ts index 66acbb5..a3d182d 100644 --- a/src/utils/API/createUser.ts +++ b/src/utils/API/createUser.ts @@ -2,19 +2,19 @@ import { appCheckToken, functionsEndpoint } from "@/app/firebase"; /** * Cloud FunctionsのAPIを呼び出して、ユーザー情報をFirestoreに登録する - * Authenticationのuidと/userのdocument IDは同じにする + * AuthenticationのuserIdと/userのdocument IDは同じにする * * @param {string} name - * @param {string} uid + * @param {string} userId */ -export const createUser = async (name: string, uid: string) => { +export const createUser = async (name: string, userId: string) => { const response = await fetch(`${functionsEndpoint}/user/`, { method: "POST", headers: { "X-Firebase-AppCheck": appCheckToken, "Content-Type": "application/json", }, - body: JSON.stringify({ uid, name }), + body: JSON.stringify({ userId, name }), }); if (!response.ok) { diff --git a/src/utils/API/fetchUser.ts b/src/utils/API/fetchUser.ts index ede47b7..2b55a24 100644 --- a/src/utils/API/fetchUser.ts +++ b/src/utils/API/fetchUser.ts @@ -4,11 +4,11 @@ import { UserData } from "@/types/types"; /** * Cloud FunctionsのAPIを呼び出して、ユーザー情報をFirestoreから取得する * - * @param {string} uid + * @param {string} userId * @return {*} {Promise} */ -export const fetchUserById = async (uid: string): Promise => { - const response = await fetch(`${functionsEndpoint}/user/id/${uid}`, { +export const fetchUserById = async (userId: string): Promise => { + const response = await fetch(`${functionsEndpoint}/user/id/${userId}`, { method: "GET", headers: { "X-Firebase-AppCheck": appCheckToken, diff --git a/src/utils/Auth/signUpWithGoogleAccount.ts b/src/utils/Auth/signUpWithGoogleAccount.ts index 707597c..c105073 100644 --- a/src/utils/Auth/signUpWithGoogleAccount.ts +++ b/src/utils/Auth/signUpWithGoogleAccount.ts @@ -16,7 +16,7 @@ export const signUpWithGoogleAccount = async () => { // uidとdocument IDを一致させる await createUser(result.user.displayName ?? "no name", result.user.uid); updateUser({ - uid: result.user.uid, + userId: result.user.uid, name: result.user.displayName ?? "no name", streak: 0, loginType: "Google", diff --git a/src/utils/Auth/signUpWithMail.ts b/src/utils/Auth/signUpWithMail.ts index b0b58f9..db83006 100644 --- a/src/utils/Auth/signUpWithMail.ts +++ b/src/utils/Auth/signUpWithMail.ts @@ -8,7 +8,7 @@ import { } from "firebase/auth"; /** - * Firebase Authenticationでユーザーを作成し、生成されたuidをドキュメントIDとしてFirestoreにユーザー情報を登録する + * Firebase Authenticationでユーザーを作成し、生成されたuserIdをドキュメントIDとしてFirestoreにユーザー情報を登録する * * @param {string} email * @param {string} password @@ -33,10 +33,10 @@ export const signUpWithMail = ( console.error("プロファイル更新に失敗しました:", profileUpdateError); } - // uidとdocument IDを一致させる + // userIdとdocument IDを一致させる await createUser(name, user.uid); updateUser({ - uid: user.uid, + userId: user.uid, name: name, streak: 0, loginType: "Mail", diff --git a/src/utils/UserContext.tsx b/src/utils/UserContext.tsx index 45e5ab4..ec77b19 100644 --- a/src/utils/UserContext.tsx +++ b/src/utils/UserContext.tsx @@ -75,7 +75,7 @@ export const UserProvider = ({ children }: Props) => { // ゲスト以外のログインの場合はユーザーデータを取得しuseContextで保持 if (loginType === "Guest") { const guestData: UserData = { - uid: firebaseUser.uid, + userId: firebaseUser.uid, name: "Guest", streak: 0, loginType: "Guest", @@ -89,7 +89,7 @@ export const UserProvider = ({ children }: Props) => { const userData = await fetchUserById(firebaseUser.uid); // ユーザーデータを作成する前にfetchしようとして"User not found"になるので、postした場所でsetさせている // "User not found"ではない(= 初回ログイン直後ではない)場合のみsetする - if (userData.uid) { + if (userData.userId) { setUser({ ...userData, loginType,