diff --git a/public/reader-image.png b/public/reader-image.png new file mode 100644 index 0000000..03cb523 Binary files /dev/null and b/public/reader-image.png differ diff --git a/public/reader-profile-dummy-image.png b/public/reader-profile-dummy-image.png new file mode 100755 index 0000000..aa3c795 Binary files /dev/null and b/public/reader-profile-dummy-image.png differ diff --git a/src/app/dashboard/stats-and-achievements/page.tsx b/src/app/dashboard/stats-and-achievements/page.tsx new file mode 100644 index 0000000..f777e98 --- /dev/null +++ b/src/app/dashboard/stats-and-achievements/page.tsx @@ -0,0 +1,151 @@ +"use client"; + +import { Header } from "@/components/dashboard/header"; +import { TimeFilter } from "@/components/stats-achievements/time-filter"; +import { StatsGrid } from "@/components/stats-achievements/stats-grid"; +import { BadgeSection } from "@/components/stats-achievements/badge-section"; +import { GoalsSection } from "@/components/stats-achievements/goals-section"; +import { AchievementsSection } from "@/components/stats-achievements/achievements-section"; +import { useState } from "react"; + +// Mock data for different time periods +const timeData = { + "This Week": { + hours: 16, + minutes: 37, + stats: [ + { label: "Books Completed", value: "2", color: "#096CFF" }, + { + label: "Average Session", + value: "45", + unit: "Minutes", + color: "#096CFF", + }, + { label: "Most Read Genre", value: "Fiction", color: "#096CFF" }, + { label: "Most Read Author", value: "J.K. Rowling", color: "#096CFF" }, + { label: "Longest Read", value: "4", unit: "Hours", color: "#096CFF" }, + { label: "Sessions", value: "12", color: "#096CFF" }, + { label: "Abandoned", value: "1", color: "#096CFF" }, + ], + }, + "This Month": { + hours: 68, + minutes: 24, + stats: [ + { label: "Books Completed", value: "8", color: "#096CFF" }, + { + label: "Average Session", + value: "52", + unit: "Minutes", + color: "#096CFF", + }, + { label: "Most Read Genre", value: "Mystery", color: "#096CFF" }, + { label: "Most Read Author", value: "Agatha Christie", color: "#096CFF" }, + { label: "Longest Read", value: "6", unit: "Hours", color: "#096CFF" }, + { label: "Sessions", value: "45", color: "#096CFF" }, + { label: "Abandoned", value: "3", color: "#096CFF" }, + ], + }, + "This Year": { + hours: 324, + minutes: 18, + stats: [ + { label: "Books Completed", value: "42", color: "#096CFF" }, + { + label: "Average Session", + value: "48", + unit: "Minutes", + color: "#096CFF", + }, + { label: "Most Read Genre", value: "Sci-Fi", color: "#096CFF" }, + { label: "Most Read Author", value: "Isaac Asimov", color: "#096CFF" }, + { label: "Longest Read", value: "8", unit: "Hours", color: "#096CFF" }, + { label: "Sessions", value: "186", color: "#096CFF" }, + { label: "Abandoned", value: "12", color: "#096CFF" }, + ], + }, + "All Time": { + hours: 1247, + minutes: 52, + stats: [ + { label: "Books Completed", value: "156", color: "#096CFF" }, + { + label: "Average Session", + value: "51", + unit: "Minutes", + color: "#096CFF", + }, + { label: "Most Read Genre", value: "Fantasy", color: "#096CFF" }, + { + label: "Most Read Author", + value: "Brandon Sanderson", + color: "#096CFF", + }, + { label: "Longest Read", value: "12", unit: "Hours", color: "#096CFF" }, + { label: "Sessions", value: "743", color: "#096CFF" }, + { label: "Abandoned", value: "28", color: "#096CFF" }, + ], + }, +}; + +export default function StatsAndAchievementsPage() { + const [selectedPeriod, setSelectedPeriod] = useState("This Week"); + const currentData = timeData[selectedPeriod as keyof typeof timeData]; + + return ( +
+
+ +
+ {/* Total Hours Read Section */} +
+
+

+ Total Hours Read +

