Hooks Documentation
Custom Hooks Overview
| Hook | Location | Purpose |
|---|---|---|
useAuth | lib/auth-context.tsx | Authentication state |
useBlockchain | hooks/use-blockchain.ts | Blockchain operations |
useToast | hooks/use-toast.ts | Toast notifications |
useMobile | hooks/use-mobile.ts | Mobile detection |
useReusabilityPrediction | lib/ml-api/hooks.ts | Prediction API |
useTreatmentRecommendation | lib/ml-api/hooks.ts | Treatment API |
useSaveReport | lib/reports/hooks.ts | Report saving |
useReports | lib/reports/hooks.ts | Report fetching |
useHealthCheck | lib/ml-api/hooks.ts | API 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-into/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