Files
fusion/packages/dashboard/app/hooks/useGithubSetupWarningDelay.ts
gsxdsm 50786f29d4 FN-7475: delay GitHub setup warnings
Delay dashboard GitHub setup warnings until the project grace period expires while keeping AI setup warnings immediate.

- Add per-project GitHub warning delay state and persistence.
- Route dashboard GitHub warnings to Settings → Authentication with a Connect GitHub action.
- Hide non-actionable GitHub-only warnings in the New Task modal and update localized copy, docs, and tests.

Files changed:
 .changeset/fn-7475-github-setup-warning.md         |   7 ++
 docs/dashboard-guide.md                            |   6 +
 packages/dashboard/app/App.tsx                     |  11 +-
 packages/dashboard/app/components/NewTaskModal.tsx |   8 +-
 .../app/components/SetupWarningBanner.css          |  10 ++
 .../app/components/SetupWarningBanner.tsx          |  18 ++-
 .../app/components/__tests__/NewTaskModal.test.tsx |  46 ++++++-
 .../__tests__/SetupWarningBanner.test.tsx          |  40 ++++++
 .../app/components/dashboard/DashboardBanners.tsx  |   3 +
 .../dashboard/__tests__/DashboardBanners.test.tsx  | 125 ++++++++++++++++++-
 .../dashboard/app/components/dashboard/types.ts    |   1 +
 .../__tests__/useGithubSetupWarningDelay.test.ts   | 134 +++++++++++++++++++++
 .../app/hooks/useGithubSetupWarningDelay.ts        |  96 +++++++++++++++
 packages/dashboard/app/utils/projectStorage.ts     |   1 +
 packages/i18n/locales/en/app.json                  |   5 +-
 packages/i18n/locales/es/app.json                  |   5 +-
 packages/i18n/locales/fr/app.json                  |   5 +-
 packages/i18n/locales/ko/app.json                  |   5 +-
 packages/i18n/locales/zh-CN/app.json               |   5 +-
 packages/i18n/locales/zh-TW/app.json               |   5 +-
 packages/i18n/src/resources.d.ts                   | 127 +++++++++++++------
 21 files changed, 606 insertions(+), 57 deletions(-)

Fusion-Task-Id: FN-7475
Fusion-Task-Lineage: 5bf1fffa-b58c-42a1-b170-367a4c20eaaf
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-03 21:45:21 -07:00

97 lines
2.7 KiB
TypeScript

import { useEffect, useState } from "react";
import { getScopedItem, removeScopedItem, setScopedItem } from "../utils/projectStorage";
export const GITHUB_SETUP_WARNING_DELAY_MS = 86_400_000;
export const GITHUB_SETUP_WARNING_MISSING_SINCE_KEY = "kb-github-setup-warning-missing-since";
export interface UseGithubSetupWarningDelayOptions {
projectId?: string;
hasGithub: boolean;
loading: boolean;
now?: () => number;
}
function readMissingSince(projectId: string): number | null {
try {
const stored = getScopedItem(GITHUB_SETUP_WARNING_MISSING_SINCE_KEY, projectId);
if (!stored) {
return null;
}
const parsed = Number(stored);
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
} catch {
return null;
}
}
function writeMissingSince(projectId: string, missingSince: number): void {
try {
setScopedItem(GITHUB_SETUP_WARNING_MISSING_SINCE_KEY, String(missingSince), projectId);
} catch {
// Best effort only: storage failures must not break dashboard rendering.
}
}
function clearMissingSince(projectId: string): void {
try {
removeScopedItem(GITHUB_SETUP_WARNING_MISSING_SINCE_KEY, projectId);
} catch {
// Best effort only: storage failures must not break dashboard rendering.
}
}
export function useGithubSetupWarningDelay({
projectId,
hasGithub,
loading,
now = Date.now,
}: UseGithubSetupWarningDelayOptions): boolean {
const [showWarning, setShowWarning] = useState(false);
useEffect(() => {
if (!projectId) {
setShowWarning(false);
return undefined;
}
if (loading) {
setShowWarning(false);
return undefined;
}
if (hasGithub) {
clearMissingSince(projectId);
setShowWarning(false);
return undefined;
}
/*
FNXC:SetupWarning 2026-07-03-00:00:
GitHub setup prompts are intentionally delayed for one day after a project first observes GitHub missing. AI-provider warnings remain immediate, but GitHub import/auth nudges should not interrupt new projects during their first 24 hours.
*/
const observedAt = now();
const existingMissingSince = readMissingSince(projectId);
const missingSince = existingMissingSince ?? observedAt;
if (existingMissingSince == null) {
writeMissingSince(projectId, missingSince);
}
const elapsedMs = observedAt - missingSince;
if (elapsedMs >= GITHUB_SETUP_WARNING_DELAY_MS) {
setShowWarning(true);
return undefined;
}
setShowWarning(false);
const timeoutMs = GITHUB_SETUP_WARNING_DELAY_MS - elapsedMs;
const timer = window.setTimeout(() => {
setShowWarning(true);
}, timeoutMs);
return () => window.clearTimeout(timer);
}, [hasGithub, loading, now, projectId]);
return showWarning;
}