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,131 @@
import { ApplicationReleaseType, PushNotificationServiceEnvironment } from './Application.types';
/**
* The human-readable version of the native application that may be displayed in the app store.
* This is the `Info.plist` value for `CFBundleShortVersionString` on iOS and the version name set
* by `version` in `app.json` on Android at the time the native app was built.
* On web, this value is `null`.
* @example
* `"2.11.0"`
*/
export declare const nativeApplicationVersion: string | null;
/**
* The internal build version of the native application that the app store may use to distinguish
* between different binaries. This is the `Info.plist` value for `CFBundleVersion` on iOS (set with
* `ios.buildNumber` value in `app.json` in a standalone app) and the version code set by
* `android.versionCode` in `app.json` on Android at the time the native app was built. On web, this
* value is `null`. The return type on Android and iOS is `string`.
* @example
* Android: `"114"`, iOS: `"2.11.0"`
*/
export declare const nativeBuildVersion: string | null;
/**
* The human-readable name of the application that is displayed with the app's icon on the device's
* home screen or desktop. On Android and iOS, this value is a `string` unless the name could not be
* retrieved, in which case this value will be `null`. On web this value is `null`.
* @example
* `"Expo"`, `"Yelp"`, `"Instagram"`
*/
export declare const applicationName: string | null;
/**
* The ID of the application. On Android, this is the application ID. On iOS, this is the bundle ID.
* On web, this is `null`.
* @example
* `"com.cocoacasts.scribbles"`, `"com.apple.Pages"`
*/
export declare const applicationId: string | null;
/**
* Gets the value of [`Settings.Secure.ANDROID_ID`](https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID).
* This is a hexadecimal `string` unique to each combination of app-signing key, user, and device.
* The value may change if a factory reset is performed on the device or if an APK signing key changes.
* For more information about how the platform handles `ANDROID_ID` in Android 8.0 (API level 26)
* and higher, see [Android 8.0 Behavior Changes](https://developer.android.com/about/versions/oreo/android-8.0-changes.html#privacy-all).
* On iOS and web, this function is unavailable.
* > In versions of the platform lower than Android 8.0 (API level 26), this value remains constant
* > for the lifetime of the user's device. See the [ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID)
* > official docs for more information.
* @example
* `"dd96dec43fb81c97"`
* @platform android
*/
export declare function getAndroidId(): string;
/**
* Gets the referrer URL of the installed app with the [`Install Referrer API`](https://developer.android.com/google/play/installreferrer)
* from the Google Play Store. In practice, the referrer URL may not be a complete, absolute URL.
* @return A `Promise` that fulfills with a `string` of the referrer URL of the installed app.
*
* @example
* ```ts
* await Application.getInstallReferrerAsync();
* // "utm_source=google-play&utm_medium=organic"
* ```
* @platform android
*/
export declare function getInstallReferrerAsync(): Promise<string>;
/**
* Gets the iOS "identifier for vendor" ([IDFV](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor))
* value, a string ID that uniquely identifies a device to the apps vendor. This method may
* sometimes return `nil`, in which case wait and call the method again later. This might happen
* when the device has been restarted before the user has unlocked the device.
*
* The OS will change the vendor identifier if all apps from the current app's vendor have been
* uninstalled.
*
* @return A `Promise` that fulfills with a `string` specifying the app's vendor ID. Apps from the
* same vendor will return the same ID. See Apple's documentation for more information about the
* vendor ID's semantics.
*
* @example
* ```ts
* await Application.getIosIdForVendorAsync();
* // "68753A44-4D6F-1226-9C60-0050E4C00067"
* ```
* @platform ios
*/
export declare function getIosIdForVendorAsync(): Promise<string | null>;
/**
* Gets the iOS application release type.
* @return Returns a promise which fulfills with an [`ApplicationReleaseType`](#applicationreleasetype).
* @platform ios
*/
export declare function getIosApplicationReleaseTypeAsync(): Promise<ApplicationReleaseType>;
/**
* Gets the current [Apple Push Notification (APN)](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment?language=objc)
* service environment.
* @return Returns a promise fulfilled with the string, either `'development'` or `'production'`,
* based on the current APN environment, or `null` on the simulator as it does not support registering with APNs.
* @platform ios
*/
export declare function getIosPushNotificationServiceEnvironmentAsync(): Promise<PushNotificationServiceEnvironment>;
/**
* Gets the time the app was installed onto the device, not counting subsequent updates. If the app
* is uninstalled and reinstalled, this method returns the time the app was reinstalled.
* - On iOS, this method uses the [`NSFileCreationDate`](https://developer.apple.com/documentation/foundation/nsfilecreationdate?language=objc)
* of the app's document root directory.
* - On Android, this method uses [`PackageInfo.firstInstallTime`](https://developer.android.com/reference/android/content/pm/PackageInfo.html#firstInstallTime).
* - On web, this method returns `null`.
*
* @return Returns a `Promise` that fulfills with a `Date` object that specifies the time the app
* was installed on the device.
*
* @example
* ```ts
* await Application.getInstallationTimeAsync();
* // 2019-07-18T18:08:26.121Z
* ```
*/
export declare function getInstallationTimeAsync(): Promise<Date>;
/**
* Gets the last time the app was updated from the Google Play Store.
* @return Returns a `Promise` that fulfills with a `Date` object that specifies the last time
* the app was updated via the Google Play Store).
*
* @example
* ```ts
* await Application.getLastUpdateTimeAsync();
* // 2019-07-18T21:20:16.887Z
* ```
* @platform android
*/
export declare function getLastUpdateTimeAsync(): Promise<Date>;
export { ApplicationReleaseType, PushNotificationServiceEnvironment };
//# sourceMappingURL=Application.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../src/Application.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AAIjG;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,GAAG,IAExC,CAAC;AAGT;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,GAAG,IAElC,CAAC;AAGT;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,GAAG,IAE/B,CAAC;AAGT;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,GAAG,IAE7B,CAAC;AAGT;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAKrC;AAGD;;;;;;;;;;;GAWG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC,CAK/D;AAGD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKrE;AAGD;;;;GAIG;AACH,wBAAsB,iCAAiC,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAKzF;AAGD;;;;;;GAMG;AACH,wBAAsB,6CAA6C,IAAI,OAAO,CAAC,kCAAkC,CAAC,CAKjH;AAGD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM9D;AAGD;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAM5D;AAED,OAAO,EAAE,sBAAsB,EAAE,kCAAkC,EAAE,CAAC"}

