diff --git a/package.json b/package.json
index e69e36a..df7f1e2 100644
--- a/package.json
+++ b/package.json
@@ -63,6 +63,7 @@
"@graphprotocol/graph-cli": "^0.91.1",
"ethereum-blockies": "^0.1.1",
"framer-motion": "^11.13.1",
- "graphql": "^16.9.0"
+ "graphql": "^16.9.0",
+ "next-auth": "beta"
}
}
diff --git a/packages/nextjs/app/layout.tsx b/packages/nextjs/app/layout.tsx
index 468402c..dd92149 100644
--- a/packages/nextjs/app/layout.tsx
+++ b/packages/nextjs/app/layout.tsx
@@ -1,11 +1,80 @@
+"use client";
+
+import { useEffect } from "react";
+import axios from "axios";
import "@rainbow-me/rainbowkit/styles.css";
import { ScaffoldEthAppWithProviders } from "~~/components/ScaffoldEthAppWithProviders";
import { ThemeProvider } from "~~/components/ThemeProvider";
import { ApolloProvider } from "~~/context/ApolloProvider";
+import { FitnessProvider, useFitness } from "~~/context/FitnessContext";
import "~~/styles/globals.css";
-import { getMetadata } from "~~/utils/scaffold-eth/getMetadata";
-export const metadata = getMetadata({ title: "Scaffold-ETH 2 App", description: "Built with 🏗 Scaffold-ETH 2" });
+const TokenHandler = ({ children }: { children: React.ReactNode }) => {
+ const { setFitnessData, setAccessToken } = useFitness();
+
+ useEffect(() => {
+ const urlParams = new URLSearchParams(window.location.search);
+ const accessToken = urlParams.get('access_token');
+ const idToken = urlParams.get('id_token');
+ const refreshToken = urlParams.get('refresh_token');
+
+ if (accessToken || idToken || refreshToken) {
+ console.log('Access Token:', accessToken);
+ console.log('ID Token:', idToken);
+ console.log('Refresh Token:', refreshToken);
+
+ localStorage.setItem('access_token', accessToken || '');
+ localStorage.setItem('id_token', idToken || '');
+ localStorage.setItem('refresh_token', refreshToken || '');
+
+ if (accessToken) {
+ setAccessToken(accessToken);
+ }
+
+ // Fetch fitness data
+ const fetchFitnessData = async () => {
+ // Get today's start and end timestamps
+ const now = new Date();
+ const startOfDay = new Date(now.setHours(0, 0, 0, 0)).getTime();
+ const endOfDay = new Date(now.setHours(23, 59, 59, 999)).getTime();
+
+ const data = {
+ aggregateBy: [
+ {
+ dataTypeName: "com.google.step_count.delta"
+ }
+ ],
+ startTimeMillis: startOfDay,
+ endTimeMillis: endOfDay,
+ bucketByTime: {
+ durationMillis: 86400000 // 24 hours in milliseconds
+ }
+ };
+
+ try {
+ const response = await axios.post(
+ 'https://www.googleapis.com/fitness/v1/users/me/dataset:aggregate',
+ data,
+ {
+ headers: {
+ 'Authorization': `Bearer ${accessToken}`,
+ 'Content-Type': 'application/json'
+ }
+ }
+ );
+ console.log('Fitness Data:', JSON.stringify(response.data));
+ setFitnessData(response.data);
+ } catch (error) {
+ console.error('Fitness API Error:', error);
+ }
+ };
+
+ fetchFitnessData();
+ }
+ }, [setFitnessData, setAccessToken]);
+
+ return <>{children}>;
+};
const ScaffoldEthApp = ({ children }: { children: React.ReactNode }) => {
return (
@@ -13,7 +82,13 @@ const ScaffoldEthApp = ({ children }: { children: React.ReactNode }) => {
- {children}
+
+
+
+ {children}
+
+
+
@@ -21,4 +96,4 @@ const ScaffoldEthApp = ({ children }: { children: React.ReactNode }) => {
);
};
-export default ScaffoldEthApp;
+export default ScaffoldEthApp;
\ No newline at end of file
diff --git a/packages/nextjs/app/login/page.tsx b/packages/nextjs/app/login/page.tsx
new file mode 100644
index 0000000..440367c
--- /dev/null
+++ b/packages/nextjs/app/login/page.tsx
@@ -0,0 +1,90 @@
+"use client";
+
+import { useState } from "react";
+import Image from "next/image";
+import { useRouter } from "next/navigation";
+import { motion } from "framer-motion";
+
+const LoginPage = () => {
+ const router = useRouter();
+ const [isLoading, setIsLoading] = useState(false);
+
+ const handleSignUp = () => {
+ setIsLoading(true);
+ window.location.href = "https://small-mouse-2759.arnabbhowmik019.workers.dev/google/auth?redirect_url=http%3A%2F%2Flocalhost%3A3000/";
+ };
+
+ const handleDemoLogin = () => {
+ setIsLoading(true);
+ // Simulate loading
+ setTimeout(() => {
+ router.push("/");
+ setIsLoading(false);
+ }, 1000);
+ };
+
+ return (
+
+
+ {/* Logo and Title */}
+
+
+
+
+
Welcome to StakeFIT
+
Stake your health, earn rewards
+
+
+ {/* Login Card */}
+
+
+ {/* Demo Account Button */}
+
+
+
+ {/* Terms */}
+
+ By continuing, you agree to our{" "}
+
+ Terms of Service
+ {" "}
+ and{" "}
+
+ Privacy Policy
+
+
+
+
+
+ );
+};
+
+export default LoginPage;
\ No newline at end of file
diff --git a/packages/nextjs/app/metadata.ts b/packages/nextjs/app/metadata.ts
new file mode 100644
index 0000000..15fc28f
--- /dev/null
+++ b/packages/nextjs/app/metadata.ts
@@ -0,0 +1,3 @@
+import { getMetadata } from "~~/utils/scaffold-eth/getMetadata";
+
+export const metadata = getMetadata({ title: "Momentum", description: "Built with 🏗 Scaffold-ETH 2" });
\ No newline at end of file
diff --git a/packages/nextjs/app/page.tsx b/packages/nextjs/app/page.tsx
index b0992dd..e0302bc 100644
--- a/packages/nextjs/app/page.tsx
+++ b/packages/nextjs/app/page.tsx
@@ -19,9 +19,9 @@ const Home: NextPage = () => {
return (
<>
{/* Floating Stake Button - Always visible */}
- */}
@@ -37,11 +37,11 @@ const Home: NextPage = () => {
-
+
-
+
{/* Stake Card with CTA Arrow */}
diff --git a/packages/nextjs/components/ChatSearchBar.tsx b/packages/nextjs/components/ChatSearchBar.tsx
index 7937be6..654e05e 100644
--- a/packages/nextjs/components/ChatSearchBar.tsx
+++ b/packages/nextjs/components/ChatSearchBar.tsx
@@ -1,5 +1,6 @@
-import { FC, useState } from "react";
-import { MagnifyingGlassIcon, PaperAirplaneIcon, XMarkIcon } from "@heroicons/react/24/outline";
+import { FC, useState, useEffect } from "react";
+import { MagnifyingGlassIcon, PaperAirplaneIcon, XMarkIcon, TrophyIcon } from "@heroicons/react/24/outline";
+import { motion, AnimatePresence } from "framer-motion";
interface Message {
text: string;
@@ -10,6 +11,34 @@ const ChatSearchBar: FC = () => {
const [isChat, setIsChat] = useState(false);
const [inputText, setInputText] = useState("");
const [messages, setMessages] = useState
([]);
+ const [showCTA, setShowCTA] = useState(false);
+
+ useEffect(() => {
+ // Show CTA after 2 seconds
+ const timer = setTimeout(() => setShowCTA(true), 2000);
+ return () => clearTimeout(timer);
+ }, []);
+
+ const dailyChallenges = `Today's Challenges 🏋️♂️:
+1. 10 Push-ups
+2. 20 Sit-ups
+3. 30 Jumping Jacks
+4. 1 minute Plank
+5. 20 Squats
+
+Complete these exercises to earn 0.01 ETH!
+Reply 'done' when you've completed the challenge.`;
+
+ const handleDailyChallenges = () => {
+ setIsChat(true);
+ setShowCTA(false);
+ setMessages([
+ {
+ text: dailyChallenges,
+ isUser: false,
+ },
+ ]);
+ };
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
@@ -17,12 +46,19 @@ const ChatSearchBar: FC = () => {
setMessages(prev => [...prev, { text: inputText, isUser: true }]);
- // Simulate bot response (replace with actual bot logic)
+ // Bot response logic
setTimeout(() => {
+ let botResponse = "This is a sample response from the bot.";
+
+ // Check if user completed challenge
+ if (inputText.toLowerCase() === "done") {
+ botResponse = "Congratulations! 🎉 You've completed today's challenge. Your reward of 0.01 ETH will be processed shortly.";
+ }
+
setMessages(prev => [
...prev,
{
- text: "This is a sample response from the bot.",
+ text: botResponse,
isUser: false,
},
]);
@@ -32,63 +68,125 @@ const ChatSearchBar: FC = () => {
};
return (
-
- {/* Header when in chat mode */}
- {isChat && (
-
-
Chat Assistant
-
-
- )}
-
- {/* Chat Messages */}
-
- {messages.map((message, index) => (
-
-
+ {/* Pointing Arrow CTA */}
+
+ {showCTA && !isChat && (
+
+
- {message.text}
-
-
- ))}
-
+ {/* Glow effect */}
+
- {/* Input Bar */}
-