Álvaro Valenzuela Valdes commited on
Commit
73126b2
Β·
1 Parent(s): f80a9d9

feat: improve mobile responsiveness for agent chat and tender tabs, verified groq integration

Browse files
frontend/components/AgentChat.tsx CHANGED
@@ -161,7 +161,7 @@ export default function AgentChat({ tender, companyProfile }: Props) {
161
  };
162
 
163
  return (
164
- <div className="flex flex-col h-[600px] md:h-[650px] glass-card rounded-[2rem] overflow-hidden border border-white/10 bg-slate-900/60 backdrop-blur-xl shadow-2xl transition-all duration-500">
165
  <input
166
  type="file"
167
  ref={fileInputRef}
@@ -266,15 +266,15 @@ export default function AgentChat({ tender, companyProfile }: Props) {
266
  )}
267
 
268
  {/* Input Area */}
269
- <div className="p-4 md:p-6 bg-white/5 border-t border-white/5">
270
- <div className="flex gap-2 md:gap-3 items-center">
271
  <button
272
  onClick={() => fileInputRef.current?.click()}
273
  disabled={isUploading || isLoading}
274
- className="w-10 h-10 md:w-12 md:h-12 rounded-2xl bg-white/5 border border-white/10 text-slate-400 flex items-center justify-center transition-all hover:bg-white/10 active:scale-95 disabled:opacity-30"
275
  title="Attach Document"
276
  >
277
- <span className={`text-xl ${isUploading ? 'animate-spin' : ''}`}>{isUploading ? 'βŒ›' : 'πŸ“Ž'}</span>
278
  </button>
279
 
280
  <input
@@ -282,30 +282,30 @@ export default function AgentChat({ tender, companyProfile }: Props) {
282
  value={input}
283
  onChange={(e) => setInput(e.target.value)}
284
  onKeyDown={(e) => e.key === 'Enter' && handleSend()}
285
- placeholder={isUploading ? "Uploading document..." : `Message ${selectedAgent.name}...`}
286
  disabled={isUploading}
287
- className="flex-1 bg-black/40 border border-white/10 rounded-2xl px-4 md:px-5 py-3 text-white text-sm placeholder:text-slate-600 focus:outline-none focus:ring-2 focus:ring-purple-500/40 transition-all disabled:opacity-50"
288
  />
289
 
290
  <button
291
  onClick={startSpeechRecognition}
292
  disabled={isListening || isLoading || isUploading}
293
- className={`w-10 h-10 md:w-12 md:h-12 rounded-2xl flex items-center justify-center transition-all active:scale-95 disabled:opacity-30 border ${
294
  isListening
295
  ? 'bg-red-500/20 border-red-500 shadow-[0_0_20px_rgba(239,68,68,0.4)] animate-pulse'
296
  : 'bg-white/5 border-white/10 text-slate-400 hover:bg-white/10'
297
  }`}
298
  title="Voice Command"
299
  >
300
- <span className="text-xl">{isListening ? 'πŸ›‘' : 'πŸŽ™οΈ'}</span>
301
  </button>
302
 
303
  <button
304
  onClick={() => handleSend()}
305
  disabled={!input.trim() || isLoading || isUploading}
306
- className="w-10 h-10 md:w-12 md:h-12 rounded-2xl premium-gradient text-white flex items-center justify-center transition-all active:scale-95 disabled:opacity-30 shadow-lg shadow-purple-500/20"
307
  >
308
- <span className="text-xl">✈️</span>
309
  </button>
310
  </div>
311
  </div>
 
161
  };
162
 
163
  return (
164
+ <div className="flex flex-col h-[550px] sm:h-[600px] md:h-[650px] lg:h-[700px] glass-card rounded-[2rem] overflow-hidden border border-white/10 bg-slate-900/60 backdrop-blur-xl shadow-2xl transition-all duration-500">
165
  <input
166
  type="file"
167
  ref={fileInputRef}
 
266
  )}
267
 
268
  {/* Input Area */}
