This commit is contained in:
Wiktor Szynaka 2024-06-12 01:33:57 +01:00
parent 766da43a8b
commit 77c4dc9c36
8 changed files with 688 additions and 113 deletions

View File

@ -6,6 +6,8 @@ import ZarzadzanieProduktami from './components/ZarzadzanieProduktami';
import Transakcje from './components/Transakcje'; import Transakcje from './components/Transakcje';
import NavBar from './components/NavBar' import NavBar from './components/NavBar'
import Sidebar from './components/Sidebar'; import Sidebar from './components/Sidebar';
import Wydatki from './components/Wydatki';
import Raporty from './components/Raporty';
const App = () => { const App = () => {
return ( return (
@ -21,6 +23,8 @@ const App = () => {
<Route path="/transakcje" element={<Transakcje />} /> <Route path="/transakcje" element={<Transakcje />} />
<Route path="/panel" element={<PanelAdministratora />} /> <Route path="/panel" element={<PanelAdministratora />} />
<Route path="/produkty" element={<ZarzadzanieProduktami />} /> <Route path="/produkty" element={<ZarzadzanieProduktami />} />
<Route path="/wydatki" element={<Wydatki />} />
<Route path="/raporty" element={<Raporty />} />
</Routes> </Routes>
</div> </div>
</div> </div>

View 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;

View File

@ -4,6 +4,8 @@ import adminIcon from "../icons/panel.png";
import produktIcon from "../icons/produkty.png"; import produktIcon from "../icons/produkty.png";
import transakcjeIcon from "../icons/transkacje.png"; import transakcjeIcon from "../icons/transkacje.png";
import harmonogramIcon from "../icons/harmonogram.png"; import harmonogramIcon from "../icons/harmonogram.png";
import wydatkiIcon from "../icons/wydatki.png";
import raportyIcon from "../icons/raport.png";
const Sidebar = () => { const Sidebar = () => {
return ( return (
@ -29,6 +31,16 @@ const Sidebar = () => {
<img src={harmonogramIcon} alt="Obrazek 1" className="w-7 h-7 mr-2" /> <img src={harmonogramIcon} alt="Obrazek 1" className="w-7 h-7 mr-2" />
Harmonogram Harmonogram
</li></Link> </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> </ul>
</div> </div>
); );

View File

@ -7,14 +7,16 @@ import plusIcon from "../icons/plus.png";
const Transakcje = () => { const Transakcje = () => {
const [transactions, setTransactions] = useState([]); const [transactions, setTransactions] = useState([]);
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [editTransaction, setEditTransaction] = useState(null);
const [newTransaction, setNewTransaction] = useState({ const [newTransaction, setNewTransaction] = useState({
id: 1, id: 2,
date: "", date: "",
employeeId: "", employeeId: "",
transactionProducts: [ transactionProducts: [
{ {
id: 0, id: 0,
transactionId: 0, transactionId: 2,
productID: "", productID: "",
quantity:"" quantity:""
} }
@ -40,17 +42,19 @@ const Transakcje = () => {
const handleAddTransaction = async () => { const handleAddTransaction = async () => {
try { try {
console.log('Nowa transakcja:', newTransaction);
await axios.post('https://localhost:7039/api/Transaction', newTransaction); await axios.post('https://localhost:7039/api/Transaction', newTransaction);
fetchTransactions(); fetchTransactions();
setIsModalOpen(false); setIsModalOpen(false);
setNewTransaction({ setNewTransaction({
id: 1, id: 2,
date: "", date: "",
employeeId: "", employeeId: "",
transactionProducts: [ transactionProducts: [
{ {
id: 0, id: 0,
transactionId: 0, transactionId: 2,
productID: "", productID: "",
quantity: "" 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 ( return (
<div className='p-10 ml-11'> <div className='p-10 ml-11'>
<div className='flex items-center justify-between'> <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 <img src={plusIcon} alt="" className="w-8 h-8 mr-2" />Dodaj
</button> </button>
</div> </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 && ( {isModalOpen && (
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 flex items-center justify-center"> <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="bg-white p-8 rounded-lg">
@ -118,11 +267,16 @@ const Transakcje = () => {
newTransactionProducts[index].quantity = e.target.value; newTransactionProducts[index].quantity = e.target.value;
setNewTransaction({ ...newTransaction, transactionProducts: newTransactionProducts }); setNewTransaction({ ...newTransaction, transactionProducts: newTransactionProducts });
}} }}
placeholder="Ilość" placeholder="Ilość" className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
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> </div>
))} ))}
<button onClick={handleAddProduct} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Dodaj
</button>
<input <input
type="text" type="text"
name="paymentType" name="paymentType"
@ -148,7 +302,11 @@ const Transakcje = () => {
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg" className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg"
/> />
<button <button
onClick={handleAddTransaction} onClick={() => {
handleAddTransaction();
setIsModalOpen(false);
}}
className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded" className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"
> >
Dodaj transakcję Dodaj transakcję
@ -163,7 +321,7 @@ const Transakcje = () => {
</div> </div>
)} )}
<div className="w-8/10 mx-auto mt-2"> <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"> <table className="w-full border-collapse border border-gray-300">
<thead className="bg-gray-200"> <thead className="bg-gray-200">
<tr> <tr>
@ -171,15 +329,18 @@ const Transakcje = () => {
<th className="border border-gray-300 p-2">Data</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">Produkt</th>
<th className="border border-gray-300 p-2">Ilość</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">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">Nr. Pracownika</th>
<th className="border border-gray-300 p-2"></th>
<th className="border border-gray-300 p-2"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{transactions.map(transaction => ( {transactions.map(transaction => (
<tr key={transaction.id}> <tr key={transaction.id}>
<td className="border border-gray-300 p-2">{transaction.id}</td> <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">{formatDate(transaction.date)}</td>
<td className="border border-gray-300 p-2"> <td className="border border-gray-300 p-2">
{transaction.transactionProducts.map(product => ( {transaction.transactionProducts.map(product => (
<div key={product.id}>{product.product.name}</div> <div key={product.id}>{product.product.name}</div>
@ -190,24 +351,33 @@ const Transakcje = () => {
<div key={product.id}>{product.quantity}</div> <div key={product.id}>{product.quantity}</div>
))} ))}
</td> </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.paymentType}</td>
<td className="border border-gray-300 p-2">{transaction.employeeId}</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> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
</div> </div>
<div className="flex justify-start mt-4"> <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> </div>
</div> </div>
); );
} }
export default Transakcje
export default Transakcje;

View 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;

View File

@ -7,6 +7,7 @@ import plusIcon from "../icons/plus.png";
const ZarzadzanieProduktami = () => { const ZarzadzanieProduktami = () => {
const [products, setProducts] = useState([]); const [products, setProducts] = useState([]);
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [newProduct, setNewProduct] = useState({ const [newProduct, setNewProduct] = useState({
name: "", name: "",
description: "", description: "",
@ -14,6 +15,7 @@ const ZarzadzanieProduktami = () => {
type: "", type: "",
availability: "" availability: ""
}); });
const [editProduct, setEditProduct] = useState(null);
const fetchProducts = async () => { const fetchProducts = async () => {
try { try {
@ -37,7 +39,7 @@ const ZarzadzanieProduktami = () => {
try { try {
const config = { const config = {
headers: { headers: {
'Content-Type': 'text/json' 'Content-Type': 'application/json'
} }
}; };
await axios.post('https://localhost:7039/api/Products', newProduct, config); await axios.post('https://localhost:7039/api/Products', newProduct, config);
@ -47,67 +49,207 @@ const ZarzadzanieProduktami = () => {
name: "", name: "",
availability: "", availability: "",
price: "", price: "",
type: "" type: "",
description: ""
}); });
} catch (error) { } catch (error) {
console.error('Błąd podczas dodawania produktu:', 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 ( return (
<div className='p-10 ml-11'> <div className='p-10 ml-11'>
<div className='flex items-center justify-between'> <div className='flex items-center justify-between'>
<div className='h-20 text-5xl ml-1'> <div className='h-20 text-5xl ml-1'>
Katalog Produktów Katalog Produktów
</div> </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> </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 && ( {isModalOpen && (
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 flex items-center justify-center"> <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"> <div className="bg-white p-8 rounded-lg shadow-lg">
<h2 className="text-2xl font-bold mb-4">Dodaj nowy produkt</h2> <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
<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" /> type="text"
<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" /> name="name"
<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" /> value={newProduct.name}
<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" /> onChange={handleInputChange}
<button onClick={handleAddProduct} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">Dodaj produkt</button> placeholder="Nazwa produktu"
<button onClick={() => setIsModalOpen(false)} className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">Anuluj</button> 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> </div>
)} )}
<div className="w-8/10 mx-auto mt-2"> <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"> <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> <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">Produkt</th>
<th className="border border-gray-300 p-2">Opis</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">Cena</th>
<th className="border border-gray-300 p-2">Kategoria</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">Dostępność</th>
<th className="border border-gray-300 p-2"></th>
<th className="border border-gray-300 p-2"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{products.map(product => ( {products.map(product => (
<tr key={product.id}> <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.name}</td>
<td className="border border-gray-300 p-2">{product.description}</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.price}</td>
<td className="border border-gray-300 p-2">{product.type}</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">{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> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
</div> </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>
</div> </div>
); );
} };
export default ZarzadzanieProduktami; export default ZarzadzanieProduktami;

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB