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,99 @@
// Russian [ru]
import dayjs from '../index';
var monthFormat = 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_');
var monthStandalone = 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_');
var monthShortFormat = 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_');
var monthShortStandalone = 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_');
var MONTHS_IN_FORMAT = /D[oD]?(\[[^[\]]*\]|\s)+MMMM?/;
function plural(word, num) {
var forms = word.split('_');
return num % 10 === 1 && num % 100 !== 11 ? forms[0] : num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]; // eslint-disable-line
}
function relativeTimeWithPlural(number, withoutSuffix, key) {
var format = {
mm: withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
hh: асасаасов',
dd: ень_дня_дней',
MM: есяц_месяцаесяцев',
yy: 'год_годает'
};
if (key === 'm') {
return withoutSuffix ? 'минута' : 'минуту';
}
return number + " " + plural(format[key], +number);
}
var months = function months(dayjsInstance, format) {
if (MONTHS_IN_FORMAT.test(format)) {
return monthFormat[dayjsInstance.month()];
}
return monthStandalone[dayjsInstance.month()];
};
months.s = monthStandalone;
months.f = monthFormat;
var monthsShort = function monthsShort(dayjsInstance, format) {
if (MONTHS_IN_FORMAT.test(format)) {
return monthShortFormat[dayjsInstance.month()];
}
return monthShortStandalone[dayjsInstance.month()];
};
monthsShort.s = monthShortStandalone;
monthsShort.f = monthShortFormat;
var locale = {
name: 'ru',
weekdays: оскресенье_понедельник_вторник_средаетверг_пятница_суббота'.split('_'),
weekdaysShort: ск_пнд_втр_срд_чтв_птн_сбт'.split('_'),
weekdaysMin: с_пн_вт_ср_чт_пт_сб'.split('_'),
months: months,
monthsShort: monthsShort,
weekStart: 1,
yearStart: 4,
formats: {
LT: 'H:mm',
LTS: 'H:mm:ss',
L: 'DD.MM.YYYY',
LL: 'D MMMM YYYY г.',
LLL: 'D MMMM YYYY г., H:mm',
LLLL: 'dddd, D MMMM YYYY г., H:mm'
},
relativeTime: {
future: 'через %s',
past: '%s назад',
s: 'несколько секунд',
m: relativeTimeWithPlural,
mm: relativeTimeWithPlural,
h: 'час',
hh: relativeTimeWithPlural,
d: 'день',
dd: relativeTimeWithPlural,
M: 'месяц',
MM: relativeTimeWithPlural,
y: 'год',
yy: relativeTimeWithPlural
},
ordinal: function ordinal(n) {
return n;
},
meridiem: function meridiem(hour) {
if (hour < 4) {
return 'ночи';
} else if (hour < 12) {
return 'утра';
} else if (hour < 17) {
return 'дня';
}
return 'вечера';
}
};
dayjs.locale(locale, null, true);
export default locale;