Asset,Alarm,Module Screen is added
This commit is contained in:
47
App.tsx
47
App.tsx
@@ -1,25 +1,32 @@
|
||||
import React from 'react';
|
||||
import { StatusBar, StyleSheet, View } from 'react-native';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import HomeScreen from './src/screens/HomeScreen/homeScreen';
|
||||
import { COLORS } from './src/constants/color';
|
||||
import { AssetCard } from './src/components/assetCard';
|
||||
import AssetScreen from './src/screens/AssetsScreen/assetScreen';
|
||||
import React, { useState } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import ModuleScreen from './src/screens/ModuleScreen/moduleScreen';
|
||||
import AlarmsScreen from './src/screens/AlarmScreen/alarmScreen';
|
||||
import AssetsScreen from './src/screens/AssetsScreen/assetScreen';
|
||||
import HomeScreen from './src/screens/HomeScreen/homeScreen';
|
||||
import BottomTabBar, { TabType } from './src/navigation/bottonTabBar';
|
||||
|
||||
|
||||
|
||||
export default function App(): React.JSX.Element {
|
||||
// Use generic type annotation for useState
|
||||
const [activeTab, setActiveTab] = useState<TabType>('Home');
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<SafeAreaProvider>
|
||||
<View style={styles.container}>
|
||||
<StatusBar barStyle="light-content" backgroundColor={COLORS.background} />
|
||||
<AssetScreen />
|
||||
<View style={{ flex: 1 }}>
|
||||
|
||||
{/* SCREEN AREA */}
|
||||
<View style={{ flex: 1 }}>
|
||||
{activeTab === 'Home' && <HomeScreen />}
|
||||
{activeTab === 'Assets' && <AssetsScreen />}
|
||||
{/* {activeTab === 'Scan' && <ScanScreen />} */}
|
||||
{activeTab === 'Alarms' && <AlarmsScreen />}
|
||||
{activeTab === 'More' && <ModuleScreen />}
|
||||
</View>
|
||||
</SafeAreaProvider>
|
||||
|
||||
{/* BOTTOM TAB BAR */}
|
||||
<BottomTabBar activeTab={activeTab} setActiveTab={setActiveTab} />
|
||||
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: COLORS.background,
|
||||
},
|
||||
});
|
||||
3993
package-lock.json
generated
3993
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,9 +11,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native/new-app-screen": "0.86.0",
|
||||
"@react-navigation/bottom-tabs": "^7.18.15",
|
||||
"@react-navigation/native": "^7.3.15",
|
||||
"expo-router": "^57.0.11",
|
||||
"react": "19.2.3",
|
||||
"react-native": "0.86.0",
|
||||
"react-native-safe-area-context": "^5.8.0",
|
||||
"react-native-safe-area-context": "^5.8.1",
|
||||
"react-native-screens": "^4.26.2",
|
||||
"react-native-svg": "^15.15.5",
|
||||
"react-native-vector-icons": "^10.3.0"
|
||||
},
|
||||
|
||||
104
src/components/Alarm/alarmCard.tsx
Normal file
104
src/components/Alarm/alarmCard.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import React from 'react';
|
||||
import { View, Text, TouchableOpacity } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
|
||||
import { COLORS } from '../../constants/color';
|
||||
import { AlarmCardProps, SeverityLevel } from '../../types/type';
|
||||
import { styles } from '../../styles/Alarm/alarmcard';
|
||||
|
||||
// Map severity levels to designated theme colors
|
||||
const getSeverityColor = (severity: SeverityLevel): string => {
|
||||
switch (severity) {
|
||||
case 'CRITICAL':
|
||||
return COLORS.red;
|
||||
case 'HIGH':
|
||||
return COLORS.red;
|
||||
case 'MEDIUM':
|
||||
return COLORS.orange;
|
||||
case 'LOW':
|
||||
return COLORS.cyan;
|
||||
default:
|
||||
return COLORS.textSecondary;
|
||||
}
|
||||
};
|
||||
|
||||
export default function AlarmCard ({alarm,onAcknowledge,onAssign,onPressDetails }:AlarmCardProps)
|
||||
{
|
||||
const accentColor = getSeverityColor(alarm.severity);
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.card,
|
||||
alarm.isExpanded && { borderColor: accentColor },
|
||||
]}
|
||||
>
|
||||
{/* Vertical Accent Strip */}
|
||||
<View
|
||||
style={[
|
||||
styles.statusIndicator,
|
||||
{ backgroundColor: accentColor },
|
||||
]}
|
||||
/>
|
||||
|
||||
<View style={styles.cardContent}>
|
||||
{/* Header */}
|
||||
<View style={styles.headerRow}>
|
||||
<View
|
||||
style={[
|
||||
styles.badge,
|
||||
{ backgroundColor: `${accentColor}20` },
|
||||
]}
|
||||
>
|
||||
<Text
|
||||
style={[
|
||||
styles.badgeText,
|
||||
{ color: accentColor },
|
||||
]}
|
||||
>
|
||||
{alarm.severity}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<Text style={styles.timeAgo}>{alarm.timeAgo}</Text>
|
||||
</View>
|
||||
|
||||
{/* Title */}
|
||||
<Text style={styles.title}>{alarm.title}</Text>
|
||||
|
||||
{/* Details */}
|
||||
<Text style={styles.details}>{alarm.details}</Text>
|
||||
|
||||
{/* Expanded Buttons */}
|
||||
{alarm.isExpanded && (
|
||||
<View style={styles.actionRow}>
|
||||
<TouchableOpacity
|
||||
style={styles.acknowledgeButton}
|
||||
onPress={() => onAcknowledge?.(alarm.id)}
|
||||
>
|
||||
<Text style={styles.acknowledgeText}>Acknowledge</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.assignButton}
|
||||
onPress={() => onAssign?.(alarm.id)}
|
||||
>
|
||||
<Text style={styles.assignText}>Assign</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.iconButton}
|
||||
onPress={() => onPressDetails?.(alarm.id)}
|
||||
>
|
||||
<Ionicons
|
||||
name="chevron-forward"
|
||||
size={18}
|
||||
color={COLORS.textPrimary}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import { View, Text } from "react-native";
|
||||
import { Asset, AssetCardProps } from "../types/type";
|
||||
import { styles } from "../styles/AssetCard";
|
||||
import { Asset, AssetCardProps } from "../../types/type";
|
||||
import { styles } from "../../styles/Asset/AssetCard";
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
import { View, TextInput } from "react-native";
|
||||
import { COLORS } from "../constants/color";
|
||||
import { styles } from "../styles/SearchbarStyles";
|
||||
import {SearchBarProps} from "../types/type"
|
||||
import { COLORS } from "../../constants/color";
|
||||
import { styles } from "../../styles/Home/SearchbarStyles";
|
||||
import {SearchBarProps} from "../../types/type"
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { View, Text, TouchableOpacity } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { styles } from '../styles/ActionGridStyles';
|
||||
import { actions } from '../constants/data';
|
||||
import { styles } from '../../styles/Home/ActionGridStyles';
|
||||
import { actions } from '../../constants/data';
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import { View, Text, TouchableOpacity } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { COLORS } from '../constants/color';
|
||||
import { HeaderProps } from '../types/type';
|
||||
import { styles } from '../styles/HeaderStyles';
|
||||
import { COLORS } from '../../constants/color';
|
||||
import { HeaderProps } from '../../types/type';
|
||||
import { styles } from '../../styles/Home/HeaderStyles';
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ import React from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
import Svg, { Circle } from 'react-native-svg';
|
||||
|
||||
import { COLORS } from '../constants/color';
|
||||
import { styles } from '../styles/SiteHealthCardStyles';
|
||||
import Card from '../utils/card';
|
||||
import { COLORS } from '../../constants/color';
|
||||
import { styles } from '../../styles/Home/SiteHealthCardStyles';
|
||||
import Card from '../common/card';
|
||||
|
||||
export default function SiteHealthCard() {
|
||||
return (
|
||||
@@ -2,9 +2,9 @@ import React from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
|
||||
import { StatCardProps } from '../types/type';
|
||||
import Card from '../utils/card';
|
||||
import { styles } from '../styles/StatCardStyle';
|
||||
import { StatCardProps } from '../../types/type';
|
||||
import Card from '../common/card';
|
||||
import { styles } from '../../styles/StatCardStyle';
|
||||
|
||||
|
||||
|
||||
76
src/components/Module/module.tsx
Normal file
76
src/components/Module/module.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import React from 'react';
|
||||
import { Text, TouchableOpacity, StyleSheet, View, Platform } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
|
||||
import { COLORS } from '../../constants/color';
|
||||
import Card from '../common/card';
|
||||
|
||||
export interface ModuleItem {
|
||||
id: string;
|
||||
title: string;
|
||||
iconName: string;
|
||||
iconColor: string;
|
||||
}
|
||||
|
||||
interface ModuleTileProps {
|
||||
module: ModuleItem;
|
||||
onPress?: (module: ModuleItem) => void;
|
||||
}
|
||||
|
||||
export const ModuleTile: React.FC<ModuleTileProps> = ({ module, onPress }) => {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.7}
|
||||
style={styles.touchable}
|
||||
onPress={() => onPress?.(module)}
|
||||
>
|
||||
<Card style={styles.cardOverride}>
|
||||
<View style={styles.iconContainer}>
|
||||
<Ionicons name={module.iconName} size={28} color={module.iconColor} />
|
||||
</View>
|
||||
<Text style={styles.title} numberOfLines={2}>
|
||||
{module.title}
|
||||
</Text>
|
||||
</Card>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
touchable: {
|
||||
width: '30.5%',
|
||||
},
|
||||
cardOverride: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingVertical: 16,
|
||||
paddingHorizontal: 8,
|
||||
height: 100,
|
||||
borderRadius: 16,
|
||||
backgroundColor: '#162032', // Dark card background
|
||||
|
||||
// --- BORDER STYLING ---
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255, 255, 255, 0.08)', // Subtle border highlight
|
||||
|
||||
// --- SHADOW FOR iOS ---
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.35,
|
||||
shadowRadius: 6,
|
||||
|
||||
// --- SHADOW FOR ANDROID ---
|
||||
elevation: 6,
|
||||
},
|
||||
iconContainer: {
|
||||
marginBottom: 8,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
title: {
|
||||
color: '#FFFFFF',
|
||||
fontSize: 12,
|
||||
fontWeight: '500',
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
||||
83
src/components/Notification/notificationcard.tsx
Normal file
83
src/components/Notification/notificationcard.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import React from 'react';
|
||||
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { NotificationCardProps } from '../../types/type';
|
||||
import Card from '../common/card';
|
||||
import { COLORS } from '../../constants/color';
|
||||
|
||||
|
||||
|
||||
|
||||
export const NotificationCard: React.FC<NotificationCardProps> = ({
|
||||
notification,
|
||||
onPress,
|
||||
}) => {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.8}
|
||||
onPress={() => onPress?.(notification.id)}
|
||||
style={styles.touchable}
|
||||
>
|
||||
<Card style={styles.cardOverride}>
|
||||
{/* Left Icon Container with Soft Colored Background */}
|
||||
<View style={[styles.iconContainer, { backgroundColor: notification.iconBgColor }]}>
|
||||
<Ionicons
|
||||
name={notification.iconName}
|
||||
size={20}
|
||||
color={notification.iconColor}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Text Content */}
|
||||
<View style={styles.content}>
|
||||
<Text style={styles.title} numberOfLines={1}>
|
||||
{notification.title}
|
||||
</Text>
|
||||
<Text style={styles.subtitle} numberOfLines={1}>
|
||||
{notification.subtitle}
|
||||
</Text>
|
||||
<Text style={styles.time}>{notification.time}</Text>
|
||||
</View>
|
||||
</Card>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
touchable: {
|
||||
marginBottom: 12,
|
||||
},
|
||||
cardOverride: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'flex-start',
|
||||
padding: 14,
|
||||
borderRadius: 16,
|
||||
},
|
||||
iconContainer: {
|
||||
width: 42,
|
||||
height: 42,
|
||||
borderRadius: 12,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginRight: 14,
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
},
|
||||
title: {
|
||||
color: COLORS.textPrimary,
|
||||
fontSize: 16,
|
||||
fontWeight: '700',
|
||||
marginBottom: 3,
|
||||
},
|
||||
subtitle: {
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 13,
|
||||
marginBottom: 4,
|
||||
},
|
||||
time: {
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 12,
|
||||
opacity: 0.8,
|
||||
},
|
||||
});
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
|
||||
import { styles } from '../styles/cardStyle';
|
||||
import { CardProps } from '../types/type';
|
||||
import { styles } from '../../styles/cardStyle';
|
||||
import { CardProps } from '../../types/type';
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Asset } from "../types/type";
|
||||
import { ModuleItem } from "../components/Module/module";
|
||||
import { AlarmItem, Asset, NotificationItem } from "../types/type";
|
||||
import { COLORS } from "./color";
|
||||
|
||||
export const actions = [
|
||||
@@ -109,3 +110,168 @@ export const SAMPLE_ASSETS: Asset[] = [
|
||||
health: 96,
|
||||
},
|
||||
];
|
||||
|
||||
export const ALARM_DATA: AlarmItem[] = [
|
||||
{
|
||||
id: '1',
|
||||
severity: 'CRITICAL',
|
||||
title: 'CH-02 compressor trip',
|
||||
details: 'Plant Room B1 · discharge 21.4 bar · load shifted to CH-01',
|
||||
timeAgo: '4m ago',
|
||||
isExpanded: true, // First item active/expanded with buttons
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
severity: 'HIGH',
|
||||
title: 'AHU-03 supply fan overload',
|
||||
details: 'Floor 5 · motor current 14.8 A',
|
||||
timeAgo: '18m ago',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
severity: 'MEDIUM',
|
||||
title: 'P-07 vibration above baseline',
|
||||
details: 'Plant Room B1 · 7.2 mm/s RMS',
|
||||
timeAgo: '41m ago',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
severity: 'MEDIUM',
|
||||
title: 'IAQ CO₂ high — Zone 4A',
|
||||
details: 'Floor 4 · 1,180 ppm',
|
||||
timeAgo: '1h ago',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
severity: 'LOW',
|
||||
title: 'Water tank T-02 level low',
|
||||
details: 'Terrace · 34% capacity',
|
||||
timeAgo: '2h ago',
|
||||
},
|
||||
];
|
||||
|
||||
export const NOTIFICATIONS_DATA = [
|
||||
{
|
||||
title: 'TODAY',
|
||||
data: [
|
||||
{
|
||||
id: '1',
|
||||
type: 'CRITICAL',
|
||||
title: 'Critical alarm — CH-02 trip',
|
||||
subtitle: 'Plant Room B1 · discharge 21.4 bar',
|
||||
time: '2 min ago',
|
||||
iconName: 'warning-outline',
|
||||
iconColor: COLORS.red,
|
||||
iconBgColor: '#2D1A24',
|
||||
section: 'TODAY',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'SETPOINT',
|
||||
title: 'Setpoint applied — AHU-01',
|
||||
subtitle: '18.0 °C · via Remote Control',
|
||||
time: '28 min ago',
|
||||
iconName: 'locate-outline',
|
||||
iconColor: COLORS.cyan,
|
||||
iconBgColor: '#122536',
|
||||
section: 'TODAY',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'AIR_QUALITY',
|
||||
title: 'Air quality — Zone 4A',
|
||||
subtitle: 'CO₂ 1,180 ppm · damper auto-opened',
|
||||
time: '1 h ago',
|
||||
iconName: 'pulse-outline',
|
||||
iconColor: COLORS.cyan,
|
||||
iconBgColor: '#122536',
|
||||
section: 'TODAY',
|
||||
},
|
||||
] as NotificationItem[],
|
||||
},
|
||||
{
|
||||
title: 'EARLIER',
|
||||
data: [
|
||||
{
|
||||
id: '4',
|
||||
type: 'SUCCESS',
|
||||
title: 'PPM-1198 completed & synced',
|
||||
subtitle: 'DG-01 monthly · by Suresh K.',
|
||||
time: 'Yesterday · 17:20',
|
||||
iconName: 'checkmark',
|
||||
iconColor: COLORS.green,
|
||||
iconBgColor: '#0F2C2B',
|
||||
section: 'EARLIER',
|
||||
},
|
||||
] as NotificationItem[],
|
||||
},
|
||||
];
|
||||
|
||||
export const MODULES_DATA: ModuleItem[] = [
|
||||
{
|
||||
id: '1',
|
||||
title: 'Equipment',
|
||||
iconName: 'cube-outline',
|
||||
iconColor: COLORS.green,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: 'Optix AI',
|
||||
iconName: 'sparkles-outline',
|
||||
iconColor: COLORS.orange,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: 'Energy',
|
||||
iconName: 'flash-outline',
|
||||
iconColor: COLORS.orange,
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
title: 'Remote Ctrl',
|
||||
iconName: 'locate-outline',
|
||||
iconColor: COLORS.cyan,
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
title: 'Help Desk',
|
||||
iconName: 'chatbox-outline',
|
||||
iconColor: COLORS.cyan,
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
title: 'Visitors',
|
||||
iconName: 'person-add-outline',
|
||||
iconColor: COLORS.green,
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
title: 'Attendance',
|
||||
iconName: 'checkbox-outline',
|
||||
iconColor: COLORS.green,
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
title: 'Air Quality',
|
||||
iconName: 'pulse-outline',
|
||||
iconColor: COLORS.cyan,
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
title: 'Alerts',
|
||||
iconName: 'notifications-outline',
|
||||
iconColor: COLORS.orange,
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
title: 'Offline Sync',
|
||||
iconName: 'sync-outline',
|
||||
iconColor: COLORS.textSecondary,
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
title: 'Profile',
|
||||
iconName: 'person-outline',
|
||||
iconColor: COLORS.textSecondary,
|
||||
},
|
||||
];
|
||||
@@ -5,57 +5,89 @@ import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { styles } from '../styles/BottontabStyle';
|
||||
import { COLORS } from '../constants/color';
|
||||
|
||||
export default function BottomTabBar() {
|
||||
// Define allowed tab names as a TypeScript type
|
||||
export type TabType = 'Home' | 'Assets' | 'Scan' | 'Alarms' | 'More';
|
||||
|
||||
// Interface for component props
|
||||
interface BottomTabBarProps {
|
||||
activeTab: TabType;
|
||||
setActiveTab: (tab: TabType) => void;
|
||||
}
|
||||
|
||||
export default function BottomTabBar({ activeTab, setActiveTab }: BottomTabBarProps) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
|
||||
{/* Home */}
|
||||
<TouchableOpacity style={styles.tab}>
|
||||
<Ionicons name="home" size={22} color={COLORS.tabActive} />
|
||||
<Text style={[styles.label, { color: COLORS.tabActive }]}>
|
||||
<TouchableOpacity
|
||||
style={styles.tab}
|
||||
onPress={() => setActiveTab('Home')}
|
||||
>
|
||||
<Ionicons
|
||||
name={activeTab === 'Home' ? "home" : "home-outline"}
|
||||
size={22}
|
||||
color={activeTab === 'Home' ? COLORS.tabActive : COLORS.tabInactive}
|
||||
/>
|
||||
<Text style={[styles.label, { color: activeTab === 'Home' ? COLORS.tabActive : COLORS.tabInactive }]}>
|
||||
Home
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* Assets */}
|
||||
<TouchableOpacity style={styles.tab}>
|
||||
<Ionicons name="cube-outline" size={22} color={COLORS.tabInactive} />
|
||||
<Text style={styles.label}>
|
||||
<TouchableOpacity
|
||||
style={styles.tab}
|
||||
onPress={() => setActiveTab('Assets')}
|
||||
>
|
||||
<Ionicons
|
||||
name={activeTab === 'Assets' ? "cube" : "cube-outline"}
|
||||
size={22}
|
||||
color={activeTab === 'Assets' ? COLORS.tabActive : COLORS.tabInactive}
|
||||
/>
|
||||
<Text style={[styles.label, { color: activeTab === 'Assets' ? COLORS.tabActive : COLORS.tabInactive }]}>
|
||||
Assets
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* Scan Button */}
|
||||
<View style={styles.scanContainer}>
|
||||
<TouchableOpacity style={styles.scanButton}>
|
||||
<TouchableOpacity
|
||||
style={styles.scanButton}
|
||||
onPress={() => setActiveTab('Scan')}
|
||||
>
|
||||
<Ionicons name="scan" size={28} color="#000" />
|
||||
</TouchableOpacity>
|
||||
|
||||
<Text style={[styles.label, { color: COLORS.tabActive }]}>
|
||||
<Text style={[styles.label, { color: activeTab === 'Scan' ? COLORS.tabActive : COLORS.tabInactive }]}>
|
||||
Scan
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Alarms */}
|
||||
<TouchableOpacity style={styles.tab}>
|
||||
<TouchableOpacity
|
||||
style={styles.tab}
|
||||
onPress={() => setActiveTab('Alarms')}
|
||||
>
|
||||
<Ionicons
|
||||
name="notifications-outline"
|
||||
name={activeTab === 'Alarms' ? "notifications" : "notifications-outline"}
|
||||
size={22}
|
||||
color={COLORS.tabInactive}
|
||||
color={activeTab === 'Alarms' ? COLORS.tabActive : COLORS.tabInactive}
|
||||
/>
|
||||
<Text style={styles.label}>
|
||||
<Text style={[styles.label, { color: activeTab === 'Alarms' ? COLORS.tabActive : COLORS.tabInactive }]}>
|
||||
Alarms
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
{/* More */}
|
||||
<TouchableOpacity style={styles.tab}>
|
||||
<TouchableOpacity
|
||||
style={styles.tab}
|
||||
onPress={() => setActiveTab('More')}
|
||||
>
|
||||
<Ionicons
|
||||
name="ellipsis-horizontal"
|
||||
name={activeTab === 'More' ? "ellipsis-horizontal" : "ellipsis-horizontal-outline"}
|
||||
size={22}
|
||||
color={COLORS.tabInactive}
|
||||
color={activeTab === 'More' ? COLORS.tabActive : COLORS.tabInactive}
|
||||
/>
|
||||
<Text style={styles.label}>
|
||||
<Text style={[styles.label, { color: activeTab === 'More' ? COLORS.tabActive : COLORS.tabInactive }]}>
|
||||
More
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
159
src/screens/AirqualityScreen/airqualityScreen.tsx
Normal file
159
src/screens/AirqualityScreen/airqualityScreen.tsx
Normal file
@@ -0,0 +1,159 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
TouchableOpacity,
|
||||
SafeAreaView,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
} from 'react-native';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import Svg, { Circle, Path, Line } from 'react-native-svg';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { styles } from '../../styles/Airquality/airqualityScreen';
|
||||
|
||||
|
||||
export default function AirQualityScreen() {
|
||||
return (
|
||||
<SafeAreaProvider style={styles.container}>
|
||||
<StatusBar barStyle="light-content" backgroundColor="#070D18" />
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{/* Top Header */}
|
||||
<View style={styles.header}>
|
||||
<TouchableOpacity style={styles.backButton} activeOpacity={0.7}>
|
||||
<Ionicons name="chevron-back" size={20} color="#FFFFFF" />
|
||||
</TouchableOpacity>
|
||||
<View style={styles.headerTitleContainer}>
|
||||
<Text style={styles.headerTitle}>Air Quality</Text>
|
||||
<Text style={styles.headerSubtitle}>Floor 4 · Zone 4A · live</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Main AQI Banner */}
|
||||
<View style={styles.bannerCard}>
|
||||
{/* Circular Gauge */}
|
||||
<View style={styles.gaugeContainer}>
|
||||
<Svg width={120} height={120} viewBox="0 0 120 120">
|
||||
{/* Gauge Track */}
|
||||
<Circle
|
||||
cx="60"
|
||||
cy="60"
|
||||
r="46"
|
||||
stroke="#1B293E"
|
||||
strokeWidth="10"
|
||||
fill="none"
|
||||
/>
|
||||
{/* Active Progress Arc */}
|
||||
<Circle
|
||||
cx="60"
|
||||
cy="60"
|
||||
r="46"
|
||||
stroke="#F59E0B"
|
||||
strokeWidth="10"
|
||||
fill="none"
|
||||
strokeDasharray="289"
|
||||
strokeDashoffset="75"
|
||||
strokeLinecap="round"
|
||||
transform="rotate(135 60 60)"
|
||||
/>
|
||||
</Svg>
|
||||
<View style={styles.gaugeTextContainer}>
|
||||
<Text style={styles.aqiValue}>78</Text>
|
||||
<Text style={styles.aqiLabel}>AQI</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Banner Description */}
|
||||
<View style={styles.bannerDetails}>
|
||||
<View style={styles.badge}>
|
||||
<Text style={styles.badgeText}>MODERATE</Text>
|
||||
</View>
|
||||
<Text style={styles.bannerDescription}>
|
||||
CO₂ slightly elevated. Fresh-air damper increased to 35% automatically.
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Metric Cards Grid */}
|
||||
<View style={styles.grid}>
|
||||
{/* CO2 Metric */}
|
||||
<View style={styles.card}>
|
||||
<Text style={styles.cardTitle}>
|
||||
CO<Text style={styles.subscript}>2</Text>
|
||||
</Text>
|
||||
<View style={styles.valueRow}>
|
||||
<Text style={[styles.cardValue, { color: '#F59E0B' }]}>1,180</Text>
|
||||
<Text style={styles.cardUnit}>ppm</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* PM2.5 Metric */}
|
||||
<View style={styles.card}>
|
||||
<Text style={styles.cardTitle}>PM2.5</Text>
|
||||
<View style={styles.valueRow}>
|
||||
<Text style={[styles.cardValue, { color: '#10B981' }]}>18</Text>
|
||||
<Text style={styles.cardUnit}>μg/m³</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* TVOC Metric */}
|
||||
<View style={styles.card}>
|
||||
<Text style={styles.cardTitle}>TVOC</Text>
|
||||
<View style={styles.valueRow}>
|
||||
<Text style={[styles.cardValue, { color: '#10B981' }]}>0.31</Text>
|
||||
<Text style={styles.cardUnit}>ppm</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Temp / RH Metric */}
|
||||
<View style={styles.card}>
|
||||
<Text style={styles.cardTitle}>Temp / RH</Text>
|
||||
<View style={styles.valueRow}>
|
||||
<Text style={[styles.cardValue, { color: '#FFFFFF' }]}>23.4°</Text>
|
||||
<Text style={styles.secondaryValue}> · 52%</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Chart Section */}
|
||||
<View style={styles.chartCard}>
|
||||
<View style={styles.chartHeader}>
|
||||
<Text style={styles.chartTitle}>
|
||||
CO<Text style={styles.subscript}>2</Text> · LAST 12H
|
||||
</Text>
|
||||
<Text style={styles.chartSubtitle}>peak 1,240 · 14:00</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.chartContainer}>
|
||||
<Svg width="100%" height={70} viewBox="0 0 300 70">
|
||||
{/* Threshold Line */}
|
||||
<Line
|
||||
x1="0"
|
||||
y1="35"
|
||||
x2="300"
|
||||
y2="35"
|
||||
stroke="#B91C1C"
|
||||
strokeDasharray="4, 4"
|
||||
strokeWidth="1.5"
|
||||
opacity={0.6}
|
||||
/>
|
||||
{/* Trend Line */}
|
||||
<Path
|
||||
d="M 0 55 Q 60 50 120 40 T 240 48 L 300 42"
|
||||
fill="none"
|
||||
stroke="#F59E0B"
|
||||
strokeWidth="3.5"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</Svg>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
|
||||
50
src/screens/AlarmScreen/alarmScreen.tsx
Normal file
50
src/screens/AlarmScreen/alarmScreen.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
|
||||
View,
|
||||
Text,
|
||||
FlatList,
|
||||
StyleSheet,
|
||||
StatusBar,
|
||||
} from 'react-native';
|
||||
import { AlarmItem } from '../../types/type';
|
||||
import { ALARM_DATA } from '../../constants/data';
|
||||
import AlarmCard from '../../components/Alarm/alarmCard';
|
||||
import { COLORS } from '../../constants/color';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import { styles } from '../../styles/Alarm/alarmScreen';
|
||||
|
||||
|
||||
|
||||
|
||||
export default function AlarmsScreen() {
|
||||
const [alarms, setAlarms] = useState<AlarmItem[]>(ALARM_DATA);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<SafeAreaProvider style={{ flex: 1, backgroundColor: COLORS.background }}>
|
||||
<StatusBar barStyle="light-content" backgroundColor={COLORS.background} />
|
||||
|
||||
<FlatList
|
||||
data={alarms}
|
||||
keyExtractor={(item) => item.id}
|
||||
renderItem={({ item }) => (
|
||||
<AlarmCard
|
||||
alarm={item}
|
||||
|
||||
/>
|
||||
)}
|
||||
ListHeaderComponent={
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.title}>Alarms</Text>
|
||||
<Text style={styles.subtitle}>Live event stream</Text>
|
||||
</View>
|
||||
}
|
||||
contentContainerStyle={styles.listContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
/>
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,11 +10,12 @@ import {
|
||||
import { SAMPLE_ASSETS } from '../../constants/data';
|
||||
import { COLORS } from '../../constants/color';
|
||||
import { } from '../../types/type';
|
||||
import { SearchBar } from '../../components/searchbar';
|
||||
import { AssetCard } from '../../components/assetCard';
|
||||
import { SearchBar } from '../../components/Asset/searchbar';
|
||||
import { AssetCard } from '../../components/Asset/assetCard';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import BottomTabBar from '../../navigation/bottonTabBar';
|
||||
import { ScrollView } from 'react-native';
|
||||
import { styles } from '../../styles/Asset/assetScreen';
|
||||
|
||||
|
||||
|
||||
@@ -29,9 +30,10 @@ export default function AssetsScreen() {
|
||||
|
||||
return (
|
||||
<SafeAreaProvider style={{ flex: 1, backgroundColor: COLORS.background }}>
|
||||
<ScrollView>
|
||||
|
||||
<StatusBar barStyle="light-content" backgroundColor={COLORS.background} />
|
||||
<View style={styles.content}>
|
||||
|
||||
{/* Header Section */}
|
||||
<Text style={styles.title}>Assets</Text>
|
||||
<Text style={styles.subtitle}>251 assets · 242 online</Text>
|
||||
@@ -46,32 +48,11 @@ export default function AssetsScreen() {
|
||||
renderItem={({ item }) => <AssetCard asset={item} />}
|
||||
showsVerticalScrollIndicator={false}
|
||||
/>
|
||||
|
||||
</View>
|
||||
</ScrollView>
|
||||
<BottomTabBar />
|
||||
|
||||
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: COLORS.background,
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 20,
|
||||
paddingTop: 16,
|
||||
},
|
||||
title: {
|
||||
color: COLORS.textPrimary,
|
||||
fontSize: 28,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
subtitle: {
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 14,
|
||||
marginTop: 4,
|
||||
marginBottom: 16,
|
||||
},
|
||||
});
|
||||
@@ -1,16 +1,16 @@
|
||||
import React from 'react';
|
||||
import { View, StyleSheet, ScrollView,Text } from 'react-native';
|
||||
import { View, ScrollView,Text } from 'react-native';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
|
||||
import { cards } from '../../constants/data';
|
||||
import { COLORS } from '../../constants/color';
|
||||
import Header from '../../components/header';
|
||||
import SiteHealthCard from '../../components/siteHealthCard';
|
||||
import ActionGrid from '../../components/actionGrid';
|
||||
import StatCard from '../../components/statCard';
|
||||
import BottomTabBar from '../../navigation/bottonTabBar';
|
||||
import Card from '../../utils/card';
|
||||
import Header from '../../components/Home/header';
|
||||
import SiteHealthCard from '../../components/Home/siteHealthCard';
|
||||
import ActionGrid from '../../components/Home/actionGrid';
|
||||
import StatCard from '../../components/Home/statCard';
|
||||
import Card from '../../components/common/card';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import styles from '../../styles/Home/homeScreen';
|
||||
|
||||
export default function HomeScreen() {
|
||||
return (
|
||||
@@ -92,7 +92,7 @@ export default function HomeScreen() {
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<BottomTabBar />
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -103,60 +103,4 @@ export default function HomeScreen() {
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: COLORS.background,
|
||||
},
|
||||
scrollContent: {
|
||||
paddingHorizontal: 16,
|
||||
paddingTop: 16,
|
||||
paddingBottom: 20,
|
||||
},
|
||||
gridRow: {
|
||||
|
||||
flexDirection: 'row',
|
||||
flexGrow:1,
|
||||
|
||||
marginBottom: 8,
|
||||
gap:10
|
||||
},
|
||||
card: {
|
||||
|
||||
borderColor: COLORS.orange,
|
||||
|
||||
marginHorizontal: 10,
|
||||
|
||||
marginTop: 10,
|
||||
|
||||
marginBottom: 20,
|
||||
},
|
||||
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
|
||||
alignItems: 'center',
|
||||
|
||||
marginBottom: 10,
|
||||
},
|
||||
|
||||
title: {
|
||||
color: COLORS.orange,
|
||||
|
||||
fontSize: 18,
|
||||
|
||||
fontWeight: 'bold',
|
||||
|
||||
marginLeft: 8,
|
||||
},
|
||||
|
||||
message: {
|
||||
color: COLORS.textPrimary,
|
||||
|
||||
fontSize: 16,
|
||||
|
||||
lineHeight: 24,
|
||||
|
||||
marginLeft: 20,
|
||||
},
|
||||
});
|
||||
|
||||
48
src/screens/ModuleScreen/moduleScreen.tsx
Normal file
48
src/screens/ModuleScreen/moduleScreen.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
SafeAreaView,
|
||||
View,
|
||||
Text,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
StatusBar,
|
||||
} from 'react-native';
|
||||
import { COLORS } from '../../constants/color';
|
||||
import { ModuleTile } from '../../components/Module/module';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import { MODULES_DATA } from '../../constants/data';
|
||||
import styles from '../../styles/Module/module';
|
||||
|
||||
|
||||
|
||||
|
||||
export default function ModulesScreen() {
|
||||
|
||||
|
||||
return (
|
||||
<SafeAreaProvider style={{ flex: 1, backgroundColor: COLORS.background }}>
|
||||
|
||||
<StatusBar barStyle="light-content" backgroundColor={COLORS.background} />
|
||||
|
||||
<ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
|
||||
{/* Header Title & Subtitle */}
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.title}>All modules</Text>
|
||||
<Text style={styles.subtitle}>Facility Management & IoT platform</Text>
|
||||
</View>
|
||||
|
||||
{/* 3-Column Grid Container */}
|
||||
<View style={styles.gridContainer}>
|
||||
{MODULES_DATA.map((item) => (
|
||||
<ModuleTile
|
||||
key={item.id}
|
||||
module={item}
|
||||
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</ScrollView>
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
|
||||
64
src/screens/Notification/notification.tsx
Normal file
64
src/screens/Notification/notification.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
SafeAreaView,
|
||||
View,
|
||||
Text,
|
||||
SectionList,
|
||||
TouchableOpacity,
|
||||
StyleSheet,
|
||||
StatusBar,
|
||||
} from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { COLORS } from '../../constants/color';
|
||||
import { NOTIFICATIONS_DATA } from '../../constants/data';
|
||||
import { NotificationCard } from '../../components/Notification/notificationcard';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
import { styles } from '../../styles/Notification/notification';
|
||||
|
||||
|
||||
|
||||
|
||||
export default function NotificationsScreen({ navigation }: any) {
|
||||
const [sections, setSections] = useState(NOTIFICATIONS_DATA);
|
||||
|
||||
|
||||
|
||||
const handleBackPress = () => {
|
||||
if (navigation) {
|
||||
navigation.goBack();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaProvider style={styles.container}>
|
||||
<StatusBar barStyle="light-content" backgroundColor={COLORS.background} />
|
||||
|
||||
{/* Header Bar */}
|
||||
<View style={styles.headerRow}>
|
||||
<TouchableOpacity style={styles.backButton} onPress={handleBackPress}>
|
||||
<Ionicons name="chevron-back" size={20} color={COLORS.textPrimary} />
|
||||
</TouchableOpacity>
|
||||
|
||||
<Text style={styles.headerTitle}>Notifications</Text>
|
||||
|
||||
<TouchableOpacity >
|
||||
<Text style={styles.markAllReadText}>Mark all read</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Grouped Notifications List */}
|
||||
<SectionList
|
||||
sections={sections}
|
||||
keyExtractor={(item) => item.id}
|
||||
renderItem={({ item }) => <NotificationCard notification={item} />}
|
||||
renderSectionHeader={({ section: { title } }) => (
|
||||
<Text style={styles.sectionHeader}>{title}</Text>
|
||||
)}
|
||||
contentContainerStyle={styles.listContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
stickySectionHeadersEnabled={false}
|
||||
/>
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
|
||||
125
src/screens/ProfileScreen/profilescreen.tsx
Normal file
125
src/screens/ProfileScreen/profilescreen.tsx
Normal file
@@ -0,0 +1,125 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
TouchableOpacity,
|
||||
Switch,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
} from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import { styles } from '../../styles/Profile/profile';
|
||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||
|
||||
export default function ProfileScreen() {
|
||||
|
||||
return (
|
||||
<SafeAreaProvider style={styles.container}>
|
||||
<StatusBar barStyle="light-content" backgroundColor="#0A111E" />
|
||||
<ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
|
||||
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<TouchableOpacity style={styles.backButton} activeOpacity={0.7}>
|
||||
<Ionicons name="chevron-back" size={20} color="#FFFFFF" />
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.headerTitle}>Profile</Text>
|
||||
</View>
|
||||
|
||||
{/* Profile Card Info */}
|
||||
<View style={styles.profileContainer}>
|
||||
<View style={styles.avatar}>
|
||||
<Text style={styles.avatarText}>AM</Text>
|
||||
</View>
|
||||
<View style={styles.userInfo}>
|
||||
<Text style={styles.userName}>Arjun Mehta</Text>
|
||||
<Text style={styles.userRole}>Facility Engineer · Shift A</Text>
|
||||
<Text style={styles.userLocation}>Godrej One — Vikhroli</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Metrics/Stats Row */}
|
||||
<View style={styles.statsRow}>
|
||||
<View style={styles.statCard}>
|
||||
<Text style={[styles.statValue, { color: '#FFFFFF' }]}>128</Text>
|
||||
<Text style={styles.statLabel}>WOs closed</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.statCard}>
|
||||
<Text style={[styles.statValue, { color: '#10B981' }]}>96%</Text>
|
||||
<Text style={styles.statLabel}>PPM on-time</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.statCard}>
|
||||
<Text style={[styles.statValue, { color: '#F97316' }]}>4.8</Text>
|
||||
<Text style={styles.statLabel}>Rating</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Options Menu Container */}
|
||||
<View style={styles.menuContainer}>
|
||||
{/* Push Notifications */}
|
||||
<View style={styles.menuItem}>
|
||||
<View style={styles.menuLeft}>
|
||||
<Ionicons name="notifications-outline" size={22} color="#60A5FA" />
|
||||
<Text style={styles.menuText}>Push notifications</Text>
|
||||
</View>
|
||||
<Switch
|
||||
|
||||
trackColor={{ false: '#374151', true: '#10B981' }}
|
||||
thumbColor="#0F172A"
|
||||
ios_backgroundColor="#374151"
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.divider} />
|
||||
|
||||
{/* Biometric Login */}
|
||||
<View style={styles.menuItem}>
|
||||
<View style={styles.menuLeft}>
|
||||
<Ionicons name="lock-closed-outline" size={22} color="#38BDF8" />
|
||||
<Text style={styles.menuText}>Biometric login</Text>
|
||||
</View>
|
||||
<Switch
|
||||
|
||||
trackColor={{ false: '#374151', true: '#10B981' }}
|
||||
thumbColor="#0F172A"
|
||||
ios_backgroundColor="#374151"
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={styles.divider} />
|
||||
|
||||
{/* Offline Sync */}
|
||||
<TouchableOpacity style={styles.menuItem} activeOpacity={0.7}>
|
||||
<View style={styles.menuLeft}>
|
||||
<Ionicons name="refresh-outline" size={22} color="#34D399" />
|
||||
<Text style={styles.menuText}>Offline sync</Text>
|
||||
</View>
|
||||
<Text style={styles.menuSubtext}>Wi-Fi only</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.divider} />
|
||||
|
||||
{/* Help & Support */}
|
||||
<TouchableOpacity style={styles.menuItem} activeOpacity={0.7}>
|
||||
<View style={styles.menuLeft}>
|
||||
<Ionicons name="alert-circle-outline" size={22} color="#9CA3AF" />
|
||||
<Text style={styles.menuText}>Help & support</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward" size={18} color="#6B7280" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Sign Out Button */}
|
||||
<TouchableOpacity style={styles.signOutButton} activeOpacity={0.8}>
|
||||
<Ionicons name="log-out-outline" size={20} color="#EF4444" />
|
||||
<Text style={styles.signOutText}>Sign out</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
</ScrollView>
|
||||
</SafeAreaProvider>
|
||||
);
|
||||
}
|
||||
|
||||
164
src/styles/Airquality/airqualityScreen.ts
Normal file
164
src/styles/Airquality/airqualityScreen.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#070D18',
|
||||
},
|
||||
scrollContent: {
|
||||
paddingHorizontal: 18,
|
||||
paddingTop: 12,
|
||||
paddingBottom: 24,
|
||||
},
|
||||
/* Header */
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 20,
|
||||
},
|
||||
backButton: {
|
||||
width: 42,
|
||||
height: 42,
|
||||
borderRadius: 12,
|
||||
backgroundColor: '#152134',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: 16,
|
||||
},
|
||||
headerTitleContainer: {
|
||||
justifyContent: 'center',
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: 22,
|
||||
fontWeight: '700',
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
headerSubtitle: {
|
||||
fontSize: 13,
|
||||
color: '#64748B',
|
||||
marginTop: 2,
|
||||
},
|
||||
/* Banner Card */
|
||||
bannerCard: {
|
||||
backgroundColor: '#152134',
|
||||
borderRadius: 20,
|
||||
padding: 20,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
gaugeContainer: {
|
||||
width: 110,
|
||||
height: 110,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
gaugeTextContainer: {
|
||||
position: 'absolute',
|
||||
alignItems: 'center',
|
||||
},
|
||||
aqiValue: {
|
||||
fontSize: 32,
|
||||
fontWeight: '800',
|
||||
color: '#FFFFFF',
|
||||
lineHeight: 34,
|
||||
},
|
||||
aqiLabel: {
|
||||
fontSize: 11,
|
||||
fontWeight: '600',
|
||||
color: '#64748B',
|
||||
marginTop: 2,
|
||||
},
|
||||
bannerDetails: {
|
||||
flex: 1,
|
||||
marginLeft: 12,
|
||||
alignItems: 'flex-start',
|
||||
},
|
||||
badge: {
|
||||
backgroundColor: 'rgba(245, 158, 11, 0.15)',
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 5,
|
||||
borderRadius: 8,
|
||||
marginBottom: 10,
|
||||
},
|
||||
badgeText: {
|
||||
color: '#F59E0B',
|
||||
fontSize: 12,
|
||||
fontWeight: '700',
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
bannerDescription: {
|
||||
color: '#94A3B8',
|
||||
fontSize: 13.5,
|
||||
lineHeight: 20,
|
||||
fontWeight: '400',
|
||||
},
|
||||
/* Grid Cards */
|
||||
grid: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
gap: 12,
|
||||
marginBottom: 16,
|
||||
},
|
||||
card: {
|
||||
width: '48.2%',
|
||||
backgroundColor: '#152134',
|
||||
borderRadius: 16,
|
||||
padding: 16,
|
||||
justifyContent: 'space-between',
|
||||
height: 100,
|
||||
},
|
||||
cardTitle: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
color: '#8E9BAE',
|
||||
},
|
||||
subscript: {
|
||||
fontSize: 10,
|
||||
},
|
||||
valueRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'baseline',
|
||||
},
|
||||
cardValue: {
|
||||
fontSize: 26,
|
||||
fontWeight: '700',
|
||||
},
|
||||
cardUnit: {
|
||||
fontSize: 13,
|
||||
color: '#64748B',
|
||||
marginLeft: 6,
|
||||
fontWeight: '500',
|
||||
},
|
||||
secondaryValue: {
|
||||
fontSize: 14,
|
||||
color: '#64748B',
|
||||
fontWeight: '500',
|
||||
},
|
||||
/* Chart Card */
|
||||
chartCard: {
|
||||
backgroundColor: '#152134',
|
||||
borderRadius: 20,
|
||||
padding: 20,
|
||||
},
|
||||
chartHeader: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
chartTitle: {
|
||||
fontSize: 13,
|
||||
fontWeight: '700',
|
||||
color: '#8E9BAE',
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
chartSubtitle: {
|
||||
fontSize: 13,
|
||||
color: '#64748B',
|
||||
},
|
||||
chartContainer: {
|
||||
height: 70,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
||||
27
src/styles/Alarm/alarmScreen.ts
Normal file
27
src/styles/Alarm/alarmScreen.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
import { COLORS } from "../../constants/color";
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: COLORS.background,
|
||||
},
|
||||
listContent: {
|
||||
paddingHorizontal: 18,
|
||||
paddingBottom: 24,
|
||||
},
|
||||
header: {
|
||||
paddingTop: 16,
|
||||
paddingBottom: 16,
|
||||
},
|
||||
title: {
|
||||
color: COLORS.textPrimary,
|
||||
fontSize: 28,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
subtitle: {
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 14,
|
||||
marginTop: 4,
|
||||
},
|
||||
});
|
||||
111
src/styles/Alarm/alarmcard.ts
Normal file
111
src/styles/Alarm/alarmcard.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { COLORS } from '../../constants/color';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
card: {
|
||||
backgroundColor: COLORS.cardBg,
|
||||
borderColor: COLORS.cardBorder,
|
||||
borderWidth: 1,
|
||||
borderRadius: 16,
|
||||
marginBottom: 12,
|
||||
flexDirection: 'row',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
|
||||
statusIndicator: {
|
||||
width: 5,
|
||||
borderTopLeftRadius: 16,
|
||||
borderBottomLeftRadius: 16,
|
||||
},
|
||||
|
||||
cardContent: {
|
||||
flex: 1,
|
||||
padding: 16,
|
||||
},
|
||||
|
||||
headerRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 8,
|
||||
},
|
||||
|
||||
badge: {
|
||||
paddingHorizontal: 8,
|
||||
paddingVertical: 3,
|
||||
borderRadius: 6,
|
||||
},
|
||||
|
||||
badgeText: {
|
||||
fontSize: 11,
|
||||
fontWeight: '800',
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
|
||||
timeAgo: {
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 13,
|
||||
},
|
||||
|
||||
title: {
|
||||
color: COLORS.textPrimary,
|
||||
fontSize: 17,
|
||||
fontWeight: '700',
|
||||
marginBottom: 6,
|
||||
},
|
||||
|
||||
details: {
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 14,
|
||||
lineHeight: 20,
|
||||
},
|
||||
|
||||
actionRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: 16,
|
||||
gap: 10,
|
||||
},
|
||||
|
||||
acknowledgeButton: {
|
||||
backgroundColor: COLORS.tabActive,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 16,
|
||||
borderRadius: 10,
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
acknowledgeText: {
|
||||
color: '#000',
|
||||
fontWeight: '700',
|
||||
fontSize: 14,
|
||||
},
|
||||
|
||||
assignButton: {
|
||||
backgroundColor: '#1E2D42',
|
||||
borderColor: COLORS.cardBorder,
|
||||
borderWidth: 1,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 16,
|
||||
borderRadius: 10,
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
},
|
||||
|
||||
assignText: {
|
||||
color: COLORS.textPrimary,
|
||||
fontWeight: '600',
|
||||
fontSize: 14,
|
||||
},
|
||||
|
||||
iconButton: {
|
||||
backgroundColor: '#1E2D42',
|
||||
borderColor: COLORS.cardBorder,
|
||||
borderWidth: 1,
|
||||
padding: 10,
|
||||
borderRadius: 10,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
import { COLORS } from "../constants/color";
|
||||
import { COLORS } from "../../constants/color";
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
card: {
|
||||
25
src/styles/Asset/assetScreen.ts
Normal file
25
src/styles/Asset/assetScreen.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
import { COLORS } from "../../constants/color";
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: COLORS.background,
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 20,
|
||||
paddingTop: 16,
|
||||
},
|
||||
title: {
|
||||
color: COLORS.textPrimary,
|
||||
fontSize: 28,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
subtitle: {
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 14,
|
||||
marginTop: 4,
|
||||
marginBottom: 16,
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { COLORS } from '../constants/color';
|
||||
import { COLORS } from '../../constants/color';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { COLORS } from '../constants/color';
|
||||
import { COLORS } from '../../constants/color';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
|
||||
53
src/styles/Home/HomeScreen.ts
Normal file
53
src/styles/Home/HomeScreen.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
// HomeScreen.styles.js
|
||||
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { COLORS } from '../../constants/color';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: COLORS.background,
|
||||
},
|
||||
|
||||
scrollContent: {
|
||||
paddingHorizontal: 16,
|
||||
paddingTop: 16,
|
||||
paddingBottom: 20,
|
||||
},
|
||||
|
||||
gridRow: {
|
||||
flexDirection: 'row',
|
||||
flexGrow: 1,
|
||||
marginBottom: 8,
|
||||
gap: 10,
|
||||
},
|
||||
|
||||
card: {
|
||||
borderColor: COLORS.orange,
|
||||
marginHorizontal: 10,
|
||||
marginTop: 10,
|
||||
marginBottom: 20,
|
||||
},
|
||||
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 10,
|
||||
},
|
||||
|
||||
title: {
|
||||
color: COLORS.orange,
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
marginLeft: 8,
|
||||
},
|
||||
|
||||
message: {
|
||||
color: COLORS.textPrimary,
|
||||
fontSize: 16,
|
||||
lineHeight: 24,
|
||||
marginLeft: 20,
|
||||
},
|
||||
});
|
||||
|
||||
export default styles;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
import { COLORS } from "../constants/color";
|
||||
import { COLORS } from "../../constants/color";
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
@@ -1,5 +1,5 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { COLORS } from '../constants/color';
|
||||
import { COLORS } from '../../constants/color';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
|
||||
38
src/styles/Module/module.ts
Normal file
38
src/styles/Module/module.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { StyleSheet, Platform, StatusBar } from 'react-native';
|
||||
import { COLORS } from '../../constants/color';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: COLORS.background,
|
||||
},
|
||||
scrollContent: {
|
||||
paddingHorizontal: 16,
|
||||
// Extra top padding ensures content clears notch and status bar
|
||||
paddingTop: Platform.OS === 'android' ? (StatusBar.currentHeight || 20) + 16 : 24,
|
||||
paddingBottom: 100, // Safe distance from bottom tab bar
|
||||
},
|
||||
header: {
|
||||
marginTop: 12, // Pushes header down away from top screen edge/time
|
||||
marginBottom: 20,
|
||||
},
|
||||
title: {
|
||||
color: COLORS.textPrimary,
|
||||
fontSize: 26,
|
||||
fontWeight: '700',
|
||||
letterSpacing: 0.3,
|
||||
},
|
||||
subtitle: {
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 14,
|
||||
marginTop: 4,
|
||||
},
|
||||
gridContainer: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'flex-start',
|
||||
gap: 12,
|
||||
},
|
||||
});
|
||||
|
||||
export default styles;
|
||||
50
src/styles/Notification/notification.ts
Normal file
50
src/styles/Notification/notification.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
import { COLORS } from "../../constants/color";
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: COLORS.background,
|
||||
},
|
||||
headerRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 14,
|
||||
},
|
||||
backButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 12,
|
||||
backgroundColor: COLORS.cardBg,
|
||||
borderColor: COLORS.cardBorder,
|
||||
borderWidth: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
headerTitle: {
|
||||
color: COLORS.textPrimary,
|
||||
fontSize: 22,
|
||||
fontWeight: '700',
|
||||
flex: 1,
|
||||
marginLeft: 14,
|
||||
},
|
||||
markAllReadText: {
|
||||
color: COLORS.orange,
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
},
|
||||
listContent: {
|
||||
paddingHorizontal: 16,
|
||||
paddingBottom: 24,
|
||||
},
|
||||
sectionHeader: {
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 12,
|
||||
fontWeight: '700',
|
||||
letterSpacing: 0.8,
|
||||
marginTop: 18,
|
||||
marginBottom: 12,
|
||||
},
|
||||
});
|
||||
147
src/styles/Profile/profile.ts
Normal file
147
src/styles/Profile/profile.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import { StyleSheet } from "react-native";
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#0A111E',
|
||||
},
|
||||
scrollContent: {
|
||||
paddingHorizontal: 20,
|
||||
paddingTop: 16,
|
||||
paddingBottom: 40,
|
||||
},
|
||||
/* Header */
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 24,
|
||||
},
|
||||
backButton: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 12,
|
||||
backgroundColor: '#162235',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: 16,
|
||||
},
|
||||
headerTitle: {
|
||||
fontSize: 22,
|
||||
fontWeight: '700',
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
/* User Profile Header */
|
||||
profileContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 24,
|
||||
},
|
||||
avatar: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
borderRadius: 18,
|
||||
backgroundColor: '#D97706',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginRight: 16,
|
||||
},
|
||||
avatarText: {
|
||||
fontSize: 22,
|
||||
fontWeight: '700',
|
||||
color: '#0F172A',
|
||||
},
|
||||
userInfo: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
userName: {
|
||||
fontSize: 22,
|
||||
fontWeight: '700',
|
||||
color: '#FFFFFF',
|
||||
marginBottom: 2,
|
||||
},
|
||||
userRole: {
|
||||
fontSize: 14,
|
||||
color: '#94A3B8',
|
||||
marginBottom: 2,
|
||||
},
|
||||
userLocation: {
|
||||
fontSize: 13,
|
||||
color: '#64748B',
|
||||
},
|
||||
/* Stats Cards */
|
||||
statsRow: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
marginBottom: 24,
|
||||
gap: 12,
|
||||
},
|
||||
statCard: {
|
||||
flex: 1,
|
||||
backgroundColor: '#162235',
|
||||
borderRadius: 16,
|
||||
paddingVertical: 18,
|
||||
paddingHorizontal: 10,
|
||||
alignItems: 'center',
|
||||
},
|
||||
statValue: {
|
||||
fontSize: 24,
|
||||
fontWeight: '700',
|
||||
marginBottom: 4,
|
||||
},
|
||||
statLabel: {
|
||||
fontSize: 12,
|
||||
color: '#64748B',
|
||||
textAlign: 'center',
|
||||
},
|
||||
/* Menu Items Section */
|
||||
menuContainer: {
|
||||
backgroundColor: '#162235',
|
||||
borderRadius: 16,
|
||||
paddingVertical: 6,
|
||||
marginBottom: 24,
|
||||
},
|
||||
menuItem: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 14,
|
||||
},
|
||||
menuLeft: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 12,
|
||||
},
|
||||
menuText: {
|
||||
fontSize: 15,
|
||||
fontWeight: '500',
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
menuSubtext: {
|
||||
fontSize: 14,
|
||||
color: '#64748B',
|
||||
},
|
||||
divider: {
|
||||
height: 1,
|
||||
backgroundColor: '#1E2D4A',
|
||||
marginLeft: 48,
|
||||
},
|
||||
/* Sign Out Button */
|
||||
signOutButton: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: 'rgba(239, 68, 68, 0.1)',
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(239, 68, 68, 0.3)',
|
||||
borderRadius: 16,
|
||||
paddingVertical: 16,
|
||||
gap: 10,
|
||||
},
|
||||
signOutText: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
color: '#EF4444',
|
||||
},
|
||||
});
|
||||
@@ -2,6 +2,7 @@ export interface HeaderProps {
|
||||
userName: string;
|
||||
locationName: string;
|
||||
badgeCount?: number;
|
||||
|
||||
}
|
||||
|
||||
export interface StatCardProps {
|
||||
@@ -38,3 +39,39 @@ export interface SearchBarProps {
|
||||
export interface AssetCardProps {
|
||||
asset: Asset;
|
||||
}
|
||||
export type SeverityLevel = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW';
|
||||
|
||||
export interface AlarmItem {
|
||||
id: string;
|
||||
severity: SeverityLevel;
|
||||
title: string;
|
||||
details: string;
|
||||
timeAgo: string;
|
||||
isExpanded?: boolean;
|
||||
}
|
||||
export interface AlarmCardProps {
|
||||
alarm: AlarmItem;
|
||||
onAcknowledge?: (id: string) => void;
|
||||
onAssign?: (id: string) => void;
|
||||
onPressDetails?: (id: string) => void;
|
||||
}
|
||||
|
||||
export type NotificationType = 'CRITICAL' | 'SETPOINT' | 'AIR_QUALITY' | 'SUCCESS';
|
||||
|
||||
export interface NotificationItem {
|
||||
id: string;
|
||||
type: NotificationType;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
time: string;
|
||||
iconName: string;
|
||||
iconColor: string;
|
||||
iconBgColor: string;
|
||||
section: 'TODAY' | 'EARLIER';
|
||||
isUnread?: boolean;
|
||||
}
|
||||
|
||||
export interface NotificationCardProps {
|
||||
notification: NotificationItem;
|
||||
onPress?: (id: string) => void;
|
||||
}
|
||||
Reference in New Issue
Block a user