0xc3 1 tháng trước cách đây
mục cha
commit
fc95e3f95b

+ 17 - 4
src/saura/cmd/sandbox/client/client.hpp

@@ -10,7 +10,7 @@
 
 #include <nlohmann/json.hpp>
 
-namespace sandbox {
+namespace saura {
 
 struct Money {
   int64_t amount;
@@ -36,7 +36,16 @@ inline void from_json(const nlohmann::json &j, Money &money) {
   j.at("currency").get_to(money.currency);
 }
 
-struct ClientInfo {
+const std::string ClientTypePhysical = "Физ";
+const std::string ClientTypeLegal = "Юр";
+const std::string ClientTypeSupplier = "Поставщик";
+const std::string ClientTypeEmployee = "Сотрудник";
+const std::string ClientTypeCounterparty = "Контрагент";
+const std::string ClientTypeCustomer = "Покупатель";
+
+class ClientInfo {
+
+public:
   std::string id;
   std::string old_id;
   bool contractor = false;
@@ -46,13 +55,15 @@ struct ClientInfo {
   std::string legal_address;
   std::string physical_address;
   std::string note;
+  std::string reg_date;
 
   Money income;
 
   std::vector<std::string> tags;
   std::vector<std::string> phones;
-  std::map<std::string, std::string> metadata;
+  std::vector<std::map<std::string, std::string>> metadata;
 
+public:
   ClientInfo() = default;
 
   static void to_json(nlohmann::json &j, const ClientInfo &client) {
@@ -70,6 +81,7 @@ struct ClientInfo {
         {"physical_address", client.physical_address},
         {"note", client.note},
         {"income", client.income},
+        {"reg_date", client.reg_date},
     };
   }
 
@@ -87,6 +99,7 @@ struct ClientInfo {
     j.at("tags").get_to(client.tags);
     j.at("phones").get_to(client.phones);
     j.at("metadata").get_to(client.metadata);
+    j.at("reg_date").get_to(client.reg_date);
   }
 
   static ClientInfo from_json(const nlohmann::json &j) {
@@ -110,6 +123,6 @@ inline void from_json(const nlohmann::json &j, ClientInfo &client) {
   ClientInfo::from_json(j, client);
 }
 
-} // namespace sandbox
+} // namespace saura
 
 #endif

+ 81 - 8
src/saura/cmd/sandbox/sandbox.cpp

@@ -1,20 +1,25 @@
+#include <fmt/format.h>
 #include <saura/core/app_base/app_base.hpp>
 
 #include <spdlog/spdlog.h>
 
 #include <imgui.h>
 #include <imgui_internal.h>
+#include <vector>
 
+#include "saura/cmd/sandbox/client/client.hpp"
 #include "server/server.hpp"
 
 namespace saura {
 struct SandboxApp : AppBase {
   std::shared_ptr<ServerAPI> server_api_ctx;
+  std::vector<ClientInfo> clients;
 
   void start() override {
     spdlog::info("Sandbox start!");
 
-    server_api_ctx = std::make_shared<ServerAPI>();
+    this->server_api_ctx = std::make_shared<ServerAPI>();
+    this->clients = server_api_ctx->fetch_clients(10, 0);
   }
 
   void update(double dt) override {
@@ -41,37 +46,105 @@ struct SandboxApp : AppBase {
             ImGuiTableFlags_Resizable | ImGuiTableFlags_Borders |
             ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_ScrollY;
 
-        if (ImGui::BeginTable("MyDataTable", 5, flags))
         {
+          int64_t total = 0;
+          for (auto &client : this->clients) {
+            total += client.income.amount;
+          }
+
+          int64_t rubles = total / 100;
+          int64_t kopecks = total % 100;
+
+          auto text = fmt::format("Общий доход: {}.{} RUB,", rubles, kopecks);
+          ImGui::Text("%s", text.c_str());
+          ImGui::SameLine();
+        }
+        {
+          auto text = fmt::format("Всего клиентов: {}", this->clients.size());
+          ImGui::Text("%s", text.c_str());
+        }
+
+        if (ImGui::Button("Создать клиента")) {
+          ImGui::OpenPopup("Test");
+        }
+
+        if (ImGui::BeginPopupModal("Test", NULL,
+                                   ImGuiWindowFlags_AlwaysAutoResize)) {
+          ImGui::Text("This is the modal content!");
+          ImGui::Separator();
+
+          if (ImGui::Button("Close", ImVec2(120, 0))) {
+            ImGui::CloseCurrentPopup(); // Function to close the currently
+                                        // open popup
+          }
+
+          ImGui::EndPopup(); // Must be called if BeginPopupModal returned
+                             // true
+        }
+
+        if (ImGui::BeginTable("MyDataTable", 9, flags)) {
           ImGui::TableSetupColumn("#");
+          ImGui::TableSetupColumn("Тип");
+          ImGui::TableSetupColumn("Теги");
           ImGui::TableSetupColumn("ФИО");
           ImGui::TableSetupColumn("Телефон");
           ImGui::TableSetupColumn("Эл. почта");
           ImGui::TableSetupColumn("Дата регистрации");
+          ImGui::TableSetupColumn(""); // Edit
+          ImGui::TableSetupColumn(""); // Delete
           ImGui::TableHeadersRow();
 
-          for (int row = 0; row < 5; row++) {
+          int32_t selected_row_idx = -1;
+          for (size_t idx = 0; idx < clients.size(); idx++) {
+            auto &client = clients[idx];
+
             ImGui::TableNextRow();
 
             // #
             ImGui::TableNextColumn();
-            ImGui::Text("0");
+            ImGui::Text("%03d", (int)idx + 1);
+
+            // Тип
+            ImGui::TableNextColumn();
+            ImGui::Text("%s", client.type.c_str());
+
+            // Теги
+            ImGui::TableNextColumn();
+            if (client.tags.size() > 1) {
+              ImGui::Text("%s...", client.tags[0].c_str());
+            } else {
+              ImGui::Text("%s", client.tags[0].c_str());
+            }
 
             // ФИО
             ImGui::TableNextColumn();
-            ImGui::Text("Воробьёв Варлам Филиппович");
+            ImGui::Text("%s", client.full_name.c_str());
 
             // Телефон
             ImGui::TableNextColumn();
-            ImGui::Text("+7 (999) 999-9999");
+            if (client.phones.size() > 1) {
+              ImGui::Text("%s...", client.phones[0].c_str());
+            } else {
+              ImGui::Text("%s", client.phones[0].c_str());
+            }
 
             // Эл. почта
             ImGui::TableNextColumn();
-            ImGui::Text("test@gmail.com");
+            ImGui::Text("%s", client.email.c_str());
 
             // Дата регистрации
             ImGui::TableNextColumn();
-            ImGui::Text("15.12.2025");
+            ImGui::Text("%s", client.reg_date.c_str());
+
+            ImGui::TableNextColumn();
+            ImGui::PushID(fmt::format("{}Edit", idx).c_str());
+            ImGui::Button("Edit");
+            ImGui::PopID();
+
+            ImGui::TableNextColumn();
+            ImGui::PushID(fmt::format("{}Delete", idx).c_str());
+            ImGui::Button("Delete");
+            ImGui::PopID();
           }
 
           ImGui::EndTable();

+ 38 - 28
src/saura/cmd/sandbox/server/server.cpp

@@ -10,7 +10,9 @@
 #include <nlohmann/json_fwd.hpp>
 #include <spdlog/spdlog.h>
 
+#include <string>
 #include <thread>
+#include <vector>
 
 namespace saura {
 ServerAPI::ServerAPI() {
@@ -24,37 +26,45 @@ ServerAPI::~ServerAPI() {
 
 void ServerAPI::run() {
   while (true) {
-    {
-      auto res = cpr::Get(
-          cpr::Url{
-              "http://api.localhost:8090/v1/example/clients?limit=10&offset=0"},
-          cpr::Timeout{1000});
-      if (res.status_code == 200) {
-        auto res_json = nlohmann::json::parse(res.text);
-        spdlog::info("Response: {}", res_json.dump(2));
-
-        if (!res_json.is_array()) {
-          throw std::runtime_error("Expected JSON array but got " +
-                                   std::string(res_json.type_name()));
-        }
-        for (size_t i = 0; i < res_json.size(); ++i) {
-          const auto &client_json = res_json[i];
-
-          sandbox::ClientInfo client =
-              sandbox::ClientInfo::from_json(client_json);
-
-          spdlog::info("✅ Client #{} parsed: {}", i, client.full_name);
-          spdlog::info("   ID: {}", client.id);
-          spdlog::info("   Tags: {}", fmt::join(client.tags, ", "));
-          spdlog::info("   Phones: {}", fmt::join(client.phones, ", "));
-          spdlog::info("   Income: {} {}", client.income.amount,
-                       client.income.currency);
-        }
-      }
-    }
+    fetch_clients(10, 0);
 
     std::this_thread::sleep_for(std::chrono::seconds(1));
   }
 }
 
+std::vector<ClientInfo> ServerAPI::fetch_clients(uint32_t limit,
+                                                 uint32_t offset) {
+
+  std::vector<ClientInfo> clients;
+
+  std::string url = fmt::format(
+      "http://api.localhost:8090/v1/example/clients?limit={}&offset={}", limit,
+      offset);
+  auto res = cpr::Get(cpr::Url(url), cpr::Timeout(1000));
+  if (res.status_code == 200) {
+    auto res_json = nlohmann::json::parse(res.text);
+    spdlog::info("Response: {}", res_json.dump(2));
+
+    if (!res_json.is_array()) {
+      throw std::runtime_error("Expected JSON array but got " +
+                               std::string(res_json.type_name()));
+    }
+    for (size_t i = 0; i < res_json.size(); ++i) {
+      const auto &client_json = res_json[i];
+
+      ClientInfo client = ClientInfo::from_json(client_json);
+      clients.push_back(client);
+
+      spdlog::info("✅ Client #{} parsed: {}", i, client.full_name);
+      spdlog::info("   ID: {}", client.id);
+      spdlog::info("   Tags: {}", fmt::join(client.tags, ", "));
+      spdlog::info("   Phones: {}", fmt::join(client.phones, ", "));
+      spdlog::info("   Income: {} {}", client.income.amount,
+                   client.income.currency);
+    }
+  }
+
+  return clients;
+}
+
 } // namespace saura

+ 4 - 0
src/saura/cmd/sandbox/server/server.hpp

@@ -3,6 +3,8 @@
 
 #include <thread>
 
+#include "saura/cmd/sandbox/client/client.hpp"
+
 namespace saura {
 class ServerAPI {
 private:
@@ -13,6 +15,8 @@ public:
   ~ServerAPI();
 
   void run();
+
+  std::vector<ClientInfo> fetch_clients(uint32_t limit, uint32_t offset);
 };
 }; // namespace saura