Skip to main content

Hooks Documentation

Custom Hooks Overview

HookLocationPurpose
useAuthlib/auth-context.tsxAuthentication state
useBlockchainhooks/use-blockchain.tsBlockchain operations
useToasthooks/use-toast.tsToast notifications
useMobilehooks/use-mobile.tsMobile detection
useReusabilityPredictionlib/ml-api/hooks.tsPrediction API
useTreatmentRecommendationlib/ml-api/hooks.tsTreatment API
useSaveReportlib/reports/hooks.tsReport saving
useReportslib/reports/hooks.tsReport fetching
useHealthChecklib/ml-api/hooks.tsAPI health status

Authentication Hook

useAuth

Location: src/lib/auth-context.tsx

Provides authentication state and methods.

interface AuthContextType {
user: User | null; // Firebase User object
loading: boolean; // Auth state loading
signIn: (email: string, password: string) => Promise<void>;
signUp: (email: string, password: string, displayName?: string) => Promise<void>;
signInWithGoogle: () => Promise<void>;
logout: () => Promise<void>;
}

// Usage
function Component() {
const { user, loading, signIn, signUp, signInWithGoogle, logout } = useAuth();

if (loading) return <Spinner />;
if (!user) return <SignInForm />;

return (
<div>
<p>Welcome, {user.displayName}</p>
<button onClick={logout}>Logout</button>
</div>
);
}

Features:

  • Auto-redirect logged users from /sign-in to /dashboard
  • Persists session via Firebase SDK
  • Provides Google OAuth support

Blockchain Hook

useBlockchain

Location: src/hooks/use-blockchain.ts

Client-side hook for blockchain operations via API routes.

interface UseBlockchainReturn {
// Methods
storeOnBlockchain: (params) => Promise<BlockchainStoreResult>;
verifyReport: (params) => Promise<BlockchainVerifyResult>;
getStatus: () => Promise<BlockchainStatus>;
reset: () => void;

// Loading states
isStoring: boolean;
isVerifying: boolean;
isLoadingStatus: boolean;

// Results
lastStoreResult: BlockchainStoreResult | null;
lastVerifyResult: BlockchainVerifyResult | null;
blockchainStatus: BlockchainStatus | null;
}

// Usage
function ReportPage() {
const { storeOnBlockchain, isStoring, lastStoreResult } = useBlockchain();

const handleSave = async (report) => {
const result = await storeOnBlockchain({
reportId: report.id,
reportType: "prediction",
userId: user.uid,
input: report.input,
output: report.output,
createdAt: new Date(),
});

if (result.success) {
console.log("Stored:", result.transactionHash);
}
};

return (
<div>
<button onClick={handleSave} disabled={isStoring}>
{isStoring ? "Storing..." : "Store on Blockchain"}
</button>
{lastStoreResult?.success && <a href={lastStoreResult.explorerUrl}>View on Explorer</a>}
</div>
);
}

Store Result:

interface BlockchainStoreResult {
success: boolean;
transactionHash?: string;
blockNumber?: number;
reportHash?: string;
explorerUrl?: string;
chainName?: string;
error?: string;
}

Verify Result:

interface BlockchainVerifyResult {
isValid: boolean;
reportHash: string;
existsOnChain: boolean;
chainName?: string;
message?: string;
}

Toast Hook

useToast

Location: src/hooks/use-toast.ts

Toast notification management.

interface Toast {
id: string;
title: string;
description?: string;
variant?: "default" | "success" | "destructive";
}

interface UseToastReturn {
toasts: Toast[];
toast: (props: Omit<Toast, "id">) => string; // Returns toast ID
dismiss: (id: string) => void;
}

// Usage
function Component() {
const { toast, toasts, dismiss } = useToast();

const handleSuccess = () => {
toast({
title: "Success!",
description: "Operation completed",
variant: "success",
});
};

const handleError = () => {
toast({
title: "Error",
description: "Something went wrong",
variant: "destructive",
});
};

return (
<>
<Toaster toasts={toasts} dismiss={dismiss} />
<button onClick={handleSuccess}>Success</button>
<button onClick={handleError}>Error</button>
</>
);
}

Mobile Detection Hook

useMobile

Location: src/hooks/use-mobile.ts

Detects if viewport is mobile-sized.

function useMobile(): boolean;

// Usage
function ResponsiveComponent() {
const isMobile = useMobile();

return isMobile ? <MobileLayout /> : <DesktopLayout />;
}

Breakpoint: 768px (configurable)


ML API Hooks

useReusabilityPrediction

Location: src/lib/ml-api/hooks.ts

Water reusability prediction.

interface UseReusabilityReturn {
data: ReusabilityResult | null;
isLoading: boolean;
error: string | null;
isSuccess: boolean;
predict: (input: WastewaterInput) => Promise<ReusabilityResult | null>;
reset: () => void;
}

