diff --git a/app/page.tsx b/app/page.tsx
index ac7044b..eb40aab 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,10 +1,12 @@
import Link from "next/link";
-import { ArrowRight, Shield, LineChart, Zap, Package, Users, CreditCard } from "lucide-react";
+import { ArrowRight, Shield, LineChart, Zap } from "lucide-react";
import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { fetchPlatformStats } from "@/lib/stats-service";
import { HomeNavbar } from "@/components/home-navbar";
import { Suspense } from "react";
+import { AnimatedStatsSection } from "@/components/animated-stats-section";
+import Image from "next/image";
+import { TextTyper } from "@/components/text-typer";
// Constants
const PY_20 = 20;
@@ -64,26 +66,7 @@ export default async function Home() {
Loading statistics...
}>
-
-
-
-
{formatNumberValue(stats.orders.completed)}+
-
Orders Processed
-
Successfully delivered to customers around the world
-
-
-
-
{formatNumberValue(stats.vendors.total)}+
-
Registered Vendors
-
Trusted merchants selling on our platform
-
-
-
-
{formatCurrencyValue(stats.transactions.volume)}
-
Transaction Volume
-
Securely processed by our platform
-
-
+
@@ -187,7 +170,7 @@ export default async function Home() {
-
{new Date().getFullYear()} Ember. All rights reserved.
+
© {new Date().getFullYear()} Ember. All rights reserved.
diff --git a/components/animated-counter.tsx b/components/animated-counter.tsx
new file mode 100644
index 0000000..c3ce52a
--- /dev/null
+++ b/components/animated-counter.tsx
@@ -0,0 +1,71 @@
+"use client";
+
+import { useState, useEffect, useRef } from "react";
+
+export interface AnimatedCounterProps {
+ value: number;
+ duration?: number;
+ prefix?: string;
+ suffix?: string;
+ formatter?: (value: number) => string;
+}
+
+export function AnimatedCounter({
+ value,
+ duration = 2000,
+ prefix = "",
+ suffix = "",
+ formatter
+}: AnimatedCounterProps) {
+ const [displayValue, setDisplayValue] = useState(0);
+ const startTimeRef = useRef(null);
+ const frameRef = useRef(null);
+
+ // Easing function for smoother animation
+ const easeOutQuad = (t: number): number => t * (2 - t);
+
+ useEffect(() => {
+ // Reset start time on new value
+ startTimeRef.current = null;
+
+ // Cancel any ongoing animation
+ if (frameRef.current) {
+ cancelAnimationFrame(frameRef.current);
+ }
+
+ // Animation function
+ const animate = (timestamp: number) => {
+ if (!startTimeRef.current) {
+ startTimeRef.current = timestamp;
+ }
+
+ const elapsed = timestamp - startTimeRef.current;
+ const progress = Math.min(elapsed / duration, 1);
+ const easedProgress = easeOutQuad(progress);
+
+ const nextValue = Math.floor(easedProgress * value);
+ setDisplayValue(nextValue);
+
+ if (progress < 1) {
+ frameRef.current = requestAnimationFrame(animate);
+ } else {
+ setDisplayValue(value);
+ }
+ };
+
+ // Start the animation
+ frameRef.current = requestAnimationFrame(animate);
+
+ return () => {
+ if (frameRef.current) {
+ cancelAnimationFrame(frameRef.current);
+ }
+ };
+ }, [value, duration]);
+
+ const formattedValue = formatter
+ ? formatter(displayValue)
+ : `${prefix}${displayValue.toLocaleString()}${suffix}`;
+
+ return {formattedValue};
+}
\ No newline at end of file
diff --git a/components/animated-stats-section.tsx b/components/animated-stats-section.tsx
new file mode 100644
index 0000000..fbabc76
--- /dev/null
+++ b/components/animated-stats-section.tsx
@@ -0,0 +1,105 @@
+"use client";
+
+import { Package, Users, CreditCard } from "lucide-react";
+import { AnimatedCounter } from "./animated-counter";
+import { TextTyper } from "./text-typer";
+import { PlatformStats } from "@/lib/stats-service";
+
+const formatCurrency = (value: number) => {
+ return new Intl.NumberFormat('en-GB', {
+ style: 'currency',
+ currency: 'GBP',
+ minimumFractionDigits: 0,
+ }).format(value);
+};
+
+interface AnimatedStatsProps {
+ stats: PlatformStats;
+}
+
+export function AnimatedStatsSection({ stats }: AnimatedStatsProps) {
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/components/text-typer.tsx b/components/text-typer.tsx
new file mode 100644
index 0000000..329fc46
--- /dev/null
+++ b/components/text-typer.tsx
@@ -0,0 +1,87 @@
+"use client";
+
+import { useState, useEffect, useRef } from "react";
+
+interface TextTyperProps {
+ text: string;
+ typingSpeed?: number;
+ delay?: number;
+ className?: string;
+ cursor?: boolean;
+ onComplete?: () => void;
+}
+
+export function TextTyper({
+ text,
+ typingSpeed = 50,
+ delay = 0,
+ className = "",
+ cursor = true,
+ onComplete
+}: TextTyperProps) {
+ // Hide component if text is empty
+ if (!text) return null;
+
+ const [displayedText, setDisplayedText] = useState("");
+ const [cursorVisible, setCursorVisible] = useState(true);
+ const [isComplete, setIsComplete] = useState(false);
+ const timeoutRef = useRef(null);
+ const cursorIntervalRef = useRef(null);
+
+ useEffect(() => {
+ // Clear any previous text
+ setDisplayedText("");
+ setIsComplete(false);
+
+ // Reset typing when text changes
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current);
+ }
+
+ // Start typing after delay
+ const startTypingTimeout = setTimeout(() => {
+ let currentIndex = 0;
+
+ const typeNextChar = () => {
+ if (currentIndex < text.length) {
+ setDisplayedText(text.substring(0, currentIndex + 1));
+ currentIndex++;
+ timeoutRef.current = setTimeout(typeNextChar, typingSpeed);
+ } else {
+ setIsComplete(true);
+ if (onComplete) {
+ onComplete();
+ }
+ }
+ };
+
+ typeNextChar();
+ }, delay);
+
+ // Store the start timeout
+ timeoutRef.current = startTypingTimeout;
+
+ // Cursor blinking effect
+ if (cursor) {
+ cursorIntervalRef.current = setInterval(() => {
+ setCursorVisible(prev => !prev);
+ }, 500);
+ }
+
+ return () => {
+ if (timeoutRef.current) {
+ clearTimeout(timeoutRef.current);
+ }
+ if (cursorIntervalRef.current) {
+ clearInterval(cursorIntervalRef.current);
+ }
+ };
+ }, [text, typingSpeed, delay, cursor, onComplete]);
+
+ return (
+
+ {displayedText}
+ {cursor && !isComplete && cursorVisible && |}
+
+ );
+}
\ No newline at end of file
diff --git a/lib/stats-service.ts b/lib/stats-service.ts
index d2dac03..0ebf82d 100644
--- a/lib/stats-service.ts
+++ b/lib/stats-service.ts
@@ -14,6 +14,8 @@ export interface PlatformStats {
export async function fetchPlatformStats(): Promise {
const BASE_API_URL = process.env.SERVER_API_URL || 'http://localhost:3001/api';
+ console.log('Fetching platform stats from:', BASE_API_URL);
+
try {
const response = await fetch(`${BASE_API_URL}/stats/platform`, {
method: 'GET',
@@ -27,7 +29,9 @@ export async function fetchPlatformStats(): Promise {
throw new Error(`API error: ${response.status}`);
}
- return await response.json();
+ const data = await response.json();
+ console.log('Fetched stats:', data);
+ return data;
} catch (error) {
console.error('Error fetching platform stats:', error);
// Return fallback data if API fails