007m commited on
Commit
fbd3ec0
·
verified ·
1 Parent(s): 4f437e1

сделай на русском и для андроид

Browse files
Files changed (2) hide show
  1. README.md +9 -5
  2. index.html +447 -18
README.md CHANGED
@@ -1,10 +1,14 @@
1
  ---
2
- title: Timetrack Pro Ru
3
- emoji: 👁
4
- colorFrom: pink
5
- colorTo: gray
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: TimeTrack Pro RU ⏱️
3
+ colorFrom: gray
4
+ colorTo: purple
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://deepsite.hf.co).
14
+
index.html CHANGED
@@ -1,19 +1,448 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
+ <title>TimeTrack Pro RU</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
12
+ <style>
13
+ body {
14
+ font-family: 'Roboto', sans-serif;
15
+ -webkit-tap-highlight-color: transparent;
16
+ }
17
+ button, input, select, textarea {
18
+ font-size: 16px !important; /* Prevent zoom on focus in mobile browsers */
19
+ }
20
+ </style>
21
+ <style>
22
+ .time-card:hover {
23
+ transform: translateY(-5px);
24
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
25
+ }
26
+ .pulse-animation {
27
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
28
+ }
29
+ @keyframes pulse {
30
+ 0%, 100% { opacity: 1; }
31
+ 50% { opacity: 0.5; }
32
+ }
33
+ </style>
34
+ </head>
35
+ <body class="bg-gray-50">
36
+ <div id="app" class="min-h-screen">
37
+ <!-- Header -->
38
+ <header class="bg-indigo-600 text-white shadow-lg">
39
+ <div class="container mx-auto px-4 py-6">
40
+ <div class="flex justify-between items-center">
41
+ <div class="flex items-center space-x-3">
42
+ <i data-feather="clock" class="w-8 h-8"></i>
43
+ <h1 class="text-2xl font-bold">TimeTrack Pro RU</h1>
44
+ </div>
45
+ <div class="flex items-center space-x-4">
46
+ <button class="px-4 py-2 bg-indigo-700 rounded-lg hover:bg-indigo-800 transition flex items-center">
47
+ <i data-feather="user" class="mr-2"></i>
48
+ Profile
49
+ </button>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </header>
54
+
55
+ <!-- Main Content -->
56
+ <main class="container mx-auto px-4 py-8">
57
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
58
+ <!-- Time Tracking Card -->
59
+ <div class="lg:col-span-2">
60
+ <div class="bg-white rounded-xl shadow-md p-6">
61
+ <h2 class="text-xl font-semibold mb-6 flex items-center">
62
+ <i data-feather="watch" class="mr-2 text-indigo-600"></i>
63
+ Текущая смена
64
+ </h2>
65
+ <div class="flex flex-col items-center justify-center py-8">
66
+ <div class="text-5xl font-bold mb-4" id="current-time">--:--:--</div>
67
+ <div class="text-gray-500 mb-8" id="current-date">Loading date...</div>
68
+
69
+ <div class="flex space-x-4 mb-8">
70
+ <button id="clock-in-btn" class="px-6 py-3 bg-green-500 text-white rounded-lg hover:bg-green-600 transition flex items-center pulse-animation">
71
+ <i data-feather="log-in" class="mr-2"></i>
72
+ Начать смену
73
+ </button>
74
+ <button id="clock-out-btn" disabled class="px-6 py-3 bg-red-500 text-white rounded-lg hover:bg-red-600 transition flex items-center opacity-50">
75
+ <i data-feather="log-out" class="mr-2"></i>
76
+ Закончить смену
77
+ </button>
78
+ </div>
79
+
80
+ <div class="w-full bg-gray-200 rounded-full h-2.5 mb-4">
81
+ <div id="progress-bar" class="bg-indigo-600 h-2.5 rounded-full" style="width: 0%"></div>
82
+ </div>
83
+ <p class="text-sm text-gray-600">Прогресс смены: <span id="progress-text">0%</span></p>
84
+ </div>
85
+ </div>
86
+
87
+ <!-- Recent Shifts -->
88
+ <div class="bg-white rounded-xl shadow-md p-6 mt-6">
89
+ <h2 class="text-xl font-semibold mb-6 flex items-center">
90
+ <i data-feather="list" class="mr-2 text-indigo-600"></i>
91
+ Последние смены
92
+ </h2>
93
+ <div class="overflow-x-auto">
94
+ <table class="min-w-full divide-y divide-gray-200">
95
+ <thead class="bg-gray-50">
96
+ <tr>
97
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Дата</th>
98
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Начало</th>
99
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Конец</th>
100
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Часы</th>
101
+ </tr>
102
+ </thead>
103
+ <tbody id="shifts-table" class="bg-white divide-y divide-gray-200">
104
+ <!-- Data will be inserted here by JavaScript -->
105
+ </tbody>
106
+ </table>
107
+ </div>
108
+ </div>
109
+ </div>
110
+
111
+ <!-- Stats and Summary -->
112
+ <div class="flex flex-col space-y-6">
113
+ <!-- Today's Summary -->
114
+ <div class="bg-white rounded-xl shadow-md p-6">
115
+ <h2 class="text-xl font-semibold mb-4 flex items-center">
116
+ <i data-feather="bar-chart-2" class="mr-2 text-indigo-600"></i>
117
+ Today's Summary
118
+ </h2>
119
+ <div class="space-y-4">
120
+ <div class="flex justify-between items-center">
121
+ <span class="text-gray-600">Отработано:</span>
122
+ <span id="today-hours" class="font-bold">0h 0m</span>
123
+ </div>
124
+ <div class="flex justify-between items-center">
125
+ <span class="text-gray-600">Заработок:</span>
126
+ <span id="today-earnings" class="font-bold">$0.00</span>
127
+ </div>
128
+ <div class="flex justify-between items-center">
129
+ <span class="text-gray-600">Статус:</span>
130
+ <span id="today-status" class="font-bold text-red-500">Не на смене</span>
131
+ </div>
132
+ </div>
133
+ </div>
134
+
135
+ <!-- Weekly Summary -->
136
+ <div class="bg-white rounded-xl shadow-md p-6">
137
+ <h2 class="text-xl font-semibold mb-4 flex items-center">
138
+ <i data-feather="calendar" class="mr-2 text-indigo-600"></i>
139
+ Weekly Summary
140
+ </h2>
141
+ <div class="space-y-4">
142
+ <div class="flex justify-between items-center">
143
+ <span class="text-gray-600">Всего часов:</span>
144
+ <span id="weekly-hours" class="font-bold">0h 0m</span>
145
+ </div>
146
+ <div class="flex justify-between items-center">
147
+ <span class="text-gray-600">Ожидаемая оплата:</span>
148
+ <span id="weekly-earnings" class="font-bold">$0.00</span>
149
+ </div>
150
+ <div class="flex justify-between items-center">
151
+ <span class="text-gray-600">Отработано дней:</span>
152
+ <span id="weekly-days" class="font-bold">0</span>
153
+ </div>
154
+ </div>
155
+ </div>
156
+
157
+ <!-- Settings Card -->
158
+ <div class="bg-white rounded-xl shadow-md p-6">
159
+ <h2 class="text-xl font-semibold mb-4 flex items-center">
160
+ <i data-feather="settings" class="mr-2 text-indigo-600"></i>
161
+ Настройки
162
+ </h2>
163
+ <div class="space-y-4">
164
+ <div>
165
+ <label for="hourly-rate" class="block text-sm font-medium text-gray-700 mb-1">Ставка (₽/час)</label>
166
+ <input type="number" id="hourly-rate" value="15.00"
167
+ class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500">
168
+ </div>
169
+ <div>
170
+ <label for="work-hours" class="block text-sm font-medium text-gray-700 mb-1">Часов в день</label>
171
+ <input type="number" id="work-hours" value="8"
172
+ class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500">
173
+ </div>
174
+ <button id="save-settings" class="w-full px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 transition">
175
+ Сохранить
176
+ </button>
177
+ </div>
178
+ </div>
179
+ </div>
180
+ </div>
181
+ </main>
182
+
183
+ <!-- Footer -->
184
+ <footer class="bg-gray-800 text-white py-6 mt-12">
185
+ <div class="container mx-auto px-4 text-center">
186
+ <p>© 2023 TimeTrack Pro RU. Все права защищены.</p>
187
+ <p class="text-gray-400 text-sm mt-2">Учитывайте время, увеличивайте заработок!</p>
188
+ </div>
189
+ </footer>
190
+ </div>
191
+
192
+ <script>
193
+ document.addEventListener('DOMContentLoaded', function() {
194
+ feather.replace();
195
+
196
+ // Update current time every second
197
+ function updateClock() {
198
+ const now = new Date();
199
+ const timeElement = document.getElementById('current-time');
200
+ const dateElement = document.getElementById('current-date');
201
+
202
+ timeElement.textContent = now.toLocaleTimeString();
203
+ dateElement.textContent = now.toLocaleDateString('ru-RU', {
204
+ weekday: 'long',
205
+ year: 'numeric',
206
+ month: 'long',
207
+ day: 'numeric'
208
+ });
209
+ }
210
+ updateClock();
211
+ setInterval(updateClock, 1000);
212
+
213
+ // Sample data for shifts (in a real app, this would come from localStorage or a database)
214
+ let shifts = JSON.parse(localStorage.getItem('shifts')) || [];
215
+ let isClockedIn = false;
216
+ let currentShift = null;
217
+
218
+ // Check if there's an active shift
219
+ if (shifts.length > 0 && !shifts[shifts.length - 1].clockOut) {
220
+ isClockedIn = true;
221
+ currentShift = shifts[shifts.length - 1];
222
+ updateClockInUI(true);
223
+ }
224
+
225
+ // Populate shifts table
226
+ function populateShiftsTable() {
227
+ const tableBody = document.getElementById('shifts-table');
228
+ tableBody.innerHTML = '';
229
+
230
+ // Show only last 5 shifts for simplicity
231
+ const recentShifts = shifts.slice(-5).reverse();
232
+
233
+ recentShifts.forEach(shift => {
234
+ const row = document.createElement('tr');
235
+
236
+ const dateCell = document.createElement('td');
237
+ dateCell.className = 'px-6 py-4 whitespace-nowrap text-sm text-gray-900';
238
+ dateCell.textContent = new Date(shift.clockIn).toLocaleDateString();
239
+
240
+ const inCell = document.createElement('td');
241
+ inCell.className = 'px-6 py-4 whitespace-nowrap text-sm text-gray-500';
242
+ inCell.textContent = new Date(shift.clockIn).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
243
+
244
+ const outCell = document.createElement('td');
245
+ outCell.className = 'px-6 py-4 whitespace-nowrap text-sm text-gray-500';
246
+ outCell.textContent = shift.clockOut ?
247
+ new Date(shift.clockOut).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) : '--:--';
248
+
249
+ const hoursCell = document.createElement('td');
250
+ hoursCell.className = 'px-6 py-4 whitespace-nowrap text-sm font-medium';
251
+
252
+ if (shift.clockOut) {
253
+ const hours = (new Date(shift.clockOut) - new Date(shift.clockIn)) / (1000 * 60 * 60);
254
+ hoursCell.textContent = hours.toFixed(2) + 'h';
255
+ hoursCell.classList.add('text-green-600');
256
+ } else {
257
+ hoursCell.textContent = 'Active';
258
+ hoursCell.classList.add('text-indigo-600');
259
+ }
260
+
261
+ row.appendChild(dateCell);
262
+ row.appendChild(inCell);
263
+ row.appendChild(outCell);
264
+ row.appendChild(hoursCell);
265
+
266
+ tableBody.appendChild(row);
267
+ });
268
+
269
+ updateSummaryCards();
270
+ }
271
+
272
+ // Update summary cards with calculations
273
+ function updateSummaryCards() {
274
+ // Today's hours
275
+ const today = new Date().toLocaleDateString();
276
+ const todayShifts = shifts.filter(shift =>
277
+ new Date(shift.clockIn).toLocaleDateString() === today && shift.clockOut
278
+ );
279
+
280
+ let todayMinutes = 0;
281
+ todayShifts.forEach(shift => {
282
+ todayMinutes += (new Date(shift.clockOut) - new Date(shift.clockIn)) / (1000 * 60);
283
+ });
284
+
285
+ const todayHours = Math.floor(todayMinutes / 60);
286
+ const todayMins = Math.floor(todayMinutes % 60);
287
+ document.getElementById('today-hours').textContent = `${todayHours}h ${todayMins}m`;
288
+
289
+ // Weekly hours (last 7 days)
290
+ const oneWeekAgo = new Date();
291
+ oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
292
+
293
+ const weeklyShifts = shifts.filter(shift =>
294
+ new Date(shift.clockIn) >= oneWeekAgo && shift.clockOut
295
+ );
296
+
297
+ let weeklyMinutes = 0;
298
+ const uniqueDays = new Set();
299
+
300
+ weeklyShifts.forEach(shift => {
301
+ weeklyMinutes += (new Date(shift.clockOut) - new Date(shift.clockIn)) / (1000 * 60);
302
+ uniqueDays.add(new Date(shift.clockIn).toLocaleDateString());
303
+ });
304
+
305
+ const weeklyHours = Math.floor(weeklyMinutes / 60);
306
+ const weeklyMins = Math.floor(weeklyMinutes % 60);
307
+ document.getElementById('weekly-hours').textContent = `${weeklyHours}h ${weeklyMins}m`;
308
+ document.getElementById('weekly-days').textContent = uniqueDays.size;
309
+
310
+ // Earnings calculations
311
+ const hourlyRate = parseFloat(document.getElementById('hourly-rate').value) || 15.00;
312
+ document.getElementById('today-earnings').textContent = `$${(todayMinutes / 60 * hourlyRate).toFixed(2)}`;
313
+ document.getElementById('weekly-earnings').textContent = `$${(weeklyMinutes / 60 * hourlyRate).toFixed(2)}`;
314
+
315
+ // Update status
316
+ const statusElement = document.getElementById('today-status');
317
+ if (isClockedIn) {
318
+ statusElement.textContent = 'На смене';
319
+ statusElement.classList.remove('text-red-500');
320
+ statusElement.classList.add('text-green-500');
321
+ } else {
322
+ statusElement.textContent = 'Не на смене';
323
+ statusElement.classList.remove('text-green-500');
324
+ statusElement.classList.add('text-red-500');
325
+ }
326
+ }
327
+
328
+ // Update UI when clocked in/out
329
+ function updateClockInUI(clockedIn) {
330
+ const clockInBtn = document.getElementById('clock-in-btn');
331
+ const clockOutBtn = document.getElementById('clock-out-btn');
332
+
333
+ if (clockedIn) {
334
+ clockInBtn.disabled = true;
335
+ clockInBtn.classList.remove('bg-green-500', 'hover:bg-green-600', 'pulse-animation');
336
+ clockInBtn.classList.add('bg-gray-400', 'hover:bg-gray-500');
337
+
338
+ clockOutBtn.disabled = false;
339
+ clockOutBtn.classList.remove('opacity-50');
340
+
341
+ // Start tracking shift progress
342
+ updateShiftProgress();
343
+ setInterval(updateShiftProgress, 60000); // Update every minute
344
+ } else {
345
+ clockInBtn.disabled = false;
346
+ clockInBtn.classList.add('bg-green-500', 'hover:bg-green-600', 'pulse-animation');
347
+ clockInBtn.classList.remove('bg-gray-400', 'hover:bg-gray-500');
348
+
349
+ clockOutBtn.disabled = true;
350
+ clockOutBtn.classList.add('opacity-50');
351
+ }
352
+ }
353
+
354
+ // Update progress bar for current shift
355
+ function updateShiftProgress() {
356
+ if (!isClockedIn) return;
357
+
358
+ const workHours = parseFloat(document.getElementById('work-hours').value) || 8;
359
+ const clockInTime = new Date(currentShift.clockIn);
360
+ const now = new Date();
361
+ const elapsedHours = (now - clockInTime) / (1000 * 60 * 60);
362
+ const progressPercent = Math.min(100, (elapsedHours / workHours) * 100);
363
+
364
+ document.getElementById('progress-bar').style.width = `${progressPercent}%`;
365
+ document.getElementById('progress-text').textContent = `${progressPercent.toFixed(1)}%`;
366
+
367
+ // Change color based on progress
368
+ const progressBar = document.getElementById('progress-bar');
369
+ progressBar.classList.remove('bg-red-500', 'bg-yellow-500', 'bg-green-500');
370
+
371
+ if (progressPercent < 50) {
372
+ progressBar.classList.add('bg-red-500');
373
+ } else if (progressPercent < 90) {
374
+ progressBar.classList.add('bg-yellow-500');
375
+ } else {
376
+ progressBar.classList.add('bg-green-500');
377
+ }
378
+ }
379
+
380
+ // Clock In button click
381
+ document.getElementById('clock-in-btn').addEventListener('click', function() {
382
+ const now = new Date();
383
+ currentShift = {
384
+ clockIn: now.toISOString(),
385
+ clockOut: null
386
+ };
387
+
388
+ shifts.push(currentShift);
389
+ localStorage.setItem('shifts', JSON.stringify(shifts));
390
+
391
+ isClockedIn = true;
392
+ updateClockInUI(true);
393
+ populateShiftsTable();
394
+ });
395
+
396
+ // Clock Out button click
397
+ document.getElementById('clock-out-btn').addEventListener('click', function() {
398
+ if (!isClockedIn || !currentShift) return;
399
+
400
+ const now = new Date();
401
+ currentShift.clockOut = now.toISOString();
402
+
403
+ // Update in shifts array
404
+ const index = shifts.findIndex(s => s.clockIn === currentShift.clockIn && !s.clockOut);
405
+ if (index !== -1) {
406
+ shifts[index] = currentShift;
407
+ }
408
+
409
+ localStorage.setItem('shifts', JSON.stringify(shifts));
410
+
411
+ isClockedIn = false;
412
+ currentShift = null;
413
+ updateClockInUI(false);
414
+ populateShiftsTable();
415
+ });
416
+
417
+ // Save settings
418
+ document.getElementById('save-settings').addEventListener('click', function() {
419
+ const hourlyRate = document.getElementById('hourly-rate').value;
420
+ const workHours = document.getElementById('work-hours').value;
421
+
422
+ localStorage.setItem('hourlyRate', hourlyRate);
423
+ localStorage.setItem('workHours', workHours);
424
+
425
+ updateSummaryCards();
426
+
427
+ // Show confirmation
428
+ const button = this;
429
+ button.textContent = 'Сохранено!';
430
+ setTimeout(() => {
431
+ button.textContent = 'Сохранить';
432
+ }, 2000);
433
+ });
434
+
435
+ // Load saved settings
436
+ if (localStorage.getItem('hourlyRate')) {
437
+ document.getElementById('hourly-rate').value = localStorage.getItem('hourlyRate');
438
+ }
439
+ if (localStorage.getItem('workHours')) {
440
+ document.getElementById('work-hours').value = localStorage.getItem('workHours');
441
+ }
442
+
443
+ // Initialize the UI
444
+ populateShiftsTable();
445
+ });
446
+ </script>
447
+ </body>
448
  </html>