Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>Flavor Profile Prediction</title> | |
| <!-- Bootstrap CSS --> | |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.4.1/dist/css/bootstrap.min.css" rel="stylesheet" /> | |
| <!-- Tailwind CSS CDN --> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <!-- Font Awesome for Icons --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" /> | |
| <!-- Animate.css for Animations --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" /> | |
| <style> | |
| body { | |
| background: linear-gradient(135deg, #fff8f0, #ffe8cc, #ffddb5, #ffdab9); | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| overflow-x: hidden; | |
| position: relative; | |
| } | |
| /* Center main content */ | |
| main { | |
| min-height: 100vh; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 2rem; | |
| position: relative; | |
| z-index: 1; | |
| } | |
| /* Card styling */ | |
| .main-card { | |
| animation: fadeInUp 0.8s ease-out; | |
| width: 100%; | |
| max-width: 600px; | |
| background: linear-gradient(135deg, #fff9f1, #fff5e6); | |
| border-radius: 1rem; | |
| box-shadow: 0 10px 30px rgba(230, 126, 34, 0.15); | |
| padding: 3rem; | |
| } | |
| @keyframes fadeInUp { | |
| from { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| /* Form group styling */ | |
| .form-group { | |
| margin-bottom: 1.5rem; | |
| position: relative; | |
| } | |
| /* Label styling */ | |
| .form-label { | |
| font-weight: 600 ; | |
| font-size: 1rem ; | |
| color: #8b4513 ; | |
| margin-bottom: 0.5rem ; | |
| display: block; | |
| } | |
| .label-icon { | |
| font-size: 1.1rem; | |
| margin-right: 0.5rem; | |
| color: #e67e22; | |
| width: 16px; | |
| text-align: center; | |
| } | |
| /* Input styling */ | |
| .form-control, .form-select { | |
| border: 2px solid #f39c12 ; | |
| border-radius: 0.75rem ; | |
| padding: 0.75rem 1rem ; | |
| font-size: 1rem ; | |
| transition: all 0.3s ease ; | |
| background-color: #fffbf7 ; | |
| min-height: 48px; | |
| } | |
| .form-control:focus, .form-select:focus { | |
| outline: none ; | |
| box-shadow: 0 0 8px rgba(230, 126, 34, 0.4), 0 0 0 0.25rem rgba(230, 126, 34, 0.2) ; | |
| border-color: #e67e22 ; | |
| transform: scale(1.01); | |
| background-color: #ffffff ; | |
| } | |
| /* Textarea specific */ | |
| textarea.form-control { | |
| resize: vertical; | |
| min-height: 100px ; | |
| padding-top: 0.75rem ; | |
| } | |
| /* Placeholder styling */ | |
| ::placeholder { | |
| color: #d35400; | |
| opacity: 0.7; | |
| font-style: italic; | |
| } | |
| /* Button styling */ | |
| .btn-predict { | |
| background: linear-gradient(45deg, #f39c12, #e67e22) ; | |
| border: none ; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| border-radius: 0.75rem ; | |
| font-weight: 700 ; | |
| font-size: 1.2rem ; | |
| padding: 1rem 2rem ; | |
| box-shadow: 0 4px 12px rgba(231, 111, 32, 0.3); | |
| color: white ; | |
| width: 100%; | |
| margin-top: 1rem; | |
| } | |
| .btn-predict::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: -100%; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent); | |
| transition: left 0.5s; | |
| border-radius: 0.75rem; | |
| } | |
| .btn-predict:hover::before { | |
| left: 100%; | |
| } | |
| .btn-predict:hover { | |
| background: linear-gradient(45deg, #e67e22, #d68910) ; | |
| box-shadow: 0 8px 25px rgba(231, 111, 32, 0.5); | |
| transform: translateY(-2px); | |
| color: white ; | |
| } | |
| /* Time inputs row */ | |
| .time-row { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 1rem; | |
| } | |
| /* Card hover */ | |
| .main-card:hover { | |
| box-shadow: 0 20px 40px rgba(230, 126, 34, 0.25) ; | |
| transform: translateY(-2px); | |
| transition: all 0.3s ease; | |
| } | |
| /* Prediction result styling */ | |
| .prediction-result { | |
| animation: slideInUp 0.6s ease-out; | |
| border: none; | |
| background: linear-gradient(135deg, #e8f5e8, #d4edda); | |
| box-shadow: 0 4px 15px rgba(40, 167, 69, 0.2); | |
| border-radius: 0.75rem; | |
| padding: 1.5rem; | |
| margin-top: 1.5rem; | |
| color: #155724; | |
| font-weight: 600; | |
| font-size: 1.1rem; | |
| text-align: center; | |
| border-left: 4px solid #28a745; | |
| } | |
| @keyframes slideInUp { | |
| from { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| /* Form validation styles */ | |
| .form-control.is-invalid, .form-select.is-invalid { | |
| border-color: #dc3545 ; | |
| box-shadow: 0 0 8px rgba(220, 53, 69, 0.4) ; | |
| } | |
| .invalid-feedback { | |
| display: block; | |
| color: #dc3545; | |
| font-size: 0.875rem; | |
| margin-top: 0.25rem; | |
| font-style: italic; | |
| } | |
| /* Responsive adjustments */ | |
| @media (max-width: 768px) { | |
| .main-card { | |
| padding: 2rem 1.5rem; | |
| margin: 1rem; | |
| } | |
| .time-row { | |
| grid-template-columns: 1fr; | |
| gap: 1rem; | |
| } | |
| h1 { | |
| font-size: 1.8rem ; | |
| } | |
| } | |
| @media (max-width: 480px) { | |
| .main-card { | |
| padding: 1.5rem 1rem; | |
| } | |
| .btn-predict { | |
| font-size: 1.1rem ; | |
| padding: 0.875rem 1.5rem ; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <main> | |
| <div class="card main-card shadow-lg animate__animated"> | |
| <h1 class="text-center mb-4 text-3xl font-extrabold text-orange-600 animate__animated animate__bounceIn"> | |
| 🍛 Indian Food Flavor Profile Prediction | |
| </h1> | |
| <form method="post" class="needs-validation" novalidate id="predictionForm"> | |
| <!-- Ingredients --> | |
| <div class="form-group"> | |
| <label for="ingredients" class="form-label"> | |
| <span class="label-icon">🌶️</span>Ingredients | |
| </label> | |
| <textarea | |
| id="ingredients" | |
| name="ingredients" | |
| rows="3" | |
| required | |
| placeholder="Enter ingredients separated by commas (e.g., cumin, coriander, ginger, turmeric)" | |
| class="form-control" | |
| ></textarea> | |
| <div class="invalid-feedback">Please enter at least one ingredient.</div> | |
| </div> | |
| <!-- Diet --> | |
| <div class="form-group"> | |
| <label for="diet" class="form-label"> | |
| <span class="label-icon">🥬</span>Diet Type | |
| </label> | |
| <select id="diet" name="diet" required class="form-select"> | |
| <option value="" disabled selected>Choose diet type</option> | |
| <option value="vegetarian">🌱 Vegetarian</option> | |
| <option value="non vegetarian">🍖 Non Vegetarian</option> | |
| </select> | |
| <div class="invalid-feedback">Please select a diet type.</div> | |
| </div> | |
| <!-- Course --> | |
| <div class="form-group"> | |
| <label for="course" class="form-label"> | |
| <span class="label-icon">🍽️</span>Course Type | |
| </label> | |
| <select id="course" name="course" required class="form-select"> | |
| <option value="" disabled selected>Choose course type</option> | |
| <option value="starter">🥗 Starter</option> | |
| <option value="main course">🍛 Main Course</option> | |
| <option value="dessert">🍮 Dessert</option> | |
| <option value="snack">🍿 Snack</option> | |
| </select> | |
| <div class="invalid-feedback">Please select a course type.</div> | |
| </div> | |
| <!-- Region --> | |
| <div class="form-group"> | |
| <label for="region" class="form-label"> | |
| <span class="label-icon">🗺️</span>Indian Region | |
| </label> | |
| <select id="region" name="region" required class="form-select"> | |
| <option value="" disabled selected>Choose regional cuisine</option> | |
| <option value="North">🏔️ North Indian</option> | |
| <option value="South">🏝️ South Indian</option> | |
| <option value="East">🌅 East Indian</option> | |
| <option value="West">🌊 West Indian</option> | |
| </select> | |
| <div class="invalid-feedback">Please select a region.</div> | |
| </div> | |
| <!-- Prep & Cook Time --> | |
| <div class="time-row"> | |
| <div class="form-group"> | |
| <label for="prep_time" class="form-label"> | |
| <span class="label-icon">⏱️</span>Prep Time (minutes) | |
| </label> | |
| <input | |
| id="prep_time" | |
| type="number" | |
| name="prep_time" | |
| min="0" | |
| max="300" | |
| required | |
| placeholder="e.g., 15" | |
| class="form-control" | |
| /> | |
| <div class="invalid-feedback">Enter preparation time (0-300 minutes).</div> | |
| </div> | |
| <div class="form-group"> | |
| <label for="cook_time" class="form-label"> | |
| <span class="label-icon">🔥</span>Cook Time (minutes) | |
| </label> | |
| <input | |
| id="cook_time" | |
| type="number" | |
| name="cook_time" | |
| min="0" | |
| max="600" | |
| required | |
| placeholder="e.g., 30" | |
| class="form-control" | |
| /> | |
| <div class="invalid-feedback">Enter cooking time (0-600 minutes).</div> | |
| </div> | |
| </div> | |
| <button type="submit" class="btn btn-predict shadow-sm" id="submitBtn"> | |
| ✨ Predict Flavor Profile | |
| </button> | |
| </form> | |
| {% if prediction %} | |
| <div class="prediction-result"> | |
| 🎯 Predicted Flavor Profile: <strong>{{ prediction }}</strong> | |
| </div> | |
| {% endif %} | |
| <!-- Colab Link Section --> | |
| <div class="text-center mt-4"> | |
| <a | |
| href="https://colab.research.google.com/drive/1hpU2sx-U63uelHoa23nobW7nUQ-_ZgCW?usp=sharing" | |
| target="_blank" | |
| class="btn btn-outline-primary btn-sm px-3 py-2" | |
| style="border-radius: 0.5rem; font-weight: 500; text-decoration: none; border: 2px solid #007bff; color: #007bff; transition: all 0.3s ease;" | |
| onmouseover="this.style.backgroundColor='#007bff'; this.style.color='white'; this.style.transform='translateY(-1px)';" | |
| onmouseout="this.style.backgroundColor='transparent'; this.style.color='#007bff'; this.style.transform='translateY(0)';" | |
| > | |
| 📊 View Colab Notebook | |
| </a> | |
| <br> | |
| <br> | |
| </div> | |
| </div> | |
| <!-- Footer --> | |
| <footer class="text-center mt-4" style="position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); color: #8b4513; font-size: 0.9rem; font-weight: 500;"> | |
| © 2025 NIELIT - ROPAR | |
| </footer> | |
| </main> | |
| <!-- Bootstrap JS Bundle --> | |
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.4.1/dist/js/bootstrap.bundle.min.js"></script> | |
| <script> | |
| // Bootstrap form validation | |
| (() => { | |
| 'use strict'; | |
| const forms = document.querySelectorAll('.needs-validation'); | |
| Array.from(forms).forEach(form => { | |
| form.addEventListener('submit', event => { | |
| if (!form.checkValidity()) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| } else { | |
| // Add loading state to button | |
| const btn = document.getElementById('submitBtn'); | |
| btn.disabled = true; | |
| btn.innerHTML = '<span class="spinner-border spinner-border-sm me-2" role="status"></span>🔮 Analyzing flavors...'; | |
| btn.classList.add('animate__animated', 'animate__pulse'); | |
| } | |
| form.classList.add('was-validated'); | |
| }, false); | |
| }); | |
| })(); | |
| // Add some interactive feedback | |
| document.querySelectorAll('.form-control, .form-select').forEach(input => { | |
| input.addEventListener('focus', function() { | |
| this.parentElement.style.transform = 'scale(1.01)'; | |
| this.parentElement.style.transition = 'transform 0.2s ease'; | |
| }); | |
| input.addEventListener('blur', function() { | |
| this.parentElement.style.transform = 'scale(1)'; | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> |