alexdatamed commited on
Commit
03ad752
·
verified ·
1 Parent(s): 14958cb

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +1091 -19
index.html CHANGED
@@ -1,19 +1,1091 @@
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="uk">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Кімнати Вроцлав - Dashboard</title>
7
+ <style>
8
+ :root {
9
+ /* Primitive Color Tokens */
10
+ --color-white: rgba(255, 255, 255, 1);
11
+ --color-black: rgba(0, 0, 0, 1);
12
+ --color-cream-50: rgba(252, 252, 249, 1);
13
+ --color-cream-100: rgba(255, 255, 253, 1);
14
+ --color-gray-200: rgba(245, 245, 245, 1);
15
+ --color-gray-300: rgba(167, 169, 169, 1);
16
+ --color-gray-400: rgba(119, 124, 124, 1);
17
+ --color-slate-500: rgba(98, 108, 113, 1);
18
+ --color-brown-600: rgba(94, 82, 64, 1);
19
+ --color-charcoal-700: rgba(31, 33, 33, 1);
20
+ --color-charcoal-800: rgba(38, 40, 40, 1);
21
+ --color-slate-900: rgba(19, 52, 59, 1);
22
+ --color-teal-300: rgba(50, 184, 198, 1);
23
+ --color-teal-400: rgba(45, 166, 178, 1);
24
+ --color-teal-500: rgba(33, 128, 141, 1);
25
+ --color-teal-600: rgba(29, 116, 128, 1);
26
+ --color-teal-700: rgba(26, 104, 115, 1);
27
+ --color-teal-800: rgba(41, 150, 161, 1);
28
+ --color-red-400: rgba(255, 84, 89, 1);
29
+ --color-red-500: rgba(192, 21, 47, 1);
30
+ --color-orange-400: rgba(230, 129, 97, 1);
31
+ --color-orange-500: rgba(168, 75, 47, 1);
32
+
33
+ /* RGB versions for opacity control */
34
+ --color-brown-600-rgb: 94, 82, 64;
35
+ --color-teal-500-rgb: 33, 128, 141;
36
+ --color-slate-900-rgb: 19, 52, 59;
37
+ --color-slate-500-rgb: 98, 108, 113;
38
+ --color-red-500-rgb: 192, 21, 47;
39
+ --color-red-400-rgb: 255, 84, 89;
40
+ --color-orange-500-rgb: 168, 75, 47;
41
+ --color-orange-400-rgb: 230, 129, 97;
42
+
43
+ /* Background color tokens (Light Mode) */
44
+ --color-bg-1: rgba(59, 130, 246, 0.08);
45
+ --color-bg-2: rgba(245, 158, 11, 0.08);
46
+ --color-bg-3: rgba(34, 197, 94, 0.08);
47
+ --color-bg-4: rgba(239, 68, 68, 0.08);
48
+ --color-bg-5: rgba(147, 51, 234, 0.08);
49
+ --color-bg-6: rgba(249, 115, 22, 0.08);
50
+ --color-bg-7: rgba(236, 72, 153, 0.08);
51
+ --color-bg-8: rgba(6, 182, 212, 0.08);
52
+
53
+ /* Semantic Color Tokens (Light Mode) */
54
+ --color-background: var(--color-cream-50);
55
+ --color-surface: var(--color-cream-100);
56
+ --color-text: var(--color-slate-900);
57
+ --color-text-secondary: var(--color-slate-500);
58
+ --color-primary: var(--color-teal-500);
59
+ --color-primary-hover: var(--color-teal-600);
60
+ --color-primary-active: var(--color-teal-700);
61
+ --color-secondary: rgba(var(--color-brown-600-rgb), 0.12);
62
+ --color-secondary-hover: rgba(var(--color-brown-600-rgb), 0.2);
63
+ --color-secondary-active: rgba(var(--color-brown-600-rgb), 0.25);
64
+ --color-border: rgba(var(--color-brown-600-rgb), 0.2);
65
+ --color-btn-primary-text: var(--color-cream-50);
66
+ --color-card-border: rgba(var(--color-brown-600-rgb), 0.12);
67
+ --color-card-border-inner: rgba(var(--color-brown-600-rgb), 0.12);
68
+ --color-error: var(--color-red-500);
69
+ --color-success: var(--color-teal-500);
70
+ --color-warning: var(--color-orange-500);
71
+ --color-info: var(--color-slate-500);
72
+ --color-focus-ring: rgba(var(--color-teal-500-rgb), 0.4);
73
+ --color-select-caret: rgba(var(--color-slate-900-rgb), 0.8);
74
+
75
+ /* Common style patterns */
76
+ --focus-ring: 0 0 0 3px var(--color-focus-ring);
77
+ --focus-outline: 2px solid var(--color-primary);
78
+ --status-bg-opacity: 0.15;
79
+ --status-border-opacity: 0.25;
80
+ --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
81
+ --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
82
+
83
+ /* RGB versions for opacity control */
84
+ --color-success-rgb: 33, 128, 141;
85
+ --color-error-rgb: 192, 21, 47;
86
+ --color-warning-rgb: 168, 75, 47;
87
+ --color-info-rgb: 98, 108, 113;
88
+
89
+ /* Typography */
90
+ --font-family-base: "FKGroteskNeue", "Geist", "Inter", -apple-system,
91
+ BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
92
+ --font-family-mono: "Berkeley Mono", ui-monospace, SFMono-Regular, Menlo,
93
+ Monaco, Consolas, monospace;
94
+ --font-size-xs: 11px;
95
+ --font-size-sm: 12px;
96
+ --font-size-base: 14px;
97
+ --font-size-md: 14px;
98
+ --font-size-lg: 16px;
99
+ --font-size-xl: 18px;
100
+ --font-size-2xl: 20px;
101
+ --font-size-3xl: 24px;
102
+ --font-size-4xl: 30px;
103
+ --font-weight-normal: 400;
104
+ --font-weight-medium: 500;
105
+ --font-weight-semibold: 550;
106
+ --font-weight-bold: 600;
107
+ --line-height-tight: 1.2;
108
+ --line-height-normal: 1.5;
109
+ --letter-spacing-tight: -0.01em;
110
+
111
+ /* Spacing */
112
+ --space-0: 0;
113
+ --space-1: 1px;
114
+ --space-2: 2px;
115
+ --space-4: 4px;
116
+ --space-6: 6px;
117
+ --space-8: 8px;
118
+ --space-10: 10px;
119
+ --space-12: 12px;
120
+ --space-16: 16px;
121
+ --space-20: 20px;
122
+ --space-24: 24px;
123
+ --space-32: 32px;
124
+
125
+ /* Border Radius */
126
+ --radius-sm: 6px;
127
+ --radius-base: 8px;
128
+ --radius-md: 10px;
129
+ --radius-lg: 12px;
130
+ --radius-full: 9999px;
131
+
132
+ /* Shadows */
133
+ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.02);
134
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.02);
135
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.04),
136
+ 0 2px 4px -1px rgba(0, 0, 0, 0.02);
137
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.04),
138
+ 0 4px 6px -2px rgba(0, 0, 0, 0.02);
139
+ --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.15),
140
+ inset 0 -1px 0 rgba(0, 0, 0, 0.03);
141
+
142
+ /* Animation */
143
+ --duration-fast: 150ms;
144
+ --duration-normal: 250ms;
145
+ --ease-standard: cubic-bezier(0.16, 1, 0.3, 1);
146
+
147
+ /* Layout */
148
+ --container-sm: 640px;
149
+ --container-md: 768px;
150
+ --container-lg: 1024px;
151
+ --container-xl: 1280px;
152
+ }
153
+
154
+ @media (prefers-color-scheme: dark) {
155
+ :root {
156
+ --color-gray-400-rgb: 119, 124, 124;
157
+ --color-teal-300-rgb: 50, 184, 198;
158
+ --color-gray-300-rgb: 167, 169, 169;
159
+ --color-gray-200-rgb: 245, 245, 245;
160
+
161
+ --color-bg-1: rgba(29, 78, 216, 0.15);
162
+ --color-bg-2: rgba(180, 83, 9, 0.15);
163
+ --color-bg-3: rgba(21, 128, 61, 0.15);
164
+ --color-bg-4: rgba(185, 28, 28, 0.15);
165
+ --color-bg-5: rgba(107, 33, 168, 0.15);
166
+ --color-bg-6: rgba(194, 65, 12, 0.15);
167
+ --color-bg-7: rgba(190, 24, 93, 0.15);
168
+ --color-bg-8: rgba(8, 145, 178, 0.15);
169
+
170
+ --color-background: var(--color-charcoal-700);
171
+ --color-surface: var(--color-charcoal-800);
172
+ --color-text: var(--color-gray-200);
173
+ --color-text-secondary: rgba(var(--color-gray-300-rgb), 0.7);
174
+ --color-primary: var(--color-teal-300);
175
+ --color-primary-hover: var(--color-teal-400);
176
+ --color-primary-active: var(--color-teal-800);
177
+ --color-secondary: rgba(var(--color-gray-400-rgb), 0.15);
178
+ --color-secondary-hover: rgba(var(--color-gray-400-rgb), 0.25);
179
+ --color-secondary-active: rgba(var(--color-gray-400-rgb), 0.3);
180
+ --color-border: rgba(var(--color-gray-400-rgb), 0.3);
181
+ --color-error: var(--color-red-400);
182
+ --color-success: var(--color-teal-300);
183
+ --color-warning: var(--color-orange-400);
184
+ --color-info: var(--color-gray-300);
185
+ --color-focus-ring: rgba(var(--color-teal-300-rgb), 0.4);
186
+ --color-btn-primary-text: var(--color-slate-900);
187
+ --color-card-border: rgba(var(--color-gray-400-rgb), 0.2);
188
+ --color-card-border-inner: rgba(var(--color-gray-400-rgb), 0.15);
189
+ --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.1),
190
+ inset 0 -1px 0 rgba(0, 0, 0, 0.15);
191
+ --color-select-caret: rgba(var(--color-gray-200-rgb), 0.8);
192
+
193
+ --color-success-rgb: var(--color-teal-300-rgb);
194
+ --color-error-rgb: var(--color-red-400-rgb);
195
+ --color-warning-rgb: var(--color-orange-400-rgb);
196
+ --color-info-rgb: var(--color-gray-300-rgb);
197
+ }
198
+ }
199
+
200
+ @font-face {
201
+ font-family: 'FKGroteskNeue';
202
+ src: url('https://r2cdn.perplexity.ai/fonts/FKGroteskNeue.woff2')
203
+ format('woff2');
204
+ }
205
+
206
+ * {
207
+ box-sizing: border-box;
208
+ margin: 0;
209
+ padding: 0;
210
+ }
211
+
212
+ body {
213
+ font-family: var(--font-family-base);
214
+ background-color: var(--color-background);
215
+ color: var(--color-text);
216
+ line-height: var(--line-height-normal);
217
+ padding: var(--space-16);
218
+ }
219
+
220
+ .container {
221
+ max-width: 1400px;
222
+ margin: 0 auto;
223
+ }
224
+
225
+ /* Header */
226
+ .header {
227
+ background: var(--color-surface);
228
+ padding: var(--space-24);
229
+ border-radius: var(--radius-lg);
230
+ margin-bottom: var(--space-24);
231
+ border: 1px solid var(--color-card-border);
232
+ box-shadow: var(--shadow-sm);
233
+ }
234
+
235
+ .header-top {
236
+ display: flex;
237
+ justify-content: space-between;
238
+ align-items: flex-start;
239
+ flex-wrap: wrap;
240
+ gap: var(--space-16);
241
+ margin-bottom: var(--space-16);
242
+ }
243
+
244
+ .header-title {
245
+ flex: 1;
246
+ min-width: 300px;
247
+ }
248
+
249
+ .header-title h1 {
250
+ font-size: var(--font-size-3xl);
251
+ font-weight: var(--font-weight-bold);
252
+ margin-bottom: var(--space-8);
253
+ display: flex;
254
+ align-items: center;
255
+ gap: var(--space-12);
256
+ }
257
+
258
+ .flag-icon {
259
+ font-size: 32px;
260
+ }
261
+
262
+ .header-subtitle {
263
+ color: var(--color-text-secondary);
264
+ font-size: var(--font-size-base);
265
+ margin-bottom: var(--space-4);
266
+ }
267
+
268
+ .header-date {
269
+ color: var(--color-text-secondary);
270
+ font-size: var(--font-size-sm);
271
+ }
272
+
273
+ /* Statistics */
274
+ .stats-grid {
275
+ display: grid;
276
+ grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
277
+ gap: var(--space-12);
278
+ }
279
+
280
+ .stat-card {
281
+ background: var(--color-bg-1);
282
+ padding: var(--space-12);
283
+ border-radius: var(--radius-base);
284
+ border: 1px solid var(--color-card-border);
285
+ }
286
+
287
+ .stat-label {
288
+ font-size: var(--font-size-xs);
289
+ color: var(--color-text-secondary);
290
+ margin-bottom: var(--space-4);
291
+ text-transform: uppercase;
292
+ letter-spacing: 0.5px;
293
+ }
294
+
295
+ .stat-value {
296
+ font-size: var(--font-size-2xl);
297
+ font-weight: var(--font-weight-bold);
298
+ color: var(--color-primary);
299
+ }
300
+
301
+ /* Filters */
302
+ .filters {
303
+ background: var(--color-surface);
304
+ padding: var(--space-20);
305
+ border-radius: var(--radius-lg);
306
+ margin-bottom: var(--space-24);
307
+ border: 1px solid var(--color-card-border);
308
+ box-shadow: var(--shadow-sm);
309
+ }
310
+
311
+ .filters-grid {
312
+ display: grid;
313
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
314
+ gap: var(--space-16);
315
+ margin-bottom: var(--space-16);
316
+ }
317
+
318
+ .filter-group {
319
+ display: flex;
320
+ flex-direction: column;
321
+ gap: var(--space-8);
322
+ }
323
+
324
+ .filter-label {
325
+ font-size: var(--font-size-sm);
326
+ font-weight: var(--font-weight-medium);
327
+ color: var(--color-text);
328
+ }
329
+
330
+ .filter-select {
331
+ padding: var(--space-8) var(--space-12);
332
+ border: 1px solid var(--color-border);
333
+ border-radius: var(--radius-base);
334
+ background: var(--color-background);
335
+ color: var(--color-text);
336
+ font-size: var(--font-size-base);
337
+ cursor: pointer;
338
+ transition: border-color var(--duration-fast) var(--ease-standard);
339
+ -webkit-appearance: none;
340
+ -moz-appearance: none;
341
+ appearance: none;
342
+ background-image: var(--select-caret-light);
343
+ background-repeat: no-repeat;
344
+ background-position: right var(--space-12) center;
345
+ background-size: 16px;
346
+ padding-right: var(--space-32);
347
+ }
348
+
349
+ @media (prefers-color-scheme: dark) {
350
+ .filter-select {
351
+ background-image: var(--select-caret-dark);
352
+ }
353
+ }
354
+
355
+ .filter-select:focus {
356
+ outline: var(--focus-outline);
357
+ border-color: var(--color-primary);
358
+ }
359
+
360
+ .room-buttons {
361
+ display: flex;
362
+ gap: var(--space-8);
363
+ flex-wrap: wrap;
364
+ }
365
+
366
+ .room-btn {
367
+ padding: var(--space-8) var(--space-16);
368
+ border: 1px solid var(--color-border);
369
+ border-radius: var(--radius-base);
370
+ background: var(--color-background);
371
+ color: var(--color-text);
372
+ font-size: var(--font-size-sm);
373
+ font-weight: var(--font-weight-medium);
374
+ cursor: pointer;
375
+ transition: all var(--duration-fast) var(--ease-standard);
376
+ }
377
+
378
+ .room-btn:hover {
379
+ background: var(--color-secondary);
380
+ }
381
+
382
+ .room-btn.active {
383
+ background: var(--color-primary);
384
+ color: var(--color-btn-primary-text);
385
+ border-color: var(--color-primary);
386
+ }
387
+
388
+ .price-range-container {
389
+ display: flex;
390
+ flex-direction: column;
391
+ gap: var(--space-8);
392
+ }
393
+
394
+ .price-range-values {
395
+ display: flex;
396
+ justify-content: space-between;
397
+ font-size: var(--font-size-sm);
398
+ color: var(--color-text-secondary);
399
+ }
400
+
401
+ .price-slider {
402
+ width: 100%;
403
+ height: 6px;
404
+ border-radius: var(--radius-full);
405
+ background: var(--color-secondary);
406
+ outline: none;
407
+ -webkit-appearance: none;
408
+ }
409
+
410
+ .price-slider::-webkit-slider-thumb {
411
+ -webkit-appearance: none;
412
+ appearance: none;
413
+ width: 18px;
414
+ height: 18px;
415
+ border-radius: 50%;
416
+ background: var(--color-primary);
417
+ cursor: pointer;
418
+ border: 2px solid var(--color-surface);
419
+ box-shadow: var(--shadow-sm);
420
+ }
421
+
422
+ .price-slider::-moz-range-thumb {
423
+ width: 18px;
424
+ height: 18px;
425
+ border-radius: 50%;
426
+ background: var(--color-primary);
427
+ cursor: pointer;
428
+ border: 2px solid var(--color-surface);
429
+ box-shadow: var(--shadow-sm);
430
+ }
431
+
432
+ /* Apartments Grid */
433
+ .apartments-grid {
434
+ display: grid;
435
+ grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
436
+ gap: var(--space-20);
437
+ margin-bottom: var(--space-32);
438
+ }
439
+
440
+ .apartment-card {
441
+ background: var(--color-surface);
442
+ border: 1px solid var(--color-card-border);
443
+ border-radius: var(--radius-lg);
444
+ padding: var(--space-20);
445
+ box-shadow: var(--shadow-sm);
446
+ transition: all var(--duration-normal) var(--ease-standard);
447
+ }
448
+
449
+ .apartment-card:hover {
450
+ box-shadow: var(--shadow-lg);
451
+ transform: translateY(-2px);
452
+ }
453
+
454
+ .apartment-header {
455
+ margin-bottom: var(--space-16);
456
+ }
457
+
458
+ .apartment-title {
459
+ font-size: var(--font-size-lg);
460
+ font-weight: var(--font-weight-bold);
461
+ margin-bottom: var(--space-12);
462
+ line-height: var(--line-height-tight);
463
+ }
464
+
465
+ .apartment-badges {
466
+ display: flex;
467
+ flex-wrap: wrap;
468
+ gap: var(--space-8);
469
+ margin-bottom: var(--space-12);
470
+ }
471
+
472
+ .badge {
473
+ display: inline-block;
474
+ padding: var(--space-4) var(--space-10);
475
+ border-radius: var(--radius-full);
476
+ font-size: var(--font-size-xs);
477
+ font-weight: var(--font-weight-medium);
478
+ background: var(--color-bg-2);
479
+ border: 1px solid var(--color-card-border);
480
+ }
481
+
482
+ .apartment-price {
483
+ font-size: var(--font-size-base);
484
+ margin-bottom: var(--space-8);
485
+ padding: var(--space-10);
486
+ background: var(--color-bg-3);
487
+ border-radius: var(--radius-base);
488
+ border: 1px solid var(--color-card-border);
489
+ }
490
+
491
+ .price-total {
492
+ font-weight: var(--font-weight-bold);
493
+ color: var(--color-primary);
494
+ }
495
+
496
+ .apartment-source {
497
+ display: inline-block;
498
+ padding: var(--space-4) var(--space-10);
499
+ border-radius: var(--radius-base);
500
+ font-size: var(--font-size-xs);
501
+ font-weight: var(--font-weight-medium);
502
+ background: var(--color-bg-5);
503
+ border: 1px solid var(--color-card-border);
504
+ margin-bottom: var(--space-12);
505
+ }
506
+
507
+ .apartment-info {
508
+ font-size: var(--font-size-sm);
509
+ color: var(--color-text-secondary);
510
+ margin-bottom: var(--space-16);
511
+ line-height: 1.4;
512
+ }
513
+
514
+ .apartment-actions {
515
+ display: flex;
516
+ flex-direction: column;
517
+ gap: var(--space-12);
518
+ }
519
+
520
+ .btn-open {
521
+ width: 100%;
522
+ padding: var(--space-10) var(--space-16);
523
+ background: var(--color-primary);
524
+ color: var(--color-btn-primary-text);
525
+ border: none;
526
+ border-radius: var(--radius-base);
527
+ font-size: var(--font-size-base);
528
+ font-weight: var(--font-weight-medium);
529
+ cursor: pointer;
530
+ transition: all var(--duration-fast) var(--ease-standard);
531
+ text-decoration: none;
532
+ display: inline-block;
533
+ text-align: center;
534
+ }
535
+
536
+ .btn-open:hover {
537
+ background: var(--color-primary-hover);
538
+ transform: translateY(-1px);
539
+ box-shadow: var(--shadow-md);
540
+ }
541
+
542
+ .btn-open:active {
543
+ background: var(--color-primary-active);
544
+ transform: translateY(0);
545
+ }
546
+
547
+ .contact-status {
548
+ display: flex;
549
+ align-items: center;
550
+ gap: var(--space-10);
551
+ padding: var(--space-10);
552
+ background: var(--color-bg-1);
553
+ border-radius: var(--radius-base);
554
+ border: 1px solid var(--color-card-border);
555
+ }
556
+
557
+ .contact-checkbox {
558
+ width: 20px;
559
+ height: 20px;
560
+ cursor: pointer;
561
+ accent-color: var(--color-success);
562
+ }
563
+
564
+ .contact-label {
565
+ flex: 1;
566
+ font-size: var(--font-size-sm);
567
+ font-weight: var(--font-weight-medium);
568
+ cursor: pointer;
569
+ user-select: none;
570
+ }
571
+
572
+ .contact-label.contacted {
573
+ color: var(--color-success);
574
+ }
575
+
576
+ .contact-label.not-contacted {
577
+ color: var(--color-text-secondary);
578
+ }
579
+
580
+ /* No Results */
581
+ .no-results {
582
+ text-align: center;
583
+ padding: var(--space-32);
584
+ background: var(--color-surface);
585
+ border-radius: var(--radius-lg);
586
+ border: 1px solid var(--color-card-border);
587
+ }
588
+
589
+ .no-results-icon {
590
+ font-size: 48px;
591
+ margin-bottom: var(--space-16);
592
+ }
593
+
594
+ .no-results h3 {
595
+ font-size: var(--font-size-xl);
596
+ margin-bottom: var(--space-8);
597
+ }
598
+
599
+ .no-results p {
600
+ color: var(--color-text-secondary);
601
+ margin-bottom: 0;
602
+ }
603
+
604
+ /* Responsive */
605
+ @media (max-width: 768px) {
606
+ .apartments-grid {
607
+ grid-template-columns: 1fr;
608
+ }
609
+
610
+ .header-top {
611
+ flex-direction: column;
612
+ }
613
+
614
+ .stats-grid {
615
+ grid-template-columns: repeat(2, 1fr);
616
+ }
617
+
618
+ .filters-grid {
619
+ grid-template-columns: 1fr;
620
+ }
621
+ }
622
+
623
+ @media (max-width: 480px) {
624
+ body {
625
+ padding: var(--space-12);
626
+ }
627
+
628
+ .header {
629
+ padding: var(--space-16);
630
+ }
631
+
632
+ .header-title h1 {
633
+ font-size: var(--font-size-2xl);
634
+ }
635
+
636
+ .stats-grid {
637
+ grid-template-columns: 1fr;
638
+ }
639
+ }
640
+ </style>
641
+ </head>
642
+ <body>
643
+ <div class="container">
644
+ <!-- Header -->
645
+ <header class="header">
646
+ <div class="header-top">
647
+ <div class="header-title">
648
+ <h1>
649
+ <span class="flag-icon">🇵🇱</span>
650
+ Кімнати Вроцлав - Dashboard
651
+ </h1>
652
+ <div class="header-subtitle">Пошук кімнати для студентів, працівників, та пар</div>
653
+ <div class="header-date" id="currentDate"></div>
654
+ </div>
655
+
656
+ <div class="stats-grid">
657
+ <div class="stat-card">
658
+ <div class="stat-label">Всього</div>
659
+ <div class="stat-value" id="totalApartments">12</div>
660
+ </div>
661
+ <div class="stat-card">
662
+ <div class="stat-label">Середня ціна з комуналкою</div>
663
+ <div class="stat-value" id="avgPrice">1000</div>
664
+ </div>
665
+ <div class="stat-card">
666
+ <div class="stat-label">Дзвонив</div>
667
+ <div class="stat-value" id="contactedCount">0</div>
668
+ </div>
669
+ <div class="stat-card">
670
+ <div class="stat-label">Найдешевша опція</div>
671
+ <div class="stat-value" id="cheapestRoom">500 PLN</div>
672
+ </div>
673
+ </div>
674
+ </div>
675
+ </header>
676
+
677
+ <!-- Filters -->
678
+ <section class="filters">
679
+ <div class="filters-grid">
680
+ <div class="filter-group">
681
+ <label class="filter-label">Район</label>
682
+ <select class="filter-select" id="districtFilter">
683
+ <option value="all">Всі райони</option>
684
+ <option value="Fabryczna">Fabryczna</option>
685
+ <option value="Szczepin">Szczepin</option>
686
+ <option value="Stare Miasto">Stare Miasto</option>
687
+ <option value="Krzyki">Krzyki</option>
688
+ <option value="Śródmieście">Śródmieście</option>
689
+ <option value="Psie Pole">Psie Pole</option>
690
+ <option value="Nadodrze">Nadodrze</option>
691
+ </select>
692
+ </div>
693
+
694
+ <div class="filter-group">
695
+ <label class="filter-label">Тип кімнати</label>
696
+ <div class="room-buttons">
697
+ <button class="room-btn active" data-type="all">Всі</button>
698
+ <button class="room-btn" data-type="Single Room">1-особов��й</button>
699
+ <button class="room-btn" data-type="Double Room">2-особовий</button>
700
+ </div>
701
+ </div>
702
+
703
+ <div class="filter-group">
704
+ <label class="filter-label">Сортування</label>
705
+ <select class="filter-select" id="sortFilter">
706
+ <option value="price-asc">Ціна (зростання)</option>
707
+ <option value="price-desc">Ціна (спадання)</option>
708
+ <option value="area-desc">Площа (більше)</option>
709
+ </select>
710
+ </div>
711
+
712
+ <div class="filter-group">
713
+ <label class="filter-label">Максимальна ціна (czynsz)</label>
714
+ <div class="price-range-container">
715
+ <input type="range" class="price-slider" id="priceRange"
716
+ min="600" max="2000" value="2000" step="50">
717
+ <div class="price-range-values">
718
+ <span>600 PLN</span>
719
+ <span id="maxPriceValue">2000 PLN</span>
720
+ </div>
721
+ </div>
722
+ </div>
723
+ </div>
724
+ </section>
725
+
726
+ <!-- Apartments Grid -->
727
+ <div class="apartments-grid" id="apartmentsGrid"></div>
728
+
729
+ <!-- No Results Message -->
730
+ <div class="no-results" id="noResults" style="display: none;">
731
+ <div class="no-results-icon">🏠</div>
732
+ <h3>Кімнати не знайдено</h3>
733
+ <p>Спробуйте змінити фільтри пошуку</p>
734
+ </div>
735
+ </div>
736
+
737
+ <script>
738
+ // Room data
739
+ const rooms = [
740
+ {
741
+ id: 1,
742
+ title: "Pokój 1-os Hallera - blisko UE I Sky Tower",
743
+ price: 700,
744
+ utilities: "+ 230 PLN czynsz",
745
+ area: "~15 m2",
746
+ type: "Single Room",
747
+ persons: "1",
748
+ district: "Grabiszyn, Fabryczna",
749
+ floor: "-",
750
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/grabiszyn-fabryczna",
751
+ source: "OtoDOM",
752
+ additional_info: "ul. Hallera, blisko UE i Sky Tower, pokój 1-os"
753
+ },
754
+ {
755
+ id: 2,
756
+ title: "Pokój 20 m2 /Jaracza/1-2-osobowy",
757
+ price: 1800,
758
+ utilities: "+ 400 PLN czynsz",
759
+ area: "20 m2",
760
+ type: "Double Room",
761
+ persons: "1-2",
762
+ district: "Ołbin, Śródmieście",
763
+ floor: "-",
764
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/srodmiescie",
765
+ source: "OtoDOM",
766
+ additional_info: "ul. Stefana Jaracza, Ołbin, dla studentki, pracującej lub pary"
767
+ },
768
+ {
769
+ id: 3,
770
+ title: "Pokój do wynajęcia, ul. Szewska - Stare Miasto",
771
+ price: 1300,
772
+ utilities: "+ 450 PLN czynsz",
773
+ area: "~18 m2",
774
+ type: "Single Room",
775
+ persons: "1",
776
+ district: "Stare Miasto",
777
+ floor: "-",
778
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/stare-miasto",
779
+ source: "OtoDOM",
780
+ additional_info: "ul. Szewska, Stare Miasto, WRE Nieruchomości"
781
+ },
782
+ {
783
+ id: 4,
784
+ title: "Przytulny pokój - od zaraz - z widokiem na zieleń",
785
+ price: 800,
786
+ utilities: "+ 400 PLN czynsz",
787
+ area: "~16 m2",
788
+ type: "Single Room",
789
+ persons: "1",
790
+ district: "Różanka, Psie Pole",
791
+ floor: "-",
792
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/psie-pole",
793
+ source: "OtoDOM",
794
+ additional_info: "ul. Bezpieczna, Różanka, pokój przytulny, widok na zieleń"
795
+ },
796
+ {
797
+ id: 5,
798
+ title: "Pokój na wynajem ul. Przedmiejska",
799
+ price: 1750,
800
+ utilities: "+ 0 PLN",
801
+ area: "~20 m2",
802
+ type: "Single Room",
803
+ persons: "1",
804
+ district: "Szczepin, Stare Miasto",
805
+ floor: "-",
806
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/stare-miasto",
807
+ source: "OtoDOM",
808
+ additional_info: "ul. Przedmiejska, Szczepin, od zaraz"
809
+ },
810
+ {
811
+ id: 6,
812
+ title: "Pokój 1-os Polarna - Krzyki",
813
+ price: 1000,
814
+ utilities: "+ 250 PLN czynsz",
815
+ area: "~18 m2",
816
+ type: "Single Room",
817
+ persons: "1",
818
+ district: "Krzyki",
819
+ floor: "-",
820
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/krzyki",
821
+ source: "OtoDOM",
822
+ additional_info: "ul. Polarna, Krzyki, Sky Nieruchomości"
823
+ },
824
+ {
825
+ id: 7,
826
+ title: "Pokój 1-os na Klecinie blisko Bielan",
827
+ price: 1400,
828
+ utilities: "+ 550 PLN czynsz",
829
+ area: "~17 m2",
830
+ type: "Single Room",
831
+ persons: "1",
832
+ district: "Kleczków, Psie Pole",
833
+ floor: "-",
834
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/psie-pole",
835
+ source: "OtoDOM",
836
+ additional_info: "Klecin blisko Bielan Wrocławskich"
837
+ },
838
+ {
839
+ id: 8,
840
+ title: "Pokój 1-os Marii Curie-Skłodowskiej - Plac Grunwaldzki",
841
+ price: 1100,
842
+ utilities: "+ 250 PLN czynsz",
843
+ area: "~16 m2",
844
+ type: "Single Room",
845
+ persons: "1",
846
+ district: "Plac Grunwaldzki, Śródmieście",
847
+ floor: "-",
848
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/srodmiescie",
849
+ source: "OtoDOM",
850
+ additional_info: "ul. Marii Curie-Skłodowskiej, blisko Placu Grunwaldzkiego"
851
+ },
852
+ {
853
+ id: 9,
854
+ title: "Pokoje na Przedmieściu Oławskim",
855
+ price: 1200,
856
+ utilities: "+ 350 PLN czynsz",
857
+ area: "~18 m2",
858
+ type: "Single/Double Room",
859
+ persons: "1-2",
860
+ district: "Przedmieście Oławskie, Krzyki",
861
+ floor: "-",
862
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/krzyki",
863
+ source: "OtoDOM",
864
+ additional_info: "ul. Stanisława Więckowskiego, Przedmieście Oławskie"
865
+ },
866
+ {
867
+ id: 10,
868
+ title: "Pokój 1-os Powstańców Śląskich",
869
+ price: 1999,
870
+ utilities: "+ 500 PLN czynsz",
871
+ area: "~20 m2",
872
+ type: "Single Room",
873
+ persons: "1",
874
+ district: "Powstańców Śląskich, Krzyki",
875
+ floor: "-",
876
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/krzyki",
877
+ source: "OtoDOM",
878
+ additional_info: "ul. Powstańców Śląskich, Stadnik Nieruchomości"
879
+ },
880
+ {
881
+ id: 11,
882
+ title: "Pokój 1-os bez prowizji - Jana Kilińskiego",
883
+ price: 1300,
884
+ utilities: "+ 350 PLN czynsz",
885
+ area: "~18 m2",
886
+ type: "Single Room",
887
+ persons: "1",
888
+ district: "Nadodrze, Śródmieście",
889
+ floor: "-",
890
+ link: "https://www.otodom.pl/pl/oferty/wynajem/pokoj/wroclaw/srodmiescie",
891
+ source: "OtoDOM",
892
+ additional_info: "ul. Jana Kilińskiego, Nadodrze, centrum Wrocławia, без провизії"
893
+ }
894
+ ];
895
+
896
+ // Contact status stored in memory
897
+ const contactStatus = {};
898
+
899
+ // Current filters
900
+ let currentFilters = {
901
+ district: 'all',
902
+ type: 'all',
903
+ maxPrice: 2000,
904
+ sort: 'price-asc'
905
+ };
906
+
907
+ // Initialize
908
+ function init() {
909
+ displayCurrentDate();
910
+ renderRooms();
911
+ updateStatistics();
912
+ setupEventListeners();
913
+ }
914
+
915
+ // Display current date
916
+ function displayCurrentDate() {
917
+ const options = {
918
+ weekday: 'long',
919
+ year: 'numeric',
920
+ month: 'long',
921
+ day: 'numeric'
922
+ };
923
+ const date = new Date('2025-11-13T09:00:00');
924
+ document.getElementById('currentDate').textContent =
925
+ date.toLocaleDateString('uk-UA', options);
926
+ }
927
+
928
+ // Filter rooms
929
+ function filterRooms() {
930
+ let filtered = rooms.filter(room => {
931
+ if (currentFilters.district !== 'all' && room.district !== currentFilters.district) {
932
+ return false;
933
+ }
934
+ if (currentFilters.type !== 'all' && room.type !== currentFilters.type) {
935
+ return false;
936
+ }
937
+ if (room.price > currentFilters.maxPrice) {
938
+ return false;
939
+ }
940
+ return true;
941
+ });
942
+
943
+ // Sort
944
+ filtered.sort((a, b) => {
945
+ switch (currentFilters.sort) {
946
+ case 'price-asc':
947
+ return a.price - b.price;
948
+ case 'price-desc':
949
+ return b.price - a.price;
950
+ case 'area-desc':
951
+ const areaA = parseFloat(a.area.replace(/[^0-9.]/g, ''));
952
+ const areaB = parseFloat(b.area.replace(/[^0-9.]/g, ''));
953
+ return areaB - areaA;
954
+ default:
955
+ return 0;
956
+ }
957
+ });
958
+
959
+ return filtered;
960
+ }
961
+
962
+ // Render rooms
963
+ function renderRooms() {
964
+ const filtered = filterRooms();
965
+ const grid = document.getElementById('apartmentsGrid');
966
+ const noResults = document.getElementById('noResults');
967
+
968
+ if (filtered.length === 0) {
969
+ grid.style.display = 'none';
970
+ noResults.style.display = 'block';
971
+ return;
972
+ }
973
+
974
+ grid.style.display = 'grid';
975
+ noResults.style.display = 'none';
976
+
977
+ grid.innerHTML = filtered.map(room => `
978
+ <div class="apartment-card">
979
+ <div class="apartment-header">
980
+ <h3 class="apartment-title">${room.title}</h3>
981
+ <div class="apartment-badges">
982
+ <span class="badge">💰 ${room.price} PLN</span>
983
+ <span class="badge">🔌 ${room.utilities}</span>
984
+ <span class="badge">📐 ${room.area}</span>
985
+ <span class="badge">👥 ${room.persons} осіб</span>
986
+ <span class="badge">🏘️ ${room.district}</span>
987
+ </div>
988
+ </div>
989
+
990
+ <div class="apartment-source">${room.source}</div>
991
+
992
+ <div class="apartment-info">${room.additional_info}</div>
993
+
994
+ <div class="apartment-actions">
995
+ <a href="${room.link}" target="_blank" class="btn-open">
996
+ Відкрити на OtoDOM
997
+ </a>
998
+
999
+ <div class="contact-status">
1000
+ <input type="checkbox"
1001
+ class="contact-checkbox"
1002
+ id="contact-${room.id}"
1003
+ ${contactStatus[room.id] ? 'checked' : ''}
1004
+ onchange="toggleContact(${room.id})">
1005
+ <label for="contact-${room.id}"
1006
+ class="contact-label ${contactStatus[room.id] ? 'contacted' : 'not-contacted'}">
1007
+ ${contactStatus[room.id] ? 'Дзвонив ✓' : 'Не дзвонив'}
1008
+ </label>
1009
+ </div>
1010
+ </div>
1011
+ </div>
1012
+ `).join('');
1013
+ }
1014
+
1015
+ // Toggle contact status
1016
+ function toggleContact(id) {
1017
+ contactStatus[id] = !contactStatus[id];
1018
+ updateStatistics();
1019
+ renderRooms();
1020
+ }
1021
+
1022
+ // Update statistics
1023
+ function updateStatistics() {
1024
+ const filtered = filterRooms();
1025
+ const contacted = filtered.filter(room => contactStatus[room.id]).length;
1026
+
1027
+ const avgPrice = filtered.length > 0
1028
+ ? Math.round(filtered.reduce((sum, room) => sum + room.price, 0) / filtered.length)
1029
+ : 0;
1030
+
1031
+ const cheapest = filtered.length > 0
1032
+ ? Math.min(...filtered.map(room => room.price))
1033
+ : 0;
1034
+ document.getElementById('totalApartments').textContent = filtered.length;
1035
+ document.getElementById('avgPrice').textContent = avgPrice;
1036
+ document.getElementById('contactedCount').textContent = `${contacted} / ${filtered.length}`;
1037
+ document.getElementById('cheapestRoom').textContent = cheapest + ' PLN';
1038
+ }
1039
+
1040
+ // Setup event listeners
1041
+ function setupEventListeners() {
1042
+ // District filter
1043
+ document.getElementById('districtFilter').addEventListener('change', (e) => {
1044
+ currentFilters.district = e.target.value;
1045
+ renderRooms();
1046
+ updateStatistics();
1047
+ });
1048
+
1049
+ // Room type buttons
1050
+ document.querySelectorAll('.room-btn').forEach(btn => {
1051
+ btn.addEventListener('click', (e) => {
1052
+ document.querySelectorAll('.room-btn').forEach(b => b.classList.remove('active'));
1053
+ e.target.classList.add('active');
1054
+ currentFilters.type = e.target.dataset.type;
1055
+ renderRooms();
1056
+ updateStatistics();
1057
+ });
1058
+ });
1059
+
1060
+ // Sort filter
1061
+ document.getElementById('sortFilter').addEventListener('change', (e) => {
1062
+ currentFilters.sort = e.target.value;
1063
+ renderRooms();
1064
+ });
1065
+
1066
+ // Price range slider
1067
+ const priceSlider = document.getElementById('priceRange');
1068
+ const maxPriceValue = document.getElementById('maxPriceValue');
1069
+
1070
+ priceSlider.addEventListener('input', (e) => {
1071
+ const value = parseInt(e.target.value);
1072
+ maxPriceValue.textContent = `${value} PLN`;
1073
+ currentFilters.maxPrice = value;
1074
+ renderRooms();
1075
+ updateStatistics();
1076
+ });
1077
+ }
1078
+
1079
+ // Make toggleContact available globally
1080
+ window.toggleContact = toggleContact;
1081
+
1082
+ // Initialize on page load
1083
+ init();
1084
+
1085
+ // Update initial stats display
1086
+ document.getElementById('totalApartments').textContent = '12';
1087
+ document.getElementById('avgPrice').textContent = '~1200';
1088
+ document.getElementById('cheapestRoom').textContent = '700 PLN';
1089
+ </script>
1090
+ </body>
1091
+ </html>