Files
SmartScanProbeTrack/templates/calibration_form.html
T

345 lines
15 KiB
HTML

{% extends "base.html" %}
{% block head %}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
{% endblock %}
{% block content %}
<div class="container mt-4">
<h2>New Calibration Batch</h2>
<form method="POST" action="{{ url_for('calibrations.create_calibrations') }}" onsubmit="return validateForm()">
<input type="hidden" name="calibrated_by" value="{{ user.id }}">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">Batch Information</h5>
<div class="row g-3">
<div class="col-md-6">
<label for="work_order_id" class="form-label">Work Order</label>
<select class="form-select select2" id="work_order_id" name="work_order_id" required>
<option value="">Select Work Order</option>
{% for wo in work_orders %}
<option value="{{ wo.id }}">{{ wo.order_number }} - {{ wo.customers.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-6">
<label for="std_used" class="form-label">Standard Used</label>
<select class="form-select select2" id="std_used" name="std_used" required>
<option value="">Select Standard</option>
{% for std in standards %}
<option value="{{ std.id }}">{{ std.make }} {{ std.model }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-6">
<label for="date" class="form-label">Calibration Date</label>
<input type="date" class="form-control" id="date" name="date" required>
</div>
<div class="col-md-3">
<label for="probe_model" class="form-label">Probe Model</label>
<select class="form-select select2" id="probe_model" name="probe_model" required>
<option value="">Select Model</option>
{% for model in probe_models %}
<option value="{{ model.id }}">{{ model.model_name }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-3">
<label for="parameter" class="form-label">Parameter</label>
<select class="form-select select2" id="parameter" name="parameter" required>
<option value="">Select Parameter</option>
{% for param in parameters %}
<option value="{{ param.id }}">{{ param.parameter_name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="text-end mt-3">
<button type="button" id="confirmBatch" class="btn btn-success">Confirm Batch Info</button>
</div>
</div>
</div>
<div class="card mb-4" id="channelsSection" style="display: none;">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="card-title mb-0">Channels</h5>
<button type="button" class="btn btn-sm btn-outline-primary" id="addChannel">
<i class="bi bi-plus"></i> Add Channel
</button>
</div>
<div id="channelRows">
<div class="channel-row mb-3">
<div class="row g-3">
<div class="col-md-3">
<label class="form-label">Channel</label>
<select class="form-select select2" name="channel_serial[]" required>
<option value="">Select Channel</option>
{% for channel in channels %}
<option value="{{ channel.serial_number }}">{{ channel.serial_number }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-1">
<label class="form-label">Scale</label>
<input type="number" step="0.001" class="form-control" name="scale[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Offset</label>
<input type="number" step="0.001" class="form-control" name="offset[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Dev Low</label>
<input type="number" step="0.001" class="form-control" name="deviation_low[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Dev Mid</label>
<input type="number" step="0.001" class="form-control" name="deviation_mid[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Dev High</label>
<input type="number" step="0.001" class="form-control" name="deviation_high[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Set Low</label>
<input type="number" step="0.001" class="form-control" name="set_low[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Set Mid</label>
<input type="number" step="0.001" class="form-control" name="set_mid[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Set High</label>
<input type="number" step="0.001" class="form-control" name="set_high[]" required>
</div>
<div class="col-md-1">
<div class="form-check form-switch mt-4">
<input class="form-check-input" type="checkbox" name="passed[]" checked>
<label class="form-check-label">Passed</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="text-end">
<button type="submit" class="btn btn-primary" id="saveBatch" disabled>Save Calibration Batch</button>
</div>
</form>
</div>
<script>
$(function() {
// Initialize Select2 and confirm button
$('.select2').select2();
console.log('Initializing calibration form...');
// Handle batch confirmation
$('#confirmBatch').on('click', function(e) {
e.preventDefault();
console.log('Confirm Batch clicked');
// Debug: Check if jQuery is working
console.log('jQuery version:', $.fn.jquery);
// Validate required fields
if (!$('#work_order_id').val() || !$('#std_used').val() ||
!$('#date').val() || !$('#probe_model').val() || !$('#parameter').val()) {
alert('Please complete all Batch Information fields');
return;
}
// Validate date is not in future
const selectedDate = new Date($('#date').val());
const today = new Date();
if (selectedDate > today) {
alert('Calibration date cannot be in the future');
return;
}
// Disable and gray out batch section
$('.card-body', $(this).closest('.card')).find('input, select').prop('disabled', true);
$(this).closest('.card').addClass('bg-light');
$('#confirmBatch').prop('disabled', true).removeClass('btn-success').addClass('btn-secondary');
// Show channels section with filtered options
$('#channelsSection').show();
updateChannelDropdowns($('#probe_model').val(), $('#parameter').val());
$('#saveBatch').prop('disabled', false);
// Remove the initial empty channel row if present
if ($('.channel-row').length === 1 && !$('select[name="channel_serial[]"]').val()) {
$('.channel-row').remove();
}
// Add first channel row with filtered options
addChannelRow();
});
// Function to update channel dropdowns
function updateChannelDropdowns(probeModelId, parameterId) {
if (!probeModelId || !parameterId) {
return;
}
$.get('/calibrations/filtered-channels', {
probe_model: probeModelId,
parameter: parameterId
}, function(data) {
window.filteredChannels = data; // Cache the filtered channels
updateAllChannelDropdowns(data);
});
}
function updateAllChannelDropdowns(channels) {
$('select[name="channel_serial[]"]').each(function() {
const $select = $(this);
const currentVal = $select.val();
$select.empty().append('<option value="">Select Channel</option>');
channels.forEach(function(channel) {
$select.append($('<option>', {
value: channel.serial_number,
text: channel.serial_number
}));
});
if (currentVal && channels.some(c => c.serial_number === currentVal)) {
$select.val(currentVal);
}
$select.trigger('change');
});
}
// Watch for changes in probe model and parameter
$('#probe_model, #parameter').on('change', function() {
const probeModelId = $('#probe_model').val();
const parameterId = $('#parameter').val();
updateChannelDropdowns(probeModelId, parameterId);
});
// Add channel row with current filter
function addChannelRow() {
const channelOptions = window.filteredChannels ?
window.filteredChannels.map(c =>
`<option value="${c.serial_number}">${c.serial_number}</option>`
).join('') :
'';
const newRow = `
<div class="channel-row mb-3">
<div class="row g-3">
<div class="col-md-3">
<label class="form-label">Channel</label>
<select class="form-select select2" name="channel_serial[]" required>
<option value="">Select Channel</option>
${channelOptions}
</select>
</div>
<div class="col-md-1">
<label class="form-label">Scale</label>
<input type="number" step="0.001" class="form-control" name="scale[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Offset</label>
<input type="number" step="0.001" class="form-control" name="offset[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Dev Low</label>
<input type="number" step="0.001" class="form-control" name="deviation_low[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Dev Mid</label>
<input type="number" step="0.001" class="form-control" name="deviation_mid[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Dev High</label>
<input type="number" step="0.001" class="form-control" name="deviation_high[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Set Low</label>
<input type="number" step="0.001" class="form-control" name="set_low[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Set Mid</label>
<input type="number" step="0.001" class="form-control" name="set_mid[]" required>
</div>
<div class="col-md-1">
<label class="form-label">Set High</label>
<input type="number" step="0.001" class="form-control" name="set_high[]" required>
</div>
<div class="col-md-1">
<div class="form-check form-switch mt-4">
<input class="form-check-input" type="checkbox" name="passed[]" checked>
<label class="form-check-label">Passed</label>
</div>
</div>
</div>
</div>`;
$('#channelRows').append(newRow);
$('.select2').select2();
}
$('#addChannel').click(addChannelRow);
// Initialize with any existing selections
if ($('#probe_model').val() && $('#parameter').val()) {
updateChannelDropdowns($('#probe_model').val(), $('#parameter').val());
}
// Form validation before submission
function validateForm() {
// Validate channel selections
const serialPattern = /^[0-9A-F]{16}$/;
const serials = $('select[name="channel_serial[]"]');
let valid = true;
serials.each(function() {
const serial = $(this).val();
if (!serial || !serialPattern.test(serial)) {
alert('Invalid channel serial number: ' + serial);
$(this).focus();
valid = false;
return false; // break loop
}
});
if (!valid) return false;
// Validate numeric fields
const numericFields = [
'scale[]', 'offset[]', 'deviation_low[]',
'deviation_mid[]', 'deviation_high[]',
'set_low[]', 'set_mid[]', 'set_high[]'
];
for (const field of numericFields) {
$(`input[name="${field}"]`).each(function() {
const val = parseFloat($(this).val());
if (isNaN(val)) {
alert('Please enter valid numbers for all fields');
$(this).focus();
valid = false;
return false;
}
});
if (!valid) break;
}
return valid;
}
});
</script>
{% endblock %}