1
- import React from 'react'
1
+ import React , { useState , useEffect } from "react" ;
2
+ import ReactMarkdown from "react-markdown" ;
3
+ import { IoSend } from "react-icons/io5" ;
2
4
3
5
const App = ( ) => {
6
+ const apikey = import . meta. env . VITE_API_GEMINI_KEY ;
7
+ const [ input , setInput ] = useState ( "" ) ;
8
+ const [ messages , setMessages ] = useState ( [ ] ) ;
9
+ const [ loading , setLoading ] = useState ( false ) ;
10
+ const [ dots , setDots ] = useState ( "." ) ;
11
+
12
+ useEffect ( ( ) => {
13
+ const interval = setInterval ( ( ) => {
14
+ setDots ( ( prev ) => ( prev === "..." ? "." : prev + "." ) ) ;
15
+ } , 500 ) ;
16
+
17
+ return ( ) => clearInterval ( interval ) ;
18
+ } , [ ] ) ;
19
+
20
+ async function fetchChatResponseFromGemini ( ) {
21
+ if ( ! input . trim ( ) ) return ;
22
+
23
+ const userMessage = { role : "user" , text : input } ;
24
+ setMessages ( ( prev ) => [ ...prev , userMessage ] ) ;
25
+ setInput ( "" ) ;
26
+
27
+ setLoading ( true ) ;
28
+
29
+ try {
30
+ const res = await fetch (
31
+ `https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent?key=${ apikey } ` ,
32
+ {
33
+ method : "POST" ,
34
+ headers : { "Content-Type" : "application/json" } ,
35
+ body : JSON . stringify ( { contents : [ { parts : [ { text : input } ] } ] } ) ,
36
+ }
37
+ ) ;
38
+
39
+ if ( ! res . ok ) throw new Error ( `HTTP error! Status: ${ res . status } ` ) ;
40
+
41
+ const data = await res . json ( ) ;
42
+ const aiResponse =
43
+ data ?. candidates ?. [ 0 ] ?. content ?. parts ?. [ 0 ] ?. text || "No response" ;
44
+
45
+ const botMessage = { role : "bot" , text : aiResponse } ;
46
+ setMessages ( ( prev ) => [ ...prev , botMessage ] ) ;
47
+ } catch ( error ) {
48
+ console . error ( "Error:" , error ) ;
49
+ setMessages ( ( prev ) => [
50
+ ...prev ,
51
+ { role : "bot" , text : "Error fetching response" } ,
52
+ ] ) ;
53
+ } finally {
54
+ setLoading ( false ) ;
55
+ }
56
+ }
57
+
58
+
59
+ const handleKeyDown = ( e ) => {
60
+ if ( e . key === "Enter" ) {
61
+ e . preventDefault ( ) ;
62
+ fetchChatResponseFromGemini ( ) ;
63
+ }
64
+ } ;
65
+
4
66
return (
5
- < div > App</ div >
6
- )
7
- }
67
+ < div className = "flex flex-col items-center justify-center min-h-screen bg-gray-900 text-white p-6" >
68
+ < h1
69
+ className = "text-3xl font-bold mb-6 text-blue-400"
70
+ style = { { fontFamily : "Yatra One" } }
71
+ >
72
+ Ram Lal AI Chatbot
73
+ </ h1 >
74
+ < div className = "bg-gray-800 p-4 rounded-sm shadow-lg w-full flex flex-col space-y-4" >
75
+ { /* Chat Messages */ }
76
+ < div className = "h-100 overflow-y-auto bg-gray-700 p-3 rounded" >
77
+ { messages . map ( ( msg , index ) => (
78
+ < div
79
+ key = { index }
80
+ className = { `p-2 my-1 rounded-sm break-words whitespace-pre-wrap max-w-[75%] ${
81
+ msg . role === "user"
82
+ ? "bg-blue-500 self-end text-white ml-auto"
83
+ : "bg-gray-600 text-gray-200 self-start"
84
+ } `}
85
+ style = { { width : "fit-content" } }
86
+ >
87
+ < div className = "overflow-hidden break-words whitespace-pre-wrap" >
88
+ < ReactMarkdown > { msg . text } </ ReactMarkdown >
89
+ </ div >
90
+ </ div >
91
+ ) ) }
92
+
93
+ { /* Typing Indicator */ }
94
+ { loading && (
95
+ < div
96
+ className = "self-start bg-gray-600 text-gray-200 p-2 my-1 rounded-sm"
97
+ style = { { width : "fit-content" } }
98
+ >
99
+ Typing< span > { dots } </ span >
100
+ </ div >
101
+ ) }
102
+ </ div >
103
+
104
+ { /* Input & Button */ }
105
+ < div className = "flex space-x-2" >
106
+ < input
107
+ type = "text"
108
+ value = { input }
109
+ onChange = { ( e ) => setInput ( e . target . value ) }
110
+ onKeyDown = { handleKeyDown }
111
+ placeholder = " Type a message..."
112
+ className = "flex-grow p-2 border border-gray-600 rounded-full bg-gray-700 text-white focus:outline-none focus:ring-2 focus:ring-blue-400"
113
+ />
114
+ < button
115
+ onClick = { fetchChatResponseFromGemini }
116
+ className = "bg-blue-500 hover:bg-blue-600 text-white font-semibold cursor-pointer p-4 rounded-full transition-all"
117
+ >
118
+ < IoSend />
119
+ </ button >
120
+ </ div >
121
+ </ div >
122
+ < p
123
+ className = "text-lg sm:text-xl md:text-2xl lg:text-3xl font-bold mt-4 sm:mt-6 text-blue-400 text-center px-4"
124
+ style = { { fontFamily : "Yatra One" } }
125
+ >
126
+ कुनाल शर्मा द्वारा बनाया गया है |❤️
127
+ </ p >
128
+ </ div >
129
+ ) ;
130
+ } ;
8
131
9
- export default App
132
+ export default App ;
0 commit comments