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 type { SpawnOptions, SpawnResult } from '@expo/spawn-async';
declare function escapeString(value: string): string;
declare function osascriptSpawnAsync(script: string | string[], opts?: SpawnOptions): Promise<SpawnResult>;
declare function isAppRunningAsync(appName: string): Promise<boolean>;
declare function safeIdOfAppAsync(appName: string): Promise<string | null>;
declare function openFinderToFolderAsync(dir: string, activate?: boolean): Promise<void>;
declare function openInAppAsync(appName: string, pth: string): Promise<SpawnResult>;
declare function chooseAppAsync(listOfAppNames: string[]): Promise<string | null>;
declare function chooseEditorAppAsync(preferredEditor?: string): Promise<string | null>;
declare function chooseTerminalAppAsync(): Promise<string | null>;
declare function openInEditorAsync(pth: string, preferredEditor?: string): Promise<SpawnResult>;
declare function openItermToSpecificFolderAsync(dir: string): Promise<SpawnResult>;
declare function openTerminalToSpecificFolderAsync(dir: string, inTab?: boolean): Promise<SpawnResult>;
declare function openFolderInTerminalAppAsync(dir: string, inTab?: boolean): Promise<SpawnResult>;
/** @deprecated */
declare function osascriptExecAsync(script: string | string[], opts?: SpawnOptions): Promise<string>;
export { chooseAppAsync, chooseEditorAppAsync, chooseTerminalAppAsync, escapeString, osascriptExecAsync as execAsync, isAppRunningAsync, openFinderToFolderAsync, openFolderInTerminalAppAsync, openInAppAsync, openInEditorAsync, openItermToSpecificFolderAsync, openTerminalToSpecificFolderAsync, safeIdOfAppAsync, osascriptSpawnAsync as spawnAsync, };

View File