+ +
+ + {/* Large Time Display */} +
+
+
+
+ {currentData.hours} +
+
+ Hours +
+
+ : +
+
+ {currentData.minutes} +
+
+ Minutes +
+
+
+
+ + {/* Stats Grid */} + +
+
+ {/* Badge Section */} + + + {/* Goals Section */} + + + {/* Achievements Section */} + +
+
+
+ ); +} diff --git a/src/app/reader-profile/following/page.tsx b/src/app/reader-profile/following/page.tsx new file mode 100644 index 0000000..c1d6fff --- /dev/null +++ b/src/app/reader-profile/following/page.tsx @@ -0,0 +1,138 @@ +"use client"; + +import { useState } from "react"; +import { ArrowLeft, BadgeCheck, CheckCircle } from "lucide-react"; +import { useRouter } from "next/navigation"; +import { useMobileMenu } from "@/hooks/useMobileMenu"; +import Image from "next/image"; + +interface FollowingUser { + id: string; + name: string; + username: string; + isVerified: boolean; + avatar?: string; +} + +export default function FollowingPage() { + const router = useRouter(); + const { openMobileMenu } = useMobileMenu(); + const [activeTab, setActiveTab] = useState< + "total" | "verified" | "unverified" + >("total"); + + const followingUsers: FollowingUser[] = Array.from({ length: 9 }, (_, i) => ({ + id: `user-${i + 1}`, + name: "Darrin Collins", + username: "@darrin_collins", + isVerified: i < 7, // First 7 are verified + avatar: "/reader-image.png?height=40&width=40", + })); + + const totalCount = followingUsers.length; + const verifiedCount = followingUsers.filter((user) => user.isVerified).length; + const unverifiedCount = totalCount - verifiedCount; + + const filteredUsers = followingUsers.filter((user) => { + if (activeTab === "verified") return user.isVerified; + if (activeTab === "unverified") return !user.isVerified; + return true; + }); + + const handleUnfollow = (userId: string) => { + console.log("Unfollow user:", userId); + }; + + return ( +
+ {/* Mobile Header */} +
+ +

Following

+
+ +
+ {/* Desktop Header */} +
+

Following

+
+ + {/* Stats Tabs */} +
+ + + +
+ + {/* Following List */} +
+ {filteredUsers.map((user) => ( +
+
+
+ {user.name} +
+
+ {user.name} + {user.isVerified && ( + + )} +
+
+ +
+ ))} +
+ + {filteredUsers.length === 0 && ( +
+

No users found in this category.

+
+ )} +
+
+ ); +} diff --git a/src/app/reader-profile/layout.tsx b/src/app/reader-profile/layout.tsx new file mode 100644 index 0000000..9cc9e88 --- /dev/null +++ b/src/app/reader-profile/layout.tsx @@ -0,0 +1,121 @@ +"use client"; +import React, { useState } from "react"; +import { X } from "lucide-react"; +import { usePathname, useRouter } from "next/navigation"; +import Link from "next/link"; +import { MobileMenuContext } from "@/hooks/useMobileMenu"; +import NavBar from "@/components/landingpage/NavBar"; + +interface ReaderProfileLayoutProps { + children: React.ReactNode; +} + +export default function ReaderProfileLayout({ + children, +}: ReaderProfileLayoutProps) { + const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); + const pathname = usePathname(); + const router = useRouter(); + + const navItems = [ + { + label: "Profile Details", + href: "/reader-profile", + }, + { + label: "Following", + href: "/reader-profile/following", + }, + { + label: "Preferences", + href: "/reader-profile/preferences", + }, + { + label: "Privacy Settings", + href: "/reader-profile/privacy", + }, + { + label: "Sign Out", + href: "/reader-profile/sign-out", + }, + ]; + + return ( + setIsMobileMenuOpen(true) }} + > +
+ +
+ {/* Desktop Sidebar */} +
+
+ +
+
+ + {/* Mobile Menu Overlay */} +
setIsMobileMenuOpen(false)} + > + {/* Mobile Menu Panel */} +
e.stopPropagation()} + > +
+

Profile

+ +
+ +
+
+ + {/* Main Content */} +
{children}
+
+
+
+ ); +} diff --git a/src/app/reader-profile/page.tsx b/src/app/reader-profile/page.tsx new file mode 100644 index 0000000..dcaf92d --- /dev/null +++ b/src/app/reader-profile/page.tsx @@ -0,0 +1,260 @@ +"use client"; + +import type React from "react"; + +import { useState, useRef, type ChangeEvent } from "react"; +import Image from "next/image"; +import { ArrowLeft } from "lucide-react"; +import { useRouter } from "next/navigation"; +import { useMobileMenu } from "@/hooks/useMobileMenu"; + +interface ProfileFormData { + firstName: string; + lastName: string; + username: string; + email: string; + bio: string; + profilePicture: string | null; +} + +export default function ProfileDetailsPage() { + const router = useRouter(); + const { openMobileMenu } = useMobileMenu(); + const [formData, setFormData] = useState({ + firstName: "Faith", + lastName: "Haruna", + username: "Faith_Haruna", + email: "example@gmail.com", + bio: "", + profilePicture: null, + }); + + const [preview, setPreview] = useState( + "/reader-profile-dummy-image.png" + ); + const fileInputRef = useRef(null); + + const handleInputChange = ( + e: ChangeEvent + ) => { + const { name, value } = e.target; + setFormData((prev) => ({ + ...prev, + [name]: value, + })); + }; + + const handleImageUpload = (e: ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onload = () => { + setPreview(reader.result as string); + setFormData((prev) => ({ + ...prev, + profilePicture: reader.result as string, + })); + }; + reader.readAsDataURL(file); + }; + + const triggerFileInput = () => { + fileInputRef.current?.click(); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + console.log("Form submitted:", formData); + }; + + return ( +
+ {/* Mobile Header */} +
+
+ +

Profile

+
+ +
+ +
+
+ {/* Profile Picture Section */} +
+
+
+ {preview ? ( + Profile Preview + ) : ( +
+ + + +
+ )} +
+ + +
+ +
+
+ {" "} +

+ {formData.username} +

+
+ + + Enthusiast + +
+
+

ID: CLRD00010

+

+ Following 17 +

+
+
+ + {/* Form Fields */} +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ +