diff --git a/components/BerthDetailsModal.vue b/components/BerthDetailsModal.vue new file mode 100644 index 0000000..d060f23 --- /dev/null +++ b/components/BerthDetailsModal.vue @@ -0,0 +1,735 @@ + + + + + diff --git a/components/BerthStatusBadge.vue b/components/BerthStatusBadge.vue new file mode 100644 index 0000000..fb663a6 --- /dev/null +++ b/components/BerthStatusBadge.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/composables/useMeasurementConversion.ts b/composables/useMeasurementConversion.ts new file mode 100644 index 0000000..1c171e9 --- /dev/null +++ b/composables/useMeasurementConversion.ts @@ -0,0 +1,72 @@ +export const useMeasurementConversion = () => { + // Convert feet to meters (NocoDB uses this formula: imperial * 0.3048) + const feetToMeters = (feet: number): number => { + return feet * 0.3048; + }; + + // Convert meters to feet (reverse conversion for editing) + const metersToFeet = (meters: number): number => { + return meters / 0.3048; + }; + + // Format measurement for display (show both units) + const formatMeasurement = (imperial: number, unit: 'ft' | 'in' = 'ft') => { + const metric = feetToMeters(imperial); + return { + imperial: `${imperial}${unit}`, + metric: `${metric.toFixed(2)}m`, + display: `${metric.toFixed(2)}m / ${imperial}${unit}`, + imperialValue: imperial, + metricValue: parseFloat(metric.toFixed(2)) + }; + }; + + // Format just metric value with precision + const formatMetric = (meters: number): string => { + return `${meters.toFixed(2)}m`; + }; + + // Format just imperial value + const formatImperial = (feet: number, unit: 'ft' | 'in' = 'ft'): string => { + return `${feet}${unit}`; + }; + + // Parse user input and convert to imperial for database storage + const parseUserInput = (input: string): { imperial: number; metric: number } | null => { + // Remove any non-numeric characters except decimal points + const cleanInput = input.replace(/[^\d.]/g, ''); + const numericValue = parseFloat(cleanInput); + + if (isNaN(numericValue)) { + return null; + } + + // Determine if input is likely metric (contains 'm') or imperial (contains 'ft' or just a number) + const isMetric = input.toLowerCase().includes('m') && !input.toLowerCase().includes('ft'); + + if (isMetric) { + // Convert metric to imperial for storage + const imperial = metersToFeet(numericValue); + return { + imperial: parseFloat(imperial.toFixed(2)), + metric: numericValue + }; + } else { + // Assume imperial, convert to metric for display + const metric = feetToMeters(numericValue); + return { + imperial: numericValue, + metric: parseFloat(metric.toFixed(2)) + }; + } + }; + + return { + feetToMeters, + metersToFeet, + formatMeasurement, + formatMetric, + formatImperial, + parseUserInput + }; +}; diff --git a/pages/dashboard/berth-list.vue b/pages/dashboard/berth-list.vue new file mode 100644 index 0000000..df3fa68 --- /dev/null +++ b/pages/dashboard/berth-list.vue @@ -0,0 +1,566 @@ + + + + + diff --git a/pages/dashboard/interest-berth-status.vue b/pages/dashboard/interest-berth-status.vue index b35c47a..e55f082 100644 --- a/pages/dashboard/interest-berth-status.vue +++ b/pages/dashboard/interest-berth-status.vue @@ -1,30 +1,502 @@