diff --git a/firm/src/components/ConfirmationModal.js b/firm/src/components/ConfirmationModal.js deleted file mode 100644 index 58c0d0e..0000000 --- a/firm/src/components/ConfirmationModal.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; - -const ConfirmationModal = ({ message, onCancel, onConfirm }) => { - return ( -
-
-

Potwierdź usunięcie

-

{message}

-
- - -
-
-
- ); -}; - -export default ConfirmationModal; diff --git a/firm/src/components/DodawanieProduktów.js b/firm/src/components/DodawanieProduktów.js index 3ae9cbd..e9772b4 100644 --- a/firm/src/components/DodawanieProduktów.js +++ b/firm/src/components/DodawanieProduktów.js @@ -27,6 +27,10 @@ const DodawanieProduktu = () => { setNewProduct({ ...newProduct, [name]: value }); }; + const handleCancel = () => { + navigate('/produkty'); + } + const handleAddProduct = async () => { const { name, description, price, type, availability } = newProduct; @@ -75,65 +79,73 @@ const DodawanieProduktu = () => { }; return ( -
-

Dodaj nowy produkt lub usługę

- {error &&

{error}

} -
- - - - - {newProduct.type === '1' && ( +
+
+

Dodaj nowy produkt lub usługę

+ {error &&

{error}

} +
+ + - )} -
-
- + + {newProduct.type === '1' && ( + + )} +
+
+ + +
); + + }; export default DodawanieProduktu; diff --git a/firm/src/components/DodawanieTransakcji.js b/firm/src/components/DodawanieTransakcji.js index adab366..4c30d5c 100644 --- a/firm/src/components/DodawanieTransakcji.js +++ b/firm/src/components/DodawanieTransakcji.js @@ -63,6 +63,9 @@ const DodawanieTransakcji = () => { const { name, value } = event.target; setNewTransaction({ ...newTransaction, [name]: value }); }; + const handleCancel = () => { + navigate('/transakcje'); + } const handleProductChange = (index, selectedOption) => { const updatedTransactionProducts = [...newTransaction.transactionProducts]; @@ -153,29 +156,29 @@ const DodawanieTransakcji = () => { }; return ( -
-

Dodaj nową transakcję

- +
+

Dodaj nową transakcję

+ {error &&

{error}

} - + - + - + {isLoading ? (
Ładowanie produktów...
) : ( @@ -200,11 +203,11 @@ const DodawanieTransakcji = () => { setNewTransaction({ ...newTransaction, transactionProducts: updatedTransactionProducts }); }} placeholder="Ilość" - className="block w-full mb-2 px-4 py-2 border border-gray-300 rounded-lg" + className="block w-full mb-2 px-4 py-2 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500" /> @@ -212,49 +215,58 @@ const DodawanieTransakcji = () => { ))} )} - + - + - + - + - - + +
+ + + +
- ); + ); }; export default DodawanieTransakcji; diff --git a/firm/src/components/EdycjaProduktu.js b/firm/src/components/EdycjaProduktu.js index 4af9b68..3b14f55 100644 --- a/firm/src/components/EdycjaProduktu.js +++ b/firm/src/components/EdycjaProduktu.js @@ -46,6 +46,10 @@ const EdycjaProduktu = () => { fetchProduct(); }, [id]); + const handleCancel = () => { + navigate('/produkty'); + } + const handleInputChange = (event) => { const { name, value } = event.target; @@ -125,86 +129,92 @@ const EdycjaProduktu = () => { }; return ( -
-

Edycja produktu

- {errors.general &&

{errors.general}

} - -
-
- - {errors.name && {errors.name}} -
- -
- - {errors.description && {errors.description}} -
- -
- - {errors.price && {errors.price}} -
- -
- - {errors.type && {errors.type}} -
- - {product.type === '1' && ( +
+
+

Edycja produktu

+ {errors.general &&

{errors.general}

} + +
+
+ + {errors.name && {errors.name}} +
+ +
+ + {errors.description && {errors.description}} +
+
- {errors.availability && {errors.availability}} + {errors.price && {errors.price}}
- )} -
- -
- + +
+ + {errors.type && {errors.type}} +
+ + {product.type === '1' && ( +
+ + {errors.availability && {errors.availability}} +
+ )} +
+ +
+ + +
- ); + ); }; export default EdycjaProduktu; diff --git a/firm/src/components/EdycjaTransakcji.js b/firm/src/components/EdycjaTransakcji.js index d7d3cd1..eca8273 100644 --- a/firm/src/components/EdycjaTransakcji.js +++ b/firm/src/components/EdycjaTransakcji.js @@ -90,6 +90,10 @@ const EdycjaTransakcji = () => { return Object.keys(validationErrors).length === 0; }; + const handleCancel = () => { + navigate('/transkacje'); + } + const handleInputChange = (event) => { const { name, value } = event.target; setTransaction((prev) => ({ ...prev, [name]: value })); @@ -199,9 +203,10 @@ const EdycjaTransakcji = () => { }; return ( -
-

Edycja Transakcji

+
+

Edycja Transakcji

{error &&

{error}

} +
{ value={transaction.date} onChange={handleInputChange} placeholder="Data" - className="block w-full px-4 py-2 border border-gray-300 rounded-lg" + 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.date && {errors.date}}
+
{ value={transaction.employeeId} onChange={handleInputChange} placeholder="Nr. Pracownika" - className="block w-full px-4 py-2 border border-gray-300 rounded-lg" + 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.employeeId && {errors.employeeId}}
+ {transaction.transactionProducts.map((product, index) => (
{ 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" + 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 && ( - {errors.paymentType} - )} + {errors.paymentType && {errors.paymentType}}
+
{ value={transaction.discount} onChange={handleInputChange} placeholder="Rabat" - className="block w-full px-4 py-2 border border-gray-300 rounded-lg" + 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.discount && {errors.discount}}
- +
+ + + +
- ); + ); }; export default EdycjaTransakcji; diff --git a/firm/src/components/Harmonogram.js b/firm/src/components/Harmonogram.js index eebec7c..67f8285 100644 --- a/firm/src/components/Harmonogram.js +++ b/firm/src/components/Harmonogram.js @@ -9,6 +9,7 @@ const Harmonogram = () => { const [manualDateChange, setManualDateChange] = useState(false); const [isWorking, setIsWorking] = useState(false); const [selectedDay, setSelectedDay] = useState(null); + const [loading, setLoading] = useState(false); useEffect(() => { const token = localStorage.getItem('token'); @@ -20,7 +21,7 @@ const Harmonogram = () => { if (!manualDateChange) { setCurrentDate(new Date()); } - }, 1000); + }, 10000); return () => clearInterval(interval); }, [manualDateChange]); @@ -31,7 +32,6 @@ const Harmonogram = () => { headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }, }); setWorkdays(response.data); - console.log(response.data); } catch (error) { console.error('Błąd podczas pobierania dni roboczych:', error); } @@ -48,9 +48,7 @@ const Harmonogram = () => { await axios.post( 'https://localhost:7039/api/workday/start', {}, - { - headers: { Authorization: `Bearer ${token}` }, - } + { headers: { Authorization: `Bearer ${token}` } } ); setIsWorking(true); } catch (error) { @@ -69,9 +67,7 @@ const Harmonogram = () => { await axios.post( 'https://localhost:7039/api/workday/stop', {}, - { - headers: { Authorization: `Bearer ${token}` }, - } + { headers: { Authorization: `Bearer ${token}` } } ); setIsWorking(false); } catch (error) { @@ -94,13 +90,12 @@ const Harmonogram = () => { 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}`; + return `${year}-${month}-${day}`; }; 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(); @@ -110,7 +105,22 @@ const Harmonogram = () => { } for (let i = 1; i <= numberOfDaysInMonth; i++) { - days.push(i); + const day = new Date(displayDate.getFullYear(), displayDate.getMonth(), i); + const formattedDate = formatDate(day); + + const dayWork = workdays.find(workday => { + const startDate = new Date(workday.startTime.split('T')[0]); + const endDate = new Date(workday.endTime.split('T')[0]); + return ( + formattedDate === workday.startTime.split('T')[0] || + (day >= startDate && day <= endDate) + ); + }); + + days.push({ + number: i, + type: dayWork ? (dayWork.absence ? 'absence' : 'working') : 'default' + }); } setDaysInMonth(days); @@ -118,7 +128,7 @@ const Harmonogram = () => { useEffect(() => { generateDaysInMonth(); - }, [displayDate]); + }, [displayDate, workdays]); const changeMonth = (direction) => { setManualDateChange(true); @@ -140,20 +150,68 @@ const Harmonogram = () => { return months[monthIndex]; }; - const handleDayClick = (day) => { - const workDay = workdays.find((workday) => { - const workDayDate = new Date(workday.startTime).toLocaleDateString(); - const selectedDayDate = new Date(displayDate.getFullYear(), displayDate.getMonth(), day).toLocaleDateString(); - return workDayDate === selectedDayDate; - }); - setSelectedDay(workDay || null); - }; - - const formatWorkedHours = (workedHours) => { - const [hours, minutes, seconds] = workedHours.split(':'); + const handleDayClick = async (day) => { + if (!day) return; - return `${hours}:${minutes}:${Math.floor(parseFloat(seconds)).toString().padStart(2, '0')}`; + const selectedDate = new Date(displayDate.getFullYear(), displayDate.getMonth(), day, 0, 0, 0, 0); + const formattedDate = formatDate(selectedDate); + + const dayStatus = workdays.find(workday => { + const startDate = new Date(workday.startTime.split('T')[0]); + const endDate = new Date(workday.endTime.split('T')[0]); + + return ( + formattedDate === workday.startTime.split('T')[0] || + (selectedDate >= startDate && selectedDate <= endDate) + ); + }); + + console.log("Selected Date:", formattedDate); + console.log("Day Status:", dayStatus); + + if (dayStatus) { + if (dayStatus.absence && dayStatus.absence.trim() !== "") { + setSelectedDay({ + date: formattedDate, + dayOfWeek: formatDayOfWeek(selectedDate), + absence: dayStatus.absence, + }); + } else { + try { + setLoading(true); + const response = await axios.get( + `https://localhost:7039/api/Workday/user/day/info/${formattedDate}`, + { headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } } + ); + const workdayDetails = response.data; + + setSelectedDay({ + date: formattedDate, + dayOfWeek: formatDayOfWeek(selectedDate), + workdayDetails: workdayDetails.workdayDetails, + totalWorkedHours: workdayDetails.totalWorkedHours, + absence: null, + }); + } catch (error) { + console.error("Błąd podczas pobierania danych dnia roboczego:", error); + setSelectedDay({ + date: formattedDate, + dayOfWeek: formatDayOfWeek(selectedDate), + absence: "Błąd pobierania danych", + }); + } finally { + setLoading(false); + } + } + } else { + setSelectedDay({ + date: formattedDate, + dayOfWeek: formatDayOfWeek(selectedDate), + absence: "Brak danych o tym dniu", + }); + } }; + return (
@@ -162,69 +220,87 @@ const 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) => ( -
new Date(workday.startTime).getDate() === day) && 'bg-green-200'}`} - style={{ - boxShadow: day ? '0 4px 6px rgba(0, 0, 0, 0.1)' : 'none', - }} - onClick={() => day && handleDayClick(day)} - > - {day} -
- ))} -
- - {selectedDay && ( -
-
-

Godziny pracy

-

Dzień: {formatDate(new Date(selectedDay.startTime))}

-

Start: {formatTime(new Date(selectedDay.startTime))}

-

Stop: {formatTime(new Date(selectedDay.endTime))}

-

Godziny pracy: {formatWorkedHours(selectedDay.workedHours)}

- +

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

+
+ +
+ {['P', 'W', 'Ś', 'C', 'P', 'S', 'N'].map((day, index) => ( +
{day}
+ ))} + {daysInMonth.map((day, index) => ( +
handleDayClick(day?.number)} + > + {day?.number || ''} +
+ ))} +
- )} + +
+ {loading ? ( +

Ładowanie danych...

+ ) : selectedDay ? ( +
+

+ Szczegóły dnia {selectedDay.date} ({selectedDay.dayOfWeek}) +

+ {selectedDay.absence && selectedDay.absence.trim() !== "" ? ( +

{selectedDay.absence}

+ ) : selectedDay.workdayDetails && selectedDay.workdayDetails.length > 0 ? ( + selectedDay.workdayDetails.map((detail, index) => { + const formattedStartTime = new Date(detail.startTime).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + }); + const formattedEndTime = new Date(detail.endTime).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + }); + const workedHours = new Date(`1970-01-01T${detail.workedHours}Z`) + .toISOString() + .substr(11, 8); + + return ( +
+

Start: {formattedStartTime}

+

Koniec: {formattedEndTime}

+

Przepracowane godziny: {workedHours}

+
+ ); + }) + ) : ( +

Brak danych o tym dniu.

+ )} +
+ ) : ( +

Wybierz dzień, aby zobaczyć szczegóły.

+ )} +
+ +
); }; diff --git a/firm/src/components/ListaProduktów.js b/firm/src/components/ListaProduktów.js index aa95279..1f1f19f 100644 --- a/firm/src/components/ListaProduktów.js +++ b/firm/src/components/ListaProduktów.js @@ -56,36 +56,38 @@ const ListaProduktow = ({ onAdd }) => { return (
-
-

Katalog Produktów

-
- - +
+ - - - - - - + + + + + + - + {products.map((product) => ( - - - - - - - + + + + + + - ))} - -
IDProduktOpisCenaDostępnośćIDProduktOpisCenaDostępnośćAkcje
{product.id}{product.name}{product.description}{parseFloat(product.price).toFixed(2)}{product.type === 0 ? "" : product.availability} +
{product.id}{product.name}{product.description}{parseFloat(product.price).toFixed(2)} zł + {product.type === 0 ? "" : product.availability} +
-
+ ))} + + +
+ {showModal && (
diff --git a/firm/src/components/ListaTransakcji.js b/firm/src/components/ListaTransakcji.js index 8a756d5..ffdd1db 100644 --- a/firm/src/components/ListaTransakcji.js +++ b/firm/src/components/ListaTransakcji.js @@ -87,56 +87,56 @@ const ListaTransakcji = ({ onAdd}) => { return (
-
-

Lista Transakcji

-
- - +
+ - - - - - - - - + + + + + + + + - + {transactions.map(transaction => ( - - - - + + + - - - - - + + +
IDDataProduktIlośćKwotaSposób płatnościNr. PracownikaIDDataProduktIlośćKwotaSposób płatnościNr. PracownikaAkcje
{transaction.id}{formatDate(transaction.date)} +
{transaction.id}{formatDate(transaction.date)} {transaction.transactionProducts.map(product => (
{product.product.name}
))}
+ {transaction.transactionProducts.map(product => (
{product.quantity}
))}
{formatPrice(transaction.totalPrice)}{transaction.paymentType}{transaction.employeeId} + {formatPrice(transaction.totalPrice)}{transaction.paymentType}{transaction.employeeId} + + +
+
- -
- - - - {selectedOption === 'raporty' && ( -
-
- - setReportType(e.target.value)} - className="p-2 border" - /> -
- -
- - setStartDate(e.target.value)} - className="p-2 border" - /> -
- -
- - setEndDate(e.target.value)} - className="p-2 border" - /> -
- - -
- )} - - {selectedOption === 'harmonogramy' && ( -
-
- - -
- {selectedEmail && ( - - )} -
- )} - - ); -}; - -const WidokHarmonogramu = ({ workdays }) => { - const [displayDate, setDisplayDate] = useState(new Date()); - const [daysInMonth, setDaysInMonth] = useState([]); - const [manualDateChange, setManualDateChange] = useState(false); - const [selectedDay, setSelectedDay] = useState(null); - - useEffect(() => { - generateDaysInMonth(); - }, [displayDate]); - - 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); - }; - - 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]; - }; - - const handleDayClick = (day) => { - const workDay = workdays.find((workday) => { - const workDayDate = new Date(workday.startTime).toLocaleDateString(); - const selectedDayDate = new Date(displayDate.getFullYear(), displayDate.getMonth(), day).toLocaleDateString(); - return workDayDate === selectedDayDate; - }); - setSelectedDay(workDay || null); - }; - - 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 formatWorkedHours = (workedHours) => { - const [hours, minutes, seconds] = workedHours.split(':'); - - return `${hours}:${minutes}:${Math.floor(parseFloat(seconds)).toString().padStart(2, '0')}`; - }; - const formatTime = (date) => { - const hours = date.getHours().toString().padStart(2, '0'); - const minutes = date.getMinutes().toString().padStart(2, '0'); - return `${hours}:${minutes}`; - }; - return ( -
-
- -

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

- -
- -
- {['P', 'W', 'Ś', 'C', 'P', 'S', 'N'].map((day, index) => ( -
{day}
- ))} - {daysInMonth.map((day, index) => ( -
new Date(workday.startTime).getDate() === day) && 'bg-green-200'}`} - style={{ - boxShadow: day ? '0 4px 6px rgba(0, 0, 0, 0.1)' : 'none', - }} - onClick={() => day && handleDayClick(day)} - > - {day} -
- ))} -
- - {selectedDay && ( -
-
-

Godziny pracy

-

Dzień: {formatDate(new Date(selectedDay.startTime))}

-

Start: {formatTime(new Date(selectedDay.startTime))}

-

Stop: {formatTime(new Date(selectedDay.endTime))}

-

Godziny pracy: {formatWorkedHours(selectedDay.workedHours)}

-
+
+ + + + {selectedOption === 'raporty' && ( +
+
+
+

Pobierz Raport

+ +
+ + +
+ +
+ + setStartDate(e.target.value)} + className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +
+ +
+ + setEndDate(e.target.value)} + className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +
+ + +
+
+
+ + + )} + + {selectedOption === 'harmonogramy' && ( +
+
+
+ +
+ + +
+ {selectedEmail && ( + + )} +
+
+
+ )} + + {selectedOption === 'absencje' && ( +
+
+
+

Dodaj Absencję

+ +
+ + +
+ +
+ + +
+ +
+ + setStartDate(e.target.value)} + className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +
+ +
+ + setEndDate(e.target.value)} + className="w-full p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +
+ + +
+
+
+ )} ); }; -export default PanelAdministratora; \ No newline at end of file +export default PanelAdministratora; diff --git a/firm/src/components/Raporty.js b/firm/src/components/Raporty.js index d1e5f94..19809bc 100644 --- a/firm/src/components/Raporty.js +++ b/firm/src/components/Raporty.js @@ -1,7 +1,6 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; import koszIcon from "../icons/kosz.png"; -import ConfirmationModal from './ConfirmationModal'; const Raporty = () => { const [fromDate, setFromDate] = useState(''); @@ -9,6 +8,7 @@ const Raporty = () => { const [error, setError] = useState(null); const [reports, setReports] = useState([]); const [deleteReportId, setDeleteReportId] = useState(null); + const [showDeleteModal, setShowDeleteModal] = useState(false); const fetchReports = async () => { const token = localStorage.getItem('token'); @@ -28,11 +28,13 @@ const Raporty = () => { } }; - const openDeleteConfirmation = (transactionId) => { - setDeleteReportId(transactionId); + const openDeleteConfirmation = (reportId) => { + setDeleteReportId(reportId); + setShowDeleteModal(true); }; const closeDeleteConfirmation = () => { + setShowDeleteModal(false); setDeleteReportId(null); }; @@ -77,7 +79,7 @@ const Raporty = () => { } }); fetchReports(); - setDeleteReportId(null); + closeDeleteConfirmation(); } catch (error) { console.error('Błąd podczas usuwania raportu:', error); if (error.response && error.response.data) { @@ -96,67 +98,116 @@ const Raporty = () => { return (
-
-
- Generowanie raportów +
+

Generowanie raportów

+
+ +
+
+
+ + setFromDate(e.target.value)} + 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" + /> +
+ +
+ + setToDate(e.target.value)} + 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" + /> +
+ +
+ + +
- - setFromDate(e.target.value)} className="mr-5" /> - - setToDate(e.target.value)} className="mr-5" /> - -
-
-

