Green Doctor Deployer commited on
Commit
a112f73
·
1 Parent(s): b97e578

Environment: Optimize for Hugging Face Spaces and update documentation

Browse files
app.json CHANGED
@@ -4,11 +4,11 @@
4
  "slug": "GreenDoctor",
5
  "version": "1.0.0",
6
  "orientation": "portrait",
7
- "icon": "./assets/icon.png",
8
  "userInterfaceStyle": "light",
9
  "newArchEnabled": true,
10
  "splash": {
11
- "image": "./assets/splash-icon.png",
12
  "resizeMode": "contain",
13
  "backgroundColor": "#ffffff"
14
  },
@@ -17,7 +17,7 @@
17
  },
18
  "android": {
19
  "adaptiveIcon": {
20
- "foregroundImage": "./assets/adaptive-icon.png",
21
  "backgroundColor": "#ffffff"
22
  },
23
  "edgeToEdgeEnabled": true,
@@ -28,7 +28,7 @@
28
  ]
29
  },
30
  "web": {
31
- "favicon": "./assets/favicon.png"
32
  },
33
  "extra": {
34
  "eas": {
 
4
  "slug": "GreenDoctor",
5
  "version": "1.0.0",
6
  "orientation": "portrait",
7
+ "icon": "./assets/logo.png",
8
  "userInterfaceStyle": "light",
9
  "newArchEnabled": true,
10
  "splash": {
11
+ "image": "./assets/logo.png",
12
  "resizeMode": "contain",
13
  "backgroundColor": "#ffffff"
14
  },
 
17
  },
18
  "android": {
19
  "adaptiveIcon": {
20
+ "foregroundImage": "./assets/logo.png",
21
  "backgroundColor": "#ffffff"
22
  },
23
  "edgeToEdgeEnabled": true,
 
28
  ]
29
  },
30
  "web": {
31
+ "favicon": "./assets/logo.png"
32
  },
