poprawy wizualne

This commit is contained in:
Wiktor Szynaka 2025-01-01 22:23:08 +01:00
parent 44fa0d8503
commit 8e6726348d
7 changed files with 281 additions and 254 deletions

View File

@ -190,14 +190,6 @@ const DodawanieTransakcji = () => {
</div>
{/*<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 shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>*/}
<label className="block mb-2 text-gray-700 font-medium">Produkty transakcji</label>
<div className="border border-gray-300 rounded-lg shadow-sm p-4 h-80 overflow-y-scroll">
{isLoading ? (

View File

@ -1,6 +1,7 @@
import React, { useState, useEffect } from "react";
import axios from "axios";
import { useParams, useNavigate } from "react-router-dom";
import {ReactComponent as MinusIcon} from "../icons/minus-icon.svg"
import Select from "react-select";
const EdycjaTransakcji = () => {
@ -204,105 +205,148 @@ const EdycjaTransakcji = () => {
return (
<div className="bg-white p-8 rounded-lg shadow-lg max-w-4xl mx-auto mt-6">
<h2 className="text-2xl font-bold mb-6 text-gray-800">Edycja Transakcji</h2>
<h2 className="text-2xl font-bold mb-6 text-gray-800">Edytuj transakcję</h2>
{error && <p className="text-red-500 mb-4">{error}</p>}
<div className="mb-4">
<div className="mb-4 flex items-center space-x-4">
<div>
<label className="block mb-2 text-gray-700 font-medium">Data transakcji</label>
<input
type="datetime-local"
name="date"
value={transaction.date}
onChange={handleInputChange}
placeholder="Data"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
className="flex-1 mb-4 px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
{errors.date && <span className="text-red-500 text-sm">{errors.date}</span>}
</div>
<div className="mb-4">
</div>
<div className="pb-4 items-center">
<label className="block mb-2 text-gray-700 font-medium">Nr pracownika</label>
<input
type="number"
name="employeeId"
value={transaction.employeeId}
onChange={handleInputChange}
placeholder="Nr. Pracownika"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Nr pracownika"
className="flex mb-4 px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
{errors.employeeId && <span className="text-red-500 text-sm">{errors.employeeId}</span>}
</div>
<label className="block mb-2 text-gray-700 font-medium">Produkty transkacji</label>
<div className="border border-gray-300 rounded-lg shadow-sm p-4 h-80 overflow-y-scroll">
{transaction.transactionProducts.map((product, index) => (
<div key={index} className="mb-4">
<div key={index} className="mb-4 flex items-center space-x-4">
<Select
value={products.find((p) => p.value === product.productID) || null}
onChange={(option) => handleProductChange(index, option)}
name={`productName-${index}`}
value={products.find((option) => option.value === product.productID)}
onChange={(selectedOption) => handleProductChange(index, selectedOption)}
options={products}
className="mb-2"
placeholder="Wybierz produkt"
className="flex-1"
placeholder="Wybierz produkt..."
/>
{errors[`productID_${index}`] && (
<span className="text-red-500 text-sm">{errors[`productID_${index}`]}</span>
)}
<input
type="number"
name={`quantity-${index}`}
value={product.quantity}
onChange={(e) => handleQuantityChange(index, e.target.value)}
placeholder="Ilość"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
className="w-24 px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
{errors[`quantity_${index}`] && (
<span className="text-red-500 text-sm">{errors[`quantity_${index}`]}</span>
)}
<button
onClick={() => handleRemoveProduct(index)}
className="bg-gradient-to-r from-red-500 to-red-700 text-white py-2 px-4 rounded-lg hover:from-red-600 hover:to-red-800 transition mt-3"
className="relative flex items-center justify-center w-10 h-10 rounded-full text-gray-500 hover:text-red-600 hover:bg-red-100 active:bg-red-200 transition focus:outline-none"
>
Usuń
<MinusIcon className="w-5 h-5" />
</button>
</div>
))}
<button
onClick={handleAddProduct}
className="bg-gradient-to-r from-blue-500 to-blue-700 text-white font-bold py-2 px-4 mb-3 rounded-lg shadow-md hover:from-blue-600 hover:to-blue-800 transition"
className="bg-gradient-to-r from-blue-500 to-blue-700 text-white py-2 px-4 rounded-lg hover:from-blue-600 hover:to-blue-800 transition mb-3"
>
Dodaj produkt
</button>
<div className="mb-4">
<input
type="text"
name="paymentType"
value={transaction.paymentType}
onChange={handleInputChange}
placeholder="Sposób płatności"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
{errors.paymentType && <span className="text-red-500 text-sm">{errors.paymentType}</span>}
</div>
<div className="mt-6 flex justify-between">
<div className="mb-4">
<label className="block mb-2 text-gray-700 font-medium">Metoda płatności</label>
<div className="flex space-x-4">
<label className="flex items-center">
<input
type="radio"
name="paymentType"
value="BLIK"
checked={transaction.paymentType === "BLIK"}
onChange={handleInputChange}
className="form-radio h-5 w-5 text-blue-500 focus:ring-blue-500"
/>
<span className="ml-2">BLIK</span>
</label>
<label className="flex items-center">
<input
type="radio"
name="paymentType"
value="Gotówka"
checked={transaction.paymentType === "Gotówka"}
onChange={handleInputChange}
className="form-radio h-5 w-5 text-blue-500 focus:ring-blue-500"
/>
<span className="ml-2">Gotówka</span>
</label>
<label className="flex items-center">
<input
type="radio"
name="paymentType"
value="Karta płatnicza"
checked={transaction.paymentType === "Karta płatnicza"}
onChange={handleInputChange}
className="form-radio h-5 w-5 text-blue-500 focus:ring-blue-500"
/>
<span className="ml-2">Karta płatnicza</span>
</label>
</div>
</div>
<div>
<label className="block mb-2 text-gray-700 font-medium">Rabat</label>
<input
type="number"
name="discount"
value={transaction.discount}
onChange={handleInputChange}
placeholder="Rabat"
className="block w-full px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
className="block w-full mb-4 px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
{errors.discount && <span className="text-red-500 text-sm">{errors.discount}</span>}
</div>
</div>
<div>
<label className="block mb-2 text-gray-700 font-medium">Opis</label>
<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 shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>
<div className="mt-6 flex justify-between">
<button
onClick={handleSaveChanges}
className="bg-gradient-to-r from-green-500 to-green-700 text-white font-bold py-2 px-4 rounded-lg shadow-md hover:from-green-600 hover:to-green-800 transition"
className="bg-gradient-to-r from-blue-500 to-blue-700 text-white font-bold py-2 px-4 rounded-lg shadow-md hover:from-blue-600 hover:to-blue-800 transition"
>
Zapisz zmiany
</button>
<button
onClick={handleCancel}
className="bg-gradient-to-r from-red-500 to-red-700 text-white font-bold py-2 px-4 rounded-lg shadow-md hover:from-red-600 hover:to-red-800 transition ml-4"
className="bg-gradient-to-r from-red-500 to-red-700 text-white py-2 px-4 rounded-lg hover:from-red-600 hover:to-red-800 transition"
>
Anuluj
</button>

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import editIcon from '../icons/edit.png';
import koszIcon from '../icons/kosz.png';
import {ReactComponent as EditIcon} from '../icons/edit.svg';
import {ReactComponent as KoszIcon} from '../icons/delete.svg';
import { useNavigate } from 'react-router-dom';
const ListaProduktow = ({ onAdd }) => {
@ -26,6 +26,11 @@ const ListaProduktow = ({ onAdd }) => {
fetchProducts();
}, []);
const openDeleteConfirmation = (productId) => {
setDeleteProductId(productId);
setShowModal(true);
};
const handleDeleteProduct = async () => {
const token = localStorage.getItem('token');
if (!token) {
@ -76,7 +81,7 @@ const ListaProduktow = ({ onAdd }) => {
</thead>
<tbody className="text-gray-600">
{products.map((product) => (
<tr key={product.id} className="hover:bg-gray-50 transition-colors">
<tr key={product.id} className="group hover:bg-gray-100 transition-colors">
<td className="p-3">{product.id}</td>
<td className="p-3">{product.name}</td>
<td className="p-3">{product.description}</td>
@ -84,25 +89,20 @@ const ListaProduktow = ({ onAdd }) => {
<td className="p-3 text-center">
{product.type === 0 ? "" : product.availability}
</td>
<td className="p-3 flex justify-center items-center space-x-2">
<div className="flex justify-center items-center opacity-0 group-hover:opacity-100 transition-opacity duration-200">
<button
onClick={() => handleEditProduct(product.id)}
className="bg-gradient-to-r from-blue-500 to-blue-700 text-white py-2 px-4 rounded-lg hover:from-blue-600 hover:to-blue-800 transition"
className="text-blue-500 hover:bg-blue-200 active:bg-blue-300 focus:outline-none p-2 rounded-full transition-colors"
>
<img src={editIcon} alt="Edytuj" className="inline w-5 mr-2" />
Edytuj
<EditIcon className = "w-5 h-5"/>
</button>
<button
onClick={() => {
setDeleteProductId(product.id);
setShowModal(true);
}}
className="bg-gradient-to-r from-red-500 to-red-700 text-white py-2 px-4 rounded-lg hover:from-red-600 hover:to-red-800 transition"
onClick={() => openDeleteConfirmation(product.id)}
className="text-red-500 hover:bg-red-200 active:bg-red-300 focus:outline-none p-2 rounded-full transition-colors"
>
<img src={koszIcon} alt="Usuń" className="inline w-5 mr-2" />
Usuń
<KoszIcon className = "w-5 h-5"/>
</button>
</td>
</div>
</tr>
))}
</tbody>

View File

@ -1,7 +1,5 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
//import editIcon from '../icons/edit.png';
//import koszIcon from '../icons/kosz.png';
import {ReactComponent as EditIcon} from '../icons/edit.svg';
import {ReactComponent as KoszIcon} from '../icons/delete.svg';
import { useNavigate } from 'react-router-dom';
@ -133,14 +131,12 @@ const ListaTransakcji = ({ onAdd}) => {
<div className="flex space-x-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
<button
onClick={() => handleEditTransaction(transaction.id)}
//className="bg-gradient-to-r from-blue-500 to-blue-700 text-white py-2 px-4 rounded-lg hover:from-blue-600 hover:to-blue-800 transition"
className="text-blue-500 hover:bg-blue-200 active:bg-blue-300 focus:outline-none p-2 rounded-full transition-colors"
>
<EditIcon className = "w-5 h-5"/>
</button>
<button
onClick={() => openDeleteConfirmation(transaction.id)}
//className="bg-gradient-to-r from-red-500 to-red-700 text-white py-2 px-4 rounded-lg hover:from-red-600 hover:to-red-800 transition"
className="text-red-500 hover:bg-red-200 active:bg-red-300 focus:outline-none p-2 rounded-full transition-colors"
>
<KoszIcon className = "w-5 h-5"/>

View File

@ -12,7 +12,6 @@ const PanelAdministratora = () => {
const [workdays, setWorkdays] = useState([]);
const [absenceType, setAbsenceType] = useState('');
// Funkcja pobierania emaili
const fetchEmails = async () => {
try {
const response = await axios.get('https://localhost:7039/api/user/emails', {
@ -24,7 +23,6 @@ const PanelAdministratora = () => {
}
};
// Funkcja dodawania absencji
const addAbsence = async () => {
if (!selectedEmail || !absenceType || !startDate || !endDate) {
alert("Wszystkie pola muszą być wypełnione!");
@ -47,7 +45,6 @@ const PanelAdministratora = () => {
}
};
// Funkcja pobierania raportu
const downloadReport = async () => {
if (!reportType || !startDate || !endDate) {
alert("Wszystkie pola muszą być wypełnione!");
@ -76,7 +73,6 @@ const PanelAdministratora = () => {
}
};
// Funkcja pobierania harmonogramów
const fetchWorkdays = async (userEmail) => {
if (!userEmail) {
setWorkdays([]);
@ -93,7 +89,6 @@ const PanelAdministratora = () => {
}
};
// UseEffect do pobierania danych emaili przy pierwszym renderowaniu
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
@ -101,7 +96,6 @@ const PanelAdministratora = () => {
}
}, []);
// UseEffect do pobierania harmonogramu przy zmianie emaila
useEffect(() => {
if (selectedEmail) {
fetchWorkdays(selectedEmail);
@ -113,7 +107,7 @@ const PanelAdministratora = () => {
<div className='flex items-center justify-between py-6 px-8 bg-gradient-to-r from-blue-500 to-teal-500 rounded-xl shadow-md mb-6'>
<h1 className="text-white text-4xl font-semibold">Panel Administratora</h1>
<div className="mr-10 text-lg flex">
<div className='px-10'>
<div className='px-5'>
<button
onClick={() => setSelectedOption('harmonogramy')}
className={`
@ -123,7 +117,7 @@ const PanelAdministratora = () => {
Harmonogramy
</button>
</div>
<div className='px-10'>
<div className='px-5'>
<button
onClick={() => setSelectedOption('absencje')}
className={`
@ -133,7 +127,7 @@ const PanelAdministratora = () => {
Absencje
</button>
</div>
<div>
<div className='px-5'>
<button
onClick={() => setSelectedOption('raporty')}
className={`

View File

@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import koszIcon from "../icons/kosz.png";
import {ReactComponent as KoszIcon} from '../icons/delete.svg';
const Raporty = () => {
const [fromDate, setFromDate] = useState('');
@ -28,6 +28,31 @@ const Raporty = () => {
}
};
const validateYear = (dateString) => {
const year = dateString.split('-')[0];
return year.length === 4 && /^\d{4}$/.test(year);
};
const handleFromDateChange = (e) => {
const value = e.target.value;
if (validateYear(value)) {
setFromDate(value);
setError(null);
} else {
setError('Rok w dacie "Od" musi być 4-cyfrowy.');
}
};
const handleToDateChange = (e) => {
const value = e.target.value;
if (validateYear(value)) {
setToDate(value);
setError(null);
} else {
setError('Rok w dacie "Do" musi być 4-cyfrowy.');
}
};
const openDeleteConfirmation = (reportId) => {
setDeleteReportId(reportId);
setShowDeleteModal(true);
@ -110,7 +135,7 @@ const Raporty = () => {
type="datetime-local"
id="fromDate"
value={fromDate}
onChange={(e) => setFromDate(e.target.value)}
onChange={handleFromDateChange}
className="w-full px-4 py-2 border-2 border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
@ -121,7 +146,7 @@ const Raporty = () => {
type="datetime-local"
id="toDate"
value={toDate}
onChange={(e) => setToDate(e.target.value)}
onChange={handleToDateChange}
className="w-full px-4 py-2 border-2 border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
@ -133,7 +158,14 @@ const Raporty = () => {
>
Generuj raport
</button>
{error && (
<div className="mt-4 text-red-500 text-center font-semibold">
{error}
</div>
)}
</div>
@ -147,25 +179,27 @@ const Raporty = () => {
<th className="p-2 text-left">Suma dochodów</th>
<th className="p-2 text-left">Suma wydatków</th>
<th className="p-2 text-left">Bilans</th>
<th className="p-2 text-center"></th>
<th className="p-2 text-center">Usuń</th>
</tr>
</thead>
<tbody>
{reports.map((report) => (
<tr key={report.id} className="hover:bg-gray-50">
<tr key={report.id} className="group hover:bg-gray-100 transition-colors">
<td className="p-2">{report.id}</td>
<td className="p-2">{formatDate(report.fromDate)}</td>
<td className="p-2">{formatDate(report.toDate)}</td>
<td className="p-2">{report.totalIncome}</td>
<td className="p-2">{report.totalExpenses}</td>
<td className="p-2">{report.totalBalance}</td>
<td className="p-2 text-center">
<td className="p-3 flex justify-center space-x-2">
<div className="flex space-x-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
<button
onClick={() => openDeleteConfirmation(report.id)}
className="bg-gradient-to-r from-red-500 to-red-700 text-white py-2 px-4 rounded-lg hover:from-red-600 hover:to-red-800 transition"
className="text-red-500 hover:bg-red-200 active:bg-red-300 focus:outline-none p-2 rounded-full transition-colors"
>
<img src={koszIcon} alt="Usuń" className="inline w-5 mr-2" /> Usuń
<KoszIcon className = "w-5 h-5"/>
</button>
</div>
</td>
</tr>
))}
@ -173,21 +207,6 @@ const Raporty = () => {
</table>
</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-lg"
>
Zamknij
</button>
</div>
</div>
)}
{showDeleteModal && (
<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">

View File

@ -1,10 +1,10 @@
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import koszIcon from "../icons/kosz.png";
import { ReactComponent as KoszIcon } from '../icons/delete.svg';
const Wydatki = () => {
const [expenses, setExpenses] = useState([]);
const [showModal, setShowModal] = useState(false);
const [fromDate, setFromDate] = useState('');
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [error, setError] = useState(null);
const [deleteExpenseId, setDeleteExpenseId] = useState(null);
@ -40,6 +40,11 @@ const Wydatki = () => {
return;
}
if (newExpense.value <= 0) {
setError('Wartość wydatku musi być liczbą dodatnią.');
return;
}
const token = localStorage.getItem('token');
try {
const response = await axios.post('https://localhost:7039/api/Expenses', newExpense, {
@ -48,7 +53,6 @@ const Wydatki = () => {
const addedExpense = response.data;
setExpenses([...expenses, addedExpense]);
setNewExpense({ date: '', value: '', description: '' });
setShowModal(false);
} catch (error) {
console.error('Błąd podczas dodawania wydatku:', error);
setError('Wystąpił błąd podczas dodawania wydatku.');
@ -62,7 +66,6 @@ const Wydatki = () => {
headers: { Authorization: `Bearer ${token}` },
});
// Optimistically update the local state by filtering out the deleted expense
setExpenses(expenses.filter(expense => expense.id !== deleteExpenseId));
setDeleteExpenseId(null);
setShowDeleteModal(false);
@ -87,19 +90,80 @@ const Wydatki = () => {
return date.toLocaleDateString('pl-PL', options).replace(",", "");
};
const handleDateChange = (e) => {
setNewExpense({ ...newExpense, date: e.target.value });
};
const handleValueChange = (e) => {
setNewExpense({ ...newExpense, value: e.target.value });
};
const handleDescriptionChange = (e) => {
setNewExpense({ ...newExpense, description: e.target.value });
};
return (
<div className="p-10 ml-11">
<div className="mt-5">
<div className="flex items-center justify-between py-6 px-8 bg-gradient-to-r from-blue-500 to-teal-500 rounded-xl shadow-md mb-6">
<div className="text-white text-4xl font-semibold">Wydatki</div>
<button
onClick={() => setShowModal(true)}
className="bg-gradient-to-r from-green-500 to-green-700 text-white py-2 px-4 rounded-lg hover:from-green-600 hover:to-green-800 transition"
>
<span>Dodaj wydatek</span>
</button>
<h1 className="text-white text-4xl font-semibold">Wydatki</h1>
</div>
<div className="bg-white shadow-lg p-8 rounded-xl max-w-3xl mx-auto">
<div className="mb-6">
<div className="flex flex-col space-y-6">
<div className="flex space-x-6">
<div className="flex-1">
<label htmlFor="expenseDate" className="block text-sm font-medium text-gray-700">Data</label>
<input
type="datetime-local"
id="expenseDate"
value={newExpense.date}
onChange={handleDateChange}
className="mt-1 py-2 px-3 block w-full shadow-md sm:text-sm rounded-lg border-gray-300 focus:ring-indigo-500 focus:border-indigo-500"
/>
</div>
<div className="flex-1">
<label htmlFor="expenseValue" className="block text-sm font-medium text-gray-700">Wartość</label>
<input
type="number"
id="expenseValue"
value={newExpense.value}
onChange={handleValueChange}
className="mt-1 py-2 px-3 block w-full shadow-md sm:text-sm rounded-lg border-gray-300 focus:ring-indigo-500 focus:border-indigo-500"
/>
</div>
</div>
<div>
<label htmlFor="expenseDescription" className="block text-sm font-medium text-gray-700">Opis</label>
<textarea
id="expenseDescription"
value={newExpense.description}
onChange={handleDescriptionChange}
className="mt-1 py-2 px-3 block w-full shadow-md sm:text-sm rounded-lg border-gray-300 focus:ring-indigo-500 focus:border-indigo-500"
rows="4"
/>
</div>
<button
onClick={handleAddExpense}
type="button"
className="bg-gradient-to-r from-blue-500 to-blue-700 text-white font-semibold py-3 px-6 rounded-lg shadow-md hover:from-blue-600 hover:to-blue-800 transition duration-300 ease-in-out w-full"
>
Dodaj
</button>
</div>
</div>
{error && (
<div className="mt-4 text-red-500 text-center font-semibold">
{error}
</div>
)}
</div>
<div className="mt-5">
<table className="w-full rounded-lg shadow-lg">
<thead className="bg-gray-100 text-gray-700">
<tr>
@ -107,24 +171,25 @@ const Wydatki = () => {
<th className="p-3 text-left">Data</th>
<th className="p-3 text-left">Wartość</th>
<th className="p-3 text-left">Opis</th>
<th className="p-3 text-center"></th>
<th className="p-3 text-center">Usuń</th>
</tr>
</thead>
<tbody className="text-gray-600">
{expenses.map(expense => (
<tr key={expense.id} className="hover:bg-gray-50 transition-colors">
<tr key={expense.id} className="group hover:bg-gray-100 transition-colors">
<td className="p-3">{expense.id}</td>
<td className="p-3">{formatDate(expense.date)}</td>
<td className="p-3">{expense.value} </td>
<td className="p-3">{expense.description}</td>
<td className="p-3 text-center">
<td className="p-3 flex justify-center space-x-2">
<div className="flex space-x-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
<button
onClick={() => openDeleteConfirmation(expense.id)}
className="bg-gradient-to-r from-red-500 to-red-700 text-white py-2 px-4 rounded-lg hover:from-red-600 hover:to-red-800 transition"
className="text-red-500 hover:bg-red-200 active:bg-red-300 focus:outline-none p-2 rounded-full transition-colors"
>
<img src={koszIcon} alt="Usuń" className="inline w-5 mr-2" />
<span>Usuń</span>
<KoszIcon className="w-5 h-5" />
</button>
</div>
</td>
</tr>
))}
@ -132,74 +197,6 @@ const Wydatki = () => {
</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 bg-gray-500 opacity-50"></div>
<div className="bg-gradient-to-r from-blue-500 to-purple-600 p-1 rounded-lg shadow-xl transform transition-all sm:max-w-lg sm:w-full">
<div className="bg-white rounded-lg shadow-lg overflow-hidden">
<div className="px-4 py-5 sm:px-6 bg-gradient-to-r from-indigo-500 to-indigo-700 text-white">
<h3 className="text-lg font-medium">Dodaj nowy wydatek</h3>
</div>
<div className="bg-white px-4 py-5 sm:p-6">
<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="datetime-local"
id="expenseDate"
value={newExpense.date}
onChange={(e) => setNewExpense({ ...newExpense, date: e.target.value })}
className="mt-1 py-2 px-3 block w-full shadow-md sm:text-sm rounded-lg border-gray-300 focus:ring-indigo-500 focus:border-indigo-500"
/>
</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 py-2 px-3 block w-full shadow-md sm:text-sm rounded-lg border-gray-300 focus:ring-indigo-500 focus:border-indigo-500"
/>
</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 py-2 px-3 block w-full shadow-md sm:text-sm rounded-lg border-gray-300 focus:ring-indigo-500 focus:border-indigo-500"
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 shadow-lg px-4 py-2 bg-gradient-to-r from-green-400 to-green-600 text-base font-medium text-white hover:bg-green-500 sm:text-sm sm:leading-5"
>
Dodaj
</button>
<button
onClick={() => setShowModal(false)}
type="button"
className="mt-3 sm:mt-0 sm:ml-3 w-full inline-flex justify-center rounded-md shadow-md px-4 py-2 bg-white text-base font-medium text-gray-700 hover:text-gray-500 border-gray-300"
>
Anuluj
</button>
</div>
</div>
</div>
</div>
</div>
)}
{showDeleteModal && (
<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">
@ -221,21 +218,6 @@ const Wydatki = () => {
</div>
</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={() => setError(null)}
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-lg"
>
Zamknij
</button>
</div>
</div>
)}
</div>
);
};