From c4cd38ecac05d78589db57a2a533a92089827b83 Mon Sep 17 00:00:00 2001 From: Wiktor Szynaka Date: Thu, 28 Nov 2024 21:30:29 +0100 Subject: [PATCH] poprawa edycji transakcji, dodanie harmonogramu --- firm/src/components/DodawanieProduktów.js | 11 +- firm/src/components/EdycjaProduktu.js | 179 +++++---- firm/src/components/EdycjaTransakcji.js | 410 ++++++++++++--------- firm/src/components/Harmonogram.js | 173 ++++++++- firm/src/components/ListaProduktów.js | 2 +- firm/src/components/NavBar.js | 2 +- firm/src/components/Sidebar.js | 23 +- 7 files changed, 542 insertions(+), 258 deletions(-) diff --git a/firm/src/components/DodawanieProduktów.js b/firm/src/components/DodawanieProduktów.js index a16cfe2..3ae9cbd 100644 --- a/firm/src/components/DodawanieProduktów.js +++ b/firm/src/components/DodawanieProduktów.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import axios from 'axios'; import { useNavigate } from 'react-router-dom'; @@ -13,6 +13,15 @@ const DodawanieProduktu = () => { }); const navigate = useNavigate(); + useEffect(() => { + if (newProduct.type === '0') { + setNewProduct(prevState => ({ + ...prevState, + availability: '', + })); + } + }, [newProduct.type]); + const handleInputChange = (event) => { const { name, value } = event.target; setNewProduct({ ...newProduct, [name]: value }); diff --git a/firm/src/components/EdycjaProduktu.js b/firm/src/components/EdycjaProduktu.js index 6f6cc3a..4af9b68 100644 --- a/firm/src/components/EdycjaProduktu.js +++ b/firm/src/components/EdycjaProduktu.js @@ -11,7 +11,7 @@ const EdycjaProduktu = () => { type: '1', availability: '', }); - const [error, setError] = useState(null); + const [errors, setErrors] = useState({}); const navigate = useNavigate(); useEffect(() => { @@ -19,7 +19,7 @@ const EdycjaProduktu = () => { try { const token = localStorage.getItem('token'); if (!token) { - setError('Brak tokena. Użytkownik musi być zalogowany.'); + setErrors({ general: 'Brak tokena. Użytkownik musi być zalogowany.' }); return; } @@ -28,10 +28,18 @@ const EdycjaProduktu = () => { Authorization: `Bearer ${token}`, }, }); - setProduct(response.data); + + const productData = response.data; + setProduct({ + name: productData.name, + description: productData.description, + price: productData.price, + type: productData.type.toString(), + availability: productData.availability || '', + }); } catch (error) { console.error('Błąd podczas pobierania produktu:', error); - setError('Wystąpił błąd podczas pobierania danych produktu.'); + setErrors({ general: 'Wystąpił błąd podczas pobierania danych produktu.' }); } }; @@ -40,17 +48,45 @@ const EdycjaProduktu = () => { const handleInputChange = (event) => { const { name, value } = event.target; - setProduct({ ...product, [name]: value }); + + if (name === 'type') { + if (value === '0') { + setProduct({ + ...product, + [name]: value, + availability: '', + }); + } else { + setProduct({ + ...product, + [name]: value, + }); + } + } else { + setProduct({ ...product, [name]: value }); + } + setErrors((prevErrors) => ({ + ...prevErrors, + [name]: null, + })); }; const handleSaveChanges = async () => { const { name, description, price, type, availability } = product; - - if (!name || !description || !price || type === '') { - setError('Proszę uzupełnić wszystkie wymagane pola.'); + let validationErrors = {}; + + if (!name) validationErrors.name = 'Nazwa produktu jest wymagana.'; + if (!description) validationErrors.description = 'Opis produktu jest wymagany.'; + if (!price) validationErrors.price = 'Cena produktu jest wymagana.'; + if (type === '') validationErrors.type = 'Typ produktu jest wymagany.'; + if (price < 0) validationErrors.price = 'Cena nie może być ujemna.'; + if (type === '1' && !availability) validationErrors.availability = 'Dostępność jest wymagana dla produktu.'; + + if (Object.keys(validationErrors).length > 0) { + setErrors(validationErrors); return; } - + const payload = { id, name, @@ -59,89 +95,106 @@ const EdycjaProduktu = () => { type: parseInt(type, 10), ...(type === '1' && { availability: availability || 0 }), }; - + try { const token = localStorage.getItem('token'); if (!token) { - setError('Brak tokena. Użytkownik musi być zalogowany.'); + setErrors({ general: 'Brak tokena. Użytkownik musi być zalogowany.' }); return; } - + const config = { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, }; - - const response = await axios.put(`https://localhost:7039/api/Products/${id}`, payload, config); - - console.log('Produkt zapisany:', response.data); - - setError(null); + + await axios.put(`https://localhost:7039/api/Products/${id}`, payload, config); + setErrors({}); navigate('/produkty'); } catch (error) { console.error('Błąd podczas zapisywania zmian:', error); - + if (error.response && error.response.status === 400) { - setError('ID produktu nie zgadza się.'); + setErrors({ general: error.response.data }); } else { - setError('Wystąpił błąd podczas zapisywania zmian. Spróbuj ponownie.'); + setErrors({ general: 'Wystąpił błąd podczas zapisywania zmian. Spróbuj ponownie.' }); } } }; - return (

Edycja produktu

- {error &&

{error}

} -
- - - - - {product.type === '1' && ( + {errors.general &&

{errors.general}

} + +
+
+ {errors.name && {errors.name}} +
+ +
+ + {errors.description && {errors.description}} +
+ +
+ + {errors.price && {errors.price}} +
+ +
+ + {errors.type && {errors.type}} +
+ + {product.type === '1' && ( +
+ + {errors.availability && {errors.availability}} +
)}
+
-
- ))} - - )} - +
+ + {errors.date && {errors.date}} +
+
+ + {errors.employeeId && {errors.employeeId}} +
+ {transaction.transactionProducts.map((product, index) => ( +
+ handleQuantityChange(index, e.target.value)} + placeholder="Ilość" + className="block w-full px-4 py-2 border border-gray-300 rounded-lg" + /> + {errors[`quantity_${index}`] && ( + {errors[`quantity_${index}`]} + )} + +
+ ))} - - - - - - - +
+ + {errors.paymentType && ( + {errors.paymentType} + )} +
+
+ + {errors.discount && {errors.discount}} +
diff --git a/firm/src/components/Harmonogram.js b/firm/src/components/Harmonogram.js index 42f2b82..cc971ae 100644 --- a/firm/src/components/Harmonogram.js +++ b/firm/src/components/Harmonogram.js @@ -1,10 +1,177 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import { jwtDecode } from 'jwt-decode'; const Harmonogram = () => { + const [workdays, setWorkdays] = useState([]); + const [email, setEmail] = useState(null); + const [currentDate, setCurrentDate] = useState(new Date()); + const [displayDate, setDisplayDate] = useState(new Date()); + const [daysInMonth, setDaysInMonth] = useState([]); + const [manualDateChange, setManualDateChange] = useState(false); + + useEffect(() => { + const token = localStorage.getItem('token'); + if (token) { + const decodedToken = jwtDecode(token); + setEmail(decodedToken.email); + fetchWorkdays(decodedToken.email); + } + + const interval = setInterval(() => { + if (!manualDateChange) { + setCurrentDate(new Date()); + } + }, 1000); + + return () => clearInterval(interval); + }, [manualDateChange]); + + const fetchWorkdays = async (email) => { + try { + const response = await axios.get(`https://localhost:7039/api/Workday/user/${email}/workdays`, { + headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }, + }); + setWorkdays(response.data); + } catch (error) { + console.error('Błąd podczas pobierania dni roboczych:', error); + } + }; + + const handleStartWorkday = async (date) => { + + const token = localStorage.getItem('token'); + if (!token) { + alert('Brak tokena. Użytkownik musi być zalogowany.'); + return; + } + + try { + await axios.post( + 'https://localhost:7039/api/workday/start', + { date }, + { + headers: { Authorization: `Bearer ${token}` }, + } + ); + alert('Dzień roboczy rozpoczęty!'); + fetchWorkdays(email); + } catch (error) { + console.error(error); + } + }; + + const isWorkday = (date) => { + return workdays.includes(date); + }; + + const formatTime = (date) => { + const hours = date.getHours().toString().padStart(2, '0'); + const minutes = date.getMinutes().toString().padStart(2, '0'); + const seconds = date.getSeconds().toString().padStart(2, '0'); + return `${hours}:${minutes}:${seconds}`; + }; + + const formatDayOfWeek = (date) => { + const daysOfWeek = ['Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota', 'Niedziela']; + return daysOfWeek[date.getDay() === 0 ? 6 : date.getDay() - 1]; + }; + + const formatDate = (date) => { + const day = date.getDate().toString().padStart(2, '0'); + const month = (date.getMonth() + 1).toString().padStart(2, '0'); + const year = date.getFullYear(); + return `${day}-${month}-${year}`; + }; + + const generateDaysInMonth = () => { + const firstDayOfMonth = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1); + const lastDayOfMonth = new Date(displayDate.getFullYear(), displayDate.getMonth() + 1, 0); + + const firstDayWeekday = (firstDayOfMonth.getDay() === 0 ? 6 : firstDayOfMonth.getDay() - 1); + const numberOfDaysInMonth = lastDayOfMonth.getDate(); + + const days = []; + for (let i = 0; i < firstDayWeekday; i++) { + days.push(null); + } + + for (let i = 1; i <= numberOfDaysInMonth; i++) { + days.push(i); + } + + setDaysInMonth(days); + }; + + useEffect(() => { + generateDaysInMonth(); + }, [displayDate]); + + const changeMonth = (direction) => { + setManualDateChange(true); + const newDate = new Date(displayDate); + if (direction === 'previous') { + newDate.setMonth(displayDate.getMonth() - 1); + } else if (direction === 'next') { + newDate.setMonth(displayDate.getMonth() + 1); + } + setDisplayDate(newDate); + setTimeout(() => setManualDateChange(false), 1000); + }; + + const formatMonth = (monthIndex) => { + const months = [ + 'Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', + 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień', + ]; + return months[monthIndex]; + }; + return ( -
-

Harmonogram

+
+
+
+

{formatDate(currentDate)} - {formatDayOfWeek(currentDate)}

+

{formatTime(currentDate)}

+
+ +
+ +

{formatMonth(displayDate.getMonth())} {displayDate.getFullYear()}

+ +
+ +
+ {['P', 'W', 'Ś', 'C', 'P', 'S', 'N'].map((day, index) => ( +
{day}
+ ))} + {daysInMonth.map((day, index) => ( +
day && handleStartWorkday(new Date(displayDate.getFullYear(), displayDate.getMonth(), day))} + > + {day} +
+ ))} +
+
); }; diff --git a/firm/src/components/ListaProduktów.js b/firm/src/components/ListaProduktów.js index 5630a1f..aa95279 100644 --- a/firm/src/components/ListaProduktów.js +++ b/firm/src/components/ListaProduktów.js @@ -81,7 +81,7 @@ const ListaProduktow = ({ onAdd }) => { {product.name} {product.description} {parseFloat(product.price).toFixed(2)} - {product.availability} + {product.type === 0 ? "" : product.availability}