import { useCallback, useState } from 'react' import { Post, PostComment, PostMedia, PostReaction } from './posts.ts' import { Temporal } from '@js-temporal/polyfill' import { produce } from 'immer' export interface PostInfo { postId: string authorName: string content: string createdAt: Temporal.Instant media: PostMedia[] possibleReactions: string[] comments: PostComment[] } type ReactionMap = Record export function usePostViewModel() { const [posts, _setPosts] = useState([]) const [reactions, setReactions] = useState({}) const setPosts = useCallback((posts: Post[]) => { _setPosts([...posts]) setReactions( posts.reduce((acc, post) => { acc[post.postId] = [...post.reactions] return acc }, {} as ReactionMap), ) }, []) const addPosts = useCallback((posts: Post[]) => { _setPosts((current) => { return [...current, ...posts] }) setReactions((current) => produce(current, (draft) => { for (const post of posts) { draft[post.postId] = [...post.reactions] } }), ) }, []) function addReaction( postId: string, emoji: string, authorName: string, reactedOn: Temporal.Instant, ) { setReactions((current) => produce(current, (draft) => { if (draft[postId]?.some((r) => r.emoji === emoji && r.authorName == authorName)) { return } const reaction: PostReaction = { emoji, authorName, reactedOn } if (!draft[postId]) { draft[postId] = [{ ...reaction }] } else { draft[postId].push({ ...reaction }) } }), ) } function removeReaction(postId: string, emoji: string, authorName: string) { setReactions((current) => produce(current, (draft) => { if (!draft[postId]) return draft[postId] = draft[postId].filter( (r) => r.emoji !== emoji || r.authorName !== authorName, ) }), ) } return { posts, reactions, addPosts, setPosts, addReaction, removeReaction } }