Compare commits

...

2 Commits

Author SHA1 Message Date
Wiktor Szynaka
03bf26a8a1 Merge branch 'master' of https://git.wmi.amu.edu.pl/s464958/FirmTracker 2024-11-21 23:52:19 +01:00
Wiktor Szynaka
d656e183b6 rozbicie transakcji i produktów na więcej komponentów 2024-11-21 23:50:34 +01:00
10 changed files with 1150 additions and 815 deletions

View File

@ -3,7 +3,11 @@ import React, { useState, useEffect } from 'react';
import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom';
import PanelAdministratora from './components/PanelAdministratora';
import ZarzadzanieProduktami from './components/ZarzadzanieProduktami';
import Transakcje from './components/Transakcje';
import DodawanieProduktu from './components/DodawanieProduktów';
import EdycjaProduktu from './components/EdycjaProduktu';
import ZarzadzanieTransakcjami from './components/ZarzadzanieTransakcjami';
import DodawanieTransakcji from './components/DodawanieTransakcji';
import EdycjaTransakcji from './components/EdycjaTransakcji';
import NavBar from './components/NavBar';
import Sidebar from './components/Sidebar';
import Wydatki from './components/Wydatki';
@ -43,22 +47,18 @@ const App = () => {
)}
<div className="w-3/4">
<Routes>
{/* Przekierowanie na stronę logowania, jeśli token jest pusty */}
<Route path="/" element={token ? <Navigate to="/transakcje" /> : <Navigate to="/login" />} />
{/* Strona logowania */}
<Route path="/login" element={token ? <Navigate to="/transakcje" /> : <Login setToken={setToken} />} />
{/* Chronione ścieżki */}
<Route path="/transakcje" element={token ? <Transakcje /> : <Navigate to="/login" />} />
<Route path="/transakcje" element={token ? <ZarzadzanieTransakcjami /> : <Navigate to="/login" />} />
<Route path="/transakcje/dodaj" element={token ? <DodawanieTransakcji /> : <Navigate to="/login" />} />
<Route path="/transakcje/edytuj/:id" element={token ? <EdycjaTransakcji /> : <Navigate to="/login" />} />
<Route path="/panel" element={token ? <PanelAdministratora /> : <Navigate to="/login" />} />
<Route path="/produkty" element={token ? <ZarzadzanieProduktami /> : <Navigate to="/login" />} />
<Route path="/produkty/dodaj" element={token ? <DodawanieProduktu /> : <Navigate to="/login" />} />
<Route path="/produkty/edytuj/:id" element={token ? <EdycjaProduktu /> : <Navigate to="/login" />} />
<Route path="/wydatki" element={token ? <Wydatki /> : <Navigate to="/login" />} />
<Route path="/raporty" element={token ? <Raporty /> : <Navigate to="/login" />} />
<Route path="/harmonogram" element={token ? <Harmonogram /> : <Navigate to="/login" />} />
{/* Przekierowanie dla nieznanych ścieżek */}
<Route path="*" element={<Navigate to="/login" />} />
</Routes>
</div>
</div>

View File