// Usage
function PredictionPage() {
const { predict, isLoading, data, error, isSuccess, reset } = useReusabilityPrediction();

const handleSubmit = async (formData) => {
try {
const result = await predict(formData);
console.log("Prediction:", result?.prediction_display);
} catch (err) {
console.error(err);
}
};

return (
<form onSubmit={handleSubmit}>
{/* Form fields */}
<button disabled={isLoading}>{isLoading ? "Predicting..." : "Predict"}</button>
{error && <p className="error">{error}</p>}
{isSuccess && <ResultDisplay data={data} />}
</form>
);
}

useTreatmentRecommendation

Location: src/lib/ml-api/hooks.ts

Treatment stage recommendation.

interface UseTreatmentReturn {
data: TreatmentResult | null;
isLoading: boolean;
error: string | null;
isSuccess: boolean;
recommend: (input: TreatmentInput, useCase?: TreatmentUseCase) => Promise<TreatmentResult | null>;
reset: () => void;
}

// Usage
function TreatmentPage() {
const { recommend, isLoading, data } = useTreatmentRecommendation();

const handleSubmit = async (formData, useCase) => {
const result = await recommend(formData, useCase);
console.log("Recommended:", result?.recommended_stage);
};
}

useHealthCheck

Location: src/lib/ml-api/hooks.ts

ML API health status with optional polling.

interface UseHealthReturn {
data: HealthStatus | null;
isLoading: boolean;
error: string | null;
refetch: () => Promise<void>;
}

// Usage
function StatusWidget() {
// Poll every 30 seconds
const { data, isLoading, error, refetch } = useHealthCheck(30000);

if (isLoading) return <Spinner />;
if (error) return <Badge variant="destructive">Offline</Badge>;

return (
<div>
<Badge variant="success">{data?.status}</Badge>
<p>Uptime: {data?.uptime_seconds}s</p>
<button onClick={refetch}>Refresh</button>
</div>
);
}

useBatchPrediction

Location: src/lib/ml-api/hooks.ts

Batch predictions for multiple samples.

const { predict, isLoading, data } = useBatchPrediction();

await predict({
model_id: "reusability",
samples: [
{ BOD: 20, COD: 150, ... },
{ BOD: 25, COD: 180, ... },
],
});

useCPCBLimits / useClassInfo

Location: src/lib/ml-api/hooks.ts

Reference data hooks.

// CPCB regulatory limits
const { data: limits } = useCPCBLimits();
// { BOD: 30, COD: 250, TSS: 100, ... }

// Reusability class information
const { data: classInfo } = useClassInfo();
// { irrigation: { purpose: "...", remedies: "..." }, ... }

Report Hooks

useSaveReport

Location: src/lib/reports/hooks.ts

Saves reports to Firestore.

interface UseSaveReportReturn {
save: <T extends Report>(reportType: ReportType, input: T["input"], output: T["output"]) => Promise<string | null>; // Returns report ID
isSaving: boolean;
error: string | null;
}

// Usage
function AnalysisPage() {
const { save, isSaving, error } = useSaveReport();

const handleComplete = async (input, output) => {
const reportId = await save("prediction", input, output);
if (reportId) {
console.log("Saved with ID:", reportId);
}
};
}

useReports

Location: src/lib/reports/hooks.ts

Fetches user's reports with filtering.

interface UseReportsReturn {
reports: Report[];
summaries: ReportSummary[];
isLoading: boolean;
error: string | null;
fetchReports: () => Promise<void>;
fetchSummaries: () => Promise<void>;
removeReport: (reportId: string, reportType?: ReportType) => Promise<void>;
}

// Usage
function HistoryPage() {
const { summaries, isLoading, fetchSummaries, removeReport } = useReports({
reportType: "prediction", // Optional filter
limit: 20,
});

useEffect(() => {
fetchSummaries();
}, []);

return (
<div>
{isLoading ? (
<Spinner />
) : (
summaries.map((report) => <ReportCard key={report.id} report={report} onDelete={() => removeReport(report.id, report.reportType)} />)
)}
</div>
);
}

useReport

Location: src/lib/reports/hooks.ts

Fetches a single report by ID.

interface UseReportReturn {
report: Report | null;
isLoading: boolean;
error: string | null;
fetchReport: () => Promise<void>;
}

// Usage
function ReportDetailPage({ reportId }) {
const { report, isLoading, fetchReport } = useReport(reportId);

useEffect(() => {
fetchReport();
}, [reportId]);

if (isLoading) return <Spinner />;
if (!report) return <NotFound />;

return <ReportDetail report={report} />;
}

Hook Patterns

Loading/Error/Success Pattern

interface HookState<T> {
data: T | null;
isLoading: boolean;
error: string | null;
isSuccess: boolean;
}

Reset Pattern

// Hooks provide reset() to clear state
const { data, reset } = useReusabilityPrediction();

// Reset before new operation or on unmount
useEffect(() => {
return () => reset();
}, []);

Callback Memoization

// All mutation callbacks are memoized with useCallback
const predict = useCallback(async (input) => {
setState({ isLoading: true, ... });
// ...
}, [dependencies]);

Last Updated: December 2024