From 92248df9d10e20a5d81df659aeaf8ef06d73a981 Mon Sep 17 00:00:00 2001 From: Roman Pyrih Date: Tue, 27 Jan 2026 15:34:07 +0100 Subject: [PATCH] =?UTF-8?q?Dodanie=20nowej=20strony=20admina=20co=20pozwal?= =?UTF-8?q?a=20dodawa=C4=87=20pane=20kontaktowe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/contacts-maps/element-edit.php | 262 ++++++++++++++++++ admin/templates/contacts-maps/view-list.php | 45 +++ admin/templates/site/main-layout.php | 5 + api/contact_map.php | 30 ++ .../admin/controls/class.ContactsMaps.php | 58 ++++ autoload/admin/factory/class.ContactsMaps.php | 137 +++++++++ .../front/controls/class.ContactsMapsApi.php | 24 ++ autoload/front/factory/class.ContactsMaps.php | 115 ++++++++ images/products/icon_product_1.svg | 5 + images/products/icon_product_2.svg | 4 + images/products/icon_product_3.svg | 7 + 11 files changed, 692 insertions(+) create mode 100644 admin/templates/contacts-maps/element-edit.php create mode 100644 admin/templates/contacts-maps/view-list.php create mode 100644 api/contact_map.php create mode 100644 autoload/admin/controls/class.ContactsMaps.php create mode 100644 autoload/admin/factory/class.ContactsMaps.php create mode 100644 autoload/front/controls/class.ContactsMapsApi.php create mode 100644 autoload/front/factory/class.ContactsMaps.php create mode 100644 images/products/icon_product_1.svg create mode 100644 images/products/icon_product_2.svg create mode 100644 images/products/icon_product_3.svg diff --git a/admin/templates/contacts-maps/element-edit.php b/admin/templates/contacts-maps/element-edit.php new file mode 100644 index 0000000..62ed8b0 --- /dev/null +++ b/admin/templates/contacts-maps/element-edit.php @@ -0,0 +1,262 @@ + + + + + item ?? []; +$products = $this -> products ?? []; +$provinces = $this -> provinces ?? []; + +/** Województwa */ +$province_values = [ 0 => '--- wybierz województwo ---' ]; +if (is_array($provinces)) { + foreach ($provinces as $p) { + $province_values[(int)$p['id']] = $p['name']; + } +} + +/** Typ salonu */ +$salon_type_values = [ + 'sales' => 'SALON SPRZEDAŻY', + 'partner' => 'SALON PARTNERSKI', +]; + +/** Produkty */ +$selected_products = $item['products'] ?? []; +if (!is_array($selected_products)) $selected_products = []; + +ob_start(); +?> + +
+ + +
+ + +
+ 'Województwo', + 'name' => 'province_id', + 'id' => 'province_id', + 'values' => $province_values, + 'value' => (int)($item['province_id'] ?? 0), + ]);?> + + 'Typ salonu', + 'name' => 'salon_type', + 'id' => 'salon_type', + 'values' => $salon_type_values, + 'value' => ($item['salon_type'] ?? 'sales'), + ]);?> + + 'Nazwa salonu', + 'name' => 'salon_name', + 'id' => 'salon_name', + 'value' => ($item['salon_name'] ?? ''), + 'inline' => true + ]);?> + + 'Miasto', + 'name' => 'city', + 'id' => 'city', + 'value' => ($item['city'] ?? ''), + 'inline' => true + ]);?> + + 'Adres', + 'name' => 'address', + 'id' => 'address', + 'value' => ($item['address'] ?? ''), + 'inline' => true + ]);?> + + 'Koordynaty (lat, lng)', + 'name' => 'coords', + 'id' => 'coords', + 'value' => ($item['coords'] ?? ''), + 'inline' => true, + 'desc' => 'Np. 50.07576365941408, 21.973886126521034' + ]);?> + + 'Godziny otwarcia', + 'name' => 'opening_hours', + 'id' => 'opening_hours', + 'value' => ($item['opening_hours'] ?? ''), + 'inline' => true, + 'desc' => 'Np. Pn-Pt: 8-17 | Sob: 9-13 | Nd: nieczynne' + ]);?> + + 'Baner (obrazek salonu)', + 'name' => 'banner_image', + 'id' => 'banner_image', + 'value' => ($item['banner_image'] ?? ''), + 'icon_content' => 'przeglądaj', + 'inline' => true, + 'icon_js' => "window.open('/libraries/filemanager-9.14.1/dialog.php?type=1&popup=1&field_id=banner_image&akey=c3cb2537d25c0efc9e573d059d79c3b8','mywindow','location=1,status=1,scrollbars=1,width=1100,height=700');" + ]);?> +
+ + +
+ + + 'Telefony (1 numer = 1 linia)', + 'name' => 'phones', + 'id' => 'phones', + 'value' => $phones_txt, + 'inline' => true + ]);?> + + 'E-maile (1 email = 1 linia)', + 'name' => 'emails', + 'id' => 'emails', + 'value' => $emails_txt, + 'inline' => true + ]);?> + + 'Tekst przycisku', + 'name' => 'button_label', + 'id' => 'button_label', + 'value' => ($item['button_label'] ?? 'SKONTAKTUJ SIĘ Z NAMI'), + 'inline' => true + ]);?> + + 'Link przycisku (URL)', + 'name' => 'button_url', + 'id' => 'button_url', + 'value' => ($item['button_url'] ?? ''), + 'inline' => true, + 'desc' => 'Np. https://twojadomena.pl/kontakt' + ]);?> +
+ + +
+
Dostępne produkty
+ + +
+ + + + +
+ +
Brak produktów w pp_contacts_maps_products.
+ +
+ + +
+ 'Aktywny', + 'name' => 'is_active', + 'checked' => (!isset($item['is_active']) || (int)$item['is_active'] === 1) ? true : false + ]);?> + + 'Sortowanie', + 'name' => 'sort', + 'id' => 'sort', + 'value' => (int)($item['sort'] ?? 0), + ]);?> +
+ + +
+
+ + id = 'contacts-maps-edit'; +$grid -> gdb_opt = $gdb; +$grid -> include_plugins = true; +$grid -> title = 'Edycja autora'; +$grid -> title = $id ? 'Edycja salonu' : 'Dodaj salon'; + +$grid->fields = [ + [ + 'db' => 'id', + 'type' => 'hidden', + 'value' => $this->item['id'] + ] +]; + +$grid -> external_code = $out; +$grid -> actions = [ + 'save' => [ 'url' => '/admin/contacts_maps/save/', 'back_url' => '/admin/contacts_maps/view_list/' ], + 'cancel' => [ 'url' => '/admin/contacts_maps/view_list/' ] +]; + +$grid -> persist_edit = true; +$grid -> id_param = 'id'; +echo $grid -> draw(); +?> + + \ No newline at end of file diff --git a/admin/templates/contacts-maps/view-list.php b/admin/templates/contacts-maps/view-list.php new file mode 100644 index 0000000..065ae51 --- /dev/null +++ b/admin/templates/contacts-maps/view-list.php @@ -0,0 +1,45 @@ +gdb_opt = $gdb; + +$grid->columns_view = [ + [ + 'name' => 'Lp.', + 'autoincrement' => true + ], + [ + 'name' => 'Salon', + 'db' => 'salon_name', + 'php' => 'echo "[salon_name]";' + ], + [ + 'name' => 'Miasto', + 'db' => 'city' + ], + [ + 'name' => 'Typ', + 'db' => 'salon_type', + 'php' => 'echo ([salon_type] === "sales" ? "SALON SPRZEDAŻY" : ([salon_type] === "partner" ? "SALON PARTNERSKI" : ""));' + ], + [ + 'name' => 'Aktywny', + 'db' => 'is_active', + 'php' => 'echo ([is_active] ? "TAK" : "NIE");' + ], + [ + 'name' => 'Usuń', + 'action' => [ 'type' => 'delete', 'url' => '/admin/contacts_maps/delete/id=[id]' ] + ] +]; + +$grid->buttons = [ + [ + 'label' => 'Dodaj salon', + 'url' => '/admin/contacts_maps/edit/', + 'class' => 'btn-success' + ] +]; + +echo $grid->draw(); diff --git a/admin/templates/site/main-layout.php b/admin/templates/site/main-layout.php index 9f8eb37..a26bedd 100644 --- a/admin/templates/site/main-layout.php +++ b/admin/templates/site/main-layout.php @@ -88,6 +88,11 @@ Zawartość statyczna + +
  • + Kontakt - lista salonów +
  • + 'mysql', + 'database_name' => $database['name'], + 'server' => $database['host'], + 'username' => $database['user'], + 'password' => $database['password'], + 'charset' => 'utf8' + ] ); + +\front\controls\ContactsMapsApi::index(); +?> \ No newline at end of file diff --git a/autoload/admin/controls/class.ContactsMaps.php b/autoload/admin/controls/class.ContactsMaps.php new file mode 100644 index 0000000..aaccfca --- /dev/null +++ b/autoload/admin/controls/class.ContactsMaps.php @@ -0,0 +1,58 @@ + \admin\factory\ContactsMaps::get(\S::get('id')), + 'products' => \admin\factory\ContactsMaps::products(), + 'provinces' => \admin\factory\ContactsMaps::provinces(), + ]); + } + + static public function save() + { + global $user; + + if (!\admin\factory\Users::check_privileges('scontainers_administration', $user['id'])) + return; + + $values = \S::json_to_array(\S::get('values')); + + $id = \admin\factory\ContactsMaps::save($values); + + echo json_encode([ + 'status' => $id ? 'ok' : 'error', + 'id' => $id + ]); + exit; + } + + static public function delete() + { + global $user; + + if (!\admin\factory\Users::check_privileges('scontainers_administration', $user['id'])) + return; + + \admin\factory\ContactsMaps::delete(\S::get('id')); + header('Location: /admin/contacts_maps/view_list/'); + exit; + } +} \ No newline at end of file diff --git a/autoload/admin/factory/class.ContactsMaps.php b/autoload/admin/factory/class.ContactsMaps.php new file mode 100644 index 0000000..8715aa2 --- /dev/null +++ b/autoload/admin/factory/class.ContactsMaps.php @@ -0,0 +1,137 @@ +select( + 'pp_contacts_maps_products', + [ 'id', 'code', 'name', 'icon' ], + [ + 'is_active' => 1, + 'ORDER' => [ + 'sort' => 'ASC' + ] + ] + ); + } + + static public function provinces() + { + global $mdb; + + return $mdb->select( + 'pp_contacts_maps_provinces', + [ 'id', 'code', 'name'], + [ + 'ORDER' => [ + 'id' => 'ASC' + ] + ] + ); + } + + static public function get($id) + { + global $mdb; + $id = (int)$id; + if (!$id) return null; + + + $row = $mdb->get( + 'pp_contacts_maps', + '*', + [ 'id' => $id ] + ); + + if (!$row) return null; + + $row['phones'] = json_decode($row['phones_json'], true) ?: []; + $row['emails'] = json_decode($row['emails_json'], true) ?: []; + $row['products'] = json_decode($row['products_json'], true) ?: []; + + $row['coords'] = ''; + if (!empty($row['lat']) && !empty($row['lng'])) { + $row['coords'] = $row['lat'] . ', ' . $row['lng']; + } + + return $row; + } + + static public function save($v) + { + global $mdb; + + $id = (int)($v['id'] ?? 0); + + // coords: "lat, lng" + $coords = trim($v['coords'] ?? ''); + $lat = 0; $lng = 0; + if ($coords) { + $parts = array_map('trim', explode(',', $coords)); + if (count($parts) >= 2) { + $lat = (float)str_replace(' ', '', $parts[0]); + $lng = (float)str_replace(' ', '', $parts[1]); + } + } + + $phones = array_filter(array_map('trim', explode("\n", $v['phones'] ?? ''))); + $emails = array_filter(array_map('trim', explode("\n", $v['emails'] ?? ''))); + + $products = []; + if (isset($v['products']) && is_array($v['products'])) { + $products = $v['products']; + } + elseif (isset($v['products[]']) && is_array($v['products[]'])) { + $products = $v['products[]']; + } + + $data = [ + 'province_id' => (int)($v['province_id'] ?? 0), + 'city' => trim($v['city'] ?? ''), + 'salon_type' => $v['salon_type'] ?? 'sales', + 'salon_name' => trim($v['salon_name'] ?? ''), + 'address' => trim($v['address'] ?? ''), + + 'lat' => $lat, + 'lng' => $lng, + + 'opening_hours' => trim($v['opening_hours'] ?? ''), + 'phones_json' => json_encode($phones, JSON_UNESCAPED_UNICODE), + 'emails_json' => json_encode($emails, JSON_UNESCAPED_UNICODE), + 'products_json' => json_encode(array_map('intval', $products)), + + 'button_label' => trim($v['button_label'] ?? 'SKONTAKTUJ SIĘ Z NAMI'), + 'button_url' => trim($v['button_url'] ?? ''), + + 'banner_image' => trim($v['banner_image'] ?? ''), + 'is_active' => !empty($v['is_active']) ? 1 : 0, + 'sort' => (int)($v['sort'] ?? 0), + ]; + + if ($id) { + $mdb->update('pp_contacts_maps', $data, [ 'id' => $id ]); + return $id; + } + + $mdb->insert('pp_contacts_maps', $data); + return (int)$mdb->id(); + } + + + static public function delete($id) + { + global $mdb; + + $id = (int)$id; + if (!$id) return false; + + return $mdb->delete( + 'pp_contacts_maps', + [ 'id' => $id ] + ); + } +} diff --git a/autoload/front/controls/class.ContactsMapsApi.php b/autoload/front/controls/class.ContactsMapsApi.php new file mode 100644 index 0000000..ee03a6a --- /dev/null +++ b/autoload/front/controls/class.ContactsMapsApi.php @@ -0,0 +1,24 @@ + 'ok', + 'count' => count($data), + 'data' => $data, + ], JSON_UNESCAPED_UNICODE); + + exit; + } +} diff --git a/autoload/front/factory/class.ContactsMaps.php b/autoload/front/factory/class.ContactsMaps.php new file mode 100644 index 0000000..ce12840 --- /dev/null +++ b/autoload/front/factory/class.ContactsMaps.php @@ -0,0 +1,115 @@ +select( + 'pp_contacts_maps_provinces', + [ 'id', 'code', 'name' ], + [ 'ORDER' => [ 'id' => 'ASC' ] ] + ); + + $provinces_by_id = []; + foreach ($provinces as $p) { + $provinces_by_id[(int)$p['id']] = $p; + } + + $products = $mdb->select( + 'pp_contacts_maps_products', + [ 'id', 'code', 'name', 'icon' ], + [ + 'is_active' => 1, + 'ORDER' => [ 'sort' => 'ASC' ] + ] + ); + + $products_by_id = []; + foreach ($products as $pr) { + $products_by_id[(int)$pr['id']] = $pr; + } + + // 2) забираємо салони + $where = [ + 'ORDER' => [ 'sort' => 'ASC' ] + ]; + if ($only_active) $where['is_active'] = 1; + + $rows = $mdb->select('pp_contacts_maps', '*', $where); + + // 3) збираємо API формат + $out = []; + foreach ($rows as $r) + { + $phones = json_decode($r['phones_json'] ?? '[]', true); + if (!is_array($phones)) $phones = []; + + $emails = json_decode($r['emails_json'] ?? '[]', true); + if (!is_array($emails)) $emails = []; + + $prod_ids = json_decode($r['products_json'] ?? '[]', true); + if (!is_array($prod_ids)) $prod_ids = []; + + $prod_out = []; + foreach ($prod_ids as $pid) { + $pid = (int)$pid; + if (isset($products_by_id[$pid])) { + $prod_out[] = [ + 'id' => (int)$products_by_id[$pid]['id'], + 'code' => $products_by_id[$pid]['code'], + 'name' => $products_by_id[$pid]['name'], + 'icon' => $products_by_id[$pid]['icon'], + ]; + } + } + + $prov = $provinces_by_id[(int)$r['province_id']] ?? null; + + $out[] = [ + 'id' => (int)$r['id'], + + 'province' => $prov ? [ + 'id' => (int)$prov['id'], + 'code' => $prov['code'], + 'name' => $prov['name'], + ] : null, + + 'city' => $r['city'], + 'salon_type' => $r['salon_type'], + 'salon_name' => $r['salon_name'], + 'address' => $r['address'], + + 'position' => [ + 'lat' => (float)$r['lat'], + 'lng' => (float)$r['lng'], + ], + + 'opening_hours' => $r['opening_hours'] ?? '', + + 'contact' => [ + 'phones' => array_values($phones), + 'emails' => array_values($emails), + ], + + 'products' => $prod_out, + + 'button' => [ + 'label' => $r['button_label'] ?? '', + 'url' => $r['button_url'] ?? '', + ], + + 'banner_image' => $r['banner_image'] ?? '', + + 'is_active' => (int)$r['is_active'], + 'sort' => (int)$r['sort'], + 'updated_at' => $r['updated_at'] ?? null, + ]; + } + + return $out; + } +} diff --git a/images/products/icon_product_1.svg b/images/products/icon_product_1.svg new file mode 100644 index 0000000..92963cc --- /dev/null +++ b/images/products/icon_product_1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/images/products/icon_product_2.svg b/images/products/icon_product_2.svg new file mode 100644 index 0000000..f41f803 --- /dev/null +++ b/images/products/icon_product_2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/images/products/icon_product_3.svg b/images/products/icon_product_3.svg new file mode 100644 index 0000000..118ca56 --- /dev/null +++ b/images/products/icon_product_3.svg @@ -0,0 +1,7 @@ + + + + + + +