Files
Eric FELIXINE e30ae8ed09 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
2026-06-01 18:00:35 -04:00

76 lines
2.0 KiB
TypeScript

import {
Animated,
Easing,
StyleSheet,
View,
TouchableOpacityProps as RNTouchableOpacityProps,
} from 'react-native';
import GenericTouchable, {
TOUCHABLE_STATE,
GenericTouchableProps,
} from './GenericTouchable';
import * as React from 'react';
import { Component } from 'react';
export type TouchableOpacityProps = RNTouchableOpacityProps &
GenericTouchableProps & {
useNativeAnimations?: boolean;
};
/**
* TouchableOpacity bases on timing animation which has been used in RN's core
*/
export default class TouchableOpacity extends Component<TouchableOpacityProps> {
static defaultProps = {
...GenericTouchable.defaultProps,
activeOpacity: 0.2,
};
// opacity is 1 one by default but could be overwritten
getChildStyleOpacityWithDefault = () => {
const childStyle = StyleSheet.flatten(this.props.style) || {};
return childStyle.opacity == null
? 1
: (childStyle.opacity.valueOf() as number);
};
opacity = new Animated.Value(this.getChildStyleOpacityWithDefault());
setOpacityTo = (value: number, duration: number) => {
Animated.timing(this.opacity, {
toValue: value,
duration: duration,
easing: Easing.inOut(Easing.quad),
useNativeDriver: this.props.useNativeAnimations ?? true,
}).start();
};
onStateChange = (_from: number, to: number) => {
if (to === TOUCHABLE_STATE.BEGAN) {
this.setOpacityTo(this.props.activeOpacity!, 0);
} else if (
to === TOUCHABLE_STATE.UNDETERMINED ||
to === TOUCHABLE_STATE.MOVED_OUTSIDE
) {
this.setOpacityTo(this.getChildStyleOpacityWithDefault(), 150);
}
};
render() {
const { style = {}, ...rest } = this.props;
return (
<GenericTouchable
{...rest}
style={[
style,
{
opacity: this.opacity as unknown as number, // TODO: fix this
},
]}
onStateChange={this.onStateChange}>
{this.props.children ? this.props.children : <View />}
</GenericTouchable>
);
}
}