From ff224d245b2dad5f71c478ff5aca6c5a29ba3c52 Mon Sep 17 00:00:00 2001 From: Tomasz Biel Date: Tue, 11 Jun 2024 10:08:24 +0200 Subject: [PATCH 01/15] feat(pdfPrinter button): :sparkles: pdfFetcher added without mutation --- src/config/urls.ts | 3 +- src/hooks/usePdf/index.tsx | 26 +++++ src/hooks/usePdf/monthlyHoursQueryOptions.ts | 21 ++++ src/pages/Calendar/index.tsx | 105 ++++++++++--------- src/pages/Users/components/DataTable.tsx | 6 ++ src/pages/Users/components/PdfFetcher.tsx | 42 ++++++++ src/types/HoursPdf.ts | 4 + 7 files changed, 155 insertions(+), 52 deletions(-) create mode 100644 src/hooks/usePdf/index.tsx create mode 100644 src/hooks/usePdf/monthlyHoursQueryOptions.ts create mode 100644 src/pages/Users/components/PdfFetcher.tsx create mode 100644 src/types/HoursPdf.ts diff --git a/src/config/urls.ts b/src/config/urls.ts index b7b7151..bd6c77b 100644 --- a/src/config/urls.ts +++ b/src/config/urls.ts @@ -14,5 +14,6 @@ export const URLS = { GET_MONTHLY_HOURS: (date: string) => `/users/monthlyTasks/${date}`, ADD_HOURS: () => '/hours/add', EDIT_HOURS: (id: string) => `/hours/${id}`, - DELETE_HOURS: (id: string) => `/hours/${id}` + DELETE_HOURS: (id: string) => `/hours/${id}`, + GET_MONTHLY_HOURS_PDF: (month: string) => `/pdfhours/${month}` }; diff --git a/src/hooks/usePdf/index.tsx b/src/hooks/usePdf/index.tsx new file mode 100644 index 0000000..7901502 --- /dev/null +++ b/src/hooks/usePdf/index.tsx @@ -0,0 +1,26 @@ +import { useQuery, useQueryClient } from '@tanstack/react-query'; + +import { monthlyHoursQueryOptions } from './monthlyHoursQueryOptions'; + +const usePdf = (month: string) => { + const queryClient = useQueryClient(); + + const { + data: monthlyHoursPdf, + refetch: monthlyHoursPdfRefetch, + isLoading: monthlyHoursPdfLoading, + isError: monthlyHoursPdfError + } = useQuery({ + ...monthlyHoursQueryOptions(month), + enabled: false // Ensure the query does not run automatically + }); + + return { + monthlyHoursPdf, + monthlyHoursPdfRefetch, + monthlyHoursPdfLoading, + monthlyHoursPdfError + }; +}; + +export default usePdf; diff --git a/src/hooks/usePdf/monthlyHoursQueryOptions.ts b/src/hooks/usePdf/monthlyHoursQueryOptions.ts new file mode 100644 index 0000000..3ebef89 --- /dev/null +++ b/src/hooks/usePdf/monthlyHoursQueryOptions.ts @@ -0,0 +1,21 @@ +import { URLS } from '@/config/urls'; +import { Axios } from '@/utils/Axios'; +import { queryOptions } from '@tanstack/react-query'; + +export const monthlyHoursQueryOptions = (month: string) => + queryOptions({ + queryKey: ['monthlyHoursPdf', month], + queryFn: async () => { + try { + Axios.get( + URLS.GET_MONTHLY_HOURS_PDF(month), + { responseType: 'blob' } // !!! + ).then(response => { + window.open(URL.createObjectURL(response.data)); + }); + } catch (err) { + console.error(err); + throw new Error('Error fetching monthly hours PDF'); + } + } + }); diff --git a/src/pages/Calendar/index.tsx b/src/pages/Calendar/index.tsx index dd4e5d6..1f64c8e 100644 --- a/src/pages/Calendar/index.tsx +++ b/src/pages/Calendar/index.tsx @@ -6,6 +6,7 @@ import FullCalendar from '@fullcalendar/react'; import timeGridPlugin from '@fullcalendar/timegrid'; import { useState } from 'react'; +import PdfFetcher from '../Users/components/PdfFetcher'; import HoursForm from './HoursForm'; export function Calendar() { @@ -32,58 +33,60 @@ export function Calendar() { return ( <> -
- ({ - title: hour.tasks, - start: hour.startTime, - end: hour.endTime, - url: hour.hoursId.toString(), - display: 'block', - borderColor: 'transparent' - })) - : [] - } - eventBackgroundColor="rgba(39, 140, 255, 0.95)" - eventContent={arg => ( -
- {arg.timeText} -
{arg.event.title}
-
- )} - /> +
+
+ ({ + title: hour.tasks, + start: hour.startTime, + end: hour.endTime, + url: hour.hoursId.toString(), + display: 'block', + borderColor: 'transparent' + })) + : [] + } + eventBackgroundColor="rgba(39, 140, 255, 0.95)" + eventContent={arg => ( +
+ {arg.timeText} +
{arg.event.title}
+
+ )} + /> +
+
- { columns: ColumnDef[]; data: TData[]; @@ -104,6 +106,7 @@ export function DataTable({ Dostosuj kolumny + {table .getAllColumns() @@ -119,6 +122,9 @@ export function DataTable({ ))} +
+ +
diff --git a/src/pages/Users/components/PdfFetcher.tsx b/src/pages/Users/components/PdfFetcher.tsx new file mode 100644 index 0000000..721ba63 --- /dev/null +++ b/src/pages/Users/components/PdfFetcher.tsx @@ -0,0 +1,42 @@ +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import usePdf from '@/hooks/usePdf'; +import React, { useState } from 'react'; + +const PdfFetcher = () => { + const [month, setMonth] = useState('2024-06'); + + const { + monthlyHoursPdf, + monthlyHoursPdfRefetch, + monthlyHoursPdfLoading, + monthlyHoursPdfError + } = usePdf(month); + + const handleFetchPdf = () => { + if (month) { + monthlyHoursPdfRefetch(); + } else { + alert('Please enter a month.'); + } + }; + + return ( +
+
+ setMonth(e.target.value)} + placeholder="Enter Month (YYYY-MM)" + className="mb-2" + /> +
+ +
+ ); +}; + +export default PdfFetcher; diff --git a/src/types/HoursPdf.ts b/src/types/HoursPdf.ts new file mode 100644 index 0000000..9b107ed --- /dev/null +++ b/src/types/HoursPdf.ts @@ -0,0 +1,4 @@ +export interface HoursPdf { + month: string; + userId?: string; +} From 73bbd72e3f49ecfd76efa8d278f71a35c9799df3 Mon Sep 17 00:00:00 2001 From: Tomasz Biel Date: Tue, 11 Jun 2024 11:51:51 +0200 Subject: [PATCH 02/15] feat(pdfPrinter button): :art: Using current month on print button input removed --- src/hooks/usePdf/index.tsx | 37 +++++++++++------------ src/pages/Calendar/index.tsx | 25 +++++++++++++-- src/pages/Users/components/PdfFetcher.tsx | 36 ++++++---------------- 3 files changed, 51 insertions(+), 47 deletions(-) diff --git a/src/hooks/usePdf/index.tsx b/src/hooks/usePdf/index.tsx index 7901502..f9cbce0 100644 --- a/src/hooks/usePdf/index.tsx +++ b/src/hooks/usePdf/index.tsx @@ -1,26 +1,25 @@ -import { useQuery, useQueryClient } from '@tanstack/react-query'; - -import { monthlyHoursQueryOptions } from './monthlyHoursQueryOptions'; +import { URLS } from '@/config/urls'; +import { HoursPdf } from '@/types/HoursPdf'; +import { Axios } from '@/utils/Axios'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; const usePdf = (month: string) => { - const queryClient = useQueryClient(); - - const { - data: monthlyHoursPdf, - refetch: monthlyHoursPdfRefetch, - isLoading: monthlyHoursPdfLoading, - isError: monthlyHoursPdfError - } = useQuery({ - ...monthlyHoursQueryOptions(month), - enabled: false // Ensure the query does not run automatically + const pdfMutation = useMutation({ + mutationFn: (month: string): Promise => + Axios.get(URLS.GET_MONTHLY_HOURS_PDF(month), { + responseType: 'blob' + }).then(res => { + const url = window.URL.createObjectURL(new Blob([res.data])); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', `hours-${month}.pdf`); + document.body.appendChild(link); + link.click(); + link.remove(); + }) }); - return { - monthlyHoursPdf, - monthlyHoursPdfRefetch, - monthlyHoursPdfLoading, - monthlyHoursPdfError + pdfMutation }; }; - export default usePdf; diff --git a/src/pages/Calendar/index.tsx b/src/pages/Calendar/index.tsx index 1f64c8e..8722071 100644 --- a/src/pages/Calendar/index.tsx +++ b/src/pages/Calendar/index.tsx @@ -4,7 +4,7 @@ import dayGridPlugin from '@fullcalendar/daygrid'; import interactionPlugin from '@fullcalendar/interaction'; import FullCalendar from '@fullcalendar/react'; import timeGridPlugin from '@fullcalendar/timegrid'; -import { useState } from 'react'; +import { useRef, useState } from 'react'; import PdfFetcher from '../Users/components/PdfFetcher'; import HoursForm from './HoursForm'; @@ -15,6 +15,26 @@ export function Calendar() { const [event, setEvent] = useState(null); const { hours } = useHours(); + const calendarRef = useRef(null); + + const getCurrentMonth = () => { + if (!calendarRef.current) return '2024-06'; + const calendarApi = calendarRef.current.getApi(); + const date = calendarApi.getDate(); + + let month = date.getMonth() + 1; + let year = date.getFullYear(); + + if (month > 12) { + month = 1; + year += 1; + } + + const formattedMonth = month < 10 ? `0${month}` : month; + + return `${year}-${formattedMonth}`; + }; + const handleDateClick = (info: any) => { setSelectedDate(info.dateStr); setEvent(null); @@ -36,6 +56,7 @@ export function Calendar() {
- +
{ - const [month, setMonth] = useState('2024-06'); +type PdfFetcherProps = { + currentMonth: () => string; +}; - const { - monthlyHoursPdf, - monthlyHoursPdfRefetch, - monthlyHoursPdfLoading, - monthlyHoursPdfError - } = usePdf(month); +const PdfFetcher: React.FC = ({ currentMonth }) => { + const [month, setMonth] = useState(currentMonth() || '2024-06'); + const { pdfMutation } = usePdf(month); const handleFetchPdf = () => { - if (month) { - monthlyHoursPdfRefetch(); - } else { - alert('Please enter a month.'); - } + const month = currentMonth(); + pdfMutation.mutate(month); }; return (
-
- setMonth(e.target.value)} - placeholder="Enter Month (YYYY-MM)" - className="mb-2" - /> -
- +
); }; From 14ec2de711d05ca2ebba373ec2efaa04f0cf4225 Mon Sep 17 00:00:00 2001 From: Tomasz Biel Date: Tue, 11 Jun 2024 11:52:35 +0200 Subject: [PATCH 03/15] only in calendar --- src/pages/Users/components/DataTable.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pages/Users/components/DataTable.tsx b/src/pages/Users/components/DataTable.tsx index 74886a8..3c987a9 100644 --- a/src/pages/Users/components/DataTable.tsx +++ b/src/pages/Users/components/DataTable.tsx @@ -122,9 +122,6 @@ export function DataTable({ ))} -
- -
From 41a310755dcaf5f0e6ae6e2ce3ce583a2f7cb9b7 Mon Sep 17 00:00:00 2001 From: Tomasz Biel Date: Wed, 12 Jun 2024 12:17:56 +0200 Subject: [PATCH 04/15] feat(Calendar for Admin): :art: Admin now has access to userHours --- src/config/urls.ts | 1 + src/hooks/useUserHours/index.tsx | 21 +++++++++ .../useUserHours/useHoursQueryOptions.ts | 18 ++++++++ src/pages/Calendar/index.tsx | 36 ++++++++++------ src/pages/Me/index.tsx | 11 +++++ src/pages/Users/components/DataTable.tsx | 16 ++++++- src/pages/Users/components/UserOptions.tsx | 1 + src/pages/Users/components/selectUsers.tsx | 43 +++++++++++++++++++ src/pages/Users/index.tsx | 7 ++- 9 files changed, 139 insertions(+), 15 deletions(-) create mode 100644 src/hooks/useUserHours/index.tsx create mode 100644 src/hooks/useUserHours/useHoursQueryOptions.ts create mode 100644 src/pages/Users/components/selectUsers.tsx diff --git a/src/config/urls.ts b/src/config/urls.ts index bd6c77b..ac728e1 100644 --- a/src/config/urls.ts +++ b/src/config/urls.ts @@ -11,6 +11,7 @@ export const URLS = { ME: () => '/users/me', GET_HOURS: () => '/hours/getAllHoursForUser', + GET_HOURS_FOR_USER: () => `/hours/getAllHoursForUser`, GET_MONTHLY_HOURS: (date: string) => `/users/monthlyTasks/${date}`, ADD_HOURS: () => '/hours/add', EDIT_HOURS: (id: string) => `/hours/${id}`, diff --git a/src/hooks/useUserHours/index.tsx b/src/hooks/useUserHours/index.tsx new file mode 100644 index 0000000..76c3b3e --- /dev/null +++ b/src/hooks/useUserHours/index.tsx @@ -0,0 +1,21 @@ +import { useQuery, useSuspenseQuery } from '@tanstack/react-query'; + +import { useHoursQueryOptions } from './useHoursQueryOptions'; + +const useUserHours = (userId: string) => { + const { + data: userHours, + isLoading: userHoursLoading, + isError: userHoursError, + error + } = useSuspenseQuery(useHoursQueryOptions(userId)); + + return { + userHours, + userHoursLoading, + userHoursError, + error + }; +}; + +export default useUserHours; diff --git a/src/hooks/useUserHours/useHoursQueryOptions.ts b/src/hooks/useUserHours/useHoursQueryOptions.ts new file mode 100644 index 0000000..a97e346 --- /dev/null +++ b/src/hooks/useUserHours/useHoursQueryOptions.ts @@ -0,0 +1,18 @@ +import { URLS } from '@/config/urls'; +import { Hours } from '@/types/Hours'; +import { Axios } from '@/utils/Axios'; +import { queryOptions } from '@tanstack/react-query'; + +export const useHoursQueryOptions = (userId: string) => + queryOptions({ + queryKey: ['userHours'], + queryFn: async () => + Axios.get(URLS.GET_HOURS_FOR_USER(), { + params: { userId: userId } + }) + .then(res => res.data) + .catch(err => { + console.log(userId); + console.error(err); + }) + }); diff --git a/src/pages/Calendar/index.tsx b/src/pages/Calendar/index.tsx index 8722071..055c82d 100644 --- a/src/pages/Calendar/index.tsx +++ b/src/pages/Calendar/index.tsx @@ -1,4 +1,6 @@ import useHours from '@/hooks/useHours'; +import useMe from '@/hooks/useMe'; +import useUserHours from '@/hooks/useUserHours'; import { Hours } from '@/types/Hours'; import dayGridPlugin from '@fullcalendar/daygrid'; import interactionPlugin from '@fullcalendar/interaction'; @@ -7,13 +9,19 @@ import timeGridPlugin from '@fullcalendar/timegrid'; import { useRef, useState } from 'react'; import PdfFetcher from '../Users/components/PdfFetcher'; +import SelectUsers from '../Users/components/selectUsers'; import HoursForm from './HoursForm'; export function Calendar() { const [selectedDate, setSelectedDate] = useState(null); const [isDialogOpen, setDialogOpened] = useState(false); const [event, setEvent] = useState(null); - const { hours } = useHours(); + const { me } = useMe(); + // const { hours } = useHours(); + const { userHours } = useUserHours('074221c8-1545-4e4b-a241-60addeaa0764'); + + const isAdmin = me && me.role === 'ROLE_ADMIN'; + const data = isAdmin ? userHours : null; const calendarRef = useRef(null); @@ -45,7 +53,7 @@ export function Calendar() { info.jsEvent.preventDefault(); setEvent(null); const eventId = info.event.url; - const event = hours?.find(hour => hour.hoursId == eventId); + const event = data?.find(hour => hour.hoursId == eventId); if (!event) return; setDialogOpened(true); setEvent(event); @@ -81,8 +89,8 @@ export function Calendar() { hour12: false }} events={ - Array.isArray(hours) - ? hours.map(hour => ({ + Array.isArray(data) + ? data.map(hour => ({ title: hour.tasks, start: hour.startTime, end: hour.endTime, @@ -107,15 +115,19 @@ export function Calendar() { /> + - + + {me.userRole === 'ROLE_USER' && ( + + )} ); } diff --git a/src/pages/Me/index.tsx b/src/pages/Me/index.tsx index be4ec88..6244df5 100644 --- a/src/pages/Me/index.tsx +++ b/src/pages/Me/index.tsx @@ -1,8 +1,19 @@ +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; import useMe from '@/hooks/useMe'; +import useUsers from '@/hooks/useUsers'; import { Link } from '@tanstack/react-router'; +import SelectUsers from '../Users/components/selectUsers'; + const Me = () => { const { me } = useMe(); + return ( <> Welcome {me?.firstName} {me?.lastName}!
Your email is {me?.email}. diff --git a/src/pages/Users/components/DataTable.tsx b/src/pages/Users/components/DataTable.tsx index 3c987a9..f3b7d2f 100644 --- a/src/pages/Users/components/DataTable.tsx +++ b/src/pages/Users/components/DataTable.tsx @@ -32,6 +32,7 @@ import { import * as React from 'react'; import PdfFetcher from './PdfFetcher'; +import { UserForm } from './UserForm'; interface DataTableProps { columns: ColumnDef[]; @@ -40,6 +41,7 @@ interface DataTableProps { noResultsMessage?: string; searchColumnKey?: string; initialState?: Partial; + userRole: string; } export function DataTable({ @@ -48,7 +50,8 @@ export function DataTable({ filterPlaceholder = 'Wyszukaj...', noResultsMessage = 'Brak wyników.', searchColumnKey, - initialState + initialState, + userRole }: DataTableProps) { const [sorting, setSorting] = React.useState( initialState?.sorting || [] @@ -61,7 +64,7 @@ export function DataTable({ const [rowSelection, setRowSelection] = React.useState( initialState?.rowSelection || {} ); - + const [isDialogOpen, setDialogOpen] = React.useState(false); const table = useReactTable({ data, columns, @@ -122,6 +125,11 @@ export function DataTable({ ))} + {userRole === 'ROLE_ADMIN' && ( + + )}
@@ -184,6 +192,10 @@ export function DataTable({ disabled={!table.getCanNextPage()}> Następna + setDialogOpen(!isDialogOpen)} + /> ); diff --git a/src/pages/Users/components/UserOptions.tsx b/src/pages/Users/components/UserOptions.tsx index 12184fd..874afb8 100644 --- a/src/pages/Users/components/UserOptions.tsx +++ b/src/pages/Users/components/UserOptions.tsx @@ -57,6 +57,7 @@ const UserOptions = ({ user }: UserOptionsProps) => { {' '} Usuń użytkownika + Kalendarz użytkownika { + const { users, usersLoading, usersError } = useUsers(); + + return ( + + ); +}; + +export default SelectUsers; diff --git a/src/pages/Users/index.tsx b/src/pages/Users/index.tsx index aa0768d..be93ba2 100644 --- a/src/pages/Users/index.tsx +++ b/src/pages/Users/index.tsx @@ -1,3 +1,4 @@ +import useMe from '@/hooks/useMe'; import useUsers from '@/hooks/useUsers'; import { DataTable } from './components/DataTable'; @@ -5,11 +6,15 @@ import { columns } from './components/columnsUsers'; export default function Users() { const { users } = useUsers(); + const { me, meLoading, meError } = useMe(); if (!users) return

Brak użytkowników

; + if (meLoading) return

Loading...

; + if (meError) return

Error loading user data

; + return (
- +
); } From 1ddec840cb1800fae62963c933d0921889c4706e Mon Sep 17 00:00:00 2001 From: Tomasz Biel Date: Thu, 13 Jun 2024 09:34:37 +0200 Subject: [PATCH 05/15] feat(Calendar for Admin): :sparkles: choosing users works printing pdf for them is not --- src/hooks/useUserHours/useHoursQueryOptions.ts | 2 +- src/pages/Calendar/index.tsx | 12 ++++++++---- src/pages/Users/components/selectUsers.tsx | 18 +++++++++++++++--- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/hooks/useUserHours/useHoursQueryOptions.ts b/src/hooks/useUserHours/useHoursQueryOptions.ts index a97e346..dbaa4ed 100644 --- a/src/hooks/useUserHours/useHoursQueryOptions.ts +++ b/src/hooks/useUserHours/useHoursQueryOptions.ts @@ -5,7 +5,7 @@ import { queryOptions } from '@tanstack/react-query'; export const useHoursQueryOptions = (userId: string) => queryOptions({ - queryKey: ['userHours'], + queryKey: ['userHours', userId], queryFn: async () => Axios.get(URLS.GET_HOURS_FOR_USER(), { params: { userId: userId } diff --git a/src/pages/Calendar/index.tsx b/src/pages/Calendar/index.tsx index 055c82d..3ec1ede 100644 --- a/src/pages/Calendar/index.tsx +++ b/src/pages/Calendar/index.tsx @@ -1,4 +1,3 @@ -import useHours from '@/hooks/useHours'; import useMe from '@/hooks/useMe'; import useUserHours from '@/hooks/useUserHours'; import { Hours } from '@/types/Hours'; @@ -16,9 +15,11 @@ export function Calendar() { const [selectedDate, setSelectedDate] = useState(null); const [isDialogOpen, setDialogOpened] = useState(false); const [event, setEvent] = useState(null); + const [selectedUser, setSelectedUser] = useState(null); const { me } = useMe(); - // const { hours } = useHours(); - const { userHours } = useUserHours('074221c8-1545-4e4b-a241-60addeaa0764'); + const { userHours, userHoursLoading, userHoursError } = useUserHours( + selectedUser || '074221c8-1545-4e4b-a241-60addeaa0764' + ); const isAdmin = me && me.role === 'ROLE_ADMIN'; const data = isAdmin ? userHours : null; @@ -115,7 +116,10 @@ export function Calendar() { /> - + {me.userRole === 'ROLE_USER' && ( diff --git a/src/pages/Users/components/selectUsers.tsx b/src/pages/Users/components/selectUsers.tsx index 01d93e7..c366dd3 100644 --- a/src/pages/Users/components/selectUsers.tsx +++ b/src/pages/Users/components/selectUsers.tsx @@ -7,11 +7,23 @@ import { } from '@/components/ui/select'; import useUsers from '@/hooks/useUsers'; -const SelectUsers = () => { +interface SelectUsersProps { + selectedUser: string | null; + setSelectedUser: (userId: string | null) => void; +} + +const SelectUsers: React.FC = ({ + selectedUser, + setSelectedUser +}) => { const { users, usersLoading, usersError } = useUsers(); + const handleChange = (value: string) => { + setSelectedUser(value); + }; + return ( - @@ -27,7 +39,7 @@ const SelectUsers = () => { ) : users && users.length > 0 ? ( users.map(user => ( - {user.lastName} + {user.lastName} {user.id} )) ) : ( From 450c2fba8f8af968b8dcfd1ad5e0b52c8ee3dc71 Mon Sep 17 00:00:00 2001 From: Tomasz Biel Date: Thu, 13 Jun 2024 11:03:31 +0200 Subject: [PATCH 06/15] feat(Calendar for Admin): :art: choosing users works, printing their calendars according to month works --- src/hooks/usePdf/index.tsx | 9 +++++--- src/hooks/usePdf/monthlyHoursQueryOptions.ts | 16 ++++++++------ src/pages/Calendar/index.tsx | 23 +++++++++++++++----- src/pages/Users/components/PdfFetcher.tsx | 18 +++++++++------ 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/hooks/usePdf/index.tsx b/src/hooks/usePdf/index.tsx index f9cbce0..2e826a1 100644 --- a/src/hooks/usePdf/index.tsx +++ b/src/hooks/usePdf/index.tsx @@ -1,12 +1,13 @@ import { URLS } from '@/config/urls'; import { HoursPdf } from '@/types/HoursPdf'; import { Axios } from '@/utils/Axios'; -import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { useMutation } from '@tanstack/react-query'; -const usePdf = (month: string) => { +const usePdf = (month: string, userId: string | null) => { const pdfMutation = useMutation({ - mutationFn: (month: string): Promise => + mutationFn: (): Promise => Axios.get(URLS.GET_MONTHLY_HOURS_PDF(month), { + params: { userId: userId }, responseType: 'blob' }).then(res => { const url = window.URL.createObjectURL(new Blob([res.data])); @@ -18,8 +19,10 @@ const usePdf = (month: string) => { link.remove(); }) }); + return { pdfMutation }; }; + export default usePdf; diff --git a/src/hooks/usePdf/monthlyHoursQueryOptions.ts b/src/hooks/usePdf/monthlyHoursQueryOptions.ts index 3ebef89..2cfd5d0 100644 --- a/src/hooks/usePdf/monthlyHoursQueryOptions.ts +++ b/src/hooks/usePdf/monthlyHoursQueryOptions.ts @@ -2,17 +2,19 @@ import { URLS } from '@/config/urls'; import { Axios } from '@/utils/Axios'; import { queryOptions } from '@tanstack/react-query'; -export const monthlyHoursQueryOptions = (month: string) => +export const monthlyHoursQueryOptions = ( + month: string, + userId: string | null +) => queryOptions({ - queryKey: ['monthlyHoursPdf', month], + queryKey: ['monthlyHoursPdf', month, userId], queryFn: async () => { try { - Axios.get( - URLS.GET_MONTHLY_HOURS_PDF(month), - { responseType: 'blob' } // !!! - ).then(response => { - window.open(URL.createObjectURL(response.data)); + const response = await Axios.get(URLS.GET_MONTHLY_HOURS_PDF(month), { + params: { userId: userId }, + responseType: 'blob' }); + window.open(URL.createObjectURL(response.data)); } catch (err) { console.error(err); throw new Error('Error fetching monthly hours PDF'); diff --git a/src/pages/Calendar/index.tsx b/src/pages/Calendar/index.tsx index 3ec1ede..f1a2441 100644 --- a/src/pages/Calendar/index.tsx +++ b/src/pages/Calendar/index.tsx @@ -1,11 +1,12 @@ import useMe from '@/hooks/useMe'; +import usePdf from '@/hooks/usePdf'; import useUserHours from '@/hooks/useUserHours'; import { Hours } from '@/types/Hours'; import dayGridPlugin from '@fullcalendar/daygrid'; import interactionPlugin from '@fullcalendar/interaction'; import FullCalendar from '@fullcalendar/react'; import timeGridPlugin from '@fullcalendar/timegrid'; -import { useRef, useState } from 'react'; +import { useRef, useState, useEffect, useCallback } from 'react'; import PdfFetcher from '../Users/components/PdfFetcher'; import SelectUsers from '../Users/components/selectUsers'; @@ -16,8 +17,9 @@ export function Calendar() { const [isDialogOpen, setDialogOpened] = useState(false); const [event, setEvent] = useState(null); const [selectedUser, setSelectedUser] = useState(null); + const [currentMonth, setCurrentMonth] = useState('2024-06'); const { me } = useMe(); - const { userHours, userHoursLoading, userHoursError } = useUserHours( + const { userHours } = useUserHours( selectedUser || '074221c8-1545-4e4b-a241-60addeaa0764' ); @@ -26,7 +28,7 @@ export function Calendar() { const calendarRef = useRef(null); - const getCurrentMonth = () => { + const getCurrentMonth = useCallback(() => { if (!calendarRef.current) return '2024-06'; const calendarApi = calendarRef.current.getApi(); const date = calendarApi.getDate(); @@ -42,7 +44,13 @@ export function Calendar() { const formattedMonth = month < 10 ? `0${month}` : month; return `${year}-${formattedMonth}`; - }; + }, []); + + useEffect(() => { + setCurrentMonth(getCurrentMonth()); + }, [selectedUser, getCurrentMonth]); + + const { pdfMutation } = usePdf(currentMonth, selectedUser); const handleDateClick = (info: any) => { setSelectedDate(info.dateStr); @@ -60,6 +68,10 @@ export function Calendar() { setEvent(event); }; + const handleDatesSet = () => { + setCurrentMonth(getCurrentMonth()); + }; + return ( <>
@@ -113,9 +125,10 @@ export function Calendar() {
{arg.event.title}
)} + datesSet={handleDatesSet} // This will trigger the month update when the calendar view changes /> - + string; + currentMonth: string; + pdfMutation: any; // Adjust the type according to your actual mutation object }; -const PdfFetcher: React.FC = ({ currentMonth }) => { - const [month, setMonth] = useState(currentMonth() || '2024-06'); - const { pdfMutation } = usePdf(month); +const PdfFetcher: React.FC = ({ + currentMonth, + pdfMutation +}) => { + const [month, setMonth] = useState(currentMonth); + + useEffect(() => { + setMonth(currentMonth); + }, [currentMonth]); const handleFetchPdf = () => { - const month = currentMonth(); pdfMutation.mutate(month); }; From eaa0a4872e00e944ec2e776e66c60373d19ea308 Mon Sep 17 00:00:00 2001 From: Tomasz Biel Date: Thu, 13 Jun 2024 11:23:54 +0200 Subject: [PATCH 07/15] fix(Calendar for Admin): :bug: hours is working both for user and admin --- src/hooks/useHours/index.tsx | 3 ++- src/pages/Calendar/index.tsx | 17 ++++++++++------- src/pages/Users/components/PdfFetcher.tsx | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/hooks/useHours/index.tsx b/src/hooks/useHours/index.tsx index 01a15a2..9fb7f8b 100644 --- a/src/hooks/useHours/index.tsx +++ b/src/hooks/useHours/index.tsx @@ -3,6 +3,7 @@ import { Hours, HoursRequest } from '@/types/Hours'; import { Axios } from '@/utils/Axios'; import { useMutation, + useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query'; @@ -17,7 +18,7 @@ const useHours = (date?: string) => { refetch: hoursRefetch, isLoading: hoursLoading, isError: hoursError - } = useSuspenseQuery(hoursQueryOptions); + } = useQuery(hoursQueryOptions); const { mutateAsync: addHours, diff --git a/src/pages/Calendar/index.tsx b/src/pages/Calendar/index.tsx index f1a2441..0b62edd 100644 --- a/src/pages/Calendar/index.tsx +++ b/src/pages/Calendar/index.tsx @@ -1,3 +1,4 @@ +import useHours from '@/hooks/useHours'; import useMe from '@/hooks/useMe'; import usePdf from '@/hooks/usePdf'; import useUserHours from '@/hooks/useUserHours'; @@ -22,9 +23,10 @@ export function Calendar() { const { userHours } = useUserHours( selectedUser || '074221c8-1545-4e4b-a241-60addeaa0764' ); + const { hours } = useHours(); const isAdmin = me && me.role === 'ROLE_ADMIN'; - const data = isAdmin ? userHours : null; + const data = isAdmin ? userHours : hours; const calendarRef = useRef(null); @@ -129,12 +131,13 @@ export function Calendar() { /> - + {me.userRole === 'ROLE_ADMIN' && ( + + )} - {me.userRole === 'ROLE_USER' && ( - )} + )}{' '} ); } diff --git a/src/pages/Users/components/PdfFetcher.tsx b/src/pages/Users/components/PdfFetcher.tsx index eb1399a..e437d7b 100644 --- a/src/pages/Users/components/PdfFetcher.tsx +++ b/src/pages/Users/components/PdfFetcher.tsx @@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react'; type PdfFetcherProps = { currentMonth: string; - pdfMutation: any; // Adjust the type according to your actual mutation object + pdfMutation: any; }; const PdfFetcher: React.FC = ({ From 8925b279590af14e92e280f86d4933851e394918 Mon Sep 17 00:00:00 2001 From: Tomasz Biel Date: Thu, 13 Jun 2024 12:07:45 +0200 Subject: [PATCH 08/15] feat(Logout button and access to pages for specific roles): --- src/config/urls.ts | 1 + src/pages/Calendar/index.tsx | 4 ++-- src/pages/Dashboard/index.tsx | 8 ++++++-- src/pages/Dashboard/logout.tsx | 21 +++++++++++++++++++++ src/pages/Me/index.tsx | 4 ++-- src/pages/Users/components/DataTable.tsx | 11 ++++++----- src/pages/Users/components/UserOptions.tsx | 1 - src/pages/Users/indexcopy.tsx | 10 ++++++++-- 8 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 src/pages/Dashboard/logout.tsx diff --git a/src/config/urls.ts b/src/config/urls.ts index ac728e1..c8dd55b 100644 --- a/src/config/urls.ts +++ b/src/config/urls.ts @@ -1,6 +1,7 @@ export const URLS = { LOGIN: () => '/auth/signin', REFRESH: () => '/auth/refresh', + LOGOUT: () => '/auth/logout', GET_COMPANIES: () => '/company/all', diff --git a/src/pages/Calendar/index.tsx b/src/pages/Calendar/index.tsx index 0b62edd..9d4631d 100644 --- a/src/pages/Calendar/index.tsx +++ b/src/pages/Calendar/index.tsx @@ -131,14 +131,14 @@ export function Calendar() { /> - {me.userRole === 'ROLE_ADMIN' && ( + {me.role === 'ROLE_ADMIN' && ( )} - {me.userRole === 'ROLE_USER' && ( + {me.role === 'ROLE_USER' && (