33
  "extra": {
34
  "eas": {
backend/__pycache__/__init__.cpython-312.pyc CHANGED
Binary files a/backend/__pycache__/__init__.cpython-312.pyc and b/backend/__pycache__/__init__.cpython-312.pyc differ
 
backend/__pycache__/app.cpython-312.pyc CHANGED
Binary files a/backend/__pycache__/app.cpython-312.pyc and b/backend/__pycache__/app.cpython-312.pyc differ
 
backend/app.py CHANGED
@@ -14,10 +14,12 @@ import gc
14
  import torch
15
  torch.set_num_threads(1)
16
 
17
- # Global variable for Lite Mode (Auto-detected)
18
  IS_RENDER = os.environ.get("RENDER", "false").lower() == "true"
 
 
19
 
20
- app = FastAPI(title="Green Doctor AI Vision")
21
 
22
  app.add_middleware(
23
  CORSMiddleware,
 
14
  import torch
15
  torch.set_num_threads(1)
16
 
17
+ # Environment Detection
18
  IS_RENDER = os.environ.get("RENDER", "false").lower() == "true"
19
+ IS_HF = "SPACE_ID" in os.environ
20
+ ENV_MODE = "HuggingFace" if IS_HF else ("Render" if IS_RENDER else "Local")
21
 
22
+ app = FastAPI(title=f"Green Doctor AI Vision [{ENV_MODE}]")
23
 
24
  app.add_middleware(
25
  CORSMiddleware,
backend/test_rejection.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ from PIL import Image
3
+ import io
4
+ import time
5
+
6
+ BASE_URL = "http://localhost:8000" # Test locally first
7
+
8
+ def test_rejection(color, name):
9
+ print(f"\n--- Testing {name} ({color}) ---")
10
+ img = Image.new('RGB', (224, 224), color=color)
11
+ img_byte_arr = io.BytesIO()
12
+ img.save(img_byte_arr, format='JPEG')
13
+ img_byte_arr = img_byte_arr.getvalue()
14
+
15
+ try:
16
+ response = requests.post(
17
+ f"{BASE_URL}/predict",
18
+ files={"file": ("test.jpg", img_byte_arr, "image/jpeg")}
19
+ )
20
+ if response.status_code == 200:
21
+ data = response.json()
22
+ print(f"Result: {data.get('class')}")
23
+ print(f"Details: {data.get('ai_details')}")
24
+ else:
25
+ print(f"Error: {response.status_code} - {response.text}")
26
+ except Exception as e:
27
+ print(f"Request failed: {e}")
28
+
29
+ # Color tests
30
+ # White (Non-plant)
31
+ test_rejection((255, 255, 255), "Pure White")
32
+ # Blue (Non-plant)
33
+ test_rejection((0, 0, 255), "Pure Blue")
34
+ # Bright Green (Likely Plant)
35
+ test_rejection((34, 139, 34), "Forest Green")
constants/theme.js CHANGED
@@ -1,37 +1,58 @@
1
  export const COLORS = {
2
- primary: '#2E7D32', // Deep Green (Logo)
3
- secondary: '#4CAF50', // Medium Green
4
- background: '#F5F5F5', // Light Gray Background
5
- surface: '#FFFFFF', // White Surface
6
- textPrimary: '#1B5E20', // Dark Green Text
7
- textSecondary: '#666666', // Gray Text
8
- accent: '#FF5722', // Orange/Red for alerts
 
 
 
 
 
 
 
 
 
9
  error: '#D32F2F',
 
 
10
  white: '#FFFFFF',
11
  black: '#000000',
12
- cardShadow: {
13
- shadowColor: "#000",
14
- shadowOffset: {
15
- width: 0,
16
- height: 2,
 
 
 
 
17
  },
18
- shadowOpacity: 0.1,
19
- shadowRadius: 3.84,
20
- elevation: 3,
 
 
 
 
 
 
 
 
 
 
 
21
  }
22
  };
23
 
24
- export const FONTS = {
25
- regular: 'System',
26
- bold: 'System',
27
- // In a real app we'd load custom fonts here
28
- };
29
-
30
  export const SIZES = {
31
- padding: 16,
32
- radius: 12,
33
- h1: 24,
34
- h2: 20,
35
- h3: 16,
36
- body: 14,
 
37
  };
 
1
  export const COLORS = {
2
+ // Brand Palette (HSL Derived for harmony)
3
+ primary: '#2E7D32', // Deep Forest Green
4
+ primaryLight: '#4CAF50', // Leaf Green
5
+ primaryDark: '#1B5E20', // Dark Moss
6
+ secondary: '#8BC34A', // Sprout Green
7
+
8
+ // Neutral Palette
9
+ background: '#F9FBF9', // Soft Mint-tinted White
10
+ surface: '#FFFFFF',
11
+ text: '#122613', // Almost Black Green
12
+ textLight: '#5C6B5D', // Muted Sage
13
+ border: '#E0EAE0',
14
+
15
+ // Status Palette
16
+ success: '#388E3C',
17
+ warning: '#F57C00',
18
  error: '#D32F2F',
19
+ info: '#1976D2',
20
+
21
  white: '#FFFFFF',
22
  black: '#000000',
23
+
24
+ // Premium Layered Shadows
25
+ shadow: {
26
+ sm: {
27
+ shadowColor: "#000",
28
+ shadowOffset: { width: 0, height: 1 },
29
+ shadowOpacity: 0.1,
30
+ shadowRadius: 2,
31
+ elevation: 2,
32
  },
33
+ md: {
34
+ shadowColor: "#1B5E20",
35
+ shadowOffset: { width: 0, height: 4 },
36
+ shadowOpacity: 0.08,
37
+ shadowRadius: 8,
38
+ elevation: 4,
39
+ },
40
+ lg: {
41
+ shadowColor: "#1B5E20",
42
+ shadowOffset: { width: 0, height: 10 },
43
+ shadowOpacity: 0.12,
44
+ shadowRadius: 20,
45
+ elevation: 8,
46
+ }
47
  }
48
  };
49
 
 
 
 
 
 
 
50
  export const SIZES = {
51
+ padding: 20,
52
+ radius: 20, // Larger radius for modern look
53
+ radiusSm: 12,
54
+ h1: 28,
55
+ h2: 24,
56
+ h3: 18,
57
+ body: 16,
58
  };
constants/translations.js CHANGED
@@ -47,6 +47,11 @@ export const TRANSLATIONS = {
47
  missionPoint3: "To promote sustainable agriculture practices in Puduvayal and beyond.",
48
  changeLanguage: "Change Language",
49
  aboutApp: "About App",
 
 
 
 
 
50
  govtSchemes: "Government Schemes",
51
  viewSchemes: "View available schemes",
52
  centralSchemes: "Central Schemes",
@@ -54,6 +59,25 @@ export const TRANSLATIONS = {
54
  otherSchemes: "Other Schemes",
55
  schemeDetails: "Scheme Details",
56
  noSchemesAvailable: "No schemes available at the moment",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  ourTeam: "OUR TEAM",
58
  principal: "Principal: Dr. K. Baskaran, Principal, ACGCET",
59
  principalInvestigator: "Principal Investigator (PI): Dr. S. Nageswari, ASP/EEE",
@@ -99,28 +123,25 @@ export const TRANSLATIONS = {
99
  noHistory: "வரலாறு இல்லை",
100
  confirmDelete: "நிச்சயமாக இதை நீக்க விரும்புகிறீர்களா?",
101
  cancel: "ரத்து செய்",
102
- // Unknown state labels
103
- unknownStatus: "சிக்கல் வி்கள்",
104
- unknownInstruction: "விமுறை்",
105
- unknownAdvice: "நிபுணர் ஆலோசனை",
106
- unknownNextSteps: "டுத்த கங்கள்",
107
- aboutTitle: "ப்றி",
108
- aboutContent: "ிரீனடாக்டர் என்பத புதுவயல் மற்றும் அதை ுற்றிுள்ள குதிகளிலஉள்ள விவசாயிகளுக்குத் தங்கள் ிகளை இலை நோய்களிலிருந்து ாதுகாகக உதவம் கையில் வடிவமைக்கப்பட்ட ஒரு புதுமையானொபைல செயலியாகும. இந் ிட்டம் உன்னத் த் அபியன் (UBA) - நிலையான விவசாய ுறை SEG இன் ீழ் பெருமையுடனஸ்ான் ெய்யப்படுகிறது, மேலும் ாரைக்குடி அழப்ப செட்டியார் அரச பொியியல் மற்றும் தொழில்நுட்பக் ல்லூரி மாணர்கள் மற்றும் ஆசிரியர்களால் ரு்கப்பட்டது.",
109
- visionTitle: "தொலைநோக்கு",
110
- visionContent: "விவசாயிகளுககுணுகக்கூடிய தொழில்நுட்பத்தின் மூலம் திகாரம அளிப்பதே உறதி. இது விாய உற்ப்தித்திறனை மேம்படுத்துிறது, பயிர இழப்பை் கறைக்கிறது றும் நிையான விவாய நடைமுறைகளை ஊககுவிக்கிறது. நவீன AI தீர்வுகுககும் பாரம்பரிய விவசாய சமூகங்களுக்கும் இடைிலான இடைவெளியைக் குறைக்க ாங்க இல்க வைத்துள்ளோம்.",
111
- missionTitle: "குிக்கள்",
112
- missionPoint1: "AI-���ல் இயங்கும்ர்வுகளமூலம நிநேர மற்றும் நம்பமான இல நோய் கண்டிதல வழங்குதல்.",
113
- missionPoint2: "உள்ளூர் விவசாயிகளுக்கு ஏற்ற நடைமுறை, சூழல் நட்பு தீர்வுகளை பரிந்துரைத்தல்.",
114
- missionPoint3: "புதுவயல் மற்றும் அதற்கு அப்பால் நிலையான விவசாய நடைமுறைகளை ஊக்குவித்தல்.",
115
- changeLanguage: "மொழியை மாற்றவும்",
116
- aboutApp: "செயலி பற்றி",
117
- govtSchemes: "அரசு திட்டங்கள்",
118
- viewSchemes: "கிடைக்கக்கூடிய திட்டங்களைக் காண்க",
119
- centralSchemes: "மத்திய திட்டங்கள்",
120
- stateSchemes: "மாநில திட்டங்கள்",
121
- otherSchemes: "பிற திட்டங்கள்",
122
- schemeDetails: "திட்ட விவரங்கள்",
123
- noSchemesAvailable: "தற்போது எந்த திட்டங்களும் இல்லை",
124
  ourTeam: "எங்கள் குழு",
125
  principal: "முதல்வர்: Dr. K. பாஸ்கரன், முதல்வர், ACGCET",
126
  principalInvestigator: "முதன்மை ஆய்வாளர் (PI): Dr. S. நாகேஸ்வரி, ASP/EEE",
 
47
  missionPoint3: "To promote sustainable agriculture practices in Puduvayal and beyond.",
48
  changeLanguage: "Change Language",
49
  aboutApp: "About App",
50
+ analyseNow: "Analyse Now",
51
+ autoScan: "AUTO SCAN",
52
+ manualCapture: "MANUAL",
53
+ scanning: "Scanning...",
54
+ holdSteady: "Hold steady...",
55
  govtSchemes: "Government Schemes",
56
  viewSchemes: "View available schemes",
57
  centralSchemes: "Central Schemes",
 
59
  otherSchemes: "Other Schemes",
60
  schemeDetails: "Scheme Details",
61
  noSchemesAvailable: "No schemes available at the moment",
62
+ clearHistory: "Clear History",
63
+ confirmClearAll: "Are you sure you want to delete ALL your scan history? This cannot be undone.",
64
+ applyOnline: "Apply Online",
65
+ dailyTips: [
66
+ "Water your plants early in the morning to prevent fungal growth and ensure better absorption.",
67
+ "Use neem oil as a natural pesticide to protect your crops without harmful chemicals.",
68
+ "Rotating your crops helps maintain soil fertility and breaks the cycle of pests and diseases.",
69
+ "Ensuring proper spacing between plants improves air circulation and reduces moisture-built diseases.",
70
+ "Regularly inspect the underside of leaves; many pests hide there before causing visible damage.",
71
+ "Adding organic compost to your soil provides essential nutrients and improves its texture.",
72
+ "Mulching your soil helps retain moisture and suppresses weed growth effectively."
73
+ ],
74
+ schemeLinks: {
75
+ s1: "https://pmkisan.gov.in/",
76
+ s2: "https://pmfby.gov.in/",
77
+ s3: "https://www.india.gov.in/spotlight/kisan-credit-card-kcc",
78
+ s4: "https://soilhealth.dac.gov.in/",
79
+ s5: "https://pmksy.gov.in/"
80
+ },
81
  ourTeam: "OUR TEAM",
82
  principal: "Principal: Dr. K. Baskaran, Principal, ACGCET",
83
  principalInvestigator: "Principal Investigator (PI): Dr. S. Nageswari, ASP/EEE",
 
123
  noHistory: "வரலாறு இல்லை",
124
  confirmDelete: "நிச்சயமாக இதை நீக்க விரும்புகிறீர்களா?",
125
  cancel: "ரத்து செய்",
126
+ clearHistory: "வரலாற்றை அழி",
127
+ confirmClearAll: "உங் அனைத்து ஸ்ேன் வராறறையும் நீக்க விருமபுிறீர்கா? இதை மாறற முடியாது.",
128
+ applyOnline: "ஆன்லைனில் விண்ணப்பிக்கவும்",
129
+ dailyTips: [
130
+ "பூஞ்சை வளர்ச்சியைத் தடுக்கவும் சிறந் உறிஞசுலை உறுதி செய்யவும் ாலையிலங்கள் தாவரங்களுக்கு நீர் ஊற்றவும்.",
131
+ "வேப்ப எண்ணெயை இய்கை பூச்சிக்கொல்லியாகப் பயன்படுத்துவதன் மூலம் பயிர்களைப் பாதுகாக்கலாம்.",
132
+ "பயிர் ற்சி ுறப் பி்புவது மிவளத்த பராமரிக்கும் பச்சிகைக் குறக்கவும் உிறது.",
133
+ "செடிகளுக்கு இடையே போிய இடவெளி விடுவது காற்றோட்டத்தை மேம்படுத்தி நோய்ளைக குறைக்கிறது.",
134
+ "இலைகளின் அடியில் அப்பது பரிசதிக்கும்; பூச்ிகள் ங்க றைந்திருக்கும்.",
135
+ "மண்ணில் இயற்ை உரங்களைச் சேர்ப்பத அத்தியாவசிய ஊட்டச்சத்துக்களை வழஙகுகிறது.",
136
+ "மண்ணில் மூடாக்கு (Mulching) இடுவு ஈபதததை தக்கவைககவும் ககளைக் கறை்க உதவுகிறது."
137
+ ],
138
+ schemeLinks: {
139
+ s1: "https://pmkisan.gov.in/",
140
+ s2: "https://pmfby.gov.in/",
141
+ s3: "https://www.india.gov.in/spotlight/kisan-credit-card-kcc",
142
+ s4: "https://soilhealth.dac.gov.in/",
143
+ s5: "https://pmksy.gov.in/"
144
+ },
 
 
 
145
  ourTeam: "எங்கள் குழு",
146
  principal: "முதல்வர்: Dr. K. பாஸ்கரன், முதல்வர், ACGCET",
147
  principalInvestigator: "முதன்மை ஆய்வாளர் (PI): Dr. S. நாகேஸ்வரி, ASP/EEE",
screens/AboutScreen.js CHANGED
@@ -1,6 +1,6 @@
1
  import React from 'react';
2
  import { StyleSheet, Text, View, Image, ScrollView, TouchableOpacity, SafeAreaView, StatusBar, Dimensions } from 'react-native';
3
- import { COLORS, SIZES } from '../constants/theme';
4
  import { TRANSLATIONS } from '../constants/translations';
5
 
6
  const { width } = Dimensions.get('window');
@@ -9,6 +9,19 @@ const AboutScreen = ({ route, navigation }) => {
9
  const language = route.params?.language || 'en';
10
  const t = TRANSLATIONS[language] || TRANSLATIONS['en'];
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  return (
13
  <SafeAreaView style={styles.container}>
14
  <StatusBar backgroundColor={COLORS.white} barStyle="dark-content" />
@@ -24,106 +37,85 @@ const AboutScreen = ({ route, navigation }) => {
24
 
25
  <ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
26
 
27
- {/* 1. Logos Section */}
28
- <View style={styles.logoRow}>
29
- <View style={styles.sideLogoContainer}>
30
- <Image
31
- source={require('../assets/uba_logo.png')}
32
- style={styles.sideLogo}
33
- resizeMode="contain"
34
- />
35
- </View>
36
-
37
- <View style={styles.mainLogoContainer}>
38
- <Image
39
- source={require('../assets/logo.png')}
40
- style={styles.mainLogo}
41
- resizeMode="contain"
42
- />
43
- </View>
44
-
45
- <View style={styles.sideLogoContainer}>
46
- <Image
47
- source={require('../assets/act_logo.png')}
48
- style={styles.sideLogo}
49
- resizeMode="contain"
50
- />
51
  </View>
 
52
  </View>
53
 
54
- {/* 2. Title */}
55
- <Text style={styles.pageHeaderTitle}>{t.aboutTitle}</Text>
 
 
 
 
56
 
57
- {/* 3. About Text */}
58
- <Text style={styles.bodyText}>
59
- {t.aboutContent}
60
- </Text>
 
61
 
62
- {/* 4. Vision & Mission */}
63
- <View style={styles.sectionContainer}>
64
- <View style={styles.sectionHeader}>
65
- <Text style={styles.sectionIcon}>👁️</Text>
66
- <Text style={styles.sectionTitle}>{t.visionTitle}</Text>
67
- </View>
68
- <Text style={styles.bodyText}>
69
- {t.visionContent}
70
- </Text>
71
- </View>
72
-
73
- <View style={styles.sectionContainer}>
74
- <View style={styles.sectionHeader}>
75
- <Text style={styles.sectionIcon}>🎯</Text>
76
- <Text style={styles.sectionTitle}>{t.missionTitle}</Text>
77
- </View>
78
  <View style={styles.bulletList}>
79
- <View style={styles.bulletItem}>
80
- <Text style={styles.bullet}>•</Text>
81
- <Text style={styles.bodyText}>{t.missionPoint1}</Text>
82
- </View>
83
- <View style={styles.bulletItem}>
84
- <Text style={styles.bullet}>•</Text>
85
- <Text style={styles.bodyText}>{t.missionPoint2}</Text>
86
- </View>
87
- <View style={styles.bulletItem}>
88
- <Text style={styles.bullet}>•</Text>
89
- <Text style={styles.bodyText}>{t.missionPoint3}</Text>
90
- </View>
91
  </View>
92
- </View>
93
 
94
- {/* 5. Our Team Section */}
95
- <View style={styles.teamContainer}>
96
- <View style={styles.sectionHeader}>
97
- <Text style={styles.sectionIcon}>👥</Text>
98
- <Text style={styles.sectionTitle}>{t.ourTeam}</Text>
 
 
99
  </View>
100
 
101
- <View style={styles.teamMember}>
102
- <Text style={styles.roleLabel}>{t.principal.split(':')[0]}:</Text>
103
- <Text style={styles.memberName}>{t.principal.split(':')[1]}</Text>
104
- </View>
 
105
 
106
- <View style={styles.teamMember}>
107
- <Text style={styles.roleLabel}>{t.principalInvestigator.split(':')[0]}:</Text>
108
- <Text style={styles.memberName}>{t.principalInvestigator.split(':')[1]}</Text>
109
- </View>
110
 
111
- <View style={styles.teamMember}>
112
- <Text style={styles.roleLabel}>{t.coPi.split(':')[0]}:</Text>
113
- <Text style={styles.memberName}>{t.coPi.split(':')[1]}</Text>
114
- </View>
115
 
116
- <View style={styles.teamMember}>
117
- <Text style={styles.roleLabel}>{t.studentInnovators}</Text>
118
- <View style={styles.studentList}>
119
- {t.studentsList && t.studentsList.map((student, index) => (
120
- <Text key={index} style={styles.studentName}>• {student}</Text>
121
- ))}
 
 
 
122
  </View>
123
  </View>
124
  </View>
125
 
126
- <View style={{ height: 60 }} />
127
  </ScrollView>
128
  </SafeAreaView>
129
  );
@@ -132,143 +124,179 @@ const AboutScreen = ({ route, navigation }) => {
132
  const styles = StyleSheet.create({
133
  container: {
134
  flex: 1,
135
- backgroundColor: COLORS.white, // Clean white background
136
  },
137
  header: {
138
  flexDirection: 'row',
139
  alignItems: 'center',
140
  justifyContent: 'space-between',
141
- paddingHorizontal: 20,
142
- paddingVertical: 15,
143
- backgroundColor: COLORS.white,
 
144
  },
145
  backButton: {
146
- padding: 5,
147
  },
148
  backButtonText: {
149
- fontSize: 28,
150
- color: '#333',
151
- fontWeight: '300', // Lighter weight for modern feel
152
  },
153
  headerTitle: {
154
- fontSize: 16,
155
- fontWeight: '600',
156
- color: '#333',
157
- letterSpacing: 1,
158
- textTransform: 'uppercase',
159
  },
160
  scrollContent: {
161
- paddingHorizontal: 24,
162
- paddingTop: 10,
163
  },
164
- logoRow: {
165
- flexDirection: 'row',
166
  alignItems: 'center',
167
- justifyContent: 'space-between',
168
  marginBottom: 30,
169
- marginTop: 10,
170
  },
171
- sideLogoContainer: {
172
- width: 70,
173
- height: 70,
174
- justifyContent: 'center',
175
  alignItems: 'center',
176
- // Optional: Add shadow or elevation for logos if needed, currently kept flat
177
- },
178
- sideLogo: {
179
- width: '100%',
180
- height: '100%',
181
  },
182
- mainLogoContainer: {
183
- width: 100,
184
- height: 100,
 
 
185
  justifyContent: 'center',
186
  alignItems: 'center',
 
 
 
 
 
 
 
 
 
 
 
 
187
  },
188
  mainLogo: {
189
- width: '100%',
190
- height: '100%',
191
  },
192
- pageHeaderTitle: {
193
- fontSize: 24,
194
- fontWeight: '800', // Heavy bold
195
- color: '#1B5E20', // Dark Green
196
- textAlign: 'center',
197
- marginBottom: 20,
198
- letterSpacing: 0.5,
199
- textTransform: 'uppercase',
200
  },
201
- bodyText: {
202
- fontSize: 15,
203
- lineHeight: 24,
204
- color: '#444', // Dark gray for better readability than pure black
205
- textAlign: 'justify',
206
- marginBottom: 20,
207
- fontWeight: '400',
208
  },
209
- sectionContainer: {
 
 
 
210
  marginBottom: 20,
 
 
 
 
 
211
  },
212
- sectionHeader: {
213
  flexDirection: 'row',
214
  alignItems: 'center',
215
- marginBottom: 10,
216
  },
217
- sectionIcon: {
 
 
 
 
 
 
 
 
 
218
  fontSize: 20,
219
- marginRight: 10,
220
- color: '#2E7D32',
221
  },
222
- sectionTitle: {
223
- fontSize: 18,
224
- fontWeight: '700',
225
- color: '#222',
226
- letterSpacing: 0.5,
227
- textTransform: 'uppercase',
 
 
 
 
228
  },
229
  bulletList: {
230
  marginTop: 5,
231
  },
232
  bulletItem: {
233
  flexDirection: 'row',
 
234
  marginBottom: 8,
235
- alignItems: 'flex-start',
236
  },
237
- bullet: {
238
- fontSize: 18,
 
 
 
239
  marginRight: 10,
240
- color: '#2E7D32',
241
- lineHeight: 24,
242
  },
243
- teamContainer: {
244
- marginTop: 10,
245
- paddingTop: 20,
246
- borderTopWidth: 1,
247
- borderTopColor: '#eee',
 
 
 
 
248
  },
249
  teamMember: {
250
- marginBottom: 15,
 
 
251
  },
252
  roleLabel: {
253
- fontSize: 14,
254
- fontWeight: '700',
255
- color: '#1B5E20',
256
  marginBottom: 2,
257
  },
258
  memberName: {
259
  fontSize: 15,
260
- fontWeight: '400',
261
- color: '#333',
262
  },
263
- studentList: {
264
  marginTop: 5,
265
- paddingLeft: 10,
266
  },
267
- studentName: {
268
- fontSize: 14,
269
- color: '#555',
270
- marginBottom: 2,
271
- lineHeight: 20,
 
 
 
 
 
 
 
 
 
 
 
 
 
272
  }
273
  });
274
 
 
1
  import React from 'react';
2
  import { StyleSheet, Text, View, Image, ScrollView, TouchableOpacity, SafeAreaView, StatusBar, Dimensions } from 'react-native';
3
+ import { COLORS, SIZES, FONTS } from '../constants/theme';
4
  import { TRANSLATIONS } from '../constants/translations';
5
 
6
  const { width } = Dimensions.get('window');
 
9
  const language = route.params?.language || 'en';
10
  const t = TRANSLATIONS[language] || TRANSLATIONS['en'];
11
 
12
+ const InfoCard = ({ icon, title, content, children }) => (
13
+ <View style={styles.card}>
14
+ <View style={styles.cardHeader}>
15
+ <View style={styles.cardIconCircle}>
16
+ <Text style={styles.cardIcon}>{icon}</Text>
17
+ </View>
18
+ <Text style={styles.cardTitle}>{title}</Text>
19
+ </View>
20
+ {content ? <Text style={styles.cardBody}>{content}</Text> : null}
21
+ {children}
22
+ </View>
23
+ );
24
+
25
  return (
26
  <SafeAreaView style={styles.container}>
27
  <StatusBar backgroundColor={COLORS.white} barStyle="dark-content" />
 
37
 
38
  <ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
39
 
40
+ {/* 1. Logos Section - Grouped Header */}
41
+ <View style={styles.brandHeader}>
42
+ <View style={styles.logoGrid}>
43
+ <View style={styles.brandBox}>
44
+ <Image source={require('../assets/uba_logo.png')} style={styles.sideLogo} resizeMode="contain" />
45
+ </View>
46
+ <View style={[styles.brandBox, styles.mainBrandBox]}>
47
+ <Image source={require('../assets/logo.png')} style={styles.mainLogo} resizeMode="contain" />
48
+ </View>
49
+ <View style={styles.brandBox}>
50
+ <Image source={require('../assets/act_logo.png')} style={styles.sideLogo} resizeMode="contain" />
51
+ </View>
 
 
 
 
 
 
 
 
 
 
 
 
52
  </View>
53
+ <Text style={styles.pageHeaderTitle}>{t.aboutTitle}</Text>
54
  </View>
55
 
56
+ {/* 2. Content Cards */}
57
+ <InfoCard
58
+ icon="🌱"
59
+ title={t.aboutApp}
60
+ content={t.aboutContent}
61
+ />
62
 
63
+ <InfoCard
64
+ icon="👁️"
65
+ title={t.visionTitle}
66
+ content={t.visionContent}
67
+ />
68
 
69
+ <InfoCard icon="🎯" title={t.missionTitle}>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  <View style={styles.bulletList}>
71
+ {[t.missionPoint1, t.missionPoint2, t.missionPoint3].map((point, i) => (
72
+ <View key={i} style={styles.bulletItem}>
73
+ <View style={styles.bulletPoint} />
74
+ <Text style={styles.bulletText}>{point}</Text>
75
+ </View>
76
+ ))}
 
 
 
 
 
 
77
  </View>
78
+ </InfoCard>
79
 
80
+ {/* 3. Team Card */}
81
+ <View style={[styles.card, styles.teamCard]}>
82
+ <View style={styles.cardHeader}>
83
+ <View style={[styles.cardIconCircle, { backgroundColor: '#E3F2FD' }]}>
84
+ <Text style={styles.cardIcon}>👥</Text>
85
+ </View>
86
+ <Text style={styles.cardTitle}>{t.ourTeam}</Text>
87
  </View>
88
 
89
+ <View style={styles.teamGrid}>
90
+ <View style={styles.teamMember}>
91
+ <Text style={styles.roleLabel}>{t.principal?.split(':')[0] || 'Principal'}</Text>
92
+ <Text style={styles.memberName}>{t.principal?.split(':')[1] || ''}</Text>
93
+ </View>
94
 
95
+ <View style={styles.teamMember}>
96
+ <Text style={styles.roleLabel}>{t.principalInvestigator?.split(':')[0] || 'PI'}</Text>
97
+ <Text style={styles.memberName}>{t.principalInvestigator?.split(':')[1] || ''}</Text>
98
+ </View>
99
 
100
+ <View style={styles.teamMember}>
101
+ <Text style={styles.roleLabel}>{t.coPi?.split(':')[0] || 'Co-PI'}</Text>
102
+ <Text style={styles.memberName}>{t.coPi?.split(':')[1] || ''}</Text>
103
+ </View>
104
 
105
+ <View style={styles.studentSection}>
106
+ <Text style={styles.roleLabel}>{t.studentInnovators}</Text>
107
+ <View style={styles.studentChips}>
108
+ {t.studentsList?.map((student, i) => (
109
+ <View key={i} style={styles.chip}>
110
+ <Text style={styles.chipText}>{student}</Text>
111
+ </View>
112
+ ))}
113
+ </View>
114
  </View>
115
  </View>
116
  </View>
117
 
118
+ <View style={{ height: 40 }} />
119
  </ScrollView>
120
  </SafeAreaView>
121
  );
 
124
  const styles = StyleSheet.create({
125
  container: {
126
  flex: 1,
127
+ backgroundColor: '#F8F9FA',
128
  },
129
  header: {
130
  flexDirection: 'row',
131
  alignItems: 'center',
132
  justifyContent: 'space-between',
133
+ paddingHorizontal: 15,
134
+ paddingTop: 10,
135
+ height: 60,
136
+ backgroundColor: '#fff',
137
  },
138
  backButton: {
139
+ padding: 10,
140
  },
141
  backButtonText: {
142
+ fontSize: 24,
143
+ color: COLORS.primary,
144
+ fontWeight: 'bold',
145
  },
146
  headerTitle: {
147
+ fontSize: 18,
148
+ fontWeight: 'bold',
149
+ color: COLORS.primary,
 
 
150
  },
151
  scrollContent: {
152
+ padding: 20,
 
153
  },
154
+ brandHeader: {
 
155
  alignItems: 'center',
 
156
  marginBottom: 30,
 
157
  },
158
+ logoGrid: {
159
+ flexDirection: 'row',
 
 
160
  alignItems: 'center',
161
+ justifyContent: 'center',
162
+ gap: 15,
163
+ marginBottom: 15,
 
 
164
  },
165
+ brandBox: {
166
+ width: 60,
167
+ height: 60,
168
+ backgroundColor: '#fff',
169
+ borderRadius: 12,
170
  justifyContent: 'center',
171
  alignItems: 'center',
172
+ elevation: 2,
173
+ shadowColor: '#000',
174
+ shadowOffset: { width: 0, height: 2 },
175
+ shadowOpacity: 0.1,
176
+ shadowRadius: 4,
177
+ },
178
+ mainBrandBox: {
179
+ width: 80,
180
+ height: 80,
181
+ borderRadius: 20,
182
+ borderWidth: 1,
183
+ borderColor: COLORS.primary + '30',
184
  },
185
  mainLogo: {
186
+ width: '80%',
187
+ height: '80%',
188
  },
189
+ sideLogo: {
190
+ width: '70%',
191
+ height: '70%',
 
 
 
 
 
192
  },
193
+ pageHeaderTitle: {
194
+ fontSize: 22,
195
+ fontWeight: 'bold',
196
+ color: COLORS.primary,
197
+ letterSpacing: 1,
 
 
198
  },
199
+ card: {
200
+ backgroundColor: '#fff',
201
+ borderRadius: 20,
202
+ padding: 20,
203
  marginBottom: 20,
204
+ elevation: 3,
205
+ shadowColor: '#000',
206
+ shadowOffset: { width: 0, height: 2 },
207
+ shadowOpacity: 0.1,
208
+ shadowRadius: 8,
209
  },
210
+ cardHeader: {
211
  flexDirection: 'row',
212
  alignItems: 'center',
213
+ marginBottom: 15,
214
  },
215
+ cardIconCircle: {
216
+ width: 40,
217
+ height: 40,
218
+ borderRadius: 20,
219
+ backgroundColor: '#F1F8E9',
220
+ justifyContent: 'center',
221
+ alignItems: 'center',
222
+ marginRight: 12,
223
+ },
224
+ cardIcon: {
225
  fontSize: 20,
 
 
226
  },
227
+ cardTitle: {
228
+ fontSize: 16,
229
+ fontWeight: 'bold',
230
+ color: COLORS.primary,
231
+ },
232
+ cardBody: {
233
+ fontSize: 14,
234
+ lineHeight: 22,
235
+ color: '#444',
236
+ textAlign: 'justify',
237
  },
238
  bulletList: {
239
  marginTop: 5,
240
  },
241
  bulletItem: {
242
  flexDirection: 'row',
243
+ alignItems: 'center',
244
  marginBottom: 8,
 
245
  },
246
+ bulletPoint: {
247
+ width: 6,
248
+ height: 6,
249
+ borderRadius: 3,
250
+ backgroundColor: COLORS.primary,
251
  marginRight: 10,
 
 
252
  },
253
+ bulletText: {
254
+ fontSize: 14,
255
+ color: '#444',
256
+ },
257
+ teamCard: {
258
+ backgroundColor: '#fff',
259
+ },
260
+ teamGrid: {
261
+ gap: 15,
262
  },
263
  teamMember: {
264
+ paddingBottom: 10,
265
+ borderBottomWidth: 1,
266
+ borderBottomColor: '#f0f0f0',
267
  },
268
  roleLabel: {
269
+ fontSize: 12,
270
+ color: COLORS.gray,
271
+ fontWeight: 'bold',
272
  marginBottom: 2,
273
  },
274
  memberName: {
275
  fontSize: 15,
276
+ color: COLORS.text,
277
+ fontWeight: '600',
278
  },
279
+ studentSection: {
280
  marginTop: 5,
 
281
  },
282
+ studentChips: {
283
+ flexDirection: 'row',
284
+ flexWrap: 'wrap',
285
+ gap: 8,
286
+ marginTop: 10,
287
+ },
288
+ chip: {
289
+ backgroundColor: '#F5F5F5',
290
+ paddingHorizontal: 12,
291
+ paddingVertical: 6,
292
+ borderRadius: 15,
293
+ borderWidth: 1,
294
+ borderColor: '#E0E0E0',
295
+ },
296
+ chipText: {
297
+ fontSize: 13,
298
+ color: '#666',
299
+ fontWeight: '500',
300
  }
301
  });
302
 
screens/HistoryScreen.js CHANGED
@@ -23,12 +23,12 @@ const HistoryScreen = ({ navigation, route }) => {
23
 
24
  const handleDelete = async (item) => {
25
  Alert.alert(
26
- t.delete,
27
- t.confirmDelete,
28
  [
29
  { text: t.cancel, style: "cancel" },
30
  {
31
- text: t.delete,
32
  style: "destructive",
33
  onPress: async () => {
34
  await deleteScan(item.timestamp);
@@ -47,18 +47,24 @@ const HistoryScreen = ({ navigation, route }) => {
47
  analysisResult: item.analysisResult,
48
  language: language
49
  })}
 
50
  >
51
- <Image source={{ uri: item.imageUri }} style={styles.thumbnail} />
 
 
 
 
 
52
  <View style={styles.cardContent}>
53
- <Text style={styles.cropName}>{item.analysisResult.crop}</Text>
54
  <Text style={styles.diseaseName}>{item.analysisResult.name[language]}</Text>
55
- <Text style={styles.date}>{new Date(item.timestamp).toLocaleDateString()}</Text>
56
  </View>
57
  <TouchableOpacity
58
- style={styles.deleteButton}
59
  onPress={() => handleDelete(item)}
60
  >
61
- <Text style={styles.deleteText}>🗑️</Text>
62
  </TouchableOpacity>
63
  </TouchableOpacity>
64
  );
@@ -66,16 +72,36 @@ const HistoryScreen = ({ navigation, route }) => {
66
  return (
67
  <View style={styles.container}>
68
  <View style={styles.header}>
69
- <TouchableOpacity onPress={() => navigation.goBack()} style={styles.backButton}>
70
- <Text style={styles.backButtonText}>←</Text>
71
- </TouchableOpacity>
72
- <Text style={styles.headerTitle}>{t.history}</Text>
 
 
 
 
73
  {history.length > 0 && (
74
- <TouchableOpacity onPress={async () => {
75
- await clearHistory();
76
- loadHistory();
77
- }}>
78
- <Text style={styles.clearText}>Clear</Text>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  </TouchableOpacity>
80
  )}
81
  </View>
@@ -83,11 +109,13 @@ const HistoryScreen = ({ navigation, route }) => {
83
  <FlatList
84
  data={history}
85
  renderItem={renderItem}
86
- keyExtractor={(item) => item.id}
87
- contentContainerStyle={styles.list}
88
  ListEmptyComponent={
89
- <View style={styles.emptyContainer}>
90
- <Text style={styles.emptyText}>{t.noHistory}</Text>
 
 
91
  </View>
92
  }
93
  />
@@ -101,87 +129,152 @@ const styles = StyleSheet.create({
101
  backgroundColor: COLORS.background,
102
  },
103
  header: {
 
 
 
 
 
 
 
 
 
 
104
  flexDirection: 'row',
105
  alignItems: 'center',
106
  justifyContent: 'space-between',
107
- paddingTop: 50,
108
- paddingBottom: 20,
109
- paddingHorizontal: 20,
110
- backgroundColor: COLORS.primary,
111
- borderBottomLeftRadius: 30,
112
- borderBottomRightRadius: 30,
113
  },
114
- backButton: {
115
- padding: 5,
 
 
 
 
 
116
  },
117
- backButtonText: {
118
  fontSize: 24,
119
- color: '#fff',
 
120
  },
121
  headerTitle: {
122
  fontSize: 20,
123
- fontWeight: 'bold',
124
- color: '#fff',
 
125
  },
126
- clearText: {
127
- color: '#fff',
128
- fontSize: 14,
 
 
 
 
 
 
 
 
 
 
129
  },
130
- list: {
131
- padding: 20,
132
  },
133
  card: {
134
  flexDirection: 'row',
135
- backgroundColor: '#fff',
136
- borderRadius: 15,
137
  marginBottom: 15,
138
- padding: 10,
139
- elevation: 3,
140
- shadowColor: '#000',
141
- shadowOffset: { width: 0, height: 2 },
142
- shadowOpacity: 0.1,
143
- shadowRadius: 4,
 
 
144
  },
145
  thumbnail: {
146
- width: 70,
147
- height: 70,
148
- borderRadius: 10,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  },
150
  cardContent: {
151
  flex: 1,
152
  marginLeft: 15,
153
- justifyContent: 'center',
154
  },
155
  cropName: {
156
- fontSize: 12,
157
- color: COLORS.gray,
158
- fontWeight: 'bold',
 
 
159
  },
160
  diseaseName: {
161
- fontSize: 16,
162
- fontWeight: 'bold',
163
  color: COLORS.text,
164
- marginBottom: 5,
165
  },
166
- date: {
167
  fontSize: 12,
168
- color: COLORS.gray,
 
169
  },
170
- deleteButton: {
 
 
 
 
171
  justifyContent: 'center',
172
- paddingHorizontal: 10,
173
  },
174
- deleteText: {
175
- fontSize: 20,
 
176
  },
177
- emptyContainer: {
178
  flex: 1,
179
- paddingTop: 100,
180
  alignItems: 'center',
 
181
  },
182
- emptyText: {
183
- fontSize: 16,
184
- color: COLORS.gray,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
186
  });
187
 
 
23
 
24
  const handleDelete = async (item) => {
25
  Alert.alert(
26
+ language === 'ta' ? "ஸ்கேனை நீக்கவா?" : "Delete Scan?",
27
+ language === 'ta' ? "நிச்சயமாக இதை நீக்க விரும்புகிறீர்களா?" : "Are you sure you want to remove this from your history?",
28
  [
29
  { text: t.cancel, style: "cancel" },
30
  {
31
+ text: language === 'ta' ? "நீக்கு" : "Delete",
32
  style: "destructive",
33
  onPress: async () => {
34
  await deleteScan(item.timestamp);
 
47
  analysisResult: item.analysisResult,
48
  language: language
49
  })}
50
+ activeOpacity={0.7}
51
  >
52
+ <View style={styles.thumbnailContainer}>
53
+ <Image source={{ uri: item.imageUri }} style={styles.thumbnail} />
54
+ <View style={styles.statusDotOverlay}>
55
+ <View style={[styles.miniDot, { backgroundColor: item.analysisResult.isHealthy ? COLORS.success : COLORS.error }]} />
56
+ </View>
57
+ </View>
58
  <View style={styles.cardContent}>
59
+ <Text style={styles.cropName}>{item.analysisResult.crop.toUpperCase()}</Text>
60
  <Text style={styles.diseaseName}>{item.analysisResult.name[language]}</Text>
61
+ <Text style={styles.dateText}>{new Date(item.timestamp).toLocaleDateString(undefined, { month: 'short', day: 'numeric', year: 'numeric' })}</Text>
62
  </View>
63
  <TouchableOpacity
64
+ style={styles.deleteIconButton}
65
  onPress={() => handleDelete(item)}
66
  >
67
+ <Text style={styles.trashIcon}>🗑️</Text>
68
  </TouchableOpacity>
69
  </TouchableOpacity>
70
  );
 
72
  return (
73
  <View style={styles.container}>
74
  <View style={styles.header}>
75
+ <View style={styles.headerTop}>
76
+ <TouchableOpacity onPress={() => navigation.goBack()} style={styles.backBtn}>
77
+ <Text style={styles.backBtnText}>←</Text>
78
+ </TouchableOpacity>
79
+ <Text style={styles.headerTitle}>{t.history}</Text>
80
+ <View style={{ width: 44 }} />
81
+ </View>
82
+
83
  {history.length > 0 && (
84
+ <TouchableOpacity
85
+ style={styles.clearBadge}
86
+ onPress={() => {
87
+ Alert.alert(
88
+ t.clearHistory,
89
+ t.confirmClearAll,
90
+ [
91
+ { text: t.cancel, style: "cancel" },
92
+ {
93
+ text: t.clearHistory,
94
+ style: "destructive",
95
+ onPress: async () => {
96
+ await clearHistory();
97
+ loadHistory();
98
+ }
99
+ }
100
+ ]
101
+ );
102
+ }}
103
+ >
104
+ <Text style={styles.clearBadgeText}>{t.clearHistory.toUpperCase()}</Text>
105
  </TouchableOpacity>
106
  )}
107
  </View>
 
109
  <FlatList
110
  data={history}
111
  renderItem={renderItem}
112
+ keyExtractor={(item) => item.timestamp.toString()}
113
+ contentContainerStyle={styles.listContainer}
114
  ListEmptyComponent={
115
+ <View style={styles.emptyBox}>
116
+ <Text style={styles.emptyIcon}>📂</Text>
117
+ <Text style={styles.emptyTitle}>{t.noHistory}</Text>
118
+ <Text style={styles.emptySub}>{language === 'ta' ? "நீங்கள் செய்த ஸ்கேன்கள் இங்கே தோன்றும்" : "Your scan history will appear here once you start scanning leaves."}</Text>
119
  </View>
120
  }
121
  />
 
129
  backgroundColor: COLORS.background,
130
  },
131
  header: {
132
+ backgroundColor: COLORS.primary,
133
+ paddingTop: 50,
134
+ paddingBottom: 25,
135
+ paddingHorizontal: SIZES.padding,
136
+ borderBottomLeftRadius: 35,
137
+ borderBottomRightRadius: 35,
138
+ ...COLORS.shadow.lg,
139
+ alignItems: 'center',
140
+ },
141
+ headerTop: {
142
  flexDirection: 'row',
143
  alignItems: 'center',
144
  justifyContent: 'space-between',
145
+ width: '100%',
146
+ marginBottom: 15,
 
 
 
 
147
  },
148
+ backBtn: {
149
+ width: 44,
150
+ height: 44,
151
+ borderRadius: 22,
152
+ backgroundColor: 'rgba(255,255,255,0.2)',
153
+ justifyContent: 'center',
154
+ alignItems: 'center',
155
  },
156
+ backBtnText: {
157
  fontSize: 24,
158
+ color: COLORS.white,
159
+ fontWeight: 'bold',
160
  },
161
  headerTitle: {
162
  fontSize: 20,
163
+ fontWeight: '900',
164
+ color: COLORS.white,
165
+ letterSpacing: 0.5,
166
  },
167
+ clearBadge: {
168
+ backgroundColor: 'rgba(0,0,0,0.2)',
169
+ paddingHorizontal: 12,
170
+ paddingVertical: 6,
171
+ borderRadius: 10,
172
+ borderWidth: 1,
173
+ borderColor: 'rgba(255,255,255,0.1)',
174
+ },
175
+ clearBadgeText: {
176
+ color: 'rgba(255,255,255,0.8)',
177
+ fontSize: 10,
178
+ fontWeight: '900',
179
+ letterSpacing: 1,
180
  },
181
+ listContainer: {
182
+ padding: SIZES.padding,
183
  },
184
  card: {
185
  flexDirection: 'row',
186
+ backgroundColor: COLORS.surface,
187
+ borderRadius: 22,
188
  marginBottom: 15,
189
+ padding: 12,
190
+ alignItems: 'center',
191
+ borderWidth: 1,
192
+ borderColor: COLORS.border,
193
+ ...COLORS.shadow.sm,
194
+ },
195
+ thumbnailContainer: {
196
+ position: 'relative',
197
  },
198
  thumbnail: {
199
+ width: 64,
200
+ height: 64,
201
+ borderRadius: 15,
202
+ backgroundColor: COLORS.background,
203
+ },
204
+ statusDotOverlay: {
205
+ position: 'absolute',
206
+ bottom: -2,
207
+ right: -2,
208
+ backgroundColor: COLORS.white,
209
+ width: 14,
210
+ height: 14,
211
+ borderRadius: 7,
212
+ justifyContent: 'center',
213
+ alignItems: 'center',
214
+ ...COLORS.shadow.sm,
215
+ },
216
+ miniDot: {
217
+ width: 8,
218
+ height: 8,
219
+ borderRadius: 4,
220
  },
221
  cardContent: {
222
  flex: 1,
223
  marginLeft: 15,
 
224
  },
225
  cropName: {
226
+ fontSize: 10,
227
+ color: COLORS.textLight,
228
+ fontWeight: '900',
229
+ letterSpacing: 1,
230
+ marginBottom: 2,
231
  },
232
  diseaseName: {
233
+ fontSize: 17,
234
+ fontWeight: '800',
235
  color: COLORS.text,
236
+ marginBottom: 4,
237
  },
238
+ dateText: {
239
  fontSize: 12,
240
+ color: COLORS.textLight,
241
+ fontWeight: '600',
242
  },
243
+ deleteIconButton: {
244
+ width: 40,
245
+ height: 40,
246
+ borderRadius: 20,
247
+ backgroundColor: COLORS.background,
248
  justifyContent: 'center',
249
+ alignItems: 'center',
250
  },
251
+ trashIcon: {
252
+ fontSize: 18,
253
+ opacity: 0.6,
254
  },
255
+ emptyBox: {
256
  flex: 1,
257
+ paddingTop: 80,
258
  alignItems: 'center',
259
+ paddingHorizontal: 40,
260
  },
261
+ emptyIcon: {
262
+ fontSize: 64,
263
+ marginBottom: 20,
264
+ opacity: 0.2,
265
+ },
266
+ emptyTitle: {
267
+ fontSize: 18,
268
+ fontWeight: '900',
269
+ color: COLORS.text,
270
+ marginBottom: 8,
271
+ },
272
+ emptySub: {
273
+ fontSize: 14,
274
+ color: COLORS.textLight,
275
+ textAlign: 'center',
276
+ lineHeight: 20,
277
+ fontWeight: '500',
278
  }
279
  });
280
 
screens/HomeScreen.js CHANGED
@@ -10,24 +10,27 @@ import { getHistory } from '../utils/storage';
10
  const { width } = Dimensions.get('window');
11
 
12
  const HomeScreen = ({ route, navigation }) => {
13
- // Robust fallback: Check if route.params exists, then check language, otherwise default to 'en'
14
  const language = route.params?.language || 'en';
15
  const [recentScans, setRecentScans] = useState([]);
16
  const [stats, setStats] = useState({ total: 0, healthy: 0, issues: 0 });
 
17
 
18
- // Safety check for translations
19
  const translations = TRANSLATIONS[language] || TRANSLATIONS['en'];
20
  const t = translations;
21
 
22
  useFocusEffect(
23
  useCallback(() => {
24
  loadData();
 
 
 
 
25
  }, [])
26
  );
27
 
28
  const loadData = async () => {
29
  const history = await getHistory();
30
- setRecentScans(history.slice(0, 5)); // Show top 5 recent
31
 
32
  const total = history.length;
33
  const healthy = history.filter(item => item.analysisResult.isHealthy).length;
@@ -36,11 +39,18 @@ const HomeScreen = ({ route, navigation }) => {
36
  setStats({ total, healthy, issues });
37
  };
38
 
39
- const StatCard = ({ icon, number, label, color, textColor }) => (
40
- <View style={[styles.statCard, { backgroundColor: color }]}>
41
- <Text style={{ fontSize: 24, paddingBottom: 5, color: textColor || COLORS.white }}>{icon}</Text>
42
- <Text style={[styles.statNumber, { color: textColor || COLORS.white }]}>{number}</Text>
43
- <Text style={[styles.statLabel, { color: textColor || COLORS.white }]}>{label}</Text>
 
 
 
 
 
 
 
44
  </View>
45
  );
46
 
@@ -53,7 +63,7 @@ const HomeScreen = ({ route, navigation }) => {
53
 
54
  let result = await ImagePicker.launchImageLibraryAsync({
55
  mediaTypes: ImagePicker.MediaTypeOptions.Images,
56
- allowsEditing: true,
57
  quality: 1,
58
  });
59
 
@@ -69,139 +79,158 @@ const HomeScreen = ({ route, navigation }) => {
69
  return (
70
  <SafeAreaView style={styles.container} edges={['right', 'left', 'top']}>
71
  <StatusBar backgroundColor={COLORS.primary} barStyle="light-content" />
72
- <ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
73
 
74
- {/* Header */}
75
- <View style={styles.header}>
76
- <View style={styles.headerLeft}>
77
- <View style={styles.logoCircle}>
78
- <Image
79
- source={require('../assets/logo.png')}
80
- style={styles.headerLogo}
81
- resizeMode="contain"
82
- />
83
- </View>
84
- <View style={styles.headerTextContainer}>
85
- <Text style={styles.headerTitle}>GREEN DOCTOR</Text>
86
- <Text style={styles.headerSubtitle}>{t.subtitle}</Text>
87
- </View>
88
  </View>
89
  <View style={styles.headerActions}>
90
  <TouchableOpacity
91
  style={styles.headerActionButton}
92
  onPress={() => navigation.navigate('Language')}
93
- title={t.changeLanguage}
94
  >
95
- <Text style={styles.headerActionIcon}>🌐</Text>
96
  </TouchableOpacity>
97
  <TouchableOpacity
98
  style={styles.headerActionButton}
99
  onPress={() => navigation.navigate('About', { language })}
100
- title={t.aboutApp}
101
  >
102
  <Text style={styles.headerActionIcon}>ℹ️</Text>
103
  </TouchableOpacity>
104
  </View>
105
  </View>
106
 
107
- {/* Action Buttons */}
108
- <View style={styles.actionContainer}>
109
- <TouchableOpacity style={styles.actionCard} onPress={takePhoto}>
110
- <View style={styles.actionIconCircle}>
111
- <Text style={styles.actionIcon}>📷</Text>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  </View>
113
- <Text style={styles.actionTitle}>{t.scanPlant}</Text>
114
- <Text style={styles.actionSubtitle}>{t.detectDiseases}</Text>
115
  </TouchableOpacity>
116
 
117
- <TouchableOpacity style={styles.actionCard} onPress={pickImage}>
118
- <View style={[styles.actionIconCircle, { backgroundColor: '#388e3c' }]}>
119
- <Text style={styles.actionIcon}>🖼️</Text>
120
  </View>
121
- <Text style={styles.actionTitle}>{t.pickFromGallery}</Text>
122
- <Text style={styles.actionSubtitle}>{t.detectDiseases}</Text>
123
  </TouchableOpacity>
124
  </View>
125
 
126
- {/* History Button (Moved below or as a full width card) */}
127
- <TouchableOpacity
128
- style={styles.historyFullCard}
129
- onPress={() => navigation.navigate('History', { language })}
130
- >
131
- <View style={styles.historyIconSmall}>
132
- <Text style={{ fontSize: 18 }}></Text>
133
  </View>
134
- <Text style={styles.historyText}>{t.history}</Text>
135
- <Text style={styles.historySubText}>{t.pastDiagnoses}</Text>
136
- </TouchableOpacity>
137
 
138
- {/* Government Schemes Button */}
139
- <TouchableOpacity
140
- style={styles.historyFullCard}
141
- onPress={() => navigation.navigate('Schemes', { language })}
142
- >
143
- <View style={[styles.historyIconSmall, { backgroundColor: '#fff3e0' }]}>
144
- <Text style={{ fontSize: 18 }}>📋</Text>
145
- </View>
146
- <Text style={styles.historyText}>{t.govtSchemes}</Text>
147
- <Text style={styles.historySubText}>{t.viewSchemes}</Text>
148
- </TouchableOpacity>
 
 
 
 
149
 
150
- {/* Stats */}
151
- <Text style={styles.sectionTitle}>{t.yourStats}</Text>
152
- <View style={styles.statsContainer}>
153
- <StatCard icon="📈" number={stats.total} label={t.totalScans} color="#00897b" />
154
- <StatCard icon="🌿" number={stats.healthy} label={t.healthyPlants} color="#00c853" />
155
- <StatCard icon="!" number={stats.issues} label={t.issuesDetected} color="#ff6f00" />
 
 
 
 
 
 
 
156
  </View>
157
 
158
- {/* Today's Tip */}
159
- <Text style={styles.sectionTitle}>{t.todaysTip}</Text>
160
- <View style={styles.tipCard}>
161
- <Text style={styles.tipIcon}>📖</Text>
162
- <Text style={styles.tipText}>{t.tipContent}</Text>
 
 
163
  </View>
164
 
165
- {/* Recent Scans */}
166
- <Text style={styles.sectionTitle}>{t.recentScans}</Text>
167
-
168
- {recentScans.length === 0 ? (
169
- <Text style={{ color: COLORS.gray, fontStyle: 'italic', marginTop: 10 }}>{t.noHistory}</Text>
170
- ) : (
171
- recentScans.map((item, index) => (
172
- <TouchableOpacity
173
- key={index}
174
- style={styles.recentItem}
175
- onPress={() => navigation.navigate('Result', {
176
- imageUri: item.imageUri,
177
- analysisResult: item.analysisResult,
178
- language: language
179
- })}
180
- >
181
- <Image source={{ uri: item.imageUri }} style={styles.recentImagePlaceholder} />
182
- <View style={styles.recentInfo}>
183
- <Text style={styles.recentPlant}>{item.analysisResult.crop}</Text>
184
- <Text style={[
185
- styles.recentIssue,
186
- { color: item.analysisResult.isHealthy ? COLORS.secondary : COLORS.warning }
187
- ]}>
188
- {item.analysisResult.name[language]}
189
- </Text>
190
- <Text style={styles.recentTime}>
191
- {new Date(item.timestamp).toLocaleDateString()}
192
- </Text>
193
- </View>
194
- <Text style={[
195
- styles.alertIcon,
196
- { color: item.analysisResult.isHealthy ? COLORS.secondary : COLORS.warning }
197
- ]}>
198
- {item.analysisResult.isHealthy ? "🌿" : "!"}
199
- </Text>
200
- </TouchableOpacity>
201
- ))
202
- )}
203
 
204
- <View style={{ height: 100 }} />
205
  </ScrollView>
206
  </SafeAreaView>
207
  );
@@ -212,235 +241,319 @@ const styles = StyleSheet.create({
212
  flex: 1,
213
  backgroundColor: COLORS.background,
214
  },
215
- scrollContent: {
216
- padding: SIZES.padding,
217
- paddingBottom: 20,
218
- },
219
- header: {
220
- flexDirection: 'row',
221
- alignItems: 'center',
222
- justifyContent: 'space-between',
223
- marginBottom: 20,
224
  backgroundColor: COLORS.primary,
225
- // Removed negative margins for SafeAreaView
226
  paddingTop: 10,
227
- paddingBottom: 20,
228
  paddingHorizontal: SIZES.padding,
229
- borderRadius: 20, // Rounded corners all around for card-like feel inside container
230
- elevation: 5,
231
- shadowColor: '#000',
232
- shadowOffset: { width: 0, height: 2 },
233
- shadowOpacity: 0.2,
234
- shadowRadius: 4,
235
- },
236
- headerLeft: {
237
  flexDirection: 'row',
 
238
  alignItems: 'center',
 
239
  },
240
- logoCircle: {
241
- width: 55,
242
- height: 55,
243
- backgroundColor: COLORS.white,
244
- borderRadius: 27.5,
245
- overflow: 'hidden',
246
- justifyContent: 'center',
247
- alignItems: 'center',
248
- borderWidth: 2,
249
- borderColor: 'rgba(255,255,255,0.3)',
250
  },
251
- headerLogo: {
252
- width: '100%',
253
- height: '100%',
 
 
254
  },
255
- headerTextContainer: {
256
- marginLeft: 12,
257
- justifyContent: 'center',
 
 
258
  },
259
  headerActions: {
260
  flexDirection: 'row',
 
261
  },
262
  headerActionButton: {
263
- width: 40,
264
- height: 40,
265
- borderRadius: 20,
266
- backgroundColor: 'rgba(255,255,255,0.2)',
267
  justifyContent: 'center',
268
  alignItems: 'center',
269
- marginLeft: 8,
 
270
  },
271
  headerActionIcon: {
272
  fontSize: 20,
273
  },
274
- historyFullCard: {
275
  flexDirection: 'row',
276
- backgroundColor: COLORS.white,
 
277
  padding: 15,
278
- borderRadius: SIZES.radius,
 
 
 
 
 
 
 
 
 
279
  alignItems: 'center',
280
- marginBottom: 20,
281
- elevation: 3,
282
- shadowColor: '#000',
283
- shadowOffset: { width: 0, height: 1 },
284
- shadowOpacity: 0.1,
285
- shadowRadius: 2,
286
- },
287
- historyIconSmall: {
288
- width: 36,
289
- height: 36,
290
- borderRadius: 18,
291
- backgroundColor: '#e0f2f1',
 
 
 
 
 
 
292
  alignItems: 'center',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  justifyContent: 'center',
294
- marginRight: 12,
 
 
 
 
 
295
  },
296
- historyText: {
297
  fontSize: 16,
298
- fontWeight: 'bold',
299
  color: COLORS.text,
300
- flex: 1,
301
  },
302
- historySubText: {
303
- fontSize: 12,
304
- color: COLORS.gray,
305
- marginRight: 10,
 
 
306
  },
307
- headerTitle: {
308
- color: 'white',
309
- fontSize: 20,
310
- fontWeight: 'bold',
 
 
 
 
311
  },
312
- headerSubtitle: {
313
- color: '#e8f5e9',
 
 
314
  fontSize: 12,
 
 
 
315
  },
316
- actionContainer: {
317
- flexDirection: 'row',
318
- justifyContent: 'space-between',
319
- marginBottom: 20,
320
- marginTop: 10,
321
  },
322
- actionCard: {
323
- backgroundColor: COLORS.white,
324
- width: '48%',
325
- padding: 20,
326
- borderRadius: SIZES.radius,
327
- alignItems: 'center',
328
- elevation: 4,
329
- shadowColor: '#000',
330
- shadowOffset: { width: 0, height: 2 },
331
- shadowOpacity: 0.1,
332
- shadowRadius: 4,
333
  },
334
- actionIconCircle: {
 
 
 
 
 
 
 
 
 
 
335
  width: 50,
336
  height: 50,
337
- borderRadius: 25,
338
- backgroundColor: '#004d40',
339
- alignItems: 'center',
340
  justifyContent: 'center',
341
- marginBottom: 10,
 
342
  },
343
- actionIcon: {
344
  fontSize: 24,
345
- color: 'white',
346
  },
347
- actionTitle: {
348
- fontSize: 16,
349
- fontWeight: 'bold',
 
 
 
350
  color: COLORS.text,
351
- marginBottom: 5,
352
  },
353
- actionSubtitle: {
354
- fontSize: 11,
355
- color: COLORS.gray,
356
- textAlign: 'center',
357
  },
358
- sectionTitle: {
 
 
 
 
 
 
359
  fontSize: 18,
360
- color: '#00695c',
361
- marginBottom: 10,
362
- fontWeight: 'bold',
 
363
  },
364
- statsContainer: {
 
 
 
365
  flexDirection: 'row',
366
- justifyContent: 'space-between',
367
- marginBottom: 25,
368
  },
369
  statCard: {
370
- width: '31%',
371
- paddingVertical: 15,
372
- paddingHorizontal: 5,
373
- borderRadius: SIZES.radius,
374
  alignItems: 'center',
375
- elevation: 2,
 
 
 
 
 
376
  },
377
  statNumber: {
378
- fontSize: 20,
379
- fontWeight: 'bold',
380
- marginBottom: 5,
381
  },
382
  statLabel: {
383
- fontSize: 11,
 
 
384
  textAlign: 'center',
 
385
  },
386
- tipCard: {
 
 
 
387
  flexDirection: 'row',
388
- backgroundColor: '#e0f2f1',
389
- padding: 15,
390
- borderRadius: SIZES.radius,
391
- marginBottom: 25,
392
  alignItems: 'center',
393
- borderLeftWidth: 4,
394
- borderLeftColor: '#00897b',
 
 
 
 
395
  },
396
- tipIcon: {
397
- fontSize: 24,
398
- marginRight: 15,
399
- color: '#004d40',
 
400
  },
401
- tipText: {
402
  flex: 1,
403
- color: '#004d40',
404
- fontSize: 14,
405
- lineHeight: 20,
406
  },
407
- recentItem: {
408
- flexDirection: 'row',
409
- backgroundColor: COLORS.white,
410
- padding: 10,
411
- borderRadius: SIZES.radius,
412
- marginBottom: 10,
413
- alignItems: 'center',
414
- elevation: 2,
415
  },
416
- recentImagePlaceholder: {
417
- width: 50,
418
- height: 50,
419
- borderRadius: 10,
420
- backgroundColor: '#eee',
421
- marginRight: 15,
422
  },
423
- recentInfo: {
424
- flex: 1,
425
  },
426
- recentPlant: {
427
- fontSize: 14,
428
- color: COLORS.gray,
429
- fontWeight: 'bold',
430
  },
431
- recentIssue: {
432
- fontSize: 15,
433
- color: COLORS.text,
434
- fontWeight: '600',
435
- marginVertical: 2,
436
  },
437
- recentTime: {
438
- fontSize: 12,
439
- color: '#999',
 
 
 
 
 
440
  },
441
- alertIcon: {
442
- fontSize: 20,
443
- paddingRight: 10,
 
444
  }
445
  });
446
 
 
10
  const { width } = Dimensions.get('window');
11
 
12
  const HomeScreen = ({ route, navigation }) => {
 
13
  const language = route.params?.language || 'en';
14
  const [recentScans, setRecentScans] = useState([]);
15
  const [stats, setStats] = useState({ total: 0, healthy: 0, issues: 0 });
16
+ const [tipIndex, setTipIndex] = useState(0);
17
 
 
18
  const translations = TRANSLATIONS[language] || TRANSLATIONS['en'];
19
  const t = translations;
20
 
21
  useFocusEffect(
22
  useCallback(() => {
23
  loadData();
24
+ // Select a random tip from the pool
25
+ if (t.dailyTips) {
26
+ setTipIndex(Math.floor(Math.random() * t.dailyTips.length));
27
+ }
28
  }, [])
29
  );
30
 
31
  const loadData = async () => {
32
  const history = await getHistory();
33
+ setRecentScans(history.slice(0, 5));
34
 
35
  const total = history.length;
36
  const healthy = history.filter(item => item.analysisResult.isHealthy).length;
 
39
  setStats({ total, healthy, issues });
40
  };
41
 
42
+ const getGreeting = () => {
43
+ const hour = new Date().getHours();
44
+ if (hour < 12) return language === 'ta' ? "காலை வணக்கம்" : "Good Morning";
45
+ if (hour < 17) return language === 'ta' ? "மதிய வணக்கம்" : "Good Afternoon";
46
+ return language === 'ta' ? "மாலை வணக்கம்" : "Good Evening";
47
+ };
48
+
49
+ const StatCard = ({ icon, number, label, color }) => (
50
+ <View style={[styles.statCard, { borderBottomColor: color }]}>
51
+ <Text style={styles.statIcon}>{icon}</Text>
52
+ <Text style={styles.statNumber}>{number}</Text>
53
+ <Text style={styles.statLabel}>{label}</Text>
54
  </View>
55
  );
56
 
 
63
 
64
  let result = await ImagePicker.launchImageLibraryAsync({
65
  mediaTypes: ImagePicker.MediaTypeOptions.Images,
66
+ allowsEditing: false,
67
  quality: 1,
68
  });
69
 
 
79
  return (
80
  <SafeAreaView style={styles.container} edges={['right', 'left', 'top']}>
81
  <StatusBar backgroundColor={COLORS.primary} barStyle="light-content" />
 
82
 
83
+ {/* Immersive Header */}
84
+ <View style={styles.premiumHeader}>
85
+ <View style={styles.headerTopRow}>
86
+ <View style={styles.headerTitleContainer}>
87
+ <Text style={styles.greetingText}>{getGreeting()},</Text>
88
+ <Text style={styles.brandTitle}>GREEN DOCTOR</Text>
 
 
 
 
 
 
 
 
89
  </View>
90
  <View style={styles.headerActions}>
91
  <TouchableOpacity
92
  style={styles.headerActionButton}
93
  onPress={() => navigation.navigate('Language')}
 
94
  >
95
+ <Text style={[styles.headerActionIcon, { fontSize: 13, fontWeight: '900', color: COLORS.white }]}>A/அ</Text>
96
  </TouchableOpacity>
97
  <TouchableOpacity
98
  style={styles.headerActionButton}
99
  onPress={() => navigation.navigate('About', { language })}
 
100
  >
101
  <Text style={styles.headerActionIcon}>ℹ️</Text>
102
  </TouchableOpacity>
103
  </View>
104
  </View>
105
 
106
+ {/* Main Hero Card */}
107
+ <View style={styles.heroCard}>
108
+ <View style={styles.logoCircleLg}>
109
+ <Image
110
+ source={require('../assets/logo.png')}
111
+ style={styles.heroLogo}
112
+ resizeMode="contain"
113
+ />
114
+ </View>
115
+ <View style={styles.heroImpact}>
116
+ <Text style={styles.heroTagline}>{t.subtitle}</Text>
117
+ <View style={styles.activeLabelContainer}>
118
+ <View style={styles.pulseIndicator} />
119
+ <Text style={styles.pulseText}>AI SYSTEM ACTIVE</Text>
120
+ </View>
121
+ </View>
122
+ </View>
123
+ </View>
124
+
125
+ <ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
126
+ {/* Core Scanning Actions */}
127
+ <View style={styles.primaryActionRow}>
128
+ <TouchableOpacity style={styles.primaryActionCard} onPress={takePhoto}>
129
+ <View style={styles.actionIconContainer}>
130
+ <Text style={styles.actionEmoji}>📷</Text>
131
  </View>
132
+ <Text style={styles.actionTitleText}>{t.scanPlant}</Text>
133
+ <Text style={styles.actionDescText}>{t.detectDiseases}</Text>
134
  </TouchableOpacity>
135
 
136
+ <TouchableOpacity style={[styles.primaryActionCard, { backgroundColor: COLORS.secondary + '10' }]} onPress={pickImage}>
137
+ <View style={[styles.actionIconContainer, { backgroundColor: COLORS.secondary }]}>
138
+ <Text style={styles.actionEmoji}>🖼️</Text>
139
  </View>
140
+ <Text style={styles.actionTitleText}>{t.pickFromGallery}</Text>
141
+ <Text style={styles.actionDescText}>{t.detectDiseases}</Text>
142
  </TouchableOpacity>
143
  </View>
144
 
145
+ {/* Daily Expert Tips integrated from Translations */}
146
+ {t.dailyTips && (
147
+ <View style={styles.proTipCard}>
148
+ <View style={styles.tipHeaderBox}>
149
+ <Text style={styles.tipLabel}>💡 {language === 'ta' ? "நிபுணரின் குறிப்பு" : "EXPERT TIP"}</Text>
150
+ </View>
151
+ <Text style={styles.tipMainText}>{t.dailyTips[tipIndex]}</Text>
152
  </View>
153
+ )}
 
 
154
 
155
+ {/* Secondary Hub Actions */}
156
+ <View style={styles.listActionArea}>
157
+ <TouchableOpacity
158
+ style={styles.fullWidthItem}
159
+ onPress={() => navigation.navigate('History', { language })}
160
+ >
161
+ <View style={[styles.itemIconBox, { backgroundColor: '#E3F2FD' }]}>
162
+ <Text style={styles.itemIcon}>↺</Text>
163
+ </View>
164
+ <View style={styles.itemInfo}>
165
+ <Text style={styles.itemTitle}>{t.history}</Text>
166
+ <Text style={styles.itemSubtitle}>{t.pastDiagnoses}</Text>
167
+ </View>
168
+ <Text style={styles.itemChevron}>›</Text>
169
+ </TouchableOpacity>
170
 
171
+ <TouchableOpacity
172
+ style={styles.fullWidthItem}
173
+ onPress={() => navigation.navigate('Schemes', { language })}
174
+ >
175
+ <View style={[styles.itemIconBox, { backgroundColor: '#FFF3E0' }]}>
176
+ <Text style={styles.itemIcon}>📋</Text>
177
+ </View>
178
+ <View style={styles.itemInfo}>
179
+ <Text style={styles.itemTitle}>{t.govtSchemes}</Text>
180
+ <Text style={styles.itemSubtitle}>{t.viewSchemes}</Text>
181
+ </View>
182
+ <Text style={[styles.itemChevron, { color: '#FFB74D' }]}>›</Text>
183
+ </TouchableOpacity>
184
  </View>
185
 
186
+ <View style={styles.statsBlock}>
187
+ <Text style={styles.sectionHeading}>{t.yourStats}</Text>
188
+ <View style={styles.statsRow}>
189
+ <StatCard icon="📈" number={stats.total} label={t.totalScans} color={COLORS.info} />
190
+ <StatCard icon="🌿" number={stats.healthy} label={t.healthyPlants} color={COLORS.success} />
191
+ <StatCard icon="⚠" number={stats.issues} label={t.issuesDetected} color={COLORS.warning} />
192
+ </View>
193
  </View>
194
 
195
+ <View style={styles.recentBlock}>
196
+ <Text style={styles.sectionHeading}>{t.recentScans}</Text>
197
+ {recentScans.length === 0 ? (
198
+ <View style={styles.noRecentBox}>
199
+ <Text style={styles.noRecentText}>{t.noHistory}</Text>
200
+ </View>
201
+ ) : (
202
+ recentScans.map((item, index) => (
203
+ <TouchableOpacity
204
+ key={index}
205
+ style={styles.recentPreviewCard}
206
+ onPress={() => navigation.navigate('Result', {
207
+ imageUri: item.imageUri,
208
+ analysisResult: item.analysisResult,
209
+ language: language
210
+ })}
211
+ >
212
+ <Image source={{ uri: item.imageUri }} style={styles.previewImage} />
213
+ <View style={styles.previewBio}>
214
+ <Text style={styles.previewCrop}>{item.analysisResult.crop}</Text>
215
+ <Text style={[
216
+ styles.previewDisease,
217
+ { color: item.analysisResult.isHealthy ? COLORS.success : COLORS.error }
218
+ ]}>
219
+ {item.analysisResult.name[language]}
220
+ </Text>
221
+ </View>
222
+ <View style={styles.previewAction}>
223
+ <Text style={styles.previewTime}>
224
+ {new Date(item.timestamp).toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}
225
+ </Text>
226
+ <Text style={styles.previewArrow}>→</Text>
227
+ </View>
228
+ </TouchableOpacity>
229
+ ))
230
+ )}
231
+ </View>
 
232
 
233
+ <View style={{ height: 40 }} />
234
  </ScrollView>
235
  </SafeAreaView>
236
  );
 
241
  flex: 1,
242
  backgroundColor: COLORS.background,
243
  },
244
+ premiumHeader: {
 
 
 
 
 
 
 
 
245
  backgroundColor: COLORS.primary,
 
246
  paddingTop: 10,
247
+ paddingBottom: 30,
248
  paddingHorizontal: SIZES.padding,
249
+ borderBottomLeftRadius: 35,
250
+ borderBottomRightRadius: 35,
251
+ ...COLORS.shadow.lg,
252
+ },
253
+ headerTopRow: {
 
 
 
254
  flexDirection: 'row',
255
+ justifyContent: 'space-between',
256
  alignItems: 'center',
257
+ marginBottom: 25,
258
  },
259
+ headerTitleContainer: {
260
+ flex: 1,
 
 
 
 
 
 
 
 
261
  },
262
+ greetingText: {
263
+ color: 'rgba(255,255,255,0.7)',
264
+ fontSize: 14,
265
+ fontWeight: '600',
266
+ letterSpacing: 0.5,
267
  },
268
+ brandTitle: {
269
+ color: COLORS.white,
270
+ fontSize: 22,
271
+ fontWeight: '900',
272
+ letterSpacing: 1,
273
  },
274
  headerActions: {
275
  flexDirection: 'row',
276
+ gap: 10,
277
  },
278
  headerActionButton: {
279
+ width: 44,
280
+ height: 44,
281
+ borderRadius: 14,
282
+ backgroundColor: 'rgba(255,255,255,0.15)',
283
  justifyContent: 'center',
284
  alignItems: 'center',
285
+ borderWidth: 1,
286
+ borderColor: 'rgba(255,255,255,0.2)',
287
  },
288
  headerActionIcon: {
289
  fontSize: 20,
290
  },
291
+ heroCard: {
292
  flexDirection: 'row',
293
+ alignItems: 'center',
294
+ backgroundColor: 'rgba(255,255,255,0.1)',
295
  padding: 15,
296
+ borderRadius: 25,
297
+ borderWidth: 1,
298
+ borderColor: 'rgba(255,255,255,0.1)',
299
+ },
300
+ logoCircleLg: {
301
+ width: 70,
302
+ height: 70,
303
+ borderRadius: 35,
304
+ backgroundColor: COLORS.white,
305
+ justifyContent: 'center',
306
  alignItems: 'center',
307
+ ...COLORS.shadow.md,
308
+ },
309
+ heroLogo: {
310
+ width: '80%',
311
+ height: '80%',
312
+ },
313
+ heroImpact: {
314
+ marginLeft: 15,
315
+ flex: 1,
316
+ },
317
+ heroTagline: {
318
+ color: COLORS.white,
319
+ fontSize: 15,
320
+ fontWeight: '700',
321
+ marginBottom: 6,
322
+ },
323
+ activeLabelContainer: {
324
+ flexDirection: 'row',
325
  alignItems: 'center',
326
+ backgroundColor: 'rgba(0,0,0,0.2)',
327
+ alignSelf: 'flex-start',
328
+ paddingHorizontal: 8,
329
+ paddingVertical: 4,
330
+ borderRadius: 10,
331
+ },
332
+ pulseIndicator: {
333
+ width: 6,
334
+ height: 6,
335
+ borderRadius: 3,
336
+ backgroundColor: '#4ade80',
337
+ marginRight: 6,
338
+ },
339
+ pulseText: {
340
+ color: '#4ade80',
341
+ fontSize: 9,
342
+ fontWeight: '900',
343
+ letterSpacing: 1,
344
+ },
345
+ scrollContent: {
346
+ padding: SIZES.padding,
347
+ },
348
+ primaryActionRow: {
349
+ flexDirection: 'row',
350
+ gap: 15,
351
+ marginTop: 20,
352
+ marginBottom: 25,
353
+ },
354
+ primaryActionCard: {
355
+ flex: 1,
356
+ backgroundColor: COLORS.primary + '10',
357
+ borderRadius: 25,
358
+ padding: 20,
359
+ alignItems: 'center',
360
+ borderWidth: 1,
361
+ borderColor: COLORS.border,
362
+ },
363
+ actionIconContainer: {
364
+ width: 60,
365
+ height: 60,
366
+ borderRadius: 30,
367
+ backgroundColor: COLORS.primary,
368
  justifyContent: 'center',
369
+ alignItems: 'center',
370
+ marginBottom: 12,
371
+ ...COLORS.shadow.md,
372
+ },
373
+ actionEmoji: {
374
+ fontSize: 28,
375
  },
376
+ actionTitleText: {
377
  fontSize: 16,
378
+ fontWeight: '800',
379
  color: COLORS.text,
380
+ textAlign: 'center',
381
  },
382
+ actionDescText: {
383
+ fontSize: 11,
384
+ color: COLORS.textLight,
385
+ textAlign: 'center',
386
+ marginTop: 4,
387
+ fontWeight: '600',
388
  },
389
+ proTipCard: {
390
+ backgroundColor: COLORS.surface,
391
+ borderRadius: 25,
392
+ padding: 20,
393
+ marginBottom: 25,
394
+ borderLeftWidth: 6,
395
+ borderLeftColor: COLORS.secondary,
396
+ ...COLORS.shadow.md,
397
  },
398
+ tipHeaderBox: {
399
+ marginBottom: 10,
400
+ },
401
+ tipLabel: {
402
  fontSize: 12,
403
+ fontWeight: '900',
404
+ color: COLORS.secondary,
405
+ letterSpacing: 1,
406
  },
407
+ tipMainText: {
408
+ fontSize: 15,
409
+ color: COLORS.text,
410
+ lineHeight: 22,
411
+ fontWeight: '500',
412
  },
413
+ listActionArea: {
414
+ gap: 12,
415
+ marginBottom: 30,
 
 
 
 
 
 
 
 
416
  },
417
+ fullWidthItem: {
418
+ flexDirection: 'row',
419
+ alignItems: 'center',
420
+ backgroundColor: COLORS.surface,
421
+ padding: 16,
422
+ borderRadius: 22,
423
+ borderWidth: 1,
424
+ borderColor: COLORS.border,
425
+ ...COLORS.shadow.sm,
426
+ },
427
+ itemIconBox: {
428
  width: 50,
429
  height: 50,
430
+ borderRadius: 15,
 
 
431
  justifyContent: 'center',
432
+ alignItems: 'center',
433
+ marginRight: 15,
434
  },
435
+ itemIcon: {
436
  fontSize: 24,
 
437
  },
438
+ itemInfo: {
439
+ flex: 1,
440
+ },
441
+ itemTitle: {
442
+ fontSize: 17,
443
+ fontWeight: '800',
444
  color: COLORS.text,
445
+ marginBottom: 2,
446
  },
447
+ itemSubtitle: {
448
+ fontSize: 12,
449
+ color: COLORS.textLight,
450
+ fontWeight: '500',
451
  },
452
+ itemChevron: {
453
+ fontSize: 28,
454
+ color: COLORS.primary,
455
+ opacity: 0.3,
456
+ fontWeight: '300',
457
+ },
458
+ sectionHeading: {
459
  fontSize: 18,
460
+ fontWeight: '900',
461
+ color: COLORS.primaryDark,
462
+ marginBottom: 15,
463
+ letterSpacing: 0.5,
464
  },
465
+ statsBlock: {
466
+ marginBottom: 30,
467
+ },
468
+ statsRow: {
469
  flexDirection: 'row',
470
+ gap: 12,
 
471
  },
472
  statCard: {
473
+ flex: 1,
474
+ backgroundColor: COLORS.surface,
475
+ borderRadius: 20,
476
+ padding: 15,
477
  alignItems: 'center',
478
+ borderBottomWidth: 4,
479
+ ...COLORS.shadow.sm,
480
+ },
481
+ statIcon: {
482
+ fontSize: 24,
483
+ marginBottom: 8,
484
  },
485
  statNumber: {
486
+ fontSize: 22,
487
+ fontWeight: '900',
488
+ color: COLORS.text,
489
  },
490
  statLabel: {
491
+ fontSize: 10,
492
+ fontWeight: '700',
493
+ color: COLORS.textLight,
494
  textAlign: 'center',
495
+ marginTop: 2,
496
  },
497
+ recentBlock: {
498
+ marginBottom: 20,
499
+ },
500
+ recentPreviewCard: {
501
  flexDirection: 'row',
 
 
 
 
502
  alignItems: 'center',
503
+ backgroundColor: COLORS.surface,
504
+ padding: 12,
505
+ borderRadius: 20,
506
+ marginBottom: 10,
507
+ borderWidth: 1,
508
+ borderColor: COLORS.border,
509
  },
510
+ previewImage: {
511
+ width: 54,
512
+ height: 54,
513
+ borderRadius: 12,
514
+ backgroundColor: COLORS.background,
515
  },
516
+ previewBio: {
517
  flex: 1,
518
+ marginLeft: 15,
 
 
519
  },
520
+ previewCrop: {
521
+ fontSize: 13,
522
+ fontWeight: '700',
523
+ color: COLORS.textLight,
524
+ textTransform: 'uppercase',
 
 
 
525
  },
526
+ previewDisease: {
527
+ fontSize: 16,
528
+ fontWeight: '800',
 
 
 
529
  },
530
+ previewAction: {
531
+ alignItems: 'flex-end',
532
  },
533
+ previewTime: {
534
+ fontSize: 11,
535
+ fontWeight: '700',
536
+ color: COLORS.textLight,
537
  },
538
+ previewArrow: {
539
+ fontSize: 18,
540
+ color: COLORS.primary,
541
+ fontWeight: '900',
542
+ marginTop: 2,
543
  },
544
+ noRecentBox: {
545
+ padding: 40,
546
+ alignItems: 'center',
547
+ backgroundColor: COLORS.surface,
548
+ borderRadius: 20,
549
+ borderStyle: 'dashed',
550
+ borderWidth: 1,
551
+ borderColor: COLORS.border,
552
  },
553
+ noRecentText: {
554
+ color: COLORS.textLight,
555
+ fontStyle: 'italic',
556
+ fontSize: 14,
557
  }
558
  });
559
 
screens/LanguageScreen.js CHANGED
@@ -1,97 +1,221 @@
1
  import React from 'react';
2
- import { View, Text, TouchableOpacity, StyleSheet, Image } from 'react-native';
3
- import { COLORS, SIZES } from '../constants/theme';
 
4
  import { TRANSLATIONS } from '../constants/translations';
5
 
 
 
6
  const LanguageScreen = ({ navigation }) => {
7
  const handleLanguageSelect = (lang) => {
8
- // Navigate to Home with selected language
9
  navigation.reset({
10
  index: 0,
11
  routes: [{ name: 'Home', params: { language: lang } }],
12
  });
13
  };
14
 
15
- return (
16
- <View style={styles.container}>
17
- {/* Logo Area */}
18
- <View style={styles.logoContainer}>
19
- <Image
20
- source={require('../assets/logo.png')}
21
- style={styles.logoImage}
22
- resizeMode="contain"
23
- />
 
 
 
 
 
 
 
 
24
  </View>
 
 
 
 
 
 
25
 
26
- <View style={styles.spacer} />
 
 
27
 
28
- {/* Language Selection Header */}
29
- <Text style={styles.title}>{TRANSLATIONS.en.selectLanguage}/</Text>
30
- <Text style={styles.title}>{TRANSLATIONS.ta.selectLanguage}</Text>
 
 
 
 
 
31
 
32
- <View style={styles.spacer} />
 
 
 
 
 
 
33
 
34
- {/* Buttons */}
35
- <TouchableOpacity
36
- style={styles.button}
37
- onPress={() => handleLanguageSelect('en')}
38
- >
39
- <Text style={styles.buttonText}>{TRANSLATIONS.en.english}</Text>
40
- </TouchableOpacity>
 
41
 
42
- <TouchableOpacity
43
- style={styles.button}
44
- onPress={() => handleLanguageSelect('ta')}
45
- >
46
- <Text style={styles.buttonText}>{TRANSLATIONS.ta.tamil}</Text>
47
- </TouchableOpacity>
48
- </View>
 
 
 
 
 
 
 
 
49
  );
50
  };
51
 
52
  const styles = StyleSheet.create({
53
  container: {
54
  flex: 1,
55
- backgroundColor: COLORS.white,
56
- alignItems: 'center',
 
 
 
 
 
 
 
 
 
 
 
 
57
  justifyContent: 'center',
58
- padding: SIZES.padding,
59
  },
60
- logoContainer: {
 
 
 
61
  alignItems: 'center',
62
- marginBottom: 20,
63
- height: 180,
64
  },
65
  logoImage: {
66
  width: 300,
67
  height: '100%',
68
  },
69
- spacer: {
70
- height: 30,
 
 
 
 
 
 
 
 
 
71
  },
72
  title: {
73
- color: '#004d00', // Dark green
74
- fontSize: 18,
 
75
  textAlign: 'center',
76
- marginBottom: 5,
 
 
 
 
 
77
  },
78
- button: {
 
 
 
79
  width: '100%',
80
- maxWidth: 250,
81
- paddingVertical: 15,
82
- borderRadius: 25,
83
  borderWidth: 1,
84
- borderColor: '#000',
85
- backgroundColor: COLORS.white,
86
- marginVertical: 15,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  alignItems: 'center',
88
  },
89
- buttonText: {
 
90
  fontSize: 20,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  fontWeight: 'bold',
92
- color: '#3e2723', // Dark brownish color from image
93
- letterSpacing: 1,
94
  },
 
 
 
 
 
 
 
95
  });
96
 
97
  export default LanguageScreen;
 
1
  import React from 'react';
2
+ import { View, Text, TouchableOpacity, StyleSheet, Image, Dimensions, StatusBar } from 'react-native';
3
+ import { SafeAreaView } from 'react-native-safe-area-context';
4
+ import { COLORS, SIZES, FONTS } from '../constants/theme';
5
  import { TRANSLATIONS } from '../constants/translations';
6
 
7
+ const { width } = Dimensions.get('window');
8
+
9
  const LanguageScreen = ({ navigation }) => {
10
  const handleLanguageSelect = (lang) => {
 
11
  navigation.reset({
12
  index: 0,
13
  routes: [{ name: 'Home', params: { language: lang } }],
14
  });
15
  };
16
 
17
+ const LanguageTile = ({ lang, code, label, subLabel, icon }) => (
18
+ <TouchableOpacity
19
+ style={styles.langTile}
20
+ onPress={() => handleLanguageSelect(code)}
21
+ activeOpacity={0.7}
22
+ >
23
+ <View style={styles.tileContent}>
24
+ <View style={styles.iconCircle}>
25
+ <Text style={styles.tileIcon}>{icon}</Text>
26
+ </View>
27
+ <View style={styles.tileTextContainer}>
28
+ <Text style={styles.tileLabel}>{label}</Text>
29
+ <Text style={styles.tileSubLabel}>{subLabel}</Text>
30
+ </View>
31
+ <View style={styles.arrowContainer}>
32
+ <Text style={styles.arrowIcon}>→</Text>
33
+ </View>
34
  </View>
35
+ </TouchableOpacity>
36
+ );
37
+
38
+ return (
39
+ <SafeAreaView style={styles.container}>
40
+ <StatusBar backgroundColor={COLORS.background} barStyle="dark-content" />
41
 
42
+ <View style={styles.content}>
43
+ {/* Visual Accent */}
44
+ <View style={styles.topAccent} />
45
 
46
+ {/* Logo Section */}
47
+ <View style={styles.logoWrapper}>
48
+ <Image
49
+ source={require('../assets/logo.png')}
50
+ style={styles.logoImage}
51
+ resizeMode="contain"
52
+ />
53
+ </View>
54
 
55
+ {/* Header Section */}
56
+ <View style={styles.header}>
57
+ <Text style={styles.welcomeText}>WELCOME / வரவேற்கிறோம்</Text>
58
+ <Text style={styles.title}>
59
+ {TRANSLATIONS.en.selectLanguage} / {TRANSLATIONS.ta.selectLanguage}
60
+ </Text>
61
+ </View>
62
 
63
+ {/* Selection Section */}
64
+ <View style={styles.selectionGrid}>
65
+ <LanguageTile
66
+ code="en"
67
+ label="English"
68
+ subLabel="Continue in English"
69
+ icon="🇬🇧"
70
+ />
71
 
72
+ <LanguageTile
73
+ code="ta"
74
+ label="தமிழ்"
75
+ subLabel="தமிழில் தொடரவும்"
76
+ icon="🇮🇳"
77
+ />
78
+ </View>
79
+
80
+ <View style={styles.footer}>
81
+ <Text style={styles.footerText}>Green Doctor v1.0.0</Text>
82
+ <View style={styles.divider} />
83
+ <Text style={styles.powerText}>Empowering Farmers with AI</Text>
84
+ </View>
85
+ </View>
86
+ </SafeAreaView>
87
  );
88
  };
89
 
90
  const styles = StyleSheet.create({
91
  container: {
92
  flex: 1,
93
+ backgroundColor: COLORS.background,
94
+ },
95
+ topAccent: {
96
+ position: 'absolute',
97
+ top: -100,
98
+ right: -100,
99
+ width: 300,
100
+ height: 300,
101
+ borderRadius: 150,
102
+ backgroundColor: COLORS.primaryLight + '10',
103
+ },
104
+ content: {
105
+ flex: 1,
106
+ paddingHorizontal: SIZES.padding * 1.5,
107
  justifyContent: 'center',
108
+ alignItems: 'center',
109
  },
110
+ logoWrapper: {
111
+ marginBottom: 30,
112
+ height: 160,
113
+ width: '100%',
114
  alignItems: 'center',
 
 
115
  },
116
  logoImage: {
117
  width: 300,
118
  height: '100%',
119
  },
120
+ header: {
121
+ alignItems: 'center',
122
+ marginBottom: 40,
123
+ },
124
+ welcomeText: {
125
+ fontSize: 12,
126
+ color: COLORS.primary,
127
+ fontWeight: '800',
128
+ letterSpacing: 3,
129
+ marginBottom: 12,
130
+ textTransform: 'uppercase',
131
  },
132
  title: {
133
+ color: COLORS.text,
134
+ fontSize: SIZES.h3,
135
+ fontWeight: '600',
136
  textAlign: 'center',
137
+ lineHeight: 26,
138
+ opacity: 0.8,
139
+ },
140
+ selectionGrid: {
141
+ width: '100%',
142
+ gap: 20,
143
  },
144
+ langTile: {
145
+ backgroundColor: COLORS.surface,
146
+ borderRadius: SIZES.radius,
147
+ padding: SIZES.padding,
148
  width: '100%',
 
 
 
149
  borderWidth: 1,
150
+ borderColor: COLORS.border,
151
+ ...COLORS.shadow.md,
152
+ },
153
+ tileContent: {
154
+ flexDirection: 'row',
155
+ alignItems: 'center',
156
+ },
157
+ iconCircle: {
158
+ width: 56,
159
+ height: 56,
160
+ borderRadius: 28,
161
+ backgroundColor: COLORS.background,
162
+ justifyContent: 'center',
163
+ alignItems: 'center',
164
+ marginRight: 16,
165
+ },
166
+ tileIcon: {
167
+ fontSize: 28,
168
+ },
169
+ tileTextContainer: {
170
+ flex: 1,
171
+ },
172
+ tileLabel: {
173
+ fontSize: 22,
174
+ fontWeight: '900',
175
+ color: COLORS.primaryDark,
176
+ marginBottom: 2,
177
+ },
178
+ tileSubLabel: {
179
+ fontSize: 13,
180
+ color: COLORS.textLight,
181
+ fontWeight: '600',
182
+ },
183
+ arrowContainer: {
184
+ width: 40,
185
+ height: 40,
186
+ borderRadius: 20,
187
+ backgroundColor: COLORS.primary,
188
+ justifyContent: 'center',
189
  alignItems: 'center',
190
  },
191
+ arrowIcon: {
192
+ color: COLORS.white,
193
  fontSize: 20,
194
+ fontWeight: '900',
195
+ },
196
+ footer: {
197
+ marginTop: 60,
198
+ alignItems: 'center',
199
+ },
200
+ divider: {
201
+ width: 40,
202
+ height: 2,
203
+ backgroundColor: COLORS.border,
204
+ marginVertical: 12,
205
+ },
206
+ footerText: {
207
+ fontSize: 12,
208
+ color: COLORS.textLight,
209
  fontWeight: 'bold',
210
+ opacity: 0.6,
 
211
  },
212
+ powerText: {
213
+ fontSize: 10,
214
+ color: COLORS.textLight,
215
+ letterSpacing: 1.5,
216
+ textTransform: 'uppercase',
217
+ opacity: 0.5,
218
+ }
219
  });
220
 
221
  export default LanguageScreen;
screens/ResultScreen.js CHANGED
@@ -9,24 +9,64 @@ const ResultScreen = ({ route, navigation }) => {
9
  // We expect imageUri and language from HomeScreen
10
  const { imageUri, language, analysisResult: initialResult } = route.params || {};
11
 
12
- const [loading, setLoading] = useState(!initialResult);
13
  const [analysisResult, setAnalysisResult] = useState(initialResult || null);
 
14
  const [activeTab, setActiveTab] = useState('organic');
15
 
16
  const translations = TRANSLATIONS[language] || TRANSLATIONS['en'];
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  useEffect(() => {
19
- if (!initialResult && imageUri) {
20
  performAnalysis();
21
  }
22
- }, [imageUri, initialResult]);
23
 
24
  const performAnalysis = async () => {
 
25
  try {
26
  const result = await analyzeImage(imageUri);
27
  setAnalysisResult(result);
28
 
29
- // Save to history
30
  const scanData = {
31
  id: Date.now().toString(),
32
  timestamp: Date.now(),
@@ -42,11 +82,45 @@ const ResultScreen = ({ route, navigation }) => {
42
  }
43
  };
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  if (loading) {
46
  return (
47
- <View style={styles.loadingContainer}>
48
  <ActivityIndicator size="large" color={COLORS.primary} />
49
- <Text style={styles.loadingText}>{translations.analyzing || "Analyzing..."}</Text>
50
  </View>
51
  );
52
  }
@@ -54,10 +128,10 @@ const ResultScreen = ({ route, navigation }) => {
54
  if (!analysisResult) {
55
  return (
56
  <View style={styles.container}>
57
- <View style={styles.loadingContainer}>
58
- <Text style={{ color: COLORS.error, fontSize: 18 }}>{translations.error || "Detection Failed"}</Text>
59
- <TouchableOpacity style={styles.homeButton} onPress={() => navigation.navigate('Home')}>
60
- <Text style={styles.homeButtonText}>{translations.backHome}</Text>
61
  </TouchableOpacity>
62
  </View>
63
  </View>
@@ -67,123 +141,110 @@ const ResultScreen = ({ route, navigation }) => {
67
  const { crop, name, isHealthy, severity, symptoms, cause, remedy, remedy_organic, remedy_chemical, prevention, confidence } = analysisResult;
68
 
69
  const getSeverityColor = (sev) => {
70
- if (!sev) return COLORS.gray;
71
  switch (sev.toLowerCase()) {
72
- case 'low': return COLORS.secondary; // Green-ish/Yellow
73
- case 'medium': return 'orange';
74
  case 'high': return COLORS.error;
75
- default: return COLORS.gray;
76
  }
77
  };
78
 
79
- const renderHeader = () => (
80
- <View style={[styles.header, { backgroundColor: isHealthy ? COLORS.secondary : COLORS.error }]}>
81
- <TouchableOpacity onPress={() => navigation.goBack()} style={styles.backButton}>
82
- <Text style={styles.backButtonText}>←</Text>
83
- </TouchableOpacity>
84
- <View style={styles.logoCircleSmall}>
85
- <Image
86
- source={require('../assets/logo.png')}
87
- style={styles.headerLogoSmall}
88
- resizeMode="cover"
89
- />
90
- </View>
91
- <Text style={[styles.headerTitle, { marginLeft: 10 }]}>{translations.results}</Text>
92
- </View>
93
- );
94
-
95
- const renderTab = (key, label) => (
96
- <TouchableOpacity
97
- style={[styles.tab, activeTab === key && styles.activeTab]}
98
- onPress={() => setActiveTab(key)}
99
- >
100
- <Text style={[styles.tabText, activeTab === key && styles.activeTabText]}>{label}</Text>
101
- </TouchableOpacity>
102
- );
103
-
104
  return (
105
  <View style={styles.container}>
106
- {renderHeader()}
107
 
108
- <ScrollView showsVerticalScrollIndicator={false}>
109
- <Image source={{ uri: imageUri }} style={styles.scannedImage} />
 
 
 
 
 
 
110
 
111
- <View style={styles.resultContainer}>
112
- <View style={styles.titleRow}>
113
- <Text style={styles.diseaseName}>{name[language]}</Text>
114
- <View style={{ alignItems: 'flex-end' }}>
115
- <View style={styles.confidenceBadge}>
116
- <Text style={styles.confidenceText}>{confidence}%</Text>
117
- </View>
118
- {analysisResult.isMock && (
119
- <Text style={{ fontSize: 10, color: COLORS.gray, marginTop: 2 }}>
120
- Offline Mode
121
- </Text>
122
- )}
123
- </View>
124
  </View>
125
 
126
  {!isHealthy && (
127
- <View style={styles.metaContainer}>
128
- <View style={[styles.severityBadge, { backgroundColor: getSeverityColor(severity) }]}>
129
- <Text style={styles.severityText}>{translations.severity}: {severity}</Text>
 
 
 
130
  </View>
131
- <Text style={styles.cropText}>{translations.detected}: {crop}</Text>
132
  </View>
133
  )}
134
 
135
- <Text style={styles.sectionTitle}>
136
- {analysisResult.id === 'UNKNOWN' ? translations.unknownStatus : translations.symptoms}
137
- </Text>
138
- <Text style={styles.description}>{symptoms[language]}</Text>
 
 
139
 
140
  {!isHealthy && cause && (
141
- <>
142
- <Text style={styles.sectionTitle}>{translations.cause}</Text>
143
- <Text style={styles.description}>{cause[language]}</Text>
144
-
145
- <View style={styles.tabContainer}>
146
- {renderTab('organic', analysisResult.id === 'UNKNOWN' ? translations.unknownInstruction : translations.organic)}
147
- {renderTab('chemical', analysisResult.id === 'UNKNOWN' ? translations.unknownAdvice : translations.chemical)}
148
- {renderTab('prevention', analysisResult.id === 'UNKNOWN' ? translations.unknownNextSteps : translations.prevention)}
149
- </View>
150
-
151
- <View style={styles.remedyBox}>
152
- {activeTab === 'organic' && <Text style={styles.remedyText}>{remedy_organic[language]}</Text>}
153
- {activeTab === 'chemical' && <Text style={styles.remedyText}>{remedy_chemical[language]}</Text>}
154
- {activeTab === 'prevention' && <Text style={styles.remedyText}>{prevention[language]}</Text>}
155
- </View>
156
- </>
157
  )}
158
 
159
  {isHealthy && remedy && (
160
- <>
161
- <Text style={styles.sectionTitle}>{translations.remedy}</Text>
162
- <Text style={styles.description}>{remedy[language]}</Text>
163
- </>
164
  )}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
 
166
- {analysisResult.diagnosticChecklist && (
167
- <View style={styles.checklistContainer}>
168
- <Text style={styles.checklistTitle}>
 
169
  {analysisResult.diagnosticChecklist.title[language]}
170
  </Text>
171
- {analysisResult.diagnosticChecklist.steps.map((step, index) => (
172
- <View key={index} style={styles.checkItem}>
173
- <View style={styles.bullet} />
174
- <Text style={styles.checkText}>{step[language]}</Text>
175
- </View>
176
- ))}
177
  </View>
178
- )}
 
 
 
 
 
 
 
179
 
180
- </View>
181
- <View style={{ height: 30 }} />
182
  </ScrollView>
183
 
184
- <TouchableOpacity style={styles.homeButton} onPress={() => navigation.navigate('Home')}>
185
- <Text style={styles.homeButtonText}>{translations.backHome}</Text>
186
- </TouchableOpacity>
 
 
187
  </View>
188
  );
189
  };
@@ -195,202 +256,371 @@ const styles = StyleSheet.create({
195
  },
196
  header: {
197
  paddingTop: 50,
198
- paddingBottom: 20,
199
- paddingHorizontal: 20,
200
  flexDirection: 'row',
201
  alignItems: 'center',
202
- borderBottomLeftRadius: 30,
203
- borderBottomRightRadius: 30,
204
- },
205
- backButton: {
206
- marginRight: 15,
 
 
 
 
 
 
207
  },
208
- backButtonText: {
209
  fontSize: 24,
210
- color: '#fff',
211
  fontWeight: 'bold',
212
  },
213
- logoCircleSmall: {
214
- width: 40,
215
- height: 40,
216
- backgroundColor: '#fff',
217
- borderRadius: 20,
218
- overflow: 'hidden',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  justifyContent: 'center',
220
  alignItems: 'center',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  },
222
- headerLogoSmall: {
223
  width: '100%',
224
  height: '100%',
225
  },
226
- headerTitle: {
227
- fontSize: 22,
228
- fontWeight: 'bold',
229
- color: '#fff',
 
 
 
 
 
 
 
 
230
  },
231
- scannedImage: {
232
- width: '90%',
233
- height: 250,
234
- alignSelf: 'center',
235
- borderRadius: 20,
236
- marginTop: 20,
237
- marginBottom: 20,
238
  },
239
- resultContainer: {
240
- paddingHorizontal: 20,
 
 
 
241
  },
242
- titleRow: {
243
- flexDirection: 'row',
244
- justifyContent: 'space-between',
245
- alignItems: 'center',
246
- marginBottom: 10,
 
 
 
247
  },
248
- diseaseName: {
249
- fontSize: 24,
250
- fontWeight: 'bold',
251
- color: COLORS.text,
252
- flex: 1,
253
  },
254
- confidenceBadge: {
255
- backgroundColor: COLORS.primary + '20', // 20% opacity
256
- paddingHorizontal: 10,
257
- paddingVertical: 5,
258
- borderRadius: 15,
 
 
 
 
 
 
259
  },
260
- confidenceText: {
261
- color: COLORS.primary,
262
- fontWeight: 'bold',
263
  },
264
- metaContainer: {
265
  flexDirection: 'row',
266
  alignItems: 'center',
267
- marginBottom: 15,
 
 
 
268
  },
269
- severityBadge: {
270
- paddingHorizontal: 10,
271
- paddingVertical: 4,
272
- borderRadius: 8,
273
- marginRight: 10,
274
  },
275
- severityText: {
276
- color: '#fff',
277
- fontWeight: 'bold',
278
  fontSize: 12,
 
 
279
  },
280
- cropText: {
281
- fontSize: 14,
282
- color: COLORS.gray,
283
  },
284
- sectionTitle: {
285
- fontSize: 18,
286
- fontWeight: 'bold',
287
  color: COLORS.primary,
288
- marginTop: 15,
289
- marginBottom: 5,
 
290
  },
291
- description: {
292
  fontSize: 16,
293
  color: COLORS.text,
294
  lineHeight: 24,
 
 
 
 
 
 
 
 
 
 
 
 
295
  },
296
- tabContainer: {
297
  flexDirection: 'row',
298
- marginTop: 20,
299
- backgroundColor: '#f0f0f0',
300
- borderRadius: 10,
301
- padding: 4,
302
  },
303
- tab: {
304
  flex: 1,
305
- paddingVertical: 10,
306
  alignItems: 'center',
307
- borderRadius: 8,
308
  },
309
- activeTab: {
310
- backgroundColor: '#fff',
311
- shadowColor: "#000",
312
- shadowOffset: { width: 0, height: 1 },
313
- shadowOpacity: 0.1,
314
- shadowRadius: 1,
315
- elevation: 1,
316
  },
317
- tabText: {
318
- color: COLORS.gray,
319
- fontWeight: '600',
 
320
  },
321
- activeTabText: {
322
- color: COLORS.primary,
 
323
  },
324
- remedyBox: {
325
- marginTop: 15,
326
- padding: 15,
327
- backgroundColor: '#f9f9f9',
328
- borderRadius: 10,
329
- borderLeftWidth: 4,
330
  borderLeftColor: COLORS.primary,
 
331
  },
332
- remedyText: {
333
- fontSize: 16,
334
  color: COLORS.text,
335
  lineHeight: 24,
 
336
  },
337
- homeButton: {
338
- backgroundColor: COLORS.primary,
339
- margin: 20,
340
- padding: 15,
341
- borderRadius: 15,
342
- alignItems: 'center',
343
- },
344
- homeButtonText: {
345
- color: '#fff',
346
- fontSize: 18,
347
- fontWeight: 'bold',
348
  },
349
- checklistContainer: {
350
- marginTop: 25,
351
- padding: 20,
352
- backgroundColor: COLORS.primary + '10', // 10% opacity
353
- borderRadius: 20,
354
- borderWidth: 1,
355
- borderColor: COLORS.primary + '30',
356
- marginBottom: 10,
357
  },
358
- checklistTitle: {
359
  fontSize: 18,
360
- fontWeight: 'bold',
361
- color: COLORS.primary,
362
- marginBottom: 15,
363
  },
364
- checkItem: {
365
  flexDirection: 'row',
366
  alignItems: 'flex-start',
367
- marginBottom: 12,
368
  },
369
- bullet: {
370
- width: 8,
371
- height: 8,
372
- borderRadius: 4,
373
- backgroundColor: COLORS.primary,
374
- marginTop: 8,
375
- marginRight: 12,
376
  },
377
- checkText: {
378
  fontSize: 15,
379
- color: COLORS.text,
380
  lineHeight: 22,
381
  flex: 1,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  },
383
- loadingContainer: {
384
  flex: 1,
385
  justifyContent: 'center',
386
  alignItems: 'center',
387
- backgroundColor: COLORS.background
388
  },
389
- loadingText: {
390
  marginTop: 20,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  fontSize: 18,
392
- color: COLORS.primary,
393
- fontWeight: 'bold'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
394
  }
395
  });
396
 
 
9
  // We expect imageUri and language from HomeScreen
10
  const { imageUri, language, analysisResult: initialResult } = route.params || {};
11
 
12
+ const [loading, setLoading] = useState(false);
13
  const [analysisResult, setAnalysisResult] = useState(initialResult || null);
14
+ const [confirmed, setConfirmed] = useState(!!initialResult);
15
  const [activeTab, setActiveTab] = useState('organic');
16
 
17
  const translations = TRANSLATIONS[language] || TRANSLATIONS['en'];
18
 
19
+ const renderHeader = (isHealthyResult = null) => {
20
+ const headerBg = isHealthyResult === null
21
+ ? COLORS.primary
22
+ : (isHealthyResult ? COLORS.success : COLORS.error);
23
+
24
+ return (
25
+ <View style={[styles.header, { backgroundColor: headerBg }]}>
26
+ <TouchableOpacity onPress={() => navigation.goBack()} style={styles.headerButton}>
27
+ <Text style={styles.headerButtonText}>←</Text>
28
+ </TouchableOpacity>
29
+ <View style={styles.headerTitleUnit}>
30
+ <Text style={styles.headerLabel}>{translations.results}</Text>
31
+ {isHealthyResult !== null && (
32
+ <Text style={styles.headerStatusSub}>
33
+ {isHealthyResult ? "PLANT IS HEALTHY" : "ISSUE DETECTED"}
34
+ </Text>
35
+ )}
36
+ </View>
37
+ <View style={styles.logoCircleHeader}>
38
+ <Image
39
+ source={require('../assets/logo.png')}
40
+ style={styles.logoImgSmall}
41
+ resizeMode="contain"
42
+ />
43
+ </View>
44
+ </View>
45
+ );
46
+ };
47
+
48
+ const renderTab = (key, label) => (
49
+ <TouchableOpacity
50
+ style={[styles.tabItem, activeTab === key && styles.activeTabItem]}
51
+ onPress={() => setActiveTab(key)}
52
+ activeOpacity={0.7}
53
+ >
54
+ <Text style={[styles.tabLabelText, activeTab === key && styles.activeTabLabelText]}>{label}</Text>
55
+ </TouchableOpacity>
56
+ );
57
+
58
  useEffect(() => {
59
+ if (!initialResult && imageUri && confirmed) {
60
  performAnalysis();
61
  }
62
+ }, [imageUri, initialResult, confirmed]);
63
 
64
  const performAnalysis = async () => {
65
+ setLoading(true);
66
  try {
67
  const result = await analyzeImage(imageUri);
68
  setAnalysisResult(result);
69
 
 
70
  const scanData = {
71
  id: Date.now().toString(),
72
  timestamp: Date.now(),
 
82
  }
83
  };
84
 
85
+ if (!confirmed) {
86
+ return (
87
+ <View style={styles.container}>
88
+ {renderHeader()}
89
+ <View style={styles.confirmBox}>
90
+ <View style={styles.imageCard}>
91
+ <Image source={{ uri: imageUri }} style={styles.previewFullScreen} />
92
+ <View style={styles.imageOverlay}>
93
+ <Text style={styles.overlayText}>READY FOR AI ANALYSIS</Text>
94
+ </View>
95
+ </View>
96
+ <View style={styles.confirmActions}>
97
+ <Text style={styles.confirmMainTitle}>{translations.analyseNow}</Text>
98
+ <Text style={styles.confirmSubTitle}>
99
+ {language === 'ta' ? "இந்த படத்தை ஆய்வு செய்ய விரும்புகிறீர்களா?" : "Our AI will now check this leaf for 30+ potential issues."}
100
+ </Text>
101
+ <TouchableOpacity
102
+ style={styles.primaryAnalyseBtn}
103
+ onPress={() => setConfirmed(true)}
104
+ >
105
+ <Text style={styles.primaryAnalyseBtnText}>START ANALYSIS</Text>
106
+ </TouchableOpacity>
107
+ <TouchableOpacity
108
+ style={styles.cancelAction}
109
+ onPress={() => navigation.goBack()}
110
+ >
111
+ <Text style={styles.cancelActionText}>{translations.cancel}</Text>
112
+ </TouchableOpacity>
113
+ </View>
114
+ </View>
115
+ </View>
116
+ );
117
+ }
118
+
119
  if (loading) {
120
  return (
121
+ <View style={styles.loaderContainer}>
122
  <ActivityIndicator size="large" color={COLORS.primary} />
123
+ <Text style={styles.loaderText}>{translations.analyzing || "Consulting AI Expert..."}</Text>
124
  </View>
125
  );
126
  }
 
128
  if (!analysisResult) {
129
  return (
130
  <View style={styles.container}>
131
+ <View style={styles.loaderContainer}>
132
+ <Text style={styles.errorTextHeading}>{translations.error || "System Error"}</Text>
133
+ <TouchableOpacity style={styles.errorBtn} onPress={() => navigation.navigate('Home')}>
134
+ <Text style={styles.errorBtnText}>{translations.backHome}</Text>
135
  </TouchableOpacity>
136
  </View>
137
  </View>
 
141
  const { crop, name, isHealthy, severity, symptoms, cause, remedy, remedy_organic, remedy_chemical, prevention, confidence } = analysisResult;
142
 
143
  const getSeverityColor = (sev) => {
144
+ if (!sev) return COLORS.textLight;
145
  switch (sev.toLowerCase()) {
146
+ case 'low': return COLORS.success;
147
+ case 'medium': return COLORS.warning;
148
  case 'high': return COLORS.error;
149
+ default: return COLORS.textLight;
150
  }
151
  };
152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  return (
154
  <View style={styles.container}>
155
+ {renderHeader(isHealthy)}
156
 
157
+ <ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={styles.scrollBody}>
158
+ <View style={styles.imageFrame}>
159
+ <Image source={{ uri: imageUri }} style={styles.mainResultImage} />
160
+ <View style={styles.confidenceFlag}>
161
+ <Text style={styles.flagValue}>{confidence}%</Text>
162
+ <Text style={styles.flagLabel}>CONFIDENCE</Text>
163
+ </View>
164
+ </View>
165
 
166
+ <View style={styles.diagnosisCard}>
167
+ <View style={styles.diagnosisHead}>
168
+ <Text style={styles.cropLabelText}>{crop.toUpperCase()}</Text>
169
+ <Text style={styles.diagnosisMainTitle}>{name[language]}</Text>
 
 
 
 
 
 
 
 
 
170
  </View>
171
 
172
  {!isHealthy && (
173
+ <View style={styles.severityRow}>
174
+ <View style={[styles.severityPill, { backgroundColor: getSeverityColor(severity) + '20' }]}>
175
+ <View style={[styles.severityDot, { backgroundColor: getSeverityColor(severity) }]} />
176
+ <Text style={[styles.severityPillText, { color: getSeverityColor(severity) }]}>
177
+ {translations.severity}: {severity.toUpperCase()}
178
+ </Text>
179
  </View>
 
180
  </View>
181
  )}
182
 
183
+ <View style={styles.infoSection}>
184
+ <Text style={styles.sectionHeaderLabel}>
185
+ {analysisResult.id === 'UNKNOWN' ? translations.unknownStatus : translations.symptoms}
186
+ </Text>
187
+ <Text style={styles.sectionDescText}>{symptoms[language]}</Text>
188
+ </View>
189
 
190
  {!isHealthy && cause && (
191
+ <View style={styles.infoSection}>
192
+ <Text style={styles.sectionHeaderLabel}>{translations.cause}</Text>
193
+ <Text style={styles.sectionDescText}>{cause[language]}</Text>
194
+ </View>
 
 
 
 
 
 
 
 
 
 
 
 
195
  )}
196
 
197
  {isHealthy && remedy && (
198
+ <View style={styles.infoSection}>
199
+ <Text style={styles.sectionHeaderLabel}>{translations.remedy}</Text>
200
+ <Text style={styles.sectionDescText}>{remedy[language]}</Text>
201
+ </View>
202
  )}
203
+ </View>
204
+
205
+ {!isHealthy && (
206
+ <View style={styles.treatmentHub}>
207
+ <Text style={styles.hubTitle}>TREATMENT OPTIONS</Text>
208
+ <View style={styles.tabSelector}>
209
+ {renderTab('organic', analysisResult.id === 'UNKNOWN' ? translations.unknownInstruction : translations.organic)}
210
+ {renderTab('chemical', analysisResult.id === 'UNKNOWN' ? translations.unknownAdvice : translations.chemical)}
211
+ {renderTab('prevention', analysisResult.id === 'UNKNOWN' ? translations.unknownNextSteps : translations.prevention)}
212
+ </View>
213
+
214
+ <View style={styles.remedyDisplay}>
215
+ <Text style={styles.remedyContentText}>
216
+ {activeTab === 'organic' && remedy_organic[language]}
217
+ {activeTab === 'chemical' && remedy_chemical[language]}
218
+ {activeTab === 'prevention' && prevention[language]}
219
+ </Text>
220
+ </View>
221
+ </View>
222
+ )}
223
 
224
+ {analysisResult.diagnosticChecklist && (
225
+ <View style={styles.checklistBoard}>
226
+ <View style={styles.checklistHead}>
227
+ <Text style={styles.checklistHeadTitle}>
228
  {analysisResult.diagnosticChecklist.title[language]}
229
  </Text>
 
 
 
 
 
 
230
  </View>
231
+ {analysisResult.diagnosticChecklist.steps.map((step, index) => (
232
+ <View key={index} style={styles.checklistLine}>
233
+ <View style={styles.checkBullet} />
234
+ <Text style={styles.checklistLineText}>{step[language]}</Text>
235
+ </View>
236
+ ))}
237
+ </View>
238
+ )}
239
 
240
+ <View style={{ height: 40 }} />
 
241
  </ScrollView>
242
 
243
+ <View style={styles.bottomActions}>
244
+ <TouchableOpacity style={styles.returnHomeBtn} onPress={() => navigation.navigate('Home')}>
245
+ <Text style={styles.returnHomeBtnText}>{translations.backHome}</Text>
246
+ </TouchableOpacity>
247
+ </View>
248
  </View>
249
  );
250
  };
 
256
  },
257
  header: {
258
  paddingTop: 50,
259
+ paddingBottom: 25,
260
+ paddingHorizontal: SIZES.padding,
261
  flexDirection: 'row',
262
  alignItems: 'center',
263
+ borderBottomLeftRadius: 35,
264
+ borderBottomRightRadius: 35,
265
+ ...COLORS.shadow.lg,
266
+ },
267
+ headerButton: {
268
+ width: 44,
269
+ height: 44,
270
+ borderRadius: 22,
271
+ backgroundColor: 'rgba(255,255,255,0.2)',
272
+ justifyContent: 'center',
273
+ alignItems: 'center',
274
  },
275
+ headerButtonText: {
276
  fontSize: 24,
277
+ color: COLORS.white,
278
  fontWeight: 'bold',
279
  },
280
+ headerTitleUnit: {
281
+ flex: 1,
282
+ marginLeft: 15,
283
+ },
284
+ headerLabel: {
285
+ fontSize: 20,
286
+ fontWeight: '900',
287
+ color: COLORS.white,
288
+ letterSpacing: 0.5,
289
+ },
290
+ headerStatusSub: {
291
+ fontSize: 10,
292
+ fontWeight: '800',
293
+ color: 'rgba(255,255,255,0.8)',
294
+ letterSpacing: 1,
295
+ marginTop: 2,
296
+ },
297
+ logoCircleHeader: {
298
+ width: 48,
299
+ height: 48,
300
+ backgroundColor: COLORS.white,
301
+ borderRadius: 24,
302
  justifyContent: 'center',
303
  alignItems: 'center',
304
+ ...COLORS.shadow.sm,
305
+ },
306
+ logoImgSmall: {
307
+ width: '70%',
308
+ height: '70%',
309
+ },
310
+ scrollBody: {
311
+ padding: SIZES.padding,
312
+ },
313
+ imageFrame: {
314
+ width: '100%',
315
+ height: 280,
316
+ borderRadius: 30,
317
+ backgroundColor: COLORS.surface,
318
+ ...COLORS.shadow.md,
319
+ overflow: 'hidden',
320
+ marginBottom: 25,
321
  },
322
+ mainResultImage: {
323
  width: '100%',
324
  height: '100%',
325
  },
326
+ confidenceFlag: {
327
+ position: 'absolute',
328
+ bottom: 20,
329
+ right: 20,
330
+ backgroundColor: COLORS.surface,
331
+ paddingHorizontal: 12,
332
+ paddingVertical: 8,
333
+ borderRadius: 15,
334
+ alignItems: 'center',
335
+ borderWidth: 1,
336
+ borderColor: COLORS.border,
337
+ ...COLORS.shadow.sm,
338
  },
339
+ flagValue: {
340
+ fontSize: 18,
341
+ fontWeight: '900',
342
+ color: COLORS.primary,
 
 
 
343
  },
344
+ flagLabel: {
345
+ fontSize: 8,
346
+ fontWeight: '800',
347
+ color: COLORS.textLight,
348
+ letterSpacing: 0.5,
349
  },
350
+ diagnosisCard: {
351
+ backgroundColor: COLORS.surface,
352
+ borderRadius: 30,
353
+ padding: 25,
354
+ marginBottom: 20,
355
+ ...COLORS.shadow.md,
356
+ borderWidth: 1,
357
+ borderColor: COLORS.border,
358
  },
359
+ diagnosisHead: {
360
+ marginBottom: 15,
 
 
 
361
  },
362
+ cropLabelText: {
363
+ fontSize: 12,
364
+ fontWeight: '900',
365
+ color: COLORS.textLight,
366
+ letterSpacing: 1.5,
367
+ marginBottom: 4,
368
+ },
369
+ diagnosisMainTitle: {
370
+ fontSize: 26,
371
+ fontWeight: '900',
372
+ color: COLORS.text,
373
  },
374
+ severityRow: {
375
+ marginBottom: 20,
 
376
  },
377
+ severityPill: {
378
  flexDirection: 'row',
379
  alignItems: 'center',
380
+ alignSelf: 'flex-start',
381
+ paddingHorizontal: 12,
382
+ paddingVertical: 6,
383
+ borderRadius: 12,
384
  },
385
+ severityDot: {
386
+ width: 8,
387
+ height: 8,
388
+ borderRadius: 4,
389
+ marginRight: 8,
390
  },
391
+ severityPillText: {
 
 
392
  fontSize: 12,
393
+ fontWeight: '900',
394
+ letterSpacing: 0.5,
395
  },
396
+ infoSection: {
397
+ marginBottom: 20,
 
398
  },
399
+ sectionHeaderLabel: {
400
+ fontSize: 14,
401
+ fontWeight: '900',
402
  color: COLORS.primary,
403
+ letterSpacing: 1,
404
+ marginBottom: 8,
405
+ textTransform: 'uppercase',
406
  },
407
+ sectionDescText: {
408
  fontSize: 16,
409
  color: COLORS.text,
410
  lineHeight: 24,
411
+ fontWeight: '500',
412
+ },
413
+ treatmentHub: {
414
+ marginBottom: 25,
415
+ },
416
+ hubTitle: {
417
+ fontSize: 14,
418
+ fontWeight: '900',
419
+ color: COLORS.textLight,
420
+ letterSpacing: 1.5,
421
+ marginBottom: 12,
422
+ textAlign: 'center',
423
  },
424
+ tabSelector: {
425
  flexDirection: 'row',
426
+ backgroundColor: 'rgba(0,0,0,0.05)',
427
+ borderRadius: 20,
428
+ padding: 5,
429
+ marginBottom: 15,
430
  },
431
+ tabItem: {
432
  flex: 1,
433
+ paddingVertical: 12,
434
  alignItems: 'center',
435
+ borderRadius: 15,
436
  },
437
+ activeTabItem: {
438
+ backgroundColor: COLORS.surface,
439
+ ...COLORS.shadow.sm,
 
 
 
 
440
  },
441
+ tabLabelText: {
442
+ fontSize: 13,
443
+ fontWeight: '700',
444
+ color: COLORS.textLight,
445
  },
446
+ activeTabLabelText: {
447
+ color: COLORS.primaryDark,
448
+ fontWeight: '900',
449
  },
450
+ remedyDisplay: {
451
+ backgroundColor: COLORS.surface,
452
+ borderRadius: 25,
453
+ padding: 20,
454
+ borderLeftWidth: 6,
 
455
  borderLeftColor: COLORS.primary,
456
+ ...COLORS.shadow.sm,
457
  },
458
+ remedyContentText: {
459
+ fontSize: 15,
460
  color: COLORS.text,
461
  lineHeight: 24,
462
+ fontWeight: '500',
463
  },
464
+ checklistBoard: {
465
+ backgroundColor: COLORS.primaryDark,
466
+ borderRadius: 30,
467
+ padding: 25,
468
+ ...COLORS.shadow.md,
 
 
 
 
 
 
469
  },
470
+ checklistHead: {
471
+ marginBottom: 15,
472
+ borderBottomWidth: 1,
473
+ borderBottomColor: 'rgba(255,255,255,0.1)',
474
+ paddingBottom: 10,
 
 
 
475
  },
476
+ checklistHeadTitle: {
477
  fontSize: 18,
478
+ fontWeight: '900',
479
+ color: COLORS.white,
 
480
  },
481
+ checklistLine: {
482
  flexDirection: 'row',
483
  alignItems: 'flex-start',
484
+ marginBottom: 15,
485
  },
486
+ checkBullet: {
487
+ width: 10,
488
+ height: 10,
489
+ borderRadius: 5,
490
+ backgroundColor: COLORS.secondary,
491
+ marginTop: 6,
492
+ marginRight: 15,
493
  },
494
+ checklistLineText: {
495
  fontSize: 15,
496
+ color: 'rgba(255,255,255,0.9)',
497
  lineHeight: 22,
498
  flex: 1,
499
+ fontWeight: '500',
500
+ },
501
+ bottomActions: {
502
+ padding: SIZES.padding,
503
+ backgroundColor: COLORS.surface,
504
+ borderTopWidth: 1,
505
+ borderTopColor: COLORS.border,
506
+ },
507
+ returnHomeBtn: {
508
+ backgroundColor: COLORS.primary,
509
+ paddingVertical: 18,
510
+ borderRadius: 20,
511
+ alignItems: 'center',
512
+ ...COLORS.shadow.md,
513
+ },
514
+ returnHomeBtnText: {
515
+ color: COLORS.white,
516
+ fontSize: 18,
517
+ fontWeight: '900',
518
+ letterSpacing: 1,
519
  },
520
+ loaderContainer: {
521
  flex: 1,
522
  justifyContent: 'center',
523
  alignItems: 'center',
524
+ backgroundColor: COLORS.background,
525
  },
526
+ loaderText: {
527
  marginTop: 20,
528
+ fontSize: 16,
529
+ color: COLORS.textLight,
530
+ fontWeight: '700',
531
+ letterSpacing: 0.5,
532
+ },
533
+ confirmBox: {
534
+ flex: 1,
535
+ padding: SIZES.padding,
536
+ },
537
+ imageCard: {
538
+ flex: 1.5,
539
+ borderRadius: 35,
540
+ overflow: 'hidden',
541
+ ...COLORS.shadow.lg,
542
+ backgroundColor: COLORS.black,
543
+ },
544
+ previewFullScreen: {
545
+ width: '100%',
546
+ height: '100%',
547
+ opacity: 0.8,
548
+ },
549
+ imageOverlay: {
550
+ position: 'absolute',
551
+ top: 30,
552
+ left: 30,
553
+ backgroundColor: 'rgba(0,0,0,0.5)',
554
+ paddingHorizontal: 12,
555
+ paddingVertical: 6,
556
+ borderRadius: 10,
557
+ borderWidth: 1,
558
+ borderColor: 'rgba(255,255,255,0.3)',
559
+ },
560
+ overlayText: {
561
+ color: COLORS.white,
562
+ fontSize: 10,
563
+ fontWeight: '900',
564
+ letterSpacing: 1,
565
+ },
566
+ confirmActions: {
567
+ flex: 1,
568
+ justifyContent: 'center',
569
+ alignItems: 'center',
570
+ paddingHorizontal: 10,
571
+ },
572
+ confirmMainTitle: {
573
+ fontSize: 28,
574
+ fontWeight: '900',
575
+ color: COLORS.text,
576
+ marginBottom: 10,
577
+ },
578
+ confirmSubTitle: {
579
+ fontSize: 15,
580
+ color: COLORS.textLight,
581
+ textAlign: 'center',
582
+ lineHeight: 22,
583
+ marginBottom: 35,
584
+ },
585
+ primaryAnalyseBtn: {
586
+ backgroundColor: COLORS.primary,
587
+ width: '100%',
588
+ paddingVertical: 20,
589
+ borderRadius: 22,
590
+ alignItems: 'center',
591
+ ...COLORS.shadow.lg,
592
+ },
593
+ primaryAnalyseBtnText: {
594
+ color: COLORS.white,
595
  fontSize: 18,
596
+ fontWeight: '900',
597
+ letterSpacing: 2,
598
+ },
599
+ cancelAction: {
600
+ marginTop: 20,
601
+ padding: 10,
602
+ },
603
+ cancelActionText: {
604
+ color: COLORS.textLight,
605
+ fontSize: 15,
606
+ fontWeight: '700',
607
+ textDecorationLine: 'underline',
608
+ },
609
+ errorTextHeading: {
610
+ fontSize: 20,
611
+ fontWeight: '900',
612
+ color: COLORS.error,
613
+ marginBottom: 20,
614
+ },
615
+ errorBtn: {
616
+ paddingHorizontal: 30,
617
+ paddingVertical: 15,
618
+ backgroundColor: COLORS.primary,
619
+ borderRadius: 15,
620
+ },
621
+ errorBtnText: {
622
+ color: COLORS.white,
623
+ fontWeight: '800',
624
  }
625
  });
626
 
screens/ScannerScreen.js CHANGED
@@ -1,45 +1,74 @@
1
  import React, { useState, useEffect, useRef } from 'react';
2
- import { StyleSheet, Text, View, TouchableOpacity, Dimensions, Animated, StatusBar, ActivityIndicator } from 'react-native';
3
  import { CameraView, useCameraPermissions } from 'expo-camera';
4
  import { COLORS, SIZES, FONTS } from '../constants/theme';
5
  import { TRANSLATIONS } from '../constants/translations';
6
  import { analyzeImage } from '../services/aiService';
7
 
8
  const { width, height } = Dimensions.get('window');
 
9
 
10
  const ScannerScreen = ({ navigation, route }) => {
11
  const language = route.params?.language || 'en';
12
  const t = TRANSLATIONS[language] || TRANSLATIONS['en'];
13
 
14
  const [permission, requestPermission] = useCameraPermissions();
 
15
  const [isScanning, setIsScanning] = useState(true);
16
  const [loading, setLoading] = useState(false);
17
- const [lastScanResult, setLastScanResult] = useState(null);
18
 
19
- // Animation for the scanning pulse
 
20
  const pulseAnim = useRef(new Animated.Value(1)).current;
21
  const cameraRef = useRef(null);
22
 
23
  useEffect(() => {
24
- if (isScanning) {
25
- startPulse();
26
  const interval = setInterval(() => {
27
- if (!loading && isScanning) {
28
  autoCapture();
29
  }
30
- }, 2000); // Polling every 2 seconds for balance between real-time and server load
31
  return () => {
32
  clearInterval(interval);
 
 
 
 
 
 
 
33
  pulseAnim.stopAnimation();
34
  };
35
  }
36
- }, [isScanning, loading]);
37
 
38
- const startPulse = () => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  Animated.loop(
40
  Animated.sequence([
41
  Animated.timing(pulseAnim, {
42
- toValue: 1.2,
43
  duration: 1000,
44
  useNativeDriver: true,
45
  }),
@@ -53,44 +82,58 @@ const ScannerScreen = ({ navigation, route }) => {
53
  };
54
 
55
  const autoCapture = async () => {
56
- if (!cameraRef.current) return;
 
 
 
 
 
57
 
58
  try {
59
  setLoading(true);
 
 
60
  const photo = await cameraRef.current.takePictureAsync({
61
- quality: 0.5, // Lower quality for faster real-time processing
62
  base64: false,
63
  });
64
 
65
  const result = await analyzeImage(photo.uri);
66
 
67
  if (result && result.status === 'success') {
68
- setLastScanResult(result);
69
- // If high confidence, stop and show result
70
- if (result.confidence > 0.85) {
71
  setIsScanning(false);
72
  navigation.navigate('Result', {
73
  imageUri: photo.uri,
74
  analysisResult: result,
75
  language
76
  });
 
 
77
  }
78
  }
79
  } catch (error) {
80
  console.log("Scanner Error:", error);
 
81
  } finally {
82
  setLoading(false);
 
83
  }
84
  };
85
 
86
- if (!permission) return <View />;
87
  if (!permission.granted) {
88
  return (
89
  <View style={styles.container}>
90
- <Text style={styles.text}>{t.cameraPermissionMessage}</Text>
91
- <TouchableOpacity onPress={requestPermission} style={styles.button}>
92
- <Text style={styles.buttonText}>{t.grantPermission}</Text>
93
- </TouchableOpacity>
 
 
 
94
  </View>
95
  );
96
  }
@@ -102,56 +145,124 @@ const ScannerScreen = ({ navigation, route }) => {
102
  style={StyleSheet.absoluteFill}
103
  facing="back"
104
  ref={cameraRef}
 
105
  />
106
 
107
- {/* Scanning Overlay */}
108
- <View style={styles.overlay}>
109
- <View style={styles.header}>
110
- <TouchableOpacity onPress={() => navigation.goBack()} style={styles.backButton}>
111
- <Text style={styles.backIcon}>✕</Text>
112
- </TouchableOpacity>
113
- <Text style={styles.headerText}>{t.scanning || 'Scanning...'}</Text>
114
- </View>
 
 
 
 
 
115
 
116
- <View style={styles.guideContainer}>
117
- <Animated.View style={[
118
- styles.scannerFrame,
119
- { transform: [{ scale: pulseAnim }], borderColor: loading ? COLORS.primary : COLORS.white }
120
- ]}>
121
- <View style={styles.cornerTopLeft} />
122
- <View style={styles.cornerTopRight} />
123
- <View style={styles.cornerBottomLeft} />
124
- <View style={styles.cornerBottomRight} />
125
- </Animated.View>
 
126
  </View>
 
 
 
 
 
 
 
 
 
 
 
127
 
128
- <View style={styles.footer}>
129
- {loading ? (
130
- <View style={styles.loadingContainer}>
131
- <ActivityIndicator size="large" color={COLORS.secondary} />
132
- <Text style={styles.loadingText}>{t.analyzing || 'Analyzing...'}</Text>
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  </View>
134
- ) : (
135
- <View style={styles.infoBox}>
136
- <Text style={styles.guideText}>{t.scannerTip || 'Point camera at leaf for instant diagnosis'}</Text>
137
- {lastScanResult && (
138
- <View style={styles.miniResult}>
139
- <Text style={styles.miniResultText}>
140
- Last Check: {lastScanResult.class} ({(lastScanResult.confidence * 100).toFixed(0)}%)
141
- </Text>
142
- </View>
143
- )}
144
  </View>
145
- )}
 
146
 
147
- <TouchableOpacity
148
- style={styles.manualButton}
149
- onPress={() => setIsScanning(!isScanning)}
150
- >
151
- <Text style={styles.manualButtonText}>
152
- {isScanning ? 'PAUSE' : 'RESUME SCAN'}
 
153
  </Text>
154
- </TouchableOpacity>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  </View>
156
  </View>
157
  </View>
@@ -161,157 +272,264 @@ const ScannerScreen = ({ navigation, route }) => {
161
  const styles = StyleSheet.create({
162
  container: {
163
  flex: 1,
164
- backgroundColor: 'black',
 
 
 
 
 
165
  },
166
- overlay: {
167
  flex: 1,
168
- justify_content: 'space-between',
169
- padding: 20,
170
  },
171
- header: {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  flexDirection: 'row',
173
  alignItems: 'center',
174
- marginTop: 40,
175
  },
176
- backButton: {
177
- padding: 10,
178
- backgroundColor: 'rgba(0,0,0,0.5)',
179
- borderRadius: 20,
 
 
180
  },
181
- backIcon: {
182
- color: 'white',
183
- fontSize: 20,
184
- fontWeight: 'bold',
185
  },
186
- headerText: {
187
- color: 'white',
188
- fontSize: 18,
189
- fontWeight: 'bold',
190
- marginLeft: 20,
 
191
  },
192
- guideContainer: {
193
- flex: 1,
 
 
 
 
 
 
 
 
194
  alignItems: 'center',
 
 
 
 
 
 
 
 
195
  justifyContent: 'center',
 
 
 
 
 
 
 
 
196
  },
197
- scannerFrame: {
198
- width: width * 0.7,
199
- height: width * 0.7,
200
- borderWidth: 2,
201
  borderRadius: 20,
202
- position: 'relative',
 
 
203
  },
204
- cornerTopLeft: {
205
- position: 'absolute',
206
- top: -2,
207
- left: -2,
208
- width: 40,
209
- height: 40,
210
- borderTopWidth: 6,
211
- borderLeftWidth: 6,
212
- borderColor: COLORS.secondary,
213
- borderTopLeftRadius: 20,
214
- },
215
- cornerTopRight: {
216
- position: 'absolute',
217
- top: -2,
218
- right: -2,
219
- width: 40,
220
- height: 40,
221
- borderTopWidth: 6,
222
- borderRightWidth: 6,
223
- borderColor: COLORS.secondary,
224
- borderTopRightRadius: 20,
225
- },
226
- cornerBottomLeft: {
227
- position: 'absolute',
228
- bottom: -2,
229
- left: -2,
230
- width: 40,
231
- height: 40,
232
- borderBottomWidth: 6,
233
- borderLeftWidth: 6,
234
- borderColor: COLORS.secondary,
235
- borderBottomLeftRadius: 20,
236
- },
237
- cornerBottomRight: {
238
- position: 'absolute',
239
- bottom: -2,
240
- right: -2,
241
- width: 40,
242
- height: 40,
243
- borderBottomWidth: 6,
244
- borderRightWidth: 6,
245
- borderColor: COLORS.secondary,
246
- borderBottomRightRadius: 20,
247
- },
248
- footer: {
249
- marginBottom: 40,
250
  alignItems: 'center',
251
  },
252
- infoBox: {
253
- backgroundColor: 'rgba(0,0,0,0.6)',
254
- padding: 15,
255
- borderRadius: 15,
256
- width: '100%',
257
  alignItems: 'center',
258
- marginBottom: 20,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  },
260
- guideText: {
261
- color: 'white',
262
- fontSize: 14,
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  textAlign: 'center',
264
  },
265
- miniResult: {
266
- marginTop: 10,
267
- paddingTop: 10,
268
- borderTopWidth: 1,
269
- borderTopColor: 'rgba(255,255,255,0.2)',
270
  width: '100%',
271
  },
272
- miniResultText: {
273
- color: COLORS.secondary,
274
- fontWeight: 'bold',
275
- textAlign: 'center',
276
- fontSize: 14,
 
 
 
 
277
  },
278
- loadingContainer: {
 
 
 
 
 
 
279
  alignItems: 'center',
280
- marginBottom: 20,
281
  },
282
- loadingText: {
283
- color: COLORS.secondary,
284
- marginTop: 10,
285
- fontWeight: 'bold',
 
 
286
  },
287
- manualButton: {
 
 
 
 
 
288
  backgroundColor: COLORS.white,
289
- paddingVertical: 12,
290
- paddingHorizontal: 30,
291
- borderRadius: 25,
292
  },
293
- manualButtonText: {
294
- color: COLORS.primary,
295
- fontWeight: 'bold',
296
- fontSize: 14,
297
  },
298
- text: {
299
- color: 'white',
300
- textAlign: 'center',
301
- fontSize: 16,
302
- padding: 20,
 
 
303
  },
304
- button: {
305
- backgroundColor: COLORS.secondary,
306
- padding: 15,
307
- borderRadius: 10,
308
- marginHorizontal: 40,
309
  },
310
- buttonText: {
311
- color: 'white',
312
- fontWeight: 'bold',
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  textAlign: 'center',
 
 
314
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  });
316
 
317
  export default ScannerScreen;
 
1
  import React, { useState, useEffect, useRef } from 'react';
2
+ import { StyleSheet, Text, View, TouchableOpacity, Dimensions, Animated, StatusBar, ActivityIndicator, Easing } from 'react-native';
3
  import { CameraView, useCameraPermissions } from 'expo-camera';
4
  import { COLORS, SIZES, FONTS } from '../constants/theme';
5
  import { TRANSLATIONS } from '../constants/translations';
6
  import { analyzeImage } from '../services/aiService';
7
 
8
  const { width, height } = Dimensions.get('window');
9
+ const SCAN_SIZE = width * 0.75;
10
 
11
  const ScannerScreen = ({ navigation, route }) => {
12
  const language = route.params?.language || 'en';
13
  const t = TRANSLATIONS[language] || TRANSLATIONS['en'];
14
 
15
  const [permission, requestPermission] = useCameraPermissions();
16
+ const [scanMode, setScanMode] = useState('auto'); // 'auto' or 'manual'
17
  const [isScanning, setIsScanning] = useState(true);
18
  const [loading, setLoading] = useState(false);
19
+ const [statusMessage, setStatusMessage] = useState('LOOKING FOR LEAVES...');
20
 
21
+ // Animations
22
+ const laserAnim = useRef(new Animated.Value(0)).current;
23
  const pulseAnim = useRef(new Animated.Value(1)).current;
24
  const cameraRef = useRef(null);
25
 
26
  useEffect(() => {
27
+ if (isScanning && scanMode === 'auto') {
28
+ startAnimations();
29
  const interval = setInterval(() => {
30
+ if (!loading && isScanning && scanMode === 'auto') {
31
  autoCapture();
32
  }
33
+ }, 3000);
34
  return () => {
35
  clearInterval(interval);
36
+ laserAnim.stopAnimation();
37
+ pulseAnim.stopAnimation();
38
+ };
39
+ } else if (isScanning && scanMode === 'manual') {
40
+ startAnimations();
41
+ return () => {
42
+ laserAnim.stopAnimation();
43
  pulseAnim.stopAnimation();
44
  };
45
  }
46
+ }, [isScanning, loading, scanMode]);
47
 
48
+ const startAnimations = () => {
49
+ // Laser Sweep
50
+ Animated.loop(
51
+ Animated.sequence([
52
+ Animated.timing(laserAnim, {
53
+ toValue: SCAN_SIZE - 4,
54
+ duration: 2000,
55
+ easing: Easing.inOut(Easing.quad),
56
+ useNativeDriver: true,
57
+ }),
58
+ Animated.timing(laserAnim, {
59
+ toValue: 0,
60
+ duration: 2000,
61
+ easing: Easing.inOut(Easing.quad),
62
+ useNativeDriver: true,
63
+ })
64
+ ])
65
+ ).start();
66
+
67
+ // Frame Pulse
68
  Animated.loop(
69
  Animated.sequence([
70
  Animated.timing(pulseAnim, {
71
+ toValue: 1.05,
72
  duration: 1000,
73
  useNativeDriver: true,
74
  }),
 
82
  };
83
 
84
  const autoCapture = async () => {
85
+ if (!cameraRef.current || loading || !isScanning || scanMode !== 'auto') return;
86
+ performCapture();
87
+ };
88
+
89
+ const performCapture = async () => {
90
+ if (!cameraRef.current || loading) return;
91
 
92
  try {
93
  setLoading(true);
94
+ setStatusMessage(scanMode === 'auto' ? 'ANALYZING DETAILS...' : 'CAPTURING...');
95
+
96
  const photo = await cameraRef.current.takePictureAsync({
97
+ quality: 0.7,
98
  base64: false,
99
  });
100
 
101
  const result = await analyzeImage(photo.uri);
102
 
103
  if (result && result.status === 'success') {
104
+ // In auto mode, we need high confidence to auto-navigate
105
+ // In manual mode, we always navigate on button press
106
+ if (scanMode === 'manual' || (result.confidence > 0.45)) {
107
  setIsScanning(false);
108
  navigation.navigate('Result', {
109
  imageUri: photo.uri,
110
  analysisResult: result,
111
  language
112
  });
113
+ } else {
114
+ setStatusMessage('HOLD STEADY...');
115
  }
116
  }
117
  } catch (error) {
118
  console.log("Scanner Error:", error);
119
+ setStatusMessage('POOR LIGHTING? TRY AGAIN');
120
  } finally {
121
  setLoading(false);
122
+ if (isScanning) setTimeout(() => setStatusMessage(scanMode === 'auto' ? 'LOOKING FOR LEAVES...' : 'READY FOR CAPTURE'), 1000);
123
  }
124
  };
125
 
126
+ if (!permission) return <View style={styles.container} />;
127
  if (!permission.granted) {
128
  return (
129
  <View style={styles.container}>
130
+ <View style={styles.permissionBox}>
131
+ <Text style={styles.permissionIcon}>📷</Text>
132
+ <Text style={styles.text}>{language === 'ta' ? "கேமரா அனுமதி தேவை" : "Camera Access Needed"}</Text>
133
+ <TouchableOpacity onPress={requestPermission} style={styles.grantButton}>
134
+ <Text style={styles.grantButtonText}>{t.grantPermission}</Text>
135
+ </TouchableOpacity>
136
+ </View>
137
  </View>
138
  );
139
  }
 
145
  style={StyleSheet.absoluteFill}
146
  facing="back"
147
  ref={cameraRef}
148
+ shutterSound={false}
149
  />
150
 
151
+ {/* Immersive Overlay */}
152
+ <View style={styles.maskContainer}>
153
+ <View style={styles.maskSide} />
154
+ <View style={styles.maskMiddle}>
155
+ <View style={styles.maskSide} />
156
+ <View style={styles.scanHole}>
157
+ <Animated.View style={[styles.laser, { transform: [{ translateY: laserAnim }] }]} />
158
+ <Animated.View style={[styles.cornerFrame, { transform: [{ scale: pulseAnim }] }]}>
159
+ <View style={[styles.corner, styles.topLeft]} />
160
+ <View style={[styles.corner, styles.topRight]} />
161
+ <View style={[styles.corner, styles.bottomLeft]} />
162
+ <View style={[styles.corner, styles.bottomRight]} />
163
+ </Animated.View>
164
 
165
+ {/* Technical HUD Details */}
166
+ <View style={styles.hudTechnicalLeft}>
167
+ <View style={styles.hudLine} />
168
+ <Text style={styles.hudTechText}>LR-24</Text>
169
+ </View>
170
+ <View style={styles.hudTechnicalRight}>
171
+ <Text style={styles.hudTechText}>AF-ON</Text>
172
+ <View style={styles.hudLine} />
173
+ </View>
174
+ </View>
175
+ <View style={styles.maskSide} />
176
  </View>
177
+ <View style={styles.maskSide} />
178
+ </View>
179
+
180
+ {/* UI UI Controls */}
181
+ <View style={styles.uiContainer}>
182
+ {/* Header Elevation */}
183
+ <View style={styles.topRegion}>
184
+ <View style={styles.appHeaderRow}>
185
+ <TouchableOpacity onPress={() => navigation.goBack()} style={styles.glassBtn}>
186
+ <Text style={styles.glassBtnText}>✕</Text>
187
+ </TouchableOpacity>
188
 
189
+ {/* High-Tech Mode Selector */}
190
+ <View style={styles.premiumSwitch}>
191
+ <TouchableOpacity
192
+ style={[styles.switchTab, scanMode === 'auto' && styles.activeSwitchTab]}
193
+ onPress={() => setScanMode('auto')}
194
+ >
195
+ <Text style={[styles.switchTabText, scanMode === 'auto' && styles.activeSwitchTabText]}>
196
+ {t.autoScan}
197
+ </Text>
198
+ </TouchableOpacity>
199
+ <TouchableOpacity
200
+ style={[styles.switchTab, scanMode === 'manual' && styles.activeSwitchTab]}
201
+ onPress={() => setScanMode('manual')}
202
+ >
203
+ <Text style={[styles.switchTabText, scanMode === 'manual' && styles.activeSwitchTabText]}>
204
+ {t.manualCapture}
205
+ </Text>
206
+ </TouchableOpacity>
207
  </View>
208
+
209
+ <View style={{ width: 44 }} />
210
+ </View>
211
+
212
+ <View style={styles.statusDisplay}>
213
+ <View style={styles.statusPill}>
214
+ <View style={[styles.pulseDot, { backgroundColor: loading ? COLORS.warning : (scanMode === 'auto' ? '#4ade80' : '#fbbf24') }]} />
215
+ <Text style={styles.statusPillText}>{statusMessage}</Text>
 
 
216
  </View>
217
+ </View>
218
+ </View>
219
 
220
+ {/* Footer elevation */}
221
+ <View style={styles.bottomRegion}>
222
+ <View style={styles.hintBox}>
223
+ <Text style={styles.instructionText}>
224
+ {scanMode === 'auto'
225
+ ? (language === 'ta' ? "இலையை சட்டத்திற்குள் வைக்கவும்" : "AI IS LOOKING FOR DISEASES AUTOMATICALLY")
226
+ : (language === 'ta' ? "புகைப்படம் எடுக்க பட்டனை அழுத்தவும்" : "TAP TO CAPTURE MANUALLY")}
227
  </Text>
228
+ </View>
229
+
230
+ <View style={styles.controlCenter}>
231
+ <TouchableOpacity style={styles.secondaryCircle} onPress={() => navigation.navigate('About')}>
232
+ <Text style={{ fontSize: 24 }}>❓</Text>
233
+ </TouchableOpacity>
234
+
235
+ <View style={styles.mainShutterOuter}>
236
+ <TouchableOpacity
237
+ style={[
238
+ styles.masterShutter,
239
+ loading && styles.shutterBusy,
240
+ scanMode === 'auto' && styles.shutterAutoMode
241
+ ]}
242
+ onPress={performCapture}
243
+ disabled={loading}
244
+ >
245
+ <View style={[styles.shutterInnerRing, scanMode === 'auto' && styles.shutterInnerAutoRing]}>
246
+ {loading ? (
247
+ <ActivityIndicator color="white" />
248
+ ) : (
249
+ scanMode === 'manual' ? (
250
+ <View style={styles.manualCore} />
251
+ ) : (
252
+ <Text style={styles.robotIcon}>🤖</Text>
253
+ )
254
+ )}
255
+ </View>
256
+ </TouchableOpacity>
257
+ </View>
258
+
259
+ <TouchableOpacity
260
+ style={styles.secondaryCircle}
261
+ onPress={() => setIsScanning(!isScanning)}
262
+ >
263
+ <Text style={{ fontSize: 24 }}>{isScanning ? '⏸️' : '▶️'}</Text>
264
+ </TouchableOpacity>
265
+ </View>
266
  </View>
267
  </View>
268
  </View>
 
272
  const styles = StyleSheet.create({
273
  container: {
274
  flex: 1,
275
+ backgroundColor: '#000',
276
+ },
277
+ maskContainer: {
278
+ ...StyleSheet.absoluteFillObject,
279
+ justifyContent: 'center',
280
+ alignItems: 'center',
281
  },
282
+ maskSide: {
283
  flex: 1,
284
+ width: '100%',
285
+ backgroundColor: 'rgba(0,0,0,0.65)',
286
  },
287
+ maskMiddle: {
288
+ flexDirection: 'row',
289
+ height: SCAN_SIZE,
290
+ },
291
+ scanHole: {
292
+ width: SCAN_SIZE,
293
+ height: SCAN_SIZE,
294
+ backgroundColor: 'transparent',
295
+ overflow: 'hidden',
296
+ },
297
+ cornerFrame: {
298
+ ...StyleSheet.absoluteFillObject,
299
+ },
300
+ corner: {
301
+ position: 'absolute',
302
+ width: 32,
303
+ height: 32,
304
+ borderColor: '#4ade80',
305
+ },
306
+ topLeft: { top: 0, left: 0, borderTopWidth: 5, borderLeftWidth: 5, borderTopLeftRadius: 18 },
307
+ topRight: { top: 0, right: 0, borderTopWidth: 5, borderRightWidth: 5, borderTopRightRadius: 18 },
308
+ bottomLeft: { bottom: 0, left: 0, borderBottomWidth: 5, borderLeftWidth: 5, borderBottomLeftRadius: 18 },
309
+ bottomRight: { bottom: 0, right: 0, borderBottomWidth: 5, borderRightWidth: 5, borderBottomRightRadius: 18 },
310
+ laser: {
311
+ height: 4,
312
+ width: '100%',
313
+ backgroundColor: '#4ade80',
314
+ shadowColor: '#4ade80',
315
+ shadowOffset: { width: 0, height: 0 },
316
+ shadowOpacity: 1,
317
+ shadowRadius: 15,
318
+ zIndex: 10,
319
+ },
320
+ hudTechnicalLeft: {
321
+ position: 'absolute',
322
+ left: 20,
323
+ top: '40%',
324
  flexDirection: 'row',
325
  alignItems: 'center',
 
326
  },
327
+ hudTechnicalRight: {
328
+ position: 'absolute',
329
+ right: 20,
330
+ top: '40%',
331
+ flexDirection: 'row',
332
+ alignItems: 'center',
333
  },
334
+ hudLine: {
335
+ width: 30,
336
+ height: 1,
337
+ backgroundColor: 'rgba(74, 222, 128, 0.5)',
338
  },
339
+ hudTechText: {
340
+ color: 'rgba(74, 222, 128, 0.7)',
341
+ fontSize: 8,
342
+ fontWeight: '900',
343
+ marginHorizontal: 8,
344
+ letterSpacing: 2,
345
  },
346
+ uiContainer: {
347
+ ...StyleSheet.absoluteFillObject,
348
+ justifyContent: 'space-between',
349
+ paddingVertical: 50,
350
+ },
351
+ topRegion: {
352
+ gap: 20,
353
+ },
354
+ appHeaderRow: {
355
+ flexDirection: 'row',
356
  alignItems: 'center',
357
+ justifyContent: 'space-between',
358
+ paddingHorizontal: 25,
359
+ },
360
+ glassBtn: {
361
+ width: 44,
362
+ height: 44,
363
+ borderRadius: 14,
364
+ backgroundColor: 'rgba(255,255,255,0.15)',
365
  justifyContent: 'center',
366
+ alignItems: 'center',
367
+ borderWidth: 1,
368
+ borderColor: 'rgba(255,255,255,0.2)',
369
+ },
370
+ glassBtnText: {
371
+ color: COLORS.white,
372
+ fontSize: 18,
373
+ fontWeight: 'bold',
374
  },
375
+ premiumSwitch: {
376
+ flexDirection: 'row',
377
+ backgroundColor: 'rgba(0,0,0,0.5)',
 
378
  borderRadius: 20,
379
+ padding: 4,
380
+ borderWidth: 1,
381
+ borderColor: 'rgba(255,255,255,0.15)',
382
  },
383
+ switchTab: {
384
+ paddingHorizontal: 22,
385
+ paddingVertical: 8,
386
+ borderRadius: 16,
387
+ },
388
+ activeSwitchTab: {
389
+ backgroundColor: COLORS.white,
390
+ },
391
+ switchTabText: {
392
+ color: COLORS.white,
393
+ fontSize: 11,
394
+ fontWeight: '900',
395
+ letterSpacing: 1,
396
+ },
397
+ activeSwitchTabText: {
398
+ color: COLORS.primaryDark,
399
+ },
400
+ statusDisplay: {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  alignItems: 'center',
402
  },
403
+ statusPill: {
404
+ flexDirection: 'row',
 
 
 
405
  alignItems: 'center',
406
+ backgroundColor: 'rgba(0,0,0,0.7)',
407
+ paddingHorizontal: 18,
408
+ paddingVertical: 10,
409
+ borderRadius: 25,
410
+ borderWidth: 1,
411
+ borderColor: 'rgba(74, 222, 128, 0.3)',
412
+ ...COLORS.shadow.md,
413
+ },
414
+ pulseDot: {
415
+ width: 10,
416
+ height: 10,
417
+ borderRadius: 5,
418
+ marginRight: 12,
419
+ },
420
+ statusPillText: {
421
+ color: COLORS.white,
422
+ fontSize: 12,
423
+ fontWeight: '900',
424
+ letterSpacing: 1.5,
425
  },
426
+ bottomRegion: {
427
+ alignItems: 'center',
428
+ paddingHorizontal: 25,
429
+ },
430
+ hintBox: {
431
+ marginBottom: 40,
432
+ backgroundColor: 'rgba(0,0,0,0.4)',
433
+ paddingHorizontal: 15,
434
+ paddingVertical: 8,
435
+ borderRadius: 12,
436
+ },
437
+ instructionText: {
438
+ color: 'rgba(255,255,255,0.9)',
439
+ fontSize: 11,
440
+ fontWeight: '800',
441
+ letterSpacing: 1,
442
  textAlign: 'center',
443
  },
444
+ controlCenter: {
445
+ flexDirection: 'row',
446
+ alignItems: 'center',
447
+ justifyContent: 'space-around',
 
448
  width: '100%',
449
  },
450
+ secondaryCircle: {
451
+ width: 60,
452
+ height: 60,
453
+ borderRadius: 30,
454
+ backgroundColor: 'rgba(255,255,255,0.15)',
455
+ justifyContent: 'center',
456
+ alignItems: 'center',
457
+ borderWidth: 1,
458
+ borderColor: 'rgba(255,255,255,0.1)',
459
  },
460
+ mainShutterOuter: {
461
+ width: 100,
462
+ height: 100,
463
+ borderRadius: 50,
464
+ borderWidth: 3,
465
+ borderColor: 'rgba(255,255,255,0.3)',
466
+ justifyContent: 'center',
467
  alignItems: 'center',
 
468
  },
469
+ masterShutter: {
470
+ width: 84,
471
+ height: 84,
472
+ borderRadius: 42,
473
+ backgroundColor: 'rgba(255,255,255,0.1)',
474
+ padding: 5,
475
  },
476
+ shutterAutoMode: {
477
+ opacity: 0.8,
478
+ },
479
+ shutterInnerRing: {
480
+ flex: 1,
481
+ borderRadius: 37,
482
  backgroundColor: COLORS.white,
483
+ justifyContent: 'center',
484
+ alignItems: 'center',
 
485
  },
486
+ shutterInnerAutoRing: {
487
+ backgroundColor: 'rgba(255,255,255,0.2)',
 
 
488
  },
489
+ manualCore: {
490
+ width: 60,
491
+ height: 60,
492
+ borderRadius: 30,
493
+ backgroundColor: COLORS.white,
494
+ borderWidth: 4,
495
+ borderColor: 'rgba(0,0,0,0.05)',
496
  },
497
+ robotIcon: {
498
+ fontSize: 34,
 
 
 
499
  },
500
+ shutterBusy: {
501
+ opacity: 0.5,
502
+ },
503
+ permissionBox: {
504
+ flex: 1,
505
+ justifyContent: 'center',
506
+ alignItems: 'center',
507
+ padding: 30,
508
+ },
509
+ permissionIcon: {
510
+ fontSize: 60,
511
+ marginBottom: 20,
512
+ },
513
+ text: {
514
+ color: COLORS.white,
515
+ fontSize: 18,
516
  textAlign: 'center',
517
+ marginBottom: 30,
518
+ fontWeight: '900',
519
  },
520
+ grantButton: {
521
+ backgroundColor: COLORS.primary,
522
+ paddingHorizontal: 45,
523
+ paddingVertical: 18,
524
+ borderRadius: 30,
525
+ ...COLORS.shadow.md,
526
+ },
527
+ grantButtonText: {
528
+ color: COLORS.white,
529
+ fontWeight: '900',
530
+ fontSize: 16,
531
+ letterSpacing: 1,
532
+ }
533
  });
534
 
535
  export default ScannerScreen;
screens/SchemesScreen.js CHANGED
@@ -1,5 +1,5 @@
1
- import React, { useState } from 'react';
2
- import { StyleSheet, Text, View, ScrollView, TouchableOpacity, SafeAreaView, StatusBar, Modal } from 'react-native';
3
  import { COLORS, SIZES } from '../constants/theme';
4
  import { TRANSLATIONS } from '../constants/translations';
5
 
@@ -154,6 +154,12 @@ const SchemesScreen = ({ route, navigation }) => {
154
  const [selectedScheme, setSelectedScheme] = useState(null);
155
  const [modalVisible, setModalVisible] = useState(false);
156
 
 
 
 
 
 
 
157
  const openSchemeDetail = (scheme) => {
158
  setSelectedScheme(scheme);
159
  setModalVisible(true);
@@ -165,93 +171,119 @@ const SchemesScreen = ({ route, navigation }) => {
165
  onPress={() => openSchemeDetail(scheme)}
166
  activeOpacity={0.7}
167
  >
168
- <View style={styles.schemeIconContainer}>
169
- <Text style={styles.schemeIcon}>{scheme.icon}</Text>
170
  </View>
171
- <Text style={styles.schemeName}>{scheme.name[language]}</Text>
 
 
 
 
 
 
172
  </TouchableOpacity>
173
  );
174
 
175
  return (
176
- <SafeAreaView style={styles.container}>
177
- <StatusBar backgroundColor={COLORS.white} barStyle="dark-content" />
178
-
179
- {/* Header */}
180
- <View style={styles.header}>
181
- <Text style={styles.appName}>GREEN DOCTOR</Text>
182
- <TouchableOpacity
183
- onPress={() => navigation.navigate('Language')}
184
- style={styles.languageButton}
185
- >
186
- <Text style={styles.languageIcon}>🌐</Text>
187
- </TouchableOpacity>
188
- </View>
189
 
190
- {/* Title */}
191
- <View style={styles.titleContainer}>
192
- <Text style={styles.pageTitle}>{t.govtSchemes.toUpperCase()}</Text>
 
 
 
 
 
 
 
 
 
193
  </View>
194
 
195
- {/* Schemes List */}
196
  <ScrollView
197
  style={styles.scrollView}
198
  contentContainerStyle={styles.scrollContent}
199
  showsVerticalScrollIndicator={false}
200
  >
201
- {SCHEMES_DATA.map((scheme) => (
202
- <SchemeCard key={scheme.id} scheme={scheme} />
203
- ))}
204
- <View style={{ height: 30 }} />
 
 
 
205
  </ScrollView>
206
 
207
- {/* Scheme Detail Modal */}
208
  <Modal
209
  animationType="slide"
210
  transparent={false}
211
  visible={modalVisible}
212
  onRequestClose={() => setModalVisible(false)}
213
  >
214
- <SafeAreaView style={styles.modalContainer}>
215
- <View style={styles.modalHeader}>
216
  <TouchableOpacity
217
  onPress={() => setModalVisible(false)}
218
- style={styles.closeButton}
219
  >
220
- <Text style={styles.closeButtonText}>✕</Text>
221
  </TouchableOpacity>
222
- <Text style={styles.modalTitle}>
223
- {selectedScheme?.name[language]}
224
  </Text>
225
  </View>
226
 
227
- <ScrollView style={styles.modalScroll} showsVerticalScrollIndicator={false}>
228
  {selectedScheme && (
229
- <View style={styles.modalContent}>
230
- <View style={styles.schemeIconLarge}>
231
- <Text style={styles.schemeIconLargeText}>{selectedScheme.icon}</Text>
 
 
 
 
 
 
232
  </View>
233
 
234
- <View style={styles.detailSection}>
235
- <Text style={styles.detailSectionTitle}>📋 {t.aboutTitle || 'About'}</Text>
236
- <Text style={styles.detailText}>{selectedScheme.description[language]}</Text>
 
 
237
  </View>
238
 
239
- <View style={styles.detailSection}>
240
- <Text style={styles.detailSectionTitle}>✅ Eligibility</Text>
241
- <Text style={styles.detailText}>{selectedScheme.eligibility[language]}</Text>
 
 
 
 
 
 
242
  </View>
243
 
244
- <View style={styles.detailSection}>
245
- <Text style={styles.detailSectionTitle}>🎁 Benefits</Text>
246
- <Text style={styles.detailText}>{selectedScheme.benefits[language]}</Text>
 
 
247
  </View>
248
 
249
- <View style={styles.detailSection}>
250
- <Text style={styles.detailSectionTitle}>📝 How to Apply</Text>
251
- <Text style={styles.detailText}>{selectedScheme.howToApply[language]}</Text>
252
- </View>
 
 
 
 
253
 
254
- <View style={{ height: 40 }} />
255
  </View>
256
  )}
257
  </ScrollView>
@@ -264,146 +296,250 @@ const SchemesScreen = ({ route, navigation }) => {
264
  const styles = StyleSheet.create({
265
  container: {
266
  flex: 1,
267
- backgroundColor: '#E8F5E9',
268
  },
269
- header: {
270
- backgroundColor: COLORS.white,
271
- paddingVertical: 15,
272
- paddingHorizontal: 20,
 
 
 
 
 
 
273
  flexDirection: 'row',
 
274
  justifyContent: 'space-between',
 
 
 
 
 
 
 
 
275
  alignItems: 'center',
276
- borderBottomWidth: 1,
277
- borderBottomColor: '#e0e0e0',
278
  },
279
- appName: {
280
- fontSize: 18,
 
281
  fontWeight: 'bold',
282
- color: COLORS.primary,
283
- },
284
- languageButton: {
285
- padding: 5,
286
  },
287
- languageIcon: {
288
- fontSize: 24,
 
 
 
289
  },
290
- titleContainer: {
291
- backgroundColor: COLORS.white,
292
- paddingVertical: 20,
293
- paddingHorizontal: 20,
 
294
  alignItems: 'center',
295
  },
296
- pageTitle: {
297
- fontSize: 24,
298
- fontWeight: 'bold',
299
- color: '#000',
300
- letterSpacing: 1,
301
  },
302
  scrollView: {
303
  flex: 1,
304
  },
305
  scrollContent: {
306
- paddingHorizontal: 20,
307
- paddingTop: 20,
308
  },
309
- schemeCard: {
310
- backgroundColor: COLORS.white,
311
- borderRadius: 25,
312
- padding: 16,
 
 
 
 
313
  marginBottom: 15,
 
 
 
314
  flexDirection: 'row',
315
  alignItems: 'center',
316
- elevation: 2,
317
- shadowColor: '#000',
318
- shadowOffset: { width: 0, height: 1 },
319
- shadowOpacity: 0.1,
320
- shadowRadius: 2,
321
- borderWidth: 1.5,
322
- borderColor: '#4CAF50',
323
- },
324
- schemeIconContainer: {
325
- width: 50,
326
- height: 50,
327
  borderRadius: 25,
328
- backgroundColor: '#E8F5E9',
 
 
 
 
 
 
 
 
 
 
329
  justifyContent: 'center',
330
  alignItems: 'center',
331
- marginRight: 15,
332
  },
333
- schemeIcon: {
334
  fontSize: 28,
335
  },
336
- schemeName: {
337
- fontSize: 16,
338
- fontWeight: 'bold',
339
- color: '#000',
340
  flex: 1,
341
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  // Modal Styles
343
- modalContainer: {
344
  flex: 1,
345
  backgroundColor: COLORS.background,
346
  },
347
- modalHeader: {
348
- backgroundColor: COLORS.primary,
349
  paddingVertical: 15,
350
- paddingHorizontal: 20,
351
  flexDirection: 'row',
352
  alignItems: 'center',
353
  },
354
- closeButton: {
 
 
 
 
 
 
355
  marginRight: 15,
356
- padding: 5,
357
  },
358
- closeButtonText: {
359
- fontSize: 24,
360
  color: COLORS.white,
361
  fontWeight: 'bold',
362
  },
363
- modalTitle: {
364
  fontSize: 18,
365
- fontWeight: 'bold',
366
  color: COLORS.white,
367
  flex: 1,
368
  },
369
- modalScroll: {
370
  flex: 1,
371
  },
372
- modalContent: {
 
 
 
 
 
 
 
373
  padding: 20,
 
 
 
 
374
  },
375
- schemeIconLarge: {
376
- width: 80,
377
- height: 80,
378
- borderRadius: 40,
379
- backgroundColor: COLORS.primary + '20',
380
  justifyContent: 'center',
381
  alignItems: 'center',
382
- alignSelf: 'center',
383
- marginBottom: 20,
384
  },
385
- schemeIconLargeText: {
386
- fontSize: 40,
387
  },
388
- detailSection: {
389
- backgroundColor: COLORS.white,
390
- borderRadius: 12,
391
- padding: 16,
392
- marginBottom: 15,
393
- borderLeftWidth: 4,
394
- borderLeftColor: COLORS.primary,
395
  },
396
- detailSectionTitle: {
397
- fontSize: 18,
398
- fontWeight: 'bold',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
  color: COLORS.primary,
400
- marginBottom: 10,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  },
402
- detailText: {
403
- fontSize: 15,
 
 
 
 
 
 
 
404
  color: COLORS.text,
405
- lineHeight: 24,
 
 
 
 
 
 
 
 
 
406
  },
 
 
 
 
 
 
407
  });
408
 
409
  export default SchemesScreen;
 
1
+ import { StyleSheet, Text, View, ScrollView, TouchableOpacity, StatusBar, Modal, Linking } from 'react-native';
2
+ import { SafeAreaView } from 'react-native-safe-area-context';
3
  import { COLORS, SIZES } from '../constants/theme';
4
  import { TRANSLATIONS } from '../constants/translations';
5
 
 
154
  const [selectedScheme, setSelectedScheme] = useState(null);
155
  const [modalVisible, setModalVisible] = useState(false);
156
 
157
+ const handleApply = (url) => {
158
+ if (url) {
159
+ Linking.openURL(url);
160
+ }
161
+ };
162
+
163
  const openSchemeDetail = (scheme) => {
164
  setSelectedScheme(scheme);
165
  setModalVisible(true);
 
171
  onPress={() => openSchemeDetail(scheme)}
172
  activeOpacity={0.7}
173
  >
174
+ <View style={styles.schemeIconBox}>
175
+ <Text style={styles.schemeIconEmoji}>{scheme.icon}</Text>
176
  </View>
177
+ <View style={styles.schemeInfo}>
178
+ <Text style={styles.schemeTitleText}>{scheme.name[language]}</Text>
179
+ <Text style={styles.schemeSubtitleText} numberOfLines={2}>
180
+ {scheme.shortDesc[language]}
181
+ </Text>
182
+ </View>
183
+ <Text style={styles.schemeArrow}>›</Text>
184
  </TouchableOpacity>
185
  );
186
 
187
  return (
188
+ <SafeAreaView style={styles.container} edges={['right', 'left', 'top']}>
189
+ <StatusBar backgroundColor={COLORS.primary} barStyle="light-content" />
 
 
 
 
 
 
 
 
 
 
 
190
 
191
+ {/* Immersive Header */}
192
+ <View style={styles.premiumHeader}>
193
+ <View style={styles.headerTopRow}>
194
+ <TouchableOpacity onPress={() => navigation.goBack()} style={styles.backButton}>
195
+ <Text style={styles.backButtonText}>←</Text>
196
+ </TouchableOpacity>
197
+ <Text style={styles.headerTitle}>{t.govtSchemes}</Text>
198
+ <View style={{ width: 44 }} />
199
+ </View>
200
+ <View style={styles.headerSearchPlaceholder}>
201
+ <Text style={styles.searchLabel}>OFFICIAL GOVERNMENT INITIATIVES</Text>
202
+ </View>
203
  </View>
204
 
 
205
  <ScrollView
206
  style={styles.scrollView}
207
  contentContainerStyle={styles.scrollContent}
208
  showsVerticalScrollIndicator={false}
209
  >
210
+ <View style={styles.listSection}>
211
+ <Text style={styles.sectionHeading}>AVAILABLE PROGRAMS</Text>
212
+ {SCHEMES_DATA.map((scheme) => (
213
+ <SchemeCard key={scheme.id} scheme={scheme} />
214
+ ))}
215
+ </View>
216
+ <View style={{ height: 40 }} />
217
  </ScrollView>
218
 
219
+ {/* Scheme Detail Modal - Redesigned as a Premium Over Sheet */}
220
  <Modal
221
  animationType="slide"
222
  transparent={false}
223
  visible={modalVisible}
224
  onRequestClose={() => setModalVisible(false)}
225
  >
226
+ <SafeAreaView style={styles.modalViewContainer}>
227
+ <View style={styles.modalPremiumHeader}>
228
  <TouchableOpacity
229
  onPress={() => setModalVisible(false)}
230
+ style={styles.modalBackBtn}
231
  >
232
+ <Text style={styles.modalBackBtnText}>✕</Text>
233
  </TouchableOpacity>
234
+ <Text style={styles.modalHeaderTitle} numberOfLines={1}>
235
+ {selectedScheme?.name?.[language] || ""}
236
  </Text>
237
  </View>
238
 
239
+ <ScrollView style={styles.modalInnerScroll} showsVerticalScrollIndicator={false}>
240
  {selectedScheme && (
241
+ <View style={styles.detailWrapper}>
242
+ <View style={styles.heroFeature}>
243
+ <View style={styles.heroEmojiCircle}>
244
+ <Text style={styles.heroEmojiText}>{selectedScheme.icon}</Text>
245
+ </View>
246
+ <View style={styles.heroMeta}>
247
+ <Text style={styles.heroTag}>VERIFIED SCHEME</Text>
248
+ <Text style={styles.heroTitleMain}>{selectedScheme.name[language]}</Text>
249
+ </View>
250
  </View>
251
 
252
+ <View style={styles.contentBlock}>
253
+ <View style={styles.infoPill}>
254
+ <Text style={styles.pillLabel}>📋 PROGRAM OVERVIEW</Text>
255
+ </View>
256
+ <Text style={styles.bodyPara}>{selectedScheme.description[language]}</Text>
257
  </View>
258
 
259
+ <View style={styles.gridBoard}>
260
+ <View style={styles.gridItem}>
261
+ <Text style={styles.gridLabel}>✅ ELIGIBILITY</Text>
262
+ <Text style={styles.gridValue}>{selectedScheme.eligibility[language]}</Text>
263
+ </View>
264
+ <View style={styles.gridItem}>
265
+ <Text style={styles.gridLabel}>🎁 KEY BENEFITS</Text>
266
+ <Text style={styles.gridValue}>{selectedScheme.benefits[language]}</Text>
267
+ </View>
268
  </View>
269
 
270
+ <View style={[styles.contentBlock, { backgroundColor: COLORS.primaryDark, borderRadius: 25, padding: 25 }]}>
271
+ <Text style={[styles.pillLabel, { color: COLORS.secondary }]}>📝 APPLICATION PROCESS</Text>
272
+ <Text style={[styles.bodyPara, { color: 'rgba(255,255,255,0.9)', marginTop: 10 }]}>
273
+ {selectedScheme.howToApply[language]}
274
+ </Text>
275
  </View>
276
 
277
+ {t.schemeLinks && t.schemeLinks[selectedScheme.id] && (
278
+ <TouchableOpacity
279
+ style={styles.ctaButton}
280
+ onPress={() => handleApply(t.schemeLinks[selectedScheme.id])}
281
+ >
282
+ <Text style={styles.ctaButtonText}>{t.applyOnline}</Text>
283
+ </TouchableOpacity>
284
+ )}
285
 
286
+ <View style={{ height: 60 }} />
287
  </View>
288
  )}
289
  </ScrollView>
 
296
  const styles = StyleSheet.create({
297
  container: {
298
  flex: 1,
299
+ backgroundColor: COLORS.background,
300
  },
301
+ premiumHeader: {
302
+ backgroundColor: COLORS.primary,
303
+ paddingTop: 10,
304
+ paddingBottom: 25,
305
+ paddingHorizontal: SIZES.padding,
306
+ borderBottomLeftRadius: 35,
307
+ borderBottomRightRadius: 35,
308
+ ...COLORS.shadow.lg,
309
+ },
310
+ headerTopRow: {
311
  flexDirection: 'row',
312
+ alignItems: 'center',
313
  justifyContent: 'space-between',
314
+ marginBottom: 20,
315
+ },
316
+ backButton: {
317
+ width: 44,
318
+ height: 44,
319
+ borderRadius: 22,
320
+ backgroundColor: 'rgba(255,255,255,0.2)',
321
+ justifyContent: 'center',
322
  alignItems: 'center',
 
 
323
  },
324
+ backButtonText: {
325
+ fontSize: 24,
326
+ color: COLORS.white,
327
  fontWeight: 'bold',
 
 
 
 
328
  },
329
+ headerTitle: {
330
+ fontSize: 20,
331
+ fontWeight: '900',
332
+ color: COLORS.white,
333
+ letterSpacing: 0.5,
334
  },
335
+ headerSearchPlaceholder: {
336
+ backgroundColor: 'rgba(0,0,0,0.15)',
337
+ paddingVertical: 8,
338
+ paddingHorizontal: 15,
339
+ borderRadius: 12,
340
  alignItems: 'center',
341
  },
342
+ searchLabel: {
343
+ color: 'rgba(255,255,255,0.6)',
344
+ fontSize: 10,
345
+ fontWeight: '900',
346
+ letterSpacing: 2,
347
  },
348
  scrollView: {
349
  flex: 1,
350
  },
351
  scrollContent: {
352
+ padding: SIZES.padding,
 
353
  },
354
+ listSection: {
355
+ paddingBottom: 20,
356
+ },
357
+ sectionHeading: {
358
+ fontSize: 12,
359
+ fontWeight: '900',
360
+ color: COLORS.textLight,
361
+ letterSpacing: 1.5,
362
  marginBottom: 15,
363
+ marginLeft: 5,
364
+ },
365
+ schemeCard: {
366
  flexDirection: 'row',
367
  alignItems: 'center',
368
+ backgroundColor: COLORS.surface,
 
 
 
 
 
 
 
 
 
 
369
  borderRadius: 25,
370
+ padding: 18,
371
+ marginBottom: 15,
372
+ borderWidth: 1,
373
+ borderColor: COLORS.border,
374
+ ...COLORS.shadow.sm,
375
+ },
376
+ schemeIconBox: {
377
+ width: 56,
378
+ height: 56,
379
+ borderRadius: 18,
380
+ backgroundColor: COLORS.primary + '10',
381
  justifyContent: 'center',
382
  alignItems: 'center',
383
+ marginRight: 18,
384
  },
385
+ schemeIconEmoji: {
386
  fontSize: 28,
387
  },
388
+ schemeInfo: {
 
 
 
389
  flex: 1,
390
  },
391
+ schemeTitleText: {
392
+ fontSize: 17,
393
+ fontWeight: '800',
394
+ color: COLORS.text,
395
+ marginBottom: 4,
396
+ },
397
+ schemeSubtitleText: {
398
+ fontSize: 12,
399
+ color: COLORS.textLight,
400
+ fontWeight: '500',
401
+ lineHeight: 18,
402
+ },
403
+ schemeArrow: {
404
+ fontSize: 24,
405
+ color: COLORS.primary,
406
+ opacity: 0.3,
407
+ fontWeight: '300',
408
+ marginLeft: 10,
409
+ },
410
  // Modal Styles
411
+ modalViewContainer: {
412
  flex: 1,
413
  backgroundColor: COLORS.background,
414
  },
415
+ modalPremiumHeader: {
416
+ backgroundColor: COLORS.primaryDark,
417
  paddingVertical: 15,
418
+ paddingHorizontal: SIZES.padding,
419
  flexDirection: 'row',
420
  alignItems: 'center',
421
  },
422
+ modalBackBtn: {
423
+ width: 36,
424
+ height: 36,
425
+ borderRadius: 18,
426
+ backgroundColor: 'rgba(255,255,255,0.15)',
427
+ justifyContent: 'center',
428
+ alignItems: 'center',
429
  marginRight: 15,
 
430
  },
431
+ modalBackBtnText: {
432
+ fontSize: 18,
433
  color: COLORS.white,
434
  fontWeight: 'bold',
435
  },
436
+ modalHeaderTitle: {
437
  fontSize: 18,
438
+ fontWeight: '800',
439
  color: COLORS.white,
440
  flex: 1,
441
  },
442
+ modalInnerScroll: {
443
  flex: 1,
444
  },
445
+ detailWrapper: {
446
+ padding: SIZES.padding,
447
+ },
448
+ heroFeature: {
449
+ flexDirection: 'row',
450
+ alignItems: 'center',
451
+ backgroundColor: COLORS.surface,
452
+ borderRadius: 30,
453
  padding: 20,
454
+ marginBottom: 25,
455
+ ...COLORS.shadow.md,
456
+ borderWidth: 1,
457
+ borderColor: COLORS.border,
458
  },
459
+ heroEmojiCircle: {
460
+ width: 70,
461
+ height: 70,
462
+ borderRadius: 35,
463
+ backgroundColor: COLORS.primary + '15',
464
  justifyContent: 'center',
465
  alignItems: 'center',
466
+ marginRight: 20,
 
467
  },
468
+ heroEmojiText: {
469
+ fontSize: 36,
470
  },
471
+ heroMeta: {
472
+ flex: 1,
 
 
 
 
 
473
  },
474
+ heroTag: {
475
+ fontSize: 9,
476
+ fontWeight: '900',
477
+ color: COLORS.success,
478
+ letterSpacing: 2,
479
+ marginBottom: 4,
480
+ },
481
+ heroTitleMain: {
482
+ fontSize: 22,
483
+ fontWeight: '900',
484
+ color: COLORS.text,
485
+ },
486
+ contentBlock: {
487
+ marginBottom: 25,
488
+ },
489
+ pillLabel: {
490
+ fontSize: 11,
491
+ fontWeight: '900',
492
  color: COLORS.primary,
493
+ letterSpacing: 1.5,
494
+ marginBottom: 12,
495
+ },
496
+ bodyPara: {
497
+ fontSize: 16,
498
+ color: COLORS.text,
499
+ lineHeight: 26,
500
+ fontWeight: '500',
501
+ },
502
+ gridBoard: {
503
+ flexDirection: 'row',
504
+ gap: 15,
505
+ marginBottom: 25,
506
+ },
507
+ gridItem: {
508
+ flex: 1,
509
+ backgroundColor: COLORS.surface,
510
+ borderRadius: 22,
511
+ padding: 20,
512
+ borderWidth: 1,
513
+ borderColor: COLORS.border,
514
+ ...COLORS.shadow.sm,
515
  },
516
+ gridLabel: {
517
+ fontSize: 10,
518
+ fontWeight: '900',
519
+ color: COLORS.textLight,
520
+ letterSpacing: 1,
521
+ marginBottom: 8,
522
+ },
523
+ gridValue: {
524
+ fontSize: 14,
525
  color: COLORS.text,
526
+ lineHeight: 20,
527
+ fontWeight: '700',
528
+ },
529
+ ctaButton: {
530
+ backgroundColor: COLORS.primary,
531
+ paddingVertical: 20,
532
+ borderRadius: 25,
533
+ alignItems: 'center',
534
+ ...COLORS.shadow.lg,
535
+ marginTop: 10,
536
  },
537
+ ctaButtonText: {
538
+ color: COLORS.white,
539
+ fontSize: 18,
540
+ fontWeight: '900',
541
+ letterSpacing: 2,
542
+ }
543
  });
544
 
545
  export default SchemesScreen;
services/aiService.js CHANGED
@@ -25,14 +25,16 @@ export const analyzeImage = async (imageUri) => {
25
 
26
  // 1. Try Custom Backend First
27
  try {
28
- console.log("Trying Backend...");
 
29
  const uploadResult = await FileSystem.uploadAsync(BACKEND_API_URL, imageUri, {
30
  httpMethod: 'POST',
31
  uploadType: FileSystem.FileSystemUploadType.MULTIPART,
32
  fieldName: 'file',
33
  });
34
 
35
- console.log("Render Backend Response:", uploadResult.status);
 
36
 
37
  if (uploadResult.status === 200) {
38
  const data = JSON.parse(uploadResult.body);
@@ -59,9 +61,12 @@ export const analyzeImage = async (imageUri) => {
59
  isFallback: false,
60
  isMock: false
61
  }
 
 
62
  }
63
  } catch (e) {
64
- console.log("Render Backend failed (likely waking up or offline):", e.message);
 
65
  }
66
 
67
  // 2. Fallback to Cloud APIs if Render fails
 
25
 
26
  // 1. Try Custom Backend First
27
  try {
28
+ console.log("---------------------------------------------------");
29
+ console.log("DEBUG: Sending request to:", BACKEND_API_URL);
30
  const uploadResult = await FileSystem.uploadAsync(BACKEND_API_URL, imageUri, {
31
  httpMethod: 'POST',
32
  uploadType: FileSystem.FileSystemUploadType.MULTIPART,
33
  fieldName: 'file',
34
  });
35
 
36
+ console.log("DEBUG: Response Status:", uploadResult.status);
37
+ console.log("DEBUG: Response Body:", uploadResult.body);
38
 
39
  if (uploadResult.status === 200) {
40
  const data = JSON.parse(uploadResult.body);
 
61
  isFallback: false,
62
  isMock: false
63
  }
64
+ } else {
65
+ console.log("DEBUG: Server returned non-200 status");
66
  }
67
  } catch (e) {
68
+ console.log("DEBUG: Upload Failed Error:", e);
69
+ console.log("DEBUG: Error Message:", e.message);
70
  }
71
 
72
  // 2. Fallback to Cloud APIs if Render fails
test_image.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:86348476c0970b6b41a68b640229a134bb4d7ab6a229e9980245aeb936b02774
3
+ size 26