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,13 @@
/**
* 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.
*
* @flow strict-local
* @format
*/
export * from '../../src/private/specs/modules/NativeSettingsManager';
import NativeSettingsManager from '../../src/private/specs/modules/NativeSettingsManager';
export default NativeSettingsManager;

View File

@@ -0,0 +1,16 @@
/*
* 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.
*/
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
@interface RCTSettingsManager : NSObject <RCTBridgeModule>
- (instancetype)initWithUserDefaults:(NSUserDefaults *)defaults NS_DESIGNATED_INITIALIZER;
@end

View File

@@ -0,0 +1,123 @@
/*
* 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.
*/
#import <React/RCTSettingsManager.h>
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTUtils.h>
#import "RCTSettingsPlugins.h"
@interface RCTSettingsManager () <NativeSettingsManagerSpec>
@end
@implementation RCTSettingsManager {
BOOL _ignoringUpdates;
NSUserDefaults *_defaults;
}
@synthesize moduleRegistry = _moduleRegistry;
RCT_EXPORT_MODULE()
+ (BOOL)requiresMainQueueSetup
{
return NO;
}
- (instancetype)init
{
return [self initWithUserDefaults:[NSUserDefaults standardUserDefaults]];
}
- (instancetype)initWithUserDefaults:(NSUserDefaults *)defaults
{
if ((self = [super init])) {
_defaults = defaults;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(userDefaultsDidChange:)
name:NSUserDefaultsDidChangeNotification
object:_defaults];
}
return self;
}
- (facebook::react::ModuleConstants<JS::NativeSettingsManager::Constants>)constantsToExport
{
return (facebook::react::ModuleConstants<JS::NativeSettingsManager::Constants>)[self getConstants];
}
- (facebook::react::ModuleConstants<JS::NativeSettingsManager::Constants>)getConstants
{
return facebook::react::typedConstants<JS::NativeSettingsManager::Constants>(
{.settings = RCTJSONClean([_defaults dictionaryRepresentation])});
}
- (void)userDefaultsDidChange:(NSNotification *)note
{
if (_ignoringUpdates) {
return;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[_moduleRegistry moduleForName:"EventDispatcher"]
sendDeviceEventWithName:@"settingsUpdated"
body:RCTJSONClean([_defaults dictionaryRepresentation])];
#pragma clang diagnostic pop
}
/**
* Set one or more values in the settings.
* TODO: would it be useful to have a callback for when this has completed?
*/
RCT_EXPORT_METHOD(setValues : (NSDictionary *)values)
{
_ignoringUpdates = YES;
[values enumerateKeysAndObjectsUsingBlock:^(NSString *key, id json, BOOL *stop) {
id plist = [RCTConvert NSPropertyList:json];
if (plist) {
[self->_defaults setObject:plist forKey:key];
} else {
[self->_defaults removeObjectForKey:key];
}
}];
[_defaults synchronize];
_ignoringUpdates = NO;
}
/**
* Remove some values from the settings.
*/
RCT_EXPORT_METHOD(deleteValues : (NSArray<NSString *> *)keys)
{
_ignoringUpdates = YES;
for (NSString *key in keys) {
[_defaults removeObjectForKey:key];
}
[_defaults synchronize];
_ignoringUpdates = NO;
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeSettingsManagerSpecJSI>(params);
}
@end
Class RCTSettingsManagerCls(void)
{
return RCTSettingsManager.class;
}

View File

@@ -0,0 +1,40 @@
/**
* 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.
*
* @generated by an internal plugin build system
*/
#ifdef RN_DISABLE_OSS_PLUGIN_HEADER
// FB Internal: FBRCTSettingsPlugins.h is autogenerated by the build system.
#import <React/FBRCTSettingsPlugins.h>
#else
// OSS-compatibility layer
#import <Foundation/Foundation.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
#ifdef __cplusplus
extern "C" {
#endif
// RCTTurboModuleManagerDelegate should call this to resolve module classes.
Class RCTSettingsClassProvider(const char *name);
// Lookup functions
Class RCTSettingsManagerCls(void) __attribute__((used));
#ifdef __cplusplus
}
#endif
#pragma GCC diagnostic pop
#endif // RN_DISABLE_OSS_PLUGIN_HEADER

View File

