"use client"; import { useState } from "react"; import { clsx } from "clsx"; import { InfoTooltip } from "~/components/ui/InfoTooltip.js"; import { formatCents } from "~/lib/format.js"; import { trpc } from "~/lib/trpc/client.js"; interface ApplyExperienceMultipliersProps { estimateId: string; canEdit: boolean; onApplied?: () => void; } export function ApplyExperienceMultipliers({ estimateId, canEdit, onApplied }: ApplyExperienceMultipliersProps) { const utils = trpc.useUtils(); const { data: sets, isLoading } = trpc.experienceMultiplier.list.useQuery(); const [selectedSetId, setSelectedSetId] = useState(""); const [showPreview, setShowPreview] = useState(false); const previewQuery = trpc.experienceMultiplier.preview.useQuery( { estimateId, multiplierSetId: selectedSetId }, { enabled: showPreview && Boolean(selectedSetId) }, ); const applyMutation = trpc.experienceMultiplier.applyRules.useMutation({ onSuccess: (result) => { utils.estimate.getById.invalidate(); setShowPreview(false); onApplied?.(); alert( `Updated ${result.linesUpdated} demand line(s).\n` + `Hours: ${result.totalOriginalHours}h -> ${result.totalAdjustedHours}h`, ); }, }); // Auto-select default set if (!selectedSetId && sets) { const defaultSet = sets.find((s) => s.isDefault) ?? sets[0]; if (defaultSet) { setSelectedSetId(defaultSet.id); } } if (!canEdit) return null; if (isLoading) { return

Loading experience multipliers...

; } if (!sets || sets.length === 0) { return (
No experience multiplier sets defined.{" "} Create one {" "} to apply rate and effort adjustments.
); } return (

Apply experience multipliers

{applyMutation.error && (

{applyMutation.error.message}

)} {/* Preview */} {showPreview && previewQuery.data && (
{previewQuery.data.demandLineCount} demand lines {previewQuery.data.ruleCount} rules {previewQuery.data.linesChanged} line(s) would be adjusted
{previewQuery.data.linesChanged > 0 && (
Total cost: {formatCents(previewQuery.data.totalOriginalCostCents)} {"->"}{" "} {formatCents(previewQuery.data.totalAdjustedCostCents)}
)} {/* Per-line preview */} {previewQuery.data.previews.length > 0 && (
Show all {previewQuery.data.previews.length} lines
{previewQuery.data.previews.map((p, i) => ( ))}
Name Chapter Cost rate Bill rate Hours Changes
{p.name} {p.chapter ?? "\u2014"} {p.hasChanges && p.adjustedCostRateCents !== p.originalCostRateCents ? ( <> {formatCents(p.originalCostRateCents)}{" "} {formatCents(p.adjustedCostRateCents)} ) : ( formatCents(p.originalCostRateCents) )} {p.hasChanges && p.adjustedBillRateCents !== p.originalBillRateCents ? ( <> {formatCents(p.originalBillRateCents)}{" "} {formatCents(p.adjustedBillRateCents)} ) : ( formatCents(p.originalBillRateCents) )} {p.hasChanges && p.adjustedHours !== p.originalHours ? ( <> {p.originalHours}h{" "} {p.adjustedHours}h ) : ( `${p.originalHours}h` )} {p.hasChanges ? p.appliedRules[0] ?? "" : "No change"}
)}
)} {showPreview && previewQuery.isLoading && (

Computing preview...

)}
); }