commit 8be37d3e924c91574e507dba4edca6213a45fa9a Author: Arkaprabha Chakraborty Date: Sun Apr 5 00:43:23 2026 +0530 init diff --git a/dmtp/README.md b/dmtp/README.md new file mode 100644 index 0000000..f1cbf63 --- /dev/null +++ b/dmtp/README.md @@ -0,0 +1,381 @@ +# 🪙 D.M.T.P — Agentic AI-Verified Micro-Task Platform on Celo Blockchain + +An **AI-powered decentralized task Platform** built on **Celo Sepolia Testnet**, where requesters post micro-tasks, workers complete them, AI verifies the results, and **payments are automatically released in cUSD** upon approval. + +--- + +## 📋 Table of Contents + +- [Overview](#-overview) +- [Tech Stack](#️-tech-stack) +- [AI Integration](#-ai-integration-google-gemini-15-pro) +- [Database Schema](#️-database-schema-core-entities) +- [Folder Structure](#-folder-structure) +- [Setup Guide](#️-setup-guide) +- [Smart Contract Deployment](#-smart-contract-deployment) +- [Workflow](#-workflow) +- [API Examples](#-example-api-calls) +- [Architecture](#-architecture-diagram) +- [Features](#-features-checklist) +- [Testing](#-testing) +- [Deployment](#-deployment) +- [Future Roadmap](#-future-roadmap) +- [License](#-license) + +--- + +## ⚡ Overview + +**D.M.T.P** introduces verifiable trust between micro-task requesters and workers. AI moderation (powered by **Google Gemini**) ensures submissions are **authentic and high-quality**, while the **TaskEscrow smart contract** on **Celo** guarantees transparent, secure on-chain payments. + +### Key Features + +- 🤖 **AI-Powered Verification** — Automated content moderation using Google Gemini +- ⛓️ **Blockchain Escrow** — Smart contract-based payment security +- 💰 **Instant Payments** — Automatic cUSD release upon task approval +- 🔐 **Wallet Authentication** — Secure login via MetaMask or MiniPay +- 📊 **Real-Time Updates** — Live task and submission status tracking +- 🎯 **Quality Control** — AI prevents spam, fraud, and low-effort submissions + +--- + +## 🛠️ Tech Stack + +### 🖥️ Frontend — Next.js (App Router) + +| Feature | Library/Framework | +| ------------------ | --------------------------------------------------- | +| UI Components | [shadcn/ui](https://ui.shadcn.com) | +| Styling | [TailwindCSS](https://tailwindcss.com) | +| State Management | [Zustand](https://zustand-demo.pmnd.rs) | +| Data Fetching | [TanStack Query](https://tanstack.com/query/v5) | +| Wallet Integration | [wagmi](https://wagmi.sh) + [viem](https://viem.sh) | +| Blockchain SDK | [@celo/contractkit](https://docs.celo.org/) | +| Wallets Supported | **MiniPay** and **MetaMask** | +| AI Moderation | [Google Gemini 1.5](https://ai.google.dev/gemini-api/) | + +### ⚙️ Backend — Express.js + TypeScript + +| Feature | Technology | +| ----------------- | ------------------------------------------ | +| Framework | Express.js | +| Database | PostgreSQL + Prisma ORM | +| Job Queue | Bull + Redis | +| AI Verification | Gemini API | +| Blockchain | Celo Sepolia | +| Authentication | Wallet Signature (EIP-191) | +| File Verification | cUSD Escrow via TaskEscrow.sol | +| Notifications | Background service + WebSocket placeholder | + +### ⛓️ Blockchain — Celo Sepolia Testnet + +- **Smart Contract:** `TaskEscrow.sol` + - Holds task payments in escrow + - Releases funds when AI-verified + - Refunds requester if submissions are rejected +- **Token:** `cUSD` (Stablecoin) +- **Network RPC:** https://forno.celo-sepolia.celo-testnet.org +- **Explorer:** [CeloScan (Sepolia)](https://sepolia.celoscan.io) + +--- + +## 🤖 AI Integration (Google Gemini 2.5 Pro) + +Used for: + +- ✅ Spam, fraud, and duplicate prevention +- ✅ Toxic or low-effort content rejection +- ✅ Criteria-based submission scoring + +Gemini runs asynchronously in a **Bull Queue worker**, sending results via webhook to approve or reject submissions. + +--- + +## 🗄️ Database Schema (Core Entities) + +| Table | Description | +| ----------------------- | ---------------------------------------------------------------------------------- | +| **users** | Stores wallet addresses, roles (`requester` / `worker`), reputation & earnings | +| **tasks** | Contains task metadata, blockchain taskID, payment amount, expiry | +| **submissions** | Tracks worker submissions, AI verification results | +| **payments** | Logs payment releases (+txHash) | +| **notifications** | In-app notifications for verification or payment updates | + +--- + +## 💎 Folder Structure + +``` +D.M.T.P/ +├── client/ # Next.js frontend +│ ├── app/ # App Router pages +│ ├── components/ # shadcn + custom UI +│ ├── hooks/ # Zustand + wagmi hooks +│ ├── lib/ # API client + Celo utils +│ └── types/ # Shared TypeScript models +│ +└── server/ # Express backend + ├── src/ + │ ├── routes/ # /api/v1 tasks, submissions, users + │ ├── controllers/ # Request handlers + │ ├── services/ # AI, blockchain, queue, moderation + │ ├── workers/ # Bull verification worker + │ └── database/ # Prisma schema + migrations + └── prisma/ +``` + +--- + +## ⚙️ Setup Guide + +### Prerequisites + +- ✅ Node.js >= 20 +- ✅ npm >= 9 +- ✅ Redis (running locally or hosted) +- ✅ PostgreSQL database +- ✅ Celo wallet with test cUSD + +### 1️⃣ Environment Variables + +#### `.env` (Backend) + +```env +# Server +PORT=3001 +NODE_ENV=development + +# Database +DATABASE_URL="postgresql://user:password@localhost:5432/D.M.T.P" + +# Blockchain +PRIVATE_KEY=YOUR_PRIVATE_KEY_WITH_CUSD +CELO_RPC_URL=https://forno.celo-sepolia.celo-testnet.org +CONTRACT_ADDRESS=0xYourTaskEscrowAddress +CUSD_SEPOLIA_ADDRESS=0x874069fa1eb16d44d622f2e0ca25eea172369bc1 + +# AI (Gemini) +GEMINI_API_KEY=your_google_gemini_api_key + +# Redis +REDIS_HOST=localhost +REDIS_PORT=6379 +``` + +#### `.env.local` (Frontend) + +```env +NEXT_PUBLIC_API_URL=http://localhost:3001 +NEXT_PUBLIC_CELO_RPC_URL=https://forno.celo-sepolia.celo-testnet.org +NEXT_PUBLIC_CUSD_ADDRESS=0x874069fa1eb16d44d622f2e0ca25eea172369bc1 +NEXT_PUBLIC_CONTRACT_ADDRESS=0xYourTaskEscrowAddress +NEXT_PUBLIC_CHAIN_ID=44787 +``` + +### 2️⃣ Backend Setup + +```bash +cd server +npm install + +# Prisma setup + migrate +npx prisma generate +npx prisma db push + +# Start Redis (using Docker) +docker run -d -p 6379:6379 redis:alpine + +# Start backend in dev mode +npm run dev +``` + +### 3️⃣ Frontend Setup + +```bash +cd client +npm install +npm run dev +``` + +Visit → [http://localhost:3000](http://localhost:3000) + +--- + +## 💰 Smart Contract Deployment + +### Our Deployed Smart Contract- [0xa520d207c91C0FE0e9cFe8D63AbE02fd18B2254e](https://sepolia.celoscan.io/address/0xa520d207c91c0fe0e9cfe8d63abe02fd18b2254e) +Deploy `TaskEscrow.sol` on **Celo Sepolia** using Remix or Hardhat. + +### Compile & Deploy + +```bash +npx hardhat run scripts/deploy.ts --network celo-sepolia +``` + +### Verify Contract + +```bash +npx hardhat verify --network celo-sepolia 0xYourContractAddress "0x874069fa1eb16d44d622f2e0ca25eea172369bc1" +``` + +--- + +## 🧠 Workflow + +### ✳️ Requester Flow + +1. Connect wallet → Create Task +2. Payment locked in smart contract +3. Task visible to workers + +### 🛠️ Worker Flow + +1. Accept Task → Submit Response +2. Gemini AI verifies content +3. If approved ✅ → Payment auto-released (cUSD) +4. If rejected ❌ → Refund to requester + +--- + +## 🧾 Example API Calls + +### Create Task + +```http +POST /api/v1/tasks/create +Content-Type: application/json + +{ + "title": "Label Images", + "description": "Tag each image with emotion category", + "paymentAmount": 3.5, + "expiresAt": "2025-11-10T12:00:00Z" +} +``` + +### Submit Task + +```http +POST /api/v1/submissions/submit +Content-Type: application/json + +{ + "taskId": "uuid", + "submissionData": { + "imageUrls": ["https://ipfs.tech/image1.png"], + "metadata": { "label": "happy" } + } +} +``` + +**AI Queue → Gemini Verification → Payment Released** + +--- + +## 🧱 Architecture Diagram + +``` +┌────────────┐ +│ Next.js │────┐ +└────────────┘ │ + ▼ +┌───────────┐ ┌──────────────┐ +│Express.js │◄─│ PostgreSQL │ +└───────────┘ └──────────────┘ + │ +┌─────┼──────┐ +▼ ▼ ▼ +Gemini Redis Celo +AI /Bull Network +(Verify) (Queue) (Escrow) +``` + +--- + +## ✅ Features Checklist + +- [X] Wallet Signature Login (EIP-191) +- [X] Gemini-based Content Moderation +- [X] Blockchain-Backed Escrow Payments +- [X] Task + Submission CRUD +- [X] Bull Queue Worker Verification +- [X] Real-Time Status Updates +- [X] cUSD Balance Tracking +- [X] Transaction Confirmation + CeloScan Link +- [X] Admin + Requester Dashboard +- [X] Fully Responsive UI + +--- + +## 🧪 Testing + +```bash +# Run backend tests +cd server +npm run test + +# Database Studio +npx prisma studio + +# Queue dashboard +npm run bull:dashboard +``` + +--- + +## 🌍 Deployment + +### Suggested Setup + +| Layer | Platform | Notes | +| -------- | ------------------------------------------------------- | ------------------------ | +| Frontend | [Vercel](https://vercel.com) | Auto-deploy from main | +| Backend | [Railway](https://railway.app) / [Render](https://render.com) | Node + Postgres service | +| Database | Neon / Supabase | Free Postgres DB | +| Redis | Upstash / Redis Cloud | Connection for Bull jobs | + +--- + +## 🧠 Future Roadmap + +- 🪄 On-chain Gemini verification proofs +- 🧩 Decentralized task reputation scoring +- 💬 Worker messaging + chat +- 🪶 File uploads to IPFS / Web3.Storage +- ⚙️ Multi-network support (Base, Polygon) + +--- + +## 🪙 Credits + +Developed with 💚 on the Celo blockchain. + +Built using **Next.js**, **Celo ContractKit**, **Gemini AI**, and **Prisma**. + +--- + +## 📝 License + +This project is licensed under the **MIT License** — feel free to fork and extend 💡 + +--- + +## 👥 Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +1. Fork the repository +2. Create your feature branch (`git checkout -b feature/AmazingFeature`) +3. Commit your changes (`git commit -m 'Add some AmazingFeature'`) +4. Push to the branch (`git push origin feature/AmazingFeature`) +5. Open a Pull Request + +--- + +## 📧 Contact + +For questions or support, please open an issue on [GitHub](https://github.com/Rio-awsm/micro-job-ai-agent-web3/issues). + +--- + +

