Skip to content

Commit 29abfee

Browse files
smoke weed everyday
1 parent 7cd7760 commit 29abfee

File tree

15 files changed

+367
-320
lines changed

15 files changed

+367
-320
lines changed

app/ChatBot/page.js

Lines changed: 127 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,125 @@
11
'use client';
22
import React, { useState, useEffect, useRef } from 'react';
33
import { motion } from 'framer-motion';
4-
import { FaPaperPlane, FaCamera, FaUpload, FaMapMarkerAlt, FaSatellite, FaRobot } from 'react-icons/fa';
4+
import { FaPaperPlane, FaMapMarkerAlt, FaSatellite, FaRobot, FaWater } from 'react-icons/fa';
55
import ReactMarkdown from 'react-markdown';
66
import { Input } from '@/components/ui/input';
77
import { Button } from '@/components/ui/button';
8-
import Image from 'next/image';
98
import { Inter } from 'next/font/google';
109
import { format, subDays } from 'date-fns';
1110
import Header from '../components/Header';
1211

1312
const inter = Inter({ subsets: ['latin'] });
1413

15-
const AgriChatbot = () => {
14+
const ChatBotPage = () => {
1615
const [messages, setMessages] = useState([]);
1716
const [input, setInput] = useState('');
1817
const [isLoading, setIsLoading] = useState(false);
19-
const [mode, setMode] = useState('text');
20-
const [image, setImage] = useState(null);
2118
const [latitude, setLatitude] = useState('');
2219
const [longitude, setLongitude] = useState('');
2320
const chatEndRef = useRef(null);
24-
const fileInputRef = useRef(null);
2521
const [nasaData, setNasaData] = useState(null);
2622
const [showNasaData, setShowNasaData] = useState(false);
23+
const [waterStressLevel, setWaterStressLevel] = useState(null);
24+
const [location, setLocation] = useState('');
25+
26+
// Predefined locations
27+
const predefinedLocations = [
28+
{ name: "Gojra (Punjab)", lat: "31.1497", lon: "72.6871" },
29+
{ name: "Sehwan (Sindh)", lat: "26.4249", lon: "67.8613" },
30+
{ name: "Charsadda (KPK)", lat: "34.1484", lon: "71.7415" },
31+
{ name: "Khuzdar (Balochistan)", lat: "27.8120", lon: "66.6101" },
32+
{ name: "Skardu (Gilgit-Baltistan)", lat: "35.2895", lon: "75.6350" }
33+
];
2734

2835
useEffect(() => {
2936
chatEndRef.current?.scrollIntoView({ behavior: 'smooth' });
3037
}, [messages]);
3138

39+
useEffect(() => {
40+
handleGetCurrentLocation();
41+
}, []);
42+
43+
useEffect(() => {
44+
if (nasaData) {
45+
calculateWaterStress();
46+
}
47+
}, [nasaData]);
48+
3249
const fetchNasaData = async () => {
3350
if (!latitude || !longitude) return null;
3451
const endDate = format(new Date(), 'yyyyMMdd');
35-
// 12 days bhi chal jae ga but 10 for safe side if user prompt is big
3652
const startDate = format(subDays(new Date(), 10), 'yyyyMMdd');
3753

3854
try {
3955
const res = await fetch(
4056
`https://power.larc.nasa.gov/api/temporal/hourly/point?start=${startDate}&end=${endDate}&latitude=${latitude}&longitude=${longitude}&community=re&parameters=T2M,PRECTOTCORR,WS2M,RH2M,ALLSKY_SFC_SW_DWN&format=json&user=demo&header=true`
4157
);
4258
const result = await res.json();
59+
setNasaData(result);
4360
return result;
4461
} catch (err) {
4562
console.error("Error fetching NASA data:", err);
4663
return null;
4764
}
4865
};
4966

67+
const calculateWaterStress = () => {
68+
if (nasaData && nasaData.properties && nasaData.properties.parameter) {
69+
const { T2M, PRECTOTCORR } = nasaData.properties.parameter;
70+
const avgTemperature = Object.values(T2M).reduce((sum, val) => sum + val, 0) / Object.values(T2M).length;
71+
const avgPrecipitation = Object.values(PRECTOTCORR).reduce((sum, val) => sum + val, 0) / Object.values(PRECTOTCORR).length;
72+
73+
const stressLevel = ((avgTemperature - 273.15) / 10) - (avgPrecipitation * 2);
74+
setWaterStressLevel(Math.max(0, Math.min(10, stressLevel)));
75+
}
76+
};
77+
78+
const getWaterStressColor = (level) => {
79+
if (level <= 3) return 'bg-green-500';
80+
if (level <= 6) return 'bg-yellow-500';
81+
return 'bg-red-500';
82+
};
83+
5084
const handleSubmit = async (e) => {
5185
e.preventDefault();
52-
if ((!input.trim() && mode === 'text') || (!image && (mode === 'camera' || mode === 'upload'))) return;
86+
if (!input.trim()) return;
5387

5488
setIsLoading(true);
5589

56-
const fetchedNasaData = await fetchNasaData();
57-
58-
let userMessage = {
90+
const userMessage = {
5991
role: 'user',
60-
content: mode === 'text' ? input : { image: image }
92+
content: input
6193
};
6294

6395
setMessages(prev => [...prev, userMessage]);
6496
setInput('');
6597

98+
const fetchedNasaData = await fetchNasaData();
99+
100+
if (waterStressLevel === null && fetchedNasaData) {
101+
calculateWaterStress();
102+
}
103+
66104
try {
105+
const waterStressInfo = waterStressLevel !== null ? `
106+
Current Water Stress Level: ${waterStressLevel.toFixed(2)} (${waterStressLevel <= 3 ? 'Low' : waterStressLevel <= 6 ? 'Moderate' : 'High'})
107+
` : '';
108+
67109
const response = await fetch('/api/chat', {
68110
method: 'POST',
69111
headers: { 'Content-Type': 'application/json' },
70112
body: JSON.stringify({
71-
messages: [...messages, {
72-
role: 'user',
73-
content: `
74-
User query: ${userMessage.content}
75-
76-
NASA POWER Data for the location:
77-
${JSON.stringify(fetchedNasaData)}
78-
79-
Please analyze the NASA POWER data provided above and use it to inform your response to the user's query. Consider how the weather conditions might affect agricultural practices or crop growth in the area.
80-
`
81-
}],
82-
mode,
113+
messages: [
114+
{
115+
role: 'system',
116+
content: `You are an AI assistant specializing in agriculture. The user is located at: ${location} (Coordinates: ${latitude}°N, ${longitude}°E). ${waterStressInfo}
117+
NASA POWER Data for the location: ${JSON.stringify(fetchedNasaData)}
118+
Please consider this information when answering the user's query.`
119+
},
120+
...messages,
121+
userMessage
122+
],
83123
}),
84124
});
85125

@@ -92,41 +132,6 @@ Please analyze the NASA POWER data provided above and use it to inform your resp
92132
setMessages(prev => [...prev, { role: 'assistant', content: "I'm sorry, I encountered an error. Please try again later." }]);
93133
} finally {
94134
setIsLoading(false);
95-
setImage(null);
96-
setMode('text');
97-
}
98-
};
99-
100-
const handleCameraCapture = async () => {
101-
try {
102-
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
103-
const videoElement = document.createElement('video');
104-
videoElement.srcObject = stream;
105-
await videoElement.play();
106-
107-
const canvas = document.createElement('canvas');
108-
canvas.width = videoElement.videoWidth;
109-
canvas.height = videoElement.videoHeight;
110-
canvas.getContext('2d').drawImage(videoElement, 0, 0);
111-
112-
setImage(canvas.toDataURL('image/jpeg'));
113-
setMode('camera');
114-
115-
stream.getTracks().forEach(track => track.stop());
116-
} catch (error) {
117-
console.error('Error accessing camera:', error);
118-
}
119-
};
120-
121-
const handleImageUpload = (e) => {
122-
const file = e.target.files[0];
123-
if (file) {
124-
const reader = new FileReader();
125-
reader.onloadend = () => {
126-
setImage(reader.result);
127-
setMode('upload');
128-
};
129-
reader.readAsDataURL(file);
130135
}
131136
};
132137

@@ -136,6 +141,8 @@ Please analyze the NASA POWER data provided above and use it to inform your resp
136141
(position) => {
137142
setLatitude(position.coords.latitude.toFixed(6));
138143
setLongitude(position.coords.longitude.toFixed(6));
144+
setLocation('Current Location');
145+
fetchNasaData();
139146
},
140147
(error) => console.error("Error getting location:", error)
141148
);
@@ -144,6 +151,13 @@ Please analyze the NASA POWER data provided above and use it to inform your resp
144151
}
145152
};
146153

