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,125 @@
/**
* 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
* @oncall react_native
*/
'use strict';
import type {IndexMap} from '../source-map';
import type {
GeneratedOffset,
GeneratedPositionLookup,
IConsumer,
Mapping,
SourcePosition,
} from './types.flow';
const AbstractConsumer = require('./AbstractConsumer');
const {EMPTY_POSITION, FIRST_COLUMN, FIRST_LINE} = require('./constants');
const createConsumer = require('./createConsumer');
const {subtractOffsetFromPosition} = require('./positionMath');
const {greatestLowerBound} = require('./search');
const {add, add0, get0, get1, sub, sub1} = require('ob1');
/**
* A source map consumer that supports "indexed" source maps (that have a
* `sections` field and no top-level mappings).
*/
class SectionsConsumer extends AbstractConsumer implements IConsumer {
_consumers: $ReadOnlyArray<[GeneratedOffset, IConsumer]>;
constructor(sourceMap: IndexMap) {
super(sourceMap);
this._consumers = sourceMap.sections.map((section, index) => {
const generatedOffset = {
lines: add0(section.offset.line),
columns: add0(section.offset.column),
};
const consumer = createConsumer(section.map);
return [generatedOffset, consumer];
});
}
originalPositionFor(
generatedPosition: GeneratedPositionLookup,
): SourcePosition {
const [generatedOffset, consumer] =
this._consumerForPosition(generatedPosition) || [];
if (!consumer) {
return {...EMPTY_POSITION};
}
return consumer.originalPositionFor(
subtractOffsetFromPosition(generatedPosition, generatedOffset),
);
}
*generatedMappings(): Iterable<Mapping> {
for (const [generatedOffset, consumer] of this._consumers) {
let first = true;
for (const mapping of consumer.generatedMappings()) {
if (
first &&
(get1(mapping.generatedLine) > 1 || get0(mapping.generatedColumn) > 0)
) {
yield {
generatedLine: FIRST_LINE,
generatedColumn: FIRST_COLUMN,
source: null,
name: null,
originalLine: null,
originalColumn: null,
};
}
first = false;
yield {
...mapping,
generatedLine: add(mapping.generatedLine, generatedOffset.lines),
generatedColumn: add(
mapping.generatedColumn,
generatedOffset.columns,
),
};
}
}
}
_consumerForPosition(
generatedPosition: GeneratedPositionLookup,
): ?[GeneratedOffset, IConsumer] {
const {line, column} = generatedPosition;
if (line == null || column == null) {
return null;
}
const index = greatestLowerBound(
this._consumers,
generatedPosition,
(position, [offset]) => {
const line0 = sub1(line);
const column0 = column;
if (line0 === offset.lines) {
return get0(sub(column0, offset.columns));
}
return get0(sub(line0, offset.lines));
},
);
return index != null ? this._consumers[index] : null;
}
sourceContentFor(source: string, nullOnMissing: true): ?string {
for (const [_, consumer] of this._consumers) {
const content = consumer.sourceContentFor(source, nullOnMissing);
if (content != null) {
return content;
}
}
return null;
}
}
module.exports = SectionsConsumer;