Made with ❤️ for the Celo ecosystem

diff --git a/dmtp/client/.gitignore b/dmtp/client/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/dmtp/client/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/dmtp/client/README.md b/dmtp/client/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/dmtp/client/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/dmtp/client/app/_sections/badge-showcase.tsx b/dmtp/client/app/_sections/badge-showcase.tsx new file mode 100644 index 0000000..ef673e4 --- /dev/null +++ b/dmtp/client/app/_sections/badge-showcase.tsx @@ -0,0 +1,31 @@ +const badges = [ + { name: "Quick Starter", icon: "⚡", earned: true }, + { name: "Accuracy Master", icon: "🎯", earned: true }, + { name: "Streak Champion", icon: "🔥", earned: true }, + { name: "Top Performer", icon: "👑", earned: false }, + { name: "Community Helper", icon: "🤝", earned: false }, + { name: "Legendary Worker", icon: "⭐", earned: false }, +] + +export function BadgeShowcase() { + return ( +
+

Badges

+
+ {badges.map((badge, index) => ( +
+
{badge.icon}
+

{badge.name}

+
+ ))} +
+
+ ) +} diff --git a/dmtp/client/app/_sections/feature-showcase.tsx b/dmtp/client/app/_sections/feature-showcase.tsx new file mode 100644 index 0000000..a09ed57 --- /dev/null +++ b/dmtp/client/app/_sections/feature-showcase.tsx @@ -0,0 +1,74 @@ +"use client" + +import { motion } from "framer-motion" +import { Brain, Wallet, Zap } from "lucide-react" + +export function FeatureShowcase() { + const features = [ + { + title: "Seamless Task Marketplace", + description: "Browse thousands of AI-verified tasks. Filter by category, difficulty, and earning potential.", + icon: Zap, + delay: 0, + }, + { + title: "AI-Powered Verification", + description: "Advanced AI models verify your work instantly. Get paid only for quality submissions.", + icon: Brain, + delay: 0.1, + }, + { + title: "Instant Payments", + description: "Earn cUSD instantly on Celo Sepolia. Withdraw anytime with zero fees.", + icon: Wallet, + delay: 0.2, + }, + ] + + return ( +
+
+ +

+ Why Choose{" "} + D.M.T.P +

+

+ The most advanced AI-powered microtask platform with instant payments and transparent verification. +

+
+ +
+ {features.map((feature, i) => { + const Icon = feature.icon + return ( + +
+ {/* Icon */} +
+ +
+ +

{feature.title}

+

{feature.description}

+
+
+ ) + })} +
+
+
+ ) +} diff --git a/dmtp/client/app/_sections/hero-section.tsx b/dmtp/client/app/_sections/hero-section.tsx new file mode 100644 index 0000000..279b89f --- /dev/null +++ b/dmtp/client/app/_sections/hero-section.tsx @@ -0,0 +1,150 @@ +"use client" + +import { Button } from "@/components/ui/button" +import { useAuth } from "@/hooks/useAuth"; +import { useCUSDBalance } from "@/hooks/useCUSDBalance"; +import { useWalletConnection } from "@/hooks/useWalletConnection"; +import { motion } from "framer-motion" +import { ArrowRight, CheckCircle } from "lucide-react" +import { useState } from "react"; + +export function HeroSection() { + const { address, isConnected, isConnecting, connect, disconnect, chainId } = useWalletConnection(); + const { authenticate, isAuthenticating, clearAuth, isAuthenticated } = useAuth(); + const { data: balance } = useCUSDBalance(address); + const [showNetworkModal, setShowNetworkModal] = useState(false); + + const expectedChainId = parseInt(process.env.NEXT_PUBLIC_CHAIN_ID || '11142220'); + const isWrongNetwork = isConnected && chainId !== expectedChainId; + + const handleConnect = async () => { + try { + // Step 1: Connect wallet + await connect(); + + // Step 2: Authenticate + await authenticate(); + } catch (error) { + console.error('Connection/Authentication error:', error); + } + }; + + return ( +
+ {/* Green accent border on top */} +
+ + {/* Content */} +
+
+ {/* Left Column - Main Content */} +
+ + + + AI-Powered Verification + + + + +

+ Complete tasks.{" "} + + Get verified by AI. + {" "} + Earn instantly. +

+
+ + + Join the AI-powered microtask marketplace on Celo Sepolia. Complete data labeling, surveys, and content + moderation tasks. Get paid in cUSD instantly. + + + + + + + + + {/* Feature Pills */} + + {[ + { label: "Powered by Gemini AI" }, + { label: "Built on Celo Sepolia" }, + { label: "Instant Payments" }, + ].map((item, i) => ( +
+
+ {item.label} +
+ ))} + +
+ + {/* Right Column - Stats Box */} + +

Platform Statistics

+
+
+
2,847
+
Active Tasks
+
+
+
$24,392
+
Paid This Week
+
+
+
15,234
+
Verified Workers
+
+
+
+
+
+
+ ) +} diff --git a/dmtp/client/app/_sections/how-it-works.tsx b/dmtp/client/app/_sections/how-it-works.tsx new file mode 100644 index 0000000..4df50c3 --- /dev/null +++ b/dmtp/client/app/_sections/how-it-works.tsx @@ -0,0 +1,79 @@ +"use client" + +import { motion } from "framer-motion" +import { CheckSquare, TrendingUp, Wallet, Zap } from "lucide-react" + +const steps = [ + { + icon: Wallet, + title: "Connect Wallet", + description: "Link your Celo wallet to get started in seconds", + }, + { + icon: CheckSquare, + title: "Complete Tasks", + description: "Choose from available tasks and complete them", + }, + { + icon: Zap, + title: "AI Verification", + description: "Gemini AI verifies your work instantly", + }, + { + icon: TrendingUp, + title: "Earn & Withdraw", + description: "Get paid in cUSD directly to your wallet", + }, +] + +export function HowItWorks() { + return ( +
+
+ +

+ How it{" "} + works +

+

Get started in 4 simple steps

+
+ +
+ {steps.map((step, index) => ( + + {index < steps.length - 1 && ( +
+ )} + +
+
+ +
+ +
+ {index + 1} +
+ +

{step.title}

+

{step.description}

+
+ + ))} +
+
+
+ ) +} diff --git a/dmtp/client/app/_sections/integrations-section.tsx b/dmtp/client/app/_sections/integrations-section.tsx new file mode 100644 index 0000000..fa65d0a --- /dev/null +++ b/dmtp/client/app/_sections/integrations-section.tsx @@ -0,0 +1,78 @@ +"use client" + +import { motion } from "framer-motion" +import { Code2, Database, MessageSquare, Zap } from "lucide-react" + +export function IntegrationsSection() { + const integrations = [ + { + icon: Code2, + title: "API Integration", + description: "Connect with your favorite tools to streamline workflows", + }, + { + icon: Database, + title: "Data Sync", + description: "Seamless data synchronization across platforms", + }, + { + icon: Zap, + title: "Automation", + description: "Automate repetitive tasks with intelligent workflows", + }, + { + icon: MessageSquare, + title: "Communication", + description: "Real-time notifications and updates", + }, + ] + + return ( +
+
+ {/* Header */} + +
+ INTEGRATIONS +
+

+ Seamless{" "} + + Integrations + +

+

Connect with your favorite tools to streamline workflows

+
+ + {/* Integration Grid */} +
+ {integrations.map((integration, index) => { + const Icon = integration.icon + return ( + +
+ +
+

{integration.title}

+

{integration.description}

+
+ ) + })} +
+
+
+ ) +} diff --git a/dmtp/client/app/_sections/reputation-meter.tsx b/dmtp/client/app/_sections/reputation-meter.tsx new file mode 100644 index 0000000..3dfe69c --- /dev/null +++ b/dmtp/client/app/_sections/reputation-meter.tsx @@ -0,0 +1,26 @@ +export function ReputationMeter() { + const reputation = 78 + const nextLevel = 85 + + return ( +
+
+
+

Reputation Score

+

{reputation}

+
+
+

Next Level

+

{nextLevel}

+
+
+
+
+
+

{nextLevel - reputation} points until next level

+
+ ) +} diff --git a/dmtp/client/app/_sections/stats-section.tsx b/dmtp/client/app/_sections/stats-section.tsx new file mode 100644 index 0000000..f6e4256 --- /dev/null +++ b/dmtp/client/app/_sections/stats-section.tsx @@ -0,0 +1,37 @@ +"use client" + +import { motion } from "framer-motion" + +const stats = [ + { label: "Active Workers", value: "12,450", suffix: "+" }, + { label: "Tasks Completed", value: "2.3M", suffix: "" }, + { label: "Total Earnings", value: "$450K", suffix: "" }, + { label: "Avg Task Pay", value: "$2.50", suffix: "" }, +] + +export function StatsSection() { + return ( +
+
+
+ {stats.map((stat, index) => ( + +
+ {stat.value} + {stat.suffix} +
+

{stat.label}

+
+ ))} +
+
+
+ ) +} diff --git a/dmtp/client/app/_sections/task-examples.tsx b/dmtp/client/app/_sections/task-examples.tsx new file mode 100644 index 0000000..8657c64 --- /dev/null +++ b/dmtp/client/app/_sections/task-examples.tsx @@ -0,0 +1,94 @@ +"use client" + +import { motion } from "framer-motion" +import { CheckCircle2 } from "lucide-react" + +const taskExamples = [ + { + category: "Data Labeling", + tasks: ["Image classification", "Object detection", "Text annotation"], + earning: "$1.50 - $5.00", + time: "5-15 min", + }, + { + category: "Content Moderation", + tasks: ["Review flagged content", "Verify guidelines compliance", "Quality assurance"], + earning: "$2.00 - $6.00", + time: "10-20 min", + }, + { + category: "Surveys & Research", + tasks: ["Market research", "User feedback", "Opinion surveys"], + earning: "$1.00 - $4.00", + time: "5-10 min", + }, + { + category: "Transcription", + tasks: ["Audio transcription", "Video captioning", "Translation"], + earning: "$3.00 - $8.00", + time: "15-30 min", + }, +] + +export function TaskExamples() { + return ( +
+
+ +

+ Available{" "} + + Task Types + +

+

Choose from diverse tasks that match your skills and schedule

+
+ +
+ {taskExamples.map((task, index) => ( + +
+

+ {task.category} +

+
    + {task.tasks.map((item, i) => ( +
  • + + {item} +
  • + ))} +
+
+
+

Earning

+

{task.earning}

+
+
+

Time

+

{task.time}

+
+
+
+
+ ))} +
+
+
+ ) +} diff --git a/dmtp/client/app/_sections/testimonials.tsx b/dmtp/client/app/_sections/testimonials.tsx new file mode 100644 index 0000000..aeaaf69 --- /dev/null +++ b/dmtp/client/app/_sections/testimonials.tsx @@ -0,0 +1,229 @@ +"use client" + +import { motion } from "framer-motion" +import { Star } from "lucide-react" +import { useEffect, useState } from "react" + +const testimonials = [ + { + name: "Sarah Chen", + role: "Student", + content: "I earn $200-300 per week doing tasks in my spare time. The AI verification is super fast!", + rating: 5, + avatar: "SC", + }, + { + name: "Marcus Johnson", + role: "Freelancer", + content: "Finally a platform where I get paid instantly. No more waiting for payments. Love it!", + rating: 5, + avatar: "MJ", + }, + { + name: "Elena Rodriguez", + role: "Remote Worker", + content: "The variety of tasks keeps things interesting. I've earned over $2000 in 3 months.", + rating: 5, + avatar: "ER", + }, + { + name: "James Park", + role: "Side Hustler", + content: "Best platform I've used. Transparent, fair, and the Celo integration is seamless.", + rating: 5, + avatar: "JP", + }, + { + name: "Sarah Chen", + role: "Student", + content: "I earn $200-300 per week doing tasks in my spare time. The AI verification is super fast!", + rating: 5, + avatar: "SC", + }, + { + name: "Marcus Johnson", + role: "Freelancer", + content: "Finally a platform where I get paid instantly. No more waiting for payments. Love it!", + rating: 5, + avatar: "MJ", + }, + { + name: "Elena Rodriguez", + role: "Remote Worker", + content: "The variety of tasks keeps things interesting. I've earned over $2000 in 3 months.", + rating: 5, + avatar: "ER", + }, + { + name: "James Park", + role: "Side Hustler", + content: "Best platform I've used. Transparent, fair, and the Celo integration is seamless.", + rating: 5, + avatar: "JP", + }, + { + name: "Sarah Chen", + role: "Student", + content: "I earn $200-300 per week doing tasks in my spare time. The AI verification is super fast!", + rating: 5, + avatar: "SC", + }, + { + name: "Marcus Johnson", + role: "Freelancer", + content: "Finally a platform where I get paid instantly. No more waiting for payments. Love it!", + rating: 5, + avatar: "MJ", + }, + { + name: "Elena Rodriguez", + role: "Remote Worker", + content: "The variety of tasks keeps things interesting. I've earned over $2000 in 3 months.", + rating: 5, + avatar: "ER", + }, + { + name: "James Park", + role: "Side Hustler", + content: "Best platform I've used. Transparent, fair, and the Celo integration is seamless.", + rating: 5, + avatar: "JP", + }, + { + name: "Sarah Chen", + role: "Student", + content: "I earn $200-300 per week doing tasks in my spare time. The AI verification is super fast!", + rating: 5, + avatar: "SC", + }, + { + name: "Marcus Johnson", + role: "Freelancer", + content: "Finally a platform where I get paid instantly. No more waiting for payments. Love it!", + rating: 5, + avatar: "MJ", + }, + { + name: "Elena Rodriguez", + role: "Remote Worker", + content: "The variety of tasks keeps things interesting. I've earned over $2000 in 3 months.", + rating: 5, + avatar: "ER", + }, + { + name: "James Park", + role: "Side Hustler", + content: "Best platform I've used. Transparent, fair, and the Celo integration is seamless.", + rating: 5, + avatar: "JP", + }, + { + name: "Sarah Chen", + role: "Student", + content: "I earn $200-300 per week doing tasks in my spare time. The AI verification is super fast!", + rating: 5, + avatar: "SC", + }, + { + name: "Marcus Johnson", + role: "Freelancer", + content: "Finally a platform where I get paid instantly. No more waiting for payments. Love it!", + rating: 5, + avatar: "MJ", + }, + { + name: "Elena Rodriguez", + role: "Remote Worker", + content: "The variety of tasks keeps things interesting. I've earned over $2000 in 3 months.", + rating: 5, + avatar: "ER", + }, + { + name: "James Park", + role: "Side Hustler", + content: "Best platform I've used. Transparent, fair, and the Celo integration is seamless.", + rating: 5, + avatar: "JP", + }, + { + name: "Sarah Chen", + role: "Student", + content: "I earn $200-300 per week doing tasks in my spare time. The AI verification is super fast!", + rating: 5, + avatar: "SC", + }, + { + name: "Marcus Johnson", + role: "Freelancer", + content: "Finally a platform where I get paid instantly. No more waiting for payments. Love it!", + rating: 5, + avatar: "MJ", + }, + { + name: "Elena Rodriguez", + role: "Remote Worker", + content: "The variety of tasks keeps things interesting. I've earned over $2000 in 3 months.", + rating: 5, + avatar: "ER", + }, + { + name: "James Park", + role: "Side Hustler", + content: "Best platform I've used. Transparent, fair, and the Celo integration is seamless.", + rating: 5, + avatar: "JP", + }, +] + +export function Testimonials() { + const [currentIndex, setCurrentIndex] = useState(0) + + useEffect(() => { + const interval = setInterval(() => { + setCurrentIndex((prev) => (prev + 1) % testimonials.length) + }, 5000) + return () => clearInterval(interval) + }, []) + + return ( +
+
+
+

Loved by workers worldwide

+

Join thousands earning on D.M.T.P

+
+ +
+ + {testimonials.map((testimonial, index) => ( + +
+
+
+ {testimonial.avatar} +
+
+

{testimonial.name}

+

{testimonial.role}

+
+
+
+ {Array.from({ length: testimonial.rating }).map((_, i) => ( + + ))} +
+

{testimonial.content}

+
+
+ ))} +
+ +
+
+
+ ) +} diff --git a/dmtp/client/app/dashboard/page.tsx b/dmtp/client/app/dashboard/page.tsx new file mode 100644 index 0000000..c0406be --- /dev/null +++ b/dmtp/client/app/dashboard/page.tsx @@ -0,0 +1,430 @@ +'use client'; + +import { useWalletConnection } from '@/hooks/useWalletConnection'; +import { api } from '@/lib/api'; +import { formatCurrency } from '@/lib/utils'; +import { VerificationStatus } from '@/types'; +import { useQuery } from '@tanstack/react-query'; +import { motion } from 'framer-motion'; +import { Award, CheckCircle2, Clock, ExternalLink, Lock, TrendingUp, Wallet, XCircle } from 'lucide-react'; +import Link from 'next/link'; +import { useEffect } from 'react'; +import { Bar, BarChart, CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; +import { LoadingSpinner } from '@/components/ui/LoadingSpinner'; + +const earningsData = [ + { day: "Mon", earnings: 12.5 }, + { day: "Tue", earnings: 18.3 }, + { day: "Wed", earnings: 15.7 }, + { day: "Thu", earnings: 22.1 }, + { day: "Fri", earnings: 25.4 }, + { day: "Sat", earnings: 19.8 }, + { day: "Sun", earnings: 28.6 }, +] + +const tasksData = [ + { day: "Mon", completed: 4 }, + { day: "Tue", completed: 6 }, + { day: "Wed", completed: 5 }, + { day: "Thu", completed: 7 }, + { day: "Fri", completed: 8 }, + { day: "Sat", completed: 6 }, + { day: "Sun", completed: 9 }, +] + +export default function DashboardPage() { + const { isConnected, address, connect } = useWalletConnection(); + + const { data: profileData, isLoading: profileLoading, refetch: refetchProfile } = useQuery({ + queryKey: ['profile'], + queryFn: () => api.users.getProfile(), + enabled: isConnected, + }); + + const { data: submissionsData, isLoading: submissionsLoading, refetch: refetchSubmissions } = useQuery({ + queryKey: ['submissions'], + queryFn: () => api.submissions.mySubmissions(), + enabled: isConnected, + }); + + // Refetch when wallet connects + useEffect(() => { + if (isConnected) { + refetchProfile(); + refetchSubmissions(); + } + }, [isConnected, refetchProfile, refetchSubmissions]); + + if (!isConnected) { + return ( +
+ {/* Animated Background */} +
+ + +
+ +
+ + + + +

+ + Connect Your Wallet + +

+

+ Please connect your wallet to view your dashboard and track your earnings +

+ + + Connect Wallet + +
+
+
+ ); + } + + if (profileLoading || submissionsLoading) { + return ( +
+ +
+ ); + } + + const profile = profileData?.data; + const submissions = submissionsData?.data || []; + + const stats = [ + { + icon: Wallet, + label: 'Total Earnings', + value: formatCurrency(profile?.totalEarnings || 0), + gradient: 'from-green-500 to-green-600', + bgGradient: 'from-green-500/10 to-green-600/5', + border: 'border-green-500/30', + }, + { + icon: CheckCircle2, + label: 'Completed Tasks', + value: profile?.stats?.submissionsApproved || 0, + gradient: 'from-green-500 to-green-600', + bgGradient: 'from-green-500/10 to-green-600/5', + border: 'border-green-500/30', + }, + { + icon: TrendingUp, + label: 'Approval Rate', + value: `${profile?.stats?.approvalRate || 0}%`, + gradient: 'from-blue-500 to-blue-600', + bgGradient: 'from-blue-500/10 to-blue-600/5', + border: 'border-blue-500/30', + }, + { + icon: Award, + label: 'Reputation', + value: `⭐ ${profile?.reputationScore || 0}`, + gradient: 'from-green-400 to-green-500', + bgGradient: 'from-green-400/10 to-green-500/5', + border: 'border-green-400/30', + }, + ]; + + const getStatusConfig = (status: string) => { + switch (status) { + case VerificationStatus.APPROVED: + return { icon: CheckCircle2, color: 'text-green-600', bg: 'bg-green-100', text: 'Approved' }; + case VerificationStatus.REJECTED: + return { icon: XCircle, color: 'text-red-600', bg: 'bg-red-100', text: 'Rejected' }; + default: + return { icon: Clock, color: 'text-green-600', bg: 'bg-green-100', text: 'Pending' }; + } + }; + + return ( +
+ {/* Animated Background */} +
+ + +
+ +
+ {/* Header */} + +
+
+

+ + Dashboard + +

+
+ + {address?.slice(0, 6)}...{address?.slice(-4)} +
+
+
+ + + + + Active Worker + +
+
+
+ + {/* Stats Grid */} +
+ {stats.map((stat, index) => ( + +
+
+ +
+ +
+
{stat.label}
+
{stat.value}
+
+ ))} +
+ + {/* Recent Submissions */} + +
+

+ + Recent Submissions +

+
+ + {submissions.length === 0 ? ( +
+ + + +

No submissions yet

+ + + Browse Tasks + + + +
+ ) : ( +
+ + + + + + + + + + + + {submissions.map((submission: any, index: number) => { + const statusConfig = getStatusConfig(submission.verificationStatus); + const StatusIcon = statusConfig.icon; + + return ( + + + + + + + + ); + })} + +
+ Task + + Amount + + Status + + Date + + Action +
+
+ {submission.task.title} +
+
+
+ {formatCurrency(submission.task.paymentAmount)} +
+
+ + + {statusConfig.text} + + + {new Date(submission.createdAt).toLocaleDateString()} + + + View Details + + +
+
+ )} +
+ +
+ {/* Earnings Chart */} +
+

Weekly Earnings

+ + + + + + + + + + + + + + + +
+ + {/* Tasks Chart */} +
+

Tasks Completed

+ + + + + + + + + + + + + + + +
+
+
+
+ ); +} \ No newline at end of file diff --git a/dmtp/client/app/favicon.ico b/dmtp/client/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/dmtp/client/app/favicon.ico differ diff --git a/dmtp/client/app/globals.css b/dmtp/client/app/globals.css new file mode 100644 index 0000000..8d517a2 --- /dev/null +++ b/dmtp/client/app/globals.css @@ -0,0 +1,168 @@ +@import "tailwindcss"; +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.45 0.15 155); + --primary-foreground: oklch(1 0 0); + --secondary: oklch(0.96 0 0); + --secondary-foreground: oklch(0.145 0 0); + --muted: oklch(0.96 0 0); + --muted-foreground: oklch(0.45 0 0); + --accent: oklch(0.50 0.15 155); + --accent-foreground: oklch(1 0 0); + --destructive: oklch(0.55 0.22 25); + --destructive-foreground: oklch(1 0 0); + --border: oklch(0.85 0 0); + --input: oklch(0.85 0 0); + --ring: oklch(0.45 0.15 155); + --chart-1: oklch(0.55 0.15 155); + --chart-2: oklch(0.60 0.12 185); + --chart-3: oklch(0.40 0.07 230); + --chart-4: oklch(0.83 0.19 85); + --chart-5: oklch(0.77 0.19 70); + --radius: 0.25rem; + --sidebar: oklch(0.98 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.45 0.15 155); + --sidebar-primary-foreground: oklch(1 0 0); + --sidebar-accent: oklch(0.96 0 0); + --sidebar-accent-foreground: oklch(0.145 0 0); + --sidebar-border: oklch(0.85 0 0); + --sidebar-ring: oklch(0.45 0.15 155); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.145 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.145 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.985 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.396 0.141 25.723); + --destructive-foreground: oklch(0.637 0.237 25.331); + --border: oklch(0.269 0 0); + --input: oklch(0.269 0 0); + --ring: oklch(0.439 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(0.269 0 0); + --sidebar-ring: oklch(0.439 0 0); +} + +@theme inline { + --font-sans: "Inter", "Inter Fallback"; + + /* McMaster-Carr inspired: Clean white with green accents */ + --color-background: #ffffff; + --color-foreground: #1a1a1a; + --color-card: #ffffff; + --color-card-hover: #f9fafb; + + /* Green Theme */ + --color-primary: #008542; + --color-primary-dark: #006633; + --color-accent: #00a854; + --color-accent-light: #4caf50; + + /* Semantic */ + --color-success: #008542; + --color-warning: #f59e0b; + --color-error: #dc2626; + --color-info: #0066cc; + + /* Borders & Dividers */ + --color-border: #d1d5db; + --color-border-light: #e5e7eb; + + /* Radius */ + --radius: 0.5rem; + + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} + +/* Removed glow effects, added smooth transitions only */ +.transition-smooth { + @apply transition-all duration-300 ease-out; +} + +/* Scrollbar styling */ +::-webkit-scrollbar { + @apply w-2; +} + +::-webkit-scrollbar-track { + @apply bg-background; +} + +::-webkit-scrollbar-thumb { + @apply bg-border hover:bg-border-light; +} diff --git a/dmtp/client/app/layout.tsx b/dmtp/client/app/layout.tsx new file mode 100644 index 0000000..4b8c2a2 --- /dev/null +++ b/dmtp/client/app/layout.tsx @@ -0,0 +1,42 @@ +import { Footer } from "@/components/layout/footer"; +import { Navbar } from "@/components/layout/Navbar"; +import { ThemeProvider } from "@/components/theme-provider"; +import { AuthProvider } from "@/providers/AuthProvider"; +import { QueryProvider } from "@/providers/QueryProvider"; +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; +import "./globals.css"; + +const inter = Inter({ subsets: ["latin"] }); + +export const metadata: Metadata = { + title: "Celo Task Marketplace", + description: "AI-powered micro-task marketplace on Celo blockchain", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + + + +
{children}
+