sergotsev commited on
Commit
871b5c9
·
verified ·
1 Parent(s): 581ea5a

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1417 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Calendar
3
- emoji: 🔥
4
- colorFrom: green
5
- colorTo: purple
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: calendar
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1417 @@
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">
6
+ <title>Smart Calendar</title>
7
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
8
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
9
+ <style>
10
+ :root {
11
+ /* Light theme */
12
+ --primary-color: #4285f4;
13
+ --secondary-color: #34a853;
14
+ --accent-color: #ea4335;
15
+ --background: #ffffff;
16
+ --surface: #f5f5f5;
17
+ --on-background: #212121;
18
+ --on-surface: #424242;
19
+ --border-color: #e0e0e0;
20
+ --card-shadow: 0 2px 10px rgba(0,0,0,0.1);
21
+ }
22
+
23
+ [data-theme="dark"] {
24
+ --primary-color: #8ab4f8;
25
+ --secondary-color: #81c995;
26
+ --accent-color: #f28b82;
27
+ --background: #121212;
28
+ --surface: #1e1e1e;
29
+ --on-background: #e0e0e0;
30
+ --on-surface: #b0b0b0;
31
+ --border-color: #333333;
32
+ --card-shadow: 0 2px 10px rgba(0,0,0,0.3);
33
+ }
34
+
35
+ * {
36
+ margin: 0;
37
+ padding: 0;
38
+ box-sizing: border-box;
39
+ transition: background-color 0.3s, color 0.3s;
40
+ }
41
+
42
+ body {
43
+ font-family: 'Roboto', sans-serif;
44
+ background-color: var(--background);
45
+ color: var(--on-background);
46
+ min-height: 100vh;
47
+ display: flex;
48
+ flex-direction: column;
49
+ }
50
+
51
+ header {
52
+ padding: 16px;
53
+ display: flex;
54
+ justify-content: space-between;
55
+ align-items: center;
56
+ background-color: var(--primary-color);
57
+ color: white;
58
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
59
+ }
60
+
61
+ .logo {
62
+ font-weight: 500;
63
+ font-size: 1.5rem;
64
+ }
65
+
66
+ .controls {
67
+ display: flex;
68
+ gap: 16px;
69
+ }
70
+
71
+ .icon-btn {
72
+ background: none;
73
+ border: none;
74
+ color: inherit;
75
+ cursor: pointer;
76
+ font-size: 1.2rem;
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ border-radius: 50%;
81
+ width: 40px;
82
+ height: 40px;
83
+ }
84
+
85
+ .icon-btn:hover {
86
+ background-color: rgba(255,255,255,0.1);
87
+ }
88
+
89
+ .tabs {
90
+ display: flex;
91
+ border-bottom: 1px solid var(--border-color);
92
+ background-color: var(--surface);
93
+ }
94
+
95
+ .tab {
96
+ flex: 1;
97
+ text-align: center;
98
+ padding: 16px;
99
+ cursor: pointer;
100
+ position: relative;
101
+ font-weight: 500;
102
+ color: var(--on-surface);
103
+ }
104
+
105
+ .tab.active {
106
+ color: var(--primary-color);
107
+ }
108
+
109
+ .tab.active::after {
110
+ content: '';
111
+ position: absolute;
112
+ bottom: -1px;
113
+ left: 0;
114
+ right: 0;
115
+ height: 3px;
116
+ background-color: var(--primary-color);
117
+ }
118
+
119
+ main {
120
+ flex: 1;
121
+ display: flex;
122
+ flex-direction: column;
123
+ overflow: hidden;
124
+ }
125
+
126
+ .calendar-header {
127
+ display: flex;
128
+ justify-content: space-between;
129
+ align-items: center;
130
+ padding: 16px;
131
+ background-color: var(--surface);
132
+ }
133
+
134
+ .month-year {
135
+ font-weight: 500;
136
+ font-size: 1.2rem;
137
+ }
138
+
139
+ .weekdays {
140
+ display: grid;
141
+ grid-template-columns: repeat(7, 1fr);
142
+ text-align: center;
143
+ padding: 8px 0;
144
+ background-color: var(--surface);
145
+ color: var(--on-surface);
146
+ font-weight: 500;
147
+ }
148
+
149
+ .days {
150
+ display: grid;
151
+ grid-template-columns: repeat(7, 1fr);
152
+ grid-auto-rows: minmax(60px, 1fr);
153
+ flex: 1;
154
+ }
155
+
156
+ .day {
157
+ border: 1px solid var(--border-color);
158
+ padding: 4px;
159
+ display: flex;
160
+ flex-direction: column;
161
+ cursor: pointer;
162
+ position: relative;
163
+ }
164
+
165
+ .day.inactive {
166
+ color: var(--on-surface);
167
+ opacity: 0.5;
168
+ }
169
+
170
+ .day-number {
171
+ align-self: flex-end;
172
+ padding: 2px 6px;
173
+ border-radius: 50%;
174
+ margin-bottom: 4px;
175
+ font-size: 0.9rem;
176
+ }
177
+
178
+ .day.today .day-number {
179
+ background-color: var(--primary-color);
180
+ color: white;
181
+ }
182
+
183
+ .event-dot {
184
+ width: 6px;
185
+ height: 6px;
186
+ border-radius: 50%;
187
+ margin: 1px auto;
188
+ }
189
+
190
+ .work {
191
+ background-color: #4285f4;
192
+ }
193
+
194
+ .home {
195
+ background-color: #34a853;
196
+ }
197
+
198
+ .hobby {
199
+ background-color: #ea4335;
200
+ }
201
+
202
+ .other {
203
+ background-color: #fbbc05;
204
+ }
205
+
206
+ .floating-btn {
207
+ position: fixed;
208
+ bottom: 24px;
209
+ right: 24px;
210
+ width: 56px;
211
+ height: 56px;
212
+ border-radius: 50%;
213
+ background-color: var(--primary-color);
214
+ color: white;
215
+ display: flex;
216
+ align-items: center;
217
+ justify-content: center;
218
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
219
+ cursor: pointer;
220
+ border: none;
221
+ z-index: 10;
222
+ }
223
+
224
+ .floating-btn .material-icons {
225
+ font-size: 24px;
226
+ }
227
+
228
+ .modal {
229
+ position: fixed;
230
+ top: 0;
231
+ left: 0;
232
+ right: 0;
233
+ bottom: 0;
234
+ background-color: rgba(0,0,0,0.5);
235
+ display: flex;
236
+ justify-content: center;
237
+ align-items: center;
238
+ z-index: 20;
239
+ opacity: 0;
240
+ pointer-events: none;
241
+ transition: opacity 0.3s;
242
+ }
243
+
244
+ .modal.active {
245
+ opacity: 1;
246
+ pointer-events: all;
247
+ }
248
+
249
+ .modal-content {
250
+ background-color: var(--background);
251
+ border-radius: 8px;
252
+ width: 90%;
253
+ max-width: 500px;
254
+ max-height: 90vh;
255
+ overflow-y: auto;
256
+ transform: translateY(20px);
257
+ transition: transform 0.3s;
258
+ }
259
+
260
+ .modal.active .modal-content {
261
+ transform: translateY(0);
262
+ }
263
+
264
+ .modal-header {
265
+ padding: 16px;
266
+ border-bottom: 1px solid var(--border-color);
267
+ display: flex;
268
+ justify-content: space-between;
269
+ align-items: center;
270
+ }
271
+
272
+ .modal-title {
273
+ font-weight: 500;
274
+ font-size: 1.2rem;
275
+ }
276
+
277
+ .modal-body {
278
+ padding: 16px;
279
+ }
280
+
281
+ .input-group {
282
+ margin-bottom: 16px;
283
+ }
284
+
285
+ .input-label {
286
+ display: block;
287
+ margin-bottom: 8px;
288
+ color: var(--on-surface);
289
+ font-size: 0.9rem;
290
+ }
291
+
292
+ .input-field {
293
+ width: 100%;
294
+ padding: 12px;
295
+ border: 1px solid var(--border-color);
296
+ border-radius: 4px;
297
+ background-color: var(--surface);
298
+ color: var(--on-background);
299
+ font-family: inherit;
300
+ }
301
+
302
+ .checkbox-group {
303
+ display: flex;
304
+ align-items: center;
305
+ margin-bottom: 8px;
306
+ }
307
+
308
+ .checkbox-label {
309
+ margin-left: 8px;
310
+ font-size: 0.9rem;
311
+ color: var(--on-surface);
312
+ }
313
+
314
+ .color-option {
315
+ display: inline-flex;
316
+ width: 24px;
317
+ height: 24px;
318
+ border-radius: 50%;
319
+ margin-right: 8px;
320
+ cursor: pointer;
321
+ position: relative;
322
+ }
323
+
324
+ .color-option.selected::after {
325
+ content: '✓';
326
+ position: absolute;
327
+ top: 50%;
328
+ left: 50%;
329
+ transform: translate(-50%, -50%);
330
+ color: white;
331
+ }
332
+
333
+ .modal-footer {
334
+ padding: 16px;
335
+ border-top: 1px solid var(--border-color);
336
+ display: flex;
337
+ justify-content: flex-end;
338
+ gap: 8px;
339
+ }
340
+
341
+ .btn {
342
+ padding: 10px 16px;
343
+ border-radius: 4px;
344
+ border: none;
345
+ font-weight: 500;
346
+ cursor: pointer;
347
+ font-family: inherit;
348
+ }
349
+
350
+ .btn-primary {
351
+ background-color: var(--primary-color);
352
+ color: white;
353
+ }
354
+
355
+ .btn-secondary {
356
+ background-color: var(--surface);
357
+ color: var(--on-surface);
358
+ }
359
+
360
+ .participants-list {
361
+ max-height: 150px;
362
+ overflow-y: auto;
363
+ border: 1px solid var(--border-color);
364
+ border-radius: 4px;
365
+ margin-top: 8px;
366
+ }
367
+
368
+ .participant {
369
+ display: flex;
370
+ align-items: center;
371
+ padding: 8px;
372
+ border-bottom: 1px solid var(--border-color);
373
+ }
374
+
375
+ .participant:last-child {
376
+ border-bottom: none;
377
+ }
378
+
379
+ .participant-avatar {
380
+ width: 32px;
381
+ height: 32px;
382
+ border-radius: 50%;
383
+ background-color: var(--primary-color);
384
+ color: white;
385
+ display: flex;
386
+ align-items: center;
387
+ justify-content: center;
388
+ margin-right: 8px;
389
+ font-size: 0.8rem;
390
+ }
391
+
392
+ .participant-name {
393
+ flex: 1;
394
+ font-size: 0.9rem;
395
+ }
396
+
397
+ .time-slots {
398
+ display: grid;
399
+ grid-template-columns: repeat(3, 1fr);
400
+ gap: 8px;
401
+ margin-top: 8px;
402
+ }
403
+
404
+ .time-slot {
405
+ padding: 8px;
406
+ border: 1px solid var(--border-color);
407
+ border-radius: 4px;
408
+ text-align: center;
409
+ cursor: pointer;
410
+ background-color: var(--surface);
411
+ font-size: 0.8rem;
412
+ }
413
+
414
+ .time-slot.selected {
415
+ background-color: var(--primary-color);
416
+ color: white;
417
+ border-color: var(--primary-color);
418
+ }
419
+
420
+ .time-slot.unavailable {
421
+ opacity: 0.5;
422
+ cursor: not-allowed;
423
+ }
424
+
425
+ .todo-item {
426
+ display: flex;
427
+ align-items: center;
428
+ padding: 8px 0;
429
+ border-bottom: 1px solid var(--border-color);
430
+ }
431
+
432
+ .todo-item:last-child {
433
+ border-bottom: none;
434
+ }
435
+
436
+ .todo-checkbox {
437
+ margin-right: 8px;
438
+ }
439
+
440
+ .todo-text {
441
+ flex: 1;
442
+ font-size: 0.9rem;
443
+ }
444
+
445
+ .add-todo {
446
+ display: flex;
447
+ margin-top: 8px;
448
+ }
449
+
450
+ .add-todo-input {
451
+ flex: 1;
452
+ padding: 8px;
453
+ border: 1px solid var(--border-color);
454
+ border-radius: 4px;
455
+ margin-right: 8px;
456
+ background-color: var(--surface);
457
+ color: var(--on-background);
458
+ }
459
+
460
+ .day-events {
461
+ flex: 1;
462
+ overflow-y: auto;
463
+ max-height: 120px;
464
+ margin-top: 4px;
465
+ padding-top: 4px;
466
+ border-top: 1px dashed var(--border-color);
467
+ }
468
+
469
+ .day-event {
470
+ font-size: 0.7rem;
471
+ padding: 2px 4px;
472
+ margin-bottom: 2px;
473
+ border-radius: 2px;
474
+ white-space: nowrap;
475
+ overflow: hidden;
476
+ text-overflow: ellipsis;
477
+ }
478
+
479
+ .day-event.work {
480
+ background-color: rgba(66, 133, 244, 0.1);
481
+ color: var(--primary-color);
482
+ }
483
+
484
+ .day-event.home {
485
+ background-color: rgba(52, 168, 83, 0.1);
486
+ color: var(--secondary-color);
487
+ }
488
+
489
+ .day-event.hobby {
490
+ background-color: rgba(234, 67, 53, 0.1);
491
+ color: var(--accent-color);
492
+ }
493
+
494
+ .day-event.other {
495
+ background-color: rgba(251, 188, 5, 0.1);
496
+ color: #fbbc05;
497
+ }
498
+
499
+ .mic-animation {
500
+ position: relative;
501
+ width: 24px;
502
+ height: 24px;
503
+ }
504
+
505
+ .mic-icon {
506
+ position: absolute;
507
+ font-size: 24px;
508
+ color: white;
509
+ animation: pulse 2s infinite;
510
+ }
511
+
512
+ @keyframes pulse {
513
+ 0% { transform: scale(1); }
514
+ 50% { transform: scale(1.1); }
515
+ 100% { transform: scale(1); }
516
+ }
517
+
518
+ .loading {
519
+ display: inline-block;
520
+ width: 20px;
521
+ height: 20px;
522
+ border: 3px solid rgba(255,255,255,.3);
523
+ border-radius: 50%;
524
+ border-top-color: white;
525
+ animation: spin 1s ease-in-out infinite;
526
+ }
527
+
528
+ @keyframes spin {
529
+ to { transform: rotate(360deg); }
530
+ }
531
+
532
+ @media (max-width: 600px) {
533
+ .time-slots {
534
+ grid-template-columns: repeat(2, 1fr);
535
+ }
536
+
537
+ .day-number {
538
+ font-size: 0.8rem;
539
+ }
540
+
541
+ .event-dot {
542
+ width: 5px;
543
+ height: 5px;
544
+ }
545
+ }
546
+
547
+ /* Animation classes */
548
+ .slide-in-right {
549
+ animation: slideInRight 0.3s forwards;
550
+ }
551
+
552
+ @keyframes slideInRight {
553
+ from { transform: translateX(100%); opacity: 0; }
554
+ to { transform: translateX(0); opacity: 1; }
555
+ }
556
+
557
+ .fade-in {
558
+ animation: fadeIn 0.3s forwards;
559
+ }
560
+
561
+ @keyframes fadeIn {
562
+ from { opacity: 0; }
563
+ to { opacity: 1; }
564
+ }
565
+ </style>
566
+ </head>
567
+ <body>
568
+ <header>
569
+ <div class="logo">Smart Calendar</div>
570
+ <div class="controls">
571
+ <button class="icon-btn" id="theme-toggle">
572
+ <span class="material-icons">brightness_6</span>
573
+ </button>
574
+ <button class="icon-btn" id="search-btn">
575
+ <span class="material-icons">search</span>
576
+ </button>
577
+ </div>
578
+ </header>
579
+
580
+ <main>
581
+ <div class="tabs">
582
+ <div class="tab active" data-tab="personal">Личное</div>
583
+ <div class="tab" data-tab="team">Совместное</div>
584
+ </div>
585
+
586
+ <div class="calendar-header">
587
+ <button class="icon-btn" id="prev-month">
588
+ <span class="material-icons">chevron_left</span>
589
+ </button>
590
+ <div class="month-year" id="month-year">Июнь 2023</div>
591
+ <button class="icon-btn" id="next-month">
592
+ <span class="material-icons">chevron_right</span>
593
+ </button>
594
+ </div>
595
+
596
+ <div class="weekdays">
597
+ <div>Пн</div>
598
+ <div>Вт</div>
599
+ <div>Ср</div>
600
+ <div>Чт</div>
601
+ <div>Пт</div>
602
+ <div>Сб</div>
603
+ <div>Вс</div>
604
+ </div>
605
+
606
+ <div class="days" id="calendar-days">
607
+ <!-- Calendar days will be generated by JavaScript -->
608
+ </div>
609
+ </main>
610
+
611
+ <button class="floating-btn" id="add-event-btn">
612
+ <span class="material-icons">add</span>
613
+ </button>
614
+
615
+ <!-- Add Event Modal -->
616
+ <div class="modal" id="event-modal">
617
+ <div class="modal-content">
618
+ <div class="modal-header">
619
+ <div class="modal-title">Новое событие</div>
620
+ <button class="icon-btn close-modal">
621
+ <span class="material-icons">close</span>
622
+ </button>
623
+ </div>
624
+ <div class="modal-body">
625
+ <div class="input-group">
626
+ <label class="input-label">Название</label>
627
+ <input type="text" class="input-field" id="event-title" placeholder="Введите название">
628
+ </div>
629
+
630
+ <div class="input-group">
631
+ <label class="input-label">Дата и время</label>
632
+ <input type="datetime-local" class="input-field" id="event-datetime">
633
+ </div>
634
+
635
+ <div class="input-group">
636
+ <label class="input-label">Категория</label>
637
+ <div>
638
+ <div class="color-option work selected" data-category="work" title="Работа"></div>
639
+ <div class="color-option home" data-category="home" title="Дом"></div>
640
+ <div class="color-option hobby" data-category="hobby" title="Хобби"></div>
641
+ <div class="color-option other" data-category="other" title="Другое"></div>
642
+ </div>
643
+ </div>
644
+
645
+ <div class="input-group">
646
+ <label class="input-label">Место</label>
647
+ <input type="text" class="input-field" id="event-location" placeholder="Место встречи">
648
+ </div>
649
+
650
+ <div class="input-group">
651
+ <label class="input-label">Напоминание</label>
652
+ <select class="input-field" id="event-reminder">
653
+ <option value="none">Нет</option>
654
+ <option value="15">15 минут до</option>
655
+ <option value="30">30 минут до</option>
656
+ <option value="60">1 час до</option>
657
+ <option value="1440">1 день до</option>
658
+ </select>
659
+ </div>
660
+
661
+ <div class="input-group">
662
+ <label class="input-label">Описание</label>
663
+ <textarea class="input-field" id="event-description" rows="3" placeholder="Дополнительные детали"></textarea>
664
+ </div>
665
+ </div>
666
+ <div class="modal-footer">
667
+ <button class="btn btn-secondary close-modal">Отмена</button>
668
+ <button class="btn btn-primary" id="save-event">Сохранить</button>
669
+ </div>
670
+ </div>
671
+ </div>
672
+
673
+ <!-- Meeting Modal -->
674
+ <div class="modal" id="meeting-modal">
675
+ <div class="modal-content">
676
+ <div class="modal-header">
677
+ <div class="modal-title">Планирование встречи</div>
678
+ <button class="icon-btn close-modal">
679
+ <span class="material-icons">close</span>
680
+ </button>
681
+ </div>
682
+ <div class="modal-body">
683
+ <div class="input-group">
684
+ <label class="input-label">Название встречи</label>
685
+ <input type="text" class="input-field" id="meeting-title" placeholder="Введите название">
686
+ </div>
687
+
688
+ <div class="input-group">
689
+ <label class="input-label">Участники</label>
690
+ <div class="participants-list" id="participants-list">
691
+ <div class="participant">
692
+ <div class="participant-avatar">ИИ</div>
693
+ <div class="participant-name">Иван Иванов</div>
694
+ <button class="icon-btn remove-participant">
695
+ <span class="material-icons">close</span>
696
+ </button>
697
+ </div>
698
+ <div class="participant">
699
+ <div class="participant-avatar">ПП</div>
700
+ <div class="participant-name">Петр Петров</div>
701
+ <button class="icon-btn remove-participant">
702
+ <span class="material-icons">close</span>
703
+ </button>
704
+ </div>
705
+ </div>
706
+ <button class="btn btn-secondary" id="add-participant" style="margin-top: 8px; width: 100%;">
707
+ <span class="material-icons" style="font-size: 1rem;">person_add</span> Добавить участника
708
+ </button>
709
+ </div>
710
+
711
+ <div class="input-group">
712
+ <label class="input-label">Дата</label>
713
+ <input type="date" class="input-field" id="meeting-date">
714
+ </div>
715
+
716
+ <div class="input-group">
717
+ <label class="input-label">Доступные слоты</label>
718
+ <div class="time-slots" id="time-slots">
719
+ <div class="time-slot">09:00 - 10:00</div>
720
+ <div class="time-slot">10:00 - 11:00</div>
721
+ <div class="time-slot unavailable">11:00 - 12:00</div>
722
+ <div class="time-slot">12:00 - 13:00</div>
723
+ <div class="time-slot selected">13:00 - 14:00</div>
724
+ <div class="time-slot">14:00 - 15:00</div>
725
+ <div class="time-slot">15:00 - 16:00</div>
726
+ <div class="time-slot">16:00 - 17:00</div>
727
+ <div class="time-slot unavailable">17:00 - 18:00</div>
728
+ </div>
729
+ </div>
730
+
731
+ <div class="input-group">
732
+ <label class="input-label">Место</label>
733
+ <input type="text" class="input-field" id="meeting-location" placeholder="Место встречи">
734
+ </div>
735
+
736
+ <div class="input-group">
737
+ <label class="input-label">Описание</label>
738
+ <textarea class="input-field" id="meeting-description" rows="3" placeholder="Цель встречи"></textarea>
739
+ </div>
740
+ </div>
741
+ <div class="modal-footer">
742
+ <button class="btn btn-secondary close-modal">Отмена</button>
743
+ <button class="btn btn-primary" id="send-invites">
744
+ <span class="material-icons" style="font-size: 1rem; vertical-align: middle;">send</span> Отправить приглашения
745
+ </button>
746
+ </div>
747
+ </div>
748
+ </div>
749
+
750
+ <!-- Voice Input Modal -->
751
+ <div class="modal" id="voice-modal">
752
+ <div class="modal-content">
753
+ <div class="modal-header">
754
+ <div class="modal-title">Голосовой ввод</div>
755
+ <button class="icon-btn close-modal">
756
+ <span class="material-icons">close</span>
757
+ </button>
758
+ </div>
759
+ <div class="modal-body" style="text-align: center; padding: 40px;">
760
+ <div class="mic-animation">
761
+ <span class="material-icons mic-icon">mic</span>
762
+ </div>
763
+ <p style="margin-top: 20px; color: var(--on-surface);">Говорите сейчас...</p>
764
+ <div id="voice-text" style="margin-top: 20px; padding: 10px; border: 1px dashed var(--border-color); border-radius: 4px; min-height: 50px;"></div>
765
+ </div>
766
+ <div class="modal-footer">
767
+ <button class="btn btn-secondary" id="stop-recording">
768
+ <span class="material-icons" style="font-size: 1rem; vertical-align: middle;">stop</span> Остановить
769
+ </button>
770
+ <button class="btn btn-primary" id="use-voice-input">
771
+ <span class="material-icons" style="font-size: 1rem; vertical-align: middle;">check</span> Использовать
772
+ </button>
773
+ </div>
774
+ </div>
775
+ </div>
776
+
777
+ <!-- Add Participant Modal -->
778
+ <div class="modal" id="participant-modal">
779
+ <div class="modal-content">
780
+ <div class="modal-header">
781
+ <div class="modal-title">Добавить участника</div>
782
+ <button class="icon-btn close-modal">
783
+ <span class="material-icons">close</span>
784
+ </button>
785
+ </div>
786
+ <div class="modal-body">
787
+ <div class="input-group">
788
+ <label class="input-label">Поиск контактов</label>
789
+ <input type="text" class="input-field" id="search-contact" placeholder="Имя или номер телефона">
790
+ </div>
791
+
792
+ <div class="input-group">
793
+ <label class="input-label">Контакты</label>
794
+ <div class="participants-list" id="contacts-list">
795
+ <div class="participant">
796
+ <div class="participant-avatar">СС</div>
797
+ <div class="participant-name">Сергей Сергеев</div>
798
+ <button class="btn btn-primary add-contact" style="padding: 4px 8px; font-size: 0.8rem;">
799
+ <span class="material-icons" style="font-size: 1rem;">add</span>
800
+ </button>
801
+ </div>
802
+ <div class="participant">
803
+ <div class="participant-avatar">АА</div>
804
+ <div class="participant-name">Анна Андреева</div>
805
+ <button class="btn btn-primary add-contact" style="padding: 4px 8px; font-size: 0.8rem;">
806
+ <span class="material-icons" style="font-size: 1rem;">add</span>
807
+ </button>
808
+ </div>
809
+ <div class="participant">
810
+ <div class="participant-avatar">ММ</div>
811
+ <div class="participant-name">Мария Михайлова</div>
812
+ <button class="btn btn-primary add-contact" style="padding: 4px 8px; font-size: 0.8rem;">
813
+ <span class="material-icons" style="font-size: 1rem;">add</span>
814
+ </button>
815
+ </div>
816
+ <div class="participant">
817
+ <div class="participant-avatar">ДП</div>
818
+ <div class="participant-name">Дмитрий Павлов</div>
819
+ <button class="btn btn-primary add-contact" style="padding: 4px 8px; font-size: 0.8rem;">
820
+ <span class="material-icons" style="font-size: 1rem;">add</span>
821
+ </button>
822
+ </div>
823
+ </div>
824
+ </div>
825
+ </div>
826
+ <div class="modal-footer">
827
+ <button class="btn btn-secondary close-modal">Отмена</button>
828
+ <button class="btn btn-primary" id="confirm-participants">Готово</button>
829
+ </div>
830
+ </div>
831
+ </div>
832
+
833
+ <!-- Event Details Modal -->
834
+ <div class="modal" id="details-modal">
835
+ <div class="modal-content">
836
+ <div class="modal-header">
837
+ <div class="modal-title">Детали события</div>
838
+ <button class="icon-btn close-modal">
839
+ <span class="material-icons">close</span>
840
+ </button>
841
+ </div>
842
+ <div class="modal-body">
843
+ <div style="margin-bottom: 16px;">
844
+ <div style="font-size: 1.2rem; font-weight: 500; margin-bottom: 4px;" id="event-detail-title">Встреча с командой</div>
845
+ <div style="display: flex; align-items: center; color: var(--on-surface); margin-bottom: 8px;">
846
+ <span class="material-icons" style="font-size: 1rem; margin-right: 4px;">schedule</span>
847
+ <span id="event-detail-time">15 июня, 14:00 - 15:30</span>
848
+ </div>
849
+ <div style="display: flex; align-items: center; color: var(--on-surface);">
850
+ <span class="material-icons" style="font-size: 1rem; margin-right: 4px;">location_on</span>
851
+ <span id="event-detail-location">Офис, переговорная 3</span>
852
+ </div>
853
+ <div style="margin-top: 8px;">
854
+ <span class="day-event work" style="display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 0.7rem;">Работа</span>
855
+ </div>
856
+ </div>
857
+
858
+ <div style="margin-bottom: 16px; border-top: 1px solid var(--border-color); padding-top: 16px;">
859
+ <div style="font-size: 0.9rem; color: var(--on-surface);" id="event-detail-description">
860
+ Обсуждение нового проекта и распределение задач между участниками команды.
861
+ </div>
862
+ </div>
863
+
864
+ <div style="margin-bottom: 16px; border-top: 1px solid var(--border-color); padding-top: 16px;">
865
+ <div style="font-weight: 500; margin-bottom: 8px;">Чек-лист</div>
866
+ <div class="todo-item">
867
+ <input type="checkbox" class="todo-checkbox" id="todo1" checked>
868
+ <label for="todo1" class="todo-text" style="text-decoration: line-through;">Подготовить презентацию</label>
869
+ </div>
870
+ <div class="todo-item">
871
+ <input type="checkbox" class="todo-checkbox" id="todo2">
872
+ <label for="todo2" class="todo-text">Отправить план проекта</label>
873
+ </div>
874
+ <div class="todo-item">
875
+ <input type="checkbox" class="todo-checkbox" id="todo3">
876
+ <label for="todo3" class="todo-text">Обновить бюджет</label>
877
+ </div>
878
+ <div class="add-todo">
879
+ <input type="text" class="add-todo-input" placeholder="Добавить новую задачу">
880
+ <button class="btn btn-primary" style="padding: 8px;">
881
+ <span class="material-icons" style="font-size: 1rem;">add</span>
882
+ </button>
883
+ </div>
884
+ </div>
885
+ </div>
886
+ <div class="modal-footer">
887
+ <button class="btn btn-secondary" id="edit-event">
888
+ <span class="material-icons" style="font-size: 1rem; vertical-align: middle;">edit</span> Редактировать
889
+ </button>
890
+ <button class="btn btn-primary" id="share-event">
891
+ <span class="material-icons" style="font-size: 1rem; vertical-align: middle;">share</span> Поделиться
892
+ </button>
893
+ </div>
894
+ </div>
895
+ </div>
896
+
897
+ <script>
898
+ document.addEventListener('DOMContentLoaded', function() {
899
+ // Current date
900
+ let currentDate = new Date();
901
+ let currentMonth = currentDate.getMonth();
902
+ let currentYear = currentDate.getFullYear();
903
+
904
+ // Sample events data
905
+ let events = [
906
+ { id: 1, title: 'Совещание', date: new Date(currentYear, currentMonth, 10, 14, 0), category: 'work', location: 'Офис', reminder: '30' },
907
+ { id: 2, title: 'Покупки', date: new Date(currentYear, currentMonth, 15, 18, 0), category: 'home', location: 'ТЦ', reminder: '60' },
908
+ { id: 3, title: 'Тренировка', date: new Date(currentYear, currentMonth, 20, 9, 0), category: 'hobby', reminder: '15' },
909
+ { id: 4, title: 'Встреча с другом', date: new Date(currentYear, currentMonth, 5, 12, 0), category: 'other' },
910
+ { id: 5, title: 'Доклад', date: new Date(currentYear, currentMonth, 7, 11, 0), category: 'work', location: 'Конференц-зал' },
911
+ { id: 6, title: 'Ремонт', date: new Date(currentYear, currentMonth, 12, 8, 0), category: 'home', reminder: '1440' },
912
+ { id: 7, title: 'Фотосессия', date: new Date(currentYear, currentMonth, 18, 16, 0), category: 'hobby', location: 'Студия' },
913
+ { id: 8, title: 'Врач', date: new Date(currentYear, currentMonth, 22, 10, 0), category: 'other', reminder: '30' },
914
+ { id: 9, title: 'Презентация', date: new Date(currentYear, currentMonth, 25, 13, 0), category: 'work', location: 'Клиентский офис' },
915
+ { id: 10, title: 'Генеральная уборка', date: new Date(currentYear, currentMonth, 28, 9, 0), category: 'home' }
916
+ ];
917
+
918
+ // Sample meeting data
919
+ let sampleMeeting = {
920
+ title: 'Обсуждение проекта',
921
+ date: new Date(currentYear, currentMonth, 15, 14, 0),
922
+ participants: [
923
+ { name: 'Иван Иванов', initials: 'ИИ' },
924
+ { name: 'Петр Петров', initials: 'ПП' }
925
+ ],
926
+ location: 'Переговорная 3',
927
+ description: 'Обсуждение нового проекта и распределение задач'
928
+ };
929
+
930
+ // UI Elements
931
+ const monthYearElement = document.getElementById('month-year');
932
+ const calendarDays = document.getElementById('calendar-days');
933
+ const prevMonthButton = document.getElementById('prev-month');
934
+ const nextMonthButton = document.getElementById('next-month');
935
+ const addEventButton = document.getElementById('add-event-btn');
936
+ const tabs = document.querySelectorAll('.tab');
937
+
938
+ // Modals
939
+ const eventModal = document.getElementById('event-modal');
940
+ const meetingModal = document.getElementById('meeting-modal');
941
+ const voiceModal = document.getElementById('voice-modal');
942
+ const participantModal = document.getElementById('participant-modal');
943
+ const detailsModal = document.getElementById('details-modal');
944
+ const allModals = document.querySelectorAll('.modal');
945
+
946
+ // Close buttons
947
+ const closeModalButtons = document.querySelectorAll('.close-modal');
948
+
949
+ // Event form elements
950
+ const eventTitle = document.getElementById('event-title');
951
+ const eventDatetime = document.getElementById('event-datetime');
952
+ const eventLocation = document.getElementById('event-location');
953
+ const eventReminder = document.getElementById('event-reminder');
954
+ const eventDescription = document.getElementById('event-description');
955
+ const saveEventButton = document.getElementById('save-event');
956
+
957
+ // Meeting form elements
958
+ const meetingTitle = document.getElementById('meeting-title');
959
+ const meetingDate = document.getElementById('meeting-date');
960
+ const meetingLocation = document.getElementById('meeting-location');
961
+ const meetingDescription = document.getElementById('meeting-description');
962
+ const participantsList = document.getElementById('participants-list');
963
+ const addParticipantButton = document.getElementById('add-participant');
964
+ const sendInvitesButton = document.getElementById('send-invites');
965
+
966
+ // Voice input elements
967
+ const voiceText = document.getElementById('voice-text');
968
+ const stopRecordingButton = document.getElementById('stop-recording');
969
+ const useVoiceInputButton = document.getElementById('use-voice-input');
970
+
971
+ // Participant modal elements
972
+ const searchContact = document.getElementById('search-contact');
973
+ const contactsList = document.getElementById('contacts-list');
974
+ const confirmParticipantsButton = document.getElementById('confirm-participants');
975
+
976
+ // Details modal elements
977
+ const editEventButton = document.getElementById('edit-event');
978
+ const shareEventButton = document.getElementById('share-event');
979
+
980
+ // Theme toggle
981
+ const themeToggle = document.getElementById('theme-toggle');
982
+
983
+ // Initialize the calendar
984
+ function initCalendar() {
985
+ updateCalendar();
986
+
987
+ // Add event listeners
988
+ prevMonthButton.addEventListener('click', () => {
989
+ currentMonth--;
990
+ if (currentMonth < 0) {
991
+ currentMonth = 11;
992
+ currentYear--;
993
+ }
994
+ updateCalendar();
995
+ });
996
+
997
+ nextMonthButton.addEventListener('click', () => {
998
+ currentMonth++;
999
+ if (currentMonth > 11) {
1000
+ currentMonth = 0;
1001
+ currentYear++;
1002
+ }
1003
+ updateCalendar();
1004
+ });
1005
+
1006
+ addEventButton.addEventListener('click', () => {
1007
+ const now = new Date();
1008
+ const defaultDate = new Date(now.getTime() + 60 * 60 * 1000); // 1 hour from now
1009
+ defaultDate.setMinutes(0, 0, 0);
1010
+
1011
+ // Set default values
1012
+ eventTitle.value = '';
1013
+ eventDatetime.value = formatDatetimeInput(defaultDate);
1014
+ eventLocation.value = '';
1015
+ eventReminder.value = 'none';
1016
+ eventDescription.value = '';
1017
+
1018
+ // Reset category selection
1019
+ document.querySelectorAll('.color-option').forEach(option => {
1020
+ option.classList.remove('selected');
1021
+ });
1022
+ document.querySelector('.color-option[data-category="work"]').classList.add('selected');
1023
+
1024
+ // Select the personal tab when adding event
1025
+ document.querySelector('.tab[data-tab="personal"]').click();
1026
+
1027
+ showModal(eventModal);
1028
+ });
1029
+
1030
+ // Tab switching
1031
+ tabs.forEach(tab => {
1032
+ tab.addEventListener('click', () => {
1033
+ tabs.forEach(t => t.classList.remove('active'));
1034
+ tab.classList.add('active');
1035
+
1036
+ // Here you would normally filter events based on tab
1037
+ updateCalendar();
1038
+ });
1039
+ });
1040
+
1041
+ // Category selection
1042
+ document.querySelectorAll('.color-option').forEach(option => {
1043
+ option.addEventListener('click', () => {
1044
+ document.querySelectorAll('.color-option').forEach(opt => {
1045
+ opt.classList.remove('selected');
1046
+ });
1047
+ option.classList.add('selected');
1048
+ });
1049
+ });
1050
+
1051
+ // Save event
1052
+ saveEventButton.addEventListener('click', () => {
1053
+ const title = eventTitle.value.trim();
1054
+ if (!title) {
1055
+ alert('Пожалуйста, введите название события');
1056
+ return;
1057
+ }
1058
+
1059
+ const datetime = eventDatetime.value;
1060
+ if (!datetime) {
1061
+ alert('Пожалуйста, укажите дату и время');
1062
+ return;
1063
+ }
1064
+
1065
+ const selectedCategory = document.querySelector('.color-option.selected').dataset.category;
1066
+
1067
+ const eventDate = new Date(datetime);
1068
+ if (isNaN(eventDate.getTime())) {
1069
+ alert('Неверная дата и время');
1070
+ return;
1071
+ }
1072
+
1073
+ const newEvent = {
1074
+ id: events.length + 1,
1075
+ title: title,
1076
+ date: eventDate,
1077
+ category: selectedCategory,
1078
+ location: eventLocation.value.trim(),
1079
+ reminder: eventReminder.value,
1080
+ description: eventDescription.value.trim()
1081
+ };
1082
+
1083
+ events.push(newEvent);
1084
+ hideModal(eventModal);
1085
+ updateCalendar();
1086
+ });
1087
+
1088
+ // Show meeting modal
1089
+ document.getElementById('team').addEventListener('click', () => {
1090
+ meetingTitle.value = sampleMeeting.title;
1091
+ meetingDate.value = formatDateInput(sampleMeeting.date);
1092
+ meetingLocation.value = sampleMeeting.location;
1093
+ meetingDescription.value = sampleMeeting.description;
1094
+
1095
+ // Populate participants
1096
+ participantsList.innerHTML = '';
1097
+ sampleMeeting.participants.forEach(participant => {
1098
+ participantsList.appendChild(createParticipantElement(participant.name, participant.initials));
1099
+ });
1100
+
1101
+ showModal(meetingModal);
1102
+ });
1103
+
1104
+ // Add participant button
1105
+ addParticipantButton.addEventListener('click', () => {
1106
+ showModal(participantModal);
1107
+ });
1108
+
1109
+ // Send invites button
1110
+ sendInvitesButton.addEventListener('click', () => {
1111
+ sendInvitesButton.innerHTML = '<span class="loading"></span> Отправка...';
1112
+ sendInvitesButton.disabled = true;
1113
+
1114
+ setTimeout(() => {
1115
+ hideModal(meetingModal);
1116
+ sendInvitesButton.innerHTML = '<span class="material-icons" style="font-size: 1rem; vertical-align: middle;">send</span> Отправить приглашения';
1117
+ sendInvitesButton.disabled = false;
1118
+ alert('Приглашения успешно отправлены!');
1119
+ }, 1500);
1120
+ });
1121
+
1122
+ // Time slot selection
1123
+ document.querySelectorAll('.time-slot:not(.unavailable)').forEach(slot => {
1124
+ slot.addEventListener('click', () => {
1125
+ document.querySelectorAll('.time-slot').forEach(s => {
1126
+ s.classList.remove('selected');
1127
+ });
1128
+ slot.classList.add('selected');
1129
+ });
1130
+ });
1131
+
1132
+ // Voice recording simulation
1133
+ document.querySelector('.color-option[data-category="work"]').addEventListener('dblclick', () => {
1134
+ showModal(voiceModal);
1135
+ voiceText.innerHTML = '';
1136
+
1137
+ // Simulate voice recognition
1138
+ setTimeout(() => {
1139
+ voiceText.innerHTML = 'Встреча с командой проекта завтра в 14:00 в главном офисе';
1140
+ }, 2000);
1141
+ });
1142
+
1143
+ stopRecordingButton.addEventListener('click', () => {
1144
+ hideModal(voiceModal);
1145
+ });
1146
+
1147
+ useVoiceInputButton.addEventListener('click', () => {
1148
+ eventTitle.value = 'Встреча с командой проекта';
1149
+ eventDatetime.value = formatDatetimeInput(new Date(new Date().getTime() + 24 * 60 * 60 * 1000).setHours(14, 0, 0, 0));
1150
+ eventLocation.value = 'Главный офис';
1151
+
1152
+ document.querySelectorAll('.color-option').forEach(opt => {
1153
+ opt.classList.remove('selected');
1154
+ });
1155
+ document.querySelector('.color-option[data-category="work"]').classList.add('selected');
1156
+
1157
+ hideModal(voiceModal);
1158
+ });
1159
+
1160
+ // Add contact
1161
+ document.querySelectorAll('.add-contact').forEach(btn => {
1162
+ btn.addEventListener('click', (e) => {
1163
+ const participantElement = e.target.closest('.participant');
1164
+ const name = participantElement.querySelector('.participant-name').textContent;
1165
+ const initials = participantElement.querySelector('.participant-avatar').textContent;
1166
+
1167
+ participantsList.appendChild(createParticipantElement(name, initials));
1168
+ hideModal(participantModal);
1169
+ });
1170
+ });
1171
+
1172
+ // Close modal buttons
1173
+ closeModalButtons.forEach(btn => {
1174
+ btn.addEventListener('click', () => {
1175
+ hideModal(btn.closest('.modal'));
1176
+ });
1177
+ });
1178
+
1179
+ // Theme toggle
1180
+ themeToggle.addEventListener('click', () => {
1181
+ if (document.body.hasAttribute('data-theme')) {
1182
+ document.body.removeAttribute('data-theme');
1183
+ themeToggle.innerHTML = '<span class="material-icons">brightness_6</span>';
1184
+ } else {
1185
+ document.body.setAttribute('data-theme', 'dark');
1186
+ themeToggle.innerHTML = '<span class="material-icons">brightness_5</span>';
1187
+ }
1188
+ });
1189
+ }
1190
+
1191
+ // Update calendar view
1192
+ function updateCalendar() {
1193
+ const firstDay = new Date(currentYear, currentMonth, 1);
1194
+ const lastDay = new Date(currentYear, currentMonth + 1, 0);
1195
+ const startDay = firstDay.getDay() === 0 ? 6 : firstDay.getDay() - 1; // Adjust so Monday is first
1196
+ const totalDays = lastDay.getDate();
1197
+
1198
+ // Previous month days
1199
+ const prevMonthLastDay = new Date(currentYear, currentMonth, 0).getDate();
1200
+
1201
+ // Next month days
1202
+ const daysFromNextMonth = (7 - (startDay + totalDays) % 7) % 7;
1203
+
1204
+ // Update month and year display
1205
+ const months = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
1206
+ monthYearElement.textContent = `${months[currentMonth]} ${currentYear}`;
1207
+
1208
+ // Clear calendar
1209
+ calendarDays.innerHTML = '';
1210
+
1211
+ // Add days from previous month
1212
+ for (let i = startDay - 1; i >= 0; i--) {
1213
+ const day = createDayElement(prevMonthLastDay - i, true);
1214
+ calendarDays.appendChild(day);
1215
+ }
1216
+
1217
+ // Add days from current month
1218
+ for (let i = 1; i <= totalDays; i++) {
1219
+ const day = createDayElement(i, false);
1220
+
1221
+ // Mark today
1222
+ const today = new Date();
1223
+ if (i === today.getDate() && currentMonth === today.getMonth() && currentYear === today.getFullYear()) {
1224
+ day.classList.add('today');
1225
+ }
1226
+
1227
+ // Add events for this day
1228
+ const dayEvents = events.filter(event =>
1229
+ event.date.getDate() === i &&
1230
+ event.date.getMonth() === currentMonth &&
1231
+ event.date.getFullYear() === currentYear
1232
+ );
1233
+
1234
+ if (dayEvents.length > 0) {
1235
+ const eventDots = document.createElement('div');
1236
+ dayEvents.forEach(event => {
1237
+ const dot = document.createElement('div');
1238
+ dot.className = `event-dot ${event.category}`;
1239
+ eventDots.appendChild(dot);
1240
+ });
1241
+ day.appendChild(eventDots);
1242
+
1243
+ // For day view (details modal)
1244
+ if (dayEvents.length > 0) {
1245
+ const dayEventsContainer = document.createElement('div');
1246
+ dayEventsContainer.className = 'day-events';
1247
+
1248
+ dayEvents.slice(0, 3).forEach(event => {
1249
+ const eventElement = document.createElement('div');
1250
+ eventElement.className = `day-event ${event.category}`;
1251
+ eventElement.textContent = event.title;
1252
+ dayEventsContainer.appendChild(eventElement);
1253
+ });
1254
+
1255
+ if (dayEvents.length > 3) {
1256
+ const moreEvents = document.createElement('div');
1257
+ moreEvents.className = 'day-event other';
1258
+ moreEvents.textContent = `+${dayEvents.length - 3} ещё`;
1259
+ dayEventsContainer.appendChild(moreEvents);
1260
+ }
1261
+
1262
+ day.appendChild(dayEventsContainer);
1263
+ }
1264
+ }
1265
+
1266
+ // Add click event for details
1267
+ day.addEventListener('click', () => {
1268
+ if (dayEvents.length > 0) {
1269
+ const event = dayEvents[0]; // Show first event for simplicity
1270
+
1271
+ // Set details
1272
+ document.getElementById('event-detail-title').textContent = event.title;
1273
+
1274
+ const endTime = new Date(event.date);
1275
+ endTime.setHours(endTime.getHours() + 1);
1276
+
1277
+ document.getElementById('event-detail-time').textContent = formatDateTimeRange(event.date, endTime);
1278
+ document.getElementById('event-detail-location').textContent = event.location || 'Место не указано';
1279
+ document.getElementById('event-detail-description').textContent = event.description || 'Описание отсутствует';
1280
+
1281
+ showModal(detailsModal);
1282
+ }
1283
+ });
1284
+
1285
+ calendarDays.appendChild(day);
1286
+ }
1287
+
1288
+ // Add days from next month
1289
+ for (let i = 1; i <= daysFromNextMonth; i++) {
1290
+ const day = createDayElement(i, true);
1291
+ calendarDays.appendChild(day);
1292
+ }
1293
+ }
1294
+
1295
+ // Helper functions
1296
+ function createDayElement(dayNumber, inactive) {
1297
+ const day = document.createElement('div');
1298
+ day.className = 'day';
1299
+ if (inactive) day.classList.add('inactive');
1300
+
1301
+ const dayNum = document.createElement('div');
1302
+ dayNum.className = 'day-number';
1303
+ dayNum.textContent = dayNumber;
1304
+ day.appendChild(dayNum);
1305
+
1306
+ return day;
1307
+ }
1308
+
1309
+ function createParticipantElement(name, initials) {
1310
+ const participant = document.createElement('div');
1311
+ participant.className = 'participant';
1312
+
1313
+ const avatar = document.createElement('div');
1314
+ avatar.className = 'participant-avatar';
1315
+ avatar.textContent = initials;
1316
+
1317
+ const nameElement = document.createElement('div');
1318
+ nameElement.className = 'participant-name';
1319
+ nameElement.textContent = name;
1320
+
1321
+ const removeBtn = document.createElement('button');
1322
+ removeBtn.className = 'icon-btn remove-participant';
1323
+ removeBtn.innerHTML = '<span class="material-icons">close</span>';
1324
+ removeBtn.addEventListener('click', () => {
1325
+ participant.remove();
1326
+ });
1327
+
1328
+ participant.appendChild(avatar);
1329
+ participant.appendChild(nameElement);
1330
+ participant.appendChild(removeBtn);
1331
+
1332
+ return participant;
1333
+ }
1334
+
1335
+ function formatDatetimeInput(date) {
1336
+ const d = new Date(date);
1337
+ const year = d.getFullYear();
1338
+ const month = String(d.getMonth() + 1).padStart(2, '0');
1339
+ const day = String(d.getDate()).padStart(2, '0');
1340
+ const hours = String(d.getHours()).padStart(2, '0');
1341
+ const minutes = String(d.getMinutes()).padStart(2, '0');
1342
+
1343
+ return `${year}-${month}-${day}T${hours}:${minutes}`;
1344
+ }
1345
+
1346
+ function formatDateInput(date) {
1347
+ const d = new Date(date);
1348
+ const year = d.getFullYear();
1349
+ const month = String(d.getMonth() + 1).padStart(2, '0');
1350
+ const day = String(d.getDate()).padStart(2, '0');
1351
+
1352
+ return `${year}-${month}-${day}`;
1353
+ }
1354
+
1355
+ function formatDateTimeRange(start, end) {
1356
+ const months = ['янв', 'фев', 'мар', 'апр', 'мая', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек'];
1357
+
1358
+ const startDay = start.getDate();
1359
+ const startMonth = months[start.getMonth()];
1360
+ const startHours = String(start.getHours()).padStart(2, '0');
1361
+ const startMinutes = String(start.getMinutes()).padStart(2, '0');
1362
+
1363
+ const endHours = String(end.getHours()).padStart(2, '0');
1364
+ const endMinutes = String(end.getMinutes()).padStart(2, '0');
1365
+
1366
+ return `${startDay} ${startMonth}, ${startHours}:${startMinutes} - ${endHours}:${endMinutes}`;
1367
+ }
1368
+
1369
+ function showModal(modal) {
1370
+ modal.classList.add('active');
1371
+
1372
+ // Add animation class based on modal type
1373
+ if (modal === voiceModal) {
1374
+ modal.querySelector('.modal-content').classList.add('fade-in');
1375
+ } else {
1376
+ modal.querySelector('.modal-content').classList.add('slide-in-right');
1377
+ }
1378
+ }
1379
+
1380
+ function hideModal(modal) {
1381
+ modal.classList.remove('active');
1382
+ modal.querySelector('.modal-content').classList.remove('slide-in-right', 'fade-in');
1383
+ }
1384
+
1385
+ // Touch events for swiping
1386
+ let touchStartX = 0;
1387
+ let touchEndX = 0;
1388
+
1389
+ document.addEventListener('touchstart', e => {
1390
+ touchStartX = e.changedTouches[0].screenX;
1391
+ }, {passive: true});
1392
+
1393
+ document.addEventListener('touchend', e => {
1394
+ touchEndX = e.changedTouches[0].screenX;
1395
+ handleSwipe();
1396
+ }, {passive: true});
1397
+
1398
+ function handleSwipe() {
1399
+ const threshold = 50;
1400
+
1401
+ if (touchEndX < touchStartX - threshold) {
1402
+ // Swipe left - next month
1403
+ nextMonthButton.click();
1404
+ }
1405
+
1406
+ if (touchEndX > touchStartX + threshold) {
1407
+ // Swipe right - previous month
1408
+ prevMonthButton.click();
1409
+ }
1410
+ }
1411
+
1412
+ // Initialize the calendar
1413
+ initCalendar();
1414
+ });
1415
+ </script>
1416
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: absolute; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">This website has been generated by <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
1417
+ </html>