diff --git a/src/app/store.js b/src/app/store.js index 0b41681..5101ecb 100644 --- a/src/app/store.js +++ b/src/app/store.js @@ -9,28 +9,16 @@ import linkReducer from "../features/link/linkSlice"; import accountPageReducer from "../features/accountPage/accountPageSlice"; const store = configureStore({ - reducer: { - user: userReducer, - currentUser: currentUserReducer, - users: usersReducer, - posts: postsReducer, - incomingMessages: incomingMessagesReducer, - outgoingMessages: outgoingMessagesReducer, - link: linkReducer, - accountPage: accountPageReducer, - }, + reducer: { + user: userReducer, + currentUser: currentUserReducer, + users: usersReducer, + posts: postsReducer, + incomingMessages: incomingMessagesReducer, + outgoingMessages: outgoingMessagesReducer, + link: linkReducer, + accountPage: accountPageReducer, + }, }); -if (import.meta.env.DEV) { - store.subscribe(() => { - const s = store.getState(); - - console.log("[DEBUG] users:", s.users); - - console.log("[DEBUG] currentUser:", s.currentUser); - - console.log("[DEBUG] posts:", s.posts); - }); -} - export default store; diff --git a/src/backend/backend.js b/src/backend/backend.js index 66ffc74..3df459f 100644 --- a/src/backend/backend.js +++ b/src/backend/backend.js @@ -329,13 +329,13 @@ function openSocket() { store.dispatch(usersUpdated([parseMsg(raw)])); }); - hub.on("fakebook.posts.post", (raw) => - store.dispatch(postsUpdated([JSON.parse(raw)])) - ); + hub.on("fakebook.posts.post", (raw) => { + store.dispatch(postsUpdated([JSON.parse(raw)])); + }); - hub.on("fakebook.posts.put", (raw) => - store.dispatch(postsUpdated([JSON.parse(raw)])) - ); + hub.on("fakebook.posts.put", (raw) => { + store.dispatch(postsUpdated([JSON.parse(raw)])); + }); }) .catch((err) => { @@ -470,31 +470,12 @@ async function patchOnline(isOnline) { await $fetch(USERS_URL, { method: "PUT", - mode: "cors", - - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}`, - }, - body: JSON.stringify({ user_id, isOnline: isOnline ? 1 : 0, // DB needs 1/0 }), }); - - /* -------- optimistic Redux update (merge, not overwrite) -------- */ - - const cur = store.getState().currentUser; - - store.dispatch(currentUserUpdated({ ...cur, isOnline })); // boolean - - const usersNew = store - .getState() - .users.map((u) => (u.userID === user_id ? { ...u, isOnline } : u)); - - store.dispatch(usersUpdated(usersNew)); } catch (err) { console.warn("[online/offline] PUT failed:", err.message); } @@ -578,13 +559,41 @@ export async function upload(post) { return { id: doc.postID }; } -export function updatePost(post, postID) { - const idx = DB.posts.findIndex((p) => p.postID === postID); +/* -------------------------------------------------------------- - if (idx !== -1) { - DB.posts[idx] = { ...DB.posts[idx], ...post }; - persist(); - } + Update a post (likes, comments, text, etc.) + + post → partial object in Redux/UI format + + postID → numeric/string id in the REST DB + + -------------------------------------------------------------- */ + +export async function updatePost(post, postID) { + const token = localStorage.getItem(LS_TOKEN); + + if (!token) throw new Error("Not authenticated"); + + /* 1. Map Redux-shape → Magic API shape ----------------------- */ + + const body = { post_id: postID }; // mandatory key + + if (post.comments !== undefined) + body.comments = JSON.stringify(post.comments); + + if (post.likes !== undefined) body.likes = JSON.stringify(post.likes); + + /* 2. Fire PUT /posts ---------------------------------------- */ + + await $fetch(POSTS_URL, { + method: "PUT", + + body: JSON.stringify(body), + }); + + /* 3. Refresh Redux state (merge) ---------------------------- */ + + //store.dispatch(postsUpdated([updatedRow])); } /* ------------------------- storage ----------------------------------- */ diff --git a/src/features/posts/postsSlice.js b/src/features/posts/postsSlice.js index c408219..01306c7 100644 --- a/src/features/posts/postsSlice.js +++ b/src/features/posts/postsSlice.js @@ -3,61 +3,58 @@ import { createSlice } from "@reduxjs/toolkit"; import mapRestPost from "../../utils/mapRestPost"; export const postsSlice = createSlice({ - name: "posts", + name: "posts", - initialState: [], // still an array + initialState: [], - reducers: { - /* full reload (initial screen) --------------------------------- */ + reducers: { + /* full reload (initial screen) --------------------------------- */ - postsLoaded: (_, action) => action.payload.map(mapRestPost), + postsLoaded: (_state, action) => + // API returns oldest → newest, so reverse once - /* incremental updates: insert new or patch existing ------------ */ + action.payload.map(mapRestPost).reverse(), - postsUpdated: (state, action) => { - const incoming = action.payload; // array of raw rows + /* incremental updates: insert new or patch existing ------------ */ - incoming.forEach((raw) => { - const postID = raw.post_id ?? raw.postID; + postsUpdated: (state, action) => { + const incoming = action.payload; // array of raw rows - const idx = state.findIndex((p) => p.postID === postID); + incoming.forEach((raw) => { + const postID = raw.post_id ?? raw.postID; - if (idx === -1) { - /* NEW */ + const idx = state.findIndex((p) => p.postID === postID); - state.push(mapRestPost(raw)); + if (idx === -1) { + /* NEW → put at the front so list stays newest-first */ - return; - } + state.unshift(mapRestPost(raw)); - /* MERGE PARTIAL UPDATE */ + return; + } - const cur = state[idx]; + /* MERGE PARTIAL UPDATE (order unchanged) ------------------ */ - const next = { ...cur }; + const cur = state[idx]; - if (raw.text !== undefined) next.text = raw.text; + if (raw.text !== undefined) cur.text = raw.text; - if (raw.photoURL !== undefined) next.photoURL = raw.photoURL; + if (raw.photoURL !== undefined) cur.photoURL = raw.photoURL; - if (raw.youtubeURL !== undefined) next.youtubeURL = raw.youtubeURL; + if (raw.youtubeURL !== undefined) cur.youtubeURL = raw.youtubeURL; - if (raw.isPhoto !== undefined) next.isPhoto = !!raw.isPhoto; + if (raw.isPhoto !== undefined) cur.isPhoto = !!raw.isPhoto; - if (raw.isYoutube !== undefined) next.isYoutube = !!raw.isYoutube; + if (raw.isYoutube !== undefined) cur.isYoutube = !!raw.isYoutube; - if (raw.comments !== undefined) - next.comments = JSON.parse(raw.comments); + if (raw.comments !== undefined) cur.comments = JSON.parse(raw.comments); - if (raw.likes !== undefined) next.likes = JSON.parse(raw.likes); + if (raw.likes !== undefined) cur.likes = JSON.parse(raw.likes); - if (raw.timestamp !== undefined) - next.timestamp = new Date(raw.timestamp); - - state[idx] = next; - }); - }, - }, + /* raw.timestamp never changes, so we leave it untouched */ + }); + }, + }, }); export const { postsLoaded, postsUpdated } = postsSlice.actions;