diff --git a/src/app/reviews/page.tsx b/src/app/reviews/page.tsx new file mode 100644 index 0000000..ccb6078 --- /dev/null +++ b/src/app/reviews/page.tsx @@ -0,0 +1,190 @@ +"use client"; +import React, { useState, useMemo } from 'react'; +import { ThemeProvider } from '@/components/ThemeProvider'; +import NavbarStyleApple from '@/components/navbar/NavbarStyleApple/NavbarStyleApple'; +import TestimonialCardThirteen from '@/components/sections/testimonial/TestimonialCardThirteen'; +import Input from '@/components/form/Input'; +import ButtonTextUnderline from '@/components/button/ButtonTextUnderline'; + +// Dummy data generation +const generateReviews = (count: number) => { + const reviews = []; + const names = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank", "Grace", "Heidi", "Ivan", "Judy"]; + const reviewTexts = [ + "Absolutely love this product! It exceeded my expectations.", "Great quality and very fast shipping. Highly recommend!", "Decent product for the price. Would buy again.", "Not entirely satisfied, but it gets the job done.", "Fantastic experience from start to finish. Five stars!", "The item arrived damaged. Customer service was helpful.", "Works as advertised. No complaints here.", "A bit pricey, but the quality justifies it.", "I've been looking for something like this for ages!", "Could be better, but it's okay.", "Exceptional value and brilliant design. This product truly stands out!", "I was skeptical at first, but now I'm a believer. What an amazing item.", "The best purchase I've made this year. So glad I found it!", "Slight learning curve, but once you get it, it's incredibly powerful.", "My new go-to. It's so versatile and performs perfectly every time.", "Customer support was stellar when I had a question. Very impressed.", "Perfect for daily use, durable, and aesthetically pleasing. A solid 10/10.", "Initially had an issue, but it was resolved quickly and efficiently. Good job.", "Transforms my routine. I can't imagine going back to how things were before.", "A genuinely innovative product that solves a real problem effortlessly.", "Surprisingly robust given its compact size. It handles everything with ease.", "I've recommended this to all my friends. It's that good!", "The attention to detail is evident. Every aspect feels thoughtfully designed.", "Worth every penny. The performance is consistently high.", "Exceeded my expectations in terms of functionality and ease of use." + ]; + const imagePlaceholders = [ + "https://api.dicebear.com/7.x/pixel-art/svg?seed=1", "https://api.dicebear.com/7.x/pixel-art/svg?seed=2", "https://api.dicebear.com/7.x/pixel-art/svg?seed=3", "https://api.dicebear.com/7.x/pixel-art/svg?seed=4", "https://api.dicebear.com/7.x/pixel-art/svg?seed=5", "https://api.dicebear.com/7.x/pixel-art/svg?seed=6", "https://api.dicebear.com/7.x/pixel-art/svg?seed=7", "https://api.dicebear.com/7.x/pixel-art/svg?seed=8", "https://api.dicebear.com/7.x/pixel-art/svg?seed=9", "https://api.dicebear.com/7.x/pixel-art/svg?seed=10" + ]; + + for (let i = 1; i <= count; i++) { + const name = names[Math.floor(Math.random() * names.length)]; + const rating = Math.floor(Math.random() * 5) + 1; // 1-5 stars + const reviewText = reviewTexts[Math.floor(Math.random() * reviewTexts.length)]; + const date = new Date(Date.now() - Math.floor(Math.random() * 365 * 24 * 60 * 60 * 1000)).toISOString().split('T')[0]; + const helpfulVotes = Math.floor(Math.random() * 100); + const isVerifiedPurchase = Math.random() > 0.3; // 70% verified + const imageSrc = imagePlaceholders[Math.floor(Math.random() * imagePlaceholders.length)]; + + reviews.push({ + id: `review-${i}`, + name, + rating, + reviewText, + date, + helpfulVotes, + isVerifiedPurchase, + imageSrc, + }); + } + return reviews; +}; + +const ALL_REVIEWS = generateReviews(350); // Generate 350 reviews + +export default function ReviewsPage() { + const [searchTerm, setSearchTerm] = useState(''); + const [sortCriteria, setSortCriteria] = useState('newest'); // 'newest', 'oldest', 'highestRating', 'lowestRating', 'mostHelpful' + const [reviewsPerPage, setReviewsPerPage] = useState(20); // Changed from 10 to 20 for more content per load + const [currentPage, setCurrentPage] = useState(1); + + const filteredAndSortedReviews = useMemo(() => { + let reviews = [...ALL_REVIEWS]; + + // 1. Filter + if (searchTerm) { + reviews = reviews.filter(review => + review.reviewText.toLowerCase().includes(searchTerm.toLowerCase()) || + review.name.toLowerCase().includes(searchTerm.toLowerCase()) + ); + } + + // 2. Sort + reviews.sort((a, b) => { + switch (sortCriteria) { + case 'newest': + return new Date(b.date).getTime() - new Date(a.date).getTime(); + case 'oldest': + return new Date(a.date).getTime() - new Date(b.date).getTime(); + case 'highestRating': + return b.rating - a.rating; + case 'lowestRating': + return a.rating - b.rating; + case 'mostHelpful': + return b.helpfulVotes - a.helpfulVotes; + default: + return 0; + } + }); + + return reviews; + }, [searchTerm, sortCriteria]); + + const displayedReviews = useMemo(() => { + const startIndex = 0; + const endIndex = currentPage * reviewsPerPage; + return filteredAndSortedReviews.slice(startIndex, endIndex); + }, [filteredAndSortedReviews, currentPage, reviewsPerPage]); + + const handleLoadMore = () => { + setCurrentPage(prevPage => prevPage + 1); + }; + + const hasMoreReviews = displayedReviews.length < filteredAndSortedReviews.length; + + const testimonialCardData = displayedReviews.map(review => ({ + id: review.id, + name: review.name, + handle: review.isVerifiedPurchase ? "Verified Purchase" : "Customer", testimonial: `${review.reviewText} (Reviewed on ${review.date}). Found helpful by ${review.helpfulVotes} people.`, + rating: review.rating, + imageSrc: review.imageSrc, + imageAlt: `${review.name}'s avatar`, + })); + + return ( + + +
+
+
+

Customer Reviews

+

+ Read what our amazing customers have to say about our products. +

+
+ +
+ +
+ + +
+
+ + + + {hasMoreReviews && ( +
+ +
+ )} +
+
+
+ ); +}