diff --git a/app/page.tsx b/app/page.tsx
index af2d3e9..8ca3ddb 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -3,6 +3,7 @@ import { ValueProps } from '@/components/landing/ValueProps';
import { CallToAction } from '@/components/landing/CallToAction';
import { TrustBar } from '@/components/landing/TrustBar';
import { PricingCards } from '@/components/pricing/PricingCards';
+import { KineticExplorer } from '@/components/landing/KineticExplorer';
export default function Home() {
return (
diff --git a/components/mobile/MobileFooter.tsx b/components/mobile/MobileFooter.tsx
index 303e290..7555d9b 100644
--- a/components/mobile/MobileFooter.tsx
+++ b/components/mobile/MobileFooter.tsx
@@ -1,26 +1,26 @@
-`use client
+'use client'
-import React from react
-import Link from next/link
+import React from 'react'
+import Link from 'next/link'
// Navigation links data
const footerLinks = [
- { label: Home, href: / },
- { label: About, href: /about },
- { label: Services, href: /services },
- { label: Support, href: /support },
- { label: Privacy Policy, href: /privacy },
- { label: Terms of Service, href: /terms },
- { label: Contact, href: /contact },
- { label: FAQs, href: /faq },
+ { label: 'Home', href: '/' },
+ { label: 'About', href: '/about' },
+ { label: 'Services', href: '/services' },
+ { label: 'Support', href: '/support' },
+ { label: 'Privacy Policy', href: '/privacy' },
+ { label: 'Terms of Service', href: '/terms' },
+ { label: 'Contact', href: '/contact' },
+ { label: 'FAQs', href: '/faq' },
]
// Social icons data
const socialLinks = [
- { label: Twitter, href: https://twitter.com/swiftchain, icon: 🐦 },
- { label: GitHub, href: https://github.com/swiftchain, icon: 🐙 },
- { label: LinkedIn, href: https://linkedin.com/company/swiftchain, icon: 🔗 },
- { label: Discord, href: https://discord.gg/swiftchain, icon: 💬 },
+ { label: 'Twitter', href: 'https://twitter.com/swiftchain', icon: '🐦' },
+ { label: 'GitHub', href: 'https://github.com/swiftchain', icon: '🐙' },
+ { label: 'LinkedIn', href: 'https://linkedin.com/company/swiftchain', icon: '🔗' },
+ { label: 'Discord', href: 'https://discord.gg/swiftchain', icon: '💬' },
]
export function MobileFooter() {
@@ -36,7 +36,7 @@ export function MobileFooter() {
key={link.href}
href={link.href}
className="rounded-lg px-3 py-2.5 text-sm text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 active:bg-gray-200 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-100 dark:active:bg-gray-700"
- style={{ minHeight: 44px }}
+ style={{ minHeight: '44px' }}
>
{link.label}
@@ -53,7 +53,7 @@ export function MobileFooter() {
rel="noopener noreferrer"
className="flex h-11 w-11 items-center justify-center rounded-full text-xl transition-colors hover:bg-gray-100 hover:text-gray-900 dark:hover:bg-gray-800 dark:hover:text-gray-100"
aria-label={social.label}
- style={{ minHeight: 44px, minWidth: 44px }}
+ style={{ minHeight: '44px', minWidth: '44px' }}
>
{social.label}
@@ -73,4 +73,3 @@ export function MobileFooter() {
}
export default MobileFooter
-
diff --git a/hooks/useDriverReputation.ts b/hooks/useDriverReputation.ts
index e70e2d1..899e803 100644
--- a/hooks/useDriverReputation.ts
+++ b/hooks/useDriverReputation.ts
@@ -18,28 +18,26 @@ export interface UseDriverReputationResult {
* state on an unmounted component.
*/
export function useDriverReputation(driverId: string): UseDriverReputationResult {
- const [onChainScore, setOnChainScore] = useState(null);
- const [isLoading, setIsLoading] = useState(true);
- const [error, setError] = useState(null);
+ // Store the settled result together with the driverId it belongs to, so
+ // loading is derived from a stale/absent result rather than written back
+ // into state from the effect.
+ const [result, setResult] = useState<{
+ driverId: string;
+ onChainScore: number | null;
+ error: string | null;
+ } | null>(null);
useEffect(() => {
- if (!driverId) {
- setOnChainScore(null);
- setIsLoading(false);
- return;
- }
+ if (!driverId) return;
const controller = new AbortController();
let cancelled = false;
- setIsLoading(true);
-
reputationService
.getDriverReputation(driverId, controller.signal)
.then((data) => {
if (cancelled) return;
- setOnChainScore(data.onChainScore);
- setError(null);
+ setResult({ driverId, onChainScore: data.onChainScore, error: null });
})
.catch((err: unknown) => {
if (cancelled) return;
@@ -48,10 +46,7 @@ export function useDriverReputation(driverId: string): UseDriverReputationResult
err instanceof Error && err.message
? err.message
: 'Failed to load on-chain reputation';
- setError(message);
- })
- .finally(() => {
- if (!cancelled) setIsLoading(false);
+ setResult({ driverId, onChainScore: null, error: message });
});
return () => {
@@ -60,5 +55,19 @@ export function useDriverReputation(driverId: string): UseDriverReputationResult
};
}, [driverId]);
- return { onChainScore, isLoading, error };
+ // With no driverId there is nothing to fetch.
+ if (!driverId) {
+ return { onChainScore: null, isLoading: false, error: null };
+ }
+
+ // No result yet for this driverId means the request is still in flight.
+ if (!result || result.driverId !== driverId) {
+ return { onChainScore: null, isLoading: true, error: null };
+ }
+
+ return {
+ onChainScore: result.onChainScore,
+ isLoading: false,
+ error: result.error,
+ };
}
diff --git a/hooks/useTheme.ts b/hooks/useTheme.ts
index aef9d28..9169305 100644
--- a/hooks/useTheme.ts
+++ b/hooks/useTheme.ts
@@ -1,11 +1,23 @@
// hooks/useTheme.ts
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useCallback } from 'react';
import { ThemeService, Theme } from '@/services/themeService';
export const useTheme = (userId?: string) => {
const [theme, setThemeState] = useState('system');
+ const updateTheme = useCallback(
+ (newTheme: Theme) => {
+ setThemeState(newTheme);
+ ThemeService.setThemeToStorage(newTheme);
+
+ if (userId) {
+ ThemeService.syncThemeToAPI(userId, newTheme).catch(console.error);
+ }
+ },
+ [userId]
+ );
+
useEffect(() => {
const initializeTheme = async () => {
// 1. Sync from local storage immediately to match the blocking script
@@ -27,7 +39,7 @@ export const useTheme = (userId?: string) => {
}
};
initializeTheme();
- }, [userId]);
+ }, [userId, updateTheme]);
// Apply theme to DOM when state changes
useEffect(() => {
@@ -60,14 +72,5 @@ export const useTheme = (userId?: string) => {
return () => mediaQuery.removeEventListener('change', handleChange);
}, [theme]);
- const updateTheme = (newTheme: Theme) => {
- setThemeState(newTheme);
- ThemeService.setThemeToStorage(newTheme);
-
- if (userId) {
- ThemeService.syncThemeToAPI(userId, newTheme).catch(console.error);
- }
- };
-
return { theme, setTheme: updateTheme };
};
\ No newline at end of file