From f201207926c5e72bdc9f652fc657fef76f142244 Mon Sep 17 00:00:00 2001 From: Elemar Rodrigues Severo Junior Date: Fri, 3 Jan 2025 09:58:30 -0300 Subject: [PATCH 1/9] Enhance OneYearAllocation component with formatter for hour display - Added a formatter function to display allocation hours with one decimal precision (e.g., "5.0h") for consulting, hands-on, squad, and internal totals. - This change improves the clarity and readability of the displayed allocation metrics, ensuring users can easily interpret the data. --- frontend/src/app/components/OneYearAllocation.tsx | 4 ++++ frontend/src/content/changelog/2025-01-03.mdx | 9 +++++++++ 2 files changed, 13 insertions(+) create mode 100644 frontend/src/content/changelog/2025-01-03.mdx diff --git a/frontend/src/app/components/OneYearAllocation.tsx b/frontend/src/app/components/OneYearAllocation.tsx index 1d7c8911..28e2a80b 100644 --- a/frontend/src/app/components/OneYearAllocation.tsx +++ b/frontend/src/app/components/OneYearAllocation.tsx @@ -534,6 +534,7 @@ const OneYearAllocation: React.FC = ({ value={totals.consulting.toString()} color={getKindColor("consulting")} total={totalHours} + formatter={(value: number) => `${value.toFixed(1)}h`} />
= ({ value={totals.handsOn.toString()} color={getKindColor("handsOn")} total={totalHours} + formatter={(value: number) => `${value.toFixed(1)}h`} />
= ({ value={totals.squad.toString()} color={getKindColor("squad")} total={totalHours} + formatter={(value: number) => `${value.toFixed(1)}h`} />
= ({ value={totals.internal.toString()} color={getKindColor("internal")} total={totalHours} + formatter={(value: number) => `${value.toFixed(1)}h`} />
diff --git a/frontend/src/content/changelog/2025-01-03.mdx b/frontend/src/content/changelog/2025-01-03.mdx new file mode 100644 index 00000000..95377392 --- /dev/null +++ b/frontend/src/content/changelog/2025-01-03.mdx @@ -0,0 +1,9 @@ +--- +title: Details, details +date: 2025-01-03 +--- + +### New Features + + +### Improvements From a4335e705d07b04e18679c3e102a0f05dc7ec31a Mon Sep 17 00:00:00 2001 From: Elemar Rodrigues Severo Junior Date: Fri, 3 Jan 2025 10:07:25 -0300 Subject: [PATCH 2/9] Enhance OneYearAllocation component to display percentage of occurrences in histogram - Added calculation for total occurrences in the histogram data to display the percentage of each bin's count. - Introduced a new visual element to show the percentage at the bottom right of each histogram bin, improving data interpretation for users. These changes enhance the clarity of the histogram representation, allowing users to better understand the distribution of occurrences. --- frontend/src/app/components/OneYearAllocation.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/components/OneYearAllocation.tsx b/frontend/src/app/components/OneYearAllocation.tsx index 28e2a80b..1700e08a 100644 --- a/frontend/src/app/components/OneYearAllocation.tsx +++ b/frontend/src/app/components/OneYearAllocation.tsx @@ -581,13 +581,15 @@ const OneYearAllocation: React.FC = ({ const renderHistogram = () => { if (!data || histogramData.length === 0) return null; + const totalOccurrences = histogramData.reduce((sum, bin) => sum + bin.count, 0); + return (
{histogramData.map((bin, index) => (
= ({ occurrences
+
+ {((bin.count / totalOccurrences) * 100).toFixed(1)}% +
))} From 1649a830b239eb93d1f634f3673c1184caaf67e5 Mon Sep 17 00:00:00 2001 From: Elemar Rodrigues Severo Junior Date: Fri, 3 Jan 2025 10:21:44 -0300 Subject: [PATCH 3/9] Implement appointment query and UI in OneYearAllocation component - Added a new query to fetch daily appointments based on the selected date, enhancing the component's functionality. - Introduced a Sheet component to display appointment details, including client and worker information, comments, and hours worked. - Implemented date selection handling to allow users to view appointments for specific dates, improving user interactivity. - Enhanced loading and empty state handling for the appointments display, ensuring a better user experience. These changes provide users with a comprehensive view of daily appointments, enriching the allocation insights offered by the OneYearAllocation component. --- .../src/app/components/OneYearAllocation.tsx | 112 +++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/components/OneYearAllocation.tsx b/frontend/src/app/components/OneYearAllocation.tsx index 1700e08a..4890bb8a 100644 --- a/frontend/src/app/components/OneYearAllocation.tsx +++ b/frontend/src/app/components/OneYearAllocation.tsx @@ -9,6 +9,12 @@ import { } from "@/components/ui/tooltip"; import SectionHeader from "@/components/SectionHeader"; import { Stat } from "@/app/components/analytics/stat"; +import { + Sheet, + SheetContent, + SheetHeader, + SheetTitle, +} from "@/components/ui/sheet"; interface ContributionProps { month?: number; @@ -83,6 +89,21 @@ const ALLOCATION_QUERY = gql` } `; +const DAILY_APPOINTMENTS_QUERY = gql` + query DailyAppointments($slug: String!, $filters: [FilterInput!]) { + timesheet(slug: $slug, filters: $filters) { + appointments { + clientName + clientSlug + workerName + workerSlug + comment + timeInHs + } + } + } +`; + const OneYearAllocation: React.FC = ({ month, year, @@ -166,6 +187,30 @@ const OneYearAllocation: React.FC = ({ }, }); + const [selectedDate, setSelectedDate] = useState(null); + + // Add query for appointments + const { data: appointmentsData, loading: appointmentsLoading } = useQuery( + DAILY_APPOINTMENTS_QUERY, + { + variables: { + slug: selectedDate + ? `timesheet-${ + // Format date from YYYY-MM-DD to DD-MM-YYYY-DD-MM-YYYY + selectedDate.split('-').reverse().join('-')}-${ + selectedDate.split('-').reverse().join('-') + }` + : "", + filters: filters.length > 0 ? filters : null, + }, + skip: !selectedDate, + } + ); + + const handleDateClick = (date: string) => { + setSelectedDate(date); + }; + if (loading) return
Loading...
; if (error) return
Error: {(error as ApolloError).message}
; @@ -620,6 +665,69 @@ const OneYearAllocation: React.FC = ({ ); }; + const renderAppointmentsSheet = () => { + if (!selectedDate) return null; + + const formattedDate = new Date(selectedDate).toLocaleDateString("en-US", { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric' + }); + + return ( + setSelectedDate(null)}> + + + {formattedDate} + +
+ {appointmentsLoading ? ( +
+ Loading... +
+ ) : appointmentsData?.timesheet?.appointments?.length ? ( +
+ {appointmentsData.timesheet.appointments.map((appointment: any, index: number) => ( +
+
+ + + {appointment.timeInHs.toFixed(1)}h + +
+ {appointment.comment && ( +

+ {appointment.comment} +

+ )} +
+ ))} +
+ ) : ( +
+ No appointments found +
+ )} +
+
+
+ ); + }; + const renderAllocationGrid = () => { if (!data) return null; @@ -654,7 +762,7 @@ const OneYearAllocation: React.FC = ({
{cell.label && (
0 @@ -688,6 +796,7 @@ const OneYearAllocation: React.FC = ({ ? 1 : 0.1, }} + onClick={() => cell.fullDate && handleDateClick(cell.fullDate)} /> )}
@@ -734,6 +843,7 @@ const OneYearAllocation: React.FC = ({ {renderKinds()} {renderHistogram()} {renderAllocationGrid()} + {renderAppointmentsSheet()}
); From 98400b655839feee0f0d8a4a96d5da3b1541e5b2 Mon Sep 17 00:00:00 2001 From: Elemar Rodrigues Severo Junior Date: Fri, 3 Jan 2025 10:33:33 -0300 Subject: [PATCH 4/9] Refactor OneYearAllocation component to enhance appointment display and interactivity - Improved the layout of the appointment display by introducing a responsive table format, allowing for better organization of worker and client information. - Added conditional rendering for worker and client columns based on the presence of names, enhancing the component's flexibility. - Updated loading and empty state messages for better user feedback, ensuring clarity during data fetching and when no appointments are found. - Enhanced the total hours calculation in the footer of the appointment table, providing users with a quick summary of hours worked. These changes improve the usability and visual presentation of the OneYearAllocation component, making it easier for users to navigate and interpret appointment data. --- .../src/app/components/OneYearAllocation.tsx | 128 +++++++++++++----- 1 file changed, 96 insertions(+), 32 deletions(-) diff --git a/frontend/src/app/components/OneYearAllocation.tsx b/frontend/src/app/components/OneYearAllocation.tsx index 4890bb8a..2f295765 100644 --- a/frontend/src/app/components/OneYearAllocation.tsx +++ b/frontend/src/app/components/OneYearAllocation.tsx @@ -675,51 +675,115 @@ const OneYearAllocation: React.FC = ({ day: 'numeric' }); + // Determine which columns to show based on filters + const showWorkerColumn = !workerName; + const showClientColumn = !clientName; + return ( setSelectedDate(null)}> - + - {formattedDate} + {formattedDate} + {(clientName || workerName) && ( +
+ {clientName && ( + + {clientName} + + )} + {clientName && workerName && " • "} + {workerName && ( + + {workerName} + + )} +
+ )}
-
+
{appointmentsLoading ? (
- Loading... + Loading...
) : appointmentsData?.timesheet?.appointments?.length ? ( -
- {appointmentsData.timesheet.appointments.map((appointment: any, index: number) => ( -
- From 1960e31728e7654ef8457f64d9c34263373e634f Mon Sep 17 00:00:00 2001 From: Elemar Rodrigues Severo Junior Date: Fri, 3 Jan 2025 10:45:42 -0300 Subject: [PATCH 5/9] Fix timezone issues in OneYearAllocation component by adjusting date handling. Updated tooltip and appointment display to add one day to selected dates, ensuring accurate representation across the UI. Enhanced changelog with new features and improvements for better clarity on recent updates. --- frontend/src/app/components/OneYearAllocation.tsx | 8 +++++++- frontend/src/content/changelog/2025-01-03.mdx | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/OneYearAllocation.tsx b/frontend/src/app/components/OneYearAllocation.tsx index 2f295765..00a31326 100644 --- a/frontend/src/app/components/OneYearAllocation.tsx +++ b/frontend/src/app/components/OneYearAllocation.tsx @@ -355,10 +355,13 @@ const OneYearAllocation: React.FC = ({ const formatTooltip = (date: string, label: string, hours: number) => { if (!label) return ""; const dateObj = new Date(date); + dateObj.setDate(dateObj.getDate() + 1); // Add one day to fix timezone issue + const formattedDate = dateObj.toLocaleString("en", { month: "short", day: "2-digit", }); + return `${formattedDate} - ${ hours > 0 ? `${hours.toFixed(1)}h` : "No hours" }`; @@ -668,7 +671,10 @@ const OneYearAllocation: React.FC = ({ const renderAppointmentsSheet = () => { if (!selectedDate) return null; - const formattedDate = new Date(selectedDate).toLocaleDateString("en-US", { + const dateObj = new Date(selectedDate); + dateObj.setDate(dateObj.getDate() + 1); // Add one day to fix timezone issue + + const formattedDate = dateObj.toLocaleDateString("en-US", { weekday: 'long', year: 'numeric', month: 'long', diff --git a/frontend/src/content/changelog/2025-01-03.mdx b/frontend/src/content/changelog/2025-01-03.mdx index 95377392..9764c085 100644 --- a/frontend/src/content/changelog/2025-01-03.mdx +++ b/frontend/src/content/changelog/2025-01-03.mdx @@ -4,6 +4,8 @@ date: 2025-01-03 --- ### New Features - +- Added "details view" to "One Year Allocation" component. ### Improvements +- Added "h" suffix to hour values in the "kind of work" cards to improve readability in One Year Allocation visualization +- Added percentages to the "history" cards in the "One Year Allocation" component \ No newline at end of file From c050563a7e53adc2db6053c3e4c3a9b43a85502c Mon Sep 17 00:00:00 2001 From: Elemar Rodrigues Severo Junior Date: Fri, 3 Jan 2025 10:59:31 -0300 Subject: [PATCH 6/9] Enhance ActiveDeals model and update changelog - Updated ActiveDealsRepository to include client or prospect name in the active deal creation process, improving data accuracy. - Enhanced changelog with new features and bug fixes, including the addition of percentages to history cards and a fix for timezone issues in the One Year Allocation component. Added support for displaying client/prospect names in active deals by integrating data from Pipedrive. --- backend/models/src/omni_models/domain/active_deals.py | 2 +- frontend/src/content/changelog/2025-01-03.mdx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/models/src/omni_models/domain/active_deals.py b/backend/models/src/omni_models/domain/active_deals.py index 8ca86dd4..dadebe09 100644 --- a/backend/models/src/omni_models/domain/active_deals.py +++ b/backend/models/src/omni_models/domain/active_deals.py @@ -43,7 +43,7 @@ def get_by_everhour_id(self, everhour_id: str) -> Optional[ActiveDeal]: return next((deal for deal in self.__data if deal.everhour_id == everhour_id), None) def __create_active_deal(self, deal) -> ActiveDeal: - return ActiveDeal(**deal.model_dump()) + return ActiveDeal(**deal.model_dump(), client_or_prospect_name=deal.client_name) def __build_data(self): self.__active_deals = [ diff --git a/frontend/src/content/changelog/2025-01-03.mdx b/frontend/src/content/changelog/2025-01-03.mdx index 9764c085..18eb9f8a 100644 --- a/frontend/src/content/changelog/2025-01-03.mdx +++ b/frontend/src/content/changelog/2025-01-03.mdx @@ -8,4 +8,8 @@ date: 2025-01-03 ### Improvements - Added "h" suffix to hour values in the "kind of work" cards to improve readability in One Year Allocation visualization -- Added percentages to the "history" cards in the "One Year Allocation" component \ No newline at end of file +- Added percentages to the "history" cards in the "One Year Allocation" component. + +### Bug Fixes +- Fixed timezone issue in the "One Year Allocation" component. +- Added support for client/prospect name display in active deals by integrating data from Pipedrive into the deals model \ No newline at end of file From 388ffdaad07508b044b54efd0392c218d072964f Mon Sep 17 00:00:00 2001 From: Elemar Rodrigues Severo Junior Date: Fri, 3 Jan 2025 11:06:12 -0300 Subject: [PATCH 7/9] Refactor ActiveDeals and Cases repositories for improved deal matching - Updated ActiveDealsRepository to enhance the deal retrieval logic by allowing for partial matches on everhour_id, improving flexibility in deal identification. - Modified CasesRepository to prevent duplicate deals from being appended to cases, ensuring data integrity. - Adjusted the frontend deal matching logic to support the updated retrieval method, allowing for better integration of deals with tracking projects. These changes enhance the accuracy and efficiency of deal management across the application. --- backend/models/src/omni_models/domain/active_deals.py | 2 +- backend/models/src/omni_models/domain/cases.py | 2 +- frontend/src/app/about-us/cases/tracking-projects/page.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/models/src/omni_models/domain/active_deals.py b/backend/models/src/omni_models/domain/active_deals.py index dadebe09..bb2fa159 100644 --- a/backend/models/src/omni_models/domain/active_deals.py +++ b/backend/models/src/omni_models/domain/active_deals.py @@ -40,7 +40,7 @@ def get_by_id(self, id: int) -> Optional[ActiveDeal]: def get_by_everhour_id(self, everhour_id: str) -> Optional[ActiveDeal]: if self.__data is None: self.__build_data() - return next((deal for deal in self.__data if deal.everhour_id == everhour_id), None) + return next((deal for deal in self.__data if deal.everhour_id and everhour_id in deal.everhour_id.split(";")), None) def __create_active_deal(self, deal) -> ActiveDeal: return ActiveDeal(**deal.model_dump(), client_or_prospect_name=deal.client_name) diff --git a/backend/models/src/omni_models/domain/cases.py b/backend/models/src/omni_models/domain/cases.py index c9721725..6cbeefa9 100644 --- a/backend/models/src/omni_models/domain/cases.py +++ b/backend/models/src/omni_models/domain/cases.py @@ -293,7 +293,7 @@ def __build_data(self) -> Dict[str, Case]: for case in cases_dict.values(): for tracker_project in case.tracker_info: deal = self.deals_repository.get_by_everhour_id(tracker_project.id) - if deal: + if deal and (deal not in case.deals): case.deals.append(deal) self.__data = cases_dict diff --git a/frontend/src/app/about-us/cases/tracking-projects/page.tsx b/frontend/src/app/about-us/cases/tracking-projects/page.tsx index 21a838e0..29642c2f 100644 --- a/frontend/src/app/about-us/cases/tracking-projects/page.tsx +++ b/frontend/src/app/about-us/cases/tracking-projects/page.tsx @@ -88,7 +88,7 @@ export default function TrackingProjectsPage() { {cases.map((caseItem: any) => caseItem.tracker?.map((tracker: any) => { const matchingDeal = caseItem.deals?.find( - (deal: any) => deal.everhourId === tracker.id + (deal: any) => deal.everhourId && deal.everhourId.split(";").includes(tracker.id) ); const salesCycle = matchingDeal?.addTime && matchingDeal?.wonTime From 2c2f2508c55cb194fa2051a00259396a1226ed9b Mon Sep 17 00:00:00 2001 From: Elemar Rodrigues Severo Junior Date: Fri, 3 Jan 2025 11:24:52 -0300 Subject: [PATCH 8/9] Refactor OneYearAllocation component for improved code consistency and readability - Standardized string quotes from single to double for consistency across the component. - Enhanced state initialization for selectedKind to use double quotes. - Improved the rendering logic and formatting for better clarity in the appointment display and histogram. - Added a total hours row in the allocation grid for better summary visibility. These changes enhance the maintainability and visual coherence of the OneYearAllocation component, ensuring a more robust user experience. --- .../src/app/components/OneYearAllocation.tsx | 194 +++++++++++------- 1 file changed, 124 insertions(+), 70 deletions(-) diff --git a/frontend/src/app/components/OneYearAllocation.tsx b/frontend/src/app/components/OneYearAllocation.tsx index 00a31326..d78de809 100644 --- a/frontend/src/app/components/OneYearAllocation.tsx +++ b/frontend/src/app/components/OneYearAllocation.tsx @@ -112,17 +112,17 @@ const OneYearAllocation: React.FC = ({ sponsor, caseTitle, }) => { - type KindType = 'consulting' | 'handsOn' | 'squad' | 'internal'; + type KindType = "consulting" | "handsOn" | "squad" | "internal"; const getKindColor = (kind: KindType) => { switch (kind) { - case 'consulting': + case "consulting": return "#F59E0B"; - case 'handsOn': + case "handsOn": return "#8B5CF6"; - case 'squad': + case "squad": return "#3B82F6"; - case 'internal': + case "internal": return "#10B981"; default: return "#6B7280"; @@ -130,7 +130,7 @@ const OneYearAllocation: React.FC = ({ }; // Initialize with empty string to ensure we select first non-zero value - const [selectedKind, setSelectedKind] = useState(''); + const [selectedKind, setSelectedKind] = useState(""); const [selectedBinIndex, setSelectedBinIndex] = useState(null); const currentDate = new Date(); const specifiedMonth = month || currentDate.getMonth() + 1; @@ -194,12 +194,11 @@ const OneYearAllocation: React.FC = ({ DAILY_APPOINTMENTS_QUERY, { variables: { - slug: selectedDate + slug: selectedDate ? `timesheet-${ // Format date from YYYY-MM-DD to DD-MM-YYYY-DD-MM-YYYY - selectedDate.split('-').reverse().join('-')}-${ - selectedDate.split('-').reverse().join('-') - }` + selectedDate.split("-").reverse().join("-") + }-${selectedDate.split("-").reverse().join("-")}` : "", filters: filters.length > 0 ? filters : null, }, @@ -234,14 +233,14 @@ const OneYearAllocation: React.FC = ({ } // Set initial selected kind to first non-zero value if not already set - if (selectedKind === '') { + if (selectedKind === "") { const firstNonZeroKind = Object.entries(totals).find( ([_, value]) => value > 0 )?.[0] as KindType; if (firstNonZeroKind) { setSelectedKind(firstNonZeroKind); } else { - setSelectedKind('consulting'); + setSelectedKind("consulting"); } } @@ -555,17 +554,20 @@ const OneYearAllocation: React.FC = ({ const renderKinds = () => { if (!data) return null; - const totalHours = totals.consulting + totals.handsOn + totals.squad + totals.internal; + const totalHours = + totals.consulting + totals.handsOn + totals.squad + totals.internal; const getStatClassName = (kind: KindType) => { return `transform cursor-pointer transition-all duration-300 ${ - selectedKind === kind ? 'ring-2 ring-black shadow-lg scale-105' : 'hover:scale-102' - } ${totals[kind] === 0 ? 'opacity-50 cursor-not-allowed' : ''}`; + selectedKind === kind + ? "ring-2 ring-black shadow-lg scale-105" + : "hover:scale-102" + } ${totals[kind] === 0 ? "opacity-50 cursor-not-allowed" : ""}`; }; const handleKindClick = (kind: KindType) => { if (totals[kind] > 0) { - setSelectedKind(selectedKind === kind ? '' : kind); + setSelectedKind(selectedKind === kind ? "" : kind); setSelectedBinIndex(null); } }; @@ -629,7 +631,10 @@ const OneYearAllocation: React.FC = ({ const renderHistogram = () => { if (!data || histogramData.length === 0) return null; - const totalOccurrences = histogramData.reduce((sum, bin) => sum + bin.count, 0); + const totalOccurrences = histogramData.reduce( + (sum, bin) => sum + bin.count, + 0 + ); return (
@@ -638,7 +643,11 @@ const OneYearAllocation: React.FC = ({
= ({ const renderAppointmentsSheet = () => { if (!selectedDate) return null; - const dateObj = new Date(selectedDate); + const dateObj = new Date(selectedDate); dateObj.setDate(dateObj.getDate() + 1); // Add one day to fix timezone issue const formattedDate = dateObj.toLocaleDateString("en-US", { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric' + weekday: "long", + year: "numeric", + month: "long", + day: "numeric", }); // Determine which columns to show based on filters @@ -693,8 +702,10 @@ const OneYearAllocation: React.FC = ({ {(clientName || workerName) && (
{clientName && ( - {clientName} @@ -702,8 +713,10 @@ const OneYearAllocation: React.FC = ({ )} {clientName && workerName && " • "} {workerName && ( - {workerName} @@ -724,62 +737,76 @@ const OneYearAllocation: React.FC = ({ {showWorkerColumn && ( - Worker + + Worker + )} {showClientColumn && ( - Client + + Client + )} - Hours - Comment + + Hours + + + Comment + - {appointmentsData.timesheet.appointments.map((appointment: any, index: number) => ( - - {showWorkerColumn && ( - - - {appointment.workerName} - + {appointmentsData.timesheet.appointments.map( + (appointment: any, index: number) => ( + + {showWorkerColumn && ( + + + {appointment.workerName} + + + )} + {showClientColumn && ( + + + {appointment.clientName} + + + )} + + {appointment.timeInHs.toFixed(1)}h - )} - {showClientColumn && ( - - - {appointment.clientName} - + + {appointment.comment || "-"} - )} - - {appointment.timeInHs.toFixed(1)}h - - - {appointment.comment || "-"} - - - ))} + + ) + )} - Total: {appointmentsData.timesheet.appointments - .reduce((sum: number, app: any) => sum + app.timeInHs, 0) - .toFixed(1)}h + .reduce( + (sum: number, app: any) => sum + app.timeInHs, + 0 + ) + .toFixed(1)} + h @@ -789,7 +816,9 @@ const OneYearAllocation: React.FC = ({
) : (
- No appointments found + + No appointments found +
)}
@@ -801,6 +830,16 @@ const OneYearAllocation: React.FC = ({ const renderAllocationGrid = () => { if (!data) return null; + const number_of_days = dayRows[0].cells.length; + var totalHoursRow = new Array(number_of_days).fill(0); + for (let i = 0; i < number_of_days; i++) { + for (let j = 0; j < dayRows.length; j++) { + if (dayRows[j].cells.length > i) { + totalHoursRow[i] += dayRows[j].cells[i].hours; + } + } + } + return (
@@ -837,7 +876,9 @@ const OneYearAllocation: React.FC = ({ backgroundColor: cell.hours > 0 ? getColorWithOpacity( - getKindColor(selectedKind as KindType), + getKindColor( + selectedKind as KindType + ), histogramData[ getBinIndex( cell.hours, @@ -849,7 +890,9 @@ const OneYearAllocation: React.FC = ({ border: `1px solid ${ cell.hours > 0 ? getDarkerColor( - getKindColor(selectedKind as KindType), + getKindColor( + selectedKind as KindType + ), histogramData[ getBinIndex( cell.hours, @@ -866,7 +909,10 @@ const OneYearAllocation: React.FC = ({ ? 1 : 0.1, }} - onClick={() => cell.fullDate && handleDateClick(cell.fullDate)} + onClick={() => + cell.fullDate && + handleDateClick(cell.fullDate) + } /> )} @@ -888,6 +934,14 @@ const OneYearAllocation: React.FC = ({ ))} ))} + + + {totalHoursRow.map((cell, index) => ( + + ))} +
Total (h) + {Number.isInteger(cell) ? cell.toString() : cell.toFixed(1)} +
From bdf339f279f7c8855330b3c3777447b1b3bc1d98 Mon Sep 17 00:00:00 2001 From: Elemar Rodrigues Severo Junior Date: Fri, 3 Jan 2025 11:25:32 -0300 Subject: [PATCH 9/9] Update changelog for January 3, 2025: Added "Total (h)" row to One Year Allocation component and improved readability by adding "h" suffix to hour values and percentages to history cards. Fixed timezone issue in the One Year Allocation component. --- frontend/src/content/changelog/2025-01-03.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/content/changelog/2025-01-03.mdx b/frontend/src/content/changelog/2025-01-03.mdx index 18eb9f8a..ef599c88 100644 --- a/frontend/src/content/changelog/2025-01-03.mdx +++ b/frontend/src/content/changelog/2025-01-03.mdx @@ -9,6 +9,7 @@ date: 2025-01-03 ### Improvements - Added "h" suffix to hour values in the "kind of work" cards to improve readability in One Year Allocation visualization - Added percentages to the "history" cards in the "One Year Allocation" component. +- Added "Total (h)" row to the "One Year Allocation" component. ### Bug Fixes - Fixed timezone issue in the "One Year Allocation" component.