omnivore/packages/web/lib/hooks/useSetPageLabels.tsx

118 lines
2.7 KiB
TypeScript
Raw Permalink Normal View History

2024-02-16 04:25:45 +00:00
import { useCallback, useEffect, useReducer } from 'react'
2023-06-20 05:36:36 +00:00
import { Label } from '../networking/fragments/labelFragment'
import { showErrorToast } from '../toastHelpers'
2023-06-21 11:59:32 +00:00
import throttle from 'lodash/throttle'
import { useSetItemLabels } from '../networking/library_items/useLibraryItems'
2023-06-20 05:36:36 +00:00
export type LabelAction = 'RESET' | 'TEMP' | 'SAVE'
export type LabelsDispatcher = (action: {
type: LabelAction
labels: Label[]
}) => void
export const useSetPageLabels = (
libraryItemId?: string,
libraryItemSlug?: string
2023-06-20 05:36:36 +00:00
): [{ labels: Label[] }, LabelsDispatcher] => {
const setItemLabels = useSetItemLabels()
2024-07-30 08:48:24 +00:00
const saveLabels = (
labels: Label[],
libraryItemId: string,
libraryItemSlug: string
) => {
2023-06-21 11:59:32 +00:00
;(async () => {
2024-07-30 08:48:24 +00:00
if (libraryItemId) {
const result = await setItemLabels.mutateAsync({
2024-07-30 08:48:24 +00:00
itemId: libraryItemId,
slug: libraryItemSlug,
labels,
})
2023-06-21 11:59:32 +00:00
if (!result) {
showErrorToast('Error saving labels', {
position: 'bottom-right',
})
}
}
})()
}
2023-06-20 05:36:36 +00:00
const labelsReducer = (
state: {
labels: Label[]
articleId: string | undefined
2024-07-30 08:48:24 +00:00
slug: string | undefined
throttledSave: (labels: Label[], articleId: string, slug: string) => void
2023-06-20 05:36:36 +00:00
},
action: {
type: string
labels: Label[]
articleId?: string
2024-07-30 08:48:24 +00:00
slug?: string
2023-06-20 05:36:36 +00:00
}
) => {
switch (action.type) {
case 'RESET': {
return {
2023-06-21 11:59:32 +00:00
...state,
2023-06-20 05:36:36 +00:00
labels: action.labels,
}
}
case 'TEMP': {
return {
2023-06-21 11:59:32 +00:00
...state,
2023-06-20 05:36:36 +00:00
labels: action.labels,
}
}
case 'SAVE': {
2024-07-30 08:48:24 +00:00
if (state.articleId && state.slug) {
state.throttledSave(action.labels, state.articleId, state.slug)
2023-06-20 05:36:36 +00:00
} else {
showErrorToast('Unable to update labels', {
position: 'bottom-right',
})
}
return {
2023-06-21 11:59:32 +00:00
...state,
2023-06-20 05:36:36 +00:00
labels: action.labels,
}
}
case 'UPDATE_ARTICLE_ID': {
return {
...state,
2024-07-30 08:48:24 +00:00
slug: action.slug,
articleId: action.articleId,
}
}
2023-06-20 05:36:36 +00:00
default:
return state
}
}
2023-06-21 11:59:32 +00:00
const debouncedSave = useCallback(
throttle(
2024-07-30 08:48:24 +00:00
(labels: Label[], articleId: string, slug: string) =>
saveLabels(labels, articleId, slug),
2000
),
2023-06-21 11:59:32 +00:00
[]
)
useEffect(() => {
dispatchLabels({
type: 'UPDATE_ARTICLE_ID',
labels: [],
2024-07-30 08:48:24 +00:00
slug: libraryItemSlug,
articleId: libraryItemId,
})
}, [libraryItemId])
2023-06-20 05:36:36 +00:00
const [labels, dispatchLabels] = useReducer(labelsReducer, {
labels: [],
articleId: libraryItemId,
2024-07-30 08:48:24 +00:00
slug: libraryItemSlug,
2023-06-21 11:59:32 +00:00
throttledSave: debouncedSave,
2023-06-20 05:36:36 +00:00
})
return [labels, dispatchLabels]
}