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,173 @@
import * as React from 'react';
import { Animated, StyleSheet, View } from 'react-native';
import color from 'color';
import { getSegmentedButtonBorderRadius, getSegmentedButtonColors, getSegmentedButtonDensityPadding } from './utils';
import { useInternalTheme } from '../../core/theming';
import Icon from '../Icon';
import TouchableRipple from '../TouchableRipple/TouchableRipple';
import Text from '../Typography/Text';
const SegmentedButtonItem = ({
checked,
accessibilityLabel,
disabled,
style,
labelStyle,
showSelectedCheck,
checkedColor,
uncheckedColor,
rippleColor: customRippleColor,
background,
icon,
testID,
label,
onPress,
segment,
density = 'regular',
theme: themeOverrides,
labelMaxFontSizeMultiplier,
hitSlop
}) => {
const theme = useInternalTheme(themeOverrides);
const checkScale = React.useRef(new Animated.Value(0)).current;
React.useEffect(() => {
if (!showSelectedCheck) {
return;
}
if (checked) {
Animated.spring(checkScale, {
toValue: 1,
useNativeDriver: true
}).start();
} else {
Animated.spring(checkScale, {
toValue: 0,
useNativeDriver: true
}).start();
}
}, [checked, checkScale, showSelectedCheck]);
const {
roundness,
isV3
} = theme;
const {
borderColor,
textColor,
borderWidth,
backgroundColor
} = getSegmentedButtonColors({
checked,
theme,
disabled,
checkedColor,
uncheckedColor
});
const borderRadius = (isV3 ? 5 : 1) * roundness;
const segmentBorderRadius = getSegmentedButtonBorderRadius({
theme,
segment
});
const rippleColor = customRippleColor || color(textColor).alpha(0.12).rgb().string();
const showIcon = !icon ? false : label && checked ? !showSelectedCheck : true;
const showCheckedIcon = checked && showSelectedCheck;
const iconSize = isV3 ? 18 : 16;
const iconStyle = {
marginRight: label ? 5 : showCheckedIcon ? 3 : 0,
...(label && {
transform: [{
scale: checkScale.interpolate({
inputRange: [0, 1],
outputRange: [1, 0]
})
}]
})
};
const buttonStyle = {
backgroundColor,
borderColor,
borderWidth,
borderRadius,
...segmentBorderRadius
};
const paddingVertical = getSegmentedButtonDensityPadding({
density
});
const rippleStyle = {
borderRadius,
...segmentBorderRadius
};
const labelTextStyle = {
...(!isV3 ? {
textTransform: 'uppercase',
fontWeight: '500'
} : theme.fonts.labelLarge),
color: textColor
};
return /*#__PURE__*/React.createElement(View, {
style: [buttonStyle, styles.button, style]
}, /*#__PURE__*/React.createElement(TouchableRipple, {
borderless: true,
onPress: onPress,
accessibilityLabel: accessibilityLabel,
accessibilityState: {
disabled,
checked
},
accessibilityRole: "button",
disabled: disabled,
rippleColor: rippleColor,
testID: testID,
style: rippleStyle,
background: background,
theme: theme,
hitSlop: hitSlop
}, /*#__PURE__*/React.createElement(View, {
style: [styles.content, {
paddingVertical
}]
}, showCheckedIcon ? /*#__PURE__*/React.createElement(Animated.View, {
testID: `${testID}-check-icon`,
style: [iconStyle, {
transform: [{
scale: checkScale
}]
}]
}, /*#__PURE__*/React.createElement(Icon, {
source: 'check',
size: iconSize,
color: textColor
})) : null, showIcon ? /*#__PURE__*/React.createElement(Animated.View, {
testID: `${testID}-icon`,
style: iconStyle
}, /*#__PURE__*/React.createElement(Icon, {
source: icon,
size: iconSize,
color: textColor
})) : null, /*#__PURE__*/React.createElement(Text, {
variant: "labelLarge",
style: [styles.label, labelTextStyle, labelStyle],
selectable: false,
numberOfLines: 1,
maxFontSizeMultiplier: labelMaxFontSizeMultiplier,
testID: `${testID}-label`
}, label))));
};
const styles = StyleSheet.create({
button: {
flex: 1,
minWidth: 76,
borderStyle: 'solid'
},
label: {
textAlign: 'center'
},
content: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 9,
paddingHorizontal: 16
}
});
export default SegmentedButtonItem;
export { SegmentedButtonItem as SegmentedButton };
//# sourceMappingURL=SegmentedButtonItem.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,99 @@
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
import * as React from 'react';
import { StyleSheet, View } from 'react-native';
import SegmentedButtonItem from './SegmentedButtonItem';
import { getDisabledSegmentedButtonStyle } from './utils';
import { useInternalTheme } from '../../core/theming';
/**
* Segmented buttons can be used to select options, switch views or sort elements.</br>
*
* ## Usage
* ```js
* import * as React from 'react';
* import { SafeAreaView, StyleSheet } from 'react-native';
* import { SegmentedButtons } from 'react-native-paper';
*
* const MyComponent = () => {
* const [value, setValue] = React.useState('');
*
* return (
* <SafeAreaView style={styles.container}>
* <SegmentedButtons
* value={value}
* onValueChange={setValue}
* buttons={[
* {
* value: 'walk',
* label: 'Walking',
* },
* {
* value: 'train',
* label: 'Transit',
* },
* { value: 'drive', label: 'Driving' },
* ]}
* />
* </SafeAreaView>
* );
* };
*
* const styles = StyleSheet.create({
* container: {
* flex: 1,
* alignItems: 'center',
* },
* });
*
* export default MyComponent;
*```
*/
const SegmentedButtons = ({
value,
onValueChange,
buttons,
multiSelect,
density,
style,
theme: themeOverrides
}) => {
const theme = useInternalTheme(themeOverrides);
return /*#__PURE__*/React.createElement(View, {
style: [styles.row, style]
}, buttons.map((item, i) => {
const disabledChildStyle = getDisabledSegmentedButtonStyle({
theme,
buttons,
index: i
});
const segment = i === 0 ? 'first' : i === buttons.length - 1 ? 'last' : undefined;
const checked = multiSelect && Array.isArray(value) ? value.includes(item.value) : value === item.value;
const onPress = e => {
var _item$onPress;
(_item$onPress = item.onPress) === null || _item$onPress === void 0 || _item$onPress.call(item, e);
const nextValue = multiSelect && Array.isArray(value) ? checked ? value.filter(val => item.value !== val) : [...value, item.value] : item.value;
// @ts-expect-error: TS doesn't preserve types after destructuring, so the type isn't inferred correctly
onValueChange(nextValue);
};
return /*#__PURE__*/React.createElement(SegmentedButtonItem, _extends({}, item, {
key: i,
checked: checked,
segment: segment,
density: density,
onPress: onPress,
style: [item.style, disabledChildStyle],
labelStyle: item.labelStyle,
theme: theme
}));
}));
};
const styles = StyleSheet.create({
row: {
flexDirection: 'row'
}
});
export default SegmentedButtons;
// @component-docs ignore-next-line
export { SegmentedButtons };
//# sourceMappingURL=SegmentedButtons.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["React","StyleSheet","View","SegmentedButtonItem","getDisabledSegmentedButtonStyle","useInternalTheme","SegmentedButtons","value","onValueChange","buttons","multiSelect","density","style","theme","themeOverrides","createElement","styles","row","map","item","i","disabledChildStyle","index","segment","length","undefined","checked","Array","isArray","includes","onPress","e","_item$onPress","call","nextValue","filter","val","_extends","key","labelStyle","create","flexDirection"],"sourceRoot":"../../../../src","sources":["components/SegmentedButtons/SegmentedButtons.tsx"],"mappings":";AAAA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAC9B,SAGEC,UAAU,EAEVC,IAAI,QAEC,cAAc;AAIrB,OAAOC,mBAAmB,MAAM,uBAAuB;AACvD,SAASC,+BAA+B,QAAQ,SAAS;AACzD,SAASC,gBAAgB,QAAQ,oBAAoB;AAuErD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,gBAAgB,GAAGA,CAA4B;EACnDC,KAAK;EACLC,aAAa;EACbC,OAAO;EACPC,WAAW;EACXC,OAAO;EACPC,KAAK;EACLC,KAAK,EAAEC;AACC,CAAC,KAAK;EACd,MAAMD,KAAK,GAAGR,gBAAgB,CAACS,cAAc,CAAC;EAE9C,oBACEd,KAAA,CAAAe,aAAA,CAACb,IAAI;IAACU,KAAK,EAAE,CAACI,MAAM,CAACC,GAAG,EAAEL,KAAK;EAAE,GAC9BH,OAAO,CAACS,GAAG,CAAC,CAACC,IAAI,EAAEC,CAAC,KAAK;IACxB,MAAMC,kBAAkB,GAAGjB,+BAA+B,CAAC;MACzDS,KAAK;MACLJ,OAAO;MACPa,KAAK,EAAEF;IACT,CAAC,CAAC;IACF,MAAMG,OAAO,GACXH,CAAC,KAAK,CAAC,GAAG,OAAO,GAAGA,CAAC,KAAKX,OAAO,CAACe,MAAM,GAAG,CAAC,GAAG,MAAM,GAAGC,SAAS;IAEnE,MAAMC,OAAO,GACXhB,WAAW,IAAIiB,KAAK,CAACC,OAAO,CAACrB,KAAK,CAAC,GAC/BA,KAAK,CAACsB,QAAQ,CAACV,IAAI,CAACZ,KAAK,CAAC,GAC1BA,KAAK,KAAKY,IAAI,CAACZ,KAAK;IAE1B,MAAMuB,OAAO,GAAIC,CAAwB,IAAK;MAAA,IAAAC,aAAA;MAC5C,CAAAA,aAAA,GAAAb,IAAI,CAACW,OAAO,cAAAE,aAAA,eAAZA,aAAA,CAAAC,IAAA,CAAAd,IAAI,EAAWY,CAAC,CAAC;MAEjB,MAAMG,SAAS,GACbxB,WAAW,IAAIiB,KAAK,CAACC,OAAO,CAACrB,KAAK,CAAC,GAC/BmB,OAAO,GACLnB,KAAK,CAAC4B,MAAM,CAAEC,GAAG,IAAKjB,IAAI,CAACZ,KAAK,KAAK6B,GAAG,CAAC,GACzC,CAAC,GAAG7B,KAAK,EAAEY,IAAI,CAACZ,KAAK,CAAC,GACxBY,IAAI,CAACZ,KAAK;;MAEhB;MACAC,aAAa,CAAC0B,SAAS,CAAC;IAC1B,CAAC;IAED,oBACElC,KAAA,CAAAe,aAAA,CAACZ,mBAAmB,EAAAkC,QAAA,KACdlB,IAAI;MACRmB,GAAG,EAAElB,CAAE;MACPM,OAAO,EAAEA,OAAQ;MACjBH,OAAO,EAAEA,OAAQ;MACjBZ,OAAO,EAAEA,OAAQ;MACjBmB,OAAO,EAAEA,OAAQ;MACjBlB,KAAK,EAAE,CAACO,IAAI,CAACP,KAAK,EAAES,kBAAkB,CAAE;MACxCkB,UAAU,EAAEpB,IAAI,CAACoB,UAAW;MAC5B1B,KAAK,EAAEA;IAAM,EACd,CAAC;EAEN,CAAC,CACG,CAAC;AAEX,CAAC;AAED,MAAMG,MAAM,GAAGf,UAAU,CAACuC,MAAM,CAAC;EAC/BvB,GAAG,EAAE;IACHwB,aAAa,EAAE;EACjB;AACF,CAAC,CAAC;AAEF,eAAenC,gBAAgB;;AAE/B;AACA,SAASA,gBAAoC","ignoreList":[]}

