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,42 @@
"use strict";
exports.__esModule = true;
exports.default = void 0;
var React = _interopRequireWildcard(require("react"));
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function createThemeProvider(defaultTheme, ThemeContext) {
var _class, _temp;
return _temp = _class =
/*#__PURE__*/
function (_React$Component) {
_inheritsLoose(ThemeProvider, _React$Component);
function ThemeProvider() {
return _React$Component.apply(this, arguments) || this;
}
var _proto = ThemeProvider.prototype;
_proto.render = function render() {
return React.createElement(ThemeContext.Provider, {
value: this.props.theme
}, this.props.children);
};
return ThemeProvider;
}(React.Component), _defineProperty(_class, "defaultProps", {
theme: defaultTheme
}), _temp;
}
var _default = createThemeProvider;
exports.default = _default;
//# sourceMappingURL=createThemeProvider.js.map

View File

@@ -0,0 +1,29 @@
/* @flow */
import * as React from 'react';
export type ThemeProviderType<T> = React.ComponentType<{
children: React.Node,
theme?: T,
}>;
function createThemeProvider<T>(
defaultTheme: T,
ThemeContext: React.Context<T>
): ThemeProviderType<T> {
return class ThemeProvider extends React.Component<*> {
static defaultProps = {
theme: defaultTheme,
};
render() {
return (
<ThemeContext.Provider value={this.props.theme}>
{this.props.children}
</ThemeContext.Provider>
);
}
};
}
export default createThemeProvider;

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/createThemeProvider.js"],"names":["createThemeProvider","defaultTheme","ThemeContext","render","props","theme","children","React","Component"],"mappings":";;;;;AAEA;;;;;;;;AAOA,SAASA,mBAAT,CACEC,YADF,EAEEC,YAFF,EAGwB;AAAA;;AACtB;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA,WAKEC,MALF,GAKE,kBAAS;AACP,aACE,oBAAC,YAAD,CAAc,QAAd;AAAuB,QAAA,KAAK,EAAE,KAAKC,KAAL,CAAWC;AAAzC,SACG,KAAKD,KAAL,CAAWE,QADd,CADF;AAKD,KAXH;;AAAA;AAAA,IAAmCC,KAAK,CAACC,SAAzC,2CACwB;AACpBH,IAAAA,KAAK,EAAEJ;AADa,GADxB;AAaD;;eAEcD,mB","sourcesContent":["/* @flow */\n\nimport * as React from 'react';\n\nexport type ThemeProviderType<T> = React.ComponentType<{\n children: React.Node,\n theme?: T,\n}>;\n\nfunction createThemeProvider<T>(\n defaultTheme: T,\n ThemeContext: React.Context<T>\n): ThemeProviderType<T> {\n return class ThemeProvider extends React.Component<*> {\n static defaultProps = {\n theme: defaultTheme,\n };\n\n render() {\n return (\n <ThemeContext.Provider value={this.props.theme}>\n {this.props.children}\n </ThemeContext.Provider>\n );\n }\n };\n}\n\nexport default createThemeProvider;\n"],"file":"createThemeProvider.js"}

View File