Raporty

- - +
+ - - - - - - - + + + + + + + - {reports.map(report => ( - - - - - - - - + + + + + + + ))}
IDData odData doSuma dochodówSuma wydatkówBilansIDData odData doSuma dochodówSuma wydatkówBilans
{report.id}{formatDate(report.fromDate)}{formatDate(report.toDate)}{report.totalIncome}{report.totalExpenses}{report.totalBalance} - + {reports.map((report) => ( +
{report.id}{formatDate(report.fromDate)}{formatDate(report.toDate)}{report.totalIncome}{report.totalExpenses}{report.totalBalance} +
+ {error && (

Błąd

{error}

-
)} - {deleteReportId && ( - handleDeleteReport(deleteReportId)} - /> + + {showDeleteModal && ( +
+
+

Czy na pewno chcesz usunąć ten raport?

+
+ + +
+
+
)}
); diff --git a/firm/src/components/WidokHarmonogramu.js b/firm/src/components/WidokHarmonogramu.js index a8121b7..8c55f39 100644 --- a/firm/src/components/WidokHarmonogramu.js +++ b/firm/src/components/WidokHarmonogramu.js @@ -1,135 +1,221 @@ import React, { useState, useEffect } from 'react'; +import axios from 'axios'; const WidokHarmonogramu = ({ workdays }) => { - const [displayDate, setDisplayDate] = useState(new Date()); - const [daysInMonth, setDaysInMonth] = useState([]); - const [manualDateChange, setManualDateChange] = useState(false); - const [selectedDay, setSelectedDay] = useState(null); - - useEffect(() => { - generateDaysInMonth(); - }, [displayDate]); - - 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); - }; - - 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]; - }; - - const handleDayClick = (day) => { - const workDay = workdays.find((workday) => { - const workDayDate = new Date(workday.startTime).toLocaleDateString(); - const selectedDayDate = new Date(displayDate.getFullYear(), displayDate.getMonth(), day).toLocaleDateString(); - return workDayDate === selectedDayDate; + const [currentDate, setCurrentDate] = useState(new Date()); + const [displayDate, setDisplayDate] = useState(new Date()); + const [daysInMonth, setDaysInMonth] = useState([]); + const [manualDateChange, setManualDateChange] = useState(false); + const [isWorking, setIsWorking] = useState(false); + const [selectedDay, setSelectedDay] = useState(null); + const [loading, setLoading] = useState(false); + + useEffect(() => { + generateDaysInMonth(); + }, [displayDate, workdays]); + + 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++) { + const day = new Date(displayDate.getFullYear(), displayDate.getMonth(), i); + const formattedDate = formatDate(day); + + const dayWork = workdays.find(workday => { + const startDate = new Date(workday.startTime.split('T')[0]); + const endDate = new Date(workday.endTime.split('T')[0]); + return ( + formattedDate === workday.startTime.split('T')[0] || + (day >= startDate && day <= endDate) + ); }); - setSelectedDay(workDay || null); - }; - - 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 formatWorkedHours = (workedHours) => { - const [hours, minutes, seconds] = workedHours.split(':'); - - return `${hours}:${minutes}:${Math.floor(parseFloat(seconds)).toString().padStart(2, '0')}`; - }; - const formatTime = (date) => { - const hours = date.getHours().toString().padStart(2, '0'); - const minutes = date.getMinutes().toString().padStart(2, '0'); - return `${hours}:${minutes}`; - }; - return ( -
-
- -

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

- -
- -
- {['P', 'W', 'Ś', 'C', 'P', 'S', 'N'].map((day, index) => ( -
{day}
- ))} - {daysInMonth.map((day, index) => ( -
new Date(workday.startTime).getDate() === day) && 'bg-green-200'}`} - style={{ - boxShadow: day ? '0 4px 6px rgba(0, 0, 0, 0.1)' : 'none', - }} - onClick={() => day && handleDayClick(day)} - > - {day} -
- ))} -
- - {selectedDay && ( -
-
-

Godziny pracy

-

Dzień: {formatDate(new Date(selectedDay.startTime))}

-

Start: {formatTime(new Date(selectedDay.startTime))}

-

Stop: {formatTime(new Date(selectedDay.endTime))}

-

Godziny pracy: {formatWorkedHours(selectedDay.workedHours)}

- -
-
- )} -
- ); + + days.push({ + number: i, + type: dayWork ? (dayWork.absence ? 'absence' : 'working') : 'default' + }); + } + + setDaysInMonth(days); }; -export default WidokHarmonogramu; \ No newline at end of file + + 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]; + }; + + const handleDayClick = async (day) => { + if (!day) return; + + const selectedDate = new Date(displayDate.getFullYear(), displayDate.getMonth(), day, 0, 0, 0, 0); + const formattedDate = formatDate(selectedDate); + + const dayStatus = workdays.find(workday => { + const startDate = new Date(workday.startTime.split('T')[0]); + const endDate = new Date(workday.endTime.split('T')[0]); + + return ( + formattedDate === workday.startTime.split('T')[0] || + (selectedDate >= startDate && selectedDate <= endDate) + ); + }); + + console.log("Selected Date:", formattedDate); + console.log("Day Status:", dayStatus); + + if (dayStatus) { + if (dayStatus.absence && dayStatus.absence.trim() !== "") { + setSelectedDay({ + date: formattedDate, + dayOfWeek: formatDayOfWeek(selectedDate), + absence: dayStatus.absence, + }); + } else { + try { + const response = await axios.get( + `https://localhost:7039/api/Workday/user/day/info/${formattedDate}`, + { headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } } + ); + const workdayDetails = response.data; + + setSelectedDay({ + date: formattedDate, + dayOfWeek: formatDayOfWeek(selectedDate), + workdayDetails: workdayDetails.workdayDetails, + totalWorkedHours: workdayDetails.totalWorkedHours, + absence: null, + }); + } catch (error) { + console.error("Błąd podczas pobierania danych dnia roboczego:", error); + setSelectedDay({ + date: formattedDate, + dayOfWeek: formatDayOfWeek(selectedDate), + absence: "Błąd pobierania danych", + }); + } + } + } else { + setSelectedDay({ + date: formattedDate, + dayOfWeek: formatDayOfWeek(selectedDate), + absence: "Brak danych o tym dniu", + }); + } + }; + + + 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 `${year}-${month}-${day}`; + }; + + return ( +
+
+
+
+ +

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

+ +
+ +
+ {['P', 'W', 'Ś', 'C', 'P', 'S', 'N'].map((day, index) => ( +
{day}
+ ))} + {daysInMonth.map((day, index) => ( +
handleDayClick(day?.number)} + > + {day?.number || ''} +
+ ))} +
+
+ +
+ {loading ? ( +

Ładowanie danych...

+ ) : selectedDay ? ( +
+

+ Szczegóły dnia {selectedDay.date} ({selectedDay.dayOfWeek}) +

+ {selectedDay.absence && selectedDay.absence.trim() !== "" ? ( +

{selectedDay.absence}

+ ) : selectedDay.workdayDetails && selectedDay.workdayDetails.length > 0 ? ( + selectedDay.workdayDetails.map((detail, index) => { + const formattedStartTime = new Date(detail.startTime).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + }); + const formattedEndTime = new Date(detail.endTime).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + }); + const workedHours = new Date(`1970-01-01T${detail.workedHours}Z`) + .toISOString() + .substr(11, 8); + + return ( +
+

Start: {formattedStartTime}

+

Koniec: {formattedEndTime}

+

Przepracowane godziny: {workedHours}

+
+ ); + }) + ) : ( +

Brak danych o tym dniu.

+ )} +
+ ) : ( +

Wybierz dzień, aby zobaczyć szczegóły.

+ )} +
+ +
+
+ ); +}; + +export default WidokHarmonogramu; diff --git a/firm/src/components/Wydatki.js b/firm/src/components/Wydatki.js index 39140bf..8b2eabe 100644 --- a/firm/src/components/Wydatki.js +++ b/firm/src/components/Wydatki.js @@ -1,12 +1,11 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; import koszIcon from "../icons/kosz.png"; -import plusIcon from "../icons/plus.png"; -import ConfirmationModal from './ConfirmationModal'; const Wydatki = () => { const [expenses, setExpenses] = useState([]); const [showModal, setShowModal] = useState(false); + const [showDeleteModal, setShowDeleteModal] = useState(false); const [error, setError] = useState(null); const [deleteExpenseId, setDeleteExpenseId] = useState(null); const [newExpense, setNewExpense] = useState({ @@ -23,9 +22,7 @@ const Wydatki = () => { } try { const response = await axios.get('https://localhost:7039/api/Expenses', { - headers: { - Authorization: `Bearer ${token}` - } + headers: { Authorization: `Bearer ${token}` }, }); setExpenses(response.data); } catch (error) { @@ -42,20 +39,15 @@ const Wydatki = () => { setError('Proszę uzupełnić wszystkie pola.'); return; } + const token = localStorage.getItem('token'); try { const response = await axios.post('https://localhost:7039/api/Expenses', newExpense, { - headers: { - Authorization: `Bearer ${token}` - } + headers: { Authorization: `Bearer ${token}` }, }); const addedExpense = response.data; setExpenses([...expenses, addedExpense]); - setNewExpense({ - date: '', - value: '', - description: '' - }); + setNewExpense({ date: '', value: '', description: '' }); setShowModal(false); } catch (error) { console.error('Błąd podczas dodawania wydatku:', error); @@ -63,16 +55,17 @@ const Wydatki = () => { } }; - const handleDeleteExpense = async (expenseId) => { + const handleDeleteExpense = async () => { const token = localStorage.getItem('token'); try { - await axios.delete(`https://localhost:7039/api/Expenses/${expenseId}`, { - headers: { - Authorization: `Bearer ${token}` - } + await axios.delete(`https://localhost:7039/api/Expenses/${deleteExpenseId}`, { + headers: { Authorization: `Bearer ${token}` }, }); - fetchExpenses(); + + // Optimistically update the local state by filtering out the deleted expense + setExpenses(expenses.filter(expense => expense.id !== deleteExpenseId)); setDeleteExpenseId(null); + setShowDeleteModal(false); } catch (error) { console.error('Błąd podczas usuwania wydatku:', error); if (error.response && error.response.data) { @@ -85,10 +78,7 @@ const Wydatki = () => { const openDeleteConfirmation = (expenseId) => { setDeleteExpenseId(expenseId); - }; - - const closeDeleteConfirmation = () => { - setDeleteExpenseId(null); + setShowDeleteModal(true); }; const formatDate = (dateString) => { @@ -100,34 +90,40 @@ const Wydatki = () => { return (
-
-
- Wydatki -
-
- - + +
+ - - - - - + + + + + - + {expenses.map(expense => ( - - - - - - + + + + + @@ -135,65 +131,111 @@ const Wydatki = () => {
IDDataWartośćOpisIDDataWartośćOpis
{expense.id}{formatDate(expense.date)}{expense.value}{expense.description} -
{expense.id}{formatDate(expense.date)}{expense.value} zł{expense.description} +
+ {showModal && (
-
-
-
-
-
-

Dodaj nowy wydatek

-
-
-
-
- - setNewExpense({ ...newExpense, date: e.target.value })} className="mt-1 border py-1 px-3 block w-full shadow-sm sm:text-sm rounded-md" /> -
+
+
+
+
+

Dodaj nowy wydatek

+
+
+
+
+ + 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" + /> +
-
- - setNewExpense({ ...newExpense, value: e.target.value })} className="mt-1 border py-1 px-3 block w-full shadow-sm sm:text-sm rounded-md" /> -
+
+ + 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" + /> +
-
- -