"Update database schema for guest request functionality (feat)"

This commit is contained in:
Till Tomczak 2025-05-29 20:10:19 +02:00
parent a68bb4505a
commit e5a92fe710
2 changed files with 189 additions and 22 deletions

Binary file not shown.

View File

@ -239,6 +239,55 @@
outline: 2px solid #0073ce;
outline-offset: 2px;
}
/* Enhanced Submit Button Styles */
.btn-primary {
position: relative;
overflow: hidden;
transition: all 0.3s ease;
transform-origin: center;
}
.btn-primary:not(:disabled):hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 115, 206, 0.3);
}
.btn-primary:not(:disabled):active {
transform: translateY(0px);
box-shadow: 0 4px 15px rgba(0, 115, 206, 0.2);
}
.btn-primary:disabled {
cursor: not-allowed;
position: relative;
}
.btn-primary:disabled:hover {
transform: none;
box-shadow: none;
}
/* Tooltip Styles */
#submit-tooltip {
z-index: 1000;
backdrop-filter: blur(10px);
}
/* Progress Indicator Styles */
#progress-indicator {
z-index: 10;
}
#progress-bar {
background: linear-gradient(90deg, currentColor 0%, currentColor 100%);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* Enhanced Success Animation */
.success-checkmark {
animation: checkmark 0.6s ease-in-out;
}
</style>
{% endblock %}
@ -614,17 +663,40 @@
</svg>
Zurücksetzen
</button>
<button type="submit" id="submit-button"
class="btn-primary" disabled>
<svg class="w-5 h-5 mr-2" id="submit-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/>
</svg>
<svg class="w-5 h-5 mr-2 animate-spin hidden" id="submit-spinner" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span id="submit-text">Antrag einreichen</span>
</button>
<!-- Enhanced Submit Button mit verbessertem Feedback -->
<div class="relative group">
<button type="submit" id="submit-button"
class="btn-primary transition-all duration-300 relative overflow-hidden" disabled>
<svg class="w-5 h-5 mr-2" id="submit-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8"/>
</svg>
<svg class="w-5 h-5 mr-2 animate-spin hidden" id="submit-spinner" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span id="submit-text">Antrag einreichen</span>
<!-- Glanz-Effekt bei aktivem Button -->
<div class="absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-white/20 to-transparent skew-x-12 group-hover:translate-x-full transition-transform duration-1000 ease-out"></div>
</button>
<!-- Tooltip für deaktivierten Button -->
<div id="submit-tooltip" class="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 px-3 py-2 bg-slate-800 text-white text-sm rounded-lg shadow-lg opacity-0 pointer-events-none transition-opacity duration-200 whitespace-nowrap">
<div class="absolute top-full left-1/2 transform -translate-x-1/2 border-4 border-transparent border-t-slate-800"></div>
<span id="tooltip-text">Bitte füllen Sie alle Pflichtfelder aus</span>
</div>
<!-- Fortschrittsanzeige -->
<div id="progress-indicator" class="absolute -bottom-8 left-0 right-0">
<div class="text-xs text-center text-mercedes-gray mb-1">
<span id="progress-text">0 von 6 Feldern ausgefüllt</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-1">
<div id="progress-bar" class="bg-mercedes-blue h-1 rounded-full transition-all duration-300" style="width: 0%"></div>
</div>
</div>
</div>
</div>
</div>
</form>
@ -687,6 +759,8 @@ document.addEventListener('DOMContentLoaded', function() {
setupAccessibility();
setupFormEnhancements();
setupProgressTracking();
setupTooltipBehavior(); // Enhanced Submit Button Tooltips
updateFormValidation(); // Initial state
}
// Enhanced File Upload with Drag & Drop
@ -989,29 +1063,96 @@ document.addEventListener('DOMContentLoaded', function() {
function updateFormValidation() {
const submitButton = document.getElementById('submit-button');
const allValid = Object.values(validationState).every(state => state === true);
const submitTooltip = document.getElementById('submit-tooltip');
const tooltipText = document.getElementById('tooltip-text');
const progressText = document.getElementById('progress-text');
const progressBar = document.getElementById('progress-bar');
const completedFields = Object.values(validationState).filter(state => state === true).length;
const totalFields = Object.keys(validationState).length;
const allValid = completedFields === totalFields;
const progress = (completedFields / totalFields) * 100;
// Update submit button state
submitButton.disabled = !allValid;
if (allValid) {
submitButton.classList.remove('opacity-50', 'cursor-not-allowed');
submitButton.classList.add('hover:scale-105', 'active:scale-95');
if (tooltipText) tooltipText.textContent = '✅ Bereit zum Einreichen!';
} else {
submitButton.classList.add('opacity-50', 'cursor-not-allowed');
submitButton.classList.remove('hover:scale-105', 'active:scale-95');
// Update tooltip with missing fields
const missingFields = [];
if (!validationState.name) missingFields.push('Name');
if (!validationState.email) missingFields.push('E-Mail');
if (!validationState.printer_id) missingFields.push('Drucker');
if (!validationState.duration_min) missingFields.push('Dauer');
if (!validationState.reason) missingFields.push('Begründung');
if (!validationState.file) missingFields.push('Datei');
if (tooltipText) {
tooltipText.textContent = `Fehlend: ${missingFields.join(', ')}`;
}
}
// Update progress indicator
if (progressText) {
progressText.textContent = `${completedFields} von ${totalFields} Feldern ausgefüllt`;
}
if (progressBar) {
progressBar.style.width = `${progress}%`;
// Change color based on progress
if (progress === 100) {
progressBar.className = 'bg-mercedes-green h-1 rounded-full transition-all duration-300';
} else if (progress >= 50) {
progressBar.className = 'bg-mercedes-blue h-1 rounded-full transition-all duration-300';
} else {
progressBar.className = 'bg-yellow-500 h-1 rounded-full transition-all duration-300';
}
}
// Enhanced tooltip behavior
setupTooltipBehavior();
// Update overall progress indicator if exists
updateProgressIndicator();
}
function updateProgressIndicator() {
const completedFields = Object.values(validationState).filter(state => state === true).length;
const totalFields = Object.keys(validationState).length;
const progress = (completedFields / totalFields) * 100;
function setupTooltipBehavior() {
const submitButton = document.getElementById('submit-button');
const submitTooltip = document.getElementById('submit-tooltip');
const progressBar = document.querySelector('.progress-step.active + .flex-1 .bg-mercedes-blue');
if (progressBar) {
progressBar.style.width = `${Math.min(progress, 100)}%`;
}
if (!submitButton || !submitTooltip) return;
// Show tooltip on hover for disabled button
submitButton.addEventListener('mouseenter', () => {
if (submitButton.disabled) {
submitTooltip.classList.remove('opacity-0');
submitTooltip.classList.add('opacity-100');
}
});
submitButton.addEventListener('mouseleave', () => {
submitTooltip.classList.remove('opacity-100');
submitTooltip.classList.add('opacity-0');
});
// Also show tooltip on focus (accessibility)
submitButton.addEventListener('focus', () => {
if (submitButton.disabled) {
submitTooltip.classList.remove('opacity-0');
submitTooltip.classList.add('opacity-100');
}
});
submitButton.addEventListener('blur', () => {
submitTooltip.classList.remove('opacity-100');
submitTooltip.classList.add('opacity-0');
});
}
// Form Submission
@ -1411,5 +1552,31 @@ document.addEventListener('DOMContentLoaded', function() {
document.querySelector('.fixed.inset-0').remove();
window.location.href = `/guest/requests?email=${encodeURIComponent(email)}`;
};
function updateProgressIndicator() {
// Legacy progress indicator support (if exists)
const completedFields = Object.values(validationState).filter(state => state === true).length;
const totalFields = Object.keys(validationState).length;
const progress = (completedFields / totalFields) * 100;
const legacyProgressBar = document.querySelector('.progress-step.active + .flex-1 .bg-mercedes-blue');
if (legacyProgressBar) {
legacyProgressBar.style.width = `${Math.min(progress, 100)}%`;
}
// Update step indicators if they exist
const progressSteps = document.querySelectorAll('.progress-step');
progressSteps.forEach((step, index) => {
if (index < completedFields) {
step.classList.add('completed');
step.classList.remove('active');
} else if (index === completedFields) {
step.classList.add('active');
step.classList.remove('completed');
} else {
step.classList.remove('active', 'completed');
}
});
}
</script>
{% endblock %}