Enhanced add attendance manually UI
This commit is contained in:
@@ -5438,12 +5438,27 @@ def get_project_locations_api():
|
|||||||
active_status=True
|
active_status=True
|
||||||
).order_by(QRCode.location).all()
|
).order_by(QRCode.location).all()
|
||||||
|
|
||||||
|
# Group QR codes by location to get unique locations
|
||||||
|
locations_dict = {}
|
||||||
|
for qr in qr_codes:
|
||||||
|
location_key = f"{qr.location}||{qr.location_address}"
|
||||||
|
|
||||||
|
if location_key not in locations_dict:
|
||||||
|
locations_dict[location_key] = {
|
||||||
|
'location': qr.location,
|
||||||
|
'location_address': qr.location_address,
|
||||||
|
'qr_codes': {}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Store QR code ID for each event type
|
||||||
|
locations_dict[location_key]['qr_codes'][qr.location_event] = qr.id
|
||||||
|
|
||||||
|
# Convert to list format
|
||||||
location_list = [{
|
location_list = [{
|
||||||
'id': qr.id,
|
'location': loc_data['location'],
|
||||||
'location': qr.location,
|
'location_address': loc_data['location_address'],
|
||||||
'location_address': qr.location_address,
|
'qr_codes': loc_data['qr_codes']
|
||||||
'location_event': qr.location_event
|
} for loc_data in locations_dict.values()]
|
||||||
} for qr in qr_codes]
|
|
||||||
|
|
||||||
return jsonify({'success': True, 'locations': location_list})
|
return jsonify({'success': True, 'locations': location_list})
|
||||||
|
|
||||||
|
|||||||
@@ -249,13 +249,13 @@
|
|||||||
|
|
||||||
<!-- Location Selection -->
|
<!-- Location Selection -->
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="location_id">
|
<label for="location_select">
|
||||||
Location <span class="required">*</span>
|
Location <span class="required">*</span>
|
||||||
</label>
|
</label>
|
||||||
<select id="location_id" name="location_id" class="form-control" required disabled>
|
<select id="location_select" class="form-control" required disabled>
|
||||||
<option value="">-- Select Project First --</option>
|
<option value="">-- Select Project First --</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="help-text">Locations will be loaded based on the selected project</div>
|
<div class="help-text">Locations will be loaded based on the selected project (each location shown once)</div>
|
||||||
<div id="location_loading" class="loading-spinner">
|
<div id="location_loading" class="loading-spinner">
|
||||||
<i class="fas fa-spinner fa-spin"></i> Loading locations...
|
<i class="fas fa-spinner fa-spin"></i> Loading locations...
|
||||||
</div>
|
</div>
|
||||||
@@ -263,15 +263,18 @@
|
|||||||
|
|
||||||
<!-- Event Type Selection -->
|
<!-- Event Type Selection -->
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="event_type">
|
<label for="event_type_select">
|
||||||
Event Type <span class="required">*</span>
|
Event Type <span class="required">*</span>
|
||||||
</label>
|
</label>
|
||||||
<select id="event_type" name="event_type" class="form-control" required disabled>
|
<select id="event_type_select" class="form-control" required disabled>
|
||||||
<option value="">-- Select Location First --</option>
|
<option value="">-- Select Location First --</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="help-text">Select whether this is a check-in or check-out event</div>
|
<div class="help-text">Select whether this is a check-in or check-out event</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Hidden field for the actual QR code ID that will be submitted -->
|
||||||
|
<input type="hidden" id="location_id" name="location_id" required>
|
||||||
|
|
||||||
<!-- Date and Time -->
|
<!-- Date and Time -->
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="check_date">
|
<label for="check_date">
|
||||||
@@ -381,10 +384,14 @@ document.addEventListener('click', function(e) {
|
|||||||
|
|
||||||
// Project selection - load locations
|
// Project selection - load locations
|
||||||
const projectSelect = document.getElementById('project_id');
|
const projectSelect = document.getElementById('project_id');
|
||||||
const locationSelect = document.getElementById('location_id');
|
const locationSelect = document.getElementById('location_select');
|
||||||
const eventTypeSelect = document.getElementById('event_type');
|
const eventTypeSelect = document.getElementById('event_type_select');
|
||||||
|
const locationIdHidden = document.getElementById('location_id');
|
||||||
const locationLoading = document.getElementById('location_loading');
|
const locationLoading = document.getElementById('location_loading');
|
||||||
|
|
||||||
|
// Store location data for later use
|
||||||
|
let locationData = {};
|
||||||
|
|
||||||
projectSelect.addEventListener('change', function() {
|
projectSelect.addEventListener('change', function() {
|
||||||
const projectId = this.value;
|
const projectId = this.value;
|
||||||
|
|
||||||
@@ -393,6 +400,8 @@ projectSelect.addEventListener('change', function() {
|
|||||||
locationSelect.disabled = true;
|
locationSelect.disabled = true;
|
||||||
eventTypeSelect.innerHTML = '<option value="">-- Select Location First --</option>';
|
eventTypeSelect.innerHTML = '<option value="">-- Select Location First --</option>';
|
||||||
eventTypeSelect.disabled = true;
|
eventTypeSelect.disabled = true;
|
||||||
|
locationIdHidden.value = '';
|
||||||
|
locationData = {};
|
||||||
|
|
||||||
if (!projectId) {
|
if (!projectId) {
|
||||||
locationSelect.innerHTML = '<option value="">-- Select Project First --</option>';
|
locationSelect.innerHTML = '<option value="">-- Select Project First --</option>';
|
||||||
@@ -410,11 +419,13 @@ projectSelect.addEventListener('change', function() {
|
|||||||
if (data.success && data.locations.length > 0) {
|
if (data.success && data.locations.length > 0) {
|
||||||
locationSelect.disabled = false;
|
locationSelect.disabled = false;
|
||||||
|
|
||||||
data.locations.forEach(loc => {
|
data.locations.forEach((loc, index) => {
|
||||||
|
const locationKey = `loc_${index}`;
|
||||||
|
locationData[locationKey] = loc.qr_codes;
|
||||||
|
|
||||||
const option = document.createElement('option');
|
const option = document.createElement('option');
|
||||||
option.value = loc.id;
|
option.value = locationKey;
|
||||||
option.textContent = `${loc.location} - ${loc.location_address}`;
|
option.textContent = `${loc.location} - ${loc.location_address}`;
|
||||||
option.dataset.event = loc.location_event;
|
|
||||||
locationSelect.appendChild(option);
|
locationSelect.appendChild(option);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -428,25 +439,50 @@ projectSelect.addEventListener('change', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Location selection - set event type
|
// Location selection - populate event type options
|
||||||
locationSelect.addEventListener('change', function() {
|
locationSelect.addEventListener('change', function() {
|
||||||
const selectedOption = this.options[this.selectedIndex];
|
const locationKey = this.value;
|
||||||
const eventType = selectedOption.dataset.event;
|
|
||||||
|
|
||||||
eventTypeSelect.innerHTML = '';
|
eventTypeSelect.innerHTML = '';
|
||||||
eventTypeSelect.disabled = false;
|
eventTypeSelect.disabled = false;
|
||||||
|
locationIdHidden.value = '';
|
||||||
|
|
||||||
if (eventType) {
|
if (locationKey && locationData[locationKey]) {
|
||||||
const option = document.createElement('option');
|
const qrCodes = locationData[locationKey];
|
||||||
option.value = eventType;
|
|
||||||
option.textContent = eventType;
|
// Add available event types
|
||||||
option.selected = true;
|
if (qrCodes['Check In']) {
|
||||||
eventTypeSelect.appendChild(option);
|
const option = document.createElement('option');
|
||||||
|
option.value = qrCodes['Check In'];
|
||||||
|
option.textContent = 'Check In';
|
||||||
|
eventTypeSelect.appendChild(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qrCodes['Check Out']) {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = qrCodes['Check Out'];
|
||||||
|
option.textContent = 'Check Out';
|
||||||
|
eventTypeSelect.appendChild(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventTypeSelect.options.length === 0) {
|
||||||
|
eventTypeSelect.innerHTML = '<option value="">No event types available</option>';
|
||||||
|
eventTypeSelect.disabled = true;
|
||||||
|
} else {
|
||||||
|
// Set the hidden location_id to the first available option
|
||||||
|
locationIdHidden.value = eventTypeSelect.options[0].value;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
eventTypeSelect.innerHTML = '<option value="">Event type not available</option>';
|
eventTypeSelect.innerHTML = '<option value="">-- Select Location First --</option>';
|
||||||
|
eventTypeSelect.disabled = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Event type selection - update hidden location_id field
|
||||||
|
eventTypeSelect.addEventListener('change', function() {
|
||||||
|
locationIdHidden.value = this.value;
|
||||||
|
});
|
||||||
|
|
||||||
// Set default date to today
|
// Set default date to today
|
||||||
document.getElementById('check_date').valueAsDate = new Date();
|
document.getElementById('check_date').valueAsDate = new Date();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user