@@ -0,0 +1,38 @@
"use strict";
exports.__esModule = true;
exports.default = createTheming;
var React = _interopRequireWildcard(require("react"));
var _deepmerge = _interopRequireDefault(require("deepmerge"));
var _createThemeProvider = _interopRequireDefault(require("./createThemeProvider"));
var _createWithTheme = _interopRequireDefault(require("./createWithTheme"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function createTheming(defaultTheme) {
var ThemeContext = React.createContext(defaultTheme);
var ThemeProvider = (0, _createThemeProvider.default)(defaultTheme, ThemeContext);
var withTheme = (0, _createWithTheme.default)(ThemeProvider, ThemeContext);
var useTheme = function useTheme(overrides) {
var theme = React.useContext(ThemeContext);
var result = React.useMemo(function () {
return theme && overrides ? (0, _deepmerge.default)(theme, overrides) : theme || overrides;
}, [theme, overrides]);
return result;
};
return {
ThemeContext: ThemeContext,
ThemeProvider: ThemeProvider,
withTheme: withTheme,
useTheme: useTheme
};
}
//# sourceMappingURL=createTheming.js.map

View File

@@ -0,0 +1,49 @@
/* @flow */
import * as React from 'react';
import deepmerge from 'deepmerge';
import createThemeProvider from './createThemeProvider';
import createWithTheme from './createWithTheme';
import type { WithThemeType } from './createWithTheme';
import type { ThemeProviderType } from './createThemeProvider';
import type { $DeepShape } from './types';
export type ThemingType<T> = {
ThemeProvider: ThemeProviderType<T>,
withTheme: WithThemeType<T>,
useTheme(overrides?: $DeepShape<T>): T,
};
export default function createTheming<T: Object>(
defaultTheme: T
): ThemingType<T> {
const ThemeContext: React.Context<T> = React.createContext(defaultTheme);
const ThemeProvider: ThemeProviderType<T> = createThemeProvider(
defaultTheme,
ThemeContext
);
const withTheme: WithThemeType<T> = createWithTheme(
ThemeProvider,
ThemeContext
);
const useTheme = (overrides?: $DeepShape<T>): T => {
const theme = React.useContext(ThemeContext);
const result = React.useMemo(
() =>
theme && overrides ? deepmerge(theme, overrides) : theme || overrides,
[theme, overrides]
);
return result;
};
return {
ThemeContext,
ThemeProvider,
withTheme,
useTheme,
};
}

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/createTheming.js"],"names":["createTheming","defaultTheme","ThemeContext","React","createContext","ThemeProvider","withTheme","useTheme","overrides","theme","useContext","result","useMemo"],"mappings":";;;;;AAEA;;AACA;;AACA;;AACA;;;;;;AAWe,SAASA,aAAT,CACbC,YADa,EAEG;AAChB,MAAMC,YAA8B,GAAGC,KAAK,CAACC,aAAN,CAAoBH,YAApB,CAAvC;AAEA,MAAMI,aAAmC,GAAG,kCAC1CJ,YAD0C,EAE1CC,YAF0C,CAA5C;AAKA,MAAMI,SAA2B,GAAG,8BAClCD,aADkC,EAElCH,YAFkC,CAApC;;AAKA,MAAMK,QAAQ,GAAG,SAAXA,QAAW,CAACC,SAAD,EAAkC;AACjD,QAAMC,KAAK,GAAGN,KAAK,CAACO,UAAN,CAAiBR,YAAjB,CAAd;AACA,QAAMS,MAAM,GAAGR,KAAK,CAACS,OAAN,CACb;AAAA,aACEH,KAAK,IAAID,SAAT,GAAqB,wBAAUC,KAAV,EAAiBD,SAAjB,CAArB,GAAmDC,KAAK,IAAID,SAD9D;AAAA,KADa,EAGb,CAACC,KAAD,EAAQD,SAAR,CAHa,CAAf;AAMA,WAAOG,MAAP;AACD,GATD;;AAWA,SAAO;AACLT,IAAAA,YAAY,EAAZA,YADK;AAELG,IAAAA,aAAa,EAAbA,aAFK;AAGLC,IAAAA,SAAS,EAATA,SAHK;AAILC,IAAAA,QAAQ,EAARA;AAJK,GAAP;AAMD","sourcesContent":["/* @flow */\n\nimport * as React from 'react';\nimport deepmerge from 'deepmerge';\nimport createThemeProvider from './createThemeProvider';\nimport createWithTheme from './createWithTheme';\nimport type { WithThemeType } from './createWithTheme';\nimport type { ThemeProviderType } from './createThemeProvider';\nimport type { $DeepShape } from './types';\n\nexport type ThemingType<T> = {\n ThemeProvider: ThemeProviderType<T>,\n withTheme: WithThemeType<T>,\n useTheme(overrides?: $DeepShape<T>): T,\n};\n\nexport default function createTheming<T: Object>(\n defaultTheme: T\n): ThemingType<T> {\n const ThemeContext: React.Context<T> = React.createContext(defaultTheme);\n\n const ThemeProvider: ThemeProviderType<T> = createThemeProvider(\n defaultTheme,\n ThemeContext\n );\n\n const withTheme: WithThemeType<T> = createWithTheme(\n ThemeProvider,\n ThemeContext\n );\n\n const useTheme = (overrides?: $DeepShape<T>): T => {\n const theme = React.useContext(ThemeContext);\n const result = React.useMemo(\n () =>\n theme && overrides ? deepmerge(theme, overrides) : theme || overrides,\n [theme, overrides]\n );\n\n return result;\n };\n\n return {\n ThemeContext,\n ThemeProvider,\n withTheme,\n useTheme,\n };\n}\n"],"file":"createTheming.js"}

View File

@@ -0,0 +1,96 @@
"use strict";
exports.__esModule = true;
exports.default = void 0;
var React = _interopRequireWildcard(require("react"));
var _deepmerge = _interopRequireDefault(require("deepmerge"));
var _hoistNonReactStatics = _interopRequireDefault(require("hoist-non-react-statics"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var createWithTheme = function createWithTheme(ThemeProvider, ThemeContext) {
return function withTheme(Comp) {
var ThemedComponent =
/*#__PURE__*/
function (_React$Component) {
_inheritsLoose(ThemedComponent, _React$Component);
function ThemedComponent() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
_defineProperty(_assertThisInitialized(_this), "_previous", void 0);
_defineProperty(_assertThisInitialized(_this), "_merge", function (a, b) {
var previous = _this._previous;
if (previous && previous.a === a && previous.b === b) {
return previous.result;
}
var result = a && b && a !== b ? (0, _deepmerge.default)(a, b) : a || b;
_this._previous = {
a: a,
b: b,
result: result
};
return result;
});
return _this;
}
var _proto = ThemedComponent.prototype;
_proto.render = function render() {
var _this2 = this;
var _this$props = this.props,
_reactThemeProviderForwardedRef = _this$props._reactThemeProviderForwardedRef,
rest = _objectWithoutPropertiesLoose(_this$props, ["_reactThemeProviderForwardedRef"]);
return React.createElement(ThemeContext.Consumer, null, function (theme) {
return React.createElement(Comp, _extends({}, rest, {
theme: _this2._merge(theme, rest.theme),
ref: _reactThemeProviderForwardedRef
}));
});
};
return ThemedComponent;
}(React.Component);
var ResultComponent = React.forwardRef(function (props, ref) {
return React.createElement(ThemedComponent, _extends({}, props, {
_reactThemeProviderForwardedRef: ref
}));
});
ResultComponent.displayName = "withTheme(" + (Comp.displayName || Comp.name) + ")";
(0, _hoistNonReactStatics.default)(ResultComponent, Comp);
return ResultComponent;
};
};
var _default = createWithTheme;
exports.default = _default;
//# sourceMappingURL=createWithTheme.js.map

View File

@@ -0,0 +1,67 @@
/* @flow */
import * as React from 'react';
import deepmerge from 'deepmerge';
import hoistNonReactStatics from 'hoist-non-react-statics';
import type { ThemeProviderType } from './createThemeProvider';
import type { $DeepShape } from './types';
export type WithThemeType<T> = <P, C: React.ComponentType<P>>(
Comp: C
) => C &
React.ComponentType<
$Diff<React.ElementConfig<C>, { theme: T }> & { theme?: $DeepShape<T> }
>;
const createWithTheme = <T: Object, S: $DeepShape<T>>(
ThemeProvider: ThemeProviderType<T>,
ThemeContext: React.Context<T>
) =>
function withTheme(Comp: *) {
class ThemedComponent extends React.Component<*> {
_previous: ?{ a: T, b: ?S, result: T };
_merge = (a: T, b: ?S) => {
const previous = this._previous;
if (previous && previous.a === a && previous.b === b) {
return previous.result;
}
const result = a && b && a !== b ? deepmerge(a, b) : a || b;
this._previous = { a, b, result };
return result;
};
render() {
const { _reactThemeProviderForwardedRef, ...rest } = this.props;
return (
<ThemeContext.Consumer>
{theme => (
<Comp
{...rest}
theme={this._merge(theme, rest.theme)}
ref={_reactThemeProviderForwardedRef}
/>
)}
</ThemeContext.Consumer>
);
}
}
const ResultComponent = React.forwardRef((props, ref) => (
<ThemedComponent {...props} _reactThemeProviderForwardedRef={ref} />
));
ResultComponent.displayName = `withTheme(${Comp.displayName || Comp.name})`;
hoistNonReactStatics(ResultComponent, Comp);
return (ResultComponent: any);
};
export default createWithTheme;

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/createWithTheme.js"],"names":["createWithTheme","ThemeProvider","ThemeContext","withTheme","Comp","ThemedComponent","a","b","previous","_previous","result","render","props","_reactThemeProviderForwardedRef","rest","theme","_merge","React","Component","ResultComponent","forwardRef","ref","displayName","name"],"mappings":";;;;;AAEA;;AACA;;AACA;;;;;;;;;;;;;;;;AAYA,IAAMA,eAAe,GAAG,SAAlBA,eAAkB,CACtBC,aADsB,EAEtBC,YAFsB;AAAA,SAItB,SAASC,SAAT,CAAmBC,IAAnB,EAA4B;AAAA,QACpBC,eADoB;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA,iEAIf,UAACC,CAAD,EAAOC,CAAP,EAAiB;AACxB,cAAMC,QAAQ,GAAG,MAAKC,SAAtB;;AAEA,cAAID,QAAQ,IAAIA,QAAQ,CAACF,CAAT,KAAeA,CAA3B,IAAgCE,QAAQ,CAACD,CAAT,KAAeA,CAAnD,EAAsD;AACpD,mBAAOC,QAAQ,CAACE,MAAhB;AACD;;AAED,cAAMA,MAAM,GAAGJ,CAAC,IAAIC,CAAL,IAAUD,CAAC,KAAKC,CAAhB,GAAoB,wBAAUD,CAAV,EAAaC,CAAb,CAApB,GAAsCD,CAAC,IAAIC,CAA1D;AAEA,gBAAKE,SAAL,GAAiB;AAAEH,YAAAA,CAAC,EAADA,CAAF;AAAKC,YAAAA,CAAC,EAADA,CAAL;AAAQG,YAAAA,MAAM,EAANA;AAAR,WAAjB;AAEA,iBAAOA,MAAP;AACD,SAhBuB;;AAAA;AAAA;;AAAA;;AAAA,aAkBxBC,MAlBwB,GAkBxB,kBAAS;AAAA;;AAAA,0BAC8C,KAAKC,KADnD;AAAA,YACCC,+BADD,eACCA,+BADD;AAAA,YACqCC,IADrC;;AAGP,eACE,oBAAC,YAAD,CAAc,QAAd,QACG,UAAAC,KAAK;AAAA,iBACJ,oBAAC,IAAD,eACMD,IADN;AAEE,YAAA,KAAK,EAAE,MAAI,CAACE,MAAL,CAAYD,KAAZ,EAAmBD,IAAI,CAACC,KAAxB,CAFT;AAGE,YAAA,GAAG,EAAEF;AAHP,aADI;AAAA,SADR,CADF;AAWD,OAhCuB;;AAAA;AAAA,MACII,KAAK,CAACC,SADV;;AAmC1B,QAAMC,eAAe,GAAGF,KAAK,CAACG,UAAN,CAAiB,UAACR,KAAD,EAAQS,GAAR;AAAA,aACvC,oBAAC,eAAD,eAAqBT,KAArB;AAA4B,QAAA,+BAA+B,EAAES;AAA7D,SADuC;AAAA,KAAjB,CAAxB;AAIAF,IAAAA,eAAe,CAACG,WAAhB,mBAA2ClB,IAAI,CAACkB,WAAL,IAAoBlB,IAAI,CAACmB,IAApE;AAEA,uCAAqBJ,eAArB,EAAsCf,IAAtC;AAEA,WAAQe,eAAR;AACD,GAhDqB;AAAA,CAAxB;;eAkDenB,e","sourcesContent":["/* @flow */\n\nimport * as React from 'react';\nimport deepmerge from 'deepmerge';\nimport hoistNonReactStatics from 'hoist-non-react-statics';\n\nimport type { ThemeProviderType } from './createThemeProvider';\nimport type { $DeepShape } from './types';\n\nexport type WithThemeType<T> = <P, C: React.ComponentType<P>>(\n Comp: C\n) => C &\n React.ComponentType<\n $Diff<React.ElementConfig<C>, { theme: T }> & { theme?: $DeepShape<T> }\n >;\n\nconst createWithTheme = <T: Object, S: $DeepShape<T>>(\n ThemeProvider: ThemeProviderType<T>,\n ThemeContext: React.Context<T>\n) =>\n function withTheme(Comp: *) {\n class ThemedComponent extends React.Component<*> {\n _previous: ?{ a: T, b: ?S, result: T };\n\n _merge = (a: T, b: ?S) => {\n const previous = this._previous;\n\n if (previous && previous.a === a && previous.b === b) {\n return previous.result;\n }\n\n const result = a && b && a !== b ? deepmerge(a, b) : a || b;\n\n this._previous = { a, b, result };\n\n return result;\n };\n\n render() {\n const { _reactThemeProviderForwardedRef, ...rest } = this.props;\n\n return (\n <ThemeContext.Consumer>\n {theme => (\n <Comp\n {...rest}\n theme={this._merge(theme, rest.theme)}\n ref={_reactThemeProviderForwardedRef}\n />\n )}\n </ThemeContext.Consumer>\n );\n }\n }\n\n const ResultComponent = React.forwardRef((props, ref) => (\n <ThemedComponent {...props} _reactThemeProviderForwardedRef={ref} />\n ));\n\n ResultComponent.displayName = `withTheme(${Comp.displayName || Comp.name})`;\n\n hoistNonReactStatics(ResultComponent, Comp);\n\n return (ResultComponent: any);\n };\n\nexport default createWithTheme;\n"],"file":"createWithTheme.js"}

View File

@@ -0,0 +1,10 @@
"use strict";
exports.__esModule = true;
var _createTheming = _interopRequireDefault(require("./createTheming"));
exports.createTheming = _createTheming.default;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,6 @@
/* @flow */
import createTheming from './createTheming';
export { createTheming };
export type { ThemingType } from './createTheming';

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../src/index.js"],"names":[],"mappings":";;;;AAEA","sourcesContent":["/* @flow */\n\nimport createTheming from './createTheming';\n\nexport { createTheming };\nexport type { ThemingType } from './createTheming';\n"],"file":"index.js"}

View File

@@ -0,0 +1,2 @@
"use strict";
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1,5 @@
/* @flow */
export type $DeepShape<O: Object> = $Shape<
$ObjMap<O, (<V: Object>(V) => $DeepShape<V>) & (<V>(V) => V)>
>;

View File

@@ -0,0 +1 @@
{"version":3,"sources":[],"names":[],"mappings":"","sourcesContent":[],"file":"types.js"}