269
+ <div className="p-3 md:p-6 bg-white/5 border-t border-white/5">
270
+ <div className="flex gap-1.5 md:gap-3 items-center">
271
  <button
272
  onClick={() => fileInputRef.current?.click()}
273
  disabled={isUploading || isLoading}
274
+ className="w-9 h-9 md:w-12 md:h-12 rounded-xl md:rounded-2xl bg-white/5 border border-white/10 text-slate-400 flex items-center justify-center transition-all hover:bg-white/10 active:scale-95 disabled:opacity-30 shrink-0"
275
  title="Attach Document"
276
  >
277
+ <span className={`text-lg md:text-xl ${isUploading ? 'animate-spin' : ''}`}>{isUploading ? 'βŒ›' : 'πŸ“Ž'}</span>
278
  </button>
279
 
280
  <input
 
282
  value={input}
283
  onChange={(e) => setInput(e.target.value)}
284
  onKeyDown={(e) => e.key === 'Enter' && handleSend()}
285
+ placeholder={isUploading ? "Uploading..." : `Message...`}
286
  disabled={isUploading}
287
+ className="flex-1 min-w-0 bg-black/40 border border-white/10 rounded-xl md:rounded-2xl px-3 md:px-5 py-2.5 md:py-3 text-white text-xs md:text-sm placeholder:text-slate-600 focus:outline-none focus:ring-2 focus:ring-purple-500/40 transition-all disabled:opacity-50"
288
  />
289
 
290
  <button
291
  onClick={startSpeechRecognition}
292
  disabled={isListening || isLoading || isUploading}
293
+ className={`w-9 h-9 md:w-12 md:h-12 rounded-xl md:rounded-2xl flex items-center justify-center transition-all active:scale-95 disabled:opacity-30 border shrink-0 ${
294
  isListening
295
  ? 'bg-red-500/20 border-red-500 shadow-[0_0_20px_rgba(239,68,68,0.4)] animate-pulse'
296
  : 'bg-white/5 border-white/10 text-slate-400 hover:bg-white/10'
297
  }`}
298
  title="Voice Command"
299
  >
300
+ <span className="text-lg md:text-xl">{isListening ? 'πŸ›‘' : 'πŸŽ™οΈ'}</span>
301
  </button>
302
 
303
  <button
304
  onClick={() => handleSend()}
305
  disabled={!input.trim() || isLoading || isUploading}
306
+ className="w-9 h-9 md:w-12 md:h-12 rounded-xl md:rounded-2xl premium-gradient text-white flex items-center justify-center transition-all active:scale-95 disabled:opacity-30 shadow-lg shadow-purple-500/20 shrink-0"
307
  >
308
+ <span className="text-lg md:text-xl">✈️</span>
309
  </button>
310
  </div>
311
  </div>
