Files
smart-city-digital-twin-mar…/smart-app-city/frontend/node_modules/react-native/Libraries/LogBox/UI/LogBoxNotification.js
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

223 lines
5.3 KiB
JavaScript

/**
* 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 {Message as MessageType} from '../Data/parseLogBoxLog';
import View from '../../Components/View/View';
import Image from '../../Image/Image';
import StyleSheet from '../../StyleSheet/StyleSheet';
import Text from '../../Text/Text';
import * as LogBoxData from '../Data/LogBoxData';
import LogBoxLog from '../Data/LogBoxLog';
import LogBoxButton from './LogBoxButton';
import LogBoxMessage from './LogBoxMessage';
import * as LogBoxStyle from './LogBoxStyle';
import * as React from 'react';
type Props = $ReadOnly<{
log: LogBoxLog,
totalLogCount: number,
level: 'warn' | 'error',
onPressOpen: () => void,
onPressDismiss: () => void,
}>;
function LogBoxLogNotification(props: Props): React.Node {
const {totalLogCount, level, log} = props;
// Eagerly symbolicate so the stack is available when pressing to inspect.
React.useEffect(() => {
LogBoxData.symbolicateLogLazy(log);
}, [log]);
return (
<View style={toastStyles.container}>
<LogBoxButton
onPress={props.onPressOpen}
style={toastStyles.press}
backgroundColor={{
default: LogBoxStyle.getBackgroundColor(1),
pressed: LogBoxStyle.getBackgroundColor(0.9),
}}>
<View style={toastStyles.content}>
<CountBadge count={totalLogCount} level={level} />
<Message message={log.message} />
<DismissButton onPress={props.onPressDismiss} />
</View>
</LogBoxButton>
</View>
);
}
function CountBadge(props: {count: number, level: 'error' | 'warn'}) {
return (
<View style={countStyles.outside}>
{/* $FlowFixMe[incompatible-type] (>=0.114.0) This suppression was added
* when fixing the type of `StyleSheet.create`. Remove this comment to
* see the error. */}
<View style={[countStyles.inside, countStyles[props.level]]}>
<Text style={countStyles.text}>
{props.count <= 1 ? '!' : props.count}
</Text>
</View>
</View>
);
}
function Message(props: {message: MessageType}) {
return (
<View style={messageStyles.container}>
<Text numberOfLines={1} style={messageStyles.text}>
{props.message && (
<LogBoxMessage
plaintext
message={props.message}
style={messageStyles.substitutionText}
/>
)}
</Text>
</View>
);
}
function DismissButton(props: {onPress: () => void}) {
return (
<View style={dismissStyles.container}>
<LogBoxButton
backgroundColor={{
default: LogBoxStyle.getTextColor(0.3),
pressed: LogBoxStyle.getTextColor(0.5),
}}
hitSlop={{
top: 12,
right: 10,
bottom: 12,
left: 10,
}}
onPress={props.onPress}
style={dismissStyles.press}>
<Image
source={require('./LogBoxImages/close.png')}
style={dismissStyles.image}
/>
</LogBoxButton>
</View>
);
}
const countStyles = StyleSheet.create({
warn: {
backgroundColor: LogBoxStyle.getWarningColor(1),
},
error: {
backgroundColor: LogBoxStyle.getErrorColor(1),
},
log: {
backgroundColor: LogBoxStyle.getLogColor(1),
},
outside: {
padding: 2,
borderRadius: 25,
backgroundColor: '#fff',
marginRight: 8,
},
inside: {
minWidth: 18,
paddingLeft: 4,
paddingRight: 4,
borderRadius: 25,
fontWeight: '600',
},
text: {
color: LogBoxStyle.getTextColor(1),
fontSize: 14,
lineHeight: 18,
textAlign: 'center',
fontWeight: '600',
textShadowColor: LogBoxStyle.getBackgroundColor(0.4),
textShadowOffset: {width: 0, height: 0},
textShadowRadius: 3,
},
});
const messageStyles = StyleSheet.create({
container: {
alignSelf: 'stretch',
flexGrow: 1,
flexShrink: 1,
flexBasis: 'auto',
borderLeftColor: LogBoxStyle.getTextColor(0.2),
borderLeftWidth: 1,
paddingLeft: 8,
},
text: {
color: LogBoxStyle.getTextColor(1),
flex: 1,
fontSize: 14,
lineHeight: 22,
},
substitutionText: {
color: LogBoxStyle.getTextColor(0.6),
},
});
const dismissStyles = StyleSheet.create({
container: {
alignSelf: 'center',
flexDirection: 'row',
flexGrow: 0,
flexShrink: 0,
flexBasis: 'auto',
marginLeft: 5,
},
press: {
height: 20,
width: 20,
borderRadius: 25,
alignSelf: 'flex-end',
alignItems: 'center',
justifyContent: 'center',
},
image: {
height: 8,
width: 8,
tintColor: LogBoxStyle.getBackgroundColor(1),
},
});
const toastStyles = StyleSheet.create({
container: {
height: 48,
position: 'relative',
width: '100%',
justifyContent: 'center',
marginTop: 0.5,
backgroundColor: LogBoxStyle.getTextColor(1),
},
press: {
height: 48,
position: 'relative',
width: '100%',
justifyContent: 'center',
marginTop: 0.5,
paddingHorizontal: 12,
},
content: {
alignItems: 'flex-start',
flexDirection: 'row',
borderRadius: 8,
flexGrow: 0,
flexShrink: 0,
flexBasis: 'auto',
},
});
export default LogBoxLogNotification;