1- import { useState } from 'react' ;
1+ import { useState , useEffect } from 'react' ;
22import { Card , CardContent , CardDescription , CardHeader , CardTitle } from "@/components/ui/card" ;
33import { Table , TableBody , TableCell , TableHead , TableHeader , TableRow } from "@/components/ui/table" ;
44import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from "@/components/ui/select" ;
5- import { Input } from "@/components/ui/input " ;
5+ import { Button } from "@/components/ui/button " ;
66import { Label } from "@/components/ui/label" ;
77import { format } from 'date-fns' ;
8-
9- type InventoryChangeReason = 'purchase' | 'sale' | 'birth' | 'death' | 'gift' | 'other' ;
10-
11- type InventoryHistoryEntry = {
12- date : string ;
13- type : 'hen' | 'cock' | 'chicks' ;
14- previousValue : number ;
15- newValue : number ;
16- change : number ;
17- reason : InventoryChangeReason ;
18- notes : string ;
19- } ;
8+ import { useChickenInventory , ChickenType , ChickenHistoryEntry } from "@/hooks/use-chicken-inventory" ;
9+ import { RefreshCcw } from "lucide-react" ;
2010
2111export function ChickenInventoryHistory ( ) {
12+ const { history, historyLoading, historyError, fetchChickenHistory } = useChickenInventory ( ) ;
13+
2214 const [ filter , setFilter ] = useState < {
23- type : 'all' | 'hen' | 'cock' | 'chicks' ;
24- reason : 'all' | InventoryChangeReason ;
15+ type : 'all' | ChickenType ;
16+ reason : 'all' | string ;
2517 } > ( { type : 'all' , reason : 'all' } ) ;
2618
27- // Load history from localStorage
28- const inventoryHistory : InventoryHistoryEntry [ ] = JSON . parse (
29- localStorage . getItem ( 'chickenInventoryHistory' ) || '[]'
30- ) ;
19+ // Fetch history when component mounts or filter changes
20+ useEffect ( ( ) => {
21+ const fetchHistory = async ( ) => {
22+ // Only pass type and reason to API if they're not 'all'
23+ const typeParam = filter . type !== 'all' ? filter . type : undefined ;
24+ const reasonParam = filter . reason !== 'all' ? filter . reason : undefined ;
25+ await fetchChickenHistory ( typeParam , reasonParam ) ;
26+ } ;
27+
28+ fetchHistory ( ) ;
29+ // Don't include fetchChickenHistory in dependencies to avoid infinite loops
30+ // eslint-disable-next-line react-hooks/exhaustive-deps
31+ } , [ filter . type , filter . reason ] ) ;
3132
32- // Filter history based on selected filters
33- const sortedHistory = [ ...inventoryHistory ] . sort ( ( a , b ) => {
34- return new Date ( b . date ) . getTime ( ) - new Date ( a . date ) . getTime ( ) ;
35- } ) ;
36-
37- const filteredHistory = sortedHistory . filter ( entry => {
38- if ( filter . type !== 'all' && entry . type !== filter . type ) return false ;
39- if ( filter . reason !== 'all' && entry . reason !== filter . reason ) return false ;
40- return true ;
33+ // Sort history by date (newest first)
34+ const sortedHistory = [ ...history ] . sort ( ( a , b ) => {
35+ return new Date ( b . created_at ) . getTime ( ) - new Date ( a . created_at ) . getTime ( ) ;
4136 } ) ;
4237
4338 // Helper function to get badge class for displaying reason
44- const getReasonBadgeClass = ( reason : InventoryChangeReason ) : string => {
39+ const getReasonBadgeClass = ( reason : string ) : string => {
4540 return 'bg-gray-100 text-gray-700 py-1 px-2 rounded text-xs font-medium' ;
4641 } ;
4742
@@ -51,7 +46,7 @@ export function ChickenInventoryHistory() {
5146 } ;
5247
5348 // Helper function to format chicken type for display
54- const formatChickenType = ( type : 'hen' | 'cock' | 'chicks' ) : string => {
49+ const formatChickenType = ( type : ChickenType ) : string => {
5550 switch ( type ) {
5651 case 'hen' : return 'Hen' ;
5752 case 'cock' : return 'Cock' ;
@@ -93,7 +88,7 @@ export function ChickenInventoryHistory() {
9388 < Label htmlFor = "reason-filter" className = "text-sm font-medium text-gray-700" > Filter by Reason</ Label >
9489 < Select
9590 value = { filter . reason }
96- onValueChange = { ( value : 'all' | InventoryChangeReason ) =>
91+ onValueChange = { ( value : 'all' | string ) =>
9792 setFilter ( { ...filter , reason : value } )
9893 }
9994 >
@@ -113,8 +108,22 @@ export function ChickenInventoryHistory() {
113108 </ div >
114109 </ div >
115110
111+ { /* Refresh Button */ }
112+ < div className = "flex justify-end mb-4" >
113+ < Button
114+ variant = "outline"
115+ size = "sm"
116+ onClick = { ( ) => fetchChickenHistory ( filter . type !== 'all' ? filter . type as ChickenType : undefined , filter . reason !== 'all' ? filter . reason : undefined ) }
117+ disabled = { historyLoading }
118+ className = "text-gray-700"
119+ >
120+ < RefreshCcw className = { `h-4 w-4 mr-1 ${ historyLoading ? 'animate-spin' : '' } ` } />
121+ { historyLoading ? 'Loading...' : 'Refresh' }
122+ </ Button >
123+ </ div >
124+
116125 { /* History Table */ }
117- { filteredHistory . length > 0 ? (
126+ { sortedHistory . length > 0 ? (
118127 < div className = "border border-gray-200 rounded-lg overflow-hidden" >
119128 < Table >
120129 < TableHeader className = "bg-gray-50" >
@@ -126,20 +135,17 @@ export function ChickenInventoryHistory() {
126135 </ TableRow >
127136 </ TableHeader >
128137 < TableBody >
129- { filteredHistory . map ( ( entry , index ) => (
130- < TableRow key = { index } className = "hover:bg-gray-50 border-t border-gray-100" >
138+ { sortedHistory . map ( ( entry , index ) => (
139+ < TableRow key = { entry . id || index } className = "hover:bg-gray-50 border-t border-gray-100" >
131140 < TableCell className = "font-medium text-gray-700" >
132- { format ( new Date ( entry . date ) , 'MMM d, yyyy h:mm a' ) }
141+ { format ( new Date ( entry . created_at ) , 'MMM d, yyyy h:mm a' ) }
133142 </ TableCell >
134143 < TableCell className = { getTypeIndicatorClass ( ) } >
135- { formatChickenType ( entry . type ) }
144+ { formatChickenType ( entry . chicken_type ) }
136145 </ TableCell >
137146 < TableCell >
138- < span className = { entry . change > 0 ? 'text-gray-900 font-medium' : 'text-gray-900 font-medium' } >
139- { entry . change > 0 ? '+' : '' } { entry . change }
140- </ span >
141- < span className = "text-gray-500 text-xs ml-1" >
142- ({ entry . previousValue } → { entry . newValue } )
147+ < span className = { entry . quantity_change > 0 ? 'text-gray-900 font-medium' : 'text-gray-900 font-medium' } >
148+ { entry . quantity_change > 0 ? '+' : '' } { entry . quantity_change }
143149 </ span >
144150 </ TableCell >
145151 < TableCell >
@@ -154,11 +160,19 @@ export function ChickenInventoryHistory() {
154160 </ div >
155161 ) : (
156162 < div className = "text-center py-8 border border-dashed border-gray-200 rounded-lg bg-gray-50" >
157- < p className = "text-gray-500 mb-2" >
158- No history records found{ filter . type !== 'all' || filter . reason !== 'all' ? ' matching your filters' : '' } .
159- </ p >
160- { ( filter . type !== 'all' || filter . reason !== 'all' ) && (
161- < p className = "text-sm text-gray-400" > Try adjusting your filters</ p >
163+ { historyLoading ? (
164+ < p className = "text-gray-500 mb-2" > Loading chicken history...</ p >
165+ ) : historyError ? (
166+ < p className = "text-red-500 mb-2" > Error: { historyError } </ p >
167+ ) : (
168+ < >
169+ < p className = "text-gray-500 mb-2" >
170+ No history records found{ filter . type !== 'all' || filter . reason !== 'all' ? ' matching your filters' : '' } .
171+ </ p >
172+ { ( filter . type !== 'all' || filter . reason !== 'all' ) && (
173+ < p className = "text-sm text-gray-400" > Try adjusting your filters</ p >
174+ ) }
175+ </ >
162176 ) }
163177 </ div >
164178 ) }
0 commit comments