Files
gridfinity-calc/src/main.ts

122 lines
4.9 KiB
TypeScript

import { calculateGridfinity, GridfinitySpec, convertUnits } from './calculator';
// DOM Elements
const inputWidth = document.getElementById('input-width') as HTMLInputElement;
const inputLength = document.getElementById('input-length') as HTMLInputElement;
const inputHeight = document.getElementById('input-height') as HTMLInputElement;
const unitMmBtn = document.getElementById('unit-mm') as HTMLButtonElement;
const unitInBtn = document.getElementById('unit-in') as HTMLButtonElement;
const specGridSize = document.getElementById('spec-grid-size') as HTMLInputElement;
const specHeightUnit = document.getElementById('spec-height-unit') as HTMLInputElement;
const specBaseThickness = document.getElementById('spec-base-thickness') as HTMLInputElement;
const resultsSection = document.getElementById('results') as HTMLElement;
const resultGridCount = document.getElementById('result-grid-count') as HTMLElement;
const resultGridFractional = document.getElementById('result-grid-fractional') as HTMLElement;
const resultBinHeight = document.getElementById('result-bin-height') as HTMLElement;
const gapWidth = document.getElementById('gap-width') as HTMLElement;
const gapLength = document.getElementById('gap-length') as HTMLElement;
const gapHeight = document.getElementById('gap-height') as HTMLElement;
// State
let currentUnit: 'mm' | 'in' = 'in';
function updateResults() {
const width = parseFloat(inputWidth.value) || 0;
const length = parseFloat(inputLength.value) || 0;
const height = parseFloat(inputHeight.value) || 0;
const spec: GridfinitySpec = {
gridSize: parseFloat(specGridSize.value) || 42,
heightUnit: parseFloat(specHeightUnit.value) || 7,
baseThickness: parseFloat(specBaseThickness.value) || 4.8,
};
if (width > 0 && length > 0 && height > 0) {
const results = calculateGridfinity({
width,
length,
height,
unit: currentUnit,
spec,
});
resultsSection.classList.remove('hidden');
resultGridCount.textContent = `${results.fullGridsX} x ${results.fullGridsY}`;
resultGridFractional.textContent = `${results.widthGrids.toFixed(2)} x ${results.lengthGrids.toFixed(2)} grids`;
resultBinHeight.textContent = `${results.maxBinUnits}U`;
const unitLabel = currentUnit === 'in' ? 'in' : 'mm';
const displayGapWidth = currentUnit === 'in' ? results.remainingWidth / 25.4 : results.remainingWidth;
const displayGapLength = currentUnit === 'in' ? results.remainingLength / 25.4 : results.remainingLength;
const displayGapHeight = currentUnit === 'in' ? results.remainingHeight / 25.4 : results.remainingHeight;
gapWidth.textContent = `${displayGapWidth.toFixed(1)} ${unitLabel}`;
gapLength.textContent = `${displayGapLength.toFixed(1)} ${unitLabel}`;
gapHeight.textContent = `${displayGapHeight.toFixed(1)} ${unitLabel}`;
} else {
resultsSection.classList.add('hidden');
}
}
// Event Listeners
[inputWidth, inputLength, inputHeight, specGridSize, specHeightUnit, specBaseThickness].forEach(el => {
el.addEventListener('input', updateResults);
});
function setUnitStyles(unit: 'mm' | 'in') {
if (unit === 'in') {
unitInBtn.classList.add('bg-blue-600', 'text-white', 'shadow-sm');
unitInBtn.classList.remove('text-slate-600', 'hover:text-slate-900');
unitMmBtn.classList.remove('bg-blue-600', 'text-white', 'shadow-sm');
unitMmBtn.classList.add('text-slate-600', 'hover:text-slate-900');
} else {
unitMmBtn.classList.add('bg-blue-600', 'text-white', 'shadow-sm');
unitMmBtn.classList.remove('text-slate-600', 'hover:text-slate-900');
unitInBtn.classList.remove('bg-blue-600', 'text-white', 'shadow-sm');
unitInBtn.classList.add('text-slate-600', 'hover:text-slate-900');
}
}
unitMmBtn.addEventListener('click', () => {
if (currentUnit === 'mm') return;
// Convert values
const width = parseFloat(inputWidth.value) || 0;
const length = parseFloat(inputLength.value) || 0;
const height = parseFloat(inputHeight.value) || 0;
if (width > 0) inputWidth.value = convertUnits(width, 'in', 'mm').toFixed(1);
if (length > 0) inputLength.value = convertUnits(length, 'in', 'mm').toFixed(1);
if (height > 0) inputHeight.value = convertUnits(height, 'in', 'mm').toFixed(1);
currentUnit = 'mm';
setUnitStyles('mm');
updateResults();
});
unitInBtn.addEventListener('click', () => {
if (currentUnit === 'in') return;
// Convert values
const width = parseFloat(inputWidth.value) || 0;
const length = parseFloat(inputLength.value) || 0;
const height = parseFloat(inputHeight.value) || 0;
if (width > 0) inputWidth.value = convertUnits(width, 'mm', 'in').toFixed(2);
if (length > 0) inputLength.value = convertUnits(length, 'mm', 'in').toFixed(2);
if (height > 0) inputHeight.value = convertUnits(height, 'mm', 'in').toFixed(2);
currentUnit = 'in';
setUnitStyles('in');
updateResults();
});
// Initial call
updateResults();
setUnitStyles(currentUnit);