83 lines
2.1 KiB
TypeScript
83 lines
2.1 KiB
TypeScript
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<string, PostReaction[]>
|
|
|
|
export function usePostViewModel() {
|
|
const [posts, _setPosts] = useState<PostInfo[]>([])
|
|
const [reactions, setReactions] = useState<ReactionMap>({})
|
|
|
|
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 }
|
|
}
|