BIGKingAlex commited on
Commit
ecb86b2
·
verified ·
1 Parent(s): 81612aa

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +862 -19
  3. prompts.txt +1 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Pro
3
- emoji: 🔥
4
- colorFrom: indigo
5
- colorTo: indigo
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: pro
3
+ emoji: 🐳
4
+ colorFrom: green
5
+ colorTo: yellow
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,862 @@
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="ru">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Недвижимость - Объявления</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script>
9
+ <script src="https://api-maps.yandex.ru/2.1/?apikey=ваш_api_ключ&lang=ru_RU" type="text/javascript"></script>
10
+ <style>
11
+ .marker-color-selector {
12
+ display: flex;
13
+ gap: 5px;
14
+ margin-top: 5px;
15
+ }
16
+ .color-option {
17
+ width: 20px;
18
+ height: 20px;
19
+ border-radius: 50%;
20
+ cursor: pointer;
21
+ border: 1px solid #ccc;
22
+ }
23
+ .color-option.selected {
24
+ border: 2px solid #000;
25
+ }
26
+ .map-container {
27
+ height: 500px;
28
+ width: 100%;
29
+ }
30
+ .object-image-thumbnail {
31
+ width: 80px;
32
+ height: 60px;
33
+ object-fit: cover;
34
+ margin-right: 5px;
35
+ cursor: pointer;
36
+ }
37
+ .object-image-thumbnail:hover {
38
+ opacity: 0.8;
39
+ }
40
+ .modal {
41
+ display: none;
42
+ position: fixed;
43
+ z-index: 100;
44
+ left: 0;
45
+ top: 0;
46
+ width: 100%;
47
+ height: 100%;
48
+ background-color: rgba(0,0,0,0.8);
49
+ }
50
+ .modal-content {
51
+ margin: 5% auto;
52
+ padding: 20px;
53
+ width: 80%;
54
+ max-width: 800px;
55
+ background: white;
56
+ border-radius: 8px;
57
+ }
58
+ .close {
59
+ color: #aaa;
60
+ float: right;
61
+ font-size: 28px;
62
+ font-weight: bold;
63
+ cursor: pointer;
64
+ }
65
+ .close:hover {
66
+ color: black;
67
+ }
68
+ @media (max-width: 768px) {
69
+ .map-container {
70
+ height: 300px;
71
+ }
72
+ .modal-content {
73
+ width: 95%;
74
+ margin: 10% auto;
75
+ }
76
+ }
77
+ </style>
78
+ </head>
79
+ <body class="bg-gradient-to-r from-blue-50 to-indigo-50 min-h-screen">
80
+ <!-- Хранилище данных -->
81
+ <script>
82
+ // Инициализация хранилища объектов
83
+ let objects = JSON.parse(localStorage.getItem('realtyObjects')) || [];
84
+ let currentUser = null;
85
+ let map = null;
86
+ let objectMarkers = [];
87
+
88
+ // Типы объектов
89
+ const objectTypes = [
90
+ "Квартира", "Дом", "Офис", "Торговая площадь",
91
+ "Склад", "Участок", "Гараж", "Другое"
92
+ ];
93
+
94
+ // Цвета маркеров
95
+ const markerColors = [
96
+ {name: "Красный", value: "#FF0000"},
97
+ {name: "Синий", value: "#0000FF"},
98
+ {name: "Зеленый", value: "#00FF00"},
99
+ {name: "Желтый", value: "#FFFF00"},
100
+ {name: "Фиолетовый", value: "#800080"},
101
+ {name: "Оранжевый", value: "#FFA500"},
102
+ {name: "Розовый", value: "#FFC0CB"},
103
+ {name: "Коричневый", value: "#A52A2A"}
104
+ ];
105
+
106
+ // Иконки маркеров
107
+ const markerIcons = [
108
+ {name: "Дом", value: "home"},
109
+ {name: "Здание", value: "building"},
110
+ {name: "Магазин", value: "store"},
111
+ {name: "Склад", value: "warehouse"},
112
+ {name: "Парковка", value: "parking"},
113
+ {name: "Офис", value: "briefcase"},
114
+ {name: "Участок", value: "tree"},
115
+ {name: "Другое", value: "map-marker-alt"}
116
+ ];
117
+ </script>
118
+
119
+ <!-- Шапка сайта -->
120
+ <header class="bg-indigo-700 text-white shadow-lg">
121
+ <div class="container mx-auto px-4 py-4 flex justify-between items-center">
122
+ <h1 class="text-2xl font-bold">Недвижимость PRO</h1>
123
+ <div class="flex space-x-4">
124
+ <button onclick="showTab('map')" class="px-4 py-2 rounded hover:bg-indigo-600">Карта</button>
125
+ <button onclick="showTab('objects')" class="px-4 py-2 rounded hover:bg-indigo-600">Объекты</button>
126
+ <button onclick="showTab('about')" class="px-4 py-2 rounded hover:bg-indigo-600">О компании</button>
127
+ <button onclick="showAdminLogin()" id="adminBtn" class="px-4 py-2 rounded bg-yellow-500 hover:bg-yellow-600 text-white hidden">Админ</button>
128
+ <button onclick="logout()" id="logoutBtn" class="px-4 py-2 rounded bg-red-500 hover:bg-red-600 text-white hidden">Выйти</button>
129
+ </div>
130
+ </div>
131
+ </header>
132
+
133
+ <!-- Основное содержимое -->
134
+ <main class="container mx-auto px-4 py-8">
135
+ <!-- Вкладка Карта -->
136
+ <div id="map-tab" class="tab-content">
137
+ <div class="bg-white rounded-lg shadow-md p-6 mb-6">
138
+ <h2 class="text-xl font-semibold mb-4">Карта объектов</h2>
139
+
140
+ <!-- Фильтры -->
141
+ <div class="mb-4 flex flex-wrap gap-2">
142
+ <button onclick="toggleFilters()" class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700">
143
+ Фильтры <i class="fas fa-filter"></i>
144
+ </button>
145
+
146
+ <div id="filtersPanel" class="hidden w-full bg-gray-100 p-4 rounded-lg mt-2">
147
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
148
+ <div>
149
+ <label class="block text-sm font-medium text-gray-700 mb-1">Тип объекта</label>
150
+ <select id="filterType" class="w-full p-2 border rounded">
151
+ <option value="">Все типы</option>
152
+ <script>
153
+ objectTypes.forEach(type => {
154
+ document.write(`<option value="${type}">${type}</option>`);
155
+ });
156
+ </script>
157
+ </select>
158
+ </div>
159
+ <div>
160
+ <label class="block text-sm font-medium text-gray-700 mb-1">Цена от</label>
161
+ <input type="number" id="filterPriceMin" class="w-full p-2 border rounded" placeholder="Минимальная цена">
162
+ </div>
163
+ <div>
164
+ <label class="block text-sm font-medium text-gray-700 mb-1">Цена до</label>
165
+ <input type="number" id="filterPriceMax" class="w-full p-2 border rounded" placeholder="Максимальная цена">
166
+ </div>
167
+ </div>
168
+ <button onclick="applyFilters()" class="mt-4 px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700">
169
+ Применить фильтры
170
+ </button>
171
+ </div>
172
+ </div>
173
+
174
+ <!-- Карта -->
175
+ <div id="map" class="map-container rounded-lg border border-gray-300"></div>
176
+ </div>
177
+ </div>
178
+
179
+ <!-- Вкладка Объекты -->
180
+ <div id="objects-tab" class="tab-content hidden">
181
+ <div class="bg-white rounded-lg shadow-md p-6">
182
+ <div class="flex justify-between items-center mb-6">
183
+ <h2 class="text-xl font-semibold">Список объектов</h2>
184
+ <button onclick="showAddObjectForm()" id="addObjectBtn" class="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700 hidden">
185
+ <i class="fas fa-plus"></i> Добавить объект
186
+ </button>
187
+ </div>
188
+
189
+ <div class="overflow-x-auto">
190
+ <table class="min-w-full bg-white border border-gray-200">
191
+ <thead>
192
+ <tr class="bg-gray-100">
193
+ <th class="py-2 px-4 border">Фото</th>
194
+ <th class="py-2 px-4 border">Тип</th>
195
+ <th class="py-2 px-4 border">Адрес</th>
196
+ <th class="py-2 px-4 border">Площадь</th>
197
+ <th class="py-2 px-4 border">Цена</th>
198
+ <th class="py-2 px-4 border">Контакты</th>
199
+ <th class="py-2 px-4 border">Действия</th>
200
+ </tr>
201
+ </thead>
202
+ <tbody id="objectsTableBody">
203
+ <!-- Объекты будут добавляться сюда -->
204
+ </tbody>
205
+ </table>
206
+ </div>
207
+ </div>
208
+ </div>
209
+
210
+ <!-- Вкладка О компании -->
211
+ <div id="about-tab" class="tab-content hidden">
212
+ <div class="bg-white rounded-lg shadow-md p-6">
213
+ <h2 class="text-xl font-semibold mb-4">О нашей компании</h2>
214
+ <p class="mb-4">Мы - лидер на рынке недвижимости с 15-летним опытом работы. Наша компания специализируется на продаже и аренде коммерческой и жилой недвижимости.</p>
215
+ <p class="mb-4">Наши преимущества:</p>
216
+ <ul class="list-disc pl-6 mb-4">
217
+ <li>Профессиональные консультации</li>
218
+ <li>Полное сопровождение сделки</li>
219
+ <li>Юридическая проверка объектов</li>
220
+ <li>Индивидуальный подход к каждому клиенту</li>
221
+ </ul>
222
+ <p>Свяжитесь с нами для получения дополнительной информации!</p>
223
+ </div>
224
+ </div>
225
+ </main>
226
+
227
+ <!-- Модальное окно входа в админку -->
228
+ <div id="adminLoginModal" class="modal">
229
+ <div class="modal-content">
230
+ <span class="close" onclick="closeModal('adminLoginModal')">&times;</span>
231
+ <h2 class="text-xl font-semibold mb-4">Вход в админ-панель</h2>
232
+ <div class="mb-4">
233
+ <label class="block text-sm font-medium text-gray-700 mb-1">Пароль</label>
234
+ <input type="password" id="adminPassword" class="w-full p-2 border rounded" placeholder="Введите пароль">
235
+ </div>
236
+ <button onclick="adminLogin()" class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700">
237
+ Войти
238
+ </button>
239
+ </div>
240
+ </div>
241
+
242
+ <!-- Модальное окно добавления/редактирования объекта -->
243
+ <div id="objectFormModal" class="modal">
244
+ <div class="modal-content">
245
+ <span class="close" onclick="closeModal('objectFormModal')">&times;</span>
246
+ <h2 id="objectFormTitle" class="text-xl font-semibold mb-4">Добавить новый объект</h2>
247
+
248
+ <form id="objectForm" class="space-y-4">
249
+ <input type="hidden" id="objectId">
250
+
251
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
252
+ <div>
253
+ <label class="block text-sm font-medium text-gray-700 mb-1">Тип объекта*</label>
254
+ <select id="objectType" class="w-full p-2 border rounded" required>
255
+ <option value="">Выберите тип</option>
256
+ <script>
257
+ objectTypes.forEach(type => {
258
+ document.write(`<option value="${type}">${type}</option>`);
259
+ });
260
+ </script>
261
+ </select>
262
+ <input type="text" id="customObjectType" class="w-full p-2 border rounded mt-2 hidden" placeholder="Укажите другой тип">
263
+ </div>
264
+
265
+ <div>
266
+ <label class="block text-sm font-medium text-gray-700 mb-1">Цена*</label>
267
+ <input type="number" id="objectPrice" class="w-full p-2 border rounded" placeholder="Укажите цену" required>
268
+ </div>
269
+ </div>
270
+
271
+ <div>
272
+ <label class="block text-sm font-medium text-gray-700 mb-1">Адрес*</label>
273
+ <input type="text" id="objectAddress" class="w-full p-2 border rounded" placeholder="Укажите адрес" required>
274
+ </div>
275
+
276
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
277
+ <div>
278
+ <label class="block text-sm font-medium text-gray-700 mb-1">Площадь (м²)*</label>
279
+ <input type="number" id="objectArea" class="w-full p-2 border rounded" placeholder="Площадь" required>
280
+ </div>
281
+
282
+ <div>
283
+ <label class="block text-sm font-medium text-gray-700 mb-1">Представитель*</label>
284
+ <input type="text" id="objectAgent" class="w-full p-2 border rounded" placeholder="ФИО представителя" required>
285
+ </div>
286
+
287
+ <div>
288
+ <label class="block text-sm font-medium text-gray-700 mb-1">Телефон*</label>
289
+ <input type="tel" id="objectPhone" class="w-full p-2 border rounded" placeholder="+7 (XXX) XXX-XX-XX" required>
290
+ </div>
291
+ </div>
292
+
293
+ <div>
294
+ <label class="block text-sm font-medium text-gray-700 mb-1">Email</label>
295
+ <input type="email" id="objectEmail" class="w-full p-2 border rounded" placeholder="email@example.com">
296
+ </div>
297
+
298
+ <div>
299
+ <label class="block text-sm font-medium text-gray-700 mb-1">Описание объекта*</label>
300
+ <textarea id="objectDescription" class="w-full p-2 border rounded" rows="3" placeholder="Подробное описание объекта" required></textarea>
301
+ </div>
302
+
303
+ <div>
304
+ <label class="block text-sm font-medium text-gray-700 mb-1">Фотографии объекта (максимум 5)</label>
305
+ <input type="file" id="objectImages" class="w-full p-2 border rounded" multiple accept="image/*">
306
+ <div id="imagePreviews" class="mt-2 flex flex-wrap gap-2"></div>
307
+ </div>
308
+
309
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
310
+ <div>
311
+ <label class="block text-sm font-medium text-gray-700 mb-1">Цвет маркера</label>
312
+ <select id="markerColorSelect" class="w-full p-2 border rounded">
313
+ <option value="">Выберите цвет</option>
314
+ <script>
315
+ markerColors.forEach(color => {
316
+ document.write(`<option value="${color.value}">${color.name}</option>`);
317
+ });
318
+ </script>
319
+ </select>
320
+ <div class="marker-color-selector mt-2">
321
+ <script>
322
+ markerColors.forEach(color => {
323
+ document.write(`<div class="color-option" style="background-color:${color.value}" onclick="selectMarkerColor('${color.value}')"></div>`);
324
+ });
325
+ </script>
326
+ </div>
327
+ </div>
328
+
329
+ <div>
330
+ <label class="block text-sm font-medium text-gray-700 mb-1">Иконка маркера</label>
331
+ <select id="markerIconSelect" class="w-full p-2 border rounded">
332
+ <option value="">Выберите иконку</option>
333
+ <script>
334
+ markerIcons.forEach(icon => {
335
+ document.write(`<option value="${icon.value}">${icon.name}</option>`);
336
+ });
337
+ </script>
338
+ </select>
339
+ </div>
340
+ </div>
341
+
342
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
343
+ <div>
344
+ <label class="block text-sm font-medium text-gray-700 mb-1">Доп. поле 1</label>
345
+ <input type="text" id="objectField1" class="w-full p-2 border rounded" placeholder="Дополнительная информация">
346
+ </div>
347
+ <div>
348
+ <label class="block text-sm font-medium text-gray-700 mb-1">Доп. поле 2</label>
349
+ <input type="text" id="objectField2" class="w-full p-2 border rounded" placeholder="Дополнительная информация">
350
+ </div>
351
+ <div>
352
+ <label class="block text-sm font-medium text-gray-700 mb-1">Доп. поле 3</label>
353
+ <input type="text" id="objectField3" class="w-full p-2 border rounded" placeholder="Дополнительная информация">
354
+ </div>
355
+ </div>
356
+
357
+ <div class="flex justify-end space-x-2">
358
+ <button type="button" onclick="closeModal('objectFormModal')" class="px-4 py-2 bg-gray-300 text-gray-700 rounded hover:bg-gray-400">
359
+ Отмена
360
+ </button>
361
+ <button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700">
362
+ Сохранить
363
+ </button>
364
+ </div>
365
+ </form>
366
+ </div>
367
+ </div>
368
+
369
+ <!-- Модальное окно просмотра объекта -->
370
+ <div id="viewObjectModal" class="modal">
371
+ <div class="modal-content">
372
+ <span class="close" onclick="closeModal('viewObjectModal')">&times;</span>
373
+ <div id="objectViewContent">
374
+ <!-- Контент будет заполнен динамически -->
375
+ </div>
376
+ </div>
377
+ </div>
378
+
379
+ <!-- Модальное окно просмотра изображения -->
380
+ <div id="imageViewModal" class="modal">
381
+ <div class="modal-content">
382
+ <span class="close" onclick="closeModal('imageViewModal')">&times;</span>
383
+ <img id="modalImageView" src="" alt="" class="w-full h-auto">
384
+ </div>
385
+ </div>
386
+
387
+ <script>
388
+ // Инициализация при загрузке страницы
389
+ document.addEventListener('DOMContentLoaded', function() {
390
+ showTab('map');
391
+ initMap();
392
+ renderObjectsTable();
393
+ checkAdminStatus();
394
+
395
+ // Обработчик формы объекта
396
+ document.getElementById('objectForm').addEventListener('submit', function(e) {
397
+ e.preventDefault();
398
+ saveObject();
399
+ });
400
+
401
+ // Обработчик изменения типа объекта
402
+ document.getElementById('objectType').addEventListener('change', function() {
403
+ const customTypeField = document.getElementById('customObjectType');
404
+ if (this.value === 'Другое') {
405
+ customTypeField.classList.remove('hidden');
406
+ customTypeField.required = true;
407
+ } else {
408
+ customTypeField.classList.add('hidden');
409
+ customTypeField.required = false;
410
+ }
411
+ });
412
+
413
+ // Обработчик загрузки изображений
414
+ document.getElementById('objectImages').addEventListener('change', function() {
415
+ const files = this.files;
416
+ const previewsContainer = document.getElementById('imagePreviews');
417
+ previewsContainer.innerHTML = '';
418
+
419
+ if (files.length > 5) {
420
+ alert('Максимальное количество фотографий - 5');
421
+ this.value = '';
422
+ return;
423
+ }
424
+
425
+ for (let i = 0; i < files.length; i++) {
426
+ const file = files[i];
427
+ if (!file.type.match('image.*')) continue;
428
+
429
+ const reader = new FileReader();
430
+ reader.onload = function(e) {
431
+ const img = document.createElement('img');
432
+ img.src = e.target.result;
433
+ img.className = 'object-image-thumbnail';
434
+ img.onclick = function() {
435
+ document.getElementById('modalImageView').src = e.target.result;
436
+ document.getElementById('imageViewModal').style.display = 'block';
437
+ };
438
+ previewsContainer.appendChild(img);
439
+ };
440
+ reader.readAsDataURL(file);
441
+ }
442
+ });
443
+ });
444
+
445
+ // Функции для работы с вкладками
446
+ function showTab(tabName) {
447
+ document.querySelectorAll('.tab-content').forEach(tab => {
448
+ tab.classList.add('hidden');
449
+ });
450
+ document.getElementById(`${tabName}-tab`).classList.remove('hidden');
451
+ }
452
+
453
+ // Функции для работы с картой
454
+ function initMap() {
455
+ ymaps.ready(function() {
456
+ map = new ymaps.Map('map', {
457
+ center: [55.76, 37.64], // Москва
458
+ zoom: 10
459
+ });
460
+
461
+ updateMapMarkers();
462
+ });
463
+ }
464
+
465
+ function updateMapMarkers() {
466
+ // Удаляем старые маркеры
467
+ objectMarkers.forEach(marker => {
468
+ map.geoObjects.remove(marker);
469
+ });
470
+ objectMarkers = [];
471
+
472
+ // Добавляем новые маркеры
473
+ objects.forEach(obj => {
474
+ const marker = new ymaps.Placemark(
475
+ [obj.lat, obj.lng],
476
+ {
477
+ balloonContentHeader: obj.type,
478
+ balloonContentBody: `
479
+ <div>
480
+ <p><strong>Адрес:</strong> ${obj.address}</p>
481
+ <p><strong>Площадь:</strong> ${obj.area} м²</p>
482
+ <p><strong>Цена:</strong> ${formatPrice(obj.price)}</p>
483
+ <p><strong>Контакты:</strong> ${obj.agent}, ${obj.phone}</p>
484
+ <p>${obj.description}</p>
485
+ ${obj.images.length > 0 ? `<img src="${obj.images[0]}" style="max-width:200px; max-height:150px; margin-top:10px;">` : ''}
486
+ </div>
487
+ `,
488
+ hintContent: obj.address
489
+ },
490
+ {
491
+ preset: obj.markerIcon ? `islands#${obj.markerIcon}Icon` : 'islands#icon',
492
+ iconColor: obj.markerColor || '#0066ff'
493
+ }
494
+ );
495
+
496
+ objectMarkers.push(marker);
497
+ map.geoObjects.add(marker);
498
+ });
499
+ }
500
+
501
+ function formatPrice(price) {
502
+ return new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB' }).format(price);
503
+ }
504
+
505
+ // Функции для работы с фильтрами
506
+ function toggleFilters() {
507
+ const panel = document.getElementById('filtersPanel');
508
+ panel.classList.toggle('hidden');
509
+ }
510
+
511
+ function applyFilters() {
512
+ const typeFilter = document.getElementById('filterType').value;
513
+ const priceMin = parseFloat(document.getElementById('filterPriceMin').value) || 0;
514
+ const priceMax = parseFloat(document.getElementById('filterPriceMax').value) || Infinity;
515
+
516
+ // Обновляем маркеры на карте
517
+ objectMarkers.forEach(marker => {
518
+ const obj = marker.properties.get('objectData');
519
+ const show =
520
+ (typeFilter === '' || obj.type === typeFilter) &&
521
+ obj.price >= priceMin &&
522
+ obj.price <= priceMax;
523
+
524
+ marker.options.set('visible', show);
525
+ });
526
+
527
+ // Закрываем панель фильтров
528
+ document.getElementById('filtersPanel').classList.add('hidden');
529
+ }
530
+
531
+ // Функции для работы с объектами
532
+ function renderObjectsTable() {
533
+ const tbody = document.getElementById('objectsTableBody');
534
+ tbody.innerHTML = '';
535
+
536
+ objects.forEach((obj, index) => {
537
+ const row = document.createElement('tr');
538
+ row.className = 'hover:bg-gray-50';
539
+
540
+ // Фото
541
+ const photoCell = document.createElement('td');
542
+ photoCell.className = 'py-2 px-4 border';
543
+ if (obj.images && obj.images.length > 0) {
544
+ const img = document.createElement('img');
545
+ img.src = obj.images[0];
546
+ img.className = 'object-image-thumbnail';
547
+ img.onclick = () => viewObject(index);
548
+ photoCell.appendChild(img);
549
+ } else {
550
+ photoCell.textContent = '-';
551
+ }
552
+
553
+ // Тип
554
+ const typeCell = document.createElement('td');
555
+ typeCell.className = 'py-2 px-4 border';
556
+ typeCell.textContent = obj.type;
557
+
558
+ // Адрес
559
+ const addressCell = document.createElement('td');
560
+ addressCell.className = 'py-2 px-4 border';
561
+ addressCell.textContent = obj.address;
562
+
563
+ // Площадь
564
+ const areaCell = document.createElement('td');
565
+ areaCell.className = 'py-2 px-4 border';
566
+ areaCell.textContent = `${obj.area} м²`;
567
+
568
+ // Цена
569
+ const priceCell = document.createElement('td');
570
+ priceCell.className = 'py-2 px-4 border';
571
+ priceCell.textContent = formatPrice(obj.price);
572
+
573
+ // Контакты
574
+ const contactsCell = document.createElement('td');
575
+ contactsCell.className = 'py-2 px-4 border';
576
+ contactsCell.innerHTML = `
577
+ <p>${obj.agent}</p>
578
+ <p>${obj.phone}</p>
579
+ ${obj.email ? `<p>${obj.email}</p>` : ''}
580
+ `;
581
+
582
+ // Действия
583
+ const actionsCell = document.createElement('td');
584
+ actionsCell.className = 'py-2 px-4 border';
585
+
586
+ const viewBtn = document.createElement('button');
587
+ viewBtn.className = 'px-2 py-1 bg-blue-500 text-white rounded hover:bg-blue-600 mr-1';
588
+ viewBtn.innerHTML = '<i class="fas fa-eye"></i>';
589
+ viewBtn.title = 'Просмотр';
590
+ viewBtn.onclick = () => viewObject(index);
591
+
592
+ actionsCell.appendChild(viewBtn);
593
+
594
+ if (currentUser) {
595
+ const editBtn = document.createElement('button');
596
+ editBtn.className = 'px-2 py-1 bg-yellow-500 text-white rounded hover:bg-yellow-600 mr-1';
597
+ editBtn.innerHTML = '<i class="fas fa-edit"></i>';
598
+ editBtn.title = 'Редактировать';
599
+ editBtn.onclick = () => editObject(index);
600
+
601
+ const deleteBtn = document.createElement('button');
602
+ deleteBtn.className = 'px-2 py-1 bg-red-500 text-white rounded hover:bg-red-600';
603
+ deleteBtn.innerHTML = '<i class="fas fa-trash"></i>';
604
+ deleteBtn.title = 'Удалить';
605
+ deleteBtn.onclick = () => deleteObject(index);
606
+
607
+ actionsCell.appendChild(editBtn);
608
+ actionsCell.appendChild(deleteBtn);
609
+ }
610
+
611
+ row.appendChild(photoCell);
612
+ row.appendChild(typeCell);
613
+ row.appendChild(addressCell);
614
+ row.appendChild(areaCell);
615
+ row.appendChild(priceCell);
616
+ row.appendChild(contactsCell);
617
+ row.appendChild(actionsCell);
618
+
619
+ tbody.appendChild(row);
620
+ });
621
+ }
622
+
623
+ function viewObject(index) {
624
+ const obj = objects[index];
625
+ const content = document.getElementById('objectViewContent');
626
+
627
+ content.innerHTML = `
628
+ <h3 class="text-lg font-semibold mb-2">${obj.type} - ${obj.address}</h3>
629
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
630
+ <div>
631
+ <p><strong>Площадь:</strong> ${obj.area} м²</p>
632
+ <p><strong>Цена:</strong> ${formatPrice(obj.price)}</p>
633
+ <p><strong>Дата создания:</strong> ${new Date(obj.createdAt).toLocaleDateString()}</p>
634
+ ${obj.field1 ? `<p><strong>Доп. поле 1:</strong> ${obj.field1}</p>` : ''}
635
+ ${obj.field2 ? `<p><strong>Доп. поле 2:</strong> ${obj.field2}</p>` : ''}
636
+ ${obj.field3 ? `<p><strong>Доп. поле 3:</strong> ${obj.field3}</p>` : ''}
637
+ </div>
638
+ <div>
639
+ <p><strong>Представитель:</strong> ${obj.agent}</p>
640
+ <p><strong>Телефон:</strong> ${obj.phone}</p>
641
+ ${obj.email ? `<p><strong>Email:</strong> ${obj.email}</p>` : ''}
642
+ </div>
643
+ </div>
644
+
645
+ <div class="mb-4">
646
+ <h4 class="font-medium mb-1">Описание:</h4>
647
+ <p>${obj.description}</p>
648
+ </div>
649
+
650
+ ${obj.images && obj.images.length > 0 ? `
651
+ <div>
652
+ <h4 class="font-medium mb-2">Фотографии:</h4>
653
+ <div class="flex flex-wrap gap-2">
654
+ ${obj.images.map(img => `
655
+ <img src="${img}" class="object-image-thumbnail cursor-pointer"
656
+ onclick="document.getElementById('modalImageView').src='${img}';
657
+ document.getElementById('imageViewModal').style.display='block'">
658
+ `).join('')}
659
+ </div>
660
+ </div>
661
+ ` : ''}
662
+ `;
663
+
664
+ document.getElementById('viewObjectModal').style.display = 'block';
665
+ }
666
+
667
+ function showAddObjectForm() {
668
+ document.getElementById('objectFormTitle').textContent = 'Добавить новый объект';
669
+ document.getElementById('objectId').value = '';
670
+ document.getElementById('objectForm').reset();
671
+ document.getElementById('imagePreviews').innerHTML = '';
672
+ document.getElementById('customObjectType').classList.add('hidden');
673
+
674
+ document.getElementById('objectFormModal').style.display = 'block';
675
+ }
676
+
677
+ function editObject(index) {
678
+ const obj = objects[index];
679
+ document.getElementById('objectFormTitle').textContent = 'Редактировать объект';
680
+ document.getElementById('objectId').value = index;
681
+
682
+ // Заполняем форму данными объекта
683
+ document.getElementById('objectType').value = obj.type === 'Другое' ? 'Другое' : obj.type;
684
+ if (obj.type === 'Другое') {
685
+ document.getElementById('customObjectType').value = obj.type;
686
+ document.getElementById('customObjectType').classList.remove('hidden');
687
+ }
688
+
689
+ document.getElementById('objectPrice').value = obj.price;
690
+ document.getElementById('objectAddress').value = obj.address;
691
+ document.getElementById('objectArea').value = obj.area;
692
+ document.getElementById('objectAgent').value = obj.agent;
693
+ document.getElementById('objectPhone').value = obj.phone;
694
+ document.getElementById('objectEmail').value = obj.email || '';
695
+ document.getElementById('objectDescription').value = obj.description;
696
+ document.getElementById('markerColorSelect').value = obj.markerColor || '';
697
+ document.getElementById('markerIconSelect').value = obj.markerIcon || '';
698
+ document.getElementById('objectField1').value = obj.field1 || '';
699
+ document.getElementById('objectField2').value = obj.field2 || '';
700
+ document.getElementById('objectField3').value = obj.field3 || '';
701
+
702
+ // Превью изображений
703
+ const previewsContainer = document.getElementById('imagePreviews');
704
+ previewsContainer.innerHTML = '';
705
+
706
+ if (obj.images && obj.images.length > 0) {
707
+ obj.images.forEach(img => {
708
+ const imgElement = document.createElement('img');
709
+ imgElement.src = img;
710
+ imgElement.className = 'object-image-thumbnail';
711
+ imgElement.onclick = function() {
712
+ document.getElementById('modalImageView').src = img;
713
+ document.getElementById('imageViewModal').style.display = 'block';
714
+ };
715
+ previewsContainer.appendChild(imgElement);
716
+ });
717
+ }
718
+
719
+ document.getElementById('objectFormModal').style.display = 'block';
720
+ }
721
+
722
+ function saveObject() {
723
+ const id = document.getElementById('objectId').value;
724
+ const type = document.getElementById('objectType').value === 'Другое'
725
+ ? document.getElementById('customObjectType').value
726
+ : document.getElementById('objectType').value;
727
+
728
+ const price = parseFloat(document.getElementById('objectPrice').value);
729
+ const address = document.getElementById('objectAddress').value;
730
+
731
+ // Геокодирование адреса
732
+ ymaps.geocode(address, { results: 1 }).then(function(res) {
733
+ const firstGeoObject = res.geoObjects.get(0);
734
+ const coords = firstGeoObject.geometry.getCoordinates();
735
+
736
+ const objectData = {
737
+ type: type,
738
+ price: price,
739
+ address: address,
740
+ lat: coords[0],
741
+ lng: coords[1],
742
+ area: parseFloat(document.getElementById('objectArea').value),
743
+ agent: document.getElementById('objectAgent').value,
744
+ phone: document.getElementById('objectPhone').value,
745
+ email: document.getElementById('objectEmail').value || '',
746
+ description: document.getElementById('objectDescription').value,
747
+ markerColor: document.getElementById('markerColorSelect').value,
748
+ markerIcon: document.getElementById('markerIconSelect').value,
749
+ field1: document.getElementById('objectField1').value || '',
750
+ field2: document.getElementById('objectField2').value || '',
751
+ field3: document.getElementById('objectField3').value || '',
752
+ createdAt: id === '' ? new Date().toISOString() : objects[id].createdAt,
753
+ images: id !== '' ? objects[id].images : []
754
+ };
755
+
756
+ // Обработка загруженных изображений
757
+ const files = document.getElementById('objectImages').files;
758
+ if (files.length > 0) {
759
+ objectData.images = [];
760
+ for (let i = 0; i < files.length; i++) {
761
+ const file = files[i];
762
+ if (!file.type.match('image.*')) continue;
763
+
764
+ const reader = new FileReader();
765
+ reader.onload = function(e) {
766
+ objectData.images.push(e.target.result);
767
+
768
+ // Когда все изображения загружены, сохраняем объект
769
+ if (objectData.images.length === files.length) {
770
+ saveObjectData(id, objectData);
771
+ }
772
+ };
773
+ reader.readAsDataURL(file);
774
+ }
775
+ } else {
776
+ saveObjectData(id, objectData);
777
+ }
778
+ });
779
+ }
780
+
781
+ function saveObjectData(id, objectData) {
782
+ if (id === '') {
783
+ // Новый объект
784
+ objects.push(objectData);
785
+ } else {
786
+ // Обновление существующего объекта
787
+ objects[id] = objectData;
788
+ }
789
+
790
+ // Сохраняем в localStorage
791
+ localStorage.setItem('realtyObjects', JSON.stringify(objects));
792
+
793
+ // Обновляем интерфейс
794
+ updateMapMarkers();
795
+ renderObjectsTable();
796
+ closeModal('objectFormModal');
797
+
798
+ alert('Объект успешно сохранен!');
799
+ }
800
+
801
+ function deleteObject(index) {
802
+ if (confirm('Вы уверены, что хотите удалить этот объект?')) {
803
+ objects.splice(index, 1);
804
+ localStorage.setItem('realtyObjects', JSON.stringify(objects));
805
+
806
+ updateMapMarkers();
807
+ renderObjectsTable();
808
+ }
809
+ }
810
+
811
+ function selectMarkerColor(color) {
812
+ document.getElementById('markerColorSelect').value = color;
813
+ }
814
+
815
+ // Функции для работы с админкой
816
+ function checkAdminStatus() {
817
+ const adminBtn = document.getElementById('adminBtn');
818
+ const logoutBtn = document.getElementById('logoutBtn');
819
+ const addObjectBtn = document.getElementById('addObjectBtn');
820
+
821
+ if (currentUser) {
822
+ adminBtn.classList.add('hidden');
823
+ logoutBtn.classList.remove('hidden');
824
+ addObjectBtn.classList.remove('hidden');
825
+ } else {
826
+ adminBtn.classList.remove('hidden');
827
+ logoutBtn.classList.add('hidden');
828
+ addObjectBtn.classList.add('hidden');
829
+ }
830
+ }
831
+
832
+ function showAdminLogin() {
833
+ document.getElementById('adminPassword').value = '';
834
+ document.getElementById('adminLoginModal').style.display = 'block';
835
+ }
836
+
837
+ function adminLogin() {
838
+ const password = document.getElementById('adminPassword').value;
839
+
840
+ if (password === 'i%UCLj2m2eg') {
841
+ currentUser = { role: 'admin' };
842
+ checkAdminStatus();
843
+ closeModal('adminLoginModal');
844
+ alert('Вы успешно вошли в админ-панель!');
845
+ } else {
846
+ alert('Неверный пароль!');
847
+ }
848
+ }
849
+
850
+ function logout() {
851
+ currentUser = null;
852
+ checkAdminStatus();
853
+ alert('Вы вышли из админ-панели');
854
+ }
855
+
856
+ // Общие функции
857
+ function closeModal(modalId) {
858
+ document.getElementById(modalId).style.display = 'none';
859
+ }
860
+ </script>
861
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=BIGKingAlex/pro" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
862
+ </html>
prompts.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ коду ниже Кнопки добавить объект перенести в админ панель. добавить вход по паролю на админ панель - i%UCLj2m2eg встроить поддержку яндекс карт Создан сайт рекламы с русским интерфейсом ✓ Интегрировать Яндекс Карты с маркерами объектов ✓ Админ-панель с входом по паролю (i%UCLj2m2eg) ✓ Управление объектами с фото и координатами ✓ фон в стиле красивого дизайна Добавить все поля из формы в схему базы данных ✓ форма редактирования объектов с полным набором полей: Тип объекта с выпадающим списком и пользовательским вводом Адрес объекта Настройки маркера (цвет и иконка) Площадь, представитель, телефон, email Дата создания Три дополнительных поля ✓ Обновлена карта для отображения расширенной информации в балунах ✓ таблица объектов с новыми колонками ✓ CSS стили для селекторов цвета и иконок форма через админ-панель - можно добавлять объекты со всеми деталями из оригинального дизайна! добавить в Основная информация под Описание объекта добавление до 5 фото. В вкладку Карта сделать Фильтры кнопкой и всплывающим меню под Картой Яндекс. Карту Яндекс разместить блоком по центру сайта. во вкладку Объекты добавить таблицу объектов с подробной информацией о каждом при клике на объект. сделать адаптивный сайт под мобильную версию. не менять основные функции сайта и кода. сделать полностью развернутый и рабочий сайт. с сохранением всех новых добавляющихся объектов и информации.