Skip to content

Commit

Permalink
Merge pull request #96 from ElemarJR/one_year_allocation_on_forecast
Browse files Browse the repository at this point in the history
One year allocation on forecast
  • Loading branch information
ElemarJR authored Jan 6, 2025
2 parents e28fd8a + 4afc80e commit 2f5b01f
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 31 deletions.
68 changes: 44 additions & 24 deletions frontend/src/app/components/OneYearAllocation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ interface ContributionProps {
clientName?: string;
sponsor?: string;
caseTitle?: string;
kind?: "consulting" | "handsOn" | "squad" | "internal";
hideTotals?: boolean;
}

interface WeekInfo {
Expand Down Expand Up @@ -111,6 +113,8 @@ const OneYearAllocation: React.FC<ContributionProps> = ({
clientName,
sponsor,
caseTitle,
kind,
hideTotals = false,
}) => {
type KindType = "consulting" | "handsOn" | "squad" | "internal";

Expand All @@ -130,7 +134,7 @@ const OneYearAllocation: React.FC<ContributionProps> = ({
};

// Initialize with empty string to ensure we select first non-zero value
const [selectedKind, setSelectedKind] = useState<KindType | "">("");
const [selectedKind, setSelectedKind] = useState<KindType | "">(kind || "");
const [selectedBinIndex, setSelectedBinIndex] = useState<number | null>(null);
const currentDate = new Date();
const specifiedMonth = month || currentDate.getMonth() + 1;
Expand Down Expand Up @@ -177,6 +181,14 @@ const OneYearAllocation: React.FC<ContributionProps> = ({
},
]
: []),
...(kind
? [
{
field: "Kind",
selectedValues: [kind.charAt(0).toUpperCase() + kind.slice(1)],
},
]
: []),
];

const { loading, error, data } = useQuery(ALLOCATION_QUERY, {
Expand Down Expand Up @@ -232,8 +244,8 @@ const OneYearAllocation: React.FC<ContributionProps> = ({
});
}

// Set initial selected kind to first non-zero value if not already set
if (selectedKind === "") {
// Set initial selected kind to first non-zero value if not already set and kind is not provided
if (selectedKind === "" && !kind) {
const firstNonZeroKind = Object.entries(totals).find(
([_, value]) => value > 0
)?.[0] as KindType;
Expand Down Expand Up @@ -552,7 +564,7 @@ const OneYearAllocation: React.FC<ContributionProps> = ({
const histogramData = calculateHistogram();

const renderKinds = () => {
if (!data) return null;
if (!data || kind) return null;

const totalHours =
totals.consulting + totals.handsOn + totals.squad + totals.internal;
Expand Down Expand Up @@ -637,38 +649,38 @@ const OneYearAllocation: React.FC<ContributionProps> = ({
);

return (
<div className="mt-4 mb-4">
<div className="grid grid-cols-2 md:grid-cols-5 gap-4">
<div className="mt-2 mb-2">
<div className="grid grid-cols-2 md:grid-cols-5 gap-2">
{histogramData.map((bin, index) => (
<div
key={index}
className={`p-2 rounded-lg cursor-pointer transition-all hover:ring-1 hover:ring-gray-300 relative
className={`p-1.5 rounded cursor-pointer transition-all hover:ring-1 hover:ring-gray-200 relative
${
selectedBinIndex === index
? "ring-2 ring-blue-500 hover:ring-2 hover:ring-blue-500"
? "ring-1 ring-gray-400 hover:ring-gray-400"
: ""
}`}
style={{
backgroundColor: getColorWithOpacity(
getKindColor(selectedKind as KindType),
selectedKind ? bin.opacity : 0.3
selectedKind ? bin.opacity * 0.7 : 0.2
),
}}
onClick={() =>
setSelectedBinIndex(selectedBinIndex === index ? null : index)
}
>
<div className="flex flex-col">
<span className="text-xs font-medium text-gray-600">
<span className="text-[10px] font-medium text-gray-600">
{bin.min.toFixed(1)}h - {bin.max.toFixed(1)}h
</span>
<div className="flex items-center gap-1 mt-1">
<span className="text-lg font-semibold">{bin.count}</span>
<span className="text-xs text-gray-500">occurrences</span>
<div className="flex items-center gap-0.5">
<span className="text-sm font-medium">{bin.count}</span>
<span className="text-[10px] text-gray-500">×</span>
</div>
</div>
<div className="absolute bottom-1 right-2 text-xs opacity-90">
{((bin.count / totalOccurrences) * 100).toFixed(1)}%
<div className="absolute bottom-1 right-1.5 text-[9px] text-gray-500">
{((bin.count / totalOccurrences) * 100).toFixed(0)}%
</div>
</div>
))}
Expand Down Expand Up @@ -934,14 +946,16 @@ const OneYearAllocation: React.FC<ContributionProps> = ({
))}
</tr>
))}
<tr>
<td className="text-xs text-gray-600 font-normal">Total (h)</td>
{totalHoursRow.map((cell, index) => (
<td key={index} className="text-[8px] text-gray-600 font-normal">
{Number.isInteger(cell) ? cell.toString() : cell.toFixed(1)}
</td>
))}
</tr>
{!hideTotals && (
<tr>
<td className="text-xs text-gray-600 font-normal">Total (h)</td>
{totalHoursRow.map((cell, index) => (
<td key={index} className="text-[8px] text-gray-600 font-normal">
{Number.isInteger(cell) ? cell.toString() : cell.toFixed(1)}
</td>
))}
</tr>
)}
</tbody>
</table>
</div>
Expand All @@ -950,11 +964,17 @@ const OneYearAllocation: React.FC<ContributionProps> = ({

if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {(error as ApolloError).message}</div>;

var title = "One Year Allocation"
if (kind) {
const capitalizedKind = kind.charAt(0).toUpperCase() + kind.slice(1);
title = `${title} - ${capitalizedKind}`
}

return (
<div className="mb-8">
<SectionHeader
title="One Year Allocation"
title={title}
subtitle={`${startDate.toLocaleDateString("en-US", {
month: "short",
year: "numeric",
Expand Down
27 changes: 20 additions & 7 deletions frontend/src/app/financial/revenue-forecast/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { processForecastData } from "./forecastData";
import { OtherTable } from "./OtherTable";
import { ConsultingPreTable } from "./ConsultingPreTable";
import { GraphVizDaily } from "./GraphVizDaily";
import OneYearAllocation from "@/app/components/OneYearAllocation";

export default function RevenueForecastPage() {
const [date, setDate] = useState<Date>(new Date());
Expand Down Expand Up @@ -187,11 +188,11 @@ export default function RevenueForecastPage() {
title: "Consulting",
subtitle: "By Consultant",
},
{
id: "consultingFuture",
title: "Consulting",
subtitle: "Next three months",
},
// {
// id: "consultingFuture",
// title: "Consulting",
// subtitle: "Next three months",
// },
{
id: "consultingPre",
title: "Consulting Pre",
Expand All @@ -212,6 +213,10 @@ export default function RevenueForecastPage() {
]}
/>

<div className="mt-4">
<OneYearAllocation kind="consulting" hideTotals={true} />
</div>

<ConsultingTable
title="Consulting"
tableData={forecastData.consulting}
Expand Down Expand Up @@ -242,7 +247,7 @@ export default function RevenueForecastPage() {
setNormalized={setNormalized}
/>

<ConsultingTableFuture
{/* <ConsultingTableFuture
title="Consulting"
tableData={forecastData.consulting}
tableId="consultingFuture"
Expand All @@ -256,7 +261,7 @@ export default function RevenueForecastPage() {
toggleClient={toggleClient}
setNormalized={setNormalized}
setUseHistorical={setUseHistorical}
/>
/> */}

<ConsultingPreTable
title="Consulting Pre"
Expand All @@ -268,6 +273,10 @@ export default function RevenueForecastPage() {
toggleClient={(clientSlug) => toggleClient(clientSlug, "consultingPre")}
/>

<div className="mt-4">
<OneYearAllocation kind="handsOn" hideTotals={true} />
</div>

<OtherTable
title="Hands On"
tableData={forecastData.handsOn}
Expand All @@ -279,6 +288,10 @@ export default function RevenueForecastPage() {
toggleClient={toggleClient}
/>

<div className="mt-4">
<OneYearAllocation kind="squad" hideTotals={true} />
</div>

<OtherTable
title="Squad"
tableData={forecastData.squad}
Expand Down

0 comments on commit 2f5b01f

Please sign in to comment.