mirror of
https://github.com/ForFarmTeam/ForFarm.git
synced 2025-12-19 14:04:08 +01:00
feat: add fetchHarvestUnits API and integrate into inventory management
This commit is contained in:
parent
ba8f754d8d
commit
bfeda8ce13
12
frontend/api/harvest.ts
Normal file
12
frontend/api/harvest.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import axiosInstance from "./config";
|
||||||
|
import type { HarvestUnits } from "@/types";
|
||||||
|
|
||||||
|
export async function fetchHarvestUnits(): Promise<HarvestUnits[]> {
|
||||||
|
try {
|
||||||
|
const response = await axiosInstance.get<HarvestUnits[]>("/harvest/units");
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching inventory status:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,6 @@
|
|||||||
import axiosInstance from "./config";
|
import axiosInstance from "./config";
|
||||||
import type {
|
import type {
|
||||||
InventoryItem,
|
InventoryItem,
|
||||||
CreateInventoryItemInput,
|
|
||||||
InventoryItemStatus,
|
InventoryItemStatus,
|
||||||
InventoryItemCategory,
|
InventoryItemCategory,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
@ -50,7 +49,7 @@ export async function fetchInventoryItems(): Promise<InventoryItem[]> {
|
|||||||
name: "Tomato Seeds",
|
name: "Tomato Seeds",
|
||||||
category: "1",
|
category: "1",
|
||||||
quantity: 500,
|
quantity: 500,
|
||||||
unit: "packets",
|
unit: "1",
|
||||||
lastUpdated: "2023-03-01",
|
lastUpdated: "2023-03-01",
|
||||||
status: "1",
|
status: "1",
|
||||||
},
|
},
|
||||||
@ -59,7 +58,7 @@ export async function fetchInventoryItems(): Promise<InventoryItem[]> {
|
|||||||
name: "NPK Fertilizer",
|
name: "NPK Fertilizer",
|
||||||
category: "3",
|
category: "3",
|
||||||
quantity: 200,
|
quantity: 200,
|
||||||
unit: "kg",
|
unit: "2",
|
||||||
lastUpdated: "2023-03-05",
|
lastUpdated: "2023-03-05",
|
||||||
status: "2",
|
status: "2",
|
||||||
},
|
},
|
||||||
@ -68,7 +67,7 @@ export async function fetchInventoryItems(): Promise<InventoryItem[]> {
|
|||||||
name: "Corn Seeds",
|
name: "Corn Seeds",
|
||||||
category: "1",
|
category: "1",
|
||||||
quantity: 300,
|
quantity: 300,
|
||||||
unit: "packets",
|
unit: "1",
|
||||||
lastUpdated: "2023-03-10",
|
lastUpdated: "2023-03-10",
|
||||||
status: "3",
|
status: "3",
|
||||||
},
|
},
|
||||||
@ -77,7 +76,7 @@ export async function fetchInventoryItems(): Promise<InventoryItem[]> {
|
|||||||
name: "Organic Compost",
|
name: "Organic Compost",
|
||||||
category: "3",
|
category: "3",
|
||||||
quantity: 150,
|
quantity: 150,
|
||||||
unit: "kg",
|
unit: "2",
|
||||||
lastUpdated: "2023-03-15",
|
lastUpdated: "2023-03-15",
|
||||||
status: "1",
|
status: "1",
|
||||||
},
|
},
|
||||||
@ -86,7 +85,7 @@ export async function fetchInventoryItems(): Promise<InventoryItem[]> {
|
|||||||
name: "Wheat Seeds",
|
name: "Wheat Seeds",
|
||||||
category: "1",
|
category: "1",
|
||||||
quantity: 250,
|
quantity: 250,
|
||||||
unit: "packets",
|
unit: "2",
|
||||||
lastUpdated: "2023-03-20",
|
lastUpdated: "2023-03-20",
|
||||||
status: "2",
|
status: "2",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -18,11 +18,6 @@ import {
|
|||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from "@/components/ui/popover";
|
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
@ -32,8 +27,11 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { cn } from "@/lib/utils";
|
import {
|
||||||
import { InventoryItemStatus, InventoryItemCategory } from "@/types";
|
InventoryItemStatus,
|
||||||
|
InventoryItemCategory,
|
||||||
|
HarvestUnits,
|
||||||
|
} from "@/types";
|
||||||
// import { updateInventoryItem } from "@/api/inventory";
|
// import { updateInventoryItem } from "@/api/inventory";
|
||||||
// import type { UpdateInventoryItemInput } from "@/types";
|
// import type { UpdateInventoryItemInput } from "@/types";
|
||||||
|
|
||||||
@ -46,6 +44,7 @@ export interface EditInventoryItemProps {
|
|||||||
quantity: number;
|
quantity: number;
|
||||||
fetchedInventoryStatus: InventoryItemStatus[];
|
fetchedInventoryStatus: InventoryItemStatus[];
|
||||||
fetchedInventoryCategory: InventoryItemCategory[];
|
fetchedInventoryCategory: InventoryItemCategory[];
|
||||||
|
fetchedHarvestUnits: HarvestUnits[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EditInventoryItem({
|
export function EditInventoryItem({
|
||||||
@ -57,6 +56,7 @@ export function EditInventoryItem({
|
|||||||
quantity,
|
quantity,
|
||||||
fetchedInventoryStatus,
|
fetchedInventoryStatus,
|
||||||
fetchedInventoryCategory,
|
fetchedInventoryCategory,
|
||||||
|
fetchedHarvestUnits,
|
||||||
}: EditInventoryItemProps) {
|
}: EditInventoryItemProps) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [itemName, setItemName] = useState(name);
|
const [itemName, setItemName] = useState(name);
|
||||||
@ -172,16 +172,24 @@ export function EditInventoryItem({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label htmlFor="unit" className="text-right">
|
<Label htmlFor="type" className="text-right">
|
||||||
Unit
|
Unit
|
||||||
</Label>
|
</Label>
|
||||||
<Input
|
<Select value={itemUnit} onValueChange={setItemUnit}>
|
||||||
id="unit"
|
<SelectTrigger className="col-span-3">
|
||||||
className="col-span-3"
|
<SelectValue placeholder="Select status" />
|
||||||
placeholder="e.g., kg, packets"
|
</SelectTrigger>
|
||||||
value={itemUnit}
|
<SelectContent>
|
||||||
onChange={(e) => setItemUnit(e.target.value)}
|
<SelectGroup>
|
||||||
/>
|
<SelectLabel>Unit</SelectLabel>
|
||||||
|
{fetchedHarvestUnits.map((unit, _) => (
|
||||||
|
<SelectItem key={unit.id} value={unit.name}>
|
||||||
|
{unit.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import {
|
|||||||
} from "@/components/ui/pagination";
|
} from "@/components/ui/pagination";
|
||||||
import { Search } from "lucide-react";
|
import { Search } from "lucide-react";
|
||||||
import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa";
|
import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa";
|
||||||
|
import { fetchHarvestUnits } from "@/api/harvest";
|
||||||
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import {
|
import {
|
||||||
@ -49,7 +50,8 @@ export default function InventoryPage() {
|
|||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
});
|
});
|
||||||
|
//////////////////////////////
|
||||||
|
// query the necessary data for edit and etc.
|
||||||
const {
|
const {
|
||||||
data: inventoryItems = [],
|
data: inventoryItems = [],
|
||||||
isLoading: isItemLoading,
|
isLoading: isItemLoading,
|
||||||
@ -78,6 +80,16 @@ export default function InventoryPage() {
|
|||||||
queryFn: fetchInventoryCategory,
|
queryFn: fetchInventoryCategory,
|
||||||
staleTime: 60 * 1000,
|
staleTime: 60 * 1000,
|
||||||
});
|
});
|
||||||
|
const {
|
||||||
|
data: harvestUnits = [],
|
||||||
|
isLoading: isLoadingHarvestUnits,
|
||||||
|
isError: isErrorHarvestUnits,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["harvestUnits"],
|
||||||
|
queryFn: fetchHarvestUnits,
|
||||||
|
staleTime: 60 * 1000,
|
||||||
|
});
|
||||||
|
//////////////////////////////
|
||||||
// console.table(inventoryItems);
|
// console.table(inventoryItems);
|
||||||
// console.table(inventoryStatus);
|
// console.table(inventoryStatus);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
@ -93,8 +105,12 @@ export default function InventoryPage() {
|
|||||||
inventoryCategory.find(
|
inventoryCategory.find(
|
||||||
(categoryItem) => categoryItem.id.toString() === item.category
|
(categoryItem) => categoryItem.id.toString() === item.category
|
||||||
)?.name || "",
|
)?.name || "",
|
||||||
|
unit:
|
||||||
|
harvestUnits.find((unit) => unit.id.toString() === item.unit)?.name ||
|
||||||
|
"",
|
||||||
fetchedInventoryStatus: inventoryStatus,
|
fetchedInventoryStatus: inventoryStatus,
|
||||||
fetchedInventoryCategory: inventoryCategory,
|
fetchedInventoryCategory: inventoryCategory,
|
||||||
|
fetchedHarvestUnits: harvestUnits,
|
||||||
id: String(item.id),
|
id: String(item.id),
|
||||||
}))
|
}))
|
||||||
.filter((item) =>
|
.filter((item) =>
|
||||||
@ -102,6 +118,8 @@ export default function InventoryPage() {
|
|||||||
);
|
);
|
||||||
}, [inventoryItems, searchTerm]);
|
}, [inventoryItems, searchTerm]);
|
||||||
|
|
||||||
|
// prepare columns for table
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ accessorKey: "name", header: "Name" },
|
{ accessorKey: "name", header: "Name" },
|
||||||
{ accessorKey: "category", header: "Category" },
|
{ accessorKey: "category", header: "Category" },
|
||||||
@ -159,14 +177,29 @@ export default function InventoryPage() {
|
|||||||
onSortingChange: setSorting,
|
onSortingChange: setSorting,
|
||||||
onPaginationChange: setPagination,
|
onPaginationChange: setPagination,
|
||||||
});
|
});
|
||||||
|
const loadingStates = [
|
||||||
|
isItemLoading,
|
||||||
|
isLoadingStatus,
|
||||||
|
isLoadingCategory,
|
||||||
|
isLoadingHarvestUnits,
|
||||||
|
];
|
||||||
|
const errorStates = [
|
||||||
|
isItemError,
|
||||||
|
isErrorStatus,
|
||||||
|
isErrorCategory,
|
||||||
|
isErrorHarvestUnits,
|
||||||
|
];
|
||||||
|
|
||||||
if (isItemLoading || isLoadingStatus || isLoadingCategory)
|
const isLoading = loadingStates.some((loading) => loading);
|
||||||
|
const isError = errorStates.some((error) => error);
|
||||||
|
|
||||||
|
if (isLoading)
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen items-center justify-center">
|
<div className="flex min-h-screen items-center justify-center">
|
||||||
Loading...
|
Loading...
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
if (isItemError || isErrorStatus || isErrorCategory)
|
if (isError)
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen items-center justify-center">
|
<div className="flex min-h-screen items-center justify-center">
|
||||||
Error loading inventory data.
|
Error loading inventory data.
|
||||||
|
|||||||
@ -77,6 +77,10 @@ export type InventoryItemCategory = {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
export type HarvestUnits = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type CreateInventoryItemInput = Omit<
|
export type CreateInventoryItemInput = Omit<
|
||||||
InventoryItem,
|
InventoryItem,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user