Add deletedAt timestamps to delete operations for better audit tracking

- Updated delete methods across hooks and components to include `deletedAt: System.timeStampInSeconds()`.
- Refactored synchronized delete logic to pass `deletedAt` for both offline and online states.
- Improved synchronization workflows to include `deletedAt` in server and IPC requests.
- Enhanced destructuring patterns for cleaner and more consistent request data.
This commit is contained in:
natreex
2026-02-09 17:12:03 -05:00
parent 209dc6f85a
commit 49bb6e06f5
14 changed files with 146 additions and 92 deletions

View File

@@ -296,12 +296,20 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
});
if (response.seriesSpellId) {
const seriesSpellResponse: SeriesSpellDetailResponse = await System.authGetQueryToServer<SeriesSpellDetailResponse>(
'series/spell/detail',
userToken,
lang,
{spellid: response.seriesSpellId}
);
let seriesSpellResponse: SeriesSpellDetailResponse;
if (isCurrentlyOffline() || book?.localBook) {
seriesSpellResponse = await window.electron.invoke<SeriesSpellDetailResponse>(
'db:series:spell:detail',
{spellId: response.seriesSpellId}
);
} else {
seriesSpellResponse = await System.authGetQueryToServer<SeriesSpellDetailResponse>(
'series/spell/detail',
userToken,
lang,
{spellid: response.seriesSpellId}
);
}
if (seriesSpellResponse) {
setSelectedSeriesSpell(seriesSpellResponse);
}
@@ -536,9 +544,10 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
const deleteSpell = useCallback(async function (spellId: string): Promise<void> {
try {
let success: boolean;
const requestData = {spellId};
const deletedAt: number = System.timeStampInSeconds();
if (isSeriesMode) {
// Series mode - dual logic
const requestData = {spellId, deletedAt};
if (isCurrentlyOffline() || localSeries) {
success = await window.electron.invoke<boolean>('db:series:spell:delete', requestData);
} else {
@@ -548,6 +557,7 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
}
}
} else {
const requestData = {spellId, bookId: entityId, deletedAt};
if (isCurrentlyOffline() || book?.localBook) {
success = await window.electron.invoke<boolean>('db:spell:delete', requestData);
} else {
@@ -844,9 +854,10 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
const deleteTag = useCallback(async function (tagId: string): Promise<boolean> {
try {
let success: boolean;
const deletedAt: number = System.timeStampInSeconds();
if (isSeriesMode) {
// Series mode - dual logic
const deleteData = {tagId};
const deleteData = {tagId, deletedAt};
if (isCurrentlyOffline() || localSeries) {
success = await window.electron.invoke<boolean>('db:series:spell:tag:delete', deleteData);
} else {
@@ -856,7 +867,7 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
}
}
} else {
const requestData = {tagId, bookId: entityId};
const requestData = {tagId, bookId: entityId, deletedAt};
if (isCurrentlyOffline() || book?.localBook) {
success = await window.electron.invoke<boolean>('db:spell:tag:delete', requestData);
} else {
@@ -885,17 +896,25 @@ export function useSpells(config: UseSpellsConfig): UseSpellsReturn {
const handleSyncComplete = useCallback(async function (): Promise<void> {
if (selectedSpell?.seriesSpellId) {
const seriesSpellResponse: SeriesSpellDetailResponse = await System.authGetQueryToServer<SeriesSpellDetailResponse>(
'series/spell/detail',
userToken,
lang,
{spellid: selectedSpell.seriesSpellId}
);
let seriesSpellResponse: SeriesSpellDetailResponse;
if (isCurrentlyOffline() || (isSeriesMode ? localSeries : book?.localBook)) {
seriesSpellResponse = await window.electron.invoke<SeriesSpellDetailResponse>(
'db:series:spell:detail',
{spellId: selectedSpell.seriesSpellId}
);
} else {
seriesSpellResponse = await System.authGetQueryToServer<SeriesSpellDetailResponse>(
'series/spell/detail',
userToken,
lang,
{spellid: selectedSpell.seriesSpellId}
);
}
if (seriesSpellResponse) {
setSelectedSeriesSpell(seriesSpellResponse);
}
}
}, [selectedSpell?.seriesSpellId, userToken, lang]);
}, [selectedSpell?.seriesSpellId, userToken, lang, isCurrentlyOffline, isSeriesMode, localSeries, book?.localBook]);
const enterDetailMode = useCallback(async function (spell: SpellListItem): Promise<void> {
await selectSpell(spell);