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 }; }