frontend/components/TenderSearch.tsx CHANGED
@@ -210,28 +210,30 @@ export default function TenderSearch({ tenders, onSearch, onAnalyze, forceShowFo
210
  // VIEW: Detail Modal
211
  const renderDetailView = (tender: Tender) => (
212
  <div className="animate-in slide-in-from-right-8 fade-in duration-700 w-full max-w-[1600px] mx-auto pt-4 pb-20">
213
- <div className="flex justify-between items-end mb-8 relative z-20">
214
  <button
215
  onClick={() => {
216
  console.log("[TenderSearch] Returning to list...");
217
  setSelectedTenderForModal(null);
218
  }}
219
- className="flex items-center gap-4 px-6 py-3 rounded-2xl bg-white/5 border border-white/10 text-slate-400 hover:text-white hover:bg-white/10 transition-all group active:scale-95 cursor-pointer relative z-30"
220
  >
221
  <span className="text-2xl group-hover:-translate-x-1 transition-transform">←</span>
222
  <span className="text-xs font-black uppercase tracking-widest">Back to search</span>
223
  </button>
224
- <div className="flex items-center gap-3 bg-white/5 p-1 rounded-2xl border border-white/10">
225
  <button
226
  onClick={() => toggleFollow(tender)}
227
- className={`px-4 py-2.5 rounded-xl text-[10px] font-black uppercase transition-all flex items-center gap-2 ${followedCodes.includes(tender.code) ? "bg-amber-500/20 text-amber-400 border border-amber-500/30" : "bg-white/5 text-slate-400 hover:bg-white/10"}`}
228
  >
229
  <span>{followedCodes.includes(tender.code) ? "β˜…" : "β˜†"}</span>
230
  <span>{followedCodes.includes(tender.code) ? "In Portfolio" : "Add to Portfolio"}</span>
231
  </button>
232
- <div className="w-px h-6 bg-white/10 mx-1" />
233
- <button onClick={() => setActiveDetailTab("Overview")} className={`px-6 py-2.5 rounded-xl text-xs font-black uppercase transition-all ${activeDetailTab === "Overview" ? "bg-purple-600 text-white shadow-lg" : "text-slate-500"}`}>Overview</button>
234
- <button onClick={() => setActiveDetailTab("Agent Chat")} className={`px-6 py-2.5 rounded-xl text-xs font-black uppercase transition-all ${activeDetailTab === "Agent Chat" ? "bg-purple-600 text-white shadow-lg" : "text-slate-500"}`}>Agent Chat</button>
 
 
235
  </div>
236
  </div>
237
 
 
210
  // VIEW: Detail Modal
211
  const renderDetailView = (tender: Tender) => (
212
  <div className="animate-in slide-in-from-right-8 fade-in duration-700 w-full max-w-[1600px] mx-auto pt-4 pb-20">
213
+ <div className="flex flex-col md:flex-row md:justify-between md:items-end gap-6 mb-8 relative z-20">
214
  <button
215
  onClick={() => {
216
  console.log("[TenderSearch] Returning to list...");
217
  setSelectedTenderForModal(null);
218
  }}
219
+ className="flex items-center gap-4 px-6 py-3 rounded-2xl bg-white/5 border border-white/10 text-slate-400 hover:text-white hover:bg-white/10 transition-all group active:scale-95 cursor-pointer relative z-30 w-fit"
220
  >
221
  <span className="text-2xl group-hover:-translate-x-1 transition-transform">←</span>
222
  <span className="text-xs font-black uppercase tracking-widest">Back to search</span>
223
  </button>
224
+ <div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-3 bg-white/5 p-1 rounded-2xl border border-white/10 w-full md:w-auto">
225
  <button
226
  onClick={() => toggleFollow(tender)}
227
+ className={`px-4 py-2.5 rounded-xl text-[10px] font-black uppercase transition-all flex items-center justify-center gap-2 ${followedCodes.includes(tender.code) ? "bg-amber-500/20 text-amber-400 border border-amber-500/30" : "bg-white/5 text-slate-400 hover:bg-white/10"}`}
228
  >
229
  <span>{followedCodes.includes(tender.code) ? "β˜…" : "β˜†"}</span>
230
  <span>{followedCodes.includes(tender.code) ? "In Portfolio" : "Add to Portfolio"}</span>
231
  </button>
232
+ <div className="hidden sm:block w-px h-6 bg-white/10 mx-1" />
233
+ <div className="flex gap-2">
234
+ <button onClick={() => setActiveDetailTab("Overview")} className={`flex-1 md:flex-none px-6 py-2.5 rounded-xl text-xs font-black uppercase transition-all ${activeDetailTab === "Overview" ? "bg-purple-600 text-white shadow-lg" : "text-slate-500 bg-white/5"}`}>Overview</button>
235
+ <button onClick={() => setActiveDetailTab("Agent Chat")} className={`flex-1 md:flex-none px-6 py-2.5 rounded-xl text-xs font-black uppercase transition-all ${activeDetailTab === "Agent Chat" ? "bg-purple-600 text-white shadow-lg" : "text-slate-500 bg-white/5"}`}>Agent Chat</button>
236
+ </div>
237
  </div>
238
  </div>
239