From 35fc65f3de9dc02f92cc393372dc3bc55a93ebd8 Mon Sep 17 00:00:00 2001 From: "sewmina7@gmail.com" Date: Sun, 14 Jul 2024 17:52:18 +0530 Subject: [PATCH] profiles done --- app/layout.tsx | 2 +- app/page.tsx | 2 +- app/users/[id]/page.tsx | 391 ++++++++++++++++++++----------------- app/users/page.tsx | 9 +- components/CalloutCard.tsx | 49 +++++ components/Header.tsx | 5 +- components/ShareModal.tsx | 60 ++++++ 7 files changed, 332 insertions(+), 186 deletions(-) create mode 100644 components/CalloutCard.tsx create mode 100644 components/ShareModal.tsx diff --git a/app/layout.tsx b/app/layout.tsx index bc15d61..0f01571 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -5,7 +5,7 @@ import "./globals.css"; const inter = Inter({ subsets: ["latin"] }); export const metadata: Metadata = { - title: "CallFi Dashboard", + title: "CallFi", description: "Call out next big mover and win!", }; diff --git a/app/page.tsx b/app/page.tsx index 419f347..3022ed4 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -276,6 +276,6 @@ export default function App() { return ( - + ); } diff --git a/app/users/[id]/page.tsx b/app/users/[id]/page.tsx index 9dc07b0..7dec062 100644 --- a/app/users/[id]/page.tsx +++ b/app/users/[id]/page.tsx @@ -1,140 +1,208 @@ "use client"; import React, { useEffect, useState } from 'react'; +import axios from 'axios'; import Header from '@/components/Header'; import Footer from '@/components/Footer'; -import Head from 'next/head' - import UserDetailModal from '@/components/UserDetailsModal'; import { motion } from 'framer-motion'; import CustomHeader from '@/components/CustomHeader'; -import { FaArrowDown, FaArrowUp, FaIcons, FaShare } from 'react-icons/fa'; +import { FaArrowDown, FaArrowUp, FaShare } from 'react-icons/fa'; import { FaArrowLeft } from 'react-icons/fa6'; import { NextSeo } from 'next-seo'; +import CalloutCard from '@/components/CalloutCard'; +import { PrivyProvider, usePrivy } from '@privy-io/react-auth'; +import ShareModal from '@/components/ShareModal'; +import Link from 'next/link'; -interface UserDetail { - tag: string; - img_url: string; - email: string; - points: string; - joined_date: string; - calloutCount: number; - // Add more fields as necessary -} +function UserPage({ params }: { params: { id: string } }) { + const { login, user, ready, logout, linkTwitter, unlinkTwitter, linkWallet, unlinkWallet } = usePrivy(); -interface Callout { - price_at_creation: string; - froze_price: string; - gains: string; - ca: string; - id: string; - icon_url: string; -} - -export default function UserPage({ params }: { params: { id: string } }) { - const [userDetail, setUserDetail] = useState(null); - const [callouts, setCallouts] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); const [activeSelected, setActiveSelected] = useState(true); const [expandedInfo, setExpandedInfo] = useState(false); - const [weekSelected, SetWeekSelected] = useState(true); - const [allTimeSelected, SetAllTimeSelected] = useState(true); - - + const [selectedPeriod, setSelectedPeriod] = useState("all time"); + const [userData, setUserData] = useState(null); + const [callouts, setCallouts] = useState([]); + const [history, setHistory] = useState([]); + const [loginAlert, setLoginAlert] = useState(null); + const [dexUrls, setDexUrls] = useState<{ [key: string]: string }>({}); + const [isShareModalOpen, setIsShareModalOpen] = useState(false); + const [isFollowing, setIsFollowing] = useState(false); + const [isFetchingFollowStatus, setIsFetchingFollowStatus] = useState(true); + const id = params.id; + const currentUser = "%40"+user?.twitter?.username ?? "null"; // Change this to the current user dynamically useEffect(() => { - const fetchUserDetail = async () => { - if (!id) return; - - try { - const response = await fetch(`https://api.callfi.io/get_user_data.php?username=${id}`); - if (!response.ok) { - throw new Error('Network response was not ok'); - } - const data = await response.json(); - setUserDetail(data); - } catch (error: any) { - setError(error.message); - } finally { - setLoading(false); - } - }; - - fetchUserDetail(); + Refresh(); }, [id]); useEffect(() => { - const fetchCalloutHistory = async () => { + const fetchCallouts = async () => { + let apiUrl = `https://api.callfi.io/get_user_callouts.php?tag=${id}`; + if (selectedPeriod === "month") { + apiUrl = `https://api.callfi.io/get_user_callouts_monthly.php?tag=${id}`; + } else if (selectedPeriod === "week") { + apiUrl = `https://api.callfi.io/get_user_callouts_weekly.php?tag=${id}`; + } + try { - const response = await fetch(`https://api.callfi.io/get_callouts_history.php?username=${id}&period=${weekSelected ? 'week' : "month"}`); - if (!response.ok) { - throw new Error('Network response was not ok'); - } + const response = await fetch(apiUrl); const data = await response.json(); setCallouts(data); - } catch (error: any) { - setError(error.message); + + // Fetch Dexscreener URLs for each callout + const urls: { [key: string]: string } = {}; + await Promise.all(data.map(async (detail: any) => { + try { + const response = await axios.get(`https://api.dexscreener.com/latest/dex/tokens/${detail.ca}`); + if (response.data && response.data.pairs && response.data.pairs.length > 0) { + urls[detail.ca] = response.data.pairs[0].url; + } + } catch (error) { + console.error(`Error fetching Dexscreener URL for ${detail.ca}:`, error); + } + })); + setDexUrls(urls); + } catch (error) { + console.error('Error fetching callouts:', error); } }; - fetchCalloutHistory(); - }, [id]); + fetchCallouts(); + }, [id, selectedPeriod]); - const formatDate = (dateString: string) => { - const date = new Date(dateString); - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - return `${year}-${month}-${day}`; + useEffect(() => { + const fetchHistory = async () => { + let apiUrl = `https://api.callfi.io/get_callouts_history.php?username=${id}&period=all time`; + if (selectedPeriod === "month") { + apiUrl = `https://api.callfi.io/get_callouts_history.php?username=${id}&period=month`; + } else if (selectedPeriod === "week") { + apiUrl = `https://api.callfi.io/get_callouts_history.php?username=${id}&period=week`; + } + + try { + const response = await fetch(apiUrl); + const data = await response.json(); + setHistory(data); + } catch (error) { + console.error('Error fetching history:', error); + } + }; + + fetchHistory(); + }, [id, selectedPeriod]); + + useEffect(() => { + Refresh(); + }, [currentUser, id]); + + function Refresh(){ + const fetchFollowStatus = async () => { + try { + const response = await fetch(`https://api.callfi.io/get_is_following.php?username=${currentUser}&target=${id}`); + const data = await response.json(); + setIsFollowing(data == "1"); + } catch (error) { + console.error('Error fetching follow status:', error); + } finally { + setIsFetchingFollowStatus(false); + } + }; + + fetchFollowStatus(); + const fetchUserData = async () => { + try { + const response = await fetch(`https://api.callfi.io/get_user_data.php?username=${id}`); + const data = await response.json(); + setUserData(data); + } catch (error) { + console.error('Error fetching user data:', error); + } + }; + + fetchUserData(); + } + + const handleFollowClick = async () => { + if (!ready || !user) { + setLoginAlert("You need to be logged in to follow."); + setTimeout(() => setLoginAlert(null), 3000); + } else { + try { + const response = await fetch(`https://api.callfi.io/${isFollowing ? "unfollow" : "follow"}_user.php?username=${currentUser}&target=${id}`); + const data = await response.json(); + Refresh(); + } catch (error) { + console.error('Error following user:', error); + } + } }; + if (!userData) { + return
Loading...
; + } + + const truncateAddress = (address: string) => { + return `${address.slice(0, 6)}...${address.slice(-5)}`; + }; + + const handleShareClick = () => { + setIsShareModalOpen(true); + }; return ( - <> - +
- - + +

CallFi Profile

{`${userDetail?.tag}'s -
+
-

{userDetail?.tag}

-

500x Gains

-

50 Points

-

10 Followers

+

{userData.tag}

+

{userData.gains.toFixed(2)}x Gains

+

{(userData.points * 100).toFixed(2)} Points

+

{userData.followerCount} Followers

-

150 Callouts

-

75% Accuracy

-

200 Days

+

{userData.calloutCount} Callouts

+

{parseFloat(userData.accuracy).toFixed(1)}% Accuracy

+

{userData.daysSinceJoined} Days

-
- {expandedInfo ? () : ()} + {expandedInfo ? ( + + ) : ( + + )}
- - + +
+ {loginAlert &&

{loginAlert}

}
-
- {/* Header Ends */} -
-
- - -
-
-
-
-
-
- -
-
- COC -
-

- 0x22...e3caf -

-
- -
-

{"$19.15 => $100"}

-

{"100%"}

-
-
-
- -
-
-
-
- -
@@ -200,66 +232,67 @@ export default function UserPage({ params }: { params: { id: string } }) {
+
+ {callouts.map((callout) => ( + + ))} +
+ +
+
+
+
+ + +
+
+
+
+ +
+ {history.map((entry) => ( + + ))} +
+
-
+ setIsShareModalOpen(false)} + shareLink={window.location.href} // Pass the current URL to the ShareModal + /> ); - - // return ( - //
- //
- //
- // {loading ? ( - //

Loading...

- // ) : error ? ( - //

Error: {error}

- // ) : userDetail ? ( - //
- //
- // {`${userDetail.tag}'s - //

{userDetail.tag}

- //

Joined: {formatDate(userDetail.joined_date)}

- //

Callout count: {userDetail.calloutCount}

- //
- //
- //
- // {periods.map((period) => ( - // - // ))} - //
- // {callouts.map((callout) => ( - //
- //
- // Coin Icon - //
- //

{callout.id}

- //

{`$${callout.price_at_creation} => $${callout.froze_price}`}

- //
- //
- //

{`${callout.gains}%`}

- //
- //
- //
- // ))} - //
- //
- // ) : ( - //

User not found

- // )} - //
- //
- //
- // ); } + +export default function WrappedUserPage(props) { + return ( + + + + ); +} \ No newline at end of file diff --git a/app/users/page.tsx b/app/users/page.tsx index 6a7e7b1..90af795 100644 --- a/app/users/page.tsx +++ b/app/users/page.tsx @@ -5,6 +5,7 @@ import { motion } from 'framer-motion'; import Link from 'next/link'; import Header from '@/components/Header'; import Footer from '@/components/Footer'; +import { PrivyProvider } from '@privy-io/react-auth'; interface User { username: string; @@ -82,4 +83,10 @@ const Page: React.FC = () => { ); }; -export default Page; +export default function WrappedUsersPage(props) { + return ( + + + + ); +} diff --git a/components/CalloutCard.tsx b/components/CalloutCard.tsx new file mode 100644 index 0000000..696cebc --- /dev/null +++ b/components/CalloutCard.tsx @@ -0,0 +1,49 @@ +import React from 'react'; + +interface CalloutCardProps { + iconUrl: string; + token: string; + ca: string; + priceAtCreation: number; + priceNow: number; + gains: number; + dexUrl: string; +} + +const CalloutCard: React.FC = ({ + iconUrl, + token, + ca, + priceAtCreation, + priceNow, + gains, + dexUrl +}) => { + const truncateAddress = (address: string) => { + return `${address.slice(0, 6)}...${address.slice(-5)}`; + }; + + return ( + +
+ +
+
+ {token} +
+

+ {truncateAddress(ca)} +

+
+
+

{`$${priceAtCreation} => $${priceNow}`}

+

0 ? 'text-green-700' : 'text-red-700'}`}>{`${(gains * 100).toFixed(2)}%`}

+
+
+
+ ); +}; + +export default CalloutCard; diff --git a/components/Header.tsx b/components/Header.tsx index b44ce15..4185b66 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -44,11 +44,8 @@ const Header: React.FC = () => { return (
-

CallFi

+

CallFi