View File

@@ -0,0 +1,189 @@
import { Platform, UnavailabilityError } from 'expo-modules-core';
import { ApplicationReleaseType } from './Application.types';
import ExpoApplication from './ExpoApplication';
// @needsAudit
/**
* The human-readable version of the native application that may be displayed in the app store.
* This is the `Info.plist` value for `CFBundleShortVersionString` on iOS and the version name set
* by `version` in `app.json` on Android at the time the native app was built.
* On web, this value is `null`.
* @example
* `"2.11.0"`
*/
export const nativeApplicationVersion = ExpoApplication
? ExpoApplication.nativeApplicationVersion || null
: null;
// @needsAudit
/**
* The internal build version of the native application that the app store may use to distinguish
* between different binaries. This is the `Info.plist` value for `CFBundleVersion` on iOS (set with
* `ios.buildNumber` value in `app.json` in a standalone app) and the version code set by
* `android.versionCode` in `app.json` on Android at the time the native app was built. On web, this
* value is `null`. The return type on Android and iOS is `string`.
* @example
* Android: `"114"`, iOS: `"2.11.0"`
*/
export const nativeBuildVersion = ExpoApplication
? ExpoApplication.nativeBuildVersion || null
: null;
// @needsAudit
/**
* The human-readable name of the application that is displayed with the app's icon on the device's
* home screen or desktop. On Android and iOS, this value is a `string` unless the name could not be
* retrieved, in which case this value will be `null`. On web this value is `null`.
* @example
* `"Expo"`, `"Yelp"`, `"Instagram"`
*/
export const applicationName = ExpoApplication
? ExpoApplication.applicationName || null
: null;
// @needsAudit
/**
* The ID of the application. On Android, this is the application ID. On iOS, this is the bundle ID.
* On web, this is `null`.
* @example
* `"com.cocoacasts.scribbles"`, `"com.apple.Pages"`
*/
export const applicationId = ExpoApplication
? ExpoApplication.applicationId || null
: null;
// @needsAudit
/**
* Gets the value of [`Settings.Secure.ANDROID_ID`](https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID).
* This is a hexadecimal `string` unique to each combination of app-signing key, user, and device.
* The value may change if a factory reset is performed on the device or if an APK signing key changes.
* For more information about how the platform handles `ANDROID_ID` in Android 8.0 (API level 26)
* and higher, see [Android 8.0 Behavior Changes](https://developer.android.com/about/versions/oreo/android-8.0-changes.html#privacy-all).
* On iOS and web, this function is unavailable.
* > In versions of the platform lower than Android 8.0 (API level 26), this value remains constant
* > for the lifetime of the user's device. See the [ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID)
* > official docs for more information.
* @example
* `"dd96dec43fb81c97"`
* @platform android
*/
export function getAndroidId() {
if (Platform.OS !== 'android') {
throw new UnavailabilityError('expo-application', 'androidId');
}
return ExpoApplication.androidId;
}
// @needsAudit
/**
* Gets the referrer URL of the installed app with the [`Install Referrer API`](https://developer.android.com/google/play/installreferrer)
* from the Google Play Store. In practice, the referrer URL may not be a complete, absolute URL.
* @return A `Promise` that fulfills with a `string` of the referrer URL of the installed app.
*
* @example
* ```ts
* await Application.getInstallReferrerAsync();
* // "utm_source=google-play&utm_medium=organic"
* ```
* @platform android
*/
export async function getInstallReferrerAsync() {
if (!ExpoApplication.getInstallReferrerAsync) {
throw new UnavailabilityError('expo-application', 'getInstallReferrerAsync');
}
return await ExpoApplication.getInstallReferrerAsync();
}
// @needsAudit
/**
* Gets the iOS "identifier for vendor" ([IDFV](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor))
* value, a string ID that uniquely identifies a device to the apps vendor. This method may
* sometimes return `nil`, in which case wait and call the method again later. This might happen
* when the device has been restarted before the user has unlocked the device.
*
* The OS will change the vendor identifier if all apps from the current app's vendor have been
* uninstalled.
*
* @return A `Promise` that fulfills with a `string` specifying the app's vendor ID. Apps from the
* same vendor will return the same ID. See Apple's documentation for more information about the
* vendor ID's semantics.
*
* @example
* ```ts
* await Application.getIosIdForVendorAsync();
* // "68753A44-4D6F-1226-9C60-0050E4C00067"
* ```
* @platform ios
*/
export async function getIosIdForVendorAsync() {
if (!ExpoApplication.getIosIdForVendorAsync) {
throw new UnavailabilityError('expo-application', 'getIosIdForVendorAsync');
}
return await ExpoApplication.getIosIdForVendorAsync();
}
// @needsAudit
/**
* Gets the iOS application release type.
* @return Returns a promise which fulfills with an [`ApplicationReleaseType`](#applicationreleasetype).
* @platform ios
*/
export async function getIosApplicationReleaseTypeAsync() {
if (!ExpoApplication.getApplicationReleaseTypeAsync) {
throw new UnavailabilityError('expo-application', 'getApplicationReleaseTypeAsync');
}
return await ExpoApplication.getApplicationReleaseTypeAsync();
}
// @needsAudit
/**
* Gets the current [Apple Push Notification (APN)](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment?language=objc)
* service environment.
* @return Returns a promise fulfilled with the string, either `'development'` or `'production'`,
* based on the current APN environment, or `null` on the simulator as it does not support registering with APNs.
* @platform ios
*/
export async function getIosPushNotificationServiceEnvironmentAsync() {
if (!ExpoApplication.getPushNotificationServiceEnvironmentAsync) {
throw new UnavailabilityError('expo-application', 'getPushNotificationServiceEnvironmentAsync');
}
return await ExpoApplication.getPushNotificationServiceEnvironmentAsync();
}
// @needsAudit
/**
* Gets the time the app was installed onto the device, not counting subsequent updates. If the app
* is uninstalled and reinstalled, this method returns the time the app was reinstalled.
* - On iOS, this method uses the [`NSFileCreationDate`](https://developer.apple.com/documentation/foundation/nsfilecreationdate?language=objc)
* of the app's document root directory.
* - On Android, this method uses [`PackageInfo.firstInstallTime`](https://developer.android.com/reference/android/content/pm/PackageInfo.html#firstInstallTime).
* - On web, this method returns `null`.
*
* @return Returns a `Promise` that fulfills with a `Date` object that specifies the time the app
* was installed on the device.
*
* @example
* ```ts
* await Application.getInstallationTimeAsync();
* // 2019-07-18T18:08:26.121Z
* ```
*/
export async function getInstallationTimeAsync() {
if (!ExpoApplication.getInstallationTimeAsync) {
throw new UnavailabilityError('expo-application', 'getInstallationTimeAsync');
}
const installationTime = await ExpoApplication.getInstallationTimeAsync();
return new Date(installationTime);
}
// @needsAudit
/**
* Gets the last time the app was updated from the Google Play Store.
* @return Returns a `Promise` that fulfills with a `Date` object that specifies the last time
* the app was updated via the Google Play Store).
*
* @example
* ```ts
* await Application.getLastUpdateTimeAsync();
* // 2019-07-18T21:20:16.887Z
* ```
* @platform android
*/
export async function getLastUpdateTimeAsync() {
if (!ExpoApplication.getLastUpdateTimeAsync) {
throw new UnavailabilityError('expo-application', 'getLastUpdateTimeAsync');
}
const lastUpdateTime = await ExpoApplication.getLastUpdateTimeAsync();
return new Date(lastUpdateTime);
}
export { ApplicationReleaseType };
//# sourceMappingURL=Application.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
export declare enum ApplicationReleaseType {
UNKNOWN = 0,
SIMULATOR = 1,
ENTERPRISE = 2,
DEVELOPMENT = 3,
AD_HOC = 4,
APP_STORE = 5
}
/**
* Maps to the [`aps-environment`](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment) key in the native target's registered entitlements.
*/
export type PushNotificationServiceEnvironment = 'development' | 'production' | null;
//# sourceMappingURL=Application.types.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Application.types.d.ts","sourceRoot":"","sources":["../src/Application.types.ts"],"names":[],"mappings":"AACA,oBAAY,sBAAsB;IAChC,OAAO,IAAI;IACX,SAAS,IAAI;IACb,UAAU,IAAI;IACd,WAAW,IAAI;IACf,MAAM,IAAI;IACV,SAAS,IAAI;CACd;AAED;;GAEG;AACH,MAAM,MAAM,kCAAkC,GAAG,aAAa,GAAG,YAAY,GAAG,IAAI,CAAC"}

