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>