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

147 lines
3.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
* @format
* @oncall react_native
*/
'use strict';
import type {PlatformConfig} from '../AnimatedPlatformConfig';
import AnimatedNode from './AnimatedNode';
import AnimatedWithChildren from './AnimatedWithChildren';
import * as React from 'react';
const MAX_DEPTH = 5;
function isPlainObject(value: any): boolean {
return (
value !== null &&
typeof value === 'object' &&
Object.getPrototypeOf(value).isPrototypeOf(Object)
);
}
// Recurse through values, executing fn for any AnimatedNodes
function visit(value: any, fn: any => void, depth: number = 0): void {
if (depth >= MAX_DEPTH) {
return;
}
if (value instanceof AnimatedNode) {
fn(value);
} else if (Array.isArray(value)) {
value.forEach(element => {
visit(element, fn, depth + 1);
});
} else if (isPlainObject(value)) {
Object.values(value).forEach(element => {
visit(element, fn, depth + 1);
});
}
}
// Returns a copy of value with a transformation fn applied to any AnimatedNodes
function mapAnimatedNodes(value: any, fn: any => any, depth: number = 0): any {
if (depth >= MAX_DEPTH) {
return value;
}
if (value instanceof AnimatedNode) {
return fn(value);
} else if (Array.isArray(value)) {
return value.map(element => mapAnimatedNodes(element, fn, depth + 1));
} else if (isPlainObject(value)) {
const result: {[string]: any} = {};
for (const key in value) {
result[key] = mapAnimatedNodes(value[key], fn, depth + 1);
}
return result;
} else {
return value;
}
}
export function hasAnimatedNode(value: any, depth: number = 0): boolean {
if (depth >= MAX_DEPTH) {
return false;
}
if (value instanceof AnimatedNode) {
return true;
} else if (Array.isArray(value)) {
for (const element of value) {
if (hasAnimatedNode(element, depth + 1)) {
return true;
}
}
} else if (isPlainObject(value)) {
// Don't consider React elements
if (React.isValidElement(value)) {
return false;
}
for (const key in value) {
if (hasAnimatedNode(value[key], depth + 1)) {
return true;
}
}
}
return false;
}
export default class AnimatedObject extends AnimatedWithChildren {
_value: any;
constructor(value: any) {
super();
this._value = value;
}
__getValue(): any {
return mapAnimatedNodes(this._value, node => {
return node.__getValue();
});
}
__getAnimatedValue(): any {
return mapAnimatedNodes(this._value, node => {
return node.__getAnimatedValue();
});
}
__attach(): void {
super.__attach();
visit(this._value, node => {
node.__addChild(this);
});
}
__detach(): void {
visit(this._value, node => {
node.__removeChild(this);
});
super.__detach();
}
__makeNative(platformConfig: ?PlatformConfig): void {
visit(this._value, value => {
value.__makeNative(platformConfig);
});
super.__makeNative(platformConfig);
}
__getNativeConfig(): any {
return {
type: 'object',
value: mapAnimatedNodes(this._value, node => {
return {nodeTag: node.__getNativeTag()};
}),
};
}
}