- 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
68 lines
1.8 KiB
Plaintext
68 lines
1.8 KiB
Plaintext
/* @flow */
|
|
|
|
import * as React from 'react';
|
|
import deepmerge from 'deepmerge';
|
|
import hoistNonReactStatics from 'hoist-non-react-statics';
|
|
|
|
import type { ThemeProviderType } from './createThemeProvider';
|
|
import type { $DeepShape } from './types';
|
|
|
|
export type WithThemeType<T> = <P, C: React.ComponentType<P>>(
|
|
Comp: C
|
|
) => C &
|
|
React.ComponentType<
|
|
$Diff<React.ElementConfig<C>, { theme: T }> & { theme?: $DeepShape<T> }
|
|
>;
|
|
|
|
const createWithTheme = <T: Object, S: $DeepShape<T>>(
|
|
ThemeProvider: ThemeProviderType<T>,
|
|
ThemeContext: React.Context<T>
|
|
) =>
|
|
function withTheme(Comp: *) {
|
|
class ThemedComponent extends React.Component<*> {
|
|
_previous: ?{ a: T, b: ?S, result: T };
|
|
|
|
_merge = (a: T, b: ?S) => {
|
|
const previous = this._previous;
|
|
|
|
if (previous && previous.a === a && previous.b === b) {
|
|
return previous.result;
|
|
}
|
|
|
|
const result = a && b && a !== b ? deepmerge(a, b) : a || b;
|
|
|
|
this._previous = { a, b, result };
|
|
|
|
return result;
|
|
};
|
|
|
|
render() {
|
|
const { _reactThemeProviderForwardedRef, ...rest } = this.props;
|
|
|
|
return (
|
|
<ThemeContext.Consumer>
|
|
{theme => (
|
|
<Comp
|
|
{...rest}
|
|
theme={this._merge(theme, rest.theme)}
|
|
ref={_reactThemeProviderForwardedRef}
|
|
/>
|
|
)}
|
|
</ThemeContext.Consumer>
|
|
);
|
|
}
|
|
}
|
|
|
|
const ResultComponent = React.forwardRef((props, ref) => (
|
|
<ThemedComponent {...props} _reactThemeProviderForwardedRef={ref} />
|
|
));
|
|
|
|
ResultComponent.displayName = `withTheme(${Comp.displayName || Comp.name})`;
|
|
|
|
hoistNonReactStatics(ResultComponent, Comp);
|
|
|
|
return (ResultComponent: any);
|
|
};
|
|
|
|
export default createWithTheme;
|