diff --git a/package.json b/package.json index 31383a9..933f7c9 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@starknet-react/chains": "^3.1.2", "@starknet-react/core": "^3.7.2", "@starknet-react/typescript-config": "^0.0.1", + "chart.js": "^4.4.9", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "framer-motion": "^12.5.0", diff --git a/public/braavos.svg b/public/braavos.svg new file mode 100644 index 0000000..19f7949 --- /dev/null +++ b/public/braavos.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/paste-icon.svg b/public/paste-icon.svg new file mode 100644 index 0000000..64f21d4 --- /dev/null +++ b/public/paste-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/app/book-lisiting-page/page.tsx b/src/app/book-lisiting-page/page.tsx index 5fb04a4..5513879 100644 --- a/src/app/book-lisiting-page/page.tsx +++ b/src/app/book-lisiting-page/page.tsx @@ -6,10 +6,8 @@ import ExploreBooks from "@/components/BookListingPage/ExploreBooks"; import NewRelease from "@/components/BookListingPage/NewRelease"; import NftEdition from "@/components/BookListingPage/NftEdition"; import Trending from "@/components/BookListingPage/Trending"; -import Footer from "@/components/layout/Footer"; -import Header from "@/components/layout/Header"; import { Input } from "@/components/ui/input"; -import bookData from "@/lib/MockData"; +import { bookData } from "@/lib/MockData"; import { useMemo, useState } from "react"; @@ -80,7 +78,6 @@ export default function Page() { return (
-
@@ -99,7 +96,7 @@ export default function Page() { -
) } \ No newline at end of file diff --git a/src/app/book-lisiting-page/review/[id]/page.tsx b/src/app/book-lisiting-page/review/[id]/page.tsx index 77b4011..dafb59e 100644 --- a/src/app/book-lisiting-page/review/[id]/page.tsx +++ b/src/app/book-lisiting-page/review/[id]/page.tsx @@ -1,7 +1,7 @@ "use client" -import bookData from '@/lib/MockData'; +import { bookData } from '@/lib/MockData'; import { useParams } from 'next/navigation'; diff --git a/src/app/dashboard/earnings/page.tsx b/src/app/dashboard/earnings/page.tsx index 34a4e59..60cbf2a 100644 --- a/src/app/dashboard/earnings/page.tsx +++ b/src/app/dashboard/earnings/page.tsx @@ -1,12 +1,104 @@ +"use client" + + +import EarningsSummary from "@/components/ dashboard-earnings/EarningSummary" +import LinkWallet from "@/components/ dashboard-earnings/LinkWallet" +import RevenueBreakdown from "@/components/ dashboard-earnings/RevenueBreakdown" +import type { EarningTab } from "@/lib/interfaces/EarningTabInterface" +import { RevenueChartInterface } from "@/lib/interfaces/RevenueChartInterface" +import { useEffect, useState } from "react" +import TransactionHistory from "../../../components/ dashboard-earnings/TransactionHistory" +import RequestPaymentModal from "@/components/ dashboard-earnings/RequestPaymentModal" +import { PaymentPropInterface } from "@/lib/interfaces/PaymentPropInterface" + + +const earningsSumaryDetails: EarningTab[] = [ + { title: "Current Balance", amount: 3150.0 , border: "#D6ECFF" }, + { title: "Pending Payout", amount: 100.06, border: "#2396413D" }, + { title: "Total Payout", amount: 2500.01, border: "#822ECB3D" }, + { title: "Total Earned", amount: 2730.19, border: "#D6ECFF" }, +] + + + + +const chartData: RevenueChartInterface[] = [ + { + name: "Monthly Subcription Payment", + value: 121, + color: "#236FEA", + percentage: "40%" + }, + { + name: "NFT Royalty", + value: 12, + color: "#FBBC05", + percentage: "10%" + }, + { + name: "NFT", + value: 101, + color: "#822ECB", + percentage: "22%" + }, + { + name: "Book Purchase", + value: 131, + color: "#34A853", + percentage: "28%" + }, +] + + + function EarningsPage() { + const [openRequestModal, setOpenRequestModal] = useState(false) + const [walletAddress, setWalletAddress] = useState({ + braavos: "", + argent: "", + }) + + const ADDRESS_KEY = "walletAddressKey" + + const [paymentDetails, setPaymentDetails] = useState ({ + amount: 0.00, + wallet: "", + walletAddress: "" +}) + + + + // This function loads saved addresses + useEffect(() => { + const savedAddresses = localStorage.getItem(ADDRESS_KEY) + if (savedAddresses) { + try { + const parsedAddresses = JSON.parse(savedAddresses) + setWalletAddress(parsedAddresses) + } + catch (error) { + console.error("Failed to parse saved addresses:", error) + } + } + }, []) + + + // this function saves wallet address to local storage + useEffect(() => { + if (walletAddress.braavos || walletAddress.argent) { + localStorage.setItem(ADDRESS_KEY, JSON.stringify(walletAddress)) + } + }, [walletAddress]) + return ( -
-

Earnings

-

- This is the earnings page. You can view your earnings here. -

+
+ + + + +{openRequestModal && }
- ); + ) } -export default EarningsPage; +export default EarningsPage diff --git a/src/app/globals.css b/src/app/globals.css index 98ac33e..25a91f5 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -84,6 +84,7 @@ /* Font Family */ --font-sans: var(--font-geist-sans); --font-mono: var(--font-geist-mono); + --font-inter: var(--font-inter); /* DIsplay TextSizes */ --text-display-large: 57px; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 1cfd19d..2747eb3 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -4,19 +4,26 @@ import NavBar from "@/components/landingpage/NavBar"; import Footer from "@/components/landingpage/Footer"; import { WalletProvider } from "../components/blockchain/WalletProvider"; import { StarknetProvider } from "../components/blockchain/Providers"; +import { Inter } from "next/font/google"; export const metadata: Metadata = { title: "ChainLib", description: "An E-Libray Platform", }; +const inter = Inter({ + subsets: ["latin"], + display: "swap", + variable: "--font-inter", +}); + export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( - + diff --git a/src/components/ dashboard-earnings/Chart.tsx b/src/components/ dashboard-earnings/Chart.tsx new file mode 100644 index 0000000..07a53f1 --- /dev/null +++ b/src/components/ dashboard-earnings/Chart.tsx @@ -0,0 +1,51 @@ +import { RevenueChartInterface } from "@/lib/interfaces/RevenueChartInterface"; +import { + BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, + Cell +} from 'recharts'; + + + +interface RevenueChartProps { + chartData: RevenueChartInterface[] +} + + + +export default function RevenueChart({chartData}: RevenueChartProps) { + + + + + + + + + return ( + +
+ + + + + `$${value}`} tick={{ dy: 10 }} tickLine={false} axisLine={{ stroke: '#D1D1D1', strokeWidth: 1 }} /> + + + + {chartData.map((entry, index) => ( + + ))} + + + + + + + +
+ ) +} \ No newline at end of file diff --git a/src/components/ dashboard-earnings/EarningSummary.tsx b/src/components/ dashboard-earnings/EarningSummary.tsx new file mode 100644 index 0000000..64c9b4e --- /dev/null +++ b/src/components/ dashboard-earnings/EarningSummary.tsx @@ -0,0 +1,38 @@ +import type { EarningTab } from "@/lib/interfaces/EarningTabInterface" +import { Button } from "../ui/button" +import Image from "next/image" +import React from "react" + +interface EarningsSummaryProps { + earningsSumaryDetails: EarningTab[] + setOpenRequestModal: React.Dispatch> +} + +const EarningsSummary = ({ earningsSumaryDetails, setOpenRequestModal }: EarningsSummaryProps) => { + return ( +
+
+ {earningsSumaryDetails.map((item, index) => ( +
+

{item.title}

+ +
+ icon +

{item.amount.toFixed(2)}

+
+
+ ))} +
+ + +
+ ) +} + +export default EarningsSummary diff --git a/src/components/ dashboard-earnings/FilterBar.tsx b/src/components/ dashboard-earnings/FilterBar.tsx new file mode 100644 index 0000000..90c250d --- /dev/null +++ b/src/components/ dashboard-earnings/FilterBar.tsx @@ -0,0 +1,47 @@ +import { Input } from "../ui/input"; + + +export default function FilterBar() { + return ( +
+
+ + + +
+ + +
+ + + +to + + + + + + + + + +
+ + + +
+ +
+
+ ); +} diff --git a/src/components/ dashboard-earnings/LinkWallet.tsx b/src/components/ dashboard-earnings/LinkWallet.tsx new file mode 100644 index 0000000..25097f6 --- /dev/null +++ b/src/components/ dashboard-earnings/LinkWallet.tsx @@ -0,0 +1,102 @@ +"use client" + +import type React from "react" + +import Image from "next/image" +import { Input } from "../ui/input" +import { handlePaste } from "../../lib/utils" + +export interface WalletAddressType { + braavos: string + argent: string +} + +interface LinkWalletProps { + walletAddress: WalletAddressType + setWalletAddress: React.Dispatch> +} + +export default function LinkWallet({ walletAddress, setWalletAddress }: LinkWalletProps) { + const handleChange = (e: React.FormEvent) => { + const target = e.target as HTMLInputElement + const { name, value } = target + + setWalletAddress((prev) => ({ + ...prev, + [name]: value, + })) + } + + return ( +
+
+

Link Wallet

+ + Change Wallet Address + +
+ +
+
+
+
+ Wallet Icon +

+ Braavos (Starknet) +

+
+
+ +
+ + +
+
+ +
+
+
+ Wallet Icon +

+ Argent (Starknet) +

+
+
+ +
+ + +
+
+
+
+ ) +} diff --git a/src/components/ dashboard-earnings/LoanRow.tsx b/src/components/ dashboard-earnings/LoanRow.tsx new file mode 100644 index 0000000..7bde864 --- /dev/null +++ b/src/components/ dashboard-earnings/LoanRow.tsx @@ -0,0 +1,33 @@ +import { TransactionHistoryInterface } from "@/lib/interfaces/TransactionIHistoryInterface"; +import { formatDate } from "@/lib/utils"; +import React from "react"; +import TransactionModalButton from "./TransactionModalButton"; + + +interface LoanRowProps { + tableData: TransactionHistoryInterface + +} + + + +export default function LoanRow({ tableData}: LoanRowProps) { + + + + + + + return ( + + {tableData.transactionId} + {tableData.transactionType} + {tableData.amount} STRK + {tableData.status ? "Successful" : "Failed"} + {formatDate(tableData.date)} + + + + + ); +} diff --git a/src/components/ dashboard-earnings/MobileLoanRow.tsx b/src/components/ dashboard-earnings/MobileLoanRow.tsx new file mode 100644 index 0000000..40534d2 --- /dev/null +++ b/src/components/ dashboard-earnings/MobileLoanRow.tsx @@ -0,0 +1,29 @@ +import { TransactionHistoryInterface } from "@/lib/interfaces/TransactionIHistoryInterface"; +import { formatDate } from "@/lib/utils"; +import React from "react"; + + +interface MobileLoanRowProps { + tableData: TransactionHistoryInterface + +} + + + +export default function MobileLoanRow({ tableData }: MobileLoanRowProps) { + + + + + + + return ( + + {tableData.transactionType} {formatDate(tableData.date)} + {tableData.amount} STRK + {tableData.status ? "Successful" : "Failed"} + + + + ); +} diff --git a/src/components/ dashboard-earnings/MobileTable.tsx b/src/components/ dashboard-earnings/MobileTable.tsx new file mode 100644 index 0000000..7ab2c2f --- /dev/null +++ b/src/components/ dashboard-earnings/MobileTable.tsx @@ -0,0 +1,93 @@ +"use client" + +import { ChevronLeft, ChevronRight } from "lucide-react" +import type { TransactionHistoryInterface } from "@/lib/interfaces/TransactionIHistoryInterface" +import MobileLoanRow from "./MobileLoanRow" + +interface MobileTableProps { + transactionHistoryData: TransactionHistoryInterface[] + startIndex: number + endIndex: number + currentPage: number + totalPages: number + handlePrev: () => void + handleNext: () => void + generatePagination: () => (number | string)[] + setCurrentPage: (page: number) => void +} + +export default function MobileTable({ + transactionHistoryData, + startIndex, + endIndex, + currentPage, + totalPages, + handlePrev, + handleNext, + generatePagination, + setCurrentPage, +}: MobileTableProps) { + return ( +
+
+ + + + + + + + + {transactionHistoryData.slice(startIndex, endIndex).map((loanDetails, i) => ( + + ))} + +
Transaction TypeAmount (USD)
+
+ + {/* Mobile Pagination Footer */} +
+

+ Showing {startIndex + 1} to{" "} + {endIndex > transactionHistoryData.length ? transactionHistoryData.length : endIndex} of{" "} + {transactionHistoryData.length} +

+ +
+ + +
    + {generatePagination().map((page, index) => ( +
  • typeof page === "number" && setCurrentPage(page)} + className={`px-2 py-1 rounded cursor-pointer text-xs ${page === currentPage + ? "text-[#096CFF] bg-[#096CFF]/10" + : typeof page === "number" + ? "text-[#888888] hover:text-[#096CFF]" + : "cursor-default text-[#888888]" + }`} + > + {page} +
  • + ))} +
+ + +
+
+
+ ) +} diff --git a/src/components/ dashboard-earnings/RequestPaymentModal.tsx b/src/components/ dashboard-earnings/RequestPaymentModal.tsx new file mode 100644 index 0000000..5f38a7a --- /dev/null +++ b/src/components/ dashboard-earnings/RequestPaymentModal.tsx @@ -0,0 +1,231 @@ +"use client" + +import { X } from "lucide-react" +import { Button } from "@/components/ui/button" +import type { PaymentPropInterface } from "@/lib/interfaces/PaymentPropInterface" +import Image from "next/image" +import { Input } from "@/components/ui/input" +import type React from "react" +import { useState } from "react" +import type { WalletAddressType } from "./LinkWallet" + +interface RequestPaymentModalProps { + paymentDetails: PaymentPropInterface + setPaymentDetails: React.Dispatch> + walletAddress: WalletAddressType + setOpenRequestModal: React.Dispatch> +} + +export default function RequestPaymentModal({paymentDetails, setPaymentDetails, walletAddress, setOpenRequestModal,}: RequestPaymentModalProps) { + const [selectedWallet, setSelectedWallet] = useState<"argent" | "braavos">("argent") + const [currentStep, setCurrentStep] = useState("1") + + const maxBalance = 1793 + + const handleAmountChange = (event: React.ChangeEvent) => { + const value = event.target.value.replace(/[^\d.]/g, "") + const numericValue = Number.parseFloat(value) || 0 + + + const finalValue = Math.min(numericValue, maxBalance) + + setPaymentDetails((prev) => ({ + ...prev, + amount: finalValue, + })) + } + + const handleMaxClick = () => { + setPaymentDetails((prev) => ({ + ...prev, + amount: maxBalance, + })) + } + + const handleWalletChange = (event: React.ChangeEvent) => { + const wallet = event.target.value as "argent" | "braavos" + setSelectedWallet(wallet) + + setPaymentDetails((prev) => ({ + ...prev, + walletAddress: walletAddress[wallet] || "", + selectedWallet: wallet, + })) + } + + const truncateWalletAddress = (address: string) => { + if (!address || address.length < 12) return address + return address.slice(0, 5) + "....." + address.slice(-6) + } + + const currentWalletAddress = walletAddress[selectedWallet] || "" + const truncatedAddress = truncateWalletAddress(currentWalletAddress) + + + + const submitRequest = () => { + alert("Confirmed") + setPaymentDetails({ + amount: 0, + wallet: "", + walletAddress: "" + }) + setOpenRequestModal(false) + } + + return ( +
setOpenRequestModal(false)} + className="w-full h-screen fixed top-0 left-0 bg-black/50 px-5 py-10 z-50" + > +
+ + + +
e.stopPropagation()} + className={`w-full max-w-[621px] bg-[#ffffff] min-w-[300px] flex flex-col py-4 px-6 gap-4 rounded-2xl transform duration-150 ease-in-out absolute ${ currentStep === "1" ? "translate-x-0" : "translate-x-[-300%] " }`} + > + + +

