Make user able to create new posts

This commit is contained in:
Alex Erdei 2025-05-04 17:16:24 +01:00
parent d491871126
commit c6e937f79f
2 changed files with 84 additions and 39 deletions

View File

@ -552,19 +552,58 @@ export function subscribePosts() {
cancelled = true;
};
}
/* ------------------------------------------------------------------ */
/* CREATE A NEW POST uses in-memory auth + sends post_id */
/* ------------------------------------------------------------------ */
export async function upload(post) {
await delay();
/* fast path: in-memory → fall back to localStorage once */
const doc = { ...post, postID: genId(), timestamp: nowISO() };
const token = authToken || localStorage.getItem(LS_TOKEN);
DB.posts.unshift(doc);
const user_id = authUser || localStorage.getItem(LS_USER_ID);
if (me()) me().posts.unshift(doc.postID);
if (!token || !user_id) throw new Error("Not authenticated");
persist();
/* Magic table requires the primary key up front */
return { id: doc.postID };
const post_id = genId(); // already in backend.js
const body = {
post_id, // ← fixes NOT NULL error
user_id,
text: post.text ?? "",
photoURL: post.photoURL ?? "",
youtubeURL: post.youtubeURL ?? "",
isPhoto: post.isPhoto ? 1 : 0, // Magic expects 1/0
isYoutube: post.isYoutube ? 1 : 0,
likes: JSON.stringify(post.likes ?? []),
comments: JSON.stringify(post.comments ?? []),
timestamp: new Date().toISOString(), // optional but useful
};
/* POST /posts let SignalR broadcast the newly created row */
await $fetch(POSTS_URL, {
method: "POST",
body: JSON.stringify(body),
}); // $fetch adds Authorization
/* keep old contract: caller expects { id } */
return { id: post_id };
}
/* --------------------------------------------------------------

View File

@ -2,59 +2,65 @@ import { createSlice } from "@reduxjs/toolkit";
import mapRestPost from "../../utils/mapRestPost";
/* --------------------------------------------------------------
helper fixes the Magic placeholder only once, on INSERT
-------------------------------------------------------------- */
const withValidTimestamp = (post) =>
post.timestamp === "Invalid Date" || !post.timestamp
? { ...post, timestamp: new Date().toISOString() }
: post;
export const postsSlice = createSlice({
name: "posts",
name: "posts",
initialState: [],
initialState: [],
reducers: {
/* full reload (initial screen) --------------------------------- */
reducers: {
/* full reload: oldest → newest, so reverse once */
postsLoaded: (_state, action) =>
// API returns oldest → newest, so reverse once
postsLoaded: (_state, action) => action.payload.map(mapRestPost).reverse(),
action.payload.map(mapRestPost).reverse(),
/* incremental updates from Signal R */
/* incremental updates: insert new or patch existing ------------ */
postsUpdated: (state, action) => {
action.payload.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;
/* -------- INSERT NEW ------------------------------------------------ */
const idx = state.findIndex((p) => p.postID === postID);
if (idx === -1) {
state.unshift(withValidTimestamp(mapRestPost(raw))); // newest first
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) ------------------ */
if (raw.text !== undefined) cur.text = raw.text;
const cur = state[idx];
if (raw.photoURL !== undefined) cur.photoURL = raw.photoURL;
if (raw.text !== undefined) cur.text = raw.text;
if (raw.youtubeURL !== undefined) cur.youtubeURL = raw.youtubeURL;
if (raw.photoURL !== undefined) cur.photoURL = raw.photoURL;
if (raw.isPhoto !== undefined) cur.isPhoto = !!raw.isPhoto;
if (raw.youtubeURL !== undefined) cur.youtubeURL = raw.youtubeURL;
if (raw.isYoutube !== undefined) cur.isYoutube = !!raw.isYoutube;
if (raw.isPhoto !== undefined) cur.isPhoto = !!raw.isPhoto;
if (raw.comments !== undefined) cur.comments = JSON.parse(raw.comments);
if (raw.isYoutube !== undefined) cur.isYoutube = !!raw.isYoutube;
if (raw.likes !== undefined) cur.likes = JSON.parse(raw.likes);
if (raw.comments !== undefined) cur.comments = JSON.parse(raw.comments);
if (raw.likes !== undefined) cur.likes = JSON.parse(raw.likes);
/* raw.timestamp never changes, so we leave it untouched */
});
},
},
/* raw.timestamp never changes in an update → leave untouched */
});
},
},
});
export const { postsLoaded, postsUpdated } = postsSlice.actions;