diff --git a/dbal/cpp/src/entities/page/crud/search_pages.hpp b/dbal/cpp/src/entities/page/crud/search_pages.hpp new file mode 100644 index 000000000..9ca2ba664 --- /dev/null +++ b/dbal/cpp/src/entities/page/crud/search_pages.hpp @@ -0,0 +1,61 @@ +#ifndef DBAL_SEARCH_PAGES_HPP +#define DBAL_SEARCH_PAGES_HPP + +#include "dbal/errors.hpp" +#include "../../../store/in_memory_store.hpp" +#include +#include +#include +#include +#include + +namespace dbal { +namespace entities { +namespace page { + +namespace { + +inline std::string toLower(const std::string& value) { + std::string lowered; + lowered.reserve(value.size()); + std::transform(value.begin(), value.end(), std::back_inserter(lowered), [](unsigned char c) { + return static_cast(std::tolower(c)); + }); + return lowered; +} + +inline bool containsInsensitive(const std::string& text, const std::string& query) { + return toLower(text).find(toLower(query)) != std::string::npos; +} + +} // namespace + +inline Result> search(InMemoryStore& store, const std::string& query, int limit = 20) { + if (query.empty()) { + return Error::validationError("search query is required"); + } + + std::vector matches; + for (const auto& [id, page] : store.pages) { + (void)id; + if (containsInsensitive(page.slug, query) || containsInsensitive(page.title, query)) { + matches.push_back(page); + } + } + + std::sort(matches.begin(), matches.end(), [](const PageView& a, const PageView& b) { + return a.slug < b.slug; + }); + + if (limit > 0 && static_cast(matches.size()) > limit) { + matches.resize(limit); + } + + return Result>(matches); +} + +} // namespace page +} // namespace entities +} // namespace dbal + +#endif diff --git a/frontends/dbal/qml/CMakeLists.txt b/frontends/dbal/qml/CMakeLists.txt new file mode 100644 index 000000000..03c3b89d5 --- /dev/null +++ b/frontends/dbal/qml/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.27) +project(dbal_qml VERSION 0.1 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +include(${CMAKE_BINARY_DIR}/conan_toolchain.cmake OPTIONAL) + +find_package(Qt6 COMPONENTS Core Gui Quick REQUIRED) + +qt_add_executable(dbal-qml + main.cpp +) + +qt_add_qml_module(dbal-qml + URI DBALObservatory + VERSION 1.0 + QML_FILES FrontPage.qml +) + +target_link_libraries(dbal-qml PRIVATE Qt6::Core Qt6::Gui Qt6::Quick) + +qt_finalize_executable(dbal-qml) + +install(TARGETS dbal-qml + RUNTIME DESTINATION bin +)