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,23 @@
import { Options } from '../index';
import { Platform } from '.';
export default class MacOSPlatform implements Platform {
private FIREFOX_BUNDLE_PATH;
private FIREFOX_BIN_PATH;
private FIREFOX_NSS_DIR;
private HOST_FILE_PATH;
/**
* macOS is pretty simple - just add the certificate to the system keychain,
* and most applications will delegate to that for determining trusted
* certificates. Firefox, of course, does it's own thing. We can try to
* automatically install the cert with Firefox if we can use certutil via the
* `nss` Homebrew package, otherwise we go manual with user-facing prompts.
*/
addToTrustStores(certificatePath: string, options?: Options): Promise<void>;
removeFromTrustStores(certificatePath: string): Promise<void>;
addDomainToHostFileIfMissing(domain: string): Promise<void>;
deleteProtectedFiles(filepath: string): Promise<void>;
readProtectedFile(filepath: string): Promise<string>;
writeProtectedFile(filepath: string, contents: string): Promise<void>;
private isFirefoxInstalled;
private isNSSInstalled;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
import { Options } from '../index';
export interface Platform {
addToTrustStores(certificatePath: string, options?: Options): Promise<void>;
removeFromTrustStores(certificatePath: string): Promise<void>;
addDomainToHostFileIfMissing(domain: string): Promise<void>;
deleteProtectedFiles(filepath: string): Promise<void>;
readProtectedFile(filepath: string): Promise<string>;
writeProtectedFile(filepath: string, contents: string): Promise<void>;
}
declare const _default: Platform;
export default _default;

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const PlatformClass = require(`./${process.platform}`).default;
exports.default = new PlatformClass();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbInBsYXRmb3Jtcy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVlBLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxLQUFNLE9BQU8sQ0FBQyxRQUFTLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQztBQUNqRSxrQkFBZSxJQUFJLGFBQWEsRUFBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT3B0aW9ucyB9IGZyb20gJy4uL2luZGV4JztcblxuXG5leHBvcnQgaW50ZXJmYWNlIFBsYXRmb3JtIHtcbiAgIGFkZFRvVHJ1c3RTdG9yZXMoY2VydGlmaWNhdGVQYXRoOiBzdHJpbmcsIG9wdGlvbnM/OiBPcHRpb25zKTogUHJvbWlzZTx2b2lkPjtcbiAgIHJlbW92ZUZyb21UcnVzdFN0b3JlcyhjZXJ0aWZpY2F0ZVBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD47XG4gICBhZGREb21haW5Ub0hvc3RGaWxlSWZNaXNzaW5nKGRvbWFpbjogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbiAgIGRlbGV0ZVByb3RlY3RlZEZpbGVzKGZpbGVwYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+O1xuICAgcmVhZFByb3RlY3RlZEZpbGUoZmlsZXBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPjtcbiAgIHdyaXRlUHJvdGVjdGVkRmlsZShmaWxlcGF0aDogc3RyaW5nLCBjb250ZW50czogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbn1cblxuY29uc3QgUGxhdGZvcm1DbGFzcyA9IHJlcXVpcmUoYC4vJHsgcHJvY2Vzcy5wbGF0Zm9ybSB9YCkuZGVmYXVsdDtcbmV4cG9ydCBkZWZhdWx0IG5ldyBQbGF0Zm9ybUNsYXNzKCkgYXMgUGxhdGZvcm07XG4iXX0=

View File

@@ -0,0 +1,26 @@
import { Options } from '../index';
import { Platform } from '.';
export default class LinuxPlatform implements Platform {
private FIREFOX_NSS_DIR;
private CHROME_NSS_DIR;
private FIREFOX_BIN_PATH;
private CHROME_BIN_PATH;
private HOST_FILE_PATH;
/**
* Linux is surprisingly difficult. There seems to be multiple system-wide
* repositories for certs, so we copy ours to each. However, Firefox does it's
* usual separate trust store. Plus Chrome relies on the NSS tooling (like
* Firefox), but uses the user's NSS database, unlike Firefox (which uses a
* separate Mozilla one). And since Chrome doesn't prompt the user with a GUI
* flow when opening certs, if we can't use certutil to install our certificate
* into the user's NSS database, we're out of luck.
*/
addToTrustStores(certificatePath: string, options?: Options): Promise<void>;
removeFromTrustStores(certificatePath: string): Promise<void>;
addDomainToHostFileIfMissing(domain: string): Promise<void>;
deleteProtectedFiles(filepath: string): Promise<void>;
readProtectedFile(filepath: string): Promise<string>;
writeProtectedFile(filepath: string, contents: string): Promise<void>;
private isFirefoxInstalled;
private isChromeInstalled;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,35 @@
/**
* Given a directory or glob pattern of directories, attempt to install the
* CA certificate to each directory containing an NSS database.
*/
export declare function addCertificateToNSSCertDB(nssDirGlob: string, certPath: string, certutilPath: string): Promise<void>;
export declare function removeCertificateFromNSSCertDB(nssDirGlob: string, certPath: string, certutilPath: string): Promise<void>;
/**
* Check to see if Firefox is still running, and if so, ask the user to close
* it. Poll until it's closed, then return.
*
* This is needed because Firefox appears to load the NSS database in-memory on
* startup, and overwrite on exit. So we have to ask the user to quite Firefox
* first so our changes don't get overwritten.
*/
export declare function closeFirefox(): Promise<void>;
/**
* Firefox manages it's own trust store for SSL certificates, which can be
* managed via the certutil command (supplied by NSS tooling packages). In the
* event that certutil is not already installed, and either can't be installed
* (Windows) or the user doesn't want to install it (skipCertutilInstall:
* true), it means that we can't programmatically tell Firefox to trust our
* root CA certificate.
*
* There is a recourse though. When a Firefox tab is directed to a URL that
* responds with a certificate, it will automatically prompt the user if they
* want to add it to their trusted certificates. So if we can't automatically
* install the certificate via certutil, we instead start a quick web server
* and host our certificate file. Then we open the hosted cert URL in Firefox
* to kick off the GUI flow.
*
* This method does all this, along with providing user prompts in the terminal
* to walk them through this process.
*/
export declare function openCertificateInFirefox(firefoxPath: string, certPath: string): Promise<void>;
export declare function assertNotTouchingFiles(filepath: string, operation: string): void;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
import { Options } from '../index';
import { Platform } from '.';
export default class WindowsPlatform implements Platform {
private HOST_FILE_PATH;
/**
* Windows is at least simple. Like macOS, most applications will delegate to
* the system trust store, which is updated with the confusingly named
* `certutil` exe (not the same as the NSS/Mozilla certutil). Firefox does it's
* own thing as usual, and getting a copy of NSS certutil onto the Windows
* machine to try updating the Firefox store is basically a nightmare, so we
* don't even try it - we just bail out to the GUI.
*/
addToTrustStores(certificatePath: string, options?: Options): Promise<void>;
removeFromTrustStores(certificatePath: string): Promise<void>;
addDomainToHostFileIfMissing(domain: string): Promise<void>;
deleteProtectedFiles(filepath: string): Promise<void>;
readProtectedFile(filepath: string): Promise<string>;
writeProtectedFile(filepath: string, contents: string): Promise<void>;
private encrypt;
private decrypt;
}

File diff suppressed because one or more lines are too long