View File

@@ -0,0 +1,11 @@
// @docsMissing
export var ApplicationReleaseType;
(function (ApplicationReleaseType) {
ApplicationReleaseType[ApplicationReleaseType["UNKNOWN"] = 0] = "UNKNOWN";
ApplicationReleaseType[ApplicationReleaseType["SIMULATOR"] = 1] = "SIMULATOR";
ApplicationReleaseType[ApplicationReleaseType["ENTERPRISE"] = 2] = "ENTERPRISE";
ApplicationReleaseType[ApplicationReleaseType["DEVELOPMENT"] = 3] = "DEVELOPMENT";
ApplicationReleaseType[ApplicationReleaseType["AD_HOC"] = 4] = "AD_HOC";
ApplicationReleaseType[ApplicationReleaseType["APP_STORE"] = 5] = "APP_STORE";
})(ApplicationReleaseType || (ApplicationReleaseType = {}));
//# sourceMappingURL=Application.types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Application.types.js","sourceRoot":"","sources":["../src/Application.types.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,MAAM,CAAN,IAAY,sBAOX;AAPD,WAAY,sBAAsB;IAChC,yEAAW,CAAA;IACX,6EAAa,CAAA;IACb,+EAAc,CAAA;IACd,iFAAe,CAAA;IACf,uEAAU,CAAA;IACV,6EAAa,CAAA;AACf,CAAC,EAPW,sBAAsB,KAAtB,sBAAsB,QAOjC","sourcesContent":["// @docsMissing\nexport enum ApplicationReleaseType {\n UNKNOWN = 0,\n SIMULATOR = 1,\n ENTERPRISE = 2,\n DEVELOPMENT = 3,\n AD_HOC = 4,\n APP_STORE = 5,\n}\n\n/**\n * Maps to the [`aps-environment`](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment) key in the native target's registered entitlements.\n */\nexport type PushNotificationServiceEnvironment = 'development' | 'production' | null;\n"]}