@ -0,0 +1,130 @@
import React, { useState } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
const DodawanieProduktu = () => {
const [error, setError] = useState(null);
const [newProduct, setNewProduct] = useState({
name: '',
description: '',
price: '',
type: '1',
availability: '',
});
const navigate = useNavigate();
const handleInputChange = (event) => {
const { name, value } = event.target;
setNewProduct({ ...newProduct, [name]: value });
};
const handleAddProduct = async () => {
const { name, description, price, type, availability } = newProduct;
if (!name || !description || !price || type === '') {
setError('Proszę uzupełnić wszystkie wymagane pola.');
return;
}
const payload = {
name,
description,
price,
type: parseInt(type, 10),
...(type === '1' && { availability: availability || 0 }),
};
try {
const token = localStorage.getItem('token');
if (!token) {
setError('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
};
await axios.post('https://localhost:7039/api/Products', payload, config);
setNewProduct({
name: '',
description: '',
price: '',
type: '1',
availability: '',
});
setError(null);
navigate('/produkty');
} catch (error) {
console.error('Błąd podczas dodawania produktu:', error);
setError('Wystąpił błąd podczas dodawania produktu. Spróbuj ponownie.');
}
};
return (
<div className="p-8 bg-gray-100 rounded-lg shadow-md">
<h2 className="text-2xl font-bold mb-4">Dodaj nowy produkt lub usługę</h2>
{error && <p className="text-red-500 mb-4">{error}</p>}
<div className="grid grid-cols-2 gap-4">
<input
type="text"
name="name"
value={newProduct.name}
onChange={handleInputChange}
placeholder="Nazwa produktu lub usługi"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="description"
value={newProduct.description}
onChange={handleInputChange}
placeholder="Opis"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="number"
step="0.01"
name="price"
value={newProduct.price}
onChange={handleInputChange}
placeholder="Cena"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
/>
<select
name="type"
value={newProduct.type}
onChange={handleInputChange}
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
>
<option value="1">Produkt</option>
<option value="0">Usługa</option>
</select>
{newProduct.type === '1' && (
<input
type="number"
name="availability"
value={newProduct.availability}
onChange={handleInputChange}
placeholder="Dostępność (ilość)"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
/>
)}
</div>
<div className="mt-4">
<button
onClick={handleAddProduct}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
>
Dodaj
</button>
</div>
</div>
);
};
export default DodawanieProduktu;

View File

@ -0,0 +1,260 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
import Select from 'react-select';
const DodawanieTransakcji = () => {
const [error, setError] = useState(null);
const [newTransaction, setNewTransaction] = useState({
id: 2,
date: '',
employeeId: '',
paymentType: '',
discount: '',
description: '',
transactionProducts: [
{
id: 2,
transactionId: 0,
productID: 0,
productName: '',
quantity: ''
}
],
});
const [products, setProducts] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const navigate = useNavigate();
useEffect(() => {
const fetchProducts = async () => {
try {
const token = localStorage.getItem('token');
if (!token) {
setError('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
};
const response = await axios.get('https://localhost:7039/api/Products', config);
const productOptions = response.data.map(product => ({
value: product.id,
label: product.name,
}));
setProducts(productOptions);
} catch (error) {
setError('Wystąpił błąd podczas ładowania produktów.');
} finally {
setIsLoading(false);
}
};
fetchProducts();
}, []);
const handleInputChange = (event) => {
const { name, value } = event.target;
setNewTransaction({ ...newTransaction, [name]: value });
};
const handleProductChange = (index, selectedOption) => {
const updatedTransactionProducts = [...newTransaction.transactionProducts];
updatedTransactionProducts[index].productID = selectedOption.value;
updatedTransactionProducts[index].productName = selectedOption.label;
setNewTransaction({
...newTransaction,
transactionProducts: updatedTransactionProducts,
});
};
const handleAddProduct = () => {
setNewTransaction({
...newTransaction,
transactionProducts: [
...newTransaction.transactionProducts,
{
id: 2,
transactionId: 0,
productID: 0,
productName: '',
quantity: ''
}
]
});
};
const handleRemoveProduct = (index) => {
const updatedTransactionProducts = [...newTransaction.transactionProducts];
updatedTransactionProducts.splice(index, 1);
setNewTransaction({
...newTransaction,
transactionProducts: updatedTransactionProducts,
});
};
const handleAddTransaction = async () => {
if (!newTransaction.date || !newTransaction.employeeId || newTransaction.transactionProducts.some(product => !product.productName || !product.quantity)) {
setError('Proszę uzupełnić wszystkie pola.');
return;
}
try {
console.log('Nowa transakcja:', newTransaction);
const token = localStorage.getItem('token');
if (!token) {
setError('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
};
await axios.post('https://localhost:7039/api/Transaction', newTransaction, config);
setNewTransaction({
id: 0,
date: '',
employeeId: '',
transactionProducts: [
{
id: 0,
transactionId: 0,
productID: 0,
productName: '',
quantity: ''
}
],
paymentType: '',
discount: '',
description: '',
totalPrice: 0,
});
navigate('/transakcje');
} catch (error) {
console.error('Błąd podczas dodawania transakcji:', error);
if (error.response && error.response.data) {
setError(error.response.data);
} else {
setError('Wystąpił nieoczekiwany błąd. Spróbuj ponownie później.');
}
}
};
return (
<div className="bg-white p-8 rounded-lg">
<h2 className="text-2xl font-bold mb-4">Dodaj nową transakcję</h2>
{error && <p className="text-red-500 mb-4">{error}</p>}
<input
type="datetime-local"
name="date"
value={newTransaction.date}
onChange={handleInputChange}
placeholder="Data"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="number"
name="employeeId"
value={newTransaction.employeeId}
onChange={handleInputChange}
placeholder="Nr. Pracownika"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
{isLoading ? (
<div className="text-center">Ładowanie produktów...</div>
) : (
<>
{newTransaction.transactionProducts.map((product, index) => (
<div key={index} className="mb-4">
<Select
name={`productName-${index}`}
value={products.find(option => option.value === product.productID)}
onChange={(selectedOption) => handleProductChange(index, selectedOption)}
options={products}
className="block w-full mb-2"
placeholder="Wybierz produkt..."
/>
<input
type="number"
name={`quantity-${index}`}
value={product.quantity}
onChange={(e) => {
const updatedTransactionProducts = [...newTransaction.transactionProducts];
updatedTransactionProducts[index].quantity = e.target.value;
setNewTransaction({ ...newTransaction, transactionProducts: updatedTransactionProducts });
}}
placeholder="Ilość"
className="block w-full mb-2 px-4 py-2 border border-gray-300 rounded-lg"
/>
<button
onClick={() => handleRemoveProduct(index)}
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
>
Usuń
</button>
</div>
))}
</>
)}
<button
onClick={handleAddProduct}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 my-3 rounded"
>
Dodaj produkt
</button>
<input
type="text"
name="paymentType"
value={newTransaction.paymentType}
onChange={handleInputChange}
placeholder="Sposób płatności"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="number"
name="discount"
value={newTransaction.discount}
onChange={handleInputChange}
placeholder="Rabat"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="description"
value={newTransaction.description}
onChange={handleInputChange}
placeholder="Opis"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<button
onClick={handleAddTransaction}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 my-3 rounded"
>
Dodaj transakcję
</button>
</div>
);
};
export default DodawanieTransakcji;

View File

@ -0,0 +1,157 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useParams, useNavigate } from 'react-router-dom';
const EdycjaProduktu = () => {
const { id } = useParams();
const [product, setProduct] = useState({
name: '',
description: '',
price: '',
type: '1',
availability: '',
});
const [error, setError] = useState(null);
const navigate = useNavigate();
useEffect(() => {
const fetchProduct = async () => {
try {
const token = localStorage.getItem('token');
if (!token) {
setError('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
const response = await axios.get(`https://localhost:7039/api/Products/${id}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
setProduct(response.data);
} catch (error) {
console.error('Błąd podczas pobierania produktu:', error);
setError('Wystąpił błąd podczas pobierania danych produktu.');
}
};
fetchProduct();
}, [id]);
const handleInputChange = (event) => {
const { name, value } = event.target;
setProduct({ ...product, [name]: value });
};
const handleSaveChanges = async () => {
const { name, description, price, type, availability } = product;
if (!name || !description || !price || type === '') {
setError('Proszę uzupełnić wszystkie wymagane pola.');
return;
}
const payload = {
id,
name,
description,
price,
type: parseInt(type, 10),
...(type === '1' && { availability: availability || 0 }),
};
try {
const token = localStorage.getItem('token');
if (!token) {
setError('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
};
const response = await axios.put(`https://localhost:7039/api/Products/${id}`, payload, config);
console.log('Produkt zapisany:', response.data);
setError(null);
navigate('/produkty');
} catch (error) {
console.error('Błąd podczas zapisywania zmian:', error);
if (error.response && error.response.status === 400) {
setError('ID produktu nie zgadza się.');
} else {
setError('Wystąpił błąd podczas zapisywania zmian. Spróbuj ponownie.');
}
}
};
return (
<div className="p-8 bg-gray-100 rounded-lg shadow-md">
<h2 className="text-2xl font-bold mb-4">Edycja produktu</h2>
{error && <p className="text-red-500 mb-4">{error}</p>}
<div className="grid grid-cols-2 gap-4">
<input
type="text"
name="name"
value={product.name}
onChange={handleInputChange}
placeholder="Nazwa produktu lub usługi"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="description"
value={product.description}
onChange={handleInputChange}
placeholder="Opis"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="number"
step="0.01"
name="price"
value={product.price}
onChange={handleInputChange}
placeholder="Cena"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
/>
<select
name="type"
value={product.type}
onChange={handleInputChange}
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
>
<option value="1">Produkt</option>
<option value="0">Usługa</option>
</select>
{product.type === '1' && (
<input
type="number"
name="availability"
value={product.availability}
onChange={handleInputChange}
placeholder="Dostępność (ilość)"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg"
/>
)}
</div>
<div className="mt-4">
<button
onClick={handleSaveChanges}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
>
Zapisz zmiany
</button>
</div>
</div>
);
};
export default EdycjaProduktu;

View File

@ -0,0 +1,243 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useParams, useNavigate } from 'react-router-dom';
import Select from 'react-select';
const EdycjaTransakcji = () => {
const { id } = useParams();
const [transaction, setTransaction] = useState({
date: '',
employeeId: '',
paymentType: '',
discount: '',
description: '',
transactionProducts: [{ productID: '', productName: '', quantity: '' }],
});
const [products, setProducts] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const navigate = useNavigate();
const getToken = () => {
const token = localStorage.getItem('token');
if (!token) {
setError('Brak tokena. Użytkownik musi być zalogowany.');
}
return token;
};
useEffect(() => {
const fetchTransaction = async () => {
try {
const token = getToken();
if (!token) return;
const transactionResponse = await axios.get(`https://localhost:7039/api/transaction/${id}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log('Dane transakcji:', transactionResponse.data);
const updatedTransaction = {
...transactionResponse.data,
transactionProducts: transactionResponse.data.transactionProducts.map((transactionProduct) => ({
productID: transactionProduct.product.id,
productName: transactionProduct.product.name,
quantity: transactionProduct.quantity,
})),
};
setTransaction(updatedTransaction);
const productResponse = await axios.get('https://localhost:7039/api/Products', {
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log('Produkty:', productResponse.data);
const productOptions = productResponse.data.map((product) => ({
value: product.id,
label: product.name,
}));
setProducts(productOptions);
} catch (error) {
console.error('Błąd podczas pobierania transakcji lub produktów:', error);
setError('Wystąpił błąd podczas ładowania danych.');
} finally {
setIsLoading(false);
}
};
fetchTransaction();
}, [id]);
const handleInputChange = (event) => {
const { name, value } = event.target;
setTransaction({ ...transaction, [name]: value });
};
const handleProductChange = (index, selectedOption) => {
const updatedTransactionProducts = [...transaction.transactionProducts];
updatedTransactionProducts[index].productID = selectedOption.value;
updatedTransactionProducts[index].productName = selectedOption.label;
setTransaction({
...transaction,
transactionProducts: updatedTransactionProducts,
});
};
const handleAddProduct = () => {
setTransaction({
...transaction,
transactionProducts: [
...transaction.transactionProducts,
{ productID: 0, productName: '', quantity: '' },
],
});
};
const handleRemoveProduct = (index) => {
const updatedTransactionProducts = [...transaction.transactionProducts];
updatedTransactionProducts.splice(index, 1);
setTransaction({
...transaction,
transactionProducts: updatedTransactionProducts,
});
};
const handleSaveChanges = async () => {
if (!transaction.date || !transaction.employeeId || transaction.transactionProducts.some(product => !product.productName || !product.quantity)) {
setError('Proszę uzupełnić wszystkie pola.');
return;
}
try {
const token = getToken();
if (!token) {
setError('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
const response = await axios.put(`https://localhost:7039/api/transaction/${id}`, transaction, {
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log('Zaktualizowana transakcja:', response.data);
navigate('/transakcje');
} catch (error) {
console.error('Błąd podczas zapisywania zmian:', error);
setError('Wystąpił błąd podczas zapisywania zmian.');
}
};
return (
<div className="bg-white p-8 rounded-lg">
<h2 className="text-2xl font-bold mb-4">Edycja Transakcji</h2>
{error && <p className="text-red-500 mb-4">{error}</p>}
<input
type="datetime-local"
name="date"
value={transaction.date}
onChange={handleInputChange}
placeholder="Data"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="number"
name="employeeId"
value={transaction.employeeId}
onChange={handleInputChange}
placeholder="Nr. Pracownika"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
{isLoading ? (
<div className="text-center">Ładowanie produktów...</div>
) : (
<>
{transaction.transactionProducts.map((product, index) => (
<div key={index} className="mb-4">
<Select
name={`productName-${index}`}
value={products.find(option => option.value === product.productID) || null}
onChange={(selectedOption) => handleProductChange(index, selectedOption)}
options={products}
className="block w-full mb-2"
placeholder="Wybierz produkt..."
/>
<input
type="number"
name={`quantity-${index}`}
value={product.quantity}
onChange={(e) => {
const updatedTransactionProducts = [...transaction.transactionProducts];
updatedTransactionProducts[index].quantity = e.target.value;
setTransaction({ ...transaction, transactionProducts: updatedTransactionProducts });
}}
placeholder="Ilość"
className="block w-full mb-2 px-4 py-2 border border-gray-300 rounded-lg"
/>
<button
onClick={() => handleRemoveProduct(index)}
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
>
Usuń
</button>
</div>
))}
</>
)}
<button
onClick={handleAddProduct}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 my-3 rounded"
>
Dodaj produkt
</button>
<input
type="text"
name="paymentType"
value={transaction.paymentType}
onChange={handleInputChange}
placeholder="Sposób płatności"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="number"
name="discount"
value={transaction.discount}
onChange={handleInputChange}
placeholder="Rabat"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="description"
value={transaction.description}
onChange={handleInputChange}
placeholder="Opis"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<button
onClick={handleSaveChanges}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 my-3 rounded"
>
Zapisz zmiany
</button>
</div>
);
};
export default EdycjaTransakcji;

View File

@ -0,0 +1,135 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import editIcon from '../icons/edit.png';
import koszIcon from '../icons/kosz.png';
import { useNavigate } from 'react-router-dom';
const ListaProduktow = ({ onAdd }) => {
const [products, setProducts] = useState([]);
const [deleteProductId, setDeleteProductId] = useState(null);
const [showModal, setShowModal] = useState(false);
const navigate = useNavigate();
const fetchProducts = async () => {
const token = localStorage.getItem('token');
try {
const response = await axios.get('https://localhost:7039/api/products', {
headers: { Authorization: `Bearer ${token}` },
});
setProducts(response.data);
} catch (error) {
console.error('Błąd podczas pobierania produktów:', error);
}
};
useEffect(() => {
fetchProducts();
}, []);
const handleDeleteProduct = async () => {
const token = localStorage.getItem('token');
if (!token) {
alert('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
if (!deleteProductId) {
console.error('Brak ID produktu do usunięcia!');
return;
}
try {
await axios.delete(`https://localhost:7039/api/Products/${deleteProductId}`, {
headers: { Authorization: `Bearer ${token}` },
});
fetchProducts();
setShowModal(false);
setDeleteProductId(null);
} catch (error) {
console.error('Błąd podczas usuwania produktu:', error);
}
};
const handleEditProduct = (productId) => {
navigate(`/produkty/edytuj/${productId}`);
};
return (
<div>
<div className="flex items-center justify-between">
<h1 className="text-5xl">Katalog Produktów</h1>
<button onClick={onAdd} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
Dodaj Produkt
</button>
</div>
<div className="mt-5">
<table className="w-full border border-gray-300">
<thead className="bg-gray-200">
<tr>
<th className="p-2 border">ID</th>
<th className="p-2 border">Produkt</th>
<th className="p-2 border">Opis</th>
<th className="p-2 border">Cena</th>
<th className="p-2 border">Dostępność</th>
<th className="p-2 border"></th>
</tr>
</thead>
<tbody>
{products.map((product) => (
<tr key={product.id}>
<td className="p-2 border">{product.id}</td>
<td className="p-2 border">{product.name}</td>
<td className="p-2 border">{product.description}</td>
<td className="p-2 border">{parseFloat(product.price).toFixed(2)}</td>
<td className="p-2 border">{product.availability}</td>
<td className="p-2 border">
<button
onClick={() => handleEditProduct(product.id)}
className="mr-2 bg-blue-500 text-white py-2 px-4 rounded"
>
<img src={editIcon} alt="Edytuj" className="inline w-5 mr-2" />
Edytuj
</button>
<button
onClick={() => {
setDeleteProductId(product.id);
setShowModal(true);
}}
className="bg-red-500 text-white py-2 px-4 rounded"
>
<img src={koszIcon} alt="Usuń" className="inline w-5 mr-2" />
Usuń
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
{showModal && (
<div className="fixed inset-0 bg-gray-500 bg-opacity-50 flex justify-center items-center z-50">
<div className="bg-white p-6 rounded-md shadow-lg w-96">
<h2 className="text-lg font-bold mb-4">Czy na pewno chcesz usunąć ten produkt?</h2>
<div className="flex justify-between">
<button
onClick={handleDeleteProduct}
className="bg-red-500 text-white py-2 px-4 rounded"
>
Tak
</button>
<button
onClick={() => setShowModal(false)}
className="bg-gray-500 text-white py-2 px-4 rounded"
>
Anuluj
</button>
</div>
</div>
</div>
)}
</div>
);
};
export default ListaProduktow;

View File

@ -0,0 +1,177 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import editIcon from '../icons/edit.png';
import koszIcon from '../icons/kosz.png';
import { useNavigate } from 'react-router-dom';
const ListaTransakcji = ({ onAdd}) => {
const [transactions, setTransactions] = useState([]);
const [deleteTransactionId, setDeleteTransactionId] = useState(null);
const [showModal, setShowModal] = useState(false);
const navigate = useNavigate();
const fetchTransactions = async () => {
const token = localStorage.getItem('token');
if (!token) {
console.error('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
try {
const response = await axios.get('https://localhost:7039/api/Transaction', {
headers: {
Authorization: `Bearer ${token}`,
},
});
setTransactions(response.data);
} catch (error) {
console.error('Błąd podczas pobierania transakcji:', error);
}
};
const fetchProducts = async () => {
const token = localStorage.getItem('token');
if (!token) {
console.error('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
try {
const response = await axios.get('https://localhost:7039/api/Products', {
headers: {
Authorization: `Bearer ${token}`,
},
});
response.data.map(product => ({ value: product.id, label: product.name }));
} catch (error) {
console.error('Błąd podczas pobierania produktów:', error);
}
};
useEffect(() => {
fetchTransactions();
fetchProducts();
}, []);
const formatDate = (date) => {
const newDate = new Date(date);
return newDate.toLocaleDateString();
};
const formatPrice = (price) => {
return price.toFixed(2).replace('.', ',');
};
const handleDeleteTransaction = async () => {
try {
await axios.delete(`https://localhost:7039/api/transaction/${deleteTransactionId}`, {
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`,
},
});
setTransactions(transactions.filter(transaction => transaction.id !== deleteTransactionId));
setShowModal(false);
setDeleteTransactionId(null);
} catch (error) {
console.error('Błąd podczas usuwania transakcji:', error);
}
};
const openDeleteConfirmation = (transactionId) => {
setDeleteTransactionId(transactionId);
setShowModal(true);
};
const handleEditTransaction = (transactionId) => {
navigate(`/transakcje/edytuj/${transactionId}`);
};
return (
<div>
<div className="flex items-center justify-between">
<h1 className="text-5xl">Lista Transakcji</h1>
<button onClick={onAdd} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
Dodaj Transakcję
</button>
</div>
<div className="w-8/10 mx-auto mt-2">
<div className="h-screen overflow-y-auto">
<table className="w-full border-collapse border border-gray-300">
<thead className="bg-gray-200">
<tr>
<th className="border border-gray-300 p-2">ID</th>
<th className="border border-gray-300 p-2">Data</th>
<th className="border border-gray-300 p-2">Produkt</th>
<th className="border border-gray-300 p-2">Ilość</th>
<th className="border border-gray-300 p-2">Kwota</th>
<th className="border border-gray-300 p-2">Sposób płatności</th>
<th className="border border-gray-300 p-2">Nr. Pracownika</th>
<th className="border border-gray-300 p-2"></th>
</tr>
</thead>
<tbody>
{transactions.map(transaction => (
<tr key={transaction.id}>
<td className="border border-gray-300 p-2">{transaction.id}</td>
<td className="border border-gray-300 p-2">{formatDate(transaction.date)}</td>
<td className="border border-gray-300 p-2">
{transaction.transactionProducts.map(product => (
<div key={product.id}>{product.product.name}</div>
))}
</td>
<td className="border border-gray-300 p-2">
{transaction.transactionProducts.map(product => (
<div key={product.id}>{product.quantity}</div>
))}
</td>
<td className="border border-gray-300 p-2">{formatPrice(transaction.totalPrice)}</td>
<td className="border border-gray-300 p-2">{transaction.paymentType}</td>
<td className="border border-gray-300 p-2">{transaction.employeeId}</td>
<td className="p-2 border">
<button
onClick={() => handleEditTransaction(transaction.id)}
className="mr-2 bg-blue-500 text-white py-2 px-4 rounded"
>
<img src={editIcon} alt="Edytuj" className="inline w-5 mr-2" />
Edytuj
</button>
<button
onClick={() => openDeleteConfirmation(transaction.id)}
className="bg-red-500 text-white py-2 px-4 rounded"
>
<img src={koszIcon} alt="Usuń" className="inline w-5 mr-2" />
Usuń
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{showModal && (
<div className="fixed inset-0 bg-gray-500 bg-opacity-50 flex justify-center items-center z-50">
<div className="bg-white p-6 rounded-md shadow-lg w-96">
<h2 className="text-lg font-bold mb-4">Czy na pewno chcesz usunąć transakcję?</h2>
<div className="flex justify-between">
<button
onClick={handleDeleteTransaction}
className="bg-red-500 text-white py-2 px-4 rounded"
>
Tak
</button>
<button
onClick={() => setShowModal(false)}
className="bg-gray-500 text-white py-2 px-4 rounded"
>
Anuluj
</button>
</div>
</div>
</div>
)}
</div>
);
};
export default ListaTransakcji;

View File

@ -1,488 +0,0 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import Select from 'react-select';
import editIcon from "../icons/edit.png";
import koszIcon from "../icons/kosz.png";
import plusIcon from "../icons/plus.png";
import ConfirmationModal from './ConfirmationModal';
const Transakcje = () => {
const [transactions, setTransactions] = useState([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [editTransaction, setEditTransaction] = useState(null);
const [error, setError] = useState(null);
const [products, setProducts] = useState([]);
const [deleteTransactionId, setDeleteTransactionId] = useState(null);
const [newTransaction, setNewTransaction] = useState({
id: 2,
date: "",
employeeId: "",
transactionProducts: [
{
id: 0,
transactionId: 2,
productID: 0,
productName: "",
quantity: ""
}
],
paymentType: "",
discount: "",
description: "",
totalPrice: 0
});
const fetchTransactions = async () => {
const token = localStorage.getItem('token');
if (!token) {
console.error('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
try {
const response = await axios.get('https://localhost:7039/api/Transaction', {
headers: {
Authorization: `Bearer ${token}`
}
});
setTransactions(response.data);
} catch (error) {
console.error('Błąd podczas dodawania transakcji:', error);
}
};
const fetchProducts = async () => {
const token = localStorage.getItem('token');
if (!token) {
console.error('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
try {
const response = await axios.get('https://localhost:7039/api/Products', {
headers: {
Authorization: `Bearer ${token}`
}
});
setProducts(response.data.map(product => ({ value: product.id, label: product.name })));
} catch (error) {
console.error('Błąd podczas pobierania produktów:', error);
}
};
useEffect(() => {
fetchTransactions();
fetchProducts();
console.log();
}, []);
const handleAddTransaction = async () => {
if (!newTransaction.date || !newTransaction.employeeId || newTransaction.transactionProducts.some(product => !product.productName || !product.quantity)) {
setError('Proszę uzupełnić wszystkie pola.');
return;
}
try {
console.log('Nowa transakcja:', newTransaction);
await axios.post('https://localhost:7039/api/Transaction', newTransaction);
fetchTransactions();
setIsModalOpen(false);
setNewTransaction({
id: 2,
date: "",
employeeId: "",
transactionProducts: [
{
id: 2,
transactionId: 0,
productID: 0,
productName: "",
quantity: ""
}
],
paymentType: "",
discount: "",
description: "",
totalPrice: 0
});
} catch (error) {
console.error('Błąd podczas dodawania transakcji:', error);
if (error.response && error.response.data) {
setError(error.response.data);
} else {
setError('Wystąpił nieoczekiwany błąd. Spróbuj ponownie później.');
}
}
};
const formatDate = (dateString) => {
const options = { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' };
const date = new Date(dateString);
return date.toLocaleDateString('pl-PL', options).replace(",", "");
};
const formatPrice = (price) => {
return parseFloat(price).toFixed(2);
};
const handleAddProduct = () => {
setNewTransaction({
...newTransaction,
transactionProducts: [
...newTransaction.transactionProducts,
{
id: 2,
transactionId: 0,
productID: 0,
productName: "",
quantity: ""
}
]
});
};
const handleRemoveProduct = (index) => {
const updatedTransactionProducts = [...newTransaction.transactionProducts];
updatedTransactionProducts.splice(index, 1);
setNewTransaction({
...newTransaction,
transactionProducts: updatedTransactionProducts
});
};
const handleDeleteTransaction = async (transactionId) => {
try {
await axios.delete(`https://localhost:7039/api/Transaction/${transactionId}`);
fetchTransactions();
setDeleteTransactionId(null);
} catch (error) {
console.error('Błąd podczas usuwania transakcji:', error);
if (error.response && error.response.data) {
setError(error.response.data);
} else {
setError('Wystąpił nieoczekiwany błąd. Spróbuj ponownie później.');
}
}
};
const handleEditTransaction = async (transaction) => {
try {
if (!editTransaction) {
setEditTransaction(transaction);
setIsEditModalOpen(true);
return;
}
if (!editTransaction.date || !editTransaction.employeeId || editTransaction.transactionProducts.some(product => !product.productName || !product.quantity) || !editTransaction.paymentType){
setError('Proszę uzupełnić wszystkie pola.');
return;}
await axios.put(`https://localhost:7039/api/Transaction/${editTransaction.id}`, editTransaction);
fetchTransactions();
setIsEditModalOpen(false);
setEditTransaction(null);
setError(null);
} catch (error) {
console.error('Błąd podczas edycji transakcji:', error);
if (error.response && error.response.data) {
setError(error.response.data);
} else {
setError('Wystąpił nieoczekiwany błąd. Spróbuj ponownie później.');
}
}
};
const handleProductChange = (index, selectedOption) => {
const updatedTransactionProducts = [...newTransaction.transactionProducts];
updatedTransactionProducts[index].productID = selectedOption.value;
updatedTransactionProducts[index].productName = selectedOption.label;
setNewTransaction({
...newTransaction,
transactionProducts: updatedTransactionProducts
});
};
const handleEditProductChange = (index, selectedOption) => {
const updatedTransactionProducts = [...editTransaction.transactionProducts];
updatedTransactionProducts[index].productID = selectedOption.value;
updatedTransactionProducts[index].productName = selectedOption.label;
setEditTransaction({
...editTransaction,
transactionProducts: updatedTransactionProducts
});
};
const openDeleteConfirmation = (transactionId) => {
setDeleteTransactionId(transactionId);
};
const closeDeleteConfirmation = () => {
setDeleteTransactionId(null);
};
return (
<div className='p-10 ml-11'>
<div className='flex items-center justify-between'>
<div className='h-20 text-5xl ml-1'>
Lista Transakcji
</div>
<button onClick={() => setIsModalOpen(true)} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded flex">
<img src={plusIcon} alt="" className="w-8 h-8 mr-2" />Dodaj
</button>
</div>
{error && (
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 flex items-center justify-center">
<div className="bg-white p-8 rounded-lg">
<h2 className="text-2xl font-bold mb-4">Błąd</h2>
<p>{error}</p>
<button onClick={() => window.location.reload()} className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">
Zamknij
</button>
</div>
</div>
)}
{isEditModalOpen && editTransaction && (
<div className="absolute top-0 left-0 w-full h-screen bg-black bg-opacity-50 flex items-center justify-center">
<div className="bg-white p-8 rounded-lg">
<h2 className="text-2xl font-bold mb-4">Edytuj transakcję</h2>
<input
type="datetime-local"
name="date"
value={editTransaction.date}
onChange={(e) => setEditTransaction({ ...editTransaction, date: e.target.value })}
placeholder="Data"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
Numer Pracownika
<input
type="number"
name="employeeId"
value={editTransaction.employeeId}
onChange={(e) => setEditTransaction({ ...editTransaction, employeeId: e.target.value })}
placeholder="Nr. Pracownika"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
{editTransaction.transactionProducts.map((product, index) => (
<div key={index}>
<Select
name={`productName-${index}`}
value={products.find(option => option.value === product.productName)}
onChange={(selectedOption) => handleEditProductChange(index, selectedOption)}
options={products}
className="block w-full mb-4"
placeholder="Wybierz produkt..."
/>
Ilość
<input
type="number"
name={`quantity-${index}`}
value={product.quantity}
onChange={(e) => {
const newTransactionProducts = [...editTransaction.transactionProducts];
newTransactionProducts[index].quantity = e.target.value;
setEditTransaction({ ...editTransaction, transactionProducts: newTransactionProducts });
}}
placeholder="Ilość"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
</div>
))}
<input
type="text"
name="paymentType"
value={editTransaction.paymentType}
onChange={(e) => setEditTransaction({ ...editTransaction, paymentType: e.target.value })}
placeholder="Sposób płatności"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
Zniżka
<input
type="number"
name="discount"
value={editTransaction.discount}
onChange={(e) => setEditTransaction({ ...editTransaction, discount: e.target.value })}
placeholder="Rabat"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="description"
value={editTransaction.description}
onChange={(e) => setEditTransaction({ ...editTransaction, description: e.target.value })}
placeholder="Opis"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<button
onClick={() => {
handleEditTransaction();
setIsEditModalOpen(false);
}}
className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
>
Zapisz zmiany
</button>
<button
onClick={() => window.location.reload()}
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
>
Anuluj
</button>
</div>
</div>
)}
{isModalOpen && (
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 flex items-center justify-center">
<div className="bg-white p-8 rounded-lg">
<h2 className="text-2xl font-bold mb-4">Dodaj nową transakcję</h2>
<input
type="datetime-local"
name="date"
value={newTransaction.date}
onChange={(e) => setNewTransaction({ ...newTransaction, date: e.target.value })}
placeholder="Data"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="number"
name="employeeId"
value={newTransaction.employeeId}
onChange={(e) => setNewTransaction({ ...newTransaction, employeeId: e.target.value })}
placeholder="Nr. Pracownika"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
{newTransaction.transactionProducts.map((product, index) => (
<div key={index}>
<Select
name={`productName-${index}`}
value={products.find(option => option.value === product.productName)}
onChange={(selectedOption) => handleProductChange(index, selectedOption)}
options={products}
className="block w-full mb-4"
placeholder="Wybierz produkt..."
/>
<input
type="number"
name={`quantity-${index}`}
value={product.quantity}
onChange={(e) => {
const newTransactionProducts = [...newTransaction.transactionProducts];
newTransactionProducts[index].quantity = e.target.value;
setNewTransaction({ ...newTransaction, transactionProducts: newTransactionProducts });
}}
placeholder="Ilość" className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<button onClick={() => handleRemoveProduct(index)} className="bg-red-500 hover:bg-red-700 text-white font-bold my-2 py-2 px-4 rounded">
Usuń
</button>
</div>
))}
<button onClick={handleAddProduct} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 my-3 rounded">
Dodaj
</button>
<input
type="text"
name="paymentType"
value={newTransaction.paymentType}
onChange={(e) => setNewTransaction({ ...newTransaction, paymentType: e.target.value })}
placeholder="Sposób płatności"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="number"
name="discount"
value={newTransaction.discount}
onChange={(e) => setNewTransaction({ ...newTransaction, discount: e.target.value })}
placeholder="Rabat"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="description"
value={newTransaction.description}
onChange={(e) => setNewTransaction({ ...newTransaction, description: e.target.value })}
placeholder="Opis"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<button
onClick={() => {
handleAddTransaction();
setIsModalOpen(false);
}}
className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
>
Dodaj transakcję
</button>
<button
onClick={() => setIsModalOpen(false)}
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 mx-1 rounded"
>
Anuluj
</button>
</div>
</div>
)}
<div className="w-8/10 mx-auto mt-2">
<div className="h-screen overflow-y-auto">
<table className="w-full border-collapse border border-gray-300">
<thead className="bg-gray-200">
<tr>
<th className="border border-gray-300 p-2">ID</th>
<th className="border border-gray-300 p-2">Data</th>
<th className="border border-gray-300 p-2">Produkt</th>
<th className="border border-gray-300 p-2">Ilość</th>
<th className="border border-gray-300 p-2">Kwota</th>
<th className="border border-gray-300 p-2">Sposób płatności</th>
<th className="border border-gray-300 p-2">Nr. Pracownika</th>
<th className="border border-gray-300 p-2"></th>
<th className="border border-gray-300 p-2"></th>
</tr>
</thead>
<tbody>
{transactions.map(transaction => (
<tr key={transaction.id}>
<td className="border border-gray-300 p-2">{transaction.id}</td>
<td className="border border-gray-300 p-2">{formatDate(transaction.date)}</td>
<td className="border border-gray-300 p-2">
{transaction.transactionProducts.map(product => (
<div key={product.id}>{product.product.name}</div>
))}
</td>
<td className="border border-gray-300 p-2">
{transaction.transactionProducts.map(product => (
<div key={product.id}>{product.quantity}</div>
))}
</td>
<td className="border border-gray-300 p-2">{formatPrice(transaction.totalPrice)}</td>
<td className="border border-gray-300 p-2">{transaction.paymentType}</td>
<td className="border border-gray-300 p-2">{transaction.employeeId}</td>
<td className="border border-gray-300 p-2"><button onClick={() =>{handleEditTransaction(transaction);
console.log(transaction);
}
}
className="mr-2 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded flex">
<img src={editIcon} alt="" className="w-8 h-8 mr-2" />Edytuj
</button></td>
<td className="border border-gray-300 p-2"><button onClick={() => openDeleteConfirmation(transaction.id)}
className="mr-2 bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded flex">
<img src={koszIcon} alt="" className="w-8 h-8 mr-2" />Usuń
</button></td>
</tr>
))}
</tbody>
</table>
</div>
<div className="flex justify-start mt-4">
</div>
</div>
{deleteTransactionId && (
<ConfirmationModal
message="Czy na pewno chcesz usunąć tę transakcję?"
onCancel={closeDeleteConfirmation}
onConfirm={() => {handleDeleteTransaction(deleteTransactionId); setDeleteTransactionId(false);}}
/>)}
</div>
);
}
export default Transakcje

View File

@ -1,325 +1,22 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import editIcon from "../icons/edit.png";
import koszIcon from "../icons/kosz.png";
import plusIcon from "../icons/plus.png";
import ConfirmationModal from './ConfirmationModal';
import React from 'react';
import { Routes, Route, useNavigate } from 'react-router-dom';
import ListaProduktow from './ListaProduktów';
import DodawanieProduktu from './DodawanieProduktów';
import EdycjaProduktu from './EdycjaProduktu';
const ZarzadzanieProduktami = () => {
const [products, setProducts] = useState([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [error, setError] = useState(null);
const [deleteProductId, setDeleteProductId] = useState(null);
const [newProduct, setNewProduct] = useState({
name: "",
description: "",
price: "",
type: "",
availability: ""
});
const [editProduct, setEditProduct] = useState(null);
const fetchProducts = async () => {
const token = localStorage.getItem('token');
if (!token) {
console.error('Brak tokena. Użytkownik musi być zalogowany.');
return;
}
try {
const response = await axios.get('https://localhost:7039/api/products', {
headers: {
Authorization: `Bearer ${token}`
}
});
setProducts(response.data);
} catch (error) {
console.error('Błąd podczas pobierania produktów:', error);
}
};
useEffect(() => {
fetchProducts();
}, []);
const handleInputChange = (event) => {
const { name, value } = event.target;
setNewProduct({ ...newProduct, [name]: value });
};
const handleAddProduct = async () => {
if (!newProduct.name || !newProduct.description || !newProduct.price || !newProduct.type || !newProduct.availability) {
setError('Proszę uzupełnić wszystkie pola.');
return;
}
try {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
await axios.post('https://localhost:7039/api/Products', newProduct, config);
fetchProducts();
setIsModalOpen(false);
setNewProduct({
name: "",
availability: "",
price: "",
type: "",
description: ""
});
} catch (error) {
console.error('Błąd podczas dodawania:', error);
if (error.response && error.response.data) {
setError(error.response.data);
} else {
setError('Wystąpił nieoczekiwany błąd. Spróbuj ponownie później.');
}
}
};
const handleEditProduct = (product) => {
setEditProduct(product);
setIsEditModalOpen(true);
};
const handleSaveEditedProduct = async () => {
if (!editProduct.name || !editProduct.description || !editProduct.price || !editProduct.type || !editProduct.availability) {
setError('Proszę uzupełnić wszystkie pola.');
return;
}
try {
await axios.put(`https://localhost:7039/api/Products/${editProduct.id}`, editProduct);
fetchProducts();
setIsEditModalOpen(false);
} catch (error) {
console.error('Błąd podczas edycji:', error);
if (error.response && error.response.data) {
setError(error.response.data);
} else {
setError('Wystąpił nieoczekiwany błąd. Spróbuj ponownie później.');
}
}
};
const handleDeleteProduct = async () => {
try {
await axios.delete(`https://localhost:7039/api/Products/${deleteProductId}`);
fetchProducts();
setDeleteProductId(null);
} catch (error) {
console.error('Błąd podczas usuwania produktu:', error);
if (error.response && error.response.data) {
setError(error.response.data);
} else {
setError('Wystąpił nieoczekiwany błąd. Spróbuj ponownie później.');
}
}
};
const openDeleteConfirmation = (productId) => {
setDeleteProductId(productId);
};
const closeDeleteConfirmation = () => {
setDeleteProductId(null);
};
const formatPrice = (price) => {
return parseFloat(price).toFixed(2);
};
const navigate = useNavigate();
return (
<div className='p-10 ml-11'>
<div className='flex items-center justify-between'>
<div className='h-20 text-5xl ml-1'>
Katalog Produktów
</div>
<button onClick={() => setIsModalOpen(true)} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded flex">
<img src={plusIcon} alt="" className="w-8 h-8 mr-2" />Dodaj
</button>
</div>
{error && (
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 flex items-center justify-center">
<div className="bg-white p-8 rounded-lg">
<h2 className="text-2xl font-bold mb-4">Błąd</h2>
<p>{error}</p>
<button onClick={() => window.location.reload()} className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">
Zamknij
</button>
</div>
</div>
)}
{isEditModalOpen && editProduct && (
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white p-8 rounded-lg shadow-lg">
<h2 className="text-2xl font-bold mb-4">Edytuj produkt</h2>
<input
type="text"
name="name"
value={editProduct.name}
onChange={(e) => setEditProduct({ ...editProduct, name: e.target.value })}
placeholder="Nazwa produktu"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="description"
value={editProduct.description}
onChange={(e) => setEditProduct({ ...editProduct, description: e.target.value })}
placeholder="Opis"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="price"
value={editProduct.price}
onChange={(e) => setEditProduct({ ...editProduct, price: e.target.value })}
placeholder="Cena"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="type"
value={editProduct.type}
onChange={(e) => setEditProduct({ ...editProduct, type: e.target.value })}
placeholder="Typ"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="availability"
value={editProduct.availability}
onChange={(e) => setEditProduct({ ...editProduct, availability: e.target.value })}
placeholder="Dostępność"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<button
onClick={() => {
handleSaveEditedProduct();
setIsEditModalOpen(false);
}}
className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
>
Zapisz zmiany
</button>
<button
onClick={() => setIsEditModalOpen(false)}
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
>
Anuluj
</button>
</div>
</div>
)}
{isModalOpen && (
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 flex items-center justify-center z-70">
<div className="bg-white p-8 rounded-lg shadow-lg">
<h2 className="text-2xl font-bold mb-4">Dodaj nowy produkt</h2>
<input
type="text"
name="name"
value={newProduct.name}
onChange={handleInputChange}
placeholder="Nazwa produktu"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="description"
value={newProduct.description}
onChange={handleInputChange}
placeholder="Opis"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="price"
value={newProduct.price}
onChange={handleInputChange}
placeholder="Cena"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="type"
value={newProduct.type}
onChange={handleInputChange}
placeholder="Kategoria"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<input
type="text"
name="availability"
value={newProduct.availability}
onChange={handleInputChange}
placeholder="Dostępność"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/>
<button
onClick={() => {
handleAddProduct();
setIsModalOpen(false)
}}
className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
>
Dodaj produkt
</button>
<button
onClick={() => setIsModalOpen(false)}
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
>
Anuluj
</button>
</div>
</div>
)}
<div className="w-8/10 mx-auto mt-2">
<div className="h-screen overflow-y-auto">
<table className="w-full border-collapse border border-gray-300">
<thead className="bg-gray-200 top-0 z-10 sticky">
<tr>
<th className="border border-gray-300 p-2">ID</th>
<th className="border border-gray-300 p-2">Produkt</th>
<th className="border border-gray-300 p-2">Opis</th>
<th className="border border-gray-300 p-2">Cena</th>
<th className="border border-gray-300 p-2">Kategoria</th>
<th className="border border-gray-300 p-2">Dostępność</th>
<th className="border border-gray-300 p-2"></th>
<th className="border border-gray-300 p-2"></th>
</tr>
</thead>
<tbody>
{products.map(product => (
<tr key={product.id}>
<td className="border border-gray-300 p-2">{product.id}</td>
<td className="border border-gray-300 p-2">{product.name}</td>
<td className="border border-gray-300 p-2">{product.description}</td>
<td className="border border-gray-300 p-2">{formatPrice(product.price)}</td>
<td className="border border-gray-300 p-2">{product.type}</td>
<td className="border border-gray-300 p-2">{product.availability}</td>
<td className="border border-gray-300 p-2"><button onClick={() => handleEditProduct(product)}
className="mr-2 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded flex">
<img src={editIcon} alt="" className="w-8 h-8 mr-2" />Edytuj
</button></td>
<td className="border border-gray-300 p-2">
<button onClick={() => openDeleteConfirmation(product.id)}
className="mr-2 bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded flex">
<img src={koszIcon} alt="" className="w-8 h-8 mr-2" />Usuń
</button></td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{deleteProductId && (
<ConfirmationModal
message="Czy na pewno chcesz usunąć ten produkt?"
onCancel={closeDeleteConfirmation}
onConfirm={ () => {handleDeleteProduct(); setDeleteProductId(false);}}
<div className="p-10 ml-11">
<Routes>
<Route
path="/"
element={<ListaProduktow onAdd={() => navigate('/produkty/dodaj')} onEdit={(id) => navigate(`/produkty/edytuj/${id}`)} />}
/>
)}
<Route path="/dodaj" element={<DodawanieProduktu />} />
<Route path="/edytuj/:id" element={<EdycjaProduktu />} />
</Routes>
</div>
);
};

View File

@ -0,0 +1,24 @@
import React from 'react';
import { Routes, Route, useNavigate } from 'react-router-dom';
import ListaTransakcji from './ListaTransakcji';
import DodawanieTransakcji from './DodawanieTransakcji';
import EdycjaTransakcji from './EdycjaTransakcji';
const ZarzadzanieTransakcjami = () => {
const navigate = useNavigate();
return (
<div className="p-10 ml-11">
<Routes>
<Route
path="/"
element={<ListaTransakcji onAdd={() => navigate('/transakcje/dodaj')} onEdit={(id) => navigate(`/transakcje/edytuj/${id}`)} />}
/>
<Route path="/dodaj" element={<DodawanieTransakcji />} />
<Route path="/edytuj/:id" element={<EdycjaTransakcji />} />
</Routes>
</div>
);
};
export default ZarzadzanieTransakcjami;