Backend: create-collection happy path (write-through + editable) and the create resync-failure 422 (honest reconcile detail), mirroring the rename/remove tests. Frontend: extract notifyCollectionEditError (the 409->nameTaken vs generic-fallback mapping that was inline in the New-collection create()) and unit-test it; wire create() through it.
34 lines
1.5 KiB
TypeScript
34 lines
1.5 KiB
TypeScript
import { HttpError } from "./api";
|
|
import { notify } from "./notifications";
|
|
|
|
/**
|
|
* Surface a failed write action as an error toast instead of the click silently doing nothing.
|
|
* Prefers the server's own reason (`HttpError.detail` — e.g. "Not enough quota left today", a
|
|
* 404/429 message) over the caller's already-translated generic fallback. Domain-agnostic: used by
|
|
* the Plex watched-toggles and the saved-view ops, and delegated to by `notifyYouTubeActionError`
|
|
* for its non-403 case.
|
|
*/
|
|
export function notifyActionError(err: unknown, fallbackMessage: string): void {
|
|
const detail = err instanceof HttpError ? err.detail : null;
|
|
notify({ level: "error", message: detail || fallbackMessage });
|
|
}
|
|
|
|
/**
|
|
* Collection write errors. The backend enforces per-library name uniqueness and returns 409 on a
|
|
* duplicate; localize that specific case to the friendly `nameTaken` copy (notifyActionError would
|
|
* otherwise surface the server's raw English detail). Everything else falls back to the generic
|
|
* edit-failed handling (which still prefers the server's reason when present). Both args are already
|
|
* translated so this stays i18n-agnostic and unit-testable.
|
|
*/
|
|
export function notifyCollectionEditError(
|
|
err: unknown,
|
|
editFailedMessage: string,
|
|
nameTakenMessage: string,
|
|
): void {
|
|
if (err instanceof HttpError && err.status === 409) {
|
|
notify({ level: "error", message: nameTakenMessage });
|
|
return;
|
|
}
|
|
notifyActionError(err, editFailedMessage);
|
|
}
|