Files
resumeformatter/frontend/src/components/HeaderBar.tsx
Laxmi Khilnani cda50356b4
Some checks failed
Profile Linker Docker Build / Build and push Docker image (push) Failing after 3s
feat: Complete Smart Resume Formatter with R2 and Gemini AI integration
- Integrated Cloudflare R2 for template storage and converted file management
- Added Google Gemini AI for resume parsing and HTML generation
- Created backend API endpoints for templates, conversion, and history
- Refactored frontend to use real API instead of mock data
- Fixed Docker networking issues (IPv6/IPv4) for R2 connectivity
- Added resumeService.ts for frontend API integration
- Updated Vite configuration for proper asset serving in Docker
- Successfully tested with 13 templates from R2 bucket
2025-10-14 21:43:41 +05:30

91 lines
3.9 KiB
TypeScript

import React, { useState, FormEvent } from 'react';
// FIX: Import Sparkles icon for AI feature button
import { Search, RefreshCw, X, FolderPlus, Sparkles } from 'lucide-react';
interface HeaderBarProps {
onSearch: (term: string) => void;
onRefresh: () => void;
onCreateFolder: () => void;
// FIX: Add prop for new AI feature
onAnalyzeImage: () => void;
isLoading: boolean;
}
const HeaderBar: React.FC<HeaderBarProps> = ({ onSearch, onRefresh, onCreateFolder, onAnalyzeImage, isLoading }) => {
const [inputValue, setInputValue] = useState('');
const handleSearch = (e: FormEvent) => {
e.preventDefault();
onSearch(inputValue);
};
const handleClear = () => {
setInputValue('');
onSearch('');
};
return (
<div className="bg-white/80 dark:bg-slate-800/80 backdrop-blur-sm p-4 rounded-lg shadow-lg mb-8 sticky top-4 z-10 border border-slate-200 dark:border-slate-700">
<form onSubmit={handleSearch} className="flex flex-col md:flex-row items-center gap-4">
<div className="relative w-full">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-slate-400 pointer-events-none" />
<input
type="text"
placeholder="Search files by name..."
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
className="w-full pl-10 pr-10 py-2 border border-slate-300 dark:border-slate-600 rounded-md bg-slate-50 dark:bg-slate-700 text-slate-800 dark:text-slate-200 focus:ring-2 focus:ring-primary focus:border-primary outline-none transition"
/>
{inputValue && (
<button
type="button"
onClick={handleClear}
className="absolute right-3 top-1/2 -translate-y-1/2 p-1 text-slate-500 hover:text-slate-800 dark:hover:text-slate-200"
aria-label="Clear search"
>
<X className="w-4 h-4" />
</button>
)}
</div>
<div className="flex items-center gap-2 w-full md:w-auto flex-shrink-0">
<button
type="button"
onClick={onCreateFolder}
className="flex items-center justify-center gap-2 w-full md:w-auto px-4 py-2 bg-green-500 text-white font-semibold rounded-md hover:bg-green-600 dark:bg-green-600 dark:hover:bg-green-500 transition-colors"
>
<FolderPlus className="w-5 h-5" />
<span>New Folder</span>
</button>
{/* FIX: Add new button for AI Vision feature */}
<button
type="button"
onClick={onAnalyzeImage}
className="flex items-center justify-center gap-2 w-full md:w-auto px-4 py-2 bg-purple-500 text-white font-semibold rounded-md hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 transition-colors"
>
<Sparkles className="w-5 h-5" />
<span>Analyze Image</span>
</button>
<button
type="submit"
className="flex items-center justify-center gap-2 w-full md:w-auto px-4 py-2 bg-slate-700 text-white font-semibold rounded-md hover:bg-slate-800 dark:bg-slate-600 dark:hover:bg-slate-500 transition-colors"
>
<Search className="w-5 h-5" />
<span>Search</span>
</button>
<button
type="button"
onClick={onRefresh}
disabled={isLoading}
className="flex items-center justify-center gap-2 w-full md:w-auto px-4 py-2 bg-primary text-white font-semibold rounded-md hover:bg-blue-600 transition-colors disabled:bg-slate-400 disabled:cursor-not-allowed"
>
<RefreshCw className={`w-5 h-5 ${isLoading ? 'animate-spin' : ''}`} />
<span>Refresh</span>
</button>
</div>
</form>
</div>
);
};
export default HeaderBar;