diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index 094446c..12b5ce0 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -3,24 +3,21 @@ import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; import NavbarLayoutFloatingInline from "@/components/navbar/NavbarLayoutFloatingInline"; import TextAbout from "@/components/sections/about/TextAbout"; -import TeamCardTwo from "@/components/sections/team/TeamCardTwo"; -import MetricCardSeven from "@/components/sections/metrics/MetricCardSeven"; +import ContactCTA from "@/components/sections/contact/ContactCTA"; import FooterBaseCard from "@/components/sections/footer/FooterBaseCard"; -import Link from "next/link"; -import { Linkedin, Twitter, Heart, Globe, Mail } from "lucide-react"; +import { Heart, Shield, Users, Award } from "lucide-react"; -const AboutPage = () => { +export default function AboutPage() { const navItems = [ { name: "Home", id: "/" }, { name: "Browse Animals", id: "/animals" }, - { name: "About", id: "about" }, + { name: "About", id: "/about" }, { name: "Contact", id: "contact" }, ]; const footerColumns = [ { - title: "Adoption", - items: [ + title: "Adoption", items: [ { label: "Browse Pets", href: "/animals" }, { label: "How to Adopt", href: "#how-it-works" }, { label: "Adoption Stories", href: "#adoption-stories" }, @@ -28,8 +25,7 @@ const AboutPage = () => { ], }, { - title: "Company", - items: [ + title: "Company", items: [ { label: "About Us", href: "/about" }, { label: "Our Team", href: "#team" }, { label: "Partner with Us", href: "/partner" }, @@ -37,8 +33,7 @@ const AboutPage = () => { ], }, { - title: "Support", - items: [ + title: "Support", items: [ { label: "Contact Us", href: "/contact" }, { label: "Donate", href: "/donate" }, { label: "Volunteer", href: "/volunteer" }, @@ -46,8 +41,7 @@ const AboutPage = () => { ], }, { - title: "Legal", - items: [ + title: "Legal", items: [ { label: "Privacy Policy", href: "#" }, { label: "Terms of Service", href: "#" }, { label: "Cookie Policy", href: "#" }, @@ -73,169 +67,70 @@ const AboutPage = () => { -
+
-
- +
-
- + +
+ +
+
@@ -248,6 +143,4 @@ const AboutPage = () => {
); -}; - -export default AboutPage; \ No newline at end of file +} diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx new file mode 100644 index 0000000..a46bcd9 --- /dev/null +++ b/src/app/admin/page.tsx @@ -0,0 +1,342 @@ +"use client"; + +import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; +import NavbarLayoutFloatingInline from "@/components/navbar/NavbarLayoutFloatingInline"; +import FooterBaseCard from "@/components/sections/footer/FooterBaseCard"; +import { useState } from "react"; +import { Plus, Edit2, Trash2, Search, Settings, Users, BarChart3, Heart } from "lucide-react"; + +export default function AdminPage() { + const [activeTab, setActiveTab] = useState<"animals" | "adoptions" | "users" | "settings">("animals"); + const [searchTerm, setSearchTerm] = useState(""); + + const navItems = [ + { name: "Home", id: "/" }, + { name: "Browse Animals", id: "/animals" }, + { name: "Admin", id: "/admin" }, + { name: "About", id: "about" }, + { name: "Contact", id: "contact" }, + ]; + + const footerColumns = [ + { + title: "Adoption", items: [ + { label: "Browse Pets", href: "/animals" }, + { label: "How to Adopt", href: "#how-it-works" }, + ], + }, + { + title: "Company", items: [ + { label: "About Us", href: "/about" }, + { label: "Our Team", href: "#team" }, + ], + }, + ]; + + const sampleAnimals = [ + { id: 1, name: "Luna", species: "Dog", breed: "Golden Retriever", status: "Available", adoptionFee: "$150" }, + { id: 2, name: "Max", species: "Cat", breed: "Tabby", status: "Pending", adoptionFee: "$75" }, + { id: 3, name: "Bella", species: "Dog", breed: "Border Collie", status: "Available", adoptionFee: "$120" }, + ]; + + const sampleAdoptions = [ + { id: 1, animalName: "Buddy", familyName: "Johnson", status: "Completed", date: "2025-01-10" }, + { id: 2, animalName: "Whiskers", familyName: "Smith", status: "In Progress", date: "2025-01-15" }, + { id: 3, animalName: "Charlie", familyName: "Williams", status: "Pending Review", date: "2025-01-20" }, + ]; + + const sampleUsers = [ + { id: 1, name: "John Doe", email: "john@example.com", role: "Admin", status: "Active" }, + { id: 2, name: "Jane Smith", email: "jane@example.com", role: "Staff", status: "Active" }, + { id: 3, name: "Bob Wilson", email: "bob@example.com", role: "Volunteer", status: "Inactive" }, + ]; + + return ( + + + +
+
+ {/* Header */} +
+

Admin Dashboard

+

Manage animals, adoptions, users, and platform settings

+
+ + {/* Tab Navigation */} +
+ + + + +
+ + {/* Search & Controls */} + {activeTab !== "settings" && ( +
+
+ + setSearchTerm(e.target.value)} + className="w-full pl-10 pr-4 py-2 border border-slate-300 dark:border-slate-600 rounded-lg bg-white dark:bg-slate-800 text-slate-900 dark:text-white placeholder-slate-500" + /> +
+ +
+ )} + + {/* Content Sections */} + {activeTab === "animals" && ( +
+
+ + + + + + + + + + + + + {sampleAnimals.map((animal) => ( + + + + + + + + + ))} + +
NameSpeciesBreedStatusFeeActions
{animal.name}{animal.species}{animal.breed} + + {animal.status} + + {animal.adoptionFee} +
+ + +
+
+
+
+ )} + + {activeTab === "adoptions" && ( +
+
+ + + + + + + + + + + + {sampleAdoptions.map((adoption) => ( + + + + + + + + ))} + +
AnimalFamilyStatusDateActions
{adoption.animalName}{adoption.familyName} + + {adoption.status} + + {adoption.date} +
+ +
+
+
+
+ )} + + {activeTab === "users" && ( +
+
+ + + + + + + + + + + + {sampleUsers.map((user) => ( + + + + + + + + ))} + +
NameEmailRoleStatusActions
{user.name}{user.email}{user.role} + + {user.status} + + +
+ + +
+
+
+
+ )} + + {activeTab === "settings" && ( +
+
+

Platform Settings

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

System Status

+
+
+ Database + Operational +
+
+ API Server + Operational +
+
+ Email Service + Operational +
+
+
+
+ )} +
+
+ + +
+ ); +} diff --git a/src/app/animals/page.tsx b/src/app/animals/page.tsx index 545ead7..6e7accf 100644 --- a/src/app/animals/page.tsx +++ b/src/app/animals/page.tsx @@ -2,13 +2,77 @@ import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; import NavbarLayoutFloatingInline from "@/components/navbar/NavbarLayoutFloatingInline"; -import ProductCardOne from "@/components/sections/product/ProductCardOne"; -import MetricCardSeven from "@/components/sections/metrics/MetricCardSeven"; -import ContactCTA from "@/components/sections/contact/ContactCTA"; +import HeroSplitKpi from "@/components/sections/hero/HeroSplitKpi"; import FooterBaseCard from "@/components/sections/footer/FooterBaseCard"; -import { Heart, TrendingUp } from "lucide-react"; +import { Heart, Filter, Search } from "lucide-react"; +import { useState, useMemo } from "react"; + +interface Animal { + id: string; + name: string; + species: string; + breed: string; + age: string; + gender: string; + size: string; + adoptionFee: string; + imageSrc: string; + imageAlt: string; + description: string; + temperament: string[]; + healthStatus: string; + available: boolean; +} + +const animalsDatabase: Animal[] = [ + { + id: "1", name: "Luna", species: "Dog", breed: "Golden Retriever", age: "3 years", gender: "Female", size: "Large", adoptionFee: "$150", imageSrc: "http://img.b2bpic.net/free-photo/close-up-dog_482257-11548.jpg", imageAlt: "Luna, a beautiful golden retriever", description: "Sweet and gentle Luna loves playing fetch and making new friends. Perfect for active families!", temperament: ["Friendly", "Playful", "Gentle", "Intelligent"], + healthStatus: "Fully vaccinated, microchipped", available: true, + }, + { + id: "2", name: "Max", species: "Cat", breed: "Tabby", age: "2 years", gender: "Male", size: "Small", adoptionFee: "$75", imageSrc: "http://img.b2bpic.net/free-photo/focus-eyes-tabby-blue-cement-floor_1150-19546.jpg", imageAlt: "Max, an adorable tabby cat", description: "Energetic Max is always ready for playtime and cuddles. Great for families with older kids.", temperament: ["Energetic", "Affectionate", "Social", "Curious"], + healthStatus: "Fully vaccinated, neutered", available: true, + }, + { + id: "3", name: "Bella", species: "Dog", breed: "Border Collie", age: "4 years", gender: "Female", size: "Medium", adoptionFee: "$120", imageSrc: "http://img.b2bpic.net/free-photo/studio-shot-cute-border-collie-dog_23-2148097506.jpg", imageAlt: "Bella, an intelligent border collie", description: "Highly intelligent Bella thrives with mental stimulation and exercise. Perfect for active owners.", temperament: ["Intelligent", "Energetic", "Loyal", "Obedient"], + healthStatus: "Fully vaccinated, microchipped", available: true, + }, + { + id: "4", name: "Charlie", species: "Rabbit", breed: "Holland Lop", age: "1 year", gender: "Male", size: "Small", adoptionFee: "$50", imageSrc: "http://img.b2bpic.net/free-photo/cute-rabbit-eating-grass-garden_181624-40766.jpg", imageAlt: "Charlie, an adorable rabbit", description: "Cute Charlie loves fresh vegetables and quiet environments. Great first pet for kids!", temperament: ["Calm", "Social", "Gentle", "Curious"], + healthStatus: "Healthy, neutered", available: true, + }, + { + id: "5", name: "Buddy", species: "Dog", breed: "Labrador", age: "5 years", gender: "Male", size: "Large", adoptionFee: "$140", imageSrc: "http://img.b2bpic.net/free-photo/close-up-dog_482257-11548.jpg", imageAlt: "Buddy, a friendly labrador", description: "Loyal Buddy is a senior dog looking for a calm home. Perfect for experienced dog owners.", temperament: ["Loyal", "Calm", "Affectionate", "Well-trained"], + healthStatus: "Fully vaccinated, senior health check", available: true, + }, + { + id: "6", name: "Whiskers", species: "Cat", breed: "Siamese", age: "1 year", gender: "Female", size: "Small", adoptionFee: "$85", imageSrc: "http://img.b2bpic.net/free-photo/focus-eyes-tabby-blue-cement-floor_1150-19546.jpg", imageAlt: "Whiskers, a beautiful siamese cat", description: "Vocal and affectionate Whiskers loves human attention and warm laps.", temperament: ["Vocal", "Affectionate", "Playful", "Social"], + healthStatus: "Fully vaccinated, spayed", available: true, + }, +]; export default function AnimalsPage() { + const [searchQuery, setSearchQuery] = useState(""); + const [speciesFilter, setSpeciesFilter] = useState("All"); + const [sizeFilter, setSizeFilter] = useState("All"); + const [showFilters, setShowFilters] = useState(false); + + const filteredAnimals = useMemo(() => { + return animalsDatabase.filter((animal) => { + const matchesSearch = + animal.name.toLowerCase().includes(searchQuery.toLowerCase()) || + animal.breed.toLowerCase().includes(searchQuery.toLowerCase()) || + animal.species.toLowerCase().includes(searchQuery.toLowerCase()); + + const matchesSpecies = + speciesFilter === "All" || animal.species === speciesFilter; + + const matchesSize = sizeFilter === "All" || animal.size === sizeFilter; + + return matchesSearch && matchesSpecies && matchesSize; + }); + }, [searchQuery, speciesFilter, sizeFilter]); + const navItems = [ { name: "Home", id: "/" }, { name: "Browse Animals", id: "/animals" }, @@ -18,26 +82,23 @@ export default function AnimalsPage() { const footerColumns = [ { - title: "Adoption", - items: [ + title: "Adoption", items: [ { label: "Browse Pets", href: "/animals" }, - { label: "How to Adopt", href: "#how-it-works" }, - { label: "Adoption Stories", href: "#adoption-stories" }, + { label: "How to Adopt", href: "/#how-it-works" }, + { label: "Adoption Stories", href: "/#adoption-stories" }, { label: "FAQ", href: "/faq" }, ], }, { - title: "Company", - items: [ + title: "Company", items: [ { label: "About Us", href: "/about" }, - { label: "Our Team", href: "#team" }, + { label: "Our Team", href: "/#team" }, { label: "Partner with Us", href: "/partner" }, { label: "Blog", href: "/blog" }, ], }, { - title: "Support", - items: [ + title: "Support", items: [ { label: "Contact Us", href: "/contact" }, { label: "Donate", href: "/donate" }, { label: "Volunteer", href: "/volunteer" }, @@ -45,8 +106,7 @@ export default function AnimalsPage() { ], }, { - title: "Legal", - items: [ + title: "Legal", items: [ { label: "Privacy Policy", href: "#" }, { label: "Terms of Service", href: "#" }, { label: "Cookie Policy", href: "#" }, @@ -77,126 +137,189 @@ export default function AnimalsPage() { /> -
- +
-
- -
+
+
+ {/* Search and Filter Bar */} +
+ {/* Search Input */} +
+ + setSearchQuery(e.target.value)} + className="w-full pl-10 pr-4 py-2 bg-card border border-accent/20 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-cta" + /> +
-
- + {/* Filter Toggle */} + + + {/* Filter Options */} + {showFilters && ( +
+ {/* Species Filter */} +
+ + +
+ + {/* Size Filter */} +
+ + +
+
+ )} +
+ + {/* Results Count */} +
+

+ Showing {filteredAnimals.length} of {animalsDatabase.length} animals +

+
+ + {/* Animals Grid */} + {filteredAnimals.length > 0 ? ( +
+ {filteredAnimals.map((animal) => ( +
+ {/* Image */} +
+ {animal.imageAlt} +
+ {animal.adoptionFee} +
+
+ + {/* Content */} +
+

+ {animal.name} +

+

+ {animal.breed} • {animal.age} +

+ + {/* Info Grid */} +
+
+ Gender: +

{animal.gender}

+
+
+ Size: +

{animal.size}

+
+
+ + {/* Description */} +

+ {animal.description} +

+ + {/* Temperament */} +
+

+ TEMPERAMENT +

+
+ {animal.temperament.map((trait) => ( + + {trait} + + ))} +
+
+ + {/* Health Status */} +

+ ✓ {animal.healthStatus} +

+ + {/* CTA */} + +
+
+ ))} +
+ ) : ( +
+

No animals found matching your criteria.

+ +
+ )} +
); -} \ No newline at end of file +} diff --git a/src/app/api/auth/login/route.ts b/src/app/api/auth/login/route.ts new file mode 100644 index 0000000..06e7ce6 --- /dev/null +++ b/src/app/api/auth/login/route.ts @@ -0,0 +1,74 @@ +import { NextRequest, NextResponse } from "next/server"; +import crypto from "crypto"; + +// Mock user database - in production, use a real database +const mockUsers = [ + { + id: "1", email: "demo@pawshome.com", passwordHash: hashPassword("password123"), + name: "Demo User"}, +]; + +function hashPassword(password: string): string { + return crypto.createHash("sha256").update(password).digest("hex"); +} + +function verifyPassword(password: string, hash: string): boolean { + return hashPassword(password) === hash; +} + +function generateToken(): string { + return crypto.randomBytes(32).toString("hex"); +} + +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { email, password } = body; + + if (!email || !password) { + return NextResponse.json( + { message: "Email and password are required" }, + { status: 400 } + ); + } + + // Find user + const user = mockUsers.find((u) => u.email === email); + if (!user) { + return NextResponse.json( + { message: "Invalid email or password" }, + { status: 401 } + ); + } + + // Verify password + if (!verifyPassword(password, user.passwordHash)) { + return NextResponse.json( + { message: "Invalid email or password" }, + { status: 401 } + ); + } + + // Generate token + const token = generateToken(); + + // Return success response + return NextResponse.json( + { + token, + user: { + id: user.id, + email: user.email, + name: user.name, + }, + }, + { status: 200 } + ); + } catch (error) { + console.error("Login error:", error); + return NextResponse.json( + { message: "Internal server error" }, + { status: 500 } + ); + } +} diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts new file mode 100644 index 0000000..020e907 --- /dev/null +++ b/src/app/api/auth/logout/route.ts @@ -0,0 +1,24 @@ +import { NextRequest, NextResponse } from "next/server"; + +export async function POST(request: NextRequest) { + try { + // Clear authentication token on client side via response + const response = NextResponse.json( + { message: "Logged out successfully" }, + { status: 200 } + ); + + // Set cookie to expire if using cookies for auth + response.cookies.set({ + name: "authToken", value: "", maxAge: 0, + path: "/"}); + + return response; + } catch (error) { + console.error("Logout error:", error); + return NextResponse.json( + { message: "Internal server error" }, + { status: 500 } + ); + } +} diff --git a/src/app/api/auth/session/route.ts b/src/app/api/auth/session/route.ts new file mode 100644 index 0000000..a2bcdbd --- /dev/null +++ b/src/app/api/auth/session/route.ts @@ -0,0 +1,39 @@ +import { NextRequest, NextResponse } from "next/server"; + +export async function GET(request: NextRequest) { + try { + const token = request.headers.get("Authorization")?.replace("Bearer ", ""); + + if (!token) { + return NextResponse.json( + { message: "No token provided" }, + { status: 401 } + ); + } + + // In production, verify token against database/cache + // For this mock, we'll validate basic structure + if (token.length !== 64) { + return NextResponse.json( + { message: "Invalid token" }, + { status: 401 } + ); + } + + // Return mock session data + return NextResponse.json( + { + user: { + id: "1", email: "demo@pawshome.com", name: "Demo User"}, + isAuthenticated: true, + }, + { status: 200 } + ); + } catch (error) { + console.error("Session error:", error); + return NextResponse.json( + { message: "Internal server error" }, + { status: 500 } + ); + } +} diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx new file mode 100644 index 0000000..5f2adea --- /dev/null +++ b/src/app/dashboard/page.tsx @@ -0,0 +1,257 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { useRouter } from "next/navigation"; +import Link from "next/link"; +import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; +import NavbarLayoutFloatingInline from "@/components/navbar/NavbarLayoutFloatingInline"; +import { LogOut, Heart, Settings } from "lucide-react"; + +interface User { + id: string; + email: string; + name: string; +} + +export default function DashboardPage() { + const router = useRouter(); + const [user, setUser] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + const navItems = [ + { name: "Home", id: "/" }, + { name: "Browse Animals", id: "/animals" }, + { name: "About", id: "/about" }, + { name: "Login", id: "/login" }, + ]; + + useEffect(() => { + const checkAuth = async () => { + try { + const token = localStorage.getItem("authToken"); + const userStr = localStorage.getItem("user"); + + if (!token) { + router.push("/login"); + return; + } + + // Verify session with backend + const response = await fetch("/api/auth/session", { + headers: { Authorization: `Bearer ${token}` }, + }); + + if (!response.ok) { + localStorage.removeItem("authToken"); + localStorage.removeItem("user"); + router.push("/login"); + return; + } + + if (userStr) { + setUser(JSON.parse(userStr)); + } + } catch (error) { + console.error("Auth check failed:", error); + router.push("/login"); + } finally { + setIsLoading(false); + } + }; + + checkAuth(); + }, [router]); + + const handleLogout = async () => { + try { + const token = localStorage.getItem("authToken"); + if (token) { + await fetch("/api/auth/logout", { + method: "POST", headers: { Authorization: `Bearer ${token}` }, + }); + } + } catch (error) { + console.error("Logout error:", error); + } finally { + localStorage.removeItem("authToken"); + localStorage.removeItem("user"); + router.push("/"); + } + }; + + if (isLoading) { + return ( + +
+
+
+

Loading...

+
+
+
+ ); + } + + if (!user) { + return ( + +
+

Redirecting...

+
+
+ ); + } + + return ( + + + +
+
+ {/* Header */} +
+
+

+ Welcome, {user.name}! +

+

Manage your PawsHome account

+
+ +
+ + {/* Dashboard Grid */} +
+ {/* Profile Card */} +
+
+
+ +
+

Profile

+
+
+
+ +

{user.name}

+
+
+ +

{user.email}

+
+ + Edit Profile + +
+
+ + {/* Favorites Card */} +
+
+
+ +
+

Favorites

+
+

+ View and manage your favorite animals +

+ + View Favorites + +
+ + {/* Adoptions Card */} +
+
+
+ +
+

My Adoptions

+
+

+ Track your adoption applications and status +

+ + View Adoptions + +
+ + {/* Settings Card */} +
+
+
+ +
+

Settings

+
+

+ Manage your account preferences and notifications +

+ + Go to Settings + +
+
+
+
+
+ ); +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 1564797..9a6e8da 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,1423 +1,37 @@ import type { Metadata } from "next"; -import { Mulish } from "next/font/google"; -import { Inter } from "next/font/google"; +import { Geist } from "next/font/google"; import "./globals.css"; -import { ServiceWrapper } from "@/components/ServiceWrapper"; -import Tag from "@/tag/Tag"; +import ServiceWrapper from "@/providers/serviceWrapper/ServiceWrapper"; +import { Tag } from "@/components/tag/Tag"; -const mulish = Mulish({ - variable: "--font-mulish", - subsets: ["latin"], -}); - -const inter = Inter({ - variable: "--font-inter", - subsets: ["latin"], +const geist = Geist({ + variable: "--font-geist", subsets: ["latin"], }); export const metadata: Metadata = { - title: "PawsHome - Animal Adoption & Rescue Platform", - description: "Find your perfect pet companion through PawsHome. Browse 2,500+ adoptable animals from 150+ partner shelters. Simple, safe, and transparent adoption process.", - keywords: "animal adoption, pet rescue, dog adoption, cat adoption, animal shelter, pet rescue platform, adopt a pet", - metadataBase: new URL("https://pawshome.com"), - alternates: { - canonical: "https://pawshome.com", - }, - openGraph: { - title: "PawsHome - Adopt Your Perfect Pet", - description: "Connect with your perfect animal companion through our trusted adoption platform.", - siteName: "PawsHome", - type: "website", - }, - twitter: { - card: "summary_large_image", - title: "PawsHome - Adopt a Pet Today", - description: "Find adoptable animals in your area. Give a rescue animal a loving home.", - }, - robots: { - index: true, - follow: true, - }, -}; + title: "PawsHome - Pet Adoption Platform", description: "Find your perfect companion and give a loving animal a second chance at happiness through PawsHome's trusted adoption platform."}; export default function RootLayout({ children, -}: Readonly<{ +}: { children: React.ReactNode; -}>) { +}) { return ( - - + + {children} - +