update component and responsive all pages

This commit is contained in:
S M Fahim Hossen 2025-10-04 12:06:08 +06:00
parent 4785ef2aaa
commit 6dee2e5b3a
10 changed files with 448 additions and 202 deletions

View file

@ -1,10 +1,10 @@
<!doctype html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/planpost.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>affiliate-planpost</title> <title>Planpost Affiliate</title>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

18
package-lock.json generated
View file

@ -71,6 +71,7 @@
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3", "@babel/generator": "^7.28.3",
@ -2305,6 +2306,7 @@
"integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"undici-types": "~7.12.0" "undici-types": "~7.12.0"
} }
@ -2315,6 +2317,7 @@
"integrity": "sha512-+kLxJpaJzXybyDyFXYADyP1cznTO8HSuBpenGlnKOAkH4hyNINiywvXS/tGJhsrGGP/gM185RA3xpjY0Yg4erA==", "integrity": "sha512-+kLxJpaJzXybyDyFXYADyP1cznTO8HSuBpenGlnKOAkH4hyNINiywvXS/tGJhsrGGP/gM185RA3xpjY0Yg4erA==",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.0.2"
} }
@ -2325,6 +2328,7 @@
"integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"peer": true,
"peerDependencies": { "peerDependencies": {
"@types/react": "^19.0.0" "@types/react": "^19.0.0"
} }
@ -2381,6 +2385,7 @@
"integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==", "integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.44.1", "@typescript-eslint/scope-manager": "8.44.1",
"@typescript-eslint/types": "8.44.1", "@typescript-eslint/types": "8.44.1",
@ -2633,6 +2638,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@ -2763,6 +2769,7 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"baseline-browser-mapping": "^2.8.3", "baseline-browser-mapping": "^2.8.3",
"caniuse-lite": "^1.0.30001741", "caniuse-lite": "^1.0.30001741",
@ -3187,6 +3194,7 @@
"integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
@ -4320,6 +4328,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
"integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@ -4329,6 +4338,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
"integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"scheduler": "^0.26.0" "scheduler": "^0.26.0"
}, },
@ -4348,6 +4358,7 @@
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@types/use-sync-external-store": "^0.0.6", "@types/use-sync-external-store": "^0.0.6",
"use-sync-external-store": "^1.4.0" "use-sync-external-store": "^1.4.0"
@ -4514,7 +4525,8 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"license": "MIT" "license": "MIT",
"peer": true
}, },
"node_modules/redux-thunk": { "node_modules/redux-thunk": {
"version": "3.1.0", "version": "3.1.0",
@ -4795,6 +4807,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@ -4863,6 +4876,7 @@
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@ -5022,6 +5036,7 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.7.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.7.tgz",
"integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==", "integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.5.0", "fdir": "^6.5.0",
@ -5113,6 +5128,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },

BIN
public/planpost.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

119
public/planpost.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -1,3 +1,4 @@
import React from "react";
import { import {
Sidebar, Sidebar,
SidebarContent, SidebarContent,
@ -9,13 +10,7 @@ import {
SidebarHeader, SidebarHeader,
SidebarFooter, SidebarFooter,
} from "@/components/ui/sidebar"; } from "@/components/ui/sidebar";
import { import { LayoutDashboard, Users, DollarSign, LogOut } from "lucide-react";
LayoutDashboard,
Users,
DollarSign,
LogOut,
Sparkles,
} from "lucide-react";
import { Link, useLocation } from "react-router-dom"; import { Link, useLocation } from "react-router-dom";
const AppSidebar: React.FC = () => { const AppSidebar: React.FC = () => {
@ -31,8 +26,8 @@ const AppSidebar: React.FC = () => {
<Sidebar className="border-r bg-gradient-to-b from-slate-50 to-white"> <Sidebar className="border-r bg-gradient-to-b from-slate-50 to-white">
<SidebarHeader className="border-b border-gray-200 pb-4"> <SidebarHeader className="border-b border-gray-200 pb-4">
<div className="flex items-center gap-3 px-2"> <div className="flex items-center gap-3 px-2">
<div className="bg-gradient-to-br from-blue-500 to-purple-600 p-2.5 rounded-lg shadow-md"> <div>
<Sparkles className="w-5 h-5 text-white" /> <img src="/planpost.png" alt="Logo" className="w-10 h-10" />
</div> </div>
<div> <div>
<h2 className="text-lg font-bold text-gray-900">Affiliate Panel</h2> <h2 className="text-lg font-bold text-gray-900">Affiliate Panel</h2>
@ -54,7 +49,7 @@ const AppSidebar: React.FC = () => {
transition-all duration-200 transition-all duration-200
${ ${
pathname === path pathname === path
? " text-white shadow-md hover:shadow-lg" ? "bg-blue-600 text-white shadow-md hover:bg-blue-700"
: "hover:bg-gray-100 text-gray-700" : "hover:bg-gray-100 text-gray-700"
} }
`} `}
@ -78,7 +73,6 @@ const AppSidebar: React.FC = () => {
</SidebarGroupContent> </SidebarGroupContent>
</SidebarGroup> </SidebarGroup>
{/* Stats Card */}
<div className="mt-6 mx-2 bg-gradient-to-br from-blue-50 to-purple-50 border border-blue-100 rounded-xl p-4"> <div className="mt-6 mx-2 bg-gradient-to-br from-blue-50 to-purple-50 border border-blue-100 rounded-xl p-4">
<p className="text-xs font-medium text-gray-600 mb-2"> <p className="text-xs font-medium text-gray-600 mb-2">
Total Earnings Total Earnings
@ -103,7 +97,6 @@ const AppSidebar: React.FC = () => {
</SidebarMenuItem> </SidebarMenuItem>
</SidebarMenu> </SidebarMenu>
{/* User Profile */}
<div className="mt-3 mx-2 flex items-center gap-3 p-3 bg-gray-50 rounded-lg border border-gray-200"> <div className="mt-3 mx-2 flex items-center gap-3 p-3 bg-gray-50 rounded-lg border border-gray-200">
<div className="w-10 h-10 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-white font-semibold"> <div className="w-10 h-10 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-white font-semibold">
JD JD

View file

@ -1,16 +1,24 @@
import React from "react"; import React from "react";
import { Outlet } from "react-router-dom"; import { Outlet } from "react-router-dom";
import AppSidebar from "../Sidebar"; import AppSidebar from "../Sidebar";
import { SidebarProvider, SidebarInset } from "../ui/sidebar"; import { SidebarProvider, SidebarInset, SidebarTrigger } from "../ui/sidebar";
const DashboardLayout: React.FC = () => { const DashboardLayout: React.FC = () => {
return ( return (
<SidebarProvider> <SidebarProvider>
<AppSidebar /> <AppSidebar />
<SidebarInset> <SidebarInset>
<main className="flex-1 p-6 bg-gray-50"> <div className="flex-1">
<Outlet /> {/* Mobile Header with Sidebar Trigger */}
</main> <header className="sticky top-0 z-10 flex h-[70px] items-center gap-2 px-2">
<SidebarTrigger className="hover:bg-gray-100" />
</header>
{/* Main Content */}
<main className="flex-1 p-6 bg-gray-50">
<Outlet />
</main>
</div>
</SidebarInset> </SidebarInset>
</SidebarProvider> </SidebarProvider>
); );

View file

@ -134,43 +134,48 @@ const Earnings: React.FC = () => {
}; };
return ( return (
<div className="min-h-screen bg-gray-50 p-6"> <div className="min-h-screen bg-gray-50 p-4 sm:p-6">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
{/* Header */} {/* Header */}
<div className="mb-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"> <div className="mb-6 sm:mb-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<div> <div>
<h1 className="text-3xl font-bold text-gray-900 mb-2">Earnings</h1> <h1 className="text-2xl sm:text-3xl font-bold text-gray-900 mb-2">
<p className="text-gray-600"> Earnings
</h1>
<p className="text-sm sm:text-base text-gray-600">
Track your affiliate performance and payouts Track your affiliate performance and payouts
</p> </p>
</div> </div>
<div className="flex gap-3"> <div className="flex gap-2 sm:gap-3">
<button className="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors flex items-center gap-2"> <button className="flex-1 sm:flex-initial px-3 sm:px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors flex items-center justify-center gap-2 text-sm sm:text-base">
<Download className="w-5 h-5 text-gray-600" /> <Download className="w-4 h-4 sm:w-5 sm:h-5 text-gray-600" />
Export <span className="hidden sm:inline">Export</span>
</button> </button>
<button <button
onClick={() => setShowPayoutModal(true)} onClick={() => setShowPayoutModal(true)}
className="px-6 py-2 bg-gradient-to-r from-indigo-600 to-purple-600 text-white rounded-lg hover:from-indigo-700 hover:to-purple-700 transition-all shadow-md flex items-center gap-2" className="flex-1 sm:flex-initial px-4 sm:px-6 py-2 bg-gradient-to-r from-indigo-600 to-purple-600 text-white rounded-lg hover:from-indigo-700 hover:to-purple-700 transition-all shadow-md flex items-center justify-center gap-2 text-sm sm:text-base"
> >
<CreditCard className="w-5 h-5" /> <CreditCard className="w-4 h-4 sm:w-5 sm:h-5" />
Request Payout <span className="hidden sm:inline">Request Payout</span>
<span className="sm:hidden">Payout</span>
</button> </button>
</div> </div>
</div> </div>
{/* Stats Grid */} {/* Stats Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6 mb-6 sm:mb-8">
{stats.map((stat, idx) => ( {stats.map((stat, idx) => (
<div <div
key={idx} key={idx}
className="bg-white rounded-xl shadow-sm border border-gray-100 p-6 hover:shadow-md transition-shadow" className="bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6 hover:shadow-md transition-shadow"
> >
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-3 sm:mb-4">
<div <div
className={`${stat.bgColor} w-12 h-12 rounded-lg flex items-center justify-center`} className={`${stat.bgColor} w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center`}
> >
<stat.icon className={`w-6 h-6 ${stat.textColor}`} /> <stat.icon
className={`w-5 h-5 sm:w-6 sm:h-6 ${stat.textColor}`}
/>
</div> </div>
{stat.trend !== "neutral" && ( {stat.trend !== "neutral" && (
<div <div
@ -179,18 +184,22 @@ const Earnings: React.FC = () => {
}`} }`}
> >
{stat.trend === "up" ? ( {stat.trend === "up" ? (
<ArrowUpRight className="w-4 h-4" /> <ArrowUpRight className="w-3 h-3 sm:w-4 sm:h-4" />
) : ( ) : (
<ArrowDownRight className="w-4 h-4" /> <ArrowDownRight className="w-3 h-3 sm:w-4 sm:h-4" />
)} )}
<span className="text-sm font-semibold">{stat.change}</span> <span className="text-xs sm:text-sm font-semibold">
{stat.change}
</span>
</div> </div>
)} )}
</div> </div>
<div className="text-3xl font-bold text-gray-900 mb-1"> <div className="text-2xl sm:text-3xl font-bold text-gray-900 mb-1">
{stat.value} {stat.value}
</div> </div>
<div className="text-sm text-gray-600">{stat.label}</div> <div className="text-xs sm:text-sm text-gray-600">
{stat.label}
</div>
{stat.trend === "neutral" && ( {stat.trend === "neutral" && (
<div className="text-xs text-gray-500 mt-1">{stat.change}</div> <div className="text-xs text-gray-500 mt-1">{stat.change}</div>
)} )}
@ -199,45 +208,45 @@ const Earnings: React.FC = () => {
</div> </div>
{/* Next Payout Card */} {/* Next Payout Card */}
<div className="bg-gradient-to-r from-indigo-600 to-purple-600 rounded-xl p-6 mb-8 shadow-lg"> <div className="bg-gradient-to-r from-indigo-600 to-purple-600 rounded-xl p-4 sm:p-6 mb-6 sm:mb-8 shadow-lg">
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4"> <div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
<div className="flex items-start gap-4"> <div className="flex items-start gap-3 sm:gap-4">
<div className="w-14 h-14 bg-white bg-opacity-20 backdrop-blur-sm rounded-xl flex items-center justify-center"> <div className="w-12 h-12 sm:w-14 sm:h-14 bg-white bg-opacity-20 backdrop-blur-sm rounded-xl flex items-center justify-center flex-shrink-0">
<Calendar className="w-7 h-7 text-white" /> <Calendar className="w-6 h-6 sm:w-7 sm:h-7 text-black" />
</div> </div>
<div> <div>
<div className="text-indigo-100 text-sm mb-1"> <div className="text-indigo-100 text-xs sm:text-sm mb-1">
Next Scheduled Payout Next Scheduled Payout
</div> </div>
<div className="text-3xl font-bold text-white mb-2"> <div className="text-xl sm:text-3xl font-bold text-white mb-2">
October 15, 2025 October 15, 2025
</div> </div>
<div className="text-indigo-100 text-sm"> <div className="text-indigo-100 text-xs sm:text-sm">
Your earnings will be processed automatically Your earnings will be processed automatically
</div> </div>
</div> </div>
</div> </div>
<div className="bg-white bg-opacity-20 backdrop-blur-sm rounded-xl p-4 text-center md:text-right"> <div className="bg-white bg-opacity-20 backdrop-blur-sm rounded-xl p-4 text-center md:text-right">
<div className="text-indigo-100 text-sm mb-1"> <div className="text-black text-xs sm:text-sm mb-1">
Estimated Amount Estimated Amount
</div> </div>
<div className="text-4xl font-bold text-white">$450</div> <div className="text-3xl sm:text-4xl font-bold text-black">
<div className="text-indigo-100 text-xs mt-1"> $450
+ pending approvals
</div> </div>
<div className="text-black text-xs mt-1">+ pending approvals</div>
</div> </div>
</div> </div>
</div> </div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8"> <div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-6 sm:mb-8">
{/* Chart Section */} {/* Chart Section */}
<div className="lg:col-span-2 bg-white rounded-xl shadow-sm border border-gray-100 p-6"> <div className="lg:col-span-2 bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6">
<div className="flex items-center justify-between mb-6"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-4 sm:mb-6 gap-3">
<div> <div>
<h2 className="text-xl font-semibold text-gray-900"> <h2 className="text-lg sm:text-xl font-semibold text-gray-900">
Earnings Overview Earnings Overview
</h2> </h2>
<p className="text-sm text-gray-600 mt-1"> <p className="text-xs sm:text-sm text-gray-600 mt-1">
Your performance over time Your performance over time
</p> </p>
</div> </div>
@ -246,7 +255,7 @@ const Earnings: React.FC = () => {
<button <button
key={period} key={period}
onClick={() => setTimeframe(period)} onClick={() => setTimeframe(period)}
className={`px-3 py-1.5 rounded-lg text-sm font-medium transition-colors ${ className={`px-2.5 sm:px-3 py-1.5 rounded-lg text-xs sm:text-sm font-medium transition-colors ${
timeframe === period timeframe === period
? "bg-indigo-600 text-white" ? "bg-indigo-600 text-white"
: "bg-gray-100 text-gray-600 hover:bg-gray-200" : "bg-gray-100 text-gray-600 hover:bg-gray-200"
@ -257,7 +266,7 @@ const Earnings: React.FC = () => {
))} ))}
</div> </div>
</div> </div>
<ResponsiveContainer width="100%" height={300}> <ResponsiveContainer width="100%" height={250}>
<AreaChart data={earningsData}> <AreaChart data={earningsData}>
<defs> <defs>
<linearGradient id="colorAmount" x1="0" y1="0" x2="0" y2="1"> <linearGradient id="colorAmount" x1="0" y1="0" x2="0" y2="1">
@ -269,9 +278,9 @@ const Earnings: React.FC = () => {
<XAxis <XAxis
dataKey="date" dataKey="date"
stroke="#9ca3af" stroke="#9ca3af"
style={{ fontSize: "12px" }} style={{ fontSize: "10px" }}
/> />
<YAxis stroke="#9ca3af" style={{ fontSize: "12px" }} /> <YAxis stroke="#9ca3af" style={{ fontSize: "10px" }} />
<Tooltip <Tooltip
contentStyle={{ contentStyle={{
backgroundColor: "#fff", backgroundColor: "#fff",
@ -284,7 +293,7 @@ const Earnings: React.FC = () => {
type="monotone" type="monotone"
dataKey="amount" dataKey="amount"
stroke="#6366f1" stroke="#6366f1"
strokeWidth={3} strokeWidth={2}
fill="url(#colorAmount)" fill="url(#colorAmount)"
/> />
</AreaChart> </AreaChart>
@ -292,46 +301,60 @@ const Earnings: React.FC = () => {
</div> </div>
{/* Payment Methods */} {/* Payment Methods */}
<div className="bg-white rounded-xl shadow-sm border border-gray-100 p-6"> <div className="bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6">
<h2 className="text-xl font-semibold text-gray-900 mb-4"> <h2 className="text-lg sm:text-xl font-semibold text-gray-900 mb-4">
Payment Method Payment Method
</h2> </h2>
<div className="space-y-3"> <div className="space-y-3">
<div className="p-4 border-2 border-indigo-600 rounded-lg bg-indigo-50"> <div className="p-3 sm:p-4 border-2 border-indigo-600 rounded-lg bg-indigo-50">
<div className="flex items-center gap-3 mb-2"> <div className="flex items-center gap-3 mb-2">
<div className="w-10 h-10 bg-indigo-600 rounded-lg flex items-center justify-center"> <div className="w-9 h-9 sm:w-10 sm:h-10 bg-indigo-600 rounded-lg flex items-center justify-center flex-shrink-0">
<CreditCard className="w-5 h-5 text-white" /> <CreditCard className="w-4 h-4 sm:w-5 sm:h-5 text-white" />
</div> </div>
<div className="flex-1"> <div className="flex-1 min-w-0">
<div className="font-semibold text-gray-900">PayPal</div> <div className="font-semibold text-gray-900 text-sm sm:text-base">
<div className="text-sm text-gray-600"> PayPal
</div>
<div className="text-xs sm:text-sm text-gray-600 truncate">
john@example.com john@example.com
</div> </div>
</div> </div>
<CheckCircle className="w-5 h-5 text-indigo-600" /> <CheckCircle className="w-4 h-4 sm:w-5 sm:h-5 text-indigo-600 flex-shrink-0" />
</div> </div>
</div> </div>
<button className="w-full p-4 border-2 border-dashed border-gray-300 rounded-lg text-gray-600 hover:border-indigo-600 hover:text-indigo-600 transition-colors font-medium"> <button className="w-full p-3 sm:p-4 border-2 border-dashed border-gray-300 rounded-lg text-gray-600 hover:border-indigo-600 hover:text-indigo-600 transition-colors font-medium text-sm sm:text-base">
+ Add Payment Method + Add Payment Method
</button> </button>
</div> </div>
<div className="mt-6 pt-6 border-t border-gray-100"> <div className="mt-4 sm:mt-6 pt-4 sm:pt-6 border-t border-gray-100">
<h3 className="font-semibold text-gray-900 mb-3">Quick Stats</h3> <h3 className="font-semibold text-gray-900 mb-3 text-sm sm:text-base">
Quick Stats
</h3>
<div className="space-y-3"> <div className="space-y-3">
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-sm text-gray-600"> <span className="text-xs sm:text-sm text-gray-600">
Total Transactions Total Transactions
</span> </span>
<span className="font-semibold text-gray-900">142</span> <span className="font-semibold text-gray-900 text-sm sm:text-base">
142
</span>
</div> </div>
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-sm text-gray-600">Avg. Commission</span> <span className="text-xs sm:text-sm text-gray-600">
<span className="font-semibold text-gray-900">$87.68</span> Avg. Commission
</span>
<span className="font-semibold text-gray-900 text-sm sm:text-base">
$87.68
</span>
</div> </div>
<div className="flex justify-between"> <div className="flex justify-between">
<span className="text-sm text-gray-600">Success Rate</span> <span className="text-xs sm:text-sm text-gray-600">
<span className="font-semibold text-green-600">98.2%</span> Success Rate
</span>
<span className="font-semibold text-green-600 text-sm sm:text-base">
98.2%
</span>
</div> </div>
</div> </div>
</div> </div>
@ -340,39 +363,42 @@ const Earnings: React.FC = () => {
{/* Transaction History */} {/* Transaction History */}
<div className="bg-white rounded-xl shadow-sm border border-gray-100"> <div className="bg-white rounded-xl shadow-sm border border-gray-100">
<div className="p-6 border-b border-gray-100"> <div className="p-4 sm:p-6 border-b border-gray-100">
<h2 className="text-xl font-semibold text-gray-900"> <h2 className="text-lg sm:text-xl font-semibold text-gray-900">
Recent Transactions Recent Transactions
</h2> </h2>
<p className="text-sm text-gray-600 mt-1"> <p className="text-xs sm:text-sm text-gray-600 mt-1">
Your latest earnings and payouts Your latest earnings and payouts
</p> </p>
</div> </div>
<div className="divide-y divide-gray-100"> <div className="divide-y divide-gray-100">
{transactionData.map((transaction, idx) => ( {transactionData.map((transaction, idx) => (
<div key={idx} className="p-6 hover:bg-gray-50 transition-colors"> <div
<div className="flex items-center justify-between"> key={idx}
<div className="flex items-center gap-4"> className="p-4 sm:p-6 hover:bg-gray-50 transition-colors"
>
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-3 sm:gap-4 min-w-0">
<div <div
className={`w-12 h-12 rounded-xl flex items-center justify-center ${ className={`w-10 h-10 sm:w-12 sm:h-12 rounded-xl flex items-center justify-center flex-shrink-0 ${
transaction.type === "Bonus" transaction.type === "Bonus"
? "bg-purple-100" ? "bg-purple-100"
: "bg-green-100" : "bg-green-100"
}`} }`}
> >
<DollarSign <DollarSign
className={`w-6 h-6 ${ className={`w-5 h-5 sm:w-6 sm:h-6 ${
transaction.type === "Bonus" transaction.type === "Bonus"
? "text-purple-600" ? "text-purple-600"
: "text-green-600" : "text-green-600"
}`} }`}
/> />
</div> </div>
<div> <div className="min-w-0">
<div className="font-semibold text-gray-900"> <div className="font-semibold text-gray-900 text-sm sm:text-base">
{transaction.type} {transaction.type}
</div> </div>
<div className="text-sm text-gray-600"> <div className="text-xs sm:text-sm text-gray-600">
{transaction.date} {transaction.date}
</div> </div>
<div className="text-xs text-gray-500 mt-1"> <div className="text-xs text-gray-500 mt-1">
@ -380,12 +406,12 @@ const Earnings: React.FC = () => {
</div> </div>
</div> </div>
</div> </div>
<div className="text-right"> <div className="text-right flex-shrink-0">
<div className="text-2xl font-bold text-gray-900"> <div className="text-lg sm:text-2xl font-bold text-gray-900">
{transaction.amount} {transaction.amount}
</div> </div>
<span <span
className={`inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-semibold mt-1 ${ className={`inline-flex items-center gap-1 px-2 py-0.5 sm:py-1 rounded-full text-xs font-semibold mt-1 ${
transaction.status === "Completed" transaction.status === "Completed"
? "bg-green-100 text-green-700" ? "bg-green-100 text-green-700"
: "bg-yellow-100 text-yellow-700" : "bg-yellow-100 text-yellow-700"
@ -396,15 +422,17 @@ const Earnings: React.FC = () => {
) : ( ) : (
<Clock className="w-3 h-3" /> <Clock className="w-3 h-3" />
)} )}
{transaction.status} <span className="hidden sm:inline">
{transaction.status}
</span>
</span> </span>
</div> </div>
</div> </div>
</div> </div>
))} ))}
</div> </div>
<div className="p-6 border-t border-gray-100 text-center"> <div className="p-4 sm:p-6 border-t border-gray-100 text-center">
<button className="text-indigo-600 hover:text-indigo-700 font-semibold text-sm"> <button className="text-indigo-600 hover:text-indigo-700 font-semibold text-xs sm:text-sm">
View All Transactions View All Transactions
</button> </button>
</div> </div>
@ -413,19 +441,19 @@ const Earnings: React.FC = () => {
{/* Payout Request Modal */} {/* Payout Request Modal */}
{showPayoutModal && ( {showPayoutModal && (
<div className="fixed inset-0 bg-black/20 bg-opacity-50 flex items-center justify-center z-50 p-4"> <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-2xl shadow-2xl h-[80vh] overflow-y-auto max-w-md w-full animate-fade-in"> <div className="bg-white rounded-2xl shadow-2xl max-h-[90vh] overflow-y-auto max-w-md w-full animate-fade-in">
{/* Modal Header */} {/* Modal Header */}
<div className="flex items-center justify-between p-6 border-b border-gray-100"> <div className="flex items-center justify-between p-4 sm:p-6 border-b border-gray-100">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-12 h-12 bg-gradient-to-br from-indigo-500 to-purple-500 rounded-xl flex items-center justify-center"> <div className="w-10 h-10 sm:w-12 sm:h-12 bg-gradient-to-br from-indigo-500 to-purple-500 rounded-xl flex items-center justify-center">
<Wallet className="w-6 h-6 text-white" /> <Wallet className="w-5 h-5 sm:w-6 sm:h-6 text-white" />
</div> </div>
<div> <div>
<h3 className="text-xl font-bold text-gray-900"> <h3 className="text-lg sm:text-xl font-bold text-gray-900">
Request Payout Request Payout
</h3> </h3>
<p className="text-sm text-gray-600"> <p className="text-xs sm:text-sm text-gray-600">
Withdraw your earnings Withdraw your earnings
</p> </p>
</div> </div>
@ -439,13 +467,15 @@ const Earnings: React.FC = () => {
</div> </div>
{/* Modal Body */} {/* Modal Body */}
<div className="p-6 space-y-5"> <div className="p-4 sm:p-6 space-y-4 sm:space-y-5">
{/* Available Balance */} {/* Available Balance */}
<div className="bg-gradient-to-br from-green-50 to-emerald-50 border border-green-200 rounded-xl p-4"> <div className="bg-gradient-to-br from-green-50 to-emerald-50 border border-green-200 rounded-xl p-4">
<div className="text-sm text-green-700 mb-1"> <div className="text-xs sm:text-sm text-green-700 mb-1">
Available Balance Available Balance
</div> </div>
<div className="text-3xl font-bold text-green-900">$890.00</div> <div className="text-2xl sm:text-3xl font-bold text-green-900">
$890.00
</div>
<div className="text-xs text-green-600 mt-1"> <div className="text-xs text-green-600 mt-1">
Ready for withdrawal Ready for withdrawal
</div> </div>
@ -464,11 +494,11 @@ const Earnings: React.FC = () => {
onChange={(e) => setPayoutAmount(e.target.value)} onChange={(e) => setPayoutAmount(e.target.value)}
placeholder="0.00" placeholder="0.00"
max="890" max="890"
className="w-full pl-10 pr-20 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent outline-none text-lg font-semibold" className="w-full pl-10 pr-16 sm:pr-20 py-2.5 sm:py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent outline-none text-base sm:text-lg font-semibold"
/> />
<button <button
onClick={() => setPayoutAmount("890")} onClick={() => setPayoutAmount("890")}
className="absolute right-2 top-1/2 transform -translate-y-1/2 px-3 py-1 bg-indigo-600 text-white text-sm rounded-md hover:bg-indigo-700 transition-colors" className="absolute right-2 top-1/2 transform -translate-y-1/2 px-2.5 sm:px-3 py-1 bg-indigo-600 text-white text-xs sm:text-sm rounded-md hover:bg-indigo-700 transition-colors"
> >
Max Max
</button> </button>
@ -483,14 +513,16 @@ const Earnings: React.FC = () => {
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">
Payment Method Payment Method
</label> </label>
<div className="p-4 border-2 border-indigo-600 rounded-lg bg-indigo-50"> <div className="p-3 sm:p-4 border-2 border-indigo-600 rounded-lg bg-indigo-50">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-10 h-10 bg-indigo-600 rounded-lg flex items-center justify-center"> <div className="w-9 h-9 sm:w-10 sm:h-10 bg-indigo-600 rounded-lg flex items-center justify-center">
<CreditCard className="w-5 h-5 text-white" /> <CreditCard className="w-4 h-4 sm:w-5 sm:h-5 text-white" />
</div> </div>
<div className="flex-1"> <div className="flex-1 min-w-0">
<div className="font-semibold text-gray-900">PayPal</div> <div className="font-semibold text-gray-900 text-sm sm:text-base">
<div className="text-sm text-gray-600"> PayPal
</div>
<div className="text-xs sm:text-sm text-gray-600 truncate">
john@example.com john@example.com
</div> </div>
</div> </div>
@ -500,9 +532,9 @@ const Earnings: React.FC = () => {
</div> </div>
{/* Processing Info */} {/* Processing Info */}
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4 flex gap-3"> <div className="bg-blue-50 border border-blue-200 rounded-lg p-3 sm:p-4 flex gap-3">
<AlertCircle className="w-5 h-5 text-blue-600 flex-shrink-0 mt-0.5" /> <AlertCircle className="w-5 h-5 text-blue-600 flex-shrink-0 mt-0.5" />
<div className="text-sm text-blue-700"> <div className="text-xs sm:text-sm text-blue-700">
<p className="font-medium mb-1">Processing Time</p> <p className="font-medium mb-1">Processing Time</p>
<p className="text-blue-600"> <p className="text-blue-600">
Payouts are typically processed within 24-48 hours on Payouts are typically processed within 24-48 hours on
@ -512,22 +544,22 @@ const Earnings: React.FC = () => {
</div> </div>
{/* Summary */} {/* Summary */}
<div className="bg-gray-50 rounded-lg p-4 space-y-2"> <div className="bg-gray-50 rounded-lg p-3 sm:p-4 space-y-2">
<div className="flex justify-between text-sm"> <div className="flex justify-between text-xs sm:text-sm">
<span className="text-gray-600">Withdrawal Amount</span> <span className="text-gray-600">Withdrawal Amount</span>
<span className="font-semibold text-gray-900"> <span className="font-semibold text-gray-900">
${payoutAmount} ${payoutAmount}
</span> </span>
</div> </div>
<div className="flex justify-between text-sm"> <div className="flex justify-between text-xs sm:text-sm">
<span className="text-gray-600">Processing Fee</span> <span className="text-gray-600">Processing Fee</span>
<span className="font-semibold text-gray-900">$0.00</span> <span className="font-semibold text-gray-900">$0.00</span>
</div> </div>
<div className="border-t border-gray-200 pt-2 flex justify-between"> <div className="border-t border-gray-200 pt-2 flex justify-between">
<span className="font-semibold text-gray-900"> <span className="font-semibold text-gray-900 text-sm sm:text-base">
You'll Receive You'll Receive
</span> </span>
<span className="text-xl font-bold text-indigo-600"> <span className="text-lg sm:text-xl font-bold text-indigo-600">
${payoutAmount} ${payoutAmount}
</span> </span>
</div> </div>
@ -535,10 +567,10 @@ const Earnings: React.FC = () => {
</div> </div>
{/* Modal Footer */} {/* Modal Footer */}
<div className="p-6 border-t border-gray-100 flex gap-3"> <div className="p-4 sm:p-6 border-t border-gray-100 flex gap-3">
<button <button
onClick={() => setShowPayoutModal(false)} onClick={() => setShowPayoutModal(false)}
className="flex-1 px-4 py-3 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors font-semibold text-gray-700" className="flex-1 px-3 sm:px-4 py-2.5 sm:py-3 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors font-semibold text-gray-700 text-sm sm:text-base"
> >
Cancel Cancel
</button> </button>
@ -549,15 +581,15 @@ const Earnings: React.FC = () => {
Number(payoutAmount) < 50 || Number(payoutAmount) < 50 ||
Number(payoutAmount) > 890 Number(payoutAmount) > 890
} }
className="flex-1 px-4 py-3 bg-gradient-to-r from-indigo-600 to-purple-600 text-white rounded-lg hover:from-indigo-700 hover:to-purple-700 transition-all font-semibold disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2" className="flex-1 px-3 sm:px-4 py-2.5 sm:py-3 bg-gradient-to-r from-indigo-600 to-purple-600 text-white rounded-lg hover:from-indigo-700 hover:to-purple-700 transition-all font-semibold disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2 text-sm sm:text-base"
> >
{isProcessing ? ( {isProcessing ? (
<> <>
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin"></div> <div className="w-4 h-4 sm:w-5 sm:h-5 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
Processing... <span className="hidden sm:inline">Processing...</span>
</> </>
) : ( ) : (
<>Confirm Request</> <>Confirm</>
)} )}
</button> </button>
</div> </div>

View file

@ -33,8 +33,8 @@ const Login: React.FC = () => {
<div className="relative z-10"> <div className="relative z-10">
<div className="flex items-center gap-3 mb-8"> <div className="flex items-center gap-3 mb-8">
<div className="w-12 h-12 bg-white rounded-xl flex items-center justify-center"> <div className="w-12 h-12 flex items-center justify-center">
<TrendingUp className="w-7 h-7 text-indigo-600" /> <img src="/planpost.png" alt="Logo" className="w-12 h-12" />
</div> </div>
<span className="text-2xl font-bold text-white"> <span className="text-2xl font-bold text-white">
Planpost Affiliate Planpost Affiliate

View file

@ -25,21 +25,25 @@ const MetricsCard = ({
trend, trend,
bgColor, bgColor,
}: MetricsCardProps) => ( }: MetricsCardProps) => (
<div className="bg-white rounded-xl shadow-sm border border-gray-100 p-6 hover:shadow-md transition-shadow"> <div className="bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6 hover:shadow-md transition-shadow">
<div className="flex items-start justify-between mb-4"> <div className="flex items-start justify-between mb-3 sm:mb-4">
<div className={`${bgColor} p-3 rounded-lg`}> <div className={`${bgColor} p-2 sm:p-3 rounded-lg`}>
<Icon className="w-6 h-6 text-white" /> <Icon className="w-5 h-5 sm:w-6 sm:h-6 text-white" />
</div> </div>
{trend && ( {trend && (
<span className="flex items-center text-sm font-medium text-green-600 bg-green-50 px-2 py-1 rounded-full"> <span className="flex items-center text-xs sm:text-sm font-medium text-green-600 bg-green-50 px-2 py-1 rounded-full">
<TrendingUp className="w-3 h-3 mr-1" /> <TrendingUp className="w-3 h-3 mr-1" />
{trend} {trend}
</span> </span>
)} )}
</div> </div>
<h3 className="text-gray-600 text-sm font-medium mb-1">{title}</h3> <h3 className="text-gray-600 text-xs sm:text-sm font-medium mb-1">
<p className="text-2xl font-bold text-gray-900">{value}</p> {title}
{subtitle && <p className="text-sm text-gray-500 mt-1">{subtitle}</p>} </h3>
<p className="text-xl sm:text-2xl font-bold text-gray-900">{value}</p>
{subtitle && (
<p className="text-xs sm:text-sm text-gray-500 mt-1">{subtitle}</p>
)}
</div> </div>
); );
@ -54,19 +58,19 @@ const Overview = () => {
}; };
return ( return (
<div className="max-w-7xl mx-auto"> <div className="w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-0">
{/* Header */} {/* Header */}
<div className="mb-8"> <div className="mb-6 sm:mb-8">
<h1 className="text-3xl font-bold text-gray-900 mb-2"> <h3 className="text-2xl sm:text-3xl font-bold text-gray-900 mb-2">
Dashboard Overview Dashboard Overview
</h1> </h3>
<p className="text-gray-600"> <p className="text-sm sm:text-base text-gray-600">
Track your affiliate performance and earnings Track your affiliate performance and earnings
</p> </p>
</div> </div>
{/* Metrics Grid */} {/* Metrics Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6 mb-6 sm:mb-8">
<MetricsCard <MetricsCard
title="Total Earnings" title="Total Earnings"
value="$3,200" value="$3,200"
@ -96,16 +100,16 @@ const Overview = () => {
</div> </div>
{/* Referral Link Section */} {/* Referral Link Section */}
<div className="bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl p-6 shadow-sm border border-blue-100"> <div className="bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl p-4 sm:p-6 shadow-sm border border-blue-100">
<div className="flex items-center gap-2 mb-4"> <div className="flex items-center gap-2 mb-3 sm:mb-4">
<div className="bg-blue-500 p-2 rounded-lg"> <div className="bg-blue-500 p-2 rounded-lg">
<Users className="w-5 h-5 text-white" /> <Users className="w-4 h-4 sm:w-5 sm:h-5 text-white" />
</div> </div>
<h2 className="text-xl font-semibold text-gray-900"> <h2 className="text-lg sm:text-xl font-semibold text-gray-900">
Your Referral Link Your Referral Link
</h2> </h2>
</div> </div>
<p className="text-gray-600 text-sm mb-4"> <p className="text-gray-600 text-xs sm:text-sm mb-3 sm:mb-4">
Share this link with your network to start earning commissions Share this link with your network to start earning commissions
</p> </p>
<div className="flex flex-col sm:flex-row gap-3"> <div className="flex flex-col sm:flex-row gap-3">
@ -114,12 +118,12 @@ const Overview = () => {
type="text" type="text"
value={referralLink} value={referralLink}
readOnly readOnly
className="w-full border-2 border-gray-200 rounded-lg px-4 py-3 bg-white focus:outline-none focus:border-blue-500 transition-colors font-mono text-sm" className="w-full border-2 border-gray-200 rounded-lg px-3 sm:px-4 py-2.5 sm:py-3 bg-white focus:outline-none focus:border-blue-500 transition-colors font-mono text-xs sm:text-sm"
/> />
</div> </div>
<button <button
onClick={handleCopy} onClick={handleCopy}
className={`px-6 py-3 rounded-lg font-medium transition-all flex items-center justify-center gap-2 min-w-[120px] ${ className={`px-4 sm:px-6 py-2.5 sm:py-3 rounded-lg font-medium transition-all flex items-center justify-center gap-2 min-w-[100px] sm:min-w-[120px] text-sm sm:text-base ${
copied copied
? "bg-green-500 text-white" ? "bg-green-500 text-white"
: "bg-blue-600 text-white hover:bg-blue-700 active:scale-95" : "bg-blue-600 text-white hover:bg-blue-700 active:scale-95"
@ -141,34 +145,38 @@ const Overview = () => {
</div> </div>
{/* Quick Stats */} {/* Quick Stats */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-8"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6 mt-6 sm:mt-8">
<div className="bg-white rounded-xl shadow-sm border border-gray-100 p-6"> <div className="bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6">
<h3 className="text-sm font-medium text-gray-600 mb-3"> <h3 className="text-xs sm:text-sm font-medium text-gray-600 mb-2 sm:mb-3">
Conversion Rate Conversion Rate
</h3> </h3>
<p className="text-3xl font-bold text-gray-900 mb-2">12.5%</p> <p className="text-2xl sm:text-3xl font-bold text-gray-900 mb-2">
12.5%
</p>
<div className="w-full bg-gray-200 rounded-full h-2"> <div className="w-full bg-gray-200 rounded-full h-2">
<div <div
className="bg-blue-500 h-2 rounded-full" className="bg-blue-500 h-2 rounded-full transition-all duration-500"
style={{ width: "12.5%" }} style={{ width: "12.5%" }}
></div> ></div>
</div> </div>
</div> </div>
<div className="bg-white rounded-xl shadow-sm border border-gray-100 p-6"> <div className="bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6">
<h3 className="text-sm font-medium text-gray-600 mb-3"> <h3 className="text-xs sm:text-sm font-medium text-gray-600 mb-2 sm:mb-3">
Average Commission Average Commission
</h3> </h3>
<p className="text-3xl font-bold text-gray-900">$37.65</p> <p className="text-2xl sm:text-3xl font-bold text-gray-900">$37.65</p>
<p className="text-sm text-green-600 mt-2"> $2.15 from last month</p> <p className="text-xs sm:text-sm text-green-600 mt-2">
$2.15 from last month
</p>
</div> </div>
<div className="bg-white rounded-xl shadow-sm border border-gray-100 p-6"> <div className="bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6 sm:col-span-2 lg:col-span-1">
<h3 className="text-sm font-medium text-gray-600 mb-3"> <h3 className="text-xs sm:text-sm font-medium text-gray-600 mb-2 sm:mb-3">
Next Payout Next Payout
</h3> </h3>
<p className="text-3xl font-bold text-gray-900">$945</p> <p className="text-2xl sm:text-3xl font-bold text-gray-900">$945</p>
<p className="text-sm text-gray-500 mt-2">In 12 days</p> <p className="text-xs sm:text-sm text-gray-500 mt-2">In 12 days</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -127,68 +127,72 @@ const Referrals: React.FC = () => {
); );
return ( return (
<div className="min-h-screen bg-gray-50 p-6"> <div className="min-h-screen bg-gray-50 p-4">
<div className="max-w-7xl mx-auto"> <div className="max-w-7xl mx-auto">
{/* Header */} {/* Header */}
<div className="mb-8"> <div className="mb-6 sm:mb-8">
<h1 className="text-3xl font-bold text-gray-900 mb-2">Referrals</h1> <h3 className="text-2xl sm:text-3xl font-bold text-gray-900 mb-2">
<p className="text-gray-600"> Referrals
</h3>
<p className="text-sm sm:text-base text-gray-600">
Track and manage your affiliate referrals Track and manage your affiliate referrals
</p> </p>
</div> </div>
{/* Stats Grid */} {/* Stats Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-6 mb-6 sm:mb-8">
{stats.map((stat, idx) => ( {stats.map((stat, idx) => (
<div <div
key={idx} key={idx}
className="bg-white rounded-xl shadow-sm border border-gray-100 p-6 hover:shadow-md transition-shadow" className="bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6 hover:shadow-md transition-shadow"
> >
<div className="flex items-center justify-between mb-4"> <div className="flex items-center justify-between mb-3 sm:mb-4">
<div <div
className={`${stat.color} w-12 h-12 rounded-lg flex items-center justify-center`} className={`${stat.color} w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center`}
> >
<stat.icon className="w-6 h-6 text-white" /> <stat.icon className="w-5 h-5 sm:w-6 sm:h-6 text-white" />
</div> </div>
</div> </div>
<div className="text-3xl font-bold text-gray-900 mb-1"> <div className="text-2xl sm:text-3xl font-bold text-gray-900 mb-1">
{stat.value} {stat.value}
</div> </div>
<div className="text-sm text-gray-600 mb-2">{stat.label}</div> <div className="text-xs sm:text-sm text-gray-600 mb-2">
{stat.label}
</div>
<div className="text-xs text-gray-500">{stat.change}</div> <div className="text-xs text-gray-500">{stat.change}</div>
</div> </div>
))} ))}
</div> </div>
{/* Referral Link Section */} {/* Referral Link Section */}
<div className="bg-gradient-to-r from-indigo-600 to-purple-600 rounded-xl p-6 mb-8 shadow-lg"> <div className="bg-gradient-to-r from-indigo-600 to-purple-600 rounded-xl p-4 sm:p-6 mb-6 sm:mb-8 shadow-lg">
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div className="flex-1"> <div className="flex-1">
<div className="flex items-center gap-2 mb-2"> <div className="flex items-center gap-2 mb-2">
<Link2 className="w-5 h-5 text-white" /> <Link2 className="w-4 h-4 sm:w-5 sm:h-5 text-white" />
<h3 className="text-lg font-semibold text-white"> <h3 className="text-base sm:text-lg font-semibold text-white">
Your Referral Link Your Referral Link
</h3> </h3>
</div> </div>
<p className="text-indigo-100 text-sm mb-4"> <p className="text-indigo-100 text-xs sm:text-sm mb-3 sm:mb-4">
Share this link to earn commissions Share this link to earn commissions
</p> </p>
<div className="flex gap-3"> <div className="flex flex-col sm:flex-row gap-3">
<div className="flex-1 bg-white bg-opacity-20 backdrop-blur-sm rounded-lg px-4 py-3 text-white font-mono text-sm"> <div className="flex-1 bg-white bg-opacity-20 backdrop-blur-sm rounded-lg px-3 sm:px-4 py-2.5 sm:py-3 text-white font-mono text-xs sm:text-sm break-all">
{referralLink} {referralLink}
</div> </div>
<button <button
onClick={handleCopy} onClick={handleCopy}
className="bg-white text-indigo-600 px-6 py-3 rounded-lg font-semibold hover:bg-gray-50 transition-all flex items-center gap-2 shadow-md" className="bg-white text-indigo-600 px-4 sm:px-6 py-2.5 sm:py-3 rounded-lg font-semibold hover:bg-gray-50 transition-all flex items-center justify-center gap-2 shadow-md text-sm sm:text-base"
> >
{copied ? ( {copied ? (
<> <>
<CheckCircle className="w-5 h-5" /> <CheckCircle className="w-4 h-4 sm:w-5 sm:h-5" />
Copied! Copied!
</> </>
) : ( ) : (
<> <>
<Copy className="w-5 h-5" /> <Copy className="w-4 h-4 sm:w-5 sm:h-5" />
Copy Link Copy Link
</> </>
)} )}
@ -201,36 +205,102 @@ const Referrals: React.FC = () => {
{/* Table Section */} {/* Table Section */}
<div className="bg-white rounded-xl shadow-sm border border-gray-100"> <div className="bg-white rounded-xl shadow-sm border border-gray-100">
{/* Table Header */} {/* Table Header */}
<div className="p-6 border-b border-gray-100"> <div className="p-4 sm:p-6 border-b border-gray-100">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
<h2 className="text-xl font-semibold text-gray-900"> <h2 className="text-lg sm:text-xl font-semibold text-gray-900">
Referral List Referral List
</h2> </h2>
<div className="flex gap-3"> <div className="flex gap-2 sm:gap-3">
<div className="relative flex-1 sm:flex-initial"> <div className="relative flex-1 sm:flex-initial">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" /> <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 sm:w-5 sm:h-5 text-gray-400" />
<input <input
type="text" type="text"
placeholder="Search referrals..." placeholder="Search..."
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent outline-none w-full sm:w-64" className="pl-9 sm:pl-10 pr-3 sm:pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent outline-none w-full sm:w-64 text-sm"
/> />
</div> </div>
<button className="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors flex items-center gap-2"> <button className="px-3 sm:px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors flex items-center gap-2">
<Filter className="w-5 h-5 text-gray-600" /> <Filter className="w-4 h-4 sm:w-5 sm:h-5 text-gray-600" />
<span className="hidden sm:inline">Filter</span> <span className="hidden sm:inline text-sm">Filter</span>
</button> </button>
<button className="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors flex items-center gap-2"> <button className="px-3 sm:px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors flex items-center gap-2">
<Download className="w-5 h-5" /> <Download className="w-4 h-4 sm:w-5 sm:h-5" />
<span className="hidden sm:inline">Export</span> <span className="hidden sm:inline text-sm">Export</span>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
{/* Table */} {/* Mobile Card View */}
<div className="overflow-x-auto"> <div className="block lg:hidden">
{filteredReferrals.map((r, idx) => (
<div
key={idx}
className="p-4 border-b border-gray-100 hover:bg-gray-50 transition-colors"
>
<div className="flex items-start justify-between mb-3">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-indigo-500 to-purple-500 flex items-center justify-center text-white font-semibold text-sm">
{r.name.charAt(0)}
</div>
<div>
<div className="font-semibold text-gray-900 text-sm">
{r.name}
</div>
<div className="text-xs text-gray-500">{r.email}</div>
</div>
</div>
<span
className={`inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-semibold ${
r.status === "Active"
? "bg-green-100 text-green-700"
: "bg-yellow-100 text-yellow-700"
}`}
>
{r.status === "Active" ? (
<CheckCircle className="w-3 h-3" />
) : (
<Clock className="w-3 h-3" />
)}
{r.status}
</span>
</div>
<div className="grid grid-cols-2 gap-3 text-sm">
<div>
<div className="text-xs text-gray-500 mb-1">
Signup Date
</div>
<div className="text-gray-700">{r.signupDate}</div>
</div>
<div>
<div className="text-xs text-gray-500 mb-1">Country</div>
<div className="text-gray-700">{r.country}</div>
</div>
<div>
<div className="text-xs text-gray-500 mb-1">
Last Earning
</div>
<div className="font-semibold text-gray-900">
{r.earnings}
</div>
</div>
<div>
<div className="text-xs text-gray-500 mb-1">
Total Commission
</div>
<div className="font-semibold text-gray-900">
{r.totalCommission}
</div>
</div>
</div>
</div>
))}
</div>
{/* Desktop Table View */}
<div className="hidden lg:block overflow-x-auto">
<table className="w-full"> <table className="w-full">
<thead className="bg-gray-50 border-b border-gray-100"> <thead className="bg-gray-50 border-b border-gray-100">
<tr> <tr>
@ -325,18 +395,18 @@ const Referrals: React.FC = () => {
</div> </div>
{/* Table Footer */} {/* Table Footer */}
<div className="p-4 border-t border-gray-100 flex items-center justify-between"> <div className="p-4 border-t border-gray-100 flex flex-col sm:flex-row items-center justify-between gap-4">
<div className="text-sm text-gray-600"> <div className="text-xs sm:text-sm text-gray-600">
Showing{" "} Showing{" "}
<span className="font-semibold">{filteredReferrals.length}</span>{" "} <span className="font-semibold">{filteredReferrals.length}</span>{" "}
of <span className="font-semibold">{referrals.length}</span>{" "} of <span className="font-semibold">{referrals.length}</span>{" "}
referrals referrals
</div> </div>
<div className="flex gap-2"> <div className="flex gap-2">
<button className="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors text-sm font-medium"> <button className="px-3 sm:px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors text-xs sm:text-sm font-medium">
Previous Previous
</button> </button>
<button className="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors text-sm font-medium"> <button className="px-3 sm:px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors text-xs sm:text-sm font-medium">
Next Next
</button> </button>
</div> </div>