124 lines
4.5 KiB
JavaScript
124 lines
4.5 KiB
JavaScript
import { useCallback } from "react";
|
|
import {
|
|
createBlankLocationMap,
|
|
createLocationMapFromZones,
|
|
publishLocationMapDraft,
|
|
saveLocationMapDraft,
|
|
} from "../api/locationMaps";
|
|
import getApiErrorMessage from "../lib/getApiErrorMessage";
|
|
import { getObjectKey, prepareObjectsForSave } from "../lib/locationMapUtils";
|
|
|
|
export default function useLocationMapDraftActions({
|
|
activeHouseholdId,
|
|
beginSaving,
|
|
endSaving,
|
|
hasUnsavedChanges,
|
|
locationId,
|
|
mapDraft,
|
|
objects,
|
|
selectedObjectKey,
|
|
setEditorTool,
|
|
setMapState,
|
|
setMode,
|
|
setPreviewDraft,
|
|
syncMapDraftFromState,
|
|
toast,
|
|
}) {
|
|
const selectedObjectIndex = selectedObjectKey
|
|
? objects.findIndex((object) => getObjectKey(object) === selectedObjectKey)
|
|
: -1;
|
|
|
|
const applyDraftResponse = useCallback((response, nextMode = "edit", nextPreviewDraft = true, options = {}) => {
|
|
setMapState(response.data);
|
|
setMode(nextMode);
|
|
setPreviewDraft(nextPreviewDraft);
|
|
syncMapDraftFromState(response.data, nextMode, nextPreviewDraft, options);
|
|
}, [setMapState, setMode, setPreviewDraft, syncMapDraftFromState]);
|
|
|
|
const handleCreateBlank = useCallback(async () => {
|
|
if (!activeHouseholdId || !locationId) return;
|
|
beginSaving("create-blank");
|
|
try {
|
|
const response = await createBlankLocationMap(activeHouseholdId, locationId, mapDraft);
|
|
applyDraftResponse(response);
|
|
setEditorTool("edit");
|
|
toast.success("Created map", "Blank draft map created");
|
|
} catch (error) {
|
|
toast.error("Create map failed", getApiErrorMessage(error, "Failed to create map"));
|
|
} finally {
|
|
endSaving();
|
|
}
|
|
}, [activeHouseholdId, applyDraftResponse, beginSaving, endSaving, locationId, mapDraft, setEditorTool, toast]);
|
|
|
|
const handleCreateFromZones = useCallback(async () => {
|
|
if (!activeHouseholdId || !locationId) return;
|
|
beginSaving("create-zones");
|
|
try {
|
|
const response = await createLocationMapFromZones(activeHouseholdId, locationId, mapDraft);
|
|
applyDraftResponse(response);
|
|
setEditorTool("edit");
|
|
toast.success("Created starter map", "Zones were added as editable rectangles");
|
|
} catch (error) {
|
|
toast.error("Create map failed", getApiErrorMessage(error, "Failed to create map from zones"));
|
|
} finally {
|
|
endSaving();
|
|
}
|
|
}, [activeHouseholdId, applyDraftResponse, beginSaving, endSaving, locationId, mapDraft, setEditorTool, toast]);
|
|
|
|
const handleSaveDraft = useCallback(async () => {
|
|
if (!activeHouseholdId || !locationId) return;
|
|
beginSaving("save");
|
|
try {
|
|
const response = await saveLocationMapDraft(activeHouseholdId, locationId, {
|
|
map: mapDraft,
|
|
objects: prepareObjectsForSave(objects),
|
|
});
|
|
applyDraftResponse(response, "edit", true, { preserveSelectedIndex: selectedObjectIndex });
|
|
toast.success("Saved draft", "Map draft saved");
|
|
} catch (error) {
|
|
toast.error("Save draft failed", getApiErrorMessage(error, "Failed to save map draft"));
|
|
} finally {
|
|
endSaving();
|
|
}
|
|
}, [
|
|
activeHouseholdId, applyDraftResponse, beginSaving, endSaving, locationId,
|
|
mapDraft, objects, selectedObjectIndex, toast,
|
|
]);
|
|
|
|
const handlePublish = useCallback(async () => {
|
|
if (!activeHouseholdId || !locationId) return;
|
|
beginSaving("publish");
|
|
let savedPendingDraft = false;
|
|
try {
|
|
if (hasUnsavedChanges) {
|
|
const saveResponse = await saveLocationMapDraft(activeHouseholdId, locationId, {
|
|
map: mapDraft,
|
|
objects: prepareObjectsForSave(objects),
|
|
});
|
|
savedPendingDraft = true;
|
|
applyDraftResponse(saveResponse, "edit", true, { preserveSelectedIndex: selectedObjectIndex });
|
|
}
|
|
|
|
const response = await publishLocationMapDraft(activeHouseholdId, locationId);
|
|
applyDraftResponse(response, "view", false);
|
|
setEditorTool("pan");
|
|
toast.success(
|
|
"Published map",
|
|
hasUnsavedChanges
|
|
? "Latest edits were saved and published"
|
|
: "Map is now visible to household members"
|
|
);
|
|
} catch (error) {
|
|
const message = getApiErrorMessage(error, "Failed to publish map");
|
|
toast.error("Publish failed", savedPendingDraft ? `${message}. Draft changes were saved.` : message);
|
|
} finally {
|
|
endSaving();
|
|
}
|
|
}, [
|
|
activeHouseholdId, applyDraftResponse, beginSaving, endSaving, hasUnsavedChanges,
|
|
locationId, mapDraft, objects, selectedObjectIndex, setEditorTool, toast,
|
|
]);
|
|
|
|
return { handleCreateBlank, handleCreateFromZones, handlePublish, handleSaveDraft };
|
|
}
|