mirror of
https://github.com/BarkProductions/barkman.git
synced 2026-06-13 06:11:55 +00:00
Merge pull request #28 from Pup-Ion-Dev/add-barcode-field
Add barcode field
This commit is contained in:
@@ -0,0 +1,108 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using barkmanapi;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace barkmanapi.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(BarkContext))]
|
||||||
|
[Migration("20250203160519_add-barcodes")]
|
||||||
|
partial class addbarcodes
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.1")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("barkmanapi.InventoryItems", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("Barcode")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("barcode");
|
||||||
|
|
||||||
|
b.Property<string>("Brand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("brand");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.Property<string>("Notes")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("notes");
|
||||||
|
|
||||||
|
b.Property<float?>("RentalPrice")
|
||||||
|
.HasColumnType("real")
|
||||||
|
.HasColumnName("rental_price");
|
||||||
|
|
||||||
|
b.Property<float?>("ReplacementCost")
|
||||||
|
.HasColumnType("real")
|
||||||
|
.HasColumnName("replacement_cost");
|
||||||
|
|
||||||
|
b.Property<string>("SerialNumber")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("serial_number");
|
||||||
|
|
||||||
|
b.Property<string>("StatusId")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("status_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_inventory");
|
||||||
|
|
||||||
|
b.HasIndex("StatusId")
|
||||||
|
.HasDatabaseName("ix_inventory_status_id");
|
||||||
|
|
||||||
|
b.ToTable("inventory", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("barkmanapi.ItemStatus", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_item_status");
|
||||||
|
|
||||||
|
b.ToTable("item_status", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("barkmanapi.InventoryItems", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("barkmanapi.ItemStatus", "Status")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("StatusId")
|
||||||
|
.HasConstraintName("fk_inventory_item_status_status_id");
|
||||||
|
|
||||||
|
b.Navigation("Status");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace barkmanapi.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class addbarcodes : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "barcode",
|
||||||
|
table: "inventory",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "barcode",
|
||||||
|
table: "inventory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,10 @@ namespace barkmanapi.Migrations
|
|||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("Barcode")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("barcode");
|
||||||
|
|
||||||
b.Property<string>("Brand")
|
b.Property<string>("Brand")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ var itemStatusGroup = app.MapGroup(prefix: "/itemstatus")
|
|||||||
.WithDescription("Endpoints for managing item status");
|
.WithDescription("Endpoints for managing item status");
|
||||||
|
|
||||||
inventoryGroup.MapGet("", async (BarkContext db) =>
|
inventoryGroup.MapGet("", async (BarkContext db) =>
|
||||||
await db.Inventory.OrderBy(item => item.Id).ToListAsync());
|
await db.Inventory.OrderBy(item => item.Barcode).ToListAsync());
|
||||||
|
|
||||||
inventoryGroup.MapGet("/{id}", async (int id, BarkContext db) =>
|
inventoryGroup.MapGet("/{id}", async (int id, BarkContext db) =>
|
||||||
{
|
{
|
||||||
@@ -73,9 +73,10 @@ inventoryGroup.MapPut("/{id}", async (int id, InventoryItems updatedItem, BarkCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
existingItem.Name = updatedItem.Name;
|
existingItem.Name = updatedItem.Name;
|
||||||
|
existingItem.Barcode = updatedItem.Barcode;
|
||||||
existingItem.Brand = updatedItem.Brand;
|
existingItem.Brand = updatedItem.Brand;
|
||||||
existingItem.SerialNumber = updatedItem.SerialNumber;
|
existingItem.SerialNumber = updatedItem.SerialNumber;
|
||||||
existingItem.Status = updatedItem.Status;
|
existingItem.StatusId = updatedItem.StatusId;
|
||||||
existingItem.RentalPrice = updatedItem.RentalPrice;
|
existingItem.RentalPrice = updatedItem.RentalPrice;
|
||||||
existingItem.ReplacementCost = updatedItem.ReplacementCost;
|
existingItem.ReplacementCost = updatedItem.ReplacementCost;
|
||||||
existingItem.Notes = updatedItem.Notes;
|
existingItem.Notes = updatedItem.Notes;
|
||||||
@@ -88,6 +89,7 @@ inventoryGroup.MapPost("", async (InventoryItems newItemInput, BarkContext db) =
|
|||||||
{
|
{
|
||||||
var newItem = new InventoryItems();
|
var newItem = new InventoryItems();
|
||||||
newItem.Name = newItemInput.Name;
|
newItem.Name = newItemInput.Name;
|
||||||
|
newItem.Barcode = newItemInput.Barcode;
|
||||||
newItem.Brand = newItemInput.Brand;
|
newItem.Brand = newItemInput.Brand;
|
||||||
newItem.SerialNumber = newItemInput.SerialNumber;
|
newItem.SerialNumber = newItemInput.SerialNumber;
|
||||||
newItem.RentalPrice = newItemInput.RentalPrice;
|
newItem.RentalPrice = newItemInput.RentalPrice;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class BarkContext(DbContextOptions<BarkContext> options) : DbContext(opti
|
|||||||
public class InventoryItems
|
public class InventoryItems
|
||||||
{
|
{
|
||||||
public int Id {get; set;}
|
public int Id {get; set;}
|
||||||
|
public int Barcode {get; set;}
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Brand { get; set; }
|
public string Brand { get; set; }
|
||||||
public string? SerialNumber { get; set; }
|
public string? SerialNumber { get; set; }
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ function App() {
|
|||||||
<Routes>
|
<Routes>
|
||||||
<Route index element={<Home/>}/>
|
<Route index element={<Home/>}/>
|
||||||
<Route path="inventory" element={<InventoryList/>}/>
|
<Route path="inventory" element={<InventoryList/>}/>
|
||||||
<Route path="itemDetail/:itemId" element={<ItemDetail/>}/>
|
<Route path="inventory/itemDetail/:itemId" element={<ItemDetail/>}/>
|
||||||
<Route path="editItem/:itemId" element={<EditItem/>}/>
|
<Route path="inventory/editItem/:itemId" element={<EditItem/>}/>
|
||||||
<Route path="addItem" element={<AddItem/>}/>
|
<Route path="inventory/addItem" element={<AddItem/>}/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</>
|
</>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
|||||||
@@ -2,17 +2,23 @@ import {Button, Group, TextInput, NumberInput, Container, Title, Flex} from '@ma
|
|||||||
import {useForm} from '@mantine/form';
|
import {useForm} from '@mantine/form';
|
||||||
import {useMutation} from "@tanstack/react-query";
|
import {useMutation} from "@tanstack/react-query";
|
||||||
import {NewItem} from "./types.ts";
|
import {NewItem} from "./types.ts";
|
||||||
import { useNavigate} from "react-router";
|
import {useNavigate} from "react-router";
|
||||||
import { IconX, IconCheck } from '@tabler/icons-react';
|
import {IconX, IconCheck} from '@tabler/icons-react';
|
||||||
import { notifications } from '@mantine/notifications';
|
import {notifications} from '@mantine/notifications';
|
||||||
|
import useInventoryList from "./hooks/useInventoryList.tsx";
|
||||||
|
import {useEffect} from "react";
|
||||||
|
|
||||||
|
|
||||||
function AddItem() {
|
function AddItem() {
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const inventoryQuery = useInventoryList();
|
||||||
|
|
||||||
const newItemForm = useForm<NewItem>({
|
const newItemForm = useForm<NewItem>({
|
||||||
mode: 'uncontrolled',
|
mode: 'uncontrolled',
|
||||||
initialValues: {
|
initialValues: {
|
||||||
|
barcode: 0,
|
||||||
name: "",
|
name: "",
|
||||||
brand: "",
|
brand: "",
|
||||||
serialNumber: "",
|
serialNumber: "",
|
||||||
@@ -36,8 +42,8 @@ function AddItem() {
|
|||||||
|
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
icon: <IconCheck size={20} />,
|
icon: <IconCheck size={20}/>,
|
||||||
color:"teal",
|
color: "teal",
|
||||||
title: "All good!",
|
title: "All good!",
|
||||||
message: "Item Created",
|
message: "Item Created",
|
||||||
position: 'top-center',
|
position: 'top-center',
|
||||||
@@ -48,8 +54,8 @@ function AddItem() {
|
|||||||
|
|
||||||
if (!result.ok) {
|
if (!result.ok) {
|
||||||
notifications.show({
|
notifications.show({
|
||||||
icon: <IconX size={20} />,
|
icon: <IconX size={20}/>,
|
||||||
color:"red",
|
color: "red",
|
||||||
title: "Bummer!",
|
title: "Bummer!",
|
||||||
message: "Something went wrong",
|
message: "Something went wrong",
|
||||||
position: 'top-center',
|
position: 'top-center',
|
||||||
@@ -57,9 +63,23 @@ function AddItem() {
|
|||||||
throw new Error('Failed to create inventory item');
|
throw new Error('Failed to create inventory item');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
},
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (inventoryQuery.data) {
|
||||||
|
const nextBarcode = inventoryQuery.data[inventoryQuery.data.length - 1].barcode + 1;
|
||||||
|
newItemForm.setValues({barcode: nextBarcode});
|
||||||
|
}
|
||||||
|
},[inventoryQuery.data]);
|
||||||
|
|
||||||
|
if (inventoryQuery.isPending) return 'Loading...'
|
||||||
|
if (inventoryQuery.error) return 'An error has occurred: ' + inventoryQuery.error.message
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -74,7 +94,8 @@ function AddItem() {
|
|||||||
wrap="wrap">
|
wrap="wrap">
|
||||||
|
|
||||||
<Title order={1}>Add Item</Title>
|
<Title order={1}>Add Item</Title>
|
||||||
|
<NumberInput withAsterisk size="md" key={newItemForm.key('barcode')} label="Barcode"
|
||||||
|
placeholder="Barcode" {...newItemForm.getInputProps('barcode')}/>
|
||||||
<TextInput withAsterisk key={newItemForm.key('brand')} size="md" label="Brand"
|
<TextInput withAsterisk key={newItemForm.key('brand')} size="md" label="Brand"
|
||||||
placeholder="Brand" {...newItemForm.getInputProps('brand')}/>
|
placeholder="Brand" {...newItemForm.getInputProps('brand')}/>
|
||||||
<TextInput withAsterisk key={newItemForm.key('name')} size="md" label="Name"
|
<TextInput withAsterisk key={newItemForm.key('name')} size="md" label="Name"
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
import {Button, Group, TextInput, Text, Textarea, NumberInput, Container, Title, Flex} from '@mantine/core';
|
import {Button, Group, TextInput, Textarea, NumberInput, Container, Title, Flex} from '@mantine/core';
|
||||||
import {useForm} from '@mantine/form';
|
import {useForm} from '@mantine/form';
|
||||||
import {useParams} from "react-router";
|
import {useNavigate, useParams} from "react-router";
|
||||||
import {useMutation, useQuery, useQueryClient} from "@tanstack/react-query";
|
import {useMutation, useQuery, useQueryClient} from "@tanstack/react-query";
|
||||||
import {InventoryItem} from "./types.ts";
|
import {InventoryItem} from "./types.ts";
|
||||||
import {useEffect} from "react";
|
import {useEffect} from "react";
|
||||||
|
import {notifications} from "@mantine/notifications";
|
||||||
|
import {IconCheck, IconX} from "@tabler/icons-react";
|
||||||
|
|
||||||
type EditableInventoryItem = Omit<InventoryItem, 'id'>;
|
type EditableInventoryItem = Omit<InventoryItem, 'id'>;
|
||||||
|
|
||||||
function EditItem() {
|
function EditItem() {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const editItemForm = useForm<EditableInventoryItem>({
|
const editItemForm = useForm<EditableInventoryItem>({
|
||||||
mode: 'uncontrolled',
|
mode: 'uncontrolled',
|
||||||
initialValues: {
|
initialValues: {
|
||||||
|
barcode: 0,
|
||||||
name: "",
|
name: "",
|
||||||
brand: "",
|
brand: "",
|
||||||
statusId: "",
|
statusId: "",
|
||||||
@@ -53,7 +57,26 @@ function EditItem() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (result.ok) {
|
||||||
|
notifications.show({
|
||||||
|
icon: <IconCheck size={20} />,
|
||||||
|
color:"teal",
|
||||||
|
title: "All good!",
|
||||||
|
message: "Item Updated",
|
||||||
|
position: 'top-center',
|
||||||
|
});
|
||||||
|
navigate("/inventory");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!result.ok) {
|
if (!result.ok) {
|
||||||
|
notifications.show({
|
||||||
|
icon: <IconX size={20} />,
|
||||||
|
color:"red",
|
||||||
|
title: "Bummer!",
|
||||||
|
message: "Something went wrong",
|
||||||
|
position: 'top-center',
|
||||||
|
});
|
||||||
throw new Error('Failed to update inventory item');
|
throw new Error('Failed to update inventory item');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +113,8 @@ function EditItem() {
|
|||||||
|
|
||||||
<div>{isFetching ? 'Updating...' : ''}</div>
|
<div>{isFetching ? 'Updating...' : ''}</div>
|
||||||
<Title order={1}>Edit Item</Title>
|
<Title order={1}>Edit Item</Title>
|
||||||
<Text>ID: {data.id}</Text>
|
<NumberInput withAsterisk size="md" key={editItemForm.key('barcode')} label="Barcode"
|
||||||
|
placeholder="Barcode" {...editItemForm.getInputProps('barcode')}/>
|
||||||
<TextInput withAsterisk key={editItemForm.key('brand')} size="md" label="Brand"
|
<TextInput withAsterisk key={editItemForm.key('brand')} size="md" label="Brand"
|
||||||
placeholder="Brand" {...editItemForm.getInputProps('brand')}/>
|
placeholder="Brand" {...editItemForm.getInputProps('brand')}/>
|
||||||
<TextInput withAsterisk key={editItemForm.key('name')} size="md" label="Name"
|
<TextInput withAsterisk key={editItemForm.key('name')} size="md" label="Name"
|
||||||
|
|||||||
@@ -1,27 +1,16 @@
|
|||||||
import {useQuery} from "@tanstack/react-query";
|
|
||||||
import {InventoryItem} from "./types";
|
|
||||||
import {Flex, Table} from '@mantine/core';
|
import {Flex, Table} from '@mantine/core';
|
||||||
import BarkButton from "../../common/components/BarkButton.tsx";
|
import BarkButton from "../../common/components/BarkButton.tsx";
|
||||||
import {Link, NavLink} from "react-router";
|
import {Link, NavLink} from "react-router";
|
||||||
|
import useInventoryList from "./hooks/useInventoryList.tsx";
|
||||||
|
|
||||||
|
|
||||||
function InventoryList() {
|
function InventoryList() {
|
||||||
|
|
||||||
const { isPending, error, data, isFetching } = useQuery({
|
const inventoryQuery = useInventoryList();
|
||||||
queryKey: ['inventory'],
|
|
||||||
queryFn: async (): Promise<InventoryItem[]> => {
|
|
||||||
const response = await fetch(
|
|
||||||
import.meta.env.VITE_API_URL + '/inventory',
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!response.ok) throw new Error('Failed to fetch inventory ' + response.statusText)
|
if (inventoryQuery.isPending) return 'Loading...'
|
||||||
|
|
||||||
return await response.json()
|
if (inventoryQuery.error) return 'An error has occurred: ' + inventoryQuery.error.message
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isPending) return 'Loading...'
|
|
||||||
|
|
||||||
if (error) return 'An error has occurred: ' + error.message
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -37,16 +26,13 @@ function InventoryList() {
|
|||||||
<p>
|
<p>
|
||||||
ARFF ARFF BARK BARK
|
ARFF ARFF BARK BARK
|
||||||
</p>
|
</p>
|
||||||
<NavLink to={'/addItem'}><BarkButton>Add Item</BarkButton></NavLink>
|
<NavLink to={'/inventory/addItem'}><BarkButton>Add Item</BarkButton></NavLink>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
|
|
||||||
<div>{isFetching ? 'Updating...' : ''}</div>
|
|
||||||
|
|
||||||
<Table striped>
|
<Table striped>
|
||||||
<Table.Thead>
|
<Table.Thead>
|
||||||
<Table.Tr>
|
<Table.Tr>
|
||||||
<Table.Th c="red">ID</Table.Th>
|
<Table.Th c="red">Barcode</Table.Th>
|
||||||
<Table.Th c="red">Brand</Table.Th>
|
<Table.Th c="red">Brand</Table.Th>
|
||||||
<Table.Th c="red">Item</Table.Th>
|
<Table.Th c="red">Item</Table.Th>
|
||||||
<Table.Th c="red">Status</Table.Th>
|
<Table.Th c="red">Status</Table.Th>
|
||||||
@@ -54,14 +40,14 @@ function InventoryList() {
|
|||||||
</Table.Tr>
|
</Table.Tr>
|
||||||
</Table.Thead>
|
</Table.Thead>
|
||||||
<Table.Tbody>
|
<Table.Tbody>
|
||||||
{data.map((data) => (
|
{inventoryQuery.data?.map((data) => (
|
||||||
<Table.Tr key={data.id}>
|
<Table.Tr key={data.id}>
|
||||||
<Table.Td>{data.id}</Table.Td>
|
<Table.Td>{data.barcode}</Table.Td>
|
||||||
<Table.Td>{data.brand}</Table.Td>
|
<Table.Td>{data.brand}</Table.Td>
|
||||||
<Table.Td>{data.name}</Table.Td>
|
<Table.Td>{data.name}</Table.Td>
|
||||||
<Table.Td>{data.statusId}</Table.Td>
|
<Table.Td>{data.statusId}</Table.Td>
|
||||||
<Table.Td>
|
<Table.Td>
|
||||||
<Link to={`/itemDetail/${data.id}`}>Details</Link>
|
<Link to={`/inventory/itemDetail/${data.id}`}>Details</Link>
|
||||||
</Table.Td>
|
</Table.Td>
|
||||||
</Table.Tr>
|
</Table.Tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ function ItemDetail() {
|
|||||||
<Container m="lg">
|
<Container m="lg">
|
||||||
<Title order={1}>Item Detail</Title>
|
<Title order={1}>Item Detail</Title>
|
||||||
<div>{isFetching ? 'Updating...' : ''}</div>
|
<div>{isFetching ? 'Updating...' : ''}</div>
|
||||||
<Text>ID: {data.id}</Text>
|
<Text>Barcode: {data.barcode}</Text>
|
||||||
<Text>Brand: {data.brand}</Text>
|
<Text>Brand: {data.brand}</Text>
|
||||||
<Text>Name: {data.name}</Text>
|
<Text>Name: {data.name}</Text>
|
||||||
<Text>Status: {data.status.name}</Text>
|
<Text>Status: {data.status.name}</Text>
|
||||||
@@ -38,7 +38,7 @@ function ItemDetail() {
|
|||||||
<Text>Replacement Cost: ${data.replacementCost}</Text>
|
<Text>Replacement Cost: ${data.replacementCost}</Text>
|
||||||
<Text>Notes: {data.notes}</Text>
|
<Text>Notes: {data.notes}</Text>
|
||||||
|
|
||||||
<Link to={`/editItem/${data.id}`}>Edit</Link>
|
<Link to={`/inventory/editItem/${data.id}`}>Edit</Link>
|
||||||
</Container>
|
</Container>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import {useQuery} from "@tanstack/react-query";
|
||||||
|
import {InventoryItem} from "../types.js";
|
||||||
|
|
||||||
|
const useInventoryList = () => useQuery({
|
||||||
|
queryKey: ['inventory'],
|
||||||
|
queryFn: async (): Promise<InventoryItem[]> => {
|
||||||
|
const response = await fetch(
|
||||||
|
import.meta.env.VITE_API_URL + '/inventory',
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error('Failed to fetch inventory ' + response.statusText)
|
||||||
|
|
||||||
|
return await response.json()
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default useInventoryList;
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
export interface InventoryItem {
|
export interface InventoryItem {
|
||||||
id: number,
|
id: number,
|
||||||
|
barcode: number,
|
||||||
brand: string,
|
brand: string,
|
||||||
name: string,
|
name: string,
|
||||||
status: {id: string; name: string},
|
status: {id: string; name: string},
|
||||||
@@ -11,6 +12,7 @@ export interface InventoryItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NewItem {
|
export interface NewItem {
|
||||||
|
barcode: number,
|
||||||
brand: string,
|
brand: string,
|
||||||
name: string,
|
name: string,
|
||||||
serialNumber: string,
|
serialNumber: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user