Request Payment

+ +
+
+

Current Balance Subtotal

+

+ icon + {maxBalance} STRK +

+
+ +
+
+

Enter Amount

+

($12 USDT)

+
+ +
+ {"token + + STRK + +
+ +
+

Destination wallet address

+
+ + + + {currentWalletAddress ? truncatedAddress : "--"} + +
+
+
+
+ + +
+ + + + + + +
e.stopPropagation()} + className={`w-full max-w-[621px] bg-[#ffffff] min-w-[300px] flex flex-col py-4 px-6 gap-4 rounded-2xl transform duration-150 ease-in-out absolute ${ currentStep === "2" ? "translate-x-0" : "translate-x-[300%] " }`} + > + + +

Confirm Details

+ +
+
+

Amount to be sent

+ +
+

icon {paymentDetails.amount} STRK

+
($12 USDT)
+ +
+ +
+ + +
+

Destination wallet address

+ + {currentWalletAddress ? truncatedAddress : "--"} + +
+ + +
+

Gas fees

+
icon 8 STRK
+
+ + + +
+

Estimated time of delivery

+
24-48 Hours
+ +
+ +
+ + +
+
+
+ ) +} diff --git a/src/components/ dashboard-earnings/RevenueBreakdown.tsx b/src/components/ dashboard-earnings/RevenueBreakdown.tsx new file mode 100644 index 0000000..a041dce --- /dev/null +++ b/src/components/ dashboard-earnings/RevenueBreakdown.tsx @@ -0,0 +1,40 @@ +import { RevenueChartInterface } from "@/lib/interfaces/RevenueChartInterface"; +import RevenueChart from "./Chart"; + + + + +interface RevenueBreakdownProps { + chartData: RevenueChartInterface[] +} + + + + +export default function RevenueBreakdown({ chartData }: RevenueBreakdownProps) { + return ( +
+ +

Revenue Breakdown

+ + + + + +
+ + + + + +
    + + {chartData.map((item, index) => ( +
  • {item.name}
  • + ))} + +
+
+
+ ) +} \ No newline at end of file diff --git a/src/components/ dashboard-earnings/TransactionHistory.tsx b/src/components/ dashboard-earnings/TransactionHistory.tsx new file mode 100644 index 0000000..f66368a --- /dev/null +++ b/src/components/ dashboard-earnings/TransactionHistory.tsx @@ -0,0 +1,28 @@ +import TransactionTable from "./TransactionTable"; + + + + + +export default function TransactionHistory() { + return ( +
+

Transaction History

+ + + + + + + + + + + + + + + +
+ ) +} \ No newline at end of file diff --git a/src/components/ dashboard-earnings/TransactionModalButton.tsx b/src/components/ dashboard-earnings/TransactionModalButton.tsx new file mode 100644 index 0000000..716e43e --- /dev/null +++ b/src/components/ dashboard-earnings/TransactionModalButton.tsx @@ -0,0 +1,213 @@ +"use client" + +import * as React from "react" +import Box from "@mui/material/Box" +import Modal from "@mui/material/Modal" +import { Upload, X } from "lucide-react" +import { Button, Stack } from "@mui/material" +import Image from "next/image" + +const style = { + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: "100%", + minWidth: "350px", + maxWidth: "853px", + height: "full", + bgcolor: "#FFFFFF", + border: "none", + boxShadow: 24, + paddingTop: "24px", + paddingBottom: "24px", + borderRadius: "8px", +} + + + +const amountDetails = [ + { + heading: "Amount Paid", + value: 800.00, + }, + { + heading: "Royalty Earned", + value: 80.00, + }, + { + heading: "Platform Commission", + value: 80.00, + }, +] + + +const transactionDetails = [ + { + heading: "Transaction Type", + value: "Book Purchase", + }, + { + heading: "Status", + value: Successful, + }, + { + heading: "Date", + value: "12 March, 2025 ", + }, + { + heading: "Time", + value: "16:32 ", + }, +] + + + +const NFTdetails = [ + { + heading: "NFT ID", + value: "#0002", + }, + { + heading: "Buyer", + value: "USER-0001", + }, + { + heading: "Transaction ID", + value: "TRANS-00112", + }, + { + heading: "Transaction Hash", + value: <>

0x5a3f7b...d6e7f8g

+ }, + { + heading: "Confirmation Status", + value: "12/12", + }, +] + +export default function TransactionModalButton() { + const [open, setOpen] = React.useState(false) + const handleOpen = () => setOpen(true) + const handleClose = () => setOpen(false) + + return ( +
+ + + +
+ +

Transaction Details

+ + + + + + + + + + + +

99 Laws of Power

+

NFT Edition

+

eBook

+
+
+ + +
+ + + + + {amountDetails.map((item, index) => ( + +

token icon {item.heading}

+

token icon {item.value} STRK

+ ))} +
+ +
+ + + + + + + + + + + + {transactionDetails.map((item, index) => ( + +

{item.heading}

+

{item.value}

+ ))} +
+ + + + + +
+ + + + {NFTdetails.map((item, index) => ( + +

{item.heading}

+

{item.value}

+ ))} +
+ +
+ + + + + +
+ + + + + + + +
+
+
+
+
+ ) +} diff --git a/src/components/ dashboard-earnings/TransactionTable.tsx b/src/components/ dashboard-earnings/TransactionTable.tsx new file mode 100644 index 0000000..ea7e4b8 --- /dev/null +++ b/src/components/ dashboard-earnings/TransactionTable.tsx @@ -0,0 +1,132 @@ +import React, { useState } from 'react'; +import { ChevronLeft, ChevronRight } from 'lucide-react'; +import { transactionHistoryData } from '@/lib/MockData'; +import FilterBar from './FilterBar'; +import LoanRow from './LoanRow'; +import MobileTable from './MobileTable'; +import useIsMobile from '@/lib/hooks/useIsMobile'; + + +export default function TransactionTable() { + const [currentPage, setCurrentPage] = useState(1); + const itemsPerPage = 5; + const totalPages = Math.ceil(transactionHistoryData.length / itemsPerPage); + + const startIndex = (currentPage - 1) * itemsPerPage; + const endIndex = currentPage * itemsPerPage; + + const handlePrev = () => { + if (currentPage > 1) setCurrentPage((prev) => prev - 1); + }; + + const handleNext = () => { + if (currentPage < totalPages) setCurrentPage((prev) => prev + 1); + }; + + const generatePagination = () => { + const delta = 1; + const range = []; + const left = Math.max(2, currentPage - delta); + const right = Math.min(totalPages - 1, currentPage + delta); + + range.push(1); + if (left > 2) range.push('...'); + + for (let i = left; i <= right; i++) { + range.push(i); + } + + if (right < totalPages - 1) range.push('...'); + if (totalPages > 1) range.push(totalPages); + + return range; + }; + + const isMobile = useIsMobile(); + + if (!isMobile) { + return ( +
+ + +
+ + + + + + + + + + + + + {transactionHistoryData.slice(startIndex, endIndex).map((loanDetails, i) => ( + + ))} + +
Transaction IDTransaction TypeAmount (STRK)StatusDate
+ + {/* Pagination Footer */} +
+

+ Showing {startIndex + 1} to{' '} + {endIndex > transactionHistoryData.length ? transactionHistoryData.length : endIndex} of{' '} + {transactionHistoryData.length} +

+ +
+ + + + +
    + {generatePagination().map((page, index) => ( +
  • typeof page === 'number' && setCurrentPage(page)} + className={`px-2 py-1 rounded cursor-pointer text-sm ${page === currentPage + ? 'text-[#096CFF]' + : typeof page === 'number' + ? 'text-[#888888] hover:text-[#096CFF]' + : 'cursor-default text-[#888888]' + }`} + > + {page} +
  • + ))} +
+
+
+
+
+ ); + } + + return ( + + ); +} diff --git a/src/components/BookListingPage/NewRelease.tsx b/src/components/BookListingPage/NewRelease.tsx index 7302aa2..0ba2a4b 100644 --- a/src/components/BookListingPage/NewRelease.tsx +++ b/src/components/BookListingPage/NewRelease.tsx @@ -1,9 +1,9 @@ "use client" -import bookData from "@/lib/MockData"; import BookCard from "../reader/BookCard"; import { useState } from "react"; import { Button } from "../ui/button"; import Spinner from "../ui/Spinner"; +import { bookData } from "@/lib/MockData"; diff --git a/src/components/BookListingPage/NftEdition.tsx b/src/components/BookListingPage/NftEdition.tsx index c5972ea..62b46dc 100644 --- a/src/components/BookListingPage/NftEdition.tsx +++ b/src/components/BookListingPage/NftEdition.tsx @@ -1,6 +1,7 @@ "use client" -import bookData from "@/lib/MockData"; + +import { bookData } from "@/lib/MockData"; import BookCard from "../reader/BookCard"; import { Splide, SplideSlide } from '@splidejs/react-splide'; import '@splidejs/react-splide/css'; diff --git a/src/components/BookListingPage/Trending.tsx b/src/components/BookListingPage/Trending.tsx index c1f143d..47402e6 100644 --- a/src/components/BookListingPage/Trending.tsx +++ b/src/components/BookListingPage/Trending.tsx @@ -1,9 +1,10 @@ "use client" -import bookData from "@/lib/MockData"; + import BookCard from "../reader/BookCard"; import { useState } from "react"; import { Button } from "../ui/button"; import Spinner from "../ui/Spinner"; +import { bookData } from "@/lib/MockData"; export default function Trending() { diff --git a/src/components/common/Modal.tsx b/src/components/common/Modal.tsx index 4ed36e3..0f100f8 100644 --- a/src/components/common/Modal.tsx +++ b/src/components/common/Modal.tsx @@ -48,18 +48,18 @@ export default function ProfileCompletionModal({ return (
-
e.stopPropagation()} > - - +
@@ -70,15 +70,15 @@ export default function ProfileCompletionModal({ experience and connect you with the right opportunities.

- +
- -
); -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/components/layout/Footer.tsx b/src/components/layout/Footer.tsx deleted file mode 100644 index f1f436c..0000000 --- a/src/components/layout/Footer.tsx +++ /dev/null @@ -1,10 +0,0 @@ - - -function Footer (){ - return( -

Footer

- ) -} - - -export default Footer; \ No newline at end of file diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx deleted file mode 100644 index 8e633cd..0000000 --- a/src/components/layout/Header.tsx +++ /dev/null @@ -1,11 +0,0 @@ - - - -function Header(){ - return( -

Header

- ) -} - - -export default Header; \ No newline at end of file diff --git a/src/lib/MockData.ts b/src/lib/MockData.ts index 9a66898..743cb29 100644 --- a/src/lib/MockData.ts +++ b/src/lib/MockData.ts @@ -1,36 +1,448 @@ import { Book } from "./interfaces/BookInterface"; +import { TransactionHistoryInterface } from "./interfaces/TransactionIHistoryInterface"; -const bookData: Book[] = [ - { id: 1, bookTitle: "Native Invisibility", author: "Darrin Collins", isNFT: true, image: "/images/bookCover1.png", price: 15, rating: 4, date: new Date("2024-04-01") }, - { id: 2, bookTitle: "Whispers of Tomorrow", author: "Lena Fitzgerald", isNFT: false, image: "/images/bookCover1.png", price: 22, rating: 3, date: new Date("2024-03-28") }, - { id: 3, bookTitle: "Echoes of the Forgotten", author: "Marcus Reed", isNFT: true, image: "/images/bookCover1.png", price: 30, rating: 5, date: new Date("2024-04-20") }, - { id: 4, bookTitle: "Fragments of Reality", author: "Sophia Turner", isNFT: false, image: "/images/bookCover1.png", price: 18, rating: 2, date: new Date("2024-04-15") }, - { id: 5, bookTitle: "The Last Horizon", author: "Isaiah Brooks", isNFT: true, image: "/images/bookCover1.png", price: 35, rating: 5, date: new Date("2024-02-10") }, - { id: 6, bookTitle: "Silent Songs", author: "Amelia Hart", isNFT: false, image: "/images/bookCover1.png", price: 27, rating: 3, date: new Date("2024-01-30") }, - { id: 7, bookTitle: "Beyond the Edge", author: "Noah Chambers", isNFT: true, image: "/images/bookCover1.png", price: 24, rating: 4, date: new Date("2024-04-22") }, - { id: 8, bookTitle: "Twilight's Embrace", author: "Olivia Bennett", isNFT: false, image: "/images/bookCover1.png", price: 20, rating: 2, date: new Date("2024-03-12") }, - { id: 9, bookTitle: "Shadows and Sparks", author: "Ethan Cruz", isNFT: true, image: "/images/bookCover1.png", price: 32, rating: 5, date: new Date("2024-04-19") }, - { id: 10, bookTitle: "Canvas of Dreams", author: "Maya Jensen", isNFT: false, image: "/images/bookCover1.png", price: 14, rating: 1, date: new Date("2024-03-05") }, - { id: 11, bookTitle: "Winds of Destiny", author: "Lucas Hayes", isNFT: true, image: "/images/bookCover1.png", price: 38, rating: 5, date: new Date("2024-04-23") }, - { id: 12, bookTitle: "Mirror of Illusions", author: "Ella Simmons", isNFT: false, image: "/images/bookCover1.png", price: 17, rating: 2, date: new Date("2024-02-28") }, - { id: 13, bookTitle: "Veil of Secrets", author: "Gabriel Vaughn", isNFT: true, image: "/images/bookCover1.png", price: 29, rating: 4, date: new Date("2024-04-18") }, - { id: 14, bookTitle: "Tides of Memory", author: "Chloe Monroe", isNFT: false, image: "/images/bookCover1.png", price: 19, rating: 3, date: new Date("2024-01-18") }, - { id: 15, bookTitle: "Broken Compass", author: "Henry Castillo", isNFT: true, image: "/images/bookCover1.png", price: 36, rating: 5, date: new Date("2024-04-21") }, - { id: 16, bookTitle: "Letters to Nowhere", author: "Aria Flores", isNFT: false, image: "/images/bookCover1.png", price: 12, rating: 2, date: new Date("2024-03-07") }, - { id: 17, bookTitle: "Crimson Skies", author: "Leo Montgomery", isNFT: true, image: "/images/bookCover1.png", price: 25, rating: 5, date: new Date("2024-04-11") }, - { id: 18, bookTitle: "Paths Uncharted", author: "Zoe Wallace", isNFT: false, image: "/images/bookCover1.png", price: 21, rating: 3, date: new Date("2024-02-25") }, - { id: 19, bookTitle: "Silent Reverie", author: "Nathaniel West", isNFT: true, image: "/images/bookCover1.png", price: 34, rating: 4, date: new Date("2024-04-16") }, - { id: 20, bookTitle: "Gates of Tomorrow", author: "Lily Armstrong", isNFT: false, image: "/images/bookCover1.png", price: 13, rating: 1, date: new Date("2024-02-11") }, - { id: 21, bookTitle: "Beneath the Surface", author: "Mason Ellis", isNFT: true, image: "/images/bookCover1.png", price: 40, rating: 5, date: new Date("2024-04-26") }, - { id: 22, bookTitle: "Embers of Hope", author: "Grace Nolan", isNFT: false, image: "/images/bookCover1.png", price: 16, rating: 2, date: new Date("2024-03-18") }, - { id: 23, bookTitle: "River of Stars", author: "Sebastian Keller", isNFT: true, image: "/images/bookCover1.png", price: 28, rating: 4, date: new Date("2024-04-24") }, - { id: 24, bookTitle: "Secrets of the Deep", author: "Isla Warner", isNFT: false, image: "/images/bookCover1.png", price: 23, rating: 3, date: new Date("2024-01-15") }, - { id: 25, bookTitle: "Ashes and Echoes", author: "Owen Sharp", isNFT: true, image: "/images/bookCover1.png", price: 39, rating: 5, date: new Date("2024-04-17") }, - { id: 26, bookTitle: "Whispers in the Wind", author: "Sienna Cross", isNFT: false, image: "/images/bookCover1.png", price: 11, rating: 2, date: new Date("2024-03-09") }, - { id: 27, bookTitle: "Lanterns of the Past", author: "Caleb Drake", isNFT: true, image: "/images/bookCover1.png", price: 37, rating: 5, date: new Date("2024-04-13") }, - { id: 28, bookTitle: "Moonlight Sonata", author: "Hannah Frost", isNFT: false, image: "/images/bookCover1.png", price: 26, rating: 4, date: new Date("2024-03-01") }, - { id: 29, bookTitle: "Valley of Mist", author: "Dominic Rhodes", isNFT: true, image: "/images/bookCover1.png", price: 31, rating: 5, date: new Date("2024-04-12") }, - { id: 30, bookTitle: "Songs of the Sea", author: "Penelope Brooks", isNFT: false, image: "/images/bookCover1.png", price: 15, rating: 2, date: new Date("2024-02-07") }, +export const bookData: Book[] = [ + { + id: 1, + bookTitle: "Native Invisibility", + author: "Darrin Collins", + isNFT: true, + image: "/images/bookCover1.png", + price: 15, + rating: 4, + date: new Date("2024-04-01"), + }, + { + id: 2, + bookTitle: "Whispers of Tomorrow", + author: "Lena Fitzgerald", + isNFT: false, + image: "/images/bookCover1.png", + price: 22, + rating: 3, + date: new Date("2024-03-28"), + }, + { + id: 3, + bookTitle: "Echoes of the Forgotten", + author: "Marcus Reed", + isNFT: true, + image: "/images/bookCover1.png", + price: 30, + rating: 5, + date: new Date("2024-04-20"), + }, + { + id: 4, + bookTitle: "Fragments of Reality", + author: "Sophia Turner", + isNFT: false, + image: "/images/bookCover1.png", + price: 18, + rating: 2, + date: new Date("2024-04-15"), + }, + { + id: 5, + bookTitle: "The Last Horizon", + author: "Isaiah Brooks", + isNFT: true, + image: "/images/bookCover1.png", + price: 35, + rating: 5, + date: new Date("2024-02-10"), + }, + { + id: 6, + bookTitle: "Silent Songs", + author: "Amelia Hart", + isNFT: false, + image: "/images/bookCover1.png", + price: 27, + rating: 3, + date: new Date("2024-01-30"), + }, + { + id: 7, + bookTitle: "Beyond the Edge", + author: "Noah Chambers", + isNFT: true, + image: "/images/bookCover1.png", + price: 24, + rating: 4, + date: new Date("2024-04-22"), + }, + { + id: 8, + bookTitle: "Twilight's Embrace", + author: "Olivia Bennett", + isNFT: false, + image: "/images/bookCover1.png", + price: 20, + rating: 2, + date: new Date("2024-03-12"), + }, + { + id: 9, + bookTitle: "Shadows and Sparks", + author: "Ethan Cruz", + isNFT: true, + image: "/images/bookCover1.png", + price: 32, + rating: 5, + date: new Date("2024-04-19"), + }, + { + id: 10, + bookTitle: "Canvas of Dreams", + author: "Maya Jensen", + isNFT: false, + image: "/images/bookCover1.png", + price: 14, + rating: 1, + date: new Date("2024-03-05"), + }, + { + id: 11, + bookTitle: "Winds of Destiny", + author: "Lucas Hayes", + isNFT: true, + image: "/images/bookCover1.png", + price: 38, + rating: 5, + date: new Date("2024-04-23"), + }, + { + id: 12, + bookTitle: "Mirror of Illusions", + author: "Ella Simmons", + isNFT: false, + image: "/images/bookCover1.png", + price: 17, + rating: 2, + date: new Date("2024-02-28"), + }, + { + id: 13, + bookTitle: "Veil of Secrets", + author: "Gabriel Vaughn", + isNFT: true, + image: "/images/bookCover1.png", + price: 29, + rating: 4, + date: new Date("2024-04-18"), + }, + { + id: 14, + bookTitle: "Tides of Memory", + author: "Chloe Monroe", + isNFT: false, + image: "/images/bookCover1.png", + price: 19, + rating: 3, + date: new Date("2024-01-18"), + }, + { + id: 15, + bookTitle: "Broken Compass", + author: "Henry Castillo", + isNFT: true, + image: "/images/bookCover1.png", + price: 36, + rating: 5, + date: new Date("2024-04-21"), + }, + { + id: 16, + bookTitle: "Letters to Nowhere", + author: "Aria Flores", + isNFT: false, + image: "/images/bookCover1.png", + price: 12, + rating: 2, + date: new Date("2024-03-07"), + }, + { + id: 17, + bookTitle: "Crimson Skies", + author: "Leo Montgomery", + isNFT: true, + image: "/images/bookCover1.png", + price: 25, + rating: 5, + date: new Date("2024-04-11"), + }, + { + id: 18, + bookTitle: "Paths Uncharted", + author: "Zoe Wallace", + isNFT: false, + image: "/images/bookCover1.png", + price: 21, + rating: 3, + date: new Date("2024-02-25"), + }, + { + id: 19, + bookTitle: "Silent Reverie", + author: "Nathaniel West", + isNFT: true, + image: "/images/bookCover1.png", + price: 34, + rating: 4, + date: new Date("2024-04-16"), + }, + { + id: 20, + bookTitle: "Gates of Tomorrow", + author: "Lily Armstrong", + isNFT: false, + image: "/images/bookCover1.png", + price: 13, + rating: 1, + date: new Date("2024-02-11"), + }, + { + id: 21, + bookTitle: "Beneath the Surface", + author: "Mason Ellis", + isNFT: true, + image: "/images/bookCover1.png", + price: 40, + rating: 5, + date: new Date("2024-04-26"), + }, + { + id: 22, + bookTitle: "Embers of Hope", + author: "Grace Nolan", + isNFT: false, + image: "/images/bookCover1.png", + price: 16, + rating: 2, + date: new Date("2024-03-18"), + }, + { + id: 23, + bookTitle: "River of Stars", + author: "Sebastian Keller", + isNFT: true, + image: "/images/bookCover1.png", + price: 28, + rating: 4, + date: new Date("2024-04-24"), + }, + { + id: 24, + bookTitle: "Secrets of the Deep", + author: "Isla Warner", + isNFT: false, + image: "/images/bookCover1.png", + price: 23, + rating: 3, + date: new Date("2024-01-15"), + }, + { + id: 25, + bookTitle: "Ashes and Echoes", + author: "Owen Sharp", + isNFT: true, + image: "/images/bookCover1.png", + price: 39, + rating: 5, + date: new Date("2024-04-17"), + }, + { + id: 26, + bookTitle: "Whispers in the Wind", + author: "Sienna Cross", + isNFT: false, + image: "/images/bookCover1.png", + price: 11, + rating: 2, + date: new Date("2024-03-09"), + }, + { + id: 27, + bookTitle: "Lanterns of the Past", + author: "Caleb Drake", + isNFT: true, + image: "/images/bookCover1.png", + price: 37, + rating: 5, + date: new Date("2024-04-13"), + }, + { + id: 28, + bookTitle: "Moonlight Sonata", + author: "Hannah Frost", + isNFT: false, + image: "/images/bookCover1.png", + price: 26, + rating: 4, + date: new Date("2024-03-01"), + }, + { + id: 29, + bookTitle: "Valley of Mist", + author: "Dominic Rhodes", + isNFT: true, + image: "/images/bookCover1.png", + price: 31, + rating: 5, + date: new Date("2024-04-12"), + }, + { + id: 30, + bookTitle: "Songs of the Sea", + author: "Penelope Brooks", + isNFT: false, + image: "/images/bookCover1.png", + price: 15, + rating: 2, + date: new Date("2024-02-07"), + }, ]; -export default bookData; +export const transactionHistoryData: TransactionHistoryInterface[] = [ + { + transactionId: "Tran-124B", + transactionType: "Monthly Payment", + amount: 10.99, + status: true, + date: new Date("2024-02-07"), + }, + { + transactionId: "Tran-124C", + transactionType: "Book Purchase", + amount: 79.09, + status: true, + date: new Date("2024-04-25"), + }, + { + transactionId: "Tran-124D", + transactionType: "Withdraw", + amount: 1560.0, + status: false, + date: new Date("2024-04-20"), + }, + { + transactionId: "Tran-124E", + transactionType: "NFT Royalties", + amount: 7.02, + status: true, + date: new Date("2024-04-18"), + }, + { + transactionId: "Tran-124F", + transactionType: "NFT Royalties", + amount: 8.09, + status: true, + date: new Date("2024-04-18"), + }, + { + transactionId: "Tran-124G", + transactionType: "Utility Bill", + amount: 45.99, + status: true, + date: new Date("2024-03-14"), + }, + { + transactionId: "Tran-124H", + transactionType: "Subscription Fee", + amount: 5.0, + status: false, + date: new Date("2024-05-02"), + }, + { + transactionId: "Tran-124I", + transactionType: "Airtime Recharge", + amount: 3.5, + status: true, + date: new Date("2024-01-27"), + }, + { + transactionId: "Tran-124J", + transactionType: "Loan Repayment", + amount: 500.0, + status: true, + date: new Date("2024-03-10"), + }, + { + transactionId: "Tran-124K", + transactionType: "Gift Card Purchase", + amount: 50.0, + status: false, + date: new Date("2024-02-21"), + }, + { + transactionId: "Tran-124L", + transactionType: "Course Fee", + amount: 120.0, + status: true, + date: new Date("2024-03-05"), + }, + { + transactionId: "Tran-124M", + transactionType: "Insurance Premium", + amount: 250.0, + status: true, + date: new Date("2024-01-12"), + }, + { + transactionId: "Tran-124N", + transactionType: "Refund", + amount: 99.99, + status: true, + date: new Date("2024-04-09"), + }, + { + transactionId: "Tran-124O", + transactionType: "Consultation Fee", + amount: 30.0, + status: false, + date: new Date("2024-05-01"), + }, + { + transactionId: "Tran-124P", + transactionType: "Web Hosting", + amount: 15.0, + status: true, + date: new Date("2024-03-16"), + }, + { + transactionId: "Tran-124Q", + transactionType: "Conference Ticket", + amount: 200.0, + status: true, + date: new Date("2024-04-02"), + }, + { + transactionId: "Tran-124R", + transactionType: "Donation", + amount: 25.0, + status: false, + date: new Date("2024-02-18"), + }, + { + transactionId: "Tran-124S", + transactionType: "Freelance Payment", + amount: 350.0, + status: true, + date: new Date("2024-04-29"), + }, + { + transactionId: "Tran-124T", + transactionType: "Ticket Booking", + amount: 60.0, + status: true, + date: new Date("2024-05-03"), + }, + { + transactionId: "Tran-124U", + transactionType: "NFT Sale", + amount: 1000.0, + status: true, + date: new Date("2024-04-22"), + }, +]; diff --git a/src/lib/hooks/useIsMobile.ts b/src/lib/hooks/useIsMobile.ts new file mode 100644 index 0000000..22fed35 --- /dev/null +++ b/src/lib/hooks/useIsMobile.ts @@ -0,0 +1,17 @@ +import { useEffect, useState } from 'react'; + +export default function useIsMobile(breakpoint = 768) { + const [isMobile, setIsMobile] = useState(false); + + useEffect(() => { + const handleResize = () => { + setIsMobile(window.innerWidth <= breakpoint); + }; + + handleResize(); // initial check + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [breakpoint]); + + return isMobile; +} diff --git a/src/lib/interfaces/EarningTabInterface.ts b/src/lib/interfaces/EarningTabInterface.ts new file mode 100644 index 0000000..ceb0e3d --- /dev/null +++ b/src/lib/interfaces/EarningTabInterface.ts @@ -0,0 +1,8 @@ + + +export interface EarningTab { + title: string; + amount: number; + border: string +} + diff --git a/src/lib/interfaces/PaymentPropInterface.ts b/src/lib/interfaces/PaymentPropInterface.ts new file mode 100644 index 0000000..7a31996 --- /dev/null +++ b/src/lib/interfaces/PaymentPropInterface.ts @@ -0,0 +1,8 @@ + + + +export interface PaymentPropInterface { +wallet: string; +amount: number; +walletAddress: string +} \ No newline at end of file diff --git a/src/lib/interfaces/RevenueChartInterface.ts b/src/lib/interfaces/RevenueChartInterface.ts new file mode 100644 index 0000000..4ee3d84 --- /dev/null +++ b/src/lib/interfaces/RevenueChartInterface.ts @@ -0,0 +1,6 @@ +export interface RevenueChartInterface { + name: string; + color: string; + value: number; + percentage: string; +} diff --git a/src/lib/interfaces/TransactionIHistoryInterface.ts b/src/lib/interfaces/TransactionIHistoryInterface.ts new file mode 100644 index 0000000..1c5f718 --- /dev/null +++ b/src/lib/interfaces/TransactionIHistoryInterface.ts @@ -0,0 +1,10 @@ + + + +export interface TransactionHistoryInterface { + transactionId: string; + transactionType: string; + amount: number; + status: boolean; + date: Date; +} \ No newline at end of file diff --git a/src/lib/interfaces/WalletAddressType.ts b/src/lib/interfaces/WalletAddressType.ts new file mode 100644 index 0000000..b653e35 --- /dev/null +++ b/src/lib/interfaces/WalletAddressType.ts @@ -0,0 +1,4 @@ +export interface WalletAddressType { + braavos: string + argent: string +} \ No newline at end of file diff --git a/src/lib/utils.ts b/src/lib/utils.ts index bd0c391..46f28b5 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -4,3 +4,53 @@ import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } + + +interface WalletAddressType { + braavos: string + argent: string +} + +export const handlePaste = async ( + walletType: string, + setWalletAddress: React.Dispatch>, +) => { + try { + if (!navigator.clipboard) { + throw new Error("Clipboard API not available") + } + + const clipboardText = await navigator.clipboard.readText() + + + setWalletAddress((prev) => ({ + ...prev, + [walletType]: clipboardText.trim(), + })) + + console.log(`Pasted to ${walletType}:`, clipboardText.trim()) + return clipboardText.trim() + } catch (error) { + console.error("Failed to read clipboard:", error) + + + const fallbackText = prompt("Clipboard access denied. Please paste your wallet address:") + if (fallbackText) { + setWalletAddress((prev) => ({ + ...prev, + [walletType]: fallbackText.trim(), + })) + return fallbackText.trim() + } + + return null + } +} + + + +export const formatDate = (date: Date) => + date.toLocaleDateString("en-GB", { + day: "2-digit", + month: "long", + });