feat(smart-app): implement complete mobile app MVP

- App.tsx: full navigation (Auth stack + Main tabs with 5 screens)
- Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen
- HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors
- MapScreen: interactive map with layer toggles (6 layers)
- MarketplaceScreen: categories (6), products (5), search
- ChatScreen: AI chat with quick prompts (4), bot responses
- ProfileScreen: user info, stats, menu (9 items), logout
- AlertsScreen: alert list with severity, acknowledge
- SensorsScreen: sensor list with type filters (6 types), search
- ZonesScreen: zone cards with stats
- SettingsScreen: language picker (FR/EN/ES/DE), privacy, about
- Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n
- Hooks: useSensors, useAlerts, useNotifications, useLocation
- Components: Card, Button, LoadingSpinner, ErrorBoundary, Header
- Services: iotService, notificationService (with axios API client)
- Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN)
- Theme: colors.ts with full design system (Blue Ocean palette)
- Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
This commit is contained in:
Eric FELIXINE
2026-06-01 18:00:35 -04:00
parent 08ca495bde
commit e30ae8ed09
35578 changed files with 3703534 additions and 43 deletions

View File

@@ -0,0 +1,27 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
add_compile_options(
-fexceptions
-frtti
-std=c++20
-Wall
-Wpedantic
-DLOG_TAG=\"Fabric\")
file(GLOB react_render_element_SRC CONFIGURE_DEPENDS *.cpp)
add_library(react_render_element SHARED ${react_render_element_SRC})
target_include_directories(react_render_element PUBLIC ${REACT_COMMON_DIR})
target_link_libraries(react_render_element
folly_runtime
glog
react_render_core
react_render_componentregistry
)

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "ComponentBuilder.h"
#include <utility>
namespace facebook::react {
ComponentBuilder::ComponentBuilder(
ComponentDescriptorRegistry::Shared componentDescriptorRegistry)
: componentDescriptorRegistry_(std::move(componentDescriptorRegistry)){};
ShadowNode::Unshared ComponentBuilder::build(
const ElementFragment& elementFragment) const {
auto& componentDescriptor =
componentDescriptorRegistry_->at(elementFragment.componentHandle);
auto children = ShadowNode::ListOfShared{};
children.reserve(elementFragment.children.size());
for (const auto& childFragment : elementFragment.children) {
children.push_back(build(childFragment));
}
auto family = componentDescriptor.createFamily(ShadowNodeFamilyFragment{
elementFragment.tag, elementFragment.surfaceId, nullptr});
auto initialState =
componentDescriptor.createInitialState(elementFragment.props, family);
auto constShadowNode = componentDescriptor.createShadowNode(
ShadowNodeFragment{
elementFragment.props,
std::make_shared<ShadowNode::ListOfShared const>(children),
initialState},
family);
if (elementFragment.stateCallback) {
auto newState = componentDescriptor.createState(
*family, elementFragment.stateCallback(initialState));
constShadowNode = componentDescriptor.cloneShadowNode(
*constShadowNode,
ShadowNodeFragment{
ShadowNodeFragment::propsPlaceholder(),
ShadowNodeFragment::childrenPlaceholder(),
newState});
}
auto shadowNode = std::const_pointer_cast<ShadowNode>(constShadowNode);
if (elementFragment.referenceCallback) {
elementFragment.referenceCallback(shadowNode);
}
if (elementFragment.finalizeCallback) {
elementFragment.finalizeCallback(*shadowNode);
}
return shadowNode;
}
} // namespace facebook::react

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <memory>
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
#include <react/renderer/core/ComponentDescriptor.h>
#include <react/renderer/core/ShadowNode.h>
#include <react/renderer/core/ShadowNodeFragment.h>
#include <react/renderer/element/Element.h>
#include <react/renderer/element/ElementFragment.h>
namespace facebook::react {
/*
* Build `ShadowNode` trees with a given given `Element` trees.
*/
class ComponentBuilder final {
public:
ComponentBuilder(
ComponentDescriptorRegistry::Shared componentDescriptorRegistry);
/*
* Copyable and movable.
*/
ComponentBuilder(const ComponentBuilder& componentBuilder) = default;
ComponentBuilder(ComponentBuilder&& componentBuilder) noexcept = default;
ComponentBuilder& operator=(const ComponentBuilder& other) = default;
ComponentBuilder& operator=(ComponentBuilder&& other) = default;
/*
* Builds a `ShadowNode` tree with given `Element` tree using stored
* `ComponentDescriptorRegistry`.
*/
template <typename ShadowNodeT>
std::shared_ptr<ShadowNodeT> build(Element<ShadowNodeT> element) const {
return std::static_pointer_cast<ShadowNodeT>(build(element.fragment_));
}
private:
/*
* Internal, type-erased version of `build`.
*/
ShadowNode::Unshared build(const ElementFragment& elementFragment) const;
ComponentDescriptorRegistry::Shared componentDescriptorRegistry_;
};
} // namespace facebook::react

View File

@@ -0,0 +1,10 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "Element.h"
// Intentionally empty.

View File

@@ -0,0 +1,162 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <functional>
#include <memory>
#include <react/renderer/core/ShadowNode.h>
#include <react/renderer/element/ElementFragment.h>
namespace facebook::react {
/*
* `Element<>` is an abstraction layer that allows describing component
* hierarchy in a declarative way. Creating `Element`s themself does not create
* a component tree (aka `ShadowNode` tree) but describes some hierarchical
* structure that might be used to build an actual component tree (similar to
* XML Elements).
* `Element` provides some basic type-safety guarantees: all modifications
* of element objects require using objects (such as Props or State) of
* compatible type.
*/
template <typename ShadowNodeT>
class Element final {
public:
using ConcreteProps = typename ShadowNodeT::ConcreteProps;
using SharedConcreteProps = std::shared_ptr<const ConcreteProps>;
using ConcreteState = typename ShadowNodeT::ConcreteState;
using ConcreteStateData = typename ShadowNodeT::ConcreteStateData;
using SharedConcreteState = std::shared_ptr<const ConcreteState>;
using ConcreteShadowNode = ShadowNodeT;
using ConcreteUnsharedShadowNode = std::shared_ptr<ConcreteShadowNode>;
using ConcreteReferenceCallback =
std::function<void(const std::shared_ptr<ShadowNodeT const>& shadowNode)>;
/*
* Constructs an `Element`.
*/
Element() {
fragment_.componentHandle = ShadowNodeT::Handle();
fragment_.componentName = ShadowNodeT::Name();
fragment_.props = ShadowNodeT::defaultSharedProps();
}
/*
* Converts to `ElementFragment` object.
*/
operator ElementFragment() {
return fragment_;
}
/*
* Sets `tag`.
*/
Element& tag(Tag tag) {
fragment_.tag = tag;
return *this;
}
/*
* Sets `surfaceId`.
*/
Element& surfaceId(SurfaceId surfaceId) {
fragment_.surfaceId = surfaceId;
return *this;
}
/*
* Sets `props`.
*/
Element& props(SharedConcreteProps props) {
fragment_.props = props;
return *this;
}
/*
* Sets `props` using callback.
*/
Element& props(std::function<SharedConcreteProps()> callback) {
fragment_.props = callback();
return *this;
}
/*
* Sets `state` using callback.
*/
Element& stateData(std::function<void(ConcreteStateData&)> callback) {
fragment_.stateCallback =
[callback = std::move(callback)](
const State::Shared& state) -> StateData::Shared {
auto stateData =
static_cast<ConcreteState const*>(state.get())->getData();
callback(stateData);
return std::make_shared<ConcreteStateData>(stateData);
};
return *this;
}
/*
* Sets children.
*/
Element& children(std::vector<ElementFragment> children) {
auto fragments = ElementFragment::List{};
fragments.reserve(children.size());
for (const auto& child : children) {
fragments.push_back(child);
}
fragment_.children = fragments;
return *this;
}
/*
* Calls the callback during component construction with a pointer to the
* component which is being constructed.
*/
Element& reference(
std::function<void(const ConcreteUnsharedShadowNode& shadowNode)>
callback) {
fragment_.referenceCallback =
[callback = std::move(callback)](const ShadowNode::Shared& shadowNode) {
callback(std::const_pointer_cast<ConcreteShadowNode>(
std::static_pointer_cast<ConcreteShadowNode const>(shadowNode)));
};
return *this;
}
/*
* During component construction, assigns a given pointer to a component
* that is being constructed.
*/
Element& reference(ConcreteUnsharedShadowNode& outShadowNode) {
fragment_.referenceCallback = [&](const ShadowNode::Shared& shadowNode) {
outShadowNode = std::const_pointer_cast<ConcreteShadowNode>(
std::static_pointer_cast<ConcreteShadowNode const>(shadowNode));
};
return *this;
}
/*
* Calls the callback with a reference to a just constructed component.
*/
Element& finalize(
std::function<void(ConcreteShadowNode& shadowNode)> finalizeCallback) {
fragment_.finalizeCallback = [=](ShadowNode& shadowNode) {
return finalizeCallback(static_cast<ConcreteShadowNode&>(shadowNode));
};
return *this;
}
private:
friend class ComponentBuilder;
ElementFragment fragment_;
};
} // namespace facebook::react

View File

@@ -0,0 +1,10 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "ElementFragment.h"
// Intentionally empty.

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <functional>
#include <memory>
#include <vector>
#include <react/renderer/core/ShadowNode.h>
namespace facebook::react {
/*
* This is an implementation detail, do not use it directly.
* A type-erased version of `Element<>`.
* `ElementFragment` carries all information that is stored inside `Element<>`
* in some generalized, type-erased manner.
*/
class ElementFragment final {
public:
using Shared = std::shared_ptr<ElementFragment>;
using List = std::vector<ElementFragment>;
using ListOfShared = std::vector<Shared>;
using ReferenceCallback =
std::function<void(const ShadowNode::Unshared& shadowNode)>;
using FinalizeCallback = std::function<void(ShadowNode& shadowNode)>;
using StateCallback =
std::function<StateData::Shared(const State::Shared& state)>;
/*
* ComponentDescriptor part (describes the type)
*/
ComponentHandle componentHandle;
ComponentName componentName;
/*
* ShadowNodeFamily part (describes the family)
*/
Tag tag;
SurfaceId surfaceId;
/*
* ShadowNode part (describes the instance)
*/
Props::Shared props;
List children;
/*
* Other
*/
ReferenceCallback referenceCallback;
FinalizeCallback finalizeCallback;
StateCallback stateCallback;
};
} // namespace facebook::react

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/components/modal/ModalHostViewComponentDescriptor.h>
#include <react/renderer/components/root/RootComponentDescriptor.h>
#include <react/renderer/components/scrollview/ScrollViewComponentDescriptor.h>
#include <react/renderer/components/text/ParagraphComponentDescriptor.h>
#include <react/renderer/components/text/RawTextComponentDescriptor.h>
#include <react/renderer/components/text/TextComponentDescriptor.h>
#include <react/renderer/components/view/ViewComponentDescriptor.h>
#include <react/renderer/element/ComponentBuilder.h>
namespace facebook::react {
inline ComponentBuilder simpleComponentBuilder(
ContextContainer::Shared contextContainer = nullptr) {
ComponentDescriptorProviderRegistry componentDescriptorProviderRegistry{};
auto eventDispatcher = EventDispatcher::Shared{};
auto componentDescriptorRegistry =
componentDescriptorProviderRegistry.createComponentDescriptorRegistry(
ComponentDescriptorParameters{
eventDispatcher, std::move(contextContainer), nullptr});
componentDescriptorProviderRegistry.add(
concreteComponentDescriptorProvider<RootComponentDescriptor>());
componentDescriptorProviderRegistry.add(
concreteComponentDescriptorProvider<ViewComponentDescriptor>());
componentDescriptorProviderRegistry.add(
concreteComponentDescriptorProvider<ScrollViewComponentDescriptor>());
componentDescriptorProviderRegistry.add(
concreteComponentDescriptorProvider<ParagraphComponentDescriptor>());
componentDescriptorProviderRegistry.add(
concreteComponentDescriptorProvider<TextComponentDescriptor>());
componentDescriptorProviderRegistry.add(
concreteComponentDescriptorProvider<RawTextComponentDescriptor>());
componentDescriptorProviderRegistry.add(
concreteComponentDescriptorProvider<ModalHostViewComponentDescriptor>());
return ComponentBuilder{componentDescriptorRegistry};
}
} // namespace facebook::react

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <memory>
#include <gtest/gtest.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/components/root/RootComponentDescriptor.h>
#include <react/renderer/components/view/ViewComponentDescriptor.h>
#include <react/renderer/element/ComponentBuilder.h>
#include <react/renderer/element/Element.h>
#include <react/renderer/element/testUtils.h>
using namespace facebook::react;
TEST(ElementTest, testNormalCases) {
auto builder = simpleComponentBuilder();
auto shadowNodeA = std::shared_ptr<RootShadowNode>{};
auto shadowNodeAA = std::shared_ptr<ViewShadowNode>{};
auto shadowNodeAB = std::shared_ptr<ViewShadowNode>{};
auto shadowNodeABA = std::shared_ptr<ViewShadowNode>{};
auto propsAA = std::make_shared<ViewShadowNodeProps>();
propsAA->nativeId = "node AA";
// clang-format off
auto element =
Element<RootShadowNode>()
.reference(shadowNodeA)
.tag(1)
.props([]() {
auto props = std::make_shared<RootProps>();
props->nativeId = "node A";
return props;
})
.finalize([](RootShadowNode &shadowNode){
shadowNode.sealRecursive();
})
.children({
Element<ViewShadowNode>()
.reference(shadowNodeAA)
.tag(2)
.props(propsAA),
Element<ViewShadowNode>()
.reference(shadowNodeAB)
.tag(3)
.props([]() {
auto props = std::make_shared<ViewShadowNodeProps>();
props->nativeId = "node AB";
return props;
})
.children({
Element<ViewShadowNode>()
.reference(shadowNodeABA)
.tag(4)
.props([]() {
auto props = std::make_shared<ViewShadowNodeProps>();
props->nativeId = "node ABA";
return props;
})
})
});
// clang-format on
auto shadowNode = builder.build(element);
EXPECT_EQ(shadowNode, shadowNodeA);
// Tags
EXPECT_EQ(shadowNodeA->getTag(), 1);
EXPECT_EQ(shadowNodeAA->getTag(), 2);
EXPECT_EQ(shadowNodeAB->getTag(), 3);
EXPECT_EQ(shadowNodeABA->getTag(), 4);
// Children
EXPECT_EQ(shadowNodeA->getChildren().size(), 2);
EXPECT_EQ(shadowNodeAA->getChildren().size(), 0);
EXPECT_EQ(shadowNodeAB->getChildren().size(), 1);
EXPECT_EQ(shadowNodeABA->getChildren().size(), 0);
EXPECT_EQ(
shadowNodeA->getChildren(),
(ShadowNode::ListOfShared{shadowNodeAA, shadowNodeAB}));
EXPECT_EQ(
shadowNodeAB->getChildren(), (ShadowNode::ListOfShared{shadowNodeABA}));
// Props
EXPECT_EQ(shadowNodeA->getProps()->nativeId, "node A");
EXPECT_EQ(shadowNodeABA->getProps()->nativeId, "node ABA");
EXPECT_EQ(shadowNodeAA->getProps(), propsAA);
// Finalize
EXPECT_TRUE(shadowNodeA->getSealed());
EXPECT_TRUE(shadowNodeAA->getSealed());
EXPECT_TRUE(shadowNodeAB->getSealed());
EXPECT_TRUE(shadowNodeABA->getSealed());
}