2023-02-17 09:21:02 +00:00
|
|
|
import type { JSX } from 'solid-js'
|
2023-11-14 15:10:00 +00:00
|
|
|
|
2023-12-20 16:54:20 +00:00
|
|
|
import { createContext, onCleanup, useContext } from 'solid-js'
|
2023-11-14 15:10:00 +00:00
|
|
|
import { createStore, reconcile } from 'solid-js/store'
|
|
|
|
|
2023-12-19 09:34:24 +00:00
|
|
|
import { apiClient } from '../graphql/client/core'
|
2023-11-28 13:18:25 +00:00
|
|
|
import { Reaction, ReactionBy, ReactionInput, ReactionKind } from '../graphql/schema/core.gen'
|
2023-02-17 09:21:02 +00:00
|
|
|
|
|
|
|
type ReactionsContextType = {
|
|
|
|
reactionEntities: Record<number, Reaction>
|
|
|
|
actions: {
|
2023-11-30 08:07:31 +00:00
|
|
|
loadReactionsBy: ({
|
|
|
|
by,
|
|
|
|
limit,
|
|
|
|
offset,
|
|
|
|
}: {
|
|
|
|
by: ReactionBy
|
|
|
|
limit?: number
|
|
|
|
offset?: number
|
|
|
|
}) => Promise<Reaction[]>
|
2023-02-17 09:21:02 +00:00
|
|
|
createReaction: (reaction: ReactionInput) => Promise<void>
|
|
|
|
updateReaction: (id: number, reaction: ReactionInput) => Promise<void>
|
|
|
|
deleteReaction: (id: number) => Promise<void>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const ReactionsContext = createContext<ReactionsContextType>()
|
|
|
|
|
|
|
|
export function useReactions() {
|
|
|
|
return useContext(ReactionsContext)
|
|
|
|
}
|
|
|
|
|
|
|
|
export const ReactionsProvider = (props: { children: JSX.Element }) => {
|
|
|
|
const [reactionEntities, setReactionEntities] = createStore<Record<number, Reaction>>({})
|
|
|
|
|
|
|
|
const loadReactionsBy = async ({
|
|
|
|
by,
|
2023-11-14 15:10:00 +00:00
|
|
|
limit,
|
2023-11-30 08:07:31 +00:00
|
|
|
offset,
|
2023-02-17 09:21:02 +00:00
|
|
|
}: {
|
|
|
|
by: ReactionBy
|
|
|
|
limit?: number
|
2023-11-30 08:07:31 +00:00
|
|
|
offset?: number
|
2023-02-17 09:21:02 +00:00
|
|
|
}): Promise<Reaction[]> => {
|
2023-12-19 09:34:24 +00:00
|
|
|
const reactions = await apiClient.getReactionsBy({ by, limit, offset })
|
2024-01-23 16:32:57 +00:00
|
|
|
const newReactionEntities = reactions.reduce(
|
|
|
|
(acc: { [reaction_id: number]: Reaction }, reaction: Reaction) => {
|
|
|
|
acc[reaction.id] = reaction
|
|
|
|
return acc
|
|
|
|
},
|
|
|
|
{},
|
|
|
|
)
|
2023-02-17 09:21:02 +00:00
|
|
|
setReactionEntities(newReactionEntities)
|
|
|
|
return reactions
|
|
|
|
}
|
|
|
|
|
|
|
|
const createReaction = async (input: ReactionInput): Promise<void> => {
|
2023-12-19 09:34:24 +00:00
|
|
|
const reaction = await apiClient.createReaction(input)
|
2024-01-31 12:34:15 +00:00
|
|
|
if (!reaction) return
|
2023-02-28 17:13:14 +00:00
|
|
|
const changes = {
|
2023-11-14 15:10:00 +00:00
|
|
|
[reaction.id]: reaction,
|
2023-02-28 17:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ([ReactionKind.Like, ReactionKind.Dislike].includes(reaction.kind)) {
|
|
|
|
const oppositeReactionKind =
|
|
|
|
reaction.kind === ReactionKind.Like ? ReactionKind.Dislike : ReactionKind.Like
|
|
|
|
|
|
|
|
const oppositeReaction = Object.values(reactionEntities).find(
|
|
|
|
(r) =>
|
|
|
|
r.kind === oppositeReactionKind &&
|
2023-11-28 13:18:25 +00:00
|
|
|
r.created_by.slug === reaction.created_by.slug &&
|
2023-02-28 17:13:14 +00:00
|
|
|
r.shout.id === reaction.shout.id &&
|
2023-11-28 13:18:25 +00:00
|
|
|
r.reply_to === reaction.reply_to,
|
2023-02-28 17:13:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
if (oppositeReaction) {
|
|
|
|
changes[oppositeReaction.id] = undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setReactionEntities(changes)
|
2023-02-17 09:21:02 +00:00
|
|
|
}
|
|
|
|
|
2024-01-23 14:41:49 +00:00
|
|
|
const deleteReaction = async (reaction_id: number): Promise<void> => {
|
2024-01-25 18:19:59 +00:00
|
|
|
if (reaction_id) {
|
|
|
|
await apiClient.destroyReaction(reaction_id)
|
|
|
|
setReactionEntities({
|
|
|
|
[reaction_id]: undefined,
|
|
|
|
})
|
|
|
|
}
|
2023-02-17 09:21:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const updateReaction = async (id: number, input: ReactionInput): Promise<void> => {
|
2023-12-19 09:34:24 +00:00
|
|
|
const reaction = await apiClient.updateReaction(id, input)
|
2023-02-17 09:21:02 +00:00
|
|
|
setReactionEntities(reaction.id, reaction)
|
|
|
|
}
|
|
|
|
|
2023-03-02 18:48:39 +00:00
|
|
|
onCleanup(() => setReactionEntities(reconcile({})))
|
2023-02-17 09:21:02 +00:00
|
|
|
|
|
|
|
const actions = {
|
|
|
|
loadReactionsBy,
|
|
|
|
createReaction,
|
|
|
|
updateReaction,
|
2023-11-14 15:10:00 +00:00
|
|
|
deleteReaction,
|
2023-02-17 09:21:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const value: ReactionsContextType = { reactionEntities, actions }
|
|
|
|
|
|
|
|
return <ReactionsContext.Provider value={value}>{props.children}</ReactionsContext.Provider>
|
|
|
|
}
|