View File

@@ -0,0 +1,156 @@
import { StyleSheet } from 'react-native';
import color from 'color';
import { black, white } from '../../styles/themes/v2/colors';
const DEFAULT_PADDING = 9;
export const getSegmentedButtonDensityPadding = ({
density
}) => {
let padding = DEFAULT_PADDING;
switch (density) {
case 'small':
return padding - 2;
case 'medium':
return padding - 4;
case 'high':
return padding - 8;
default:
return padding;
}
};
export const getDisabledSegmentedButtonStyle = ({
theme,
index,
buttons
}) => {
var _buttons$index, _buttons;
const width = getSegmentedButtonBorderWidth({
theme
});
const isDisabled = (_buttons$index = buttons[index]) === null || _buttons$index === void 0 ? void 0 : _buttons$index.disabled;
const isNextDisabled = (_buttons = buttons[index + 1]) === null || _buttons === void 0 ? void 0 : _buttons.disabled;
if (!isDisabled && isNextDisabled) {
return {
borderRightWidth: width
};
}
return {};
};
export const getSegmentedButtonBorderRadius = ({
segment,
theme
}) => {
if (segment === 'first') {
return {
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
...(theme.isV3 && {
borderEndWidth: 0
})
};
} else if (segment === 'last') {
return {
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0
};
} else {
return {
borderRadius: 0,
...(theme.isV3 && {
borderEndWidth: 0
})
};
}
};
const getSegmentedButtonBackgroundColor = ({
checked,
theme
}) => {
if (checked) {
if (theme.isV3) {
return theme.colors.secondaryContainer;
} else {
return color(theme.colors.primary).alpha(0.12).rgb().string();
}
}
return 'transparent';
};
const getSegmentedButtonBorderColor = ({
theme,
disabled,
checked
}) => {
if (theme.isV3) {
if (disabled) {
return theme.colors.surfaceDisabled;
}
return theme.colors.outline;
}
if (checked) {
return theme.colors.primary;
}
return color(theme.dark ? white : black).alpha(0.29).rgb().string();
};
const getSegmentedButtonBorderWidth = ({
theme
}) => {
if (theme.isV3) {
return 1;
}
return StyleSheet.hairlineWidth;
};
const getSegmentedButtonTextColor = ({
theme,
disabled,
checked,
checkedColor,
uncheckedColor
}) => {
if (theme.isV3) {
if (disabled) {
return theme.colors.onSurfaceDisabled;
}
if (checked) {
return checkedColor ?? theme.colors.onSecondaryContainer;
}
return uncheckedColor ?? theme.colors.onSurface;
}
if (disabled) {
return theme.colors.disabled;
}
// Primary color is used for checked state too.
return theme.colors.primary;
};
export const getSegmentedButtonColors = ({
theme,
disabled,
checked,
checkedColor,
uncheckedColor
}) => {
const backgroundColor = getSegmentedButtonBackgroundColor({
theme,
checked
});
const borderColor = getSegmentedButtonBorderColor({
theme,
disabled,
checked
});
const textColor = getSegmentedButtonTextColor({
theme,
disabled,
checked,
checkedColor,
uncheckedColor
});
const borderWidth = getSegmentedButtonBorderWidth({
theme
});
return {
backgroundColor,
borderColor,
textColor,
borderWidth
};
};
//# sourceMappingURL=utils.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["StyleSheet","color","black","white","DEFAULT_PADDING","getSegmentedButtonDensityPadding","density","padding","getDisabledSegmentedButtonStyle","theme","index","buttons","_buttons$index","_buttons","width","getSegmentedButtonBorderWidth","isDisabled","disabled","isNextDisabled","borderRightWidth","getSegmentedButtonBorderRadius","segment","borderTopRightRadius","borderBottomRightRadius","isV3","borderEndWidth","borderTopLeftRadius","borderBottomLeftRadius","borderRadius","getSegmentedButtonBackgroundColor","checked","colors","secondaryContainer","primary","alpha","rgb","string","getSegmentedButtonBorderColor","surfaceDisabled","outline","dark","hairlineWidth","getSegmentedButtonTextColor","checkedColor","uncheckedColor","onSurfaceDisabled","onSecondaryContainer","onSurface","getSegmentedButtonColors","backgroundColor","borderColor","textColor","borderWidth"],"sourceRoot":"../../../../src","sources":["components/SegmentedButtons/utils.ts"],"mappings":"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","ignoreList":[]}