View File

@@ -0,0 +1,3 @@
declare const _default: any;
export default _default;
//# sourceMappingURL=ExpoApplication.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ExpoApplication.d.ts","sourceRoot":"","sources":["../src/ExpoApplication.ts"],"names":[],"mappings":";AAEA,wBAAsD"}

View File

@@ -0,0 +1,3 @@
import { requireNativeModule } from 'expo-modules-core';
export default requireNativeModule('ExpoApplication');
//# sourceMappingURL=ExpoApplication.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ExpoApplication.js","sourceRoot":"","sources":["../src/ExpoApplication.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,eAAe,mBAAmB,CAAC,iBAAiB,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from 'expo-modules-core';\n\nexport default requireNativeModule('ExpoApplication');\n"]}

View File

@@ -0,0 +1,10 @@
declare const _default: {
readonly applicationName: null;
readonly bundleId: null;
readonly nativeApplicationVersion: null;
readonly nativeBuildVersion: null;
readonly androidId: null;
getInstallationTimeAsync(): Promise<null>;
};
export default _default;
//# sourceMappingURL=ExpoApplication.web.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ExpoApplication.web.d.ts","sourceRoot":"","sources":["../src/ExpoApplication.web.ts"],"names":[],"mappings":";;;;;;gCAgBoC,QAAQ,IAAI,CAAC;;AAhBjD,wBAmBE"}

View File

@@ -0,0 +1,21 @@
export default {
get applicationName() {
return null;
},
get bundleId() {
return null;
},
get nativeApplicationVersion() {
return null;
},
get nativeBuildVersion() {
return null;
},
get androidId() {
return null;
},
async getInstallationTimeAsync() {
return null;
},
};
//# sourceMappingURL=ExpoApplication.web.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ExpoApplication.web.js","sourceRoot":"","sources":["../src/ExpoApplication.web.ts"],"names":[],"mappings":"AAAA,eAAe;IACb,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,wBAAwB;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,kBAAkB;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,SAAS;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,CAAC,wBAAwB;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC","sourcesContent":["export default {\n get applicationName(): null {\n return null;\n },\n get bundleId(): null {\n return null;\n },\n get nativeApplicationVersion(): null {\n return null;\n },\n get nativeBuildVersion(): null {\n return null;\n },\n get androidId(): null {\n return null;\n },\n async getInstallationTimeAsync(): Promise<null> {\n return null;\n },\n};\n"]}