@@ -0,0 +1,33 @@
/**
* 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.
*
* @generated by an internal plugin build system
*/
#ifndef RN_DISABLE_OSS_PLUGIN_HEADER
// OSS-compatibility layer
#import "RCTSettingsPlugins.h"
#import <string>
#import <unordered_map>
Class RCTSettingsClassProvider(const char *name) {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"SettingsManager", RCTSettingsManagerCls},
};
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
return nil;
}
#endif // RN_DISABLE_OSS_PLUGIN_HEADER

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.
require "json"
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json")))
version = package['version']
source = { :git => 'https://github.com/facebook/react-native.git' }
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which were presumably in.
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
else
source[:tag] = "v#{version}"
end
folly_config = get_folly_config()
folly_compiler_flags = folly_config[:compiler_flags]
folly_version = folly_config[:version]
header_search_paths = [
"\"$(PODS_ROOT)/RCT-Folly\"",
"\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"",
]
Pod::Spec.new do |s|
s.name = "React-RCTSettings"
s.version = version
s.summary = "A wrapper for NSUserDefaults, a persistent key-value store available only on iOS."
s.homepage = "https://reactnative.dev/"
s.documentation_url = "https://reactnative.dev/docs/settings"
s.license = package["license"]
s.author = "Meta Platforms, Inc. and its affiliates"
s.platforms = min_supported_versions
s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness'
s.source = source
s.source_files = "*.{m,mm}"
s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs"
s.header_dir = "RCTSettings"
s.pod_target_xcconfig = {
"USE_HEADERMAP" => "YES",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
"HEADER_SEARCH_PATHS" => header_search_paths.join(' ')
}
s.dependency "RCT-Folly", folly_version
s.dependency "RCTTypeSafety"
s.dependency "React-jsi"
s.dependency "React-Core/RCTSettingsHeaders"
add_dependency(s, "React-Codegen", :additional_framework_paths => ["build/generated/ios"])
add_dependency(s, "ReactCommon", :subspec => "turbomodule/core", :additional_framework_paths => ["react/nativemodule/core"])
add_dependency(s, "React-NativeModulesApple", :additional_framework_paths => ["build/generated/ios"])
end

View File

@@ -0,0 +1,18 @@
/**
* 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.
*
* @format
*/
export interface SettingsStatic {
get(key: string): any;
set(settings: Object): void;
watchKeys(keys: string | Array<string>, callback: () => void): number;
clearWatch(watchId: number): void;
}
export const Settings: SettingsStatic;
export type Settings = SettingsStatic;

View File

@@ -0,0 +1,81 @@
/**
* 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.
*
* @format
* @flow
*/
import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter';
import NativeSettingsManager from './NativeSettingsManager';
import invariant from 'invariant';
const subscriptions: Array<{
keys: Array<string>,
callback: ?Function,
...
}> = [];
const Settings = {
_settings: (NativeSettingsManager &&
NativeSettingsManager.getConstants().settings: any),
get(key: string): mixed {
// $FlowFixMe[object-this-reference]
return this._settings[key];
},
set(settings: Object) {
// $FlowFixMe[object-this-reference]
this._settings = Object.assign(this._settings, settings);
NativeSettingsManager.setValues(settings);
},
watchKeys(keys: string | Array<string>, callback: Function): number {
if (typeof keys === 'string') {
keys = [keys];
}
invariant(
Array.isArray(keys),
'keys should be a string or array of strings',
);
const sid = subscriptions.length;
subscriptions.push({keys: keys, callback: callback});
return sid;
},
clearWatch(watchId: number) {
if (watchId < subscriptions.length) {
subscriptions[watchId] = {keys: [], callback: null};
}
},
_sendObservations(body: Object) {
Object.keys(body).forEach(key => {
const newValue = body[key];
// $FlowFixMe[object-this-reference]
const didChange = this._settings[key] !== newValue;
// $FlowFixMe[object-this-reference]
this._settings[key] = newValue;
if (didChange) {
subscriptions.forEach(sub => {
if (sub.keys.indexOf(key) !== -1 && sub.callback) {
sub.callback();
}
});
}
});
},
};
RCTDeviceEventEmitter.addListener(
'settingsUpdated',
Settings._sendObservations.bind(Settings),
);
module.exports = Settings;

View File

@@ -0,0 +1,33 @@
/**
* 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.
*
* @format
* @flow
*/
'use strict';
const Settings = {
get(key: string): mixed {
console.warn('Settings is not yet supported on this platform.');
return null;
},
set(settings: Object) {
console.warn('Settings is not yet supported on this platform.');
},
watchKeys(keys: string | Array<string>, callback: Function): number {
console.warn('Settings is not yet supported on this platform.');
return -1;
},
clearWatch(watchId: number) {
console.warn('Settings is not yet supported on this platform.');
},
};
module.exports = Settings;