2
This commit is contained in:
parent
766da43a8b
commit
77c4dc9c36
@ -6,6 +6,8 @@ import ZarzadzanieProduktami from './components/ZarzadzanieProduktami';
|
||||
import Transakcje from './components/Transakcje';
|
||||
import NavBar from './components/NavBar'
|
||||
import Sidebar from './components/Sidebar';
|
||||
import Wydatki from './components/Wydatki';
|
||||
import Raporty from './components/Raporty';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
@ -21,6 +23,8 @@ const App = () => {
|
||||
<Route path="/transakcje" element={<Transakcje />} />
|
||||
<Route path="/panel" element={<PanelAdministratora />} />
|
||||
<Route path="/produkty" element={<ZarzadzanieProduktami />} />
|
||||
<Route path="/wydatki" element={<Wydatki />} />
|
||||
<Route path="/raporty" element={<Raporty />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</div>
|
||||
|
101
firm/src/components/Raporty.js
Normal file
101
firm/src/components/Raporty.js
Normal file
@ -0,0 +1,101 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import koszIcon from "../icons/kosz.png";
|
||||
|
||||
const Raporty = () => {
|
||||
const [fromDate, setFromDate] = useState('');
|
||||
const [toDate, setToDate] = useState('');
|
||||
const [reports, setReports] = useState([]);
|
||||
|
||||
const fetchReports = async () => {
|
||||
try {
|
||||
const response = await axios.get('https://localhost:7039/api/Report');
|
||||
setReports(response.data);
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas pobierania raportów:', error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchReports();
|
||||
}, []);
|
||||
|
||||
const handleGenerateReport = async () => {
|
||||
try {
|
||||
const response = await axios.post('https://localhost:7039/api/Report', {
|
||||
fromDate,
|
||||
toDate
|
||||
});
|
||||
const newReport = response.data;
|
||||
setReports([...reports, newReport]);
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas generowania raportu:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteReport = async (reportId) => {
|
||||
try {
|
||||
await axios.delete(`https://localhost:7039/api/Report/${reportId}`);
|
||||
fetchReports();
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas usuwania raportu:', error);
|
||||
}
|
||||
};
|
||||
|
||||
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(",", "");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-10 ml-11">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="h-20 text-5xl ml-1">
|
||||
Generowanie raportów
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-5">
|
||||
<label htmlFor="fromDate" className="mr-3">Od:</label>
|
||||
<input type="date" id="fromDate" value={fromDate} onChange={(e) => setFromDate(e.target.value)} className="mr-5" />
|
||||
<label htmlFor="toDate" className="mr-3">Do:</label>
|
||||
<input type="date" id="toDate" value={toDate} onChange={(e) => setToDate(e.target.value)} className="mr-5" />
|
||||
<button onClick={handleGenerateReport} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Generuj</button>
|
||||
</div>
|
||||
<div className="mt-5">
|
||||
<h2 className="text-2xl font-bold mb-4">Raporty</h2>
|
||||
<table className="w-full border-collapse border border-gray-300">
|
||||
<thead className="bg-gray-200 top-0 z-10">
|
||||
<tr>
|
||||
<th className="border border-gray-300 p-2">ID</th>
|
||||
<th className="border border-gray-300 p-2">Data od</th>
|
||||
<th className="border border-gray-300 p-2">Data do</th>
|
||||
<th className="border border-gray-300 p-2">Suma dochodów</th>
|
||||
<th className="border border-gray-300 p-2">Suma wydatków</th>
|
||||
<th className="border border-gray-300 p-2">Bilans</th>
|
||||
<th className="border border-gray-300 p-2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{reports.map(report => (
|
||||
<tr key={report.id}>
|
||||
<td className="border border-gray-300 p-2">{report.id}</td>
|
||||
<td className="border border-gray-300 p-2">{formatDate(report.fromDate)}</td>
|
||||
<td className="border border-gray-300 p-2">{formatDate(report.toDate)}</td>
|
||||
<td className="border border-gray-300 p-2">{report.totalIncome}</td>
|
||||
<td className="border border-gray-300 p-2">{report.totalExpenses}</td>
|
||||
<td className="border border-gray-300 p-2">{report.totalBalance}</td>
|
||||
<td className="border border-gray-300 p-2">
|
||||
<button onClick={() => handleDeleteReport(report.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>
|
||||
);
|
||||
};
|
||||
|
||||
export default Raporty;
|
@ -4,6 +4,8 @@ import adminIcon from "../icons/panel.png";
|
||||
import produktIcon from "../icons/produkty.png";
|
||||
import transakcjeIcon from "../icons/transkacje.png";
|
||||
import harmonogramIcon from "../icons/harmonogram.png";
|
||||
import wydatkiIcon from "../icons/wydatki.png";
|
||||
import raportyIcon from "../icons/raport.png";
|
||||
|
||||
const Sidebar = () => {
|
||||
return (
|
||||
@ -29,6 +31,16 @@ const Sidebar = () => {
|
||||
<img src={harmonogramIcon} alt="Obrazek 1" className="w-7 h-7 mr-2" />
|
||||
Harmonogram
|
||||
</li></Link>
|
||||
<Link to="/wydatki" className="text-black px-10 py-2 block font-customFont text-center w-max flex-item-center">
|
||||
<li className='flex items-center'>
|
||||
<img src={wydatkiIcon} alt="Obrazek 1" className="w-7 h-7 mr-2" />
|
||||
Wydatki
|
||||
</li></Link>
|
||||
<Link to="/raporty" className="text-black px-10 py-2 block font-customFont text-center w-max flex-item-center">
|
||||
<li className='flex items-center'>
|
||||
<img src={raportyIcon} alt="Obrazek 1" className="w-7 h-7 mr-2" />
|
||||
Raporty
|
||||
</li></Link>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
|
@ -7,14 +7,16 @@ import plusIcon from "../icons/plus.png";
|
||||
const Transakcje = () => {
|
||||
const [transactions, setTransactions] = useState([]);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
const [editTransaction, setEditTransaction] = useState(null);
|
||||
const [newTransaction, setNewTransaction] = useState({
|
||||
id: 1,
|
||||
id: 2,
|
||||
date: "",
|
||||
employeeId: "",
|
||||
transactionProducts: [
|
||||
{
|
||||
id: 0,
|
||||
transactionId: 0,
|
||||
transactionId: 2,
|
||||
productID: "",
|
||||
quantity:""
|
||||
}
|
||||
@ -40,17 +42,19 @@ const Transakcje = () => {
|
||||
|
||||
const handleAddTransaction = async () => {
|
||||
try {
|
||||
console.log('Nowa transakcja:', newTransaction);
|
||||
await axios.post('https://localhost:7039/api/Transaction', newTransaction);
|
||||
|
||||
fetchTransactions();
|
||||
setIsModalOpen(false);
|
||||
setNewTransaction({
|
||||
id: 1,
|
||||
id: 2,
|
||||
date: "",
|
||||
employeeId: "",
|
||||
transactionProducts: [
|
||||
{
|
||||
id: 0,
|
||||
transactionId: 0,
|
||||
transactionId: 2,
|
||||
productID: "",
|
||||
quantity: ""
|
||||
}
|
||||
@ -65,6 +69,60 @@ const Transakcje = () => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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 handleAddProduct = () => {
|
||||
setNewTransaction({
|
||||
...newTransaction,
|
||||
transactionProducts: [
|
||||
...newTransaction.transactionProducts,
|
||||
{
|
||||
id: 0,
|
||||
transactionId: 2,
|
||||
productID: "",
|
||||
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();
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas usuwania transakcji:', error);
|
||||
}
|
||||
};
|
||||
const handleEditTransaction = (transaction) => {
|
||||
setEditTransaction(transaction);
|
||||
setIsEditModalOpen(true);
|
||||
};
|
||||
const handleSaveEditedTransaction = async () => {
|
||||
try {
|
||||
await axios.put(`https://localhost:7039/api/Transaction/${editTransaction.id}`, editTransaction);
|
||||
fetchTransactions();
|
||||
setIsEditModalOpen(false);
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas edycji transakcji:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className='p-10 ml-11'>
|
||||
<div className='flex items-center justify-between'>
|
||||
@ -75,6 +133,97 @@ const Transakcje = () => {
|
||||
<img src={plusIcon} alt="" className="w-8 h-8 mr-2" />Dodaj
|
||||
</button>
|
||||
</div>
|
||||
{isEditModalOpen && editTransaction && (
|
||||
<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">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"
|
||||
/>
|
||||
<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}>
|
||||
<input
|
||||
type="number"
|
||||
name={`productID-${index}`}
|
||||
value={product.productID}
|
||||
onChange={(e) => {
|
||||
const newTransactionProducts = [...editTransaction.transactionProducts];
|
||||
newTransactionProducts[index].productID = e.target.value;
|
||||
setEditTransaction({ ...editTransaction, transactionProducts: newTransactionProducts });
|
||||
}}
|
||||
placeholder="ID Produktu"
|
||||
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"/>
|
||||
<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"
|
||||
/>
|
||||
<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={() => {
|
||||
handleSaveEditedTransaction();
|
||||
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">
|
||||
<div className="bg-white p-8 rounded-lg">
|
||||
@ -118,96 +267,117 @@ const Transakcje = () => {
|
||||
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"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
<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}
|
||||
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 rounded"
|
||||
>
|
||||
Anuluj
|
||||
</button>
|
||||
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 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 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 rounded"
|
||||
>
|
||||
Anuluj
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="w-8/10 mx-auto mt-2">
|
||||
<div className="h-140 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">{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)}
|
||||
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={() => handleDeleteTransaction(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>
|
||||
)}
|
||||
<div className="w-8/10 mx-auto mt-2">
|
||||
<div className="h-64 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">Sposób płatności</th>
|
||||
<th className="border border-gray-300 p-2">Nr. Pracownika</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">{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">{transaction.paymentType}</td>
|
||||
<td className="border border-gray-300 p-2">{transaction.employeeId}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="flex justify-start mt-4">
|
||||
<button 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>
|
||||
<button 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default Transakcje
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export default Transakcje;
|
||||
|
146
firm/src/components/Wydatki.js
Normal file
146
firm/src/components/Wydatki.js
Normal file
@ -0,0 +1,146 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import koszIcon from "../icons/kosz.png";
|
||||
import plusIcon from "../icons/plus.png";
|
||||
|
||||
const Wydatki = () => {
|
||||
const [expenses, setExpenses] = useState([]);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [newExpense, setNewExpense] = useState({
|
||||
date: '',
|
||||
value: '',
|
||||
description: ''
|
||||
});
|
||||
|
||||
const fetchExpenses = async () => {
|
||||
try {
|
||||
const response = await axios.get('https://localhost:7039/api/Expenses');
|
||||
setExpenses(response.data);
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas pobierania wydatków:', error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchExpenses();
|
||||
}, []);
|
||||
|
||||
const handleAddExpense = async () => {
|
||||
try {
|
||||
const response = await axios.post('https://localhost:7039/api/Expenses', newExpense);
|
||||
const addedExpense = response.data;
|
||||
setExpenses([...expenses, addedExpense]);
|
||||
setNewExpense({
|
||||
date: '',
|
||||
value: '',
|
||||
description: ''
|
||||
});
|
||||
setShowModal(false);
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas dodawania wydatku:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteExpense = async (expenseId) => {
|
||||
try {
|
||||
await axios.delete(`https://localhost:7039/api/Expenses/${expenseId}`);
|
||||
fetchExpenses();
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas usuwania wydatku:', error);
|
||||
}
|
||||
};
|
||||
|
||||
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(",", "");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-10 ml-11">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="h-20 text-5xl ml-1">
|
||||
Zarządzanie wydatkami
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-2xl font-bold mb-4">Wydatki</h2>
|
||||
<button onClick={() => setShowModal(true)} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
|
||||
<img src={plusIcon} alt="" className="w-8 h-8 mr-2" />Dodaj
|
||||
</button>
|
||||
</div>
|
||||
<table className="w-full border-collapse border border-gray-300">
|
||||
<thead className="bg-gray-200 top-0 z-10">
|
||||
<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">Wartość</th>
|
||||
<th className="border border-gray-300 p-2">Opis</th>
|
||||
<th className="border border-gray-300 p-2"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{expenses.map(expense => (
|
||||
<tr key={expense.id}>
|
||||
<td className="border border-gray-300 p-2">{expense.id}</td>
|
||||
<td className="border border-gray-300 p-2">{formatDate(expense.date)}</td>
|
||||
<td className="border border-gray-300 p-2">{expense.value}</td>
|
||||
<td className="border border-gray-300 p-2">{expense.description}</td>
|
||||
<td className="border border-gray-300 p-2">
|
||||
<button onClick={() => handleDeleteExpense(expense.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>
|
||||
{showModal && (
|
||||
<div className="fixed z-10 inset-0 overflow-y-auto">
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<div className="fixed inset-0 transition-opacity">
|
||||
<div className="absolute inset-0 bg-gray-500 opacity-75"></div>
|
||||
</div>
|
||||
<div className="bg-white rounded-lg overflow-hidden shadow-xl transform transition-all sm:max-w-lg sm:w-full">
|
||||
<div className="px-4 py-5 sm:px-6">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-900">Dodaj nowy wydatek</h3>
|
||||
</div>
|
||||
<div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div className="grid grid-cols-6 gap-6">
|
||||
<div className="col-span-6 sm:col-span-3">
|
||||
<label htmlFor="expenseDate" className="block text-sm font-medium text-gray-700">Data</label>
|
||||
<input type="date" id="expenseDate" value={newExpense.date} onChange={(e) => setNewExpense({ ...newExpense, date: e.target.value })} className="mt-1 border py-1 px-3 block w-full shadow-sm sm:text-sm rounded-md" />
|
||||
</div>
|
||||
|
||||
<div className="col-span-6 sm:col-span-3">
|
||||
<label htmlFor="expenseValue" className="block text-sm font-medium text-gray-700">Wartość</label>
|
||||
<input type="number" id="expenseValue" value={newExpense.value} onChange={(e) => setNewExpense({ ...newExpense, value: e.target.value })} className="mt-1 border py-1 px-3 block w-full shadow-sm sm:text-sm rounded-md" />
|
||||
</div>
|
||||
|
||||
<div className="col-span-6">
|
||||
<label htmlFor="expenseDescription" className="block text-sm font-medium text-gray-700">Opis</label>
|
||||
<textarea id="expenseDescription" value={newExpense.description} onChange={(e) => setNewExpense({ ...newExpense, description: e.target.value })}
|
||||
className="mt-1 border py-2 px-3 block w-full shadow-sm sm:text-sm rounded-md" rows="4"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<button onClick={handleAddExpense} type="button" className="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-600 text-base font-medium text-white hover:bg-green-500 focus:outline-none focus:border-green-700 focus:shadow-outline-green transition ease-in-out duration-150 sm:text-sm sm:leading-5">
|
||||
Dodaj
|
||||
</button>
|
||||
<button onClick={() => setShowModal(false)} type="button" className="mt-3 sm:mt-0 mr-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue transition ease-in-out duration-150 sm:text-sm sm:leading-5">
|
||||
Anuluj
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Wydatki;
|
||||
|
@ -7,6 +7,7 @@ import plusIcon from "../icons/plus.png";
|
||||
const ZarzadzanieProduktami = () => {
|
||||
const [products, setProducts] = useState([]);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
const [newProduct, setNewProduct] = useState({
|
||||
name: "",
|
||||
description: "",
|
||||
@ -14,6 +15,7 @@ const ZarzadzanieProduktami = () => {
|
||||
type: "",
|
||||
availability: ""
|
||||
});
|
||||
const [editProduct, setEditProduct] = useState(null);
|
||||
|
||||
const fetchProducts = async () => {
|
||||
try {
|
||||
@ -37,7 +39,7 @@ const ZarzadzanieProduktami = () => {
|
||||
try {
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': 'text/json'
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
await axios.post('https://localhost:7039/api/Products', newProduct, config);
|
||||
@ -47,67 +49,207 @@ const ZarzadzanieProduktami = () => {
|
||||
name: "",
|
||||
availability: "",
|
||||
price: "",
|
||||
type: ""
|
||||
type: "",
|
||||
description: ""
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas dodawania produktu:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEditProduct = (product) => {
|
||||
setEditProduct(product);
|
||||
setIsEditModalOpen(true);
|
||||
};
|
||||
|
||||
const handleSaveEditedProduct = async () => {
|
||||
try {
|
||||
await axios.put(`https://localhost:7039/api/Products/${editProduct.id}`, editProduct);
|
||||
fetchProducts();
|
||||
setIsEditModalOpen(false);
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas edycji produktu:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteProduct = async (productId) => {
|
||||
try {
|
||||
await axios.delete(`https://localhost:7039/api/Products/${productId}`);
|
||||
fetchProducts();
|
||||
} catch (error) {
|
||||
console.error('Błąd podczas usuwania produktu:', error);
|
||||
}
|
||||
};
|
||||
|
||||
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>
|
||||
<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>
|
||||
{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}
|
||||
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">
|
||||
<div className="bg-white p-8 rounded-lg">
|
||||
<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="Typ" 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} 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>
|
||||
<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="Typ"
|
||||
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}
|
||||
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-64 overflow-y-auto">
|
||||
<div className="h-140 overflow-y-auto">
|
||||
<table className="w-full border-collapse border border-gray-300">
|
||||
<thead className="bg-gray-200">
|
||||
<thead className="bg-gray-200 top-0 z-10">
|
||||
<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">{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={() => handleDeleteProduct(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 className="flex justify-start mt-4">
|
||||
<button 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>
|
||||
<button 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ZarzadzanieProduktami;
|
||||
|
BIN
firm/src/icons/raport.png
Normal file
BIN
firm/src/icons/raport.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
firm/src/icons/wydatki.png
Normal file
BIN
firm/src/icons/wydatki.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Loading…
Reference in New Issue
Block a user