mirror of
https://github.com/ForFarmTeam/ForFarm.git
synced 2025-12-19 14:04:08 +01:00
feat: add fetchInventoryCategory API and integrate into inventory management
This commit is contained in:
parent
e7bdb5d6a1
commit
ba8f754d8d
@ -3,14 +3,15 @@ import type {
|
|||||||
InventoryItem,
|
InventoryItem,
|
||||||
CreateInventoryItemInput,
|
CreateInventoryItemInput,
|
||||||
InventoryItemStatus,
|
InventoryItemStatus,
|
||||||
|
InventoryItemCategory,
|
||||||
} from "@/types";
|
} from "@/types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulates an API call to fetch inventory items.
|
* Simulates an API call to fetch inventory items.
|
||||||
* Waits for a simulated delay and then attempts an axios GET request.
|
* Waits for a simulated delay and then attempts an axios GET request.
|
||||||
* If the request fails, returns fallback dummy data.
|
* If the request fails, returns fallback dummy data.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export async function fetchInventoryStatus(): Promise<InventoryItemStatus[]> {
|
export async function fetchInventoryStatus(): Promise<InventoryItemStatus[]> {
|
||||||
try {
|
try {
|
||||||
@ -23,6 +24,19 @@ export async function fetchInventoryStatus(): Promise<InventoryItemStatus[]> {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export async function fetchInventoryCategory(): Promise<
|
||||||
|
InventoryItemCategory[]
|
||||||
|
> {
|
||||||
|
try {
|
||||||
|
const response = await axiosInstance.get<InventoryItemCategory[]>(
|
||||||
|
"/inventory/category"
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching inventory status:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchInventoryItems(): Promise<InventoryItem[]> {
|
export async function fetchInventoryItems(): Promise<InventoryItem[]> {
|
||||||
try {
|
try {
|
||||||
@ -34,52 +48,47 @@ export async function fetchInventoryItems(): Promise<InventoryItem[]> {
|
|||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "Tomato Seeds",
|
name: "Tomato Seeds",
|
||||||
category: "Seeds",
|
category: "1",
|
||||||
type: "Plantation",
|
|
||||||
quantity: 500,
|
quantity: 500,
|
||||||
unit: "packets",
|
unit: "packets",
|
||||||
lastUpdated: "2023-03-01",
|
lastUpdated: "2023-03-01",
|
||||||
status: "In Stock",
|
status: "1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: "NPK Fertilizer",
|
name: "NPK Fertilizer",
|
||||||
category: "Fertilizer",
|
category: "3",
|
||||||
type: "Fertilizer",
|
|
||||||
quantity: 200,
|
quantity: 200,
|
||||||
unit: "kg",
|
unit: "kg",
|
||||||
lastUpdated: "2023-03-05",
|
lastUpdated: "2023-03-05",
|
||||||
status: "Low Stock",
|
status: "2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: "Corn Seeds",
|
name: "Corn Seeds",
|
||||||
category: "Seeds",
|
category: "1",
|
||||||
type: "Plantation",
|
|
||||||
quantity: 300,
|
quantity: 300,
|
||||||
unit: "packets",
|
unit: "packets",
|
||||||
lastUpdated: "2023-03-10",
|
lastUpdated: "2023-03-10",
|
||||||
status: "In Stock",
|
status: "3",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
name: "Organic Compost",
|
name: "Organic Compost",
|
||||||
category: "Fertilizer",
|
category: "3",
|
||||||
type: "Fertilizer",
|
|
||||||
quantity: 150,
|
quantity: 150,
|
||||||
unit: "kg",
|
unit: "kg",
|
||||||
lastUpdated: "2023-03-15",
|
lastUpdated: "2023-03-15",
|
||||||
status: "Out Of Stock",
|
status: "1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
name: "Wheat Seeds",
|
name: "Wheat Seeds",
|
||||||
category: "Seeds",
|
category: "1",
|
||||||
type: "Plantation",
|
|
||||||
quantity: 250,
|
quantity: 250,
|
||||||
unit: "packets",
|
unit: "packets",
|
||||||
lastUpdated: "2023-03-20",
|
lastUpdated: "2023-03-20",
|
||||||
status: "In Stock",
|
status: "2",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -108,7 +117,6 @@ export async function createInventoryItem(
|
|||||||
id: Math.floor(Math.random() * 1000),
|
id: Math.floor(Math.random() * 1000),
|
||||||
name: item.name,
|
name: item.name,
|
||||||
category: item.category,
|
category: item.category,
|
||||||
type: item.type,
|
|
||||||
quantity: item.quantity,
|
quantity: item.quantity,
|
||||||
unit: item.unit,
|
unit: item.unit,
|
||||||
lastUpdated: new Date().toISOString(),
|
lastUpdated: new Date().toISOString(),
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import {
|
|||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { InventoryItemStatus, InventoryItemCategory } from "@/types";
|
||||||
// import { updateInventoryItem } from "@/api/inventory";
|
// import { updateInventoryItem } from "@/api/inventory";
|
||||||
// import type { UpdateInventoryItemInput } from "@/types";
|
// import type { UpdateInventoryItemInput } from "@/types";
|
||||||
|
|
||||||
@ -41,9 +42,10 @@ export interface EditInventoryItemProps {
|
|||||||
name: string;
|
name: string;
|
||||||
category: string;
|
category: string;
|
||||||
status: string;
|
status: string;
|
||||||
type: string;
|
|
||||||
unit: string;
|
unit: string;
|
||||||
quantity: number;
|
quantity: number;
|
||||||
|
fetchedInventoryStatus: InventoryItemStatus[];
|
||||||
|
fetchedInventoryCategory: InventoryItemCategory[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function EditInventoryItem({
|
export function EditInventoryItem({
|
||||||
@ -51,13 +53,13 @@ export function EditInventoryItem({
|
|||||||
name,
|
name,
|
||||||
category,
|
category,
|
||||||
status,
|
status,
|
||||||
type,
|
|
||||||
unit,
|
unit,
|
||||||
quantity,
|
quantity,
|
||||||
|
fetchedInventoryStatus,
|
||||||
|
fetchedInventoryCategory,
|
||||||
}: EditInventoryItemProps) {
|
}: EditInventoryItemProps) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [itemName, setItemName] = useState(name);
|
const [itemName, setItemName] = useState(name);
|
||||||
const [itemType, setItemType] = useState(type);
|
|
||||||
const [itemCategory, setItemCategory] = useState(category);
|
const [itemCategory, setItemCategory] = useState(category);
|
||||||
const [itemQuantity, setItemQuantity] = useState(quantity);
|
const [itemQuantity, setItemQuantity] = useState(quantity);
|
||||||
const [itemUnit, setItemUnit] = useState(unit);
|
const [itemUnit, setItemUnit] = useState(unit);
|
||||||
@ -119,17 +121,20 @@ 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="type" className="text-right">
|
<Label htmlFor="type" className="text-right">
|
||||||
Type
|
Category
|
||||||
</Label>
|
</Label>
|
||||||
<Select value={itemType.toLowerCase()} onValueChange={setItemType}>
|
<Select value={itemCategory} onValueChange={setItemCategory}>
|
||||||
<SelectTrigger className="col-span-3">
|
<SelectTrigger className="col-span-3">
|
||||||
<SelectValue placeholder="Select type" />
|
<SelectValue placeholder="Select type" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectLabel>Type</SelectLabel>
|
<SelectLabel>Category</SelectLabel>
|
||||||
<SelectItem value="plantation">Plantation</SelectItem>
|
{fetchedInventoryCategory.map((categoryItem, _) => (
|
||||||
<SelectItem value="fertilizer">Fertilizer</SelectItem>
|
<SelectItem key={categoryItem.id} value={categoryItem.name}>
|
||||||
|
{categoryItem.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
</SelectGroup>
|
</SelectGroup>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
@ -138,35 +143,22 @@ export function EditInventoryItem({
|
|||||||
<Label htmlFor="type" className="text-right">
|
<Label htmlFor="type" className="text-right">
|
||||||
Status
|
Status
|
||||||
</Label>
|
</Label>
|
||||||
<Select
|
<Select value={itemStatus} onValueChange={setItemStatus}>
|
||||||
value={itemStatus.toLowerCase()}
|
|
||||||
onValueChange={setItemStatus}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="col-span-3">
|
<SelectTrigger className="col-span-3">
|
||||||
<SelectValue placeholder="Select status" />
|
<SelectValue placeholder="Select status" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectLabel>Status</SelectLabel>
|
<SelectLabel>Status</SelectLabel>
|
||||||
<SelectItem value="in stock">In Stock</SelectItem>
|
{fetchedInventoryStatus.map((statusItem, _) => (
|
||||||
<SelectItem value="low stock">Low Stock</SelectItem>
|
<SelectItem key={statusItem.id} value={statusItem.name}>
|
||||||
<SelectItem value="out of stock">Out Of Stock</SelectItem>
|
{statusItem.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
</SelectGroup>
|
</SelectGroup>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
|
||||||
<Label htmlFor="category" className="text-right">
|
|
||||||
Category
|
|
||||||
</Label>
|
|
||||||
<Input
|
|
||||||
id="category"
|
|
||||||
className="col-span-3"
|
|
||||||
placeholder="e.g., Seeds, Organic"
|
|
||||||
value={itemCategory}
|
|
||||||
onChange={(e) => setItemCategory(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-4 items-center gap-4">
|
<div className="grid grid-cols-4 items-center gap-4">
|
||||||
<Label htmlFor="quantity" className="text-right">
|
<Label htmlFor="quantity" className="text-right">
|
||||||
Quantity
|
Quantity
|
||||||
|
|||||||
@ -31,7 +31,11 @@ import { Search } from "lucide-react";
|
|||||||
import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa";
|
import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa";
|
||||||
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { fetchInventoryItems, fetchInventoryStatus } from "@/api/inventory";
|
import {
|
||||||
|
fetchInventoryItems,
|
||||||
|
fetchInventoryStatus,
|
||||||
|
fetchInventoryCategory,
|
||||||
|
} from "@/api/inventory";
|
||||||
import { AddInventoryItem } from "./add-inventory-item";
|
import { AddInventoryItem } from "./add-inventory-item";
|
||||||
import {
|
import {
|
||||||
EditInventoryItem,
|
EditInventoryItem,
|
||||||
@ -65,14 +69,33 @@ export default function InventoryPage() {
|
|||||||
queryFn: fetchInventoryStatus,
|
queryFn: fetchInventoryStatus,
|
||||||
staleTime: 60 * 1000,
|
staleTime: 60 * 1000,
|
||||||
});
|
});
|
||||||
|
const {
|
||||||
|
data: inventoryCategory = [],
|
||||||
|
isLoading: isLoadingCategory,
|
||||||
|
isError: isErrorCategory,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["inventoryCategory"],
|
||||||
|
queryFn: fetchInventoryCategory,
|
||||||
|
staleTime: 60 * 1000,
|
||||||
|
});
|
||||||
// console.table(inventoryItems);
|
// console.table(inventoryItems);
|
||||||
console.table(inventoryStatus);
|
// console.table(inventoryStatus);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const filteredItems = useMemo(() => {
|
const filteredItems = useMemo(() => {
|
||||||
return inventoryItems
|
return inventoryItems
|
||||||
.map((item) => ({
|
.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
id: String(item.id), // Convert `id` to string here
|
status:
|
||||||
|
inventoryStatus.find(
|
||||||
|
(statusItem) => statusItem.id.toString() === item.status
|
||||||
|
)?.name || "",
|
||||||
|
category:
|
||||||
|
inventoryCategory.find(
|
||||||
|
(categoryItem) => categoryItem.id.toString() === item.category
|
||||||
|
)?.name || "",
|
||||||
|
fetchedInventoryStatus: inventoryStatus,
|
||||||
|
fetchedInventoryCategory: inventoryCategory,
|
||||||
|
id: String(item.id),
|
||||||
}))
|
}))
|
||||||
.filter((item) =>
|
.filter((item) =>
|
||||||
item.name.toLowerCase().includes(searchTerm.toLowerCase())
|
item.name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
@ -110,7 +133,11 @@ export default function InventoryPage() {
|
|||||||
accessorKey: "edit",
|
accessorKey: "edit",
|
||||||
header: "Edit",
|
header: "Edit",
|
||||||
cell: ({ row }: { row: { original: EditInventoryItemProps } }) => (
|
cell: ({ row }: { row: { original: EditInventoryItemProps } }) => (
|
||||||
<EditInventoryItem {...row.original} />
|
<EditInventoryItem
|
||||||
|
{...row.original}
|
||||||
|
fetchedInventoryStatus={inventoryStatus}
|
||||||
|
fetchedInventoryCategory={inventoryCategory}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
@ -133,13 +160,13 @@ export default function InventoryPage() {
|
|||||||
onPaginationChange: setPagination,
|
onPaginationChange: setPagination,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isItemLoading || isLoadingStatus)
|
if (isItemLoading || isLoadingStatus || isLoadingCategory)
|
||||||
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)
|
if (isItemError || isErrorStatus || isErrorCategory)
|
||||||
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.
|
||||||
|
|||||||
@ -63,7 +63,6 @@ export type InventoryItem = {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
category: string;
|
category: string;
|
||||||
type: string;
|
|
||||||
quantity: number;
|
quantity: number;
|
||||||
unit: string;
|
unit: string;
|
||||||
lastUpdated: string;
|
lastUpdated: string;
|
||||||
@ -74,7 +73,15 @@ export type InventoryItemStatus = {
|
|||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateInventoryItemInput = Omit<InventoryItem, "id" | "lastUpdated" | "status">;
|
export type InventoryItemCategory = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CreateInventoryItemInput = Omit<
|
||||||
|
InventoryItem,
|
||||||
|
"id" | "lastUpdated" | "status"
|
||||||
|
>;
|
||||||
|
|
||||||
export interface Blog {
|
export interface Blog {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user