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,340 @@
#include "JSISerializer.h"
#include <cxxabi.h>
#include <iostream>
#include <sstream>
const std::vector<std::string> SUPPORTED_ERROR_TYPES = {
"Error",
"AggregateError",
"EvalError",
"RangeError",
"ReferenceError",
"SyntaxError",
"TypeError",
"URIError",
"InternalError"};
const std::vector<std::string> SUPPORTED_INDEXED_COLLECTION_TYPES = {
"Int8Array",
"Uint8Array",
"Uint8ClampedArray",
"Int16Array",
"Uint16Array",
"Int32Array",
"Uint32Array",
"BigInt64Array",
"BigUint64Array",
"Float32Array",
"Float64Array",
};
const std::vector<std::string> SUPPORTED_STRUCTURED_DATA_TYPES = {
"ArrayBuffer",
"SharedArrayBuffer",
"DataView",
"Atomics",
"JSON",
};
const std::vector<std::string> SUPPORTED_MANAGING_MEMORY_TYPES = {
"WeakRef",
"FinalizationRegistry",
};
const std::vector<std::string> SUPPORTED_ABSTRACTION_OBJECT_TYPES = {
"Iterator",
"AsyncIterator",
"Promise",
"GeneratorFunction",
"AsyncGeneratorFunction",
"Generator",
"AsyncGenerator",
"AsyncFunction",
};
const std::vector<std::string> SUPPORTED_REFLECTION_TYPES = {
"Reflect",
"Proxy",
};
static inline std::string getObjectTypeName(
jsi::Runtime &rt,
const jsi::Object &object) {
return object.getPropertyAsObject(rt, "constructor")
.getProperty(rt, "name")
.toString(rt)
.utf8(rt);
}
static inline bool isInstanceOf(
jsi::Runtime &rt,
const jsi::Object &object,
const std::string &type) {
return getObjectTypeName(rt, object) == type;
}
static inline bool isInstanceOfAny(
jsi::Runtime &rt,
const jsi::Object &object,
const std::vector<std::string> &supportedTypes) {
auto instanceType = getObjectTypeName(rt, object);
return std::find(
supportedTypes.begin(), supportedTypes.end(), instanceType) !=
supportedTypes.end();
}
JSISerializer::JSISerializer(jsi::Runtime &rt)
: rt_(rt),
visitedNodes_(rt_.global()
.getPropertyAsFunction(rt_, "Set")
.callAsConstructor(rt_)
.asObject(rt_)) {}
std::string JSISerializer::stringifyWithName(const jsi::Object &object) {
std::stringstream ss;
ss << '[' << getObjectTypeName(rt_, object) << ']';
return ss.str();
}
std::string JSISerializer::stringifyArray(const jsi::Array &arr) {
std::stringstream ss;
ss << '[';
for (size_t i = 0, length = arr.size(rt_); i < length; i++) {
jsi::Value element = arr.getValueAtIndex(rt_, i);
ss << stringifyJSIValueRecursively(element);
if (i != length - 1) {
ss << ", ";
}
}
ss << ']';
return ss.str();
}
std::string JSISerializer::stringifyFunction(const jsi::Function &func) {
std::stringstream ss;
auto kind = (func.isHostFunction(rt_) ? "jsi::HostFunction" : "Function");
auto name = func.getProperty(rt_, "name").toString(rt_).utf8(rt_);
name = name.empty() ? "anonymous" : name;
ss << '[' << kind << ' ' << name << ']';
return ss.str();
}
std::string JSISerializer::stringifyHostObject(jsi::HostObject &hostObject) {
int status = -1;
char *hostObjClassName =
abi::__cxa_demangle(typeid(hostObject).name(), NULL, NULL, &status);
if (status != 0) {
return "[jsi::HostObject]";
}
std::stringstream ss;
ss << "[jsi::HostObject(" << hostObjClassName << ")";
std::free(hostObjClassName);
auto props = hostObject.getPropertyNames(rt_);
auto propsCount = props.size();
if (propsCount > 0) {
ss << " {";
auto lastKey = props.back().utf8(rt_);
for (const auto &key : props) {
auto formattedKey = key.utf8(rt_);
auto value = hostObject.get(rt_, key);
ss << '"' << formattedKey << '"' << ": "
<< stringifyJSIValueRecursively(value);
if (formattedKey != lastKey) {
ss << ", ";
}
}
ss << '}';
}
ss << ']';
return ss.str();
}
std::string JSISerializer::stringifyObject(const jsi::Object &object) {
std::stringstream ss;
ss << '{';
auto props = object.getPropertyNames(rt_);
for (size_t i = 0, propsCount = props.size(rt_); i < propsCount; i++) {
jsi::String propName = props.getValueAtIndex(rt_, i).toString(rt_);
ss << '"' << propName.utf8(rt_) << '"' << ": "
<< stringifyJSIValueRecursively(object.getProperty(rt_, propName));
if (i != propsCount - 1) {
ss << ", ";
}
}
ss << '}';
return ss.str();
}
std::string JSISerializer::stringifyError(const jsi::Object &object) {
std::stringstream ss;
ss << '[' << object.getProperty(rt_, "name").toString(rt_).utf8(rt_) << ": "
<< object.getProperty(rt_, "message").toString(rt_).utf8(rt_) << ']';
return ss.str();
}
std::string JSISerializer::stringifySet(const jsi::Object &object) {
std::stringstream ss;
jsi::Function arrayFrom = rt_.global()
.getPropertyAsObject(rt_, "Array")
.getPropertyAsFunction(rt_, "from");
jsi::Object result = arrayFrom.call(rt_, object).asObject(rt_);
if (!result.isArray(rt_)) {
return "[Set]";
}
auto arr = result.asArray(rt_);
ss << "Set {";
for (size_t i = 0, length = arr.size(rt_); i < length; i++) {
ss << stringifyJSIValueRecursively(arr.getValueAtIndex(rt_, i));
if (i != length - 1) {
ss << ", ";
}
}
ss << '}';
return ss.str();
}
std::string JSISerializer::stringifyMap(const jsi::Object &object) {
std::stringstream ss;
jsi::Function arrayFrom = rt_.global()
.getPropertyAsObject(rt_, "Array")
.getPropertyAsFunction(rt_, "from");
jsi::Object result = arrayFrom.call(rt_, object).asObject(rt_);
if (!result.isArray(rt_)) {
return "[Map]";
}
auto arr = result.asArray(rt_);
ss << "Map {";
for (size_t i = 0, length = arr.size(rt_); i < length; i++) {
auto pair = arr.getValueAtIndex(rt_, i).asObject(rt_).getArray(rt_);
auto key = pair.getValueAtIndex(rt_, 0);
auto value = pair.getValueAtIndex(rt_, 1);
ss << stringifyJSIValueRecursively(key) << ": "
<< stringifyJSIValueRecursively(value);
if (i != length - 1) {
ss << ", ";
}
}
ss << '}';
return ss.str();
}
std::string JSISerializer::stringifyRecursiveType(const jsi::Object &object) {
auto type = getObjectTypeName(rt_, object);
if (type == "Array") {
return "[...]";
}
if (type == "Object") {
return "{...}";
}
return "...";
}
std::string JSISerializer::stringifyWithToString(const jsi::Object &object) {
return object.getPropertyAsFunction(rt_, "toString")
.callWithThis(rt_, object)
.toString(rt_)
.utf8(rt_);
}
std::string JSISerializer::stringifyJSIValueRecursively(
const jsi::Value &value,
bool isTopLevel) {
if (value.isBool() || value.isNumber()) {
return value.toString(rt_).utf8(rt_);
}
if (value.isString()) {
return isTopLevel ? value.getString(rt_).utf8(rt_)
: '"' + value.getString(rt_).utf8(rt_) + '"';
}
if (value.isSymbol()) {
return value.getSymbol(rt_).toString(rt_);
}
#if REACT_NATIVE_MINOR_VERSION >= 71
if (value.isBigInt()) {
return value.getBigInt(rt_).toString(rt_).utf8(rt_) + 'n';
}
#endif
if (value.isUndefined()) {
return "undefined";
}
if (value.isNull()) {
return "null";
}
if (value.isObject()) {
jsi::Object object = value.asObject(rt_);
if (hasBeenVisited(object)) {
return stringifyRecursiveType(object);
}
markAsVisited(object);
if (object.isArray(rt_)) {
return stringifyArray(object.getArray(rt_));
}
if (object.isFunction(rt_)) {
return stringifyFunction(object.getFunction(rt_));
}
if (object.isHostObject(rt_)) {
return stringifyHostObject(*object.getHostObject(rt_));
}
if (isInstanceOfAny(rt_, object, SUPPORTED_ERROR_TYPES)) {
return stringifyError(object);
}
if (isInstanceOfAny(rt_, object, SUPPORTED_INDEXED_COLLECTION_TYPES) ||
isInstanceOfAny(rt_, object, SUPPORTED_STRUCTURED_DATA_TYPES) ||
isInstanceOfAny(rt_, object, SUPPORTED_MANAGING_MEMORY_TYPES) ||
isInstanceOfAny(rt_, object, SUPPORTED_ABSTRACTION_OBJECT_TYPES) ||
isInstanceOfAny(rt_, object, SUPPORTED_REFLECTION_TYPES) ||
isInstanceOf(rt_, object, "Intl") ||
isInstanceOf(rt_, object, "WeakMap") ||
isInstanceOf(rt_, object, "WeakSet")) {
// TODO: Consider extending this log info
return stringifyWithName(object);
}
if (isInstanceOf(rt_, object, "Date") ||
isInstanceOf(rt_, object, "RegExp")) {
return stringifyWithToString(object);
}
if (isInstanceOf(rt_, object, "Map")) {
return stringifyMap(object);
}
if (isInstanceOf(rt_, object, "Set")) {
return stringifySet(object);
}
return stringifyObject(object);
}
throw std::runtime_error("[Reanimated] Unsupported value type.");
}
std::string stringifyJSIValue(jsi::Runtime &rt, const jsi::Value &value) {
JSISerializer serializer(rt);
return serializer.stringifyJSIValueRecursively(value, true);
}