Spaces:
Running
Running
File size: 13,002 Bytes
a0494fe 2afa0fe | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document Similarity Checker</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(to bottom right, #141e30, #243b55);
}
.card {
backdrop-filter: blur(10px);
background-color: rgba(40, 50, 60, 0.7);
border: 1px solid rgba(255, 255, 255, 0.1);
transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
}
.file-input-wrapper {
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out;
}
</style>
</head>
<body class="flex items-center justify-center min-h-screen p-4">
<!-- Main application container with a modern card design -->
<div class="card p-8 rounded-3xl shadow-2xl max-w-lg w-full text-center">
<h1 class="text-4xl font-bold text-white mb-2 tracking-wide">DocChecker</h1>
<p class="text-base text-gray-400 mb-8">Upload two .docx files to check their content similarity.</p>
<!-- Form for file uploads -->
<form id="uploadForm" class="space-y-6">
<div>
<label for="file1" class="block text-left text-sm font-medium text-gray-300 mb-1">Base Document</label>
<label for="file1" class="file-input-wrapper flex items-center justify-center space-x-2 cursor-pointer bg-gray-700 hover:bg-gray-600 rounded-lg p-4 transition duration-300 ease-in-out border-2 border-solid border-gray-600 focus-within:border-cyan-500">
<input type="file" id="file1" name="file1" accept=".docx" required class="hidden">
<!-- SVG icon for a document -->
<svg class="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<span id="file1-name" class="text-sm font-medium text-gray-400">Choose a .docx file...</span>
</label>
</div>
<div>
<label for="file2" class="block text-left text-sm font-medium text-gray-300 mb-1">Candidate Document</label>
<label for="file2" class="file-input-wrapper flex items-center justify-center space-x-2 cursor-pointer bg-gray-700 hover:bg-gray-600 rounded-lg p-4 transition duration-300 ease-in-out border-2 border-solid border-gray-600 focus-within:border-cyan-500">
<input type="file" id="file2" name="file2" accept=".docx" required class="hidden">
<!-- SVG icon for a document -->
<svg class="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<span id="file2-name" class="text-sm font-medium text-gray-400">Choose a .docx file...</span>
</label>
</div>
<!-- Submit button with a hover and active effect -->
<button type="submit" id="submitBtn" class="w-full py-3 px-4 bg-cyan-500 text-white font-semibold rounded-full
shadow-lg hover:bg-cyan-600 focus:outline-none focus:ring-2 focus:ring-cyan-500
focus:ring-offset-2 focus:ring-offset-gray-800 transition duration-300 ease-in-out
transform hover:scale-105 active:scale-95">
Check Similarity
</button>
</form>
<!-- Area for displaying results or messages -->
<div id="resultContainer" class="mt-8 relative min-h-[100px] flex items-center justify-center">
<!-- Loading spinner with animation -->
<div id="loading" class="hidden text-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 opacity-0 transition-opacity duration-500 ease-in-out">
<div class="inline-block h-10 w-10 animate-spin rounded-full border-4 border-solid border-current border-r-transparent text-cyan-400" role="status">
<span class="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]">Loading...</span>
</div>
<p class="mt-3 text-sm text-gray-400">Checking files...</p>
</div>
<!-- Result display area with fade-in effect -->
<div id="result" class="hidden absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 opacity-0 transition-opacity duration-500 ease-in-out">
<p class="text-xl text-gray-300">Similarity Score:</p>
<p id="score" class="text-6xl font-extrabold text-cyan-400 mt-2"></p>
</div>
<!-- Error message display area with fade-in effect -->
<div id="error" class="hidden absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 opacity-0 transition-opacity duration-500 ease-in-out">
<p id="errorMessage" class="text-red-400 text-sm font-medium mt-2"></p>
</div>
</div>
<!-- Developer Information Section -->
<div class="mt-12 pt-6 border-t border-gray-700 text-gray-400 text-sm">
<p class="mb-2">Developed by Muhammad Hamza</p>
<div class="flex justify-center space-x-6">
<a href="https://github.com/MuhammadHamza123c" target="_blank" class="hover:text-white transition duration-200" title="GitHub">
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.956 0-1.091.39-1.984 1.029-2.682-.103-.253-.446-1.272.098-2.651 0 0 .84-.268 2.75 1.022A9.615 9.615 0 0112 6.865c.85.006 1.704.114 2.504.337 1.909-1.29 2.747-1.022 2.747-1.022.546 1.379.202 2.398.099 2.651.64.698 1.028 1.591 1.028 2.682 0 3.854-2.339 4.691-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd" />
</svg>
</a>
<a href="https://www.linkedin.com/in/muhammad-hamzads/" target="_blank" class="hover:text-white transition duration-200" title="LinkedIn">
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/>
</svg>
</a>
<a href="mailto:muhammadhamzao241@gmaul.com" target="_blank" class="hover:text-white transition duration-200" title="Email">
<svg class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 12.713l-11.985-9.713h23.97l-11.985 9.713zm0 2.574l-12-9.722v16.435h24v-16.435l-12 9.722z"/>
</svg>
</a>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('uploadForm');
const file1Input = document.getElementById('file1');
const file2Input = document.getElementById('file2');
const submitBtn = document.getElementById('submitBtn');
const loading = document.getElementById('loading');
const resultDiv = document.getElementById('result');
const scoreSpan = document.getElementById('score');
const errorDiv = document.getElementById('error');
const errorMessageSpan = document.getElementById('errorMessage');
// The base URL for the FastAPI service
const baseUrl = 'https://humza7656-my-doc-checker.hf.space';
// Function to show a message box by fading in the content
function showMessage(element, message, isError = false) {
// Hide all result containers first
loading.classList.add('hidden', 'opacity-0');
resultDiv.classList.add('hidden', 'opacity-0');
errorDiv.classList.add('hidden', 'opacity-0');
if (isError) {
errorMessageSpan.textContent = message;
} else {
scoreSpan.textContent = message;
}
// Show the specific element and fade it in
element.classList.remove('hidden');
setTimeout(() => element.classList.remove('opacity-0'), 10);
}
// Update the display text for file inputs
file1Input.addEventListener('change', (event) => {
const fileName = event.target.files[0] ? event.target.files[0].name : 'Choose a .docx file...';
document.getElementById('file1-name').textContent = fileName;
});
file2Input.addEventListener('change', (event) => {
const fileName = event.target.files[0] ? event.target.files[0].name : 'Choose a .docx file...';
document.getElementById('file2-name').textContent = fileName;
});
form.addEventListener('submit', async (e) => {
e.preventDefault();
// Get the files from the input fields
const file1 = file1Input.files[0];
const file2 = file2Input.files[0];
// Simple client-side validation for file types
if (!file1 || !file2) {
showMessage(errorDiv, 'Please select both files.', true);
return;
}
if (!file1.name.endsWith('.docx') || !file2.name.endsWith('.docx')) {
showMessage(errorDiv, 'Both files must be of type .docx', true);
return;
}
// Show loading state
showMessage(loading, '', false);
submitBtn.disabled = true;
// Create a FormData object to send the files
const formData = new FormData();
formData.append('f1', file1);
formData.append('f2', file2);
try {
const response = await fetch(`${baseUrl}/similar_doc`, {
method: 'POST',
body: formData
});
const data = await response.json();
if (response.ok) {
// API call was successful
const similarity = data.Similarity;
showMessage(resultDiv, similarity.toFixed(2));
} else {
// API returned an error
const errorMsg = data.error || 'An unknown error occurred.';
showMessage(errorDiv, errorMsg, true);
}
} catch (error) {
// Network or other fetch-related error
console.error('Error:', error);
showMessage(errorDiv, 'Could not connect to the API. Please try again later.', true);
} finally {
// Re-enable button
submitBtn.disabled = false;
}
});
});
</script>
</body>
</html>
|