port-nimara-client-portal/server/api/update-berth.ts

115 lines
4.0 KiB
TypeScript
Raw Normal View History

import { withBerthQueue } from '~/server/utils/operation-lock';
import { getNocoDbConfiguration } from '~/server/utils/nocodb';
import { requireAuth } from '~/server/utils/auth';
import {
BerthStatus,
BerthArea,
SidePontoon,
MooringType,
CleatType,
CleatCapacity,
BollardType,
BollardCapacity,
Access
} from '~/utils/types';
export default defineEventHandler(async (event) => {
console.log('[update-berth] Request received');
// Check authentication (x-tag header OR Keycloak session)
await requireAuth(event);
try {
const body = await readBody(event);
const { berthId, updates } = body;
console.log('[update-berth] Request body:', { berthId, updates });
if (!berthId || !updates) {
throw createError({
statusCode: 400,
statusMessage: "berthId and updates object are required"
});
}
// Validate enum fields
const validEnumFields: Record<string, string[]> = {
'Status': Object.values(BerthStatus),
'Area': Object.values(BerthArea),
'Side Pontoon': Object.values(SidePontoon),
'Mooring Type': Object.values(MooringType),
'Cleat Type': Object.values(CleatType),
'Cleat Capacity': Object.values(CleatCapacity),
'Bollard Type': Object.values(BollardType),
'Bollard Capacity': Object.values(BollardCapacity),
'Access': Object.values(Access)
};
// Validate enum values
for (const [field, value] of Object.entries(updates)) {
if (validEnumFields[field] && value !== null && value !== undefined) {
if (!validEnumFields[field].includes(value as string)) {
throw createError({
statusCode: 400,
statusMessage: `Invalid value for ${field}: ${value}. Must be one of: ${validEnumFields[field].join(', ')}`
});
}
}
}
// Handle measurement conversions
// If metric values are being updated, convert them to imperial for storage
const measurementFields = ['Nominal Boat Size', 'Water Depth', 'Length', 'Width', 'Depth'];
const processedUpdates = { ...updates };
for (const field of measurementFields) {
if (processedUpdates[field] !== undefined) {
const value = processedUpdates[field];
if (typeof value === 'string') {
// Parse user input and convert metric to imperial if needed
const cleanInput = value.replace(/[^\d.]/g, '');
const numericValue = parseFloat(cleanInput);
if (!isNaN(numericValue)) {
const isMetric = value.toLowerCase().includes('m') && !value.toLowerCase().includes('ft');
if (isMetric) {
// Convert metric to imperial for NocoDB storage
const imperial = numericValue / 0.3048;
processedUpdates[field] = parseFloat(imperial.toFixed(2));
console.log(`[update-berth] Converted ${field} from ${numericValue}m to ${processedUpdates[field]}ft`);
} else {
// Assume imperial, store as is
processedUpdates[field] = numericValue;
}
}
}
}
}
// Use queuing system to handle concurrent updates
return await withBerthQueue(berthId, async () => {
const config = getNocoDbConfiguration();
const berthsTableId = "mczgos9hr3oa9qc";
const url = `${config.url}/api/v2/tables/${berthsTableId}/records/${berthId}`;
console.log('[update-berth] URL:', url);
console.log('[update-berth] Processed updates:', processedUpdates);
const result = await $fetch(url, {
method: 'PATCH',
headers: {
"xc-token": config.token,
},
body: processedUpdates,
});
console.log('[update-berth] Successfully updated berth:', berthId);
return result;
});
} catch (error) {
console.error('[update-berth] Error occurred:', error);
console.error('[update-berth] Error details:', error instanceof Error ? error.message : 'Unknown error');
throw error;
}
});