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,19 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
export default {
primary: '#1292B4',
white: '#FFF',
lighter: '#F3F3F3',
light: '#DAE1E7',
dark: '#444',
darker: '#222',
black: '#000',
};

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type {Node} from 'react';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import Platform from '../../Utilities/Platform';
import React from 'react';
const styles = StyleSheet.create({
highlight: {
fontWeight: '700',
},
});
const DebugInstructions: () => Node = Platform.select({
ios: () => (
<Text>
Press <Text style={styles.highlight}>Cmd + D</Text> in the simulator or{' '}
<Text style={styles.highlight}>Shake</Text> your device to open the Dev
Menu.
</Text>
),
default: () => (
<Text>
Press <Text style={styles.highlight}>Cmd or Ctrl + M</Text> or{' '}
<Text style={styles.highlight}>Shake</Text> your device to open the Dev
Menu.
</Text>
),
});
export default DebugInstructions;

View File

@@ -0,0 +1,77 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type {Node} from 'react';
import ImageBackground from '../../Image/ImageBackground';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import useColorScheme from '../../Utilities/useColorScheme';
import Colors from './Colors';
import HermesBadge from './HermesBadge';
import React from 'react';
const Header = (): Node => {
const isDarkMode = useColorScheme() === 'dark';
return (
<ImageBackground
accessibilityRole="image"
testID="new-app-screen-header"
source={require('./logo.png')}
style={[
styles.background,
{
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
},
]}
imageStyle={styles.logo}>
<HermesBadge />
<Text
style={[
styles.text,
{
color: isDarkMode ? Colors.white : Colors.black,
},
]}>
Welcome to
{'\n'}
React Native
</Text>
</ImageBackground>
);
};
const styles = StyleSheet.create({
background: {
paddingBottom: 40,
paddingTop: 96,
paddingHorizontal: 32,
},
logo: {
opacity: 0.2,
overflow: 'visible',
resizeMode: 'cover',
/*
* These negative margins allow the image to be offset similarly across screen sizes and component sizes.
*
* The source logo.png image is 512x512px, so as such, these margins attempt to be relative to the
* source image's size.
*/
marginLeft: -128,
marginBottom: -192,
},
text: {
fontSize: 40,
fontWeight: '700',
textAlign: 'center',
},
});
export default Header;

View File

@@ -0,0 +1,53 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type {Node} from 'react';
import View from '../../Components/View/View';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import useColorScheme from '../../Utilities/useColorScheme';
import Colors from './Colors';
import React from 'react';
const HermesBadge = (): Node => {
const isDarkMode = useColorScheme() === 'dark';
const version =
global.HermesInternal?.getRuntimeProperties?.()['OSS Release Version'] ??
'';
return global.HermesInternal ? (
<View style={styles.badge}>
<Text
style={[
styles.badgeText,
{
color: isDarkMode ? Colors.light : Colors.dark,
},
]}>
{`Engine: Hermes ${version}`}
</Text>
</View>
) : null;
};
const styles = StyleSheet.create({
badge: {
position: 'absolute',
top: 8,
right: 12,
},
badgeText: {
fontSize: 14,
fontWeight: '600',
textAlign: 'right',
},
});
export default HermesBadge;

View File

@@ -0,0 +1,148 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type {Node} from 'react';
import TouchableOpacity from '../../Components/Touchable/TouchableOpacity';
import View from '../../Components/View/View';
import openURLInBrowser from '../../Core/Devtools/openURLInBrowser';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import useColorScheme from '../../Utilities/useColorScheme';
import Colors from './Colors';
import React, {Fragment} from 'react';
const links = [
{
id: 1,
title: 'The Basics',
link: 'https://reactnative.dev/docs/tutorial',
description: 'Explains a Hello World for React Native.',
},
{
id: 2,
title: 'Style',
link: 'https://reactnative.dev/docs/style',
description:
'Covers how to use the prop named style which controls the visuals.',
},
{
id: 3,
title: 'Layout',
link: 'https://reactnative.dev/docs/flexbox',
description: 'React Native uses flexbox for layout, learn how it works.',
},
{
id: 4,
title: 'Components',
link: 'https://reactnative.dev/docs/components-and-apis',
description: 'The full list of components and APIs inside React Native.',
},
{
id: 5,
title: 'Navigation',
link: 'https://reactnative.dev/docs/navigation',
description:
'How to handle moving between screens inside your application.',
},
{
id: 6,
title: 'Networking',
link: 'https://reactnative.dev/docs/network',
description: 'How to use the Fetch API in React Native.',
},
{
id: 7,
title: 'Debugging',
link: 'https://facebook.github.io/react-native/docs/debugging',
description:
'Learn about the tools available to debug and inspect your app.',
},
{
id: 8,
title: 'Help',
link: 'https://facebook.github.io/react-native/help',
description:
'Need more help? There are many other React Native developers who may have the answer.',
},
{
id: 9,
title: 'Follow us on Twitter',
link: 'https://twitter.com/reactnative',
description:
'Stay in touch with the community, join in on Q&As and more by following React Native on Twitter.',
},
];
const LinkList = (): Node => {
const isDarkMode = useColorScheme() === 'dark';
return (
<View style={styles.container}>
{links.map(({id, title, link, description}) => (
<Fragment key={id}>
<View
style={[
styles.separator,
{
backgroundColor: isDarkMode ? Colors.dark : Colors.light,
},
]}
/>
<TouchableOpacity
accessibilityRole="button"
onPress={() => openURLInBrowser(link)}
style={styles.linkContainer}>
<Text style={styles.link}>{title}</Text>
<Text
style={[
styles.description,
{
color: isDarkMode ? Colors.lighter : Colors.dark,
},
]}>
{description}
</Text>
</TouchableOpacity>
</Fragment>
))}
</View>
);
};
const styles = StyleSheet.create({
container: {
marginTop: 32,
paddingHorizontal: 24,
},
linkContainer: {
flexWrap: 'wrap',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingVertical: 8,
},
link: {
flex: 2,
fontSize: 18,
fontWeight: '400',
color: Colors.primary,
},
description: {
flex: 3,
paddingVertical: 16,
fontWeight: '400',
fontSize: 18,
},
separator: {
height: StyleSheet.hairlineWidth,
},
});
export default LinkList;

View File

@@ -0,0 +1,39 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
import type {Node} from 'react';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import Platform from '../../Utilities/Platform';
import React from 'react';
const styles = StyleSheet.create({
highlight: {
fontWeight: '700',
},
});
const ReloadInstructions: () => Node = Platform.select({
ios: () => (
<Text>
Press <Text style={styles.highlight}>Cmd + R</Text> in the simulator to
reload your app's code.
</Text>
),
default: () => (
<Text>
Double tap <Text style={styles.highlight}>R</Text> on your keyboard to
reload your app's code.
</Text>
),
});
export default ReloadInstructions;

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB