Building a simple inventory management web app for laser-engraved products:
python3 -m venv venv
source venv/bin/activate
pip install django djangorestframework psycopg2-binary django-cors-headers
pip freeze > requirements.txt
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install postgresql postgresql-contrib libpq-dev
sudo systemctl status postgresql@15-main
sudo -u postgres psql
CREATE USER engraveruser WITH PASSWORD 'engraverpass';
CREATE DATABASE engraverdb OWNER engraveruser;
GRANT ALL PRIVILEGES ON DATABASE engraverdb TO engraveruser;
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'engraverdb',
'USER': 'engraveruser',
'PASSWORD': 'engraverpass',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
django-admin startproject engraver_app .
python manage.py startapp inventory
INSTALLED_APPS = [
'corsheaders',
'rest_framework',
'inventory',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
]
CORS_ALLOWED_ORIGINS = [
"http://localhost:5173",
]
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
cost = models.DecimalField(max_digits=10, decimal_places=2)
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.IntegerField()
python manage.py makemigrations inventory
python manage.py migrate
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet
router = DefaultRouter()
router.register(r'products', ProductViewSet)
urlpatterns = [
path('', include(router.urls)),
]
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('inventory.urls')),
]
python manage.py runserver
Visit: http://127.0.0.1:8000/api/products/
sudo apt install nodejs npm
npm create vite@latest laser-inventory-frontend -- --template react
cd laser-inventory-frontend
npm install
npm run dev
import { useEffect, useState } from 'react';
import './App.css';
function App() {
const [products, setProducts] = useState([]);
const [newProduct, setNewProduct] = useState({
name: '',
cost: '',
price: '',
stock: ''
});
useEffect(() => {
fetch('http://127.0.0.1:8000/api/products/')
.then(response => response.json())
.then(data => setProducts(data))
.catch(error => console.error('Error fetching products:', error));
}, []);
const handleChange = (e) => {
const { name, value } = e.target;
setNewProduct(prevState => ({
...prevState,
[name]: value
}));
};
const handleSubmit = (e) => {
e.preventDefault();
fetch('http://127.0.0.1:8000/api/products/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(newProduct)
})
.then(response => response.json())
.then(data => {
setProducts(prevProducts => [...prevProducts, data]);
setNewProduct({ name: '', cost: '', price: '', stock: '' });
})
.catch(error => console.error(error));
};
return (
<div>
<h1>Laser Inventory</h1>
<table border="1">
<thead>
<tr>
<th>Name</th>
<th>Cost</th>
<th>Price</th>
<th>Stock</th>
</tr>
</thead>
<tbody>
{products.map(product => (
<tr key={product.id}>
<td>{product.name}</td>
<td>{product.cost}</td>
<td>{product.price}</td>
<td>{product.stock}</td>
</tr>
))}
</tbody>
</table>
<h2>Add New Product</h2>
<form onSubmit={handleSubmit}>
<input type="text" name="name" placeholder="Name" value={newProduct.name} onChange={handleChange} required />
<input type="number" step="0.01" name="cost" placeholder="Cost" value={newProduct.cost} onChange={handleChange} required />
<input type="number" step="0.01" name="price" placeholder="Price" value={newProduct.price} onChange={handleChange} required />
<input type="number" name="stock" placeholder="Stock" value={newProduct.stock} onChange={handleChange} required />
<button type="submit">Add Product</button>
</form>
</div>
);
}
export default App;