All files / src/pages/flowsheet-page/economics/capital EconomicsCapitalBreakdown.tsx

86.04% Statements 37/43
46.8% Branches 22/47
57.14% Functions 4/7
93.33% Lines 28/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124                    22x           22x                 22x         1x   22x   24x     1x   22x 1x       23x 23x                   1x                     154x       1x         1x   1x 1x 4x                                   4x   1x   3x   2x 4x         1x 1x 1x   1x               1x    
import { Badge } from "@/ahuora-design-system/ui/badge";
import type { EconomicsResultLineRead } from "@/api/apiStore.gen";
import { cn } from "@/lib/utils";
import {
  capitalFactorLabel,
  capitalFactorMeta,
  capitalFactorsFromPayload,
  formatAmountWithUnit,
} from "./economicsCapitalFactors";
 
export function CapitalCostBreakdown({
  lines,
  stale,
  runId,
  unitName,
  className,
  fullWidth = false,
}: {
  lines: EconomicsResultLineRead[];
  stale: boolean;
  runId: number | null;
  unitName?: string;
  className?: string;
  fullWidth?: boolean;
}) {
  const matchingLines = lines.filter((line) =>
    line.kind.toString().includes("capital"),
  );
  return (
    <div
      className={cn(
        "mt-3 w-full rounded-md border border-input bg-muted/20 p-3 text-left",
        !fullWidth && "md:w-1/2",
        className,
      )}
    >
      <div className="flex flex-wrap items-center justify-between gap-2">
        <span className="text-sm font-semibold text-muted-foreground">
          Capital cost
        </span>
        {stale && (
          <Badge variant="secondary" size="xs" borderRadius="round">
            Stale
          </Badge>
        )}
      </div>
      {matchingLines.length === 0 ? (
        <div className="mt-2 text-xs text-muted-foreground">
          {runId
            ? "No capital result is available for this unit."
            : "Calculate results to see capital cost."}
        </div>
      ) : (
        <div className="mt-3 space-y-3">
          {matchingLines.map((line) => (
            <div key={line.id}>
              {resultLineLabel(line.label, unitName) !== "Capital cost" && (
                <div className="mb-2 text-xs text-muted-foreground">
                  {resultLineLabel(line.label, unitName)}
                </div>
              )}
              <CapitalFactorBreakdown line={line} />
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
 
export function CapitalFactorBreakdown({
  line,
}: {
  line: EconomicsResultLineRead;
}) {
  const factors = capitalFactorsFromPayload(line.warning_payload);
  return (
    <dl className="space-y-2.5">
      {factors.map((factor, index) => (
        <div
          key={`${factor.kind}-${index}`}
          className="grid grid-cols-[minmax(0,1fr)_auto] items-start gap-x-3"
        >
          <dt className="min-w-0">
            <div className="truncate text-sm text-muted-foreground">
              {capitalFactorLabel(factor)}
            </div>
            {capitalFactorMeta(factor) && (
              <div className="mt-0.5 truncate text-xs leading-4 text-muted-foreground/70">
                {capitalFactorMeta(factor)}
              </div>
            )}
          </dt>
          <dd className="justify-self-end text-right text-sm tabular-nums text-muted-foreground">
            {formatAmountWithUnit(factor.amount, line.unit)}
          </dd>
        </div>
      ))}
      <div className="grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-3 border-t border-input/70 pt-2">
        <dt className="text-sm font-semibold text-foreground">Total</dt>
        <dd className="justify-self-end text-right text-sm font-semibold tabular-nums text-foreground">
          {formatAmountWithUnit(line.amount, line.unit)}
        </dd>
      </div>
    </dl>
  );
}
 
function resultLineLabel(label: string, unitName?: string) {
  const trimmedLabel = label.trim();
  const trimmedUnitName = unitName?.trim();
  Iif (!trimmedUnitName) return trimmedLabel;
  if (trimmedLabel.toLowerCase().startsWith(trimmedUnitName.toLowerCase())) {
    return capitalizeFirst(
      trimmedLabel.slice(trimmedUnitName.length).trim() || "Result",
    );
  }
  return trimmedLabel;
}
 
function capitalizeFirst(value: string) {
  return value ? `${value[0].toUpperCase()}${value.slice(1)}` : value;
}