91 lines
2.2 KiB
TypeScript
91 lines
2.2 KiB
TypeScript
import { ref } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { t } from '@/i18n'
|
|
import { useLocalizedToast } from '@/i18n/presentation'
|
|
import { ApiError } from '@/composables/useApi'
|
|
import { useEntries } from '@/composables/useEntries'
|
|
import type { EntryDraft } from '@/composables/useEntryDraft'
|
|
import { isGoneError } from '@/lib/entryServerError'
|
|
import { contentPath } from '@/lib/routePaths'
|
|
|
|
const UNAUTHORIZED = 401
|
|
const TOAST_ID = 'entry-deleted'
|
|
|
|
export type RemovalStage = 'closed' | 'confirm' | 'failed'
|
|
|
|
export function useEntryRemoval(editor: EntryDraft, typeName: () => string, title: () => string) {
|
|
const router = useRouter()
|
|
const toast = useLocalizedToast()
|
|
const { deleteEntry } = useEntries()
|
|
|
|
const stage = ref<RemovalStage>('closed')
|
|
const pending = ref(false)
|
|
const done = ref(false)
|
|
|
|
function open() {
|
|
if (!pending.value && !editor.saving.value && editor.entryId.value !== null) {
|
|
stage.value = 'confirm'
|
|
}
|
|
}
|
|
|
|
function close() {
|
|
if (!pending.value) {
|
|
stage.value = 'closed'
|
|
}
|
|
}
|
|
|
|
function announce(deletedTitle: string) {
|
|
toast.add(() => ({
|
|
id: TOAST_ID,
|
|
color: 'success',
|
|
icon: 'i-lucide-circle-check',
|
|
title: t('Entry deleted'),
|
|
description: t('"{0}" was deleted from {1}.', [deletedTitle, typeName()]),
|
|
}))
|
|
}
|
|
|
|
function refuse(error: unknown) {
|
|
if (error instanceof ApiError && error.status === UNAUTHORIZED) {
|
|
return
|
|
}
|
|
if (isGoneError(error)) {
|
|
stage.value = 'closed'
|
|
editor.load.markGone(error)
|
|
return
|
|
}
|
|
stage.value = 'failed'
|
|
}
|
|
|
|
async function confirm() {
|
|
const id = editor.entryId.value
|
|
if (pending.value || id === null) {
|
|
return
|
|
}
|
|
const deletedTitle = title()
|
|
pending.value = true
|
|
stage.value = 'confirm'
|
|
try {
|
|
await deleteEntry(editor.typeKey, id)
|
|
} catch (error) {
|
|
pending.value = false
|
|
refuse(error)
|
|
return
|
|
}
|
|
pending.value = false
|
|
done.value = true
|
|
stage.value = 'closed'
|
|
announce(deletedTitle)
|
|
const arrived = await router.replace(contentPath(editor.typeKey)).then(
|
|
(failure) => !failure,
|
|
() => false,
|
|
)
|
|
if (!arrived) {
|
|
done.value = false
|
|
}
|
|
}
|
|
|
|
return { stage, pending, done, open, close, confirm }
|
|
}
|
|
|
|
export type EntryRemoval = ReturnType<typeof useEntryRemoval>
|