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,17 @@
import { DetachedCommandFunction } from '@react-native-community/cli-types';
type FlagsT = {
fix: boolean | void;
contributor: boolean | void;
};
declare const _default: {
func: DetachedCommandFunction<FlagsT>;
detached: boolean;
name: string;
description: string;
options: {
name: string;
description: string;
}[];
};
export default _default;
//# sourceMappingURL=doctor.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,uBAAuB,EAAC,MAAM,mCAAmC,CAAC;AAiF1E,KAAK,MAAM,GAAG;IACZ,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7B,CAAC;;;;;;;;;;;AA8KF,wBAiBE"}

View File

@@ -0,0 +1,229 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
function _cliTools() {
const data = require("@react-native-community/cli-tools");
_cliTools = function () {
return data;
};
return data;
}
var _healthchecks = require("../tools/healthchecks");
var _printFixOptions = _interopRequireWildcard(require("../tools/printFixOptions"));
var _runAutomaticFix = _interopRequireWildcard(require("../tools/runAutomaticFix"));
var _envinfo = _interopRequireDefault(require("../tools/envinfo"));
var _common = require("../tools/healthchecks/common");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const printCategory = ({
label,
key
}) => {
if (key > 0) {
_cliTools().logger.log();
}
_cliTools().logger.log(_chalk().default.dim(label));
};
const printVersions = ({
version,
versions,
versionRange
}) => {
if (versions) {
const versionsToShow = Array.isArray(versions) ? versions.join(', ') : 'N/A';
(0, _common.logMessage)(`- Versions found: ${_chalk().default.red(versionsToShow)}`);
(0, _common.logMessage)(`- Version supported: ${_chalk().default.green(versionRange)}`);
return;
}
const versionsToShow = version && version !== 'Not Found' ? version : 'N/A';
(0, _common.logMessage)(`- Version found: ${_chalk().default.red(versionsToShow)}`);
(0, _common.logMessage)(`- Version supported: ${_chalk().default.green(versionRange)}`);
return;
};
const printIssue = ({
label,
needsToBeFixed,
version,
versions,
versionRange,
isRequired,
description
}) => {
const symbol = needsToBeFixed ? isRequired ? _chalk().default.red('✖') : _chalk().default.yellow('●') : _chalk().default.green('✓');
const descriptionToShow = description ? ` - ${description}` : '';
_cliTools().logger.log(` ${symbol} ${label}${descriptionToShow}`);
if (needsToBeFixed && versionRange) {
return printVersions({
version,
versions,
versionRange
});
}
};
const printOverallStats = ({
errors,
warnings
}) => {
_cliTools().logger.log(`\n${_chalk().default.bold('Errors:')} ${errors}`);
_cliTools().logger.log(`${_chalk().default.bold('Warnings:')} ${warnings}`);
};
/**
* Given a `healthcheck` and a `platform`, returns the specific fix for
* it or the fallback one if there is not one (`runAutomaticFix`).
*/
const getAutomaticFixForPlatform = (healthcheck, platform) => {
switch (platform) {
case 'win32':
return healthcheck.win32AutomaticFix || healthcheck.runAutomaticFix;
case 'darwin':
return healthcheck.darwinAutomaticFix || healthcheck.runAutomaticFix;
case 'linux':
return healthcheck.linuxAutomaticFix || healthcheck.runAutomaticFix;
default:
return healthcheck.runAutomaticFix;
}
};
const doctorCommand = async (_, options, config) => {
const loader = (0, _cliTools().getLoader)();
loader.start('Running diagnostics...');
const environmentInfo = await (0, _envinfo.default)();
const iterateOverHealthChecks = async ({
label,
healthchecks
}) => ({
label,
healthchecks: (await Promise.all(healthchecks.map(async healthcheck => {
if (healthcheck.visible === false) {
return;
}
const {
description,
needsToBeFixed,
version,
versions,
versionRange
} = await healthcheck.getDiagnostics(environmentInfo, config);
// Assume that it's required unless specified otherwise
const isRequired = healthcheck.isRequired !== false;
const isWarning = needsToBeFixed && !isRequired;
return {
label: healthcheck.label,
needsToBeFixed: Boolean(needsToBeFixed),
version,
versions,
versionRange,
description: description ?? healthcheck.description,
runAutomaticFix: getAutomaticFixForPlatform(healthcheck, process.platform),
isRequired,
type: needsToBeFixed ? isWarning ? _healthchecks.HEALTHCHECK_TYPES.WARNING : _healthchecks.HEALTHCHECK_TYPES.ERROR : undefined
};
}))).filter(healthcheck => healthcheck !== undefined)
});
// Remove all the categories that don't have any healthcheck with
// `needsToBeFixed` so they don't show when the user taps to fix encountered
// issues
const removeFixedCategories = categories => categories.filter(category => category.healthchecks.some(healthcheck => healthcheck.needsToBeFixed));
const iterateOverCategories = categories => Promise.all(categories.map(iterateOverHealthChecks));
const healthchecksPerCategory = await iterateOverCategories(Object.values((0, _healthchecks.getHealthchecks)(options)).filter(category => category !== undefined));
loader.stop();
const stats = {
errors: 0,
warnings: 0
};
healthchecksPerCategory.forEach((issueCategory, key) => {
printCategory({
...issueCategory,
key
});
issueCategory.healthchecks.forEach(healthcheck => {
printIssue(healthcheck);
if (healthcheck.type === _healthchecks.HEALTHCHECK_TYPES.WARNING) {
stats.warnings++;
return;
}
if (healthcheck.type === _healthchecks.HEALTHCHECK_TYPES.ERROR) {
stats.errors++;
return;
}
});
});
printOverallStats(stats);
if (options.fix) {
return await (0, _runAutomaticFix.default)({
healthchecks: removeFixedCategories(healthchecksPerCategory),
automaticFixLevel: _runAutomaticFix.AUTOMATIC_FIX_LEVELS.ALL_ISSUES,
stats,
loader,
environmentInfo,
config
});
}
const removeKeyPressListener = () => {
if (typeof process.stdin.setRawMode === 'function') {
process.stdin.setRawMode(false);
}
process.stdin.removeAllListeners('data');
};
const onKeyPress = async key => {
if (key === _printFixOptions.KEYS.EXIT || key === '\u0003') {
removeKeyPressListener();
process.exit(0);
}
if ([_printFixOptions.KEYS.FIX_ALL_ISSUES, _printFixOptions.KEYS.FIX_ERRORS, _printFixOptions.KEYS.FIX_WARNINGS].includes(key)) {
removeKeyPressListener();
try {
const automaticFixLevel = {
[_printFixOptions.KEYS.FIX_ALL_ISSUES]: _runAutomaticFix.AUTOMATIC_FIX_LEVELS.ALL_ISSUES,
[_printFixOptions.KEYS.FIX_ERRORS]: _runAutomaticFix.AUTOMATIC_FIX_LEVELS.ERRORS,
[_printFixOptions.KEYS.FIX_WARNINGS]: _runAutomaticFix.AUTOMATIC_FIX_LEVELS.WARNINGS
};
await (0, _runAutomaticFix.default)({
healthchecks: removeFixedCategories(healthchecksPerCategory),
automaticFixLevel: automaticFixLevel[key],
stats,
loader,
environmentInfo,
config
});
process.exit(0);
} catch (err) {
_cliTools().logger.log(err.stderr || err.stdout);
throw new (_cliTools().CLIError)('Failed to run automatic fixes.', err);
}
}
};
if (stats.errors || stats.warnings) {
(0, _printFixOptions.default)({
onKeyPress
});
}
};
var _default = {
func: doctorCommand,
detached: true,
name: 'doctor',
description: 'Diagnose and fix common Node.js, iOS, Android & React Native issues.',
options: [{
name: '--fix',
description: 'Attempt to fix all diagnosed issues.'
}, {
name: '--contributor',
description: 'Add healthchecks required to installations required for contributing to React Native.'
}]
};
exports.default = _default;
//# sourceMappingURL=doctor.ts.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Config } from '@react-native-community/cli-types';
declare const _default: {
name: string;
description: string;
func: (_argv: string[], ctx: Config) => Promise<void>;
};
export default _default;
//# sourceMappingURL=info.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"info.d.ts","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;;;;;;AAoFzD,wBAIE"}

