diff --git a/package-lock.json b/package-lock.json index 471fb08..c259a4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "eslint-config-next": "15.5.4", "jsdom": "^27.4.0", "tailwindcss": "^4", - "typescript": "5.9.3", + "typescript": "^5", "vitest": "^4.0.16" } }, diff --git a/public/preview_image.png b/public/preview_image.png new file mode 100644 index 0000000..3f0b841 Binary files /dev/null and b/public/preview_image.png differ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9b66a15..0c190c6 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -7,6 +7,8 @@ import "./globals.css"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { + metadataBase: new URL('https://www.browseping.com'), + title: "BrowsePing - Socialize Your Browsing Experience", description: "Transform your solitary browsing into a vibrant social experience. Connect with friends, share your digital presence, and discover what's capturing everyone's attention across the web.", @@ -14,7 +16,31 @@ export const metadata: Metadata = { authors: [{ name: "BrowsePing" }], icons: { icon: "/browseping.svg", - } + }, + + openGraph: { + title: "BrowsePing - Socialize Your Browsing Experience", + description: "Transform your solitary browsing into a vibrant social experience. Connect with friends, share your digital presence, and discover what's capturing everyone's attention across the web.", + url: 'https://www.browseping.com', + siteName: 'BrowsePing', + images: [ + { + url: '/preview_image.png', + width: 1200, + height: 630, + alt: 'BrowsePing - Open Source Browser Extension', + }, + ], + type: 'website', + }, + + // Twitter Card + twitter: { + card: 'summary_large_image', + title: "BrowsePing - Socialize Your Browsing Experience", + description: "Transform your solitary browsing into a vibrant social experience. Connect with friends, share your digital presence, and discover what's capturing everyone's attention across the web.", + images: ['/preview_image.png'], + }, }; export const viewport: Viewport = { diff --git a/src/components/home/FeaturesSection.tsx b/src/components/home/FeaturesSection.tsx index c82fbe5..353e37a 100644 --- a/src/components/home/FeaturesSection.tsx +++ b/src/components/home/FeaturesSection.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState ,useCallback} from 'react'; import Image from 'next/image'; import { FiUsers, FiBarChart, FiShield, FiMessageCircle, FiGithub, FiClock, FiBell, FiWifi, FiCode, FiChevronLeft, FiChevronRight, FiZap } from 'react-icons/fi'; import { FaTrophy } from 'react-icons/fa'; @@ -102,31 +102,46 @@ const FeaturesSection = () => { benefits: ['Automatic tracking', 'Digital wellness insights', 'Time optimization'] } ]; + - useEffect(() => { - intervalRef.current = setInterval(() => { - setCurrentIndex((prev) => (prev + 1) % features.length); - }, 4000); +const startAutoScroll = useCallback(() => { + if (intervalRef.current) { + clearInterval(intervalRef.current); + } - return () => { - if (intervalRef.current) { - clearInterval(intervalRef.current); - } - }; - }, [features.length]); - - const nextSlide = () => { + intervalRef.current = setInterval(() => { setCurrentIndex((prev) => (prev + 1) % features.length); + }, 10000); +}, [features.length]); + + +useEffect(() => { + startAutoScroll(); + + return () => { + if (intervalRef.current) { + clearInterval(intervalRef.current); + } }; +}, [startAutoScroll]); + + + const nextSlide = () => { + setCurrentIndex((prev) => (prev + 1) % features.length); + startAutoScroll(); +}; + const prevSlide = () => { - setCurrentIndex((prev) => (prev - 1 + features.length) % features.length); - }; + setCurrentIndex((prev) => (prev - 1 + features.length) % features.length); + startAutoScroll(); +}; - const goToSlide = (index: number) => { - setCurrentIndex(index); - }; + const goToSlide = (index: number) => { + setCurrentIndex(index); + startAutoScroll(); +}; return (
{/* Background effects */} diff --git a/src/components/leaderboard/PublicLeaderboard.tsx b/src/components/leaderboard/PublicLeaderboard.tsx index 077ecbf..d00020e 100644 --- a/src/components/leaderboard/PublicLeaderboard.tsx +++ b/src/components/leaderboard/PublicLeaderboard.tsx @@ -28,10 +28,8 @@ const PublicLeaderboard = () => { try { setLoading(true); setError(null); - const apiUrl = process.env.NEXT_PUBLIC_API_URL; const url = `${apiUrl}/api/leaderboard/public-top`; - const response = await fetch(url, { method: 'GET', headers: { @@ -44,7 +42,7 @@ const PublicLeaderboard = () => { } const result = await response.json(); - + if (result.success) { setData(result.data); } else { @@ -167,69 +165,69 @@ const PublicLeaderboard = () => { ) : ( <> - {/* Header */} -
-
-
Rank
-
User
-
Monthly Time
-
Total Time
-
-
- - {/* Leaderboard entries */} -
- {data.leaderboard.map((user) => ( -
-
- {/* Rank */} -
-
- {user.rank <= 3 ? getRankIcon(user.rank) : user.rank} -
-
- - {/* User */} -
-
-
- + {/* Scrollable Leaderboard Container */} +
+
+ {/* Header */} +
+
+
Rank
+
User
+
Monthly Time
+
Total Time
+
+
+ {/* Leaderboard entries */} +
+ {data.leaderboard.map((user) => ( +
+
+ {/* Rank */} +
+
+ {user.rank <= 3 ? getRankIcon(user.rank) : user.rank} +
-
-
- {user.displayName || user.username} + {/* User */} +
+
+
+ +
+
+
+ {user.displayName || user.username} +
+ {user.displayName && ( +
@{user.username}
+ )} +
- {user.displayName && ( -
@{user.username}
- )} +
+ {/* Monthly Time */} +
+
+ + + {formatHours(user.monthlyHours)} + +
+
+ {/* Total Time */} +
+ + {formatHours(user.totalOnlineHours)} +
- - {/* Monthly Time */} -
-
- - - {formatHours(user.monthlyHours)} - -
-
- - {/* Total Time */} -
- - {formatHours(user.totalOnlineHours)} - -
-
+ ))}
- ))} +
- {/* Footer */} {data.totalUsers > 0 && (
@@ -246,4 +244,4 @@ const PublicLeaderboard = () => { ); }; -export default PublicLeaderboard; \ No newline at end of file +export default PublicLeaderboard;