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,58 @@
/**
* 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
*/
import {NativeEventSubscription} from '../EventEmitter/RCTNativeAppEventEmitter';
/**
* AppState can tell you if the app is in the foreground or background,
* and notify you when the state changes.
*
* AppState is frequently used to determine the intent and proper behavior
* when handling push notifications.
*
* App State Events
* change - This even is received when the app state has changed.
* focus [Android] - Received when the app gains focus (the user is interacting with the app).
* blur [Android] - Received when the user is not actively interacting with the app.
*
* App States
* active - The app is running in the foreground
* background - The app is running in the background. The user is either in another app or on the home screen
* inactive [iOS] - This is a transition state that happens when the app launches, is asking for permissions or when a call or SMS message is received.
* unknown [iOS] - Initial value until the current app state is determined
* extension [iOS] - The app is running as an app extension
*
* For more information, see Apple's documentation: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html
*
* @see https://reactnative.dev/docs/appstate#app-states
*/
export type AppStateEvent = 'change' | 'memoryWarning' | 'blur' | 'focus';
export type AppStateStatus =
| 'active'
| 'background'
| 'inactive'
| 'unknown'
| 'extension';
export interface AppStateStatic {
currentState: AppStateStatus;
isAvailable: boolean;
/**
* Add a handler to AppState changes by listening to the change event
* type and providing the handler
*/
addEventListener(
type: AppStateEvent,
listener: (state: AppStateStatus) => void,
): NativeEventSubscription;
}
export const AppState: AppStateStatic;
export type AppState = AppStateStatic;

View File

@@ -0,0 +1,128 @@
/**
* 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
*/
import NativeEventEmitter from '../EventEmitter/NativeEventEmitter';
import logError from '../Utilities/logError';
import Platform from '../Utilities/Platform';
import {type EventSubscription} from '../vendor/emitter/EventEmitter';
import NativeAppState from './NativeAppState';
export type AppStateValues = 'inactive' | 'background' | 'active';
type AppStateEventDefinitions = {
change: [AppStateValues],
memoryWarning: [],
blur: [],
focus: [],
};
type NativeAppStateEventDefinitions = {
appStateDidChange: [{app_state: AppStateValues}],
appStateFocusChange: [boolean],
memoryWarning: [],
};
/**
* `AppState` can tell you if the app is in the foreground or background,
* and notify you when the state changes.
*
* See https://reactnative.dev/docs/appstate
*/
class AppState {
currentState: ?string = null;
isAvailable: boolean;
_emitter: ?NativeEventEmitter<NativeAppStateEventDefinitions>;
constructor() {
if (NativeAppState == null) {
this.isAvailable = false;
} else {
this.isAvailable = true;
const emitter: NativeEventEmitter<NativeAppStateEventDefinitions> =
new NativeEventEmitter(
// T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior
// If you want to use the native module on other platforms, please remove this condition and test its behavior
Platform.OS !== 'ios' ? null : NativeAppState,
);
this._emitter = emitter;
this.currentState = NativeAppState.getConstants().initialAppState;
let eventUpdated = false;
// TODO: this is a terrible solution - in order to ensure `currentState`
// prop is up to date, we have to register an observer that updates it
// whenever the state changes, even if nobody cares. We should just
// deprecate the `currentState` property and get rid of this.
emitter.addListener('appStateDidChange', appStateData => {
eventUpdated = true;
this.currentState = appStateData.app_state;
});
// TODO: see above - this request just populates the value of `currentState`
// when the module is first initialized. Would be better to get rid of the
// prop and expose `getCurrentAppState` method directly.
// $FlowExpectedError[incompatible-call]
NativeAppState.getCurrentAppState(appStateData => {
// It's possible that the state will have changed here & listeners need to be notified
if (!eventUpdated && this.currentState !== appStateData.app_state) {
this.currentState = appStateData.app_state;
// $FlowFixMe[incompatible-call]
emitter.emit('appStateDidChange', appStateData);
}
}, logError);
}
}
/**
* Add a handler to AppState changes by listening to the `change` event type
* and providing the handler.
*
* See https://reactnative.dev/docs/appstate#addeventlistener
*/
addEventListener<K: $Keys<AppStateEventDefinitions>>(
type: K,
handler: (...$ElementType<AppStateEventDefinitions, K>) => void,
): EventSubscription {
const emitter = this._emitter;
if (emitter == null) {
throw new Error('Cannot use AppState when `isAvailable` is false.');
}
switch (type) {
case 'change':
// $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type
const changeHandler: AppStateValues => void = handler;
return emitter.addListener('appStateDidChange', appStateData => {
changeHandler(appStateData.app_state);
});
case 'memoryWarning':
// $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type
const memoryWarningHandler: () => void = handler;
return emitter.addListener('memoryWarning', memoryWarningHandler);
case 'blur':
case 'focus':
// $FlowIssue[invalid-tuple-arity] Flow cannot refine handler based on the event type
const focusOrBlurHandler: () => void = handler;
return emitter.addListener('appStateFocusChange', hasFocus => {
if (type === 'blur' && !hasFocus) {
focusOrBlurHandler();
}
if (type === 'focus' && hasFocus) {
focusOrBlurHandler();
}
});
}
throw new Error('Trying to subscribe to unknown event: ' + type);
}
}
module.exports = (new AppState(): AppState);

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/NativeAppState';
import NativeAppState from '../../src/private/specs/modules/NativeAppState';
export default NativeAppState;