View File

@@ -0,0 +1,108 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _envinfo = _interopRequireDefault(require("../tools/envinfo"));
function _cliTools() {
const data = require("@react-native-community/cli-tools");
_cliTools = function () {
return data;
};
return data;
}
function _cliPlatformApple() {
const data = require("@react-native-community/cli-platform-apple");
_cliPlatformApple = function () {
return data;
};
return data;
}
function _fsExtra() {
const data = require("fs-extra");
_fsExtra = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _yaml() {
const data = require("yaml");
_yaml = function () {
return data;
};
return data;
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const info = async function getInfo(_argv, ctx) {
try {
var _ctx$project$ios, _ctx$project$android;
_cliTools().logger.info('Fetching system and libraries information...');
const notFound = 'Not found';
const platforms = {
Android: {
hermesEnabled: notFound,
newArchEnabled: notFound
},
iOS: {
hermesEnabled: notFound,
newArchEnabled: notFound
}
};
if (process.platform !== 'win32' && ((_ctx$project$ios = ctx.project.ios) === null || _ctx$project$ios === void 0 ? void 0 : _ctx$project$ios.sourceDir)) {
try {
const podfile = await (0, _fsExtra().readFile)(_path().default.join(ctx.project.ios.sourceDir, '/Podfile.lock'), 'utf8');
platforms.iOS.hermesEnabled = podfile.includes('hermes-engine');
} catch (e) {
platforms.iOS.hermesEnabled = notFound;
}
try {
const isNewArchitecture = await (0, _cliPlatformApple().getArchitecture)(ctx.project.ios.sourceDir);
platforms.iOS.newArchEnabled = isNewArchitecture;
} catch {
platforms.iOS.newArchEnabled = notFound;
}
}
if ((_ctx$project$android = ctx.project.android) === null || _ctx$project$android === void 0 ? void 0 : _ctx$project$android.sourceDir) {
try {
const gradleProperties = await (0, _fsExtra().readFile)(_path().default.join(ctx.project.android.sourceDir, '/gradle.properties'), 'utf8');
platforms.Android.hermesEnabled = gradleProperties.includes('hermesEnabled=true');
platforms.Android.newArchEnabled = gradleProperties.includes('newArchEnabled=true');
} catch {
platforms.Android.hermesEnabled = notFound;
platforms.Android.newArchEnabled = notFound;
}
}
const output = await (0, _envinfo.default)();
_cliTools().logger.log((0, _yaml().stringify)({
...output,
...platforms
}));
} catch (err) {
_cliTools().logger.error(`Unable to print environment info.\n${err}`);
} finally {
await _cliTools().version.logIfUpdateAvailable(ctx.root);
}
};
var _default = {
name: 'info',
description: 'Get relevant version info about OS, toolchain and libraries',
func: info
};
exports.default = _default;
//# sourceMappingURL=info.ts.map

File diff suppressed because one or more lines are too long