@@ -0,0 +1,197 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.chooseAppAsync = chooseAppAsync;
exports.chooseEditorAppAsync = chooseEditorAppAsync;
exports.chooseTerminalAppAsync = chooseTerminalAppAsync;
exports.escapeString = escapeString;
exports.execAsync = osascriptExecAsync;
exports.isAppRunningAsync = isAppRunningAsync;
exports.openFinderToFolderAsync = openFinderToFolderAsync;
exports.openFolderInTerminalAppAsync = openFolderInTerminalAppAsync;
exports.openInAppAsync = openInAppAsync;
exports.openInEditorAsync = openInEditorAsync;
exports.openItermToSpecificFolderAsync = openItermToSpecificFolderAsync;
exports.openTerminalToSpecificFolderAsync = openTerminalToSpecificFolderAsync;
exports.safeIdOfAppAsync = safeIdOfAppAsync;
exports.spawnAsync = osascriptSpawnAsync;
const spawn_async_1 = __importDefault(require("@expo/spawn-async"));
const path_1 = __importDefault(require("path"));
function escapeString(value) {
return value
.replace(/\\/g, '\\\\')
.replace(/"/g, '\\"')
.replace(/\r/g, '\\r')
.replace(/\n/g, '\\n')
.replace(/\t/g, '\\t');
}
function shellQuote(value) {
return `'${value.replace(/'/g, `'\\''`)}'`;
}
function osascriptArgs(script) {
if (!Array.isArray(script)) {
script = [script];
}
const args = [];
for (const line of script) {
args.push('-e');
args.push(line);
}
return args;
}
async function osascriptSpawnAsync(script, opts) {
return await (0, spawn_async_1.default)('osascript', osascriptArgs(script), opts);
}
async function isAppRunningAsync(appName) {
const { stdout } = await osascriptSpawnAsync(`tell app "System Events" to count processes whose name is "${escapeString(appName)}"`);
return stdout.trim() !== '0';
}
async function safeIdOfAppAsync(appName) {
try {
const { stdout } = await osascriptSpawnAsync(`id of app "${escapeString(appName)}"`);
return stdout.trim();
}
catch {
return null;
}
}
async function openFinderToFolderAsync(dir, activate = true) {
await osascriptSpawnAsync([
'tell application "Finder"',
`open POSIX file "${escapeString(dir)}"`,
(activate && 'activate') || '',
'end tell',
]);
}
async function openInAppAsync(appName, pth) {
return await osascriptSpawnAsync(`tell app "${escapeString(appName)}" to open "${escapeString(path_1.default.resolve(pth))}"`);
}
async function chooseAppAsync(listOfAppNames) {
const runningAwaitables = [];
const appIdAwaitables = [];
for (const appName of listOfAppNames) {
runningAwaitables.push(isAppRunningAsync(appName));
appIdAwaitables.push(safeIdOfAppAsync(appName));
}
const running = await Promise.all(runningAwaitables);
const appIds = await Promise.all(appIdAwaitables);
let i;
for (i = 0; i < listOfAppNames.length; i++) {
if (running[i]) {
const appName = listOfAppNames[i];
if (appName != null) {
return appName;
}
}
}
for (i = 0; i < listOfAppNames.length; i++) {
if (appIds[i]) {
const appName = listOfAppNames[i];
if (appName != null) {
return appName;
}
}
}
return null;
}
async function chooseEditorAppAsync(preferredEditor) {
if (preferredEditor) {
// Make sure this editor exists
const appId = await safeIdOfAppAsync(preferredEditor);
if (appId) {
return preferredEditor;
}
else {
console.warn(`Your preferred editor (${preferredEditor}) isn't installed on this computer.`);
}
}
const editorsToTry = [
'Visual Studio Code',
'Atom',
'Sublime Text',
'TextMate',
'TextWrangler',
'Visual Studio Code',
'Brackets',
'SubEthaEdit',
'BBEdit',
'Textastic',
'UltraEdit',
'MacVim',
'CodeRunner 2',
'CodeRunner',
'TextEdit',
];
return await chooseAppAsync(editorsToTry);
}
async function chooseTerminalAppAsync() {
return await chooseAppAsync([
'iTerm 3',
'iTerm 2',
'iTerm',
'HyperTerm',
// 'Cathode',
// 'Terminator',
// 'MacTerm',
'Terminal',
]);
}
async function openInEditorAsync(pth, preferredEditor) {
const appName = await chooseEditorAppAsync(preferredEditor);
if (!appName) {
throw new Error('No editor found.');
}
console.log('Will open in ' + appName + ' -- ' + pth);
return await openInAppAsync(appName, pth);
}
async function openItermToSpecificFolderAsync(dir) {
const shellCommand = escapeString(`cd ${shellQuote(dir)} && clear`);
return await osascriptSpawnAsync([
'tell application "iTerm"',
'make new terminal',
'tell the first terminal',
'activate current session',
'launch session "Default Session"',
'tell the last session',
`write text "${shellCommand}"`,
'end tell',
'end tell',
'end tell',
]);
}
async function openTerminalToSpecificFolderAsync(dir, inTab = false) {
const shellCommand = escapeString(`cd ${shellQuote(dir)} && clear`);
if (inTab) {
return await osascriptSpawnAsync([
'tell application "terminal"',
'tell application "System Events" to tell process "terminal" to keystroke "t" using command down',
`do script with command "${shellCommand}" in selected tab of the front window`,
'end tell',
]);
}
else {
return await osascriptSpawnAsync([
'tell application "terminal"',
`do script "${shellCommand}"`,
'end tell',
'tell application "terminal" to activate',
]);
}
}
async function openFolderInTerminalAppAsync(dir, inTab = false) {
const program = await chooseTerminalAppAsync();
switch (program) {
case 'iTerm':
return await openItermToSpecificFolderAsync(dir);
case 'Terminal':
default:
return await openTerminalToSpecificFolderAsync(dir, inTab);
}
}
/** @deprecated */
async function osascriptExecAsync(script, opts) {
return (await osascriptSpawnAsync(script, opts)).stdout.trim();
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}