Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions components/estimator/estimate-pdf.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Steel-Tech / StructuPath
import { useMemo } from "react";
import { Printer } from "lucide-react";
import { formatCurrency, formatCurrencyPrecise } from "@/lib/estimator/calculate";
import type { EstimateInput, EstimateResult } from "@/lib/types/estimator";
Expand All @@ -18,11 +19,19 @@ export function EstimatePdf({
result,
companyName = "IronForge Estimator",
}: Props) {
const today = new Date().toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
// Stamp the date + estimate id once at mount — computing them during render
// is impure (the id would change on every re-render).
const { today, estimateId } = useMemo(() => {
const now = new Date();
return {
today: now.toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
}),
estimateId: now.getTime().toString().slice(-6),
};
}, []);
const stateData = input.state ? STATE_REGISTRY[input.state] : undefined;

function handlePrint() {
Expand Down Expand Up @@ -52,8 +61,7 @@ export function EstimatePdf({
<strong>Date:</strong> {today}
</div>
<div>
<strong>Estimate #:</strong> EST-
{Date.now().toString().slice(-6)}
<strong>Estimate #:</strong> EST-{estimateId}
</div>
</div>
</header>
Expand Down
2 changes: 1 addition & 1 deletion components/estimator/estimate-results.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function EstimateResults({ input, result }: Props) {
<div className="relative flex flex-col md:flex-row md:items-end justify-between gap-6">
<div>
<div className="text-[10px] font-mono text-text-muted tracking-[0.3em] uppercase mb-2">
// Total Bid Estimate
{"// Total Bid Estimate"}
</div>
<div className="font-mono font-bold text-text-primary tracking-tight">
<span className="text-5xl md:text-6xl text-neon-cyan text-glow-cyan">
Expand Down
1 change: 0 additions & 1 deletion components/ui/error-boundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
}

componentDidCatch(error: Error, info: ErrorInfo) {
// eslint-disable-next-line no-console
console.error("[ErrorBoundary]", error, info);
}

Expand Down
4 changes: 3 additions & 1 deletion components/vault/expiration-alerts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2026 Steel-Tech / StructuPath
import { useState } from "react";
import { AlertTriangle } from "lucide-react";
import type { VaultDocument } from "@/lib/types/vault";

Expand All @@ -16,7 +17,8 @@ interface Bucket {
}

export function ExpirationAlerts({ documents }: ExpirationAlertsProps) {
const now = Date.now();
// Captured once at mount — Date.now() in render is impure.
const [now] = useState(() => Date.now());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep expiration thresholds current

When the vault page stays open across a threshold change, this frozen now keeps all bucket decisions tied to the initial mount time. app/vault/page.tsx keeps ExpirationAlerts mounted for the page lifetime, so a document that was 31 days out at load will not enter the <30 days alert on later refresh/rerender, and an 8-day document can remain in the warning bucket after it crosses 7 days or expires; the per-card status still recomputes from Date.now(), so the banner can disagree with the cards. Track current time with a refresh/remount trigger or derive it when recomputing buckets instead of storing it once.

Useful? React with 👍 / 👎.

const thirty = 30 * 86_400_000;
const seven = 7 * 86_400_000;

Expand Down
Loading