diff --git a/src/components/SearchOverlay.tsx b/src/components/SearchOverlay.tsx new file mode 100644 index 0000000..2169ce2 --- /dev/null +++ b/src/components/SearchOverlay.tsx @@ -0,0 +1,66 @@ +import { useEffect, useState } from 'react'; +import { Input } from '@/components/ui/input'; +import { X } from 'lucide-react'; + +interface SearchOverlayProps { + isOpen: boolean; + onClose: () => void; + onSearch: (query: string) => void; +} + +const SearchOverlay = ({ isOpen, onClose, onSearch }: SearchOverlayProps) => { + const [searchQuery, setSearchQuery] = useState(''); + + useEffect(() => { + if (isOpen) { + // Reset search when opened + setSearchQuery(''); + } + }, [isOpen]); + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + onClose(); + } + }; + + if (isOpen) { + window.addEventListener('keydown', handleKeyDown); + } + + return () => { + window.removeEventListener('keydown', handleKeyDown); + }; + }, [isOpen, onClose]); + + if (!isOpen) return null; + + return ( +
+
+
+ { + setSearchQuery(e.target.value); + onSearch(e.target.value); + }} + className="flex-1" + autoFocus + /> + +
+
+
+ ); +}; + +export default SearchOverlay; \ No newline at end of file diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index 795a118..476e802 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Plus, Factory, TrendingUp, Briefcase, FileText } from 'lucide-react'; @@ -10,6 +10,7 @@ import { IndJob } from '@/lib/types'; import { Badge } from '@/components/ui/badge'; import BatchTransactionForm from '@/components/BatchTransactionForm'; import { useJobs } from '@/hooks/useDataService'; +import SearchOverlay from '@/components/SearchOverlay'; const Index = () => { const { @@ -26,11 +27,25 @@ const Index = () => { const [showJobForm, setShowJobForm] = useState(false); const [editingJob, setEditingJob] = useState(null); const [showBatchForm, setShowBatchForm] = useState(false); + const [searchOpen, setSearchOpen] = useState(false); + const [searchQuery, setSearchQuery] = useState(''); const [collapsedGroups, setCollapsedGroups] = useState>(() => { const saved = localStorage.getItem('jobGroupsCollapsed'); return saved ? JSON.parse(saved) : {}; }); + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if ((e.ctrlKey || e.metaKey) && e.key === 'f') { + e.preventDefault(); + setSearchOpen(true); + } + }; + + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, []); + if (loading) { return (
@@ -73,6 +88,14 @@ const Index = () => { } }; + const filterJobs = (jobs: IndJob[]) => { + if (!searchQuery) return jobs; + const query = searchQuery.toLowerCase(); + return jobs.filter(job => + job.outputItem.toLowerCase().includes(query) + ); + }; + const sortedJobs = [...jobs].sort((a, b) => { const priorityA = getStatusPriority(a.status); const priorityB = getStatusPriority(b.status); @@ -82,8 +105,8 @@ const Index = () => { return priorityA - priorityB; }); - const regularJobs = sortedJobs.filter(job => job.status !== 'Tracked'); - const trackedJobs = sortedJobs.filter(job => job.status === 'Tracked'); + const regularJobs = filterJobs(sortedJobs.filter(job => job.status !== 'Tracked')); + const trackedJobs = filterJobs(sortedJobs.filter(job => job.status === 'Tracked')); const totalJobs = regularJobs.length; const totalProfit = regularJobs.reduce((sum, job) => { @@ -197,6 +220,14 @@ const Index = () => { return (
+ { + setSearchOpen(false); + setSearchQuery(''); + }} + onSearch={setSearchQuery} + />