154+
const handleLocationSelect = (loc) => {
155+
setLatitude(loc.lat);
156+
setLongitude(loc.lon);
157+
setLocation(loc.name);
158+
fetchNasaData();
159+
};
160+
147161
const renderMessageContent = (content) => {
148162
if (typeof content === 'string') {
149163
return (
@@ -162,8 +176,6 @@ Please analyze the NASA POWER data provided above and use it to inform your resp
162176
{content}
163177
</ReactMarkdown>
164178
);
165-
} else if (content && typeof content === 'object' && content.image) {
166-
return <img src={content.image} alt="User uploaded" className="max-w-full h-auto rounded-lg" />;
167179
}
168180
return <p>Unsupported message content</p>;
169181
};
@@ -205,6 +217,43 @@ Please analyze the NASA POWER data provided above and use it to inform your resp
205217
);
206218
};
207219

220+
const renderWaterStressIndicator = () => {
221+
if (waterStressLevel === null) return null;
222+
223+
let stressDescription, precautions;
224+
if (waterStressLevel <= 3) {
225+
stressDescription = "Low water stress indicates favorable conditions for most crops.";
226+
precautions = "Monitor soil moisture and maintain regular irrigation schedules.";
227+
} else if (waterStressLevel <= 6) {
228+
stressDescription = "Moderate water stress may impact sensitive crops and reduce yields.";
229+
precautions = "Increase irrigation frequency, consider mulching, and prioritize water-efficient practices.";
230+
} else {
231+
stressDescription = "High water stress can severely affect crop health and yield.";
232+
precautions = "Implement drought-resistant strategies, consider crop selection changes, and optimize water usage.";
233+
}
234+
235+
return (
236+
<div className="mb-6 p-4 bg-white rounded-2xl shadow-xl">
237+
<h3 className="text-lg font-semibold text-gray-800 mb-2 flex items-center">
238+
<FaWater className="mr-2 text-blue-500" /> Water Stress Level
239+
</h3>
240+
<div className="w-full bg-gray-200 rounded-full h-2.5 mb-2">
241+
<div
242+
className={`h-2.5 rounded-full ${getWaterStressColor(waterStressLevel)}`}
243+
style={{width: `${waterStressLevel * 10}%`}}
244+
></div>
245+
</div>
246+
<p className="text-gray-600 font-semibold mb-2">
247+
{waterStressLevel <= 3 ? 'Low' : waterStressLevel <= 6 ? 'Moderate' : 'High'} water stress
248+
</p>
249+
<div className="text-sm text-gray-600">
250+
<p className="mb-2"><strong>Significance:</strong> {stressDescription}</p>
251+
<p><strong>Precautions:</strong> {precautions}</p>
252+
</div>
253+
</div>
254+
);
255+
};
256+
208257
return (
209258
<div className={`${inter.className} bg-gradient-to-br from-green-50 to-blue-50 min-h-screen flex flex-col`}>
210259
<Header />
@@ -216,6 +265,8 @@ Please analyze the NASA POWER data provided above and use it to inform your resp
216265
<p className="text-gray-600">Your AI-powered agricultural companion. Ask questions, get insights, and make data-driven decisions for your farm.</p>
217266
</div>
218267

268+
{renderWaterStressIndicator()}
269+
219270
<div className="flex-grow overflow-y-auto mb-6 space-y-6 scrollbar-thin scrollbar-thumb-green-400 scrollbar-track-gray-200 pr-2 sm:pr-4 bg-white rounded-2xl shadow-xl p-6">
220271
{messages.map((message, index) => (
221272
<motion.div
@@ -235,6 +286,13 @@ Please analyze the NASA POWER data provided above and use it to inform your resp
235286

236287
<div className="bg-white rounded-2xl p-6 space-y-4 sm:space-y-6 shadow-xl">
237288
<div className="flex flex-col sm:flex-row items-center space-y-4 sm:space-y-0 sm:space-x-4">
289+
<Input
290+
type="text"
291+
value={location}
292+
onChange={(e) => setLocation(e.target.value)}
293+
placeholder="Enter location"
294+
className="w-full sm:flex-grow bg-gray-100 text-gray-900 placeholder-gray-500 border-gray-300"
295+
/>
238296
<Input
239297
type="text"
240298
value={latitude}
@@ -251,41 +309,22 @@ Please analyze the NASA POWER data provided above and use it to inform your resp
251309
/>
252310
<Button onClick={handleGetCurrentLocation} variant="secondary" className="w-full sm:w-auto bg-green-600 hover:bg-green-700 text-white">
253311
<FaMapMarkerAlt className="mr-2" />
254-
Get Location
312+
Get Current Location
255313
</Button>
256314
</div>
257315

258-
<div className="flex flex-wrap justify-center gap-2 mt-4">
259-
{[
260-
{ name: "Gojra (Punjab)", lat: "31.582045", lon: "74.329376" },
261-
{ name: "Sehwan (Sindh)", lat: "24.860966", lon: "67.001137" },
262-
{ name: "Charsadda (KPK)", lat: "34.008053", lon: "71.578640" },
263-
{ name: "Khuzdar (Balochistan)", lat: "28.394857", lon: "66.261768" },
264-
{ name: "Skardu (Gilgit-Baltistan)", lat: "35.350659", lon: "74.857989" }
265-
].map((location) => (
266-
<Button
267-
key={location.name}
268-
onClick={() => { setLatitude(location.lat); setLongitude(location.lon); }}
316+
<div className="flex flex-wrap justify-center gap-2">
317+
{predefinedLocations.map((loc) => (
318+
<Button
319+
key={loc.name}
320+
onClick={() => handleLocationSelect(loc)}
269321
className="bg-blue-100 hover:bg-blue-200 text-blue-800 text-xs sm:text-sm py-1 px-2 rounded-full"
270322
>
271-
{location.name}
323+
{loc.name}
272324
</Button>
273325
))}
274326
</div>
275327

276-
{image && (
277-
<div className="mt-4 sm:mt-6">
278-
<Image
279-
src={image}
280-
alt="Captured or uploaded image"
281-
width={500}
282-
height={300}
283-
layout="responsive"
284-
className="rounded-xl shadow-lg"
285-
/>
286-
</div>
287-
)}
288-
289328
<form onSubmit={handleSubmit} className="flex flex-col sm:flex-row items-center space-y-4 sm:space-y-0 sm:space-x-4">
290329
<Input
291330
type="text"
@@ -315,4 +354,4 @@ Please analyze the NASA POWER data provided above and use it to inform your resp
315354
);
316355
};
317356

318-
export default AgriChatbot;
357+
export default ChatBotPage;

app/InsectDetector/page.js

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
'use client'
2-
import React, { useState, useEffect, useRef } from 'react';
2+
import React, { useState, useRef } from 'react';
33
import { motion } from 'framer-motion';
44
import { FaCamera, FaUpload, FaBug } from 'react-icons/fa';
55
import ReactMarkdown from 'react-markdown';
66
import Header from '../components/Header';
7-
import { useRouter } from 'next/navigation';
8-
import { useUser } from '@clerk/nextjs';
97
import { Button } from '@/components/ui/button';
108

119
const InsectDetector = () => {
12-
const router = useRouter();
13-
const { isLoaded, isSignedIn, user } = useUser();
1410
const [messages, setMessages] = useState([]);
1511
const [isLoading, setIsLoading] = useState(false);
1612
const chatEndRef = useRef(null);
@@ -21,16 +17,6 @@ const InsectDetector = () => {
2117
const canvasRef = useRef(null);
2218
const streamRef = useRef(null);
2319

24-
useEffect(() => {
25-
if (isLoaded && !isSignedIn) {
26-
router.push('/sign-in');
27-
}
28-
}, [isLoaded, isSignedIn, router]);
29-
30-
useEffect(() => {
31-
chatEndRef.current?.scrollIntoView({ behavior: 'smooth' });
32-
}, [messages]);
33-
3420
const handleSubmit = async () => {
3521
if (!image) return;
3622

@@ -134,10 +120,6 @@ const InsectDetector = () => {
134120
return <p>Unsupported message content</p>;
135121
};
136122

137-
if (!isLoaded || !isSignedIn) {
138-
return null; // or a loading spinner
139-
}
140-
141123
return (
142124
<div className="bg-gradient-to-br from-green-50 to-blue-50 min-h-screen flex flex-col">
143125
<Header />

0 commit comments

Comments
 (0)