132 lines
3.3 KiB
JavaScript
132 lines
3.3 KiB
JavaScript
const locationMapModel = require("../models/location-map.model");
|
|
const { sendError } = require("../utils/http");
|
|
const { logError } = require("../utils/logger");
|
|
|
|
function parsePositiveInteger(value) {
|
|
const parsed = Number.parseInt(String(value), 10);
|
|
return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
|
|
}
|
|
|
|
function canManageMaps(req) {
|
|
return ["owner", "admin"].includes(req.household?.role);
|
|
}
|
|
|
|
function getScope(req) {
|
|
return {
|
|
householdId: parsePositiveInteger(req.params.householdId),
|
|
locationId: parsePositiveInteger(req.params.locationId),
|
|
};
|
|
}
|
|
|
|
function validateScope(res, scope) {
|
|
if (!scope.householdId || !scope.locationId) {
|
|
sendError(res, 400, "Household ID and location ID must be positive integers");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function sendMapState(res, state, req) {
|
|
if (!state) {
|
|
return sendError(res, 404, "Store location not found");
|
|
}
|
|
|
|
return res.json({
|
|
...state,
|
|
can_manage: canManageMaps(req),
|
|
});
|
|
}
|
|
|
|
exports.getLocationMap = async (req, res) => {
|
|
const scope = getScope(req);
|
|
if (!validateScope(res, scope)) return;
|
|
|
|
try {
|
|
const state = await locationMapModel.getMapState(
|
|
scope.householdId,
|
|
scope.locationId,
|
|
canManageMaps(req)
|
|
);
|
|
sendMapState(res, state, req);
|
|
} catch (error) {
|
|
logError(req, "locationMaps.getLocationMap", error);
|
|
sendError(res, 500, "Failed to load location map");
|
|
}
|
|
};
|
|
|
|
exports.createBlankMap = async (req, res) => {
|
|
const scope = getScope(req);
|
|
if (!validateScope(res, scope)) return;
|
|
|
|
try {
|
|
const state = await locationMapModel.saveBlankDraft(
|
|
scope.householdId,
|
|
scope.locationId,
|
|
req.user.id,
|
|
req.body?.map || req.body || {}
|
|
);
|
|
res.status(201);
|
|
sendMapState(res, state, req);
|
|
} catch (error) {
|
|
logError(req, "locationMaps.createBlankMap", error);
|
|
sendError(res, 500, "Failed to create blank map");
|
|
}
|
|
};
|
|
|
|
exports.createMapFromZones = async (req, res) => {
|
|
const scope = getScope(req);
|
|
if (!validateScope(res, scope)) return;
|
|
|
|
try {
|
|
const state = await locationMapModel.createDraftFromZones(
|
|
scope.householdId,
|
|
scope.locationId,
|
|
req.user.id,
|
|
req.body?.map || req.body || {}
|
|
);
|
|
res.status(201);
|
|
sendMapState(res, state, req);
|
|
} catch (error) {
|
|
logError(req, "locationMaps.createMapFromZones", error);
|
|
sendError(res, 500, "Failed to create map from zones");
|
|
}
|
|
};
|
|
|
|
exports.saveDraft = async (req, res) => {
|
|
const scope = getScope(req);
|
|
if (!validateScope(res, scope)) return;
|
|
|
|
try {
|
|
const state = await locationMapModel.saveDraft(
|
|
scope.householdId,
|
|
scope.locationId,
|
|
req.user.id,
|
|
req.body || {}
|
|
);
|
|
sendMapState(res, state, req);
|
|
} catch (error) {
|
|
logError(req, "locationMaps.saveDraft", error);
|
|
sendError(res, 500, "Failed to save map draft");
|
|
}
|
|
};
|
|
|
|
exports.publishDraft = async (req, res) => {
|
|
const scope = getScope(req);
|
|
if (!validateScope(res, scope)) return;
|
|
|
|
try {
|
|
const state = await locationMapModel.publishDraft(
|
|
scope.householdId,
|
|
scope.locationId,
|
|
req.user.id
|
|
);
|
|
if (!state) {
|
|
return sendError(res, 404, "No draft map to publish");
|
|
}
|
|
sendMapState(res, state, req);
|
|
} catch (error) {
|
|
logError(req, "locationMaps.publishDraft", error);
|
|
sendError(res, 500, "Failed to publish map");
|
|
}
|
|
};
|