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

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,197 @@
'use strict';
var fs = require('fs');
var path = require('path');
var nodeunit = require('nodeunit');
var bplistParser = require('bplist-parser');
var bplistCreator = require('../');
module.exports = {
// 'iTunes Small': function(test) {
// var file = path.join(__dirname, "iTunes-small.bplist");
// testFile(test, file);
// },
'sample1': function(test) {
var file = path.join(__dirname, "sample1.bplist");
testFile(test, file);
},
'sample2': function(test) {
var file = path.join(__dirname, "sample2.bplist");
testFile(test, file);
},
'binary data': function(test) {
var file = path.join(__dirname, "binaryData.bplist");
testFile(test, file);
},
'airplay': function(test) {
var file = path.join(__dirname, "airplay.bplist");
testFile(test, file);
},
// 'utf16': function(test) {
// var file = path.join(__dirname, "utf16.bplist");
// testFile(test, file);
// },
// 'uid': function(test) {
// var file = path.join(__dirname, "uid.bplist");
// testFile(test, file);
// }
};
function testFile(test, file) {
fs.readFile(file, function(err, fileData) {
if (err) {
return test.done(err);
}
bplistParser.parseFile(file, function(err, dicts) {
if (err) {
return test.done(err);
}
// airplay overrides
if (dicts && dicts[0] && dicts[0].loadedTimeRanges && dicts[0].loadedTimeRanges[0] && dicts[0].loadedTimeRanges[0].hasOwnProperty('start')) {
dicts[0].loadedTimeRanges[0].start = {
bplistOverride: true,
type: 'double',
value: dicts[0].loadedTimeRanges[0].start
};
}
if (dicts && dicts[0] && dicts[0].loadedTimeRanges && dicts[0].seekableTimeRanges[0] && dicts[0].seekableTimeRanges[0].hasOwnProperty('start')) {
dicts[0].seekableTimeRanges[0].start = {
bplistOverride: true,
type: 'double',
value: dicts[0].seekableTimeRanges[0].start
};
}
if (dicts && dicts[0] && dicts[0].hasOwnProperty('rate')) {
dicts[0].rate = {
bplistOverride: true,
type: 'double',
value: dicts[0].rate
};
}
// utf16
if (dicts && dicts[0] && dicts[0].hasOwnProperty('NSHumanReadableCopyright')) {
dicts[0].NSHumanReadableCopyright = {
bplistOverride: true,
type: 'string-utf16',
value: dicts[0].NSHumanReadableCopyright
};
}
if (dicts && dicts[0] && dicts[0].hasOwnProperty('CFBundleExecutable')) {
dicts[0].CFBundleExecutable = {
bplistOverride: true,
type: 'string',
value: dicts[0].CFBundleExecutable
};
}
if (dicts && dicts[0] && dicts[0].CFBundleURLTypes && dicts[0].CFBundleURLTypes[0] && dicts[0].CFBundleURLTypes[0].hasOwnProperty('CFBundleURLSchemes')) {
dicts[0].CFBundleURLTypes[0].CFBundleURLSchemes[0] = {
bplistOverride: true,
type: 'string',
value: dicts[0].CFBundleURLTypes[0].CFBundleURLSchemes[0]
};
}
if (dicts && dicts[0] && dicts[0].hasOwnProperty('CFBundleDisplayName')) {
dicts[0].CFBundleDisplayName = {
bplistOverride: true,
type: 'string',
value: dicts[0].CFBundleDisplayName
};
}
if (dicts && dicts[0] && dicts[0].hasOwnProperty('DTPlatformBuild')) {
dicts[0].DTPlatformBuild = {
bplistOverride: true,
type: 'string',
value: dicts[0].DTPlatformBuild
};
}
var buf = bplistCreator(dicts);
compareBuffers(test, buf, fileData);
return test.done();
});
});
}
function compareBuffers(test, buf1, buf2) {
if (buf1.length !== buf2.length) {
printBuffers(buf1, buf2);
return test.fail("buffer size mismatch. found: " + buf1.length + ", expected: " + buf2.length + ".");
}
for (var i = 0; i < buf1.length; i++) {
if (buf1[i] !== buf2[i]) {
printBuffers(buf1, buf2);
return test.fail("buffer mismatch at offset 0x" + i.toString(16) + ". found: 0x" + buf1[i].toString(16) + ", expected: 0x" + buf2[i].toString(16) + ".");
}
}
}
function printBuffers(buf1, buf2) {
var i, t;
for (var lineOffset = 0; lineOffset < buf1.length || lineOffset < buf2.length; lineOffset += 16) {
var line = '';
t = ('000000000' + lineOffset.toString(16));
line += t.substr(t.length - 8) + ': ';
for (i = 0; i < 16; i++) {
if (i == 8) {
line += ' ';
}
if (lineOffset + i < buf1.length) {
t = ('00' + buf1[lineOffset + i].toString(16));
line += t.substr(t.length - 2) + ' ';
} else {
line += ' ';
}
}
line += ' ';
for (i = 0; i < 16; i++) {
if (lineOffset + i < buf1.length) {
t = String.fromCharCode(buf1[lineOffset + i]);
if (t < ' ' || t > '~') {
t = '.';
}
line += t;
} else {
line += ' ';
}
}
line += ' - ';
for (i = 0; i < 16; i++) {
if (i == 8) {
line += ' ';
}
if (lineOffset + i < buf2.length) {
t = ('00' + buf2[lineOffset + i].toString(16));
line += t.substr(t.length - 2) + ' ';
} else {
line += ' ';
}
}
line += ' ';
for (i = 0; i < 16; i++) {
if (lineOffset + i < buf2.length) {
t = String.fromCharCode(buf2[lineOffset + i]);
if (t < ' ' || t > '~') {
t = '.';
}
line += t;
} else {
line += ' ';
}
}
console.log(line);
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.