CoolFace
Apppublic

sameernotes/slimshadow-ocr

sourceHugging Faceupdated 1y agoView on Hugging Face
1likes
feedback.html390 linesDownload Raw Back to root
1<!DOCTYPE html>2<html lang="en" class=""> <!-- Start without 'dark' initially -->3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1.0">6    <title>Feedback - AI Text Tools</title>7    <!-- Tailwind CSS via CDN -->8    <script src="https://cdn.tailwindcss.com/3.4.1"></script>9    <script>10        // Tailwind config11        tailwind.config = {12            darkMode: 'class',13            theme: {14                extend: {15                    colors: { primary: '#1a73e8', secondary: '#e8f0fe' },16                    borderRadius: { 'none': '0px', 'sm': '4px', DEFAULT: '8px', 'md': '12px', 'lg': '16px', 'xl': '20px', '2xl': '24px', '3xl': '32px', 'full': '9999px', 'button': '8px' }17                }18            }19        }20    </script>21    <!-- Fonts -->22    <link rel="preconnect" href="https://fonts.googleapis.com">23    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>24    <link href="https://fonts.googleapis.com/css2?family=Pacifico&display=swap" rel="stylesheet">25    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Devanagari:wght@400;700&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">26    <!-- Icons -->27    <link href="https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.css" rel="stylesheet">28    <!-- Custom Styles -->29    <style>30        body { font-family: 'Inter', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }31        .hindi-font { font-family: 'Noto Sans Devanagari', sans-serif; }32        .custom-switch { position: relative; display: inline-block; width: 50px; height: 24px; }33        .custom-switch-input { opacity: 0; width: 0; height: 0; }34        .custom-switch-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 34px; }35        .custom-switch-slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: .4s; border-radius: 50%; }36        .custom-switch-input:checked + .custom-switch-slider { background-color: #1a73e8; }37        .custom-switch-input:checked + .custom-switch-slider:before { transform: translateX(26px); }38        *:focus-visible { outline: 2px solid #1a73e8; outline-offset: 2px; box-shadow: 0 0 0 2px rgba(26, 115, 232, 0.3); }39        /* Base Dark Mode */40        html.dark body { background-color: #1a202c; color: #e2e8f0; }41        html.dark header, html.dark footer { background-color: #2d3748; color: #e2e8f0; }42        html.dark .card { background-color: #2d3748; border-color: #4a5568; } /* Simplified card selector */43        html.dark h1, html.dark h2, html.dark h3, html.dark p, html.dark span, html.dark li, html.dark label, html.dark small, html.dark strong, html.dark button:not(.bg-red-500):not(.bg-green-600), html.dark a { color: #e2e8f0; }44        html.dark a.text-primary { color: #60a5fa; }45        html.dark .text-gray-600, html.dark .text-gray-700, html.dark .text-gray-800, html.dark .text-gray-900 { color: #a0aec0; }46        html.dark .text-gray-500, html.dark .text-gray-400 { color: #718096; }47        html.dark .bg-white { background-color: #2d3748 !important; }48        html.dark .bg-gray-50 { background-color: #1a202c !important; }49        html.dark .bg-gray-100 { background-color: #374151 !important; }50        html.dark .border-gray-100, html.dark .border-gray-200 { border-color: #4a5568 !important; }51        /* Dark mode Forms */52        html.dark input, html.dark textarea { background-color: #1f2937; border-color: #4b5563; color: #e5e7eb; }53        html.dark input::placeholder, html.dark textarea::placeholder { color: #6b7280; }54        html.dark .error-message { background-color: #450a0a; color: #fecaca; border-color: #7f1d1d; }55        html.dark .success-message { background-color: #064e3b; color: #a7f3d0; border-color: #047857;}56        html.dark .spinner { border-color: rgba(255, 255, 255, 0.1); border-left-color: #60a5fa; }57        /* General Loading Spinner */58        .spinner { border: 3px solid rgba(255, 255, 255, 0.3); width: 16px; height: 16px; border-radius: 50%; border-left-color: #fff; animation: spin 1s ease infinite; }59        @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }60        /* Form Message Styling */61        .form-message { padding: 0.75rem 1rem; border-radius: 8px; margin-top: 1rem; font-weight: 500; border: 1px solid; font-size: 0.9rem; display: none; }62        .error-message { color: #dc2626; background-color: #fee2e2; border-color: #fecaca; }63        .success-message { color: #059669; background-color: #d1fae5; border-color: #a7f3d0; }64        /* Input Field Style */65        .input-field {66             display: block;67             width: 100%;68             padding: 0.5rem 0.75rem;69             border: 1px solid #d1d5db;70             border-radius: 8px;71             box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);72             transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;73             font-size: 0.875rem;74         }75         html.dark .input-field {76             background-color: #374151;77             border-color: #4b5563;78             color: #e5e7eb;79         }80         .input-field:focus {81             outline: none;82             border-color: #1a73e8;83             box-shadow: 0 0 0 2px rgba(26, 115, 232, 0.3);84         }85         html.dark .input-field:focus {86             border-color: #60a5fa;87             box-shadow: 0 0 0 2px rgba(96, 165, 250, 0.3);88         }89         /* Ensure nav link styling is consistent */90         .nav-link { transition: color 0.2s ease-in-out; }91 92    </style>93</head>94<body class="bg-gray-50 dark:bg-gray-900 min-h-screen flex flex-col text-gray-900 dark:text-gray-200">95 96    <!-- Header -->97    <header class="bg-white dark:bg-gray-800 shadow-sm sticky top-0 z-50">98        <div class="container mx-auto px-4 py-3 flex items-center justify-between">99            <div class="flex items-center">100                <a href="index.html" class="text-2xl font-['Pacifico'] text-primary dark:text-blue-400 mr-8" data-lang-en="AI Text Tools" data-lang-hi="एआई टेक्स्ट उपकरण">AI Text Tools</a>101                <!-- *** START: Updated Navigation Bar *** -->102                <nav id="mainNav" class="hidden md:flex space-x-6">103                     <a href="index.html" class="nav-link hover:text-primary dark:hover:text-blue-400 text-gray-600 dark:text-gray-300" data-lang-en="Home" data-lang-hi="होम">Home</a>104                     <!-- Assuming recognizer.html is the main tool page, link from index.html might be better -->105                     <a href="recognizer.html" class="nav-link hover:text-primary dark:hover:text-blue-400 text-gray-600 dark:text-gray-300" data-lang-en="Recognize" data-lang-hi="पहचानें">Recognize</a>106                     <!-- Assuming examples.html exists -->107                     <a href="examples.html" class="nav-link hover:text-primary dark:hover:text-blue-400 text-gray-600 dark:text-gray-300" data-lang-en="Examples" data-lang-hi="उदाहरण">Examples</a>108                     <!-- Assuming technology.html exists -->109                     <a href="technology.html" class="nav-link hover:text-primary dark:hover:text-blue-400 text-gray-600 dark:text-gray-300" data-lang-en="Technology" data-lang-hi="तकनीक">Technology</a>110                     <!-- Assuming about.html exists -->111                    <a href="about.html" class="nav-link hover:text-primary dark:hover:text-blue-400 text-gray-600 dark:text-gray-300" data-lang-en="About" data-lang-hi="बारे में">About</a>112                    <!-- Link to contact.html -->113                    <a href="contact.html" class="nav-link hover:text-primary dark:hover:text-blue-400 text-gray-600 dark:text-gray-300" data-lang-en="Contact" data-lang-hi="संपर्क">Contact</a>114                    <!-- Active link for this page -->115                    <a href="feedback.html" class="nav-link text-primary dark:text-blue-400 font-medium" data-lang-en="Feedback" data-lang-hi="प्रतिक्रिया">Feedback</a>116                </nav>117                <!-- *** END: Updated Navigation Bar *** -->118            </div>119            <!-- Right side header items (Theme, Lang Toggles) -->120            <div class="flex items-center space-x-4">121                <div class="items-center space-x-2 hidden md:flex"> <span class="text-sm text-gray-600 dark:text-gray-400">EN</span> <label class="custom-switch"><input type="checkbox" id="languageToggle" class="custom-switch-input"><span class="custom-switch-slider"></span></label> <span class="text-sm text-gray-600 dark:text-gray-400 hindi-font">हिंदी</span> </div>122                <div class="items-center space-x-2 hidden md:flex"> <span class="text-sm text-gray-600 dark:text-gray-400"><i class="ri-sun-line"></i></span> <label class="custom-switch"><input type="checkbox" id="themeToggle" class="custom-switch-input"><span class="custom-switch-slider"></span></label> <span class="text-sm text-gray-600 dark:text-gray-400"><i class="ri-moon-line"></i></span> </div>123                <!-- Removed Logout Button and User Icons for feedback page -->124                <button class="md:hidden w-10 h-10 flex items-center justify-center" aria-label="Toggle Menu"><i class="ri-menu-line text-gray-600 dark:text-gray-300 text-xl"></i></button>125            </div>126        </div>127    </header>128 129    <!-- ===== Main Content Area ===== -->130    <main class="flex-grow container mx-auto px-4 py-12">131 132        <h1 class="text-3xl font-bold text-center text-gray-800 dark:text-white mb-4" data-lang-en="Provide Feedback" data-lang-hi="प्रतिक्रिया दें">Provide Feedback</h1>133        <p class="text-center text-gray-600 dark:text-gray-400 mb-10" data-lang-en="Help us improve the AI Text Tools by sharing your thoughts." data-lang-hi="अपने विचार साझा करके एआई टेक्स्ट उपकरण को बेहतर बनाने में हमारी सहायता करें।">134            Help us improve the AI Text Tools by sharing your thoughts.135        </p>136 137        <div class="max-w-2xl mx-auto bg-white dark:bg-gray-800 p-8 rounded-xl shadow-lg border border-gray-100 dark:border-gray-700 card">138            <form id="feedbackForm" novalidate>139                <div class="mb-6">140                    <label for="feedbackText" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2" data-lang-en="Your Feedback" data-lang-hi="आपकी प्रतिक्रिया">Your Feedback</label>141                    <textarea id="feedbackText" name="feedback" rows="6" required class="input-field" placeholder="Enter your feedback here..." data-lang-en-placeholder="Enter your feedback here..." data-lang-hi-placeholder="अपनी प्रतिक्रिया यहाँ दर्ज करें..."></textarea>142                </div>143 144                <div id="formMessage" class="form-message mb-6"></div> <!-- For Success/Error Messages -->145 146                <button type="submit" id="submitFeedbackButton" class="w-full flex justify-center items-center gap-2 py-2.5 px-4 border border-transparent rounded-button shadow-sm text-sm font-medium text-white bg-primary hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary dark:focus:ring-offset-gray-800 disabled:opacity-50">147                    <span data-lang-en="Submit Feedback" data-lang-hi="प्रतिक्रिया जमा करें">Submit Feedback</span>148                    <i class="ri-send-plane-fill text-base"></i>149                    <div class="spinner hidden ml-2"></div> <!-- Loading Spinner -->150                </button>151            </form>152        </div>153 154    </main>155 156    <!-- Footer -->157    <footer class="bg-gray-900 text-gray-400 py-12 mt-16">158         <div class="container mx-auto px-4">159             <div class="grid grid-cols-1 md:grid-cols-4 gap-8">160                 <div>161                     <a href="index.html" class="text-2xl font-['Pacifico'] text-white mb-4 inline-block" data-lang-en="AI Text Tools" data-lang-hi="एआई टेक्स्ट उपकरण">AI Text Tools</a>162                     <p class="mb-4 text-sm" data-lang-en="AI-powered tools for text analysis and processing." data-lang-hi="पाठ विश्लेषण और प्रसंस्करण के लिए एआई-संचालित उपकरण।">AI-powered tools for text analysis.</p>163                     <div class="flex space-x-4">164                         <a href="#" class="hover:text-white" title="GitHub (Placeholder)"><i class="ri-github-fill"></i></a>165                         <a href="#" class="hover:text-white" title="LinkedIn (Placeholder)"><i class="ri-linkedin-box-fill"></i></a>166                     </div>167                 </div>168                 <div>169                     <h3 class="text-lg font-medium text-white mb-4" data-lang-en="Quick Links" data-lang-hi="त्वरित लिंक्स">Quick Links</h3>170                     <ul class="space-y-2 text-sm">171                         <li><a href="index.html" class="hover:text-white" data-lang-en="Home" data-lang-hi="होम">Home</a></li>172                         <li><a href="index.html#ocrContent" class="hover:text-white" data-lang-en="Tools" data-lang-hi="उपकरण">Tools</a></li> <!-- Link to Tools section on index -->173                         <li><a href="about.html" class="hover:text-white" data-lang-en="About" data-lang-hi="बारे में">About</a></li>174                         <li><a href="contact.html" class="hover:text-white" data-lang-en="Contact" data-lang-hi="संपर्क">Contact</a></li>175                         <li><a href="feedback.html" class="hover:text-white" data-lang-en="Feedback" data-lang-hi="प्रतिक्रिया">Feedback</a></li>176                     </ul>177                 </div>178                 <div>179                     <h3 class="text-lg font-medium text-white mb-4" data-lang-en="Resources" data-lang-hi="संसाधन">Resources</h3>180                     <ul class="space-y-2 text-sm">181                         <li><a href="#" class="hover:text-white" data-lang-en="API Docs (TBD)" data-lang-hi="एपीआई डॉक्स (TBD)">API Docs (TBD)</a></li>182                         <li><a href="#" class="hover:text-white" data-lang-en="GitHub Repo" data-lang-hi="गिटहब रेपो">GitHub Repo</a></li>183                     </ul>184                 </div>185                 <div>186                     <h3 class="text-lg font-medium text-white mb-4" data-lang-en="Contact" data-lang-hi="संपर्क">Contact</h3>187                     <ul class="space-y-2 text-sm">188                         <li class="flex items-start"><i class="ri-mail-line mt-1 mr-2"></i><span>your-email@example.com</span></li>189                     </ul>190                 </div>191             </div>192             <div class="border-t border-gray-700 mt-8 pt-8 text-center">193                  <p class="text-sm">© 2024 Your Name/Org | AI Text Tools Project</p>194             </div>195         </div>196    </footer>197 198    <!-- Base Theme/Language Script -->199    <script>200        const themeToggle = document.getElementById('themeToggle');201        const htmlElement = document.documentElement;202        function applyTheme(isDark) { if (isDark) { htmlElement.classList.add('dark'); if(themeToggle) themeToggle.checked = true; } else { htmlElement.classList.remove('dark'); if(themeToggle) themeToggle.checked = false; } }203        const languageToggle = document.getElementById('languageToggle');204        const langElements = document.querySelectorAll('[data-lang-en]');205        const placeholderElements = document.querySelectorAll('[data-lang-en-placeholder]'); // Select elements with placeholder translations206 207        function applyLanguage(lang) {208            htmlElement.setAttribute('lang', lang);209            // Handle regular text elements210            langElements.forEach(el => {211                const text = el.getAttribute(`data-lang-${lang}`);212                if (text) {213                    const icon = el.querySelector('i');214                    if (icon && el.childNodes.length > 1) { // Element has icon and text node215                        let updated = false;216                        el.childNodes.forEach(node => {217                            if (node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== '') {218                                node.textContent = ` ${text} `; // Add spaces around text if next to icon219                                updated = true;220                            }221                        });222                        // Fallback if text node wasn't found/updated directly223                        if (!updated) {224                           const currentText = el.getAttribute(`data-lang-${lang === 'en' ? 'hi' : 'en'}`);225                           if (currentText) el.innerHTML = el.innerHTML.replace(currentText.trim(), text);226                        }227                    } else { // Element is likely just text228                         el.textContent = text;229                    }230                 }231             });232             // Handle placeholder attributes233            placeholderElements.forEach(el => {234                const placeholderText = el.getAttribute(`data-lang-${lang}-placeholder`);235                 if (placeholderText !== null) { // Check if attribute exists236                     el.placeholder = placeholderText;237                 }238             });239 240             if (languageToggle) languageToggle.checked = (lang === 'hi');241             localStorage.setItem('language', lang);242         }243 244         // Function to initialize theme/language from storage or system preference245         function initializeSettings() {246             const savedLang = localStorage.getItem('language') || 'en';247             const prefersDark = localStorage.getItem('theme') === 'dark' || (localStorage.getItem('theme') === null && window.matchMedia('(prefers-color-scheme: dark)').matches);248             applyTheme(prefersDark);249             applyLanguage(savedLang); // Apply language after DOM is ready potentially250 251             if (languageToggle) {252                 languageToggle.addEventListener('change', (event) => {253                     const newLang = event.target.checked ? 'hi' : 'en';254                     applyLanguage(newLang);255                 });256             } else {257                 console.warn("Language toggle button not found.");258             }259 260             if (themeToggle) {261                 themeToggle.addEventListener('change', (event) => {262                     const isDark = event.target.checked;263                     applyTheme(isDark);264                     localStorage.setItem('theme', isDark ? 'dark' : 'light');265                 });266             } else {267                 console.warn("Theme toggle button not found.");268             }269         }270    </script>271 272    <!-- Feedback Form Submission Script (Corrected API Endpoint) -->273    <script>274        // *** CORRECTED: Define the FULL API endpoint URL from app.py context ***275        // MAKE SURE this URL points to where your app.py (OCR API) is running276        const OCR_API_BASE_URL = 'https://sameernotes-ocr.hf.space'; // Or 'http://localhost:8000' if running locally277        const FEEDBACK_API_ENDPOINT = `${OCR_API_BASE_URL}/feedback/`;278 279        // Get DOM elements (ensure these are correct IDs)280        const feedbackForm = document.getElementById('feedbackForm');281        const submitButton = document.getElementById('submitFeedbackButton');282        const feedbackTextInput = document.getElementById('feedbackText');283        const formMessageDiv = document.getElementById('formMessage');284        const spinner = submitButton ? submitButton.querySelector('.spinner') : null;285        // Language toggle reference is needed from the base script above, assumed available286 287        // Function to display messages288        function showFormMessage(message, isSuccess = true) {289            if (!formMessageDiv) return;290            formMessageDiv.textContent = message;291            formMessageDiv.className = 'form-message mb-6'; // Reset classes, keep margin292            if (isSuccess) {293                formMessageDiv.classList.add('success-message');294            } else {295                formMessageDiv.classList.add('error-message');296            }297            formMessageDiv.style.display = 'block';298            setTimeout(() => hideFormMessage(), 5000); // Hide after 5 seconds299        }300 301        function hideFormMessage() {302             if (formMessageDiv) {303                 formMessageDiv.style.display = 'none';304                 formMessageDiv.textContent = '';305             }306        }307 308        // Function to handle loading state309        function setFormLoading(isLoading) {310            if (!submitButton || !spinner) return;311            submitButton.disabled = isLoading;312            spinner.classList.toggle('hidden', !isLoading);313            // Adjust opacity of button content for visual feedback314            const contentElements = submitButton.querySelectorAll('span, i');315            contentElements.forEach(el => el.style.opacity = isLoading ? '0.5' : '1');316        }317 318        // Add event listener only if the form exists319        if (feedbackForm && submitButton && feedbackTextInput) {320            feedbackForm.addEventListener('submit', async (event) => {321                event.preventDefault();322                hideFormMessage();323 324                const comment = feedbackTextInput.value.trim();325                const currentLangIsHi = languageToggle && languageToggle.checked;326 327                if (!comment) {328                    const errorMessage = currentLangIsHi ? 'कृपया अपनी प्रतिक्रिया दर्ज करें।' : 'Please enter your feedback.';329                    showFormMessage(errorMessage, false);330                    return;331                }332 333                setFormLoading(true);334 335                const payload = {336                    username: "Anonymous", // Explicitly anonymous for this page337                    comment: comment338                };339 340                console.log("Sending feedback payload to:", FEEDBACK_API_ENDPOINT, payload);341 342                try {343                    const response = await fetch(FEEDBACK_API_ENDPOINT, {344                        method: 'POST',345                        headers: {346                            'Content-Type': 'application/json',347                            'Accept': 'application/json'348                        },349                        body: JSON.stringify(payload)350                    });351 352                    const responseData = await response.json();353 354                    if (!response.ok) {355                        // Attempt to get detail from common FastAPI error structure356                        const errorDetail = responseData.detail || `Request failed with status ${response.status}`;357                        throw new Error(errorDetail);358                    }359 360                    console.log("Feedback submitted successfully:", responseData);361                    const successMsg = currentLangIsHi ? 'आपकी प्रतिक्रिया सफलतापूर्वक जमा कर दी गई है! धन्यवाद।' : 'Feedback submitted successfully! Thank you.';362                    showFormMessage(successMsg, true);363                    feedbackTextInput.value = ''; // Clear the textarea364 365                } catch (error) {366                    console.error('Error submitting feedback:', error);367                    let detailedErrorMsg = error.message;368                    if (error instanceof TypeError && error.message.toLowerCase().includes('failed to fetch')) {369                         detailedErrorMsg = currentLangIsHi ? 'नेटवर्क त्रुटि या सर्वर तक पहुंचने में असमर्थ। CORS समस्या या सर्वर डाउन हो सकता है।' : 'Network error or unable to reach server. Check CORS or if the server is running.';370                    }371                    const errorMsg = (currentLangIsHi ? 'प्रतिक्रिया जमा करने में त्रुटि हुई: ' : 'Error submitting feedback: ') + detailedErrorMsg;372                    showFormMessage(errorMsg, false);373                } finally {374                    setFormLoading(false);375                }376            });377        } else {378            console.error("Required feedback form elements not found on the page.");379        }380 381        // Initialize theme and language settings when the DOM is fully loaded382        document.addEventListener('DOMContentLoaded', () => {383            initializeSettings(); // Call the function defined in the base script block384            console.log("Feedback page DOM Loaded and Initialized.");385        });386 387    </script>388 389</body>390</html>