Add search functionality

This commit is contained in:
2025-07-07 13:17:35 +02:00
parent bdb5766d58
commit fa03bdb207
2 changed files with 100 additions and 3 deletions

View File

@@ -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 (
<div className="fixed top-4 left-1/2 transform -translate-x-1/2 z-50 w-full max-w-lg">
<div className="bg-gray-800 rounded-lg shadow-lg p-4 mx-4">
<div className="flex items-center gap-2">
<Input
type="text"
placeholder="Search..."
value={searchQuery}
onChange={(e) => {
setSearchQuery(e.target.value);
onSearch(e.target.value);
}}
className="flex-1"
autoFocus
/>
<button
onClick={onClose}
className="p-2 hover:bg-gray-700 rounded-full"
>
<X className="h-4 w-4" />
</button>
</div>
</div>
</div>
);
};
export default SearchOverlay;

View File

@@ -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<IndJob | null>(null);
const [showBatchForm, setShowBatchForm] = useState(false);
const [searchOpen, setSearchOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
const [collapsedGroups, setCollapsedGroups] = useState<Record<string, boolean>>(() => {
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 (
<div className="min-h-screen bg-gray-950 p-6 flex items-center justify-center">
@@ -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 (
<div className="container mx-auto p-4 space-y-4">
<SearchOverlay
isOpen={searchOpen}
onClose={() => {
setSearchOpen(false);
setSearchQuery('');
}}
onSearch={setSearchQuery}
/>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Card className="bg-gray-900 border-gray-700 text-white">
<CardHeader>