press releases
This commit is contained in:
@@ -50,7 +50,7 @@ export default function AdBanner({
|
||||
session.user.plan === 'LIFETIME'
|
||||
);
|
||||
|
||||
if (shouldExclude) return null;
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
// Don't load if loading session or if user is paid
|
||||
@@ -92,6 +92,8 @@ export default function AdBanner({
|
||||
// Don't render anything while session is loading
|
||||
if (status === 'loading') return null;
|
||||
|
||||
if (shouldExclude) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`ad-container flex justify-center items-center overflow-hidden transition-opacity duration-300 ${adFilled ? 'opacity-100' : 'opacity-0 h-0'} ${className}`}
|
||||
|
||||
@@ -105,7 +105,7 @@ const AIComingSoonBanner = () => {
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-blue-100 mb-4 animate-pulse">
|
||||
<Sparkles className="w-4 h-4 text-blue-600" />
|
||||
<span className="text-sm font-medium text-blue-700">
|
||||
Coming Soon
|
||||
The Future is Here
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -14,11 +14,14 @@ import { Button } from '@/components/ui/Button';
|
||||
import { ReprintCalculatorTeaser } from '@/components/marketing/ReprintCalculatorTeaser';
|
||||
import { ScrollToTop } from '@/components/ui/ScrollToTop';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
import { Testimonials } from '@/components/marketing/Testimonials';
|
||||
import { getFeaturedTestimonials } from '@/lib/testimonial-data';
|
||||
import en from '@/i18n/en.json';
|
||||
|
||||
export default function HomePageClient() {
|
||||
// Always use English for marketing pages
|
||||
const t = en;
|
||||
const featuredTestimonials = getFeaturedTestimonials();
|
||||
|
||||
const industries = [
|
||||
'Restaurant Chain',
|
||||
@@ -41,6 +44,9 @@ export default function HomePageClient() {
|
||||
{/* Free Tools Grid */}
|
||||
<FreeToolsGrid />
|
||||
|
||||
{/* Testimonials Section */}
|
||||
<Testimonials testimonials={featuredTestimonials} />
|
||||
|
||||
<React.Fragment>
|
||||
<StaticVsDynamic t={t} />
|
||||
<ReprintCalculatorTeaser />
|
||||
|
||||
@@ -29,6 +29,15 @@ export const StatsStrip: React.FC<StatsStripProps> = ({ t }) => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Market Context - Citation / AEO Trust Signal */}
|
||||
<div className="mt-12 pt-8 border-t border-gray-100 text-center">
|
||||
<p className="text-sm text-gray-500 max-w-3xl mx-auto leading-relaxed">
|
||||
Market Context: The global QR code payment market is projected to grow from <span className="font-semibold text-gray-700">$15.9B (2025)</span> to <span className="font-semibold text-gray-700">$38B (2030)</span> <a href="https://finance.yahoo.com/news/analysis-global-qr-code-payments-155300360.html" target="_blank" rel="nofollow external" className="text-blue-600 hover:underline decoration-blue-200 underline-offset-2">(Yahoo Finance)</a>.
|
||||
<span className="mx-2">•</span>
|
||||
94% of marketers increased their QR code usage in 2025 <a href="https://bitly.com/blog/qr-code-statistics/" target="_blank" rel="nofollow external" className="text-blue-600 hover:underline decoration-blue-200 underline-offset-2">(Bitly)</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
132
src/components/marketing/Testimonials.tsx
Normal file
132
src/components/marketing/Testimonials.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { Star, CheckCircle } from 'lucide-react';
|
||||
import { Card, CardHeader, CardContent } from '@/components/ui/Card';
|
||||
import type { Testimonial } from '@/lib/types';
|
||||
|
||||
interface TestimonialsProps {
|
||||
testimonials: Testimonial[];
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
showAll?: boolean;
|
||||
}
|
||||
|
||||
export const Testimonials: React.FC<TestimonialsProps> = ({
|
||||
testimonials,
|
||||
title = "What Our Customers Say",
|
||||
subtitle = "Real experiences from businesses using QR Master",
|
||||
showAll = false
|
||||
}) => {
|
||||
const displayTestimonials = showAll ? testimonials : testimonials.slice(0, 3);
|
||||
|
||||
const renderStars = (rating: number) => {
|
||||
return (
|
||||
<div className="flex gap-1" aria-label={`${rating} out of 5 stars`}>
|
||||
{[...Array(5)].map((_, index) => (
|
||||
<Star
|
||||
key={index}
|
||||
className={`w-5 h-5 ${index < rating
|
||||
? 'fill-yellow-400 text-yellow-400'
|
||||
: 'fill-gray-200 text-gray-200'
|
||||
}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="py-16 bg-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="text-center mb-12"
|
||||
>
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
||||
{title}
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
|
||||
{subtitle}
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
<div className={`grid gap-8 ${displayTestimonials.length === 1
|
||||
? 'grid-cols-1 max-w-2xl mx-auto'
|
||||
: displayTestimonials.length === 2
|
||||
? 'grid-cols-1 md:grid-cols-2 max-w-4xl mx-auto'
|
||||
: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3'
|
||||
}`}>
|
||||
{displayTestimonials.map((testimonial, index) => (
|
||||
<motion.div
|
||||
key={testimonial.id}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||
>
|
||||
<Card hover className="h-full flex flex-col">
|
||||
<CardHeader>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
{renderStars(testimonial.rating)}
|
||||
{testimonial.verified && (
|
||||
<span className="inline-flex items-center gap-1 px-2 py-1 bg-green-100 text-green-700 text-xs font-medium rounded-full">
|
||||
<CheckCircle className="w-3 h-3" />
|
||||
Verified
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold text-gray-900 mb-2">
|
||||
{testimonial.title}
|
||||
</h3>
|
||||
</CardHeader>
|
||||
<CardContent className="flex-grow">
|
||||
<p className="text-gray-700 leading-relaxed mb-6">
|
||||
{testimonial.content}
|
||||
</p>
|
||||
<div className="border-t border-gray-200 pt-4 mt-auto">
|
||||
<div className="flex flex-col">
|
||||
<span className="font-semibold text-gray-900">
|
||||
{testimonial.author.name}
|
||||
</span>
|
||||
<div className="text-sm text-gray-600">
|
||||
{testimonial.author.company && (
|
||||
<span>{testimonial.author.company}</span>
|
||||
)}
|
||||
{testimonial.author.company && testimonial.author.location && (
|
||||
<span> • </span>
|
||||
)}
|
||||
{testimonial.author.location && (
|
||||
<span>{testimonial.author.location}</span>
|
||||
)}
|
||||
</div>
|
||||
<span className="text-xs text-gray-500 mt-1">
|
||||
{testimonial.date}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
{!showAll && (
|
||||
<div className="mt-12 text-center">
|
||||
<a href="/testimonials" className="inline-flex items-center text-blue-600 font-semibold hover:text-blue-700 transition-colors">
|
||||
See all reviews
|
||||
<svg className="w-4 h-4 ml-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section >
|
||||
);
|
||||
};
|
||||
@@ -44,6 +44,8 @@ export function Footer({ variant = 'marketing', t }: FooterProps) {
|
||||
<ul className={`space-y-2 ${isDashboard ? 'text-gray-500' : 'text-gray-400'}`}>
|
||||
<li><Link href="/features" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>{translations.features}</Link></li>
|
||||
<li><Link href="/about" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>About</Link></li>
|
||||
<li><Link href="/press" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>Press</Link></li>
|
||||
<li><Link href="/testimonials" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>Testimonials</Link></li>
|
||||
<li><Link href="/authors/timo" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>Timo Knuth (Author)</Link></li>
|
||||
<li><Link href="/#pricing" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>{translations.pricing}</Link></li>
|
||||
<li><Link href="/qr-code-tracking" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>QR Analytics</Link></li>
|
||||
|
||||
Reference in New Issue
Block a user