bagustyo commited on
Commit
bb825f2
·
verified ·
1 Parent(s): 2405660

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +197 -39
templates/index.html CHANGED
@@ -3,48 +3,206 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>778 TXT File Processor</title>
 
 
 
 
 
 
 
 
 
 
7
  <style>
8
- body { font-family: Arial, sans-serif; margin: 40px; background: #f8f9fa; }
9
- .container { max-width: 700px; margin: auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 0 15px rgba(0,0,0,0.1); }
10
- h1 { color: #333; }
11
- input[type="file"] { margin: 15px 0; }
12
- button { padding: 12px 20px; background: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; }
13
- button:hover { background: #0056b3; }
14
- .result { margin-top: 20px; padding: 15px; background: #e9f7ef; border-radius: 5px; }
 
 
 
 
 
 
 
 
15
  </style>
16
  </head>
17
- <body>
18
- <div class="container">
19
- <h1>778 TXT Processor</h1>
20
- <p>Upload multiple <strong>.txt</strong> files or one <strong>.zip</strong> folder containing them.</p>
21
-
22
- <form action="/upload/" method="post" enctype="multipart/form-data">
23
- <input type="file" name="files" multiple accept=".txt,.zip" required>
24
- <br><br>
25
- <button type="submit">Upload & Process</button>
26
- </form>
27
-
28
- <div id="result"></div>
29
- </div>
30
-
31
- <script>
32
- document.querySelector('form').addEventListener('submit', async (e) => {
33
- e.preventDefault();
34
- const formData = new FormData(e.target);
35
- const res = await fetch('/upload/', { method: 'POST', body: formData });
36
- const data = await res.json();
37
-
38
- document.getElementById('result').innerHTML = `
39
- <div class="result">
40
- <h2>✅ Processing Complete!</h2>
41
- <p><strong>Uploaded:</strong> ${data.uploaded_files}</p>
42
- <p><strong>Processed input files:</strong> ${data.processed_input_files}</p>
43
- <p><strong>Generated FNL files:</strong> ${data.generated_fnl_files}</p>
44
- <a href="/download/" download><button>📥 Download All FNL Files (ZIP)</button></a>
45
  </div>
46
- `;
47
- });
48
- </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  </body>
50
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>778 TXT Processor</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
9
+ <script>
10
+ tailwind.config = {
11
+ content: [],
12
+ theme: {
13
+ extend: {}
14
+ }
15
+ }
16
+ </script>
17
  <style>
18
+ .drop-zone {
19
+ transition: all 0.3s ease;
20
+ }
21
+ .drop-zone.dragover {
22
+ background-color: #eff6ff;
23
+ border-color: #3b82f6;
24
+ transform: scale(1.02);
25
+ }
26
+ .spinner {
27
+ animation: spin 1s linear infinite;
28
+ }
29
+ @keyframes spin {
30
+ 0% { transform: rotate(0deg); }
31
+ 100% { transform: rotate(360deg); }
32
+ }
33
  </style>
34
  </head>
35
+ <body class="bg-gradient-to-br from-slate-50 to-slate-100 min-h-screen font-sans">
36
+ <div class="max-w-2xl mx-auto py-12 px-6">
37
+ <!-- Header -->
38
+ <div class="text-center mb-10">
39
+ <div class="inline-flex items-center justify-center w-16 h-16 bg-blue-600 text-white rounded-2xl mb-4 shadow-lg">
40
+ <i class="fa-solid fa-file-lines text-3xl"></i>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  </div>
42
+ <h1 class="text-4xl font-bold text-slate-800 tracking-tight">778 TXT Processor</h1>
43
+ <p class="text-slate-600 mt-2 text-lg">Clean • Fast • Automated</p>
44
+ </div>
45
+
46
+ <div class="bg-white rounded-3xl shadow-xl overflow-hidden">
47
+ <!-- Upload Section -->
48
+ <div class="p-8 border-b">
49
+ <div class="mb-6">
50
+ <h2 class="text-xl font-semibold text-slate-700 flex items-center gap-2">
51
+ <i class="fa-solid fa-cloud-arrow-up"></i>
52
+ Upload Files
53
+ </h2>
54
+ <p class="text-slate-500 text-sm mt-1">
55
+ Select multiple <strong>.txt</strong> files or one <strong>.zip</strong> archive containing your files
56
+ </p>
57
+ </div>
58
+
59
+ <form id="uploadForm" class="space-y-6">
60
+ <!-- Drag & Drop Zone -->
61
+ <div id="dropZone"
62
+ class="drop-zone border-2 border-dashed border-slate-300 rounded-2xl p-12 text-center cursor-pointer hover:border-blue-400 bg-slate-50">
63
+ <i class="fa-solid fa-cloud-arrow-up text-5xl text-slate-400 mb-4"></i>
64
+ <p class="text-lg font-medium text-slate-700">Drag & drop your files here</p>
65
+ <p class="text-slate-500 text-sm mt-1">or</p>
66
+ <label class="inline-block mt-4 px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-xl cursor-pointer transition font-medium">
67
+ <i class="fa-solid fa-folder-open mr-2"></i>
68
+ Browse Files
69
+ <input type="file" id="fileInput" name="files" multiple accept=".txt,.zip" class="hidden">
70
+ </label>
71
+ <p class="text-xs text-slate-400 mt-6">Supported: .txt and .zip files</p>
72
+ </div>
73
+
74
+ <button type="submit"
75
+ id="submitBtn"
76
+ class="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-4 rounded-2xl flex items-center justify-center gap-3 transition shadow-md">
77
+ <i class="fa-solid fa-gear"></i>
78
+ Upload & Process Files
79
+ </button>
80
+ </form>
81
+ </div>
82
+
83
+ <!-- Result Section -->
84
+ <div id="resultSection" class="hidden p-8">
85
+ <div id="loading" class="hidden text-center py-12">
86
+ <div class="inline-block w-10 h-10 border-4 border-blue-200 border-t-blue-600 rounded-full spinner mb-4"></div>
87
+ <p class="text-slate-600 font-medium">Processing your files...</p>
88
+ <p class="text-xs text-slate-400 mt-1">Please wait</p>
89
+ </div>
90
+
91
+ <div id="successResult" class="hidden">
92
+ <div class="flex items-center gap-3 mb-6">
93
+ <div class="w-10 h-10 bg-emerald-100 text-emerald-600 rounded-2xl flex items-center justify-center">
94
+ <i class="fa-solid fa-check text-2xl"></i>
95
+ </div>
96
+ <div>
97
+ <h2 class="text-2xl font-semibold text-emerald-700">Processing Complete!</h2>
98
+ <p class="text-slate-500">Your FNL files have been generated successfully.</p>
99
+ </div>
100
+ </div>
101
+
102
+ <div class="grid grid-cols-3 gap-4 mb-8">
103
+ <div class="bg-slate-50 rounded-2xl p-4 text-center">
104
+ <p class="text-xs text-slate-500">Uploaded</p>
105
+ <p id="uploadedCount" class="text-3xl font-bold text-slate-700">0</p>
106
+ </div>
107
+ <div class="bg-slate-50 rounded-2xl p-4 text-center">
108
+ <p class="text-xs text-slate-500">Processed</p>
109
+ <p id="processedCount" class="text-3xl font-bold text-slate-700">0</p>
110
+ </div>
111
+ <div class="bg-slate-50 rounded-2xl p-4 text-center">
112
+ <p class="text-xs text-slate-500">Generated</p>
113
+ <p id="generatedCount" class="text-3xl font-bold text-emerald-600">0</p>
114
+ </div>
115
+ </div>
116
+
117
+ <a id="downloadLink" href="/download/"
118
+ class="block w-full bg-emerald-600 hover:bg-emerald-700 text-white font-semibold py-4 rounded-2xl text-center transition flex items-center justify-center gap-3 shadow-md">
119
+ <i class="fa-solid fa-download"></i>
120
+ Download All FNL Files (ZIP)
121
+ </a>
122
+ </div>
123
+ </div>
124
+ </div>
125
+
126
+ <!-- Footer -->
127
+ <div class="text-center text-slate-400 text-xs mt-8">
128
+ FastAPI • Jinja2 • Tailwind CSS
129
+ </div>
130
+ </div>
131
+
132
+ <script>
133
+ const dropZone = document.getElementById('dropZone');
134
+ const fileInput = document.getElementById('fileInput');
135
+ const form = document.getElementById('uploadForm');
136
+ const submitBtn = document.getElementById('submitBtn');
137
+ const resultSection = document.getElementById('resultSection');
138
+ const loading = document.getElementById('loading');
139
+ const successResult = document.getElementById('successResult');
140
+
141
+ // Tailwind script already loaded via CDN
142
+
143
+ // Drag & Drop handlers
144
+ dropZone.addEventListener('dragover', (e) => {
145
+ e.preventDefault();
146
+ dropZone.classList.add('dragover');
147
+ });
148
+
149
+ dropZone.addEventListener('dragleave', () => {
150
+ dropZone.classList.remove('dragover');
151
+ });
152
+
153
+ dropZone.addEventListener('drop', (e) => {
154
+ e.preventDefault();
155
+ dropZone.classList.remove('dragover');
156
+ fileInput.files = e.dataTransfer.files;
157
+ });
158
+
159
+ dropZone.addEventListener('click', () => {
160
+ fileInput.click();
161
+ });
162
+
163
+ // Form submit
164
+ form.addEventListener('submit', async (e) => {
165
+ e.preventDefault();
166
+
167
+ if (fileInput.files.length === 0) {
168
+ alert("Please select at least one file or ZIP archive.");
169
+ return;
170
+ }
171
+
172
+ // Show loading
173
+ resultSection.classList.remove('hidden');
174
+ loading.classList.remove('hidden');
175
+ successResult.classList.add('hidden');
176
+ submitBtn.disabled = true;
177
+ submitBtn.innerHTML = `<i class="fa-solid fa-spinner spinner mr-2"></i> Processing...`;
178
+
179
+ const formData = new FormData(form);
180
+
181
+ try {
182
+ const res = await fetch('/upload/', {
183
+ method: 'POST',
184
+ body: formData
185
+ });
186
+
187
+ const data = await res.json();
188
+
189
+ // Hide loading, show success
190
+ loading.classList.add('hidden');
191
+ successResult.classList.remove('hidden');
192
+
193
+ // Fill statistics
194
+ document.getElementById('uploadedCount').textContent = data.uploaded_files || 0;
195
+ document.getElementById('processedCount').textContent = data.processed_input_files || 0;
196
+ document.getElementById('generatedCount').textContent = data.generated_fnl_files || 0;
197
+
198
+ } catch (err) {
199
+ alert("An error occurred during processing. Please try again.");
200
+ console.error(err);
201
+ } finally {
202
+ submitBtn.disabled = false;
203
+ submitBtn.innerHTML = `<i class="fa-solid fa-gear"></i> Upload & Process Files`;
204
+ }
205
+ });
206
+ </script>
207
  </body>
208
  </html>