diff --git a/src/app/(marketing)/tools/crypto-qr-code/CryptoGenerator.tsx b/src/app/(marketing)/tools/crypto-qr-code/CryptoGenerator.tsx index a23dc21..ee12fd8 100644 --- a/src/app/(marketing)/tools/crypto-qr-code/CryptoGenerator.tsx +++ b/src/app/(marketing)/tools/crypto-qr-code/CryptoGenerator.tsx @@ -209,7 +209,7 @@ export default function CryptoGenerator() { Wallet Direct -

+

{qrMode === 'universal' ? "Works with any phone camera. Opens blockchain explorer." : "Requires scanning from a wallet app. Enables direct payment."} @@ -319,7 +319,7 @@ export default function CryptoGenerator() { {currency} -

+
{address || 'Wallet Address'}
@@ -344,7 +344,7 @@ export default function CryptoGenerator() { -

+

Scanning copies the wallet address or opens a crypto app.

diff --git a/src/app/(marketing)/tools/email-qr-code/EmailGenerator.tsx b/src/app/(marketing)/tools/email-qr-code/EmailGenerator.tsx index 3b558cb..c45643c 100644 --- a/src/app/(marketing)/tools/email-qr-code/EmailGenerator.tsx +++ b/src/app/(marketing)/tools/email-qr-code/EmailGenerator.tsx @@ -272,7 +272,7 @@ export default function EmailGenerator() { -

+

100% free. No signup required.

diff --git a/src/app/(marketing)/tools/event-qr-code/EventGenerator.tsx b/src/app/(marketing)/tools/event-qr-code/EventGenerator.tsx index 643e5e1..ce836b9 100644 --- a/src/app/(marketing)/tools/event-qr-code/EventGenerator.tsx +++ b/src/app/(marketing)/tools/event-qr-code/EventGenerator.tsx @@ -277,7 +277,7 @@ export default function EventGenerator() { {title || 'Event Title'} {(startDate) && ( -
+
{new Date(startDate).toLocaleDateString()}
@@ -304,7 +304,7 @@ export default function EventGenerator() {
-

+

Scanning adds the event to the user's calendar.

diff --git a/src/app/(marketing)/tools/facebook-qr-code/FacebookGenerator.tsx b/src/app/(marketing)/tools/facebook-qr-code/FacebookGenerator.tsx index 2dc570c..2a00d7d 100644 --- a/src/app/(marketing)/tools/facebook-qr-code/FacebookGenerator.tsx +++ b/src/app/(marketing)/tools/facebook-qr-code/FacebookGenerator.tsx @@ -105,7 +105,7 @@ export default function FacebookGenerator() { onChange={(e) => setUrl(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#1877F2] focus:ring-[#1877F2]" /> -

Paste the full link to your profile, page, group, or post.

+

Paste the full link to your profile, page, group, or post.

@@ -198,7 +198,7 @@ export default function FacebookGenerator() { {url ? url.replace('https://', '') : 'facebook.com/...'} -
Opens in Facebook App
+
Opens in Facebook App
@@ -221,7 +221,7 @@ export default function FacebookGenerator() { -

+

Scanning redirects directly to the Facebook profile or page.

diff --git a/src/app/(marketing)/tools/geolocation-qr-code/GeolocationGenerator.tsx b/src/app/(marketing)/tools/geolocation-qr-code/GeolocationGenerator.tsx index 4bf38e6..84efdb3 100644 --- a/src/app/(marketing)/tools/geolocation-qr-code/GeolocationGenerator.tsx +++ b/src/app/(marketing)/tools/geolocation-qr-code/GeolocationGenerator.tsx @@ -148,7 +148,7 @@ export default function GeolocationGenerator() { /> -

+

Tip: You can copy-paste coordinates directly from Google Maps. (Right-click a location on standard Maps, then click the coordinates to copy).

@@ -243,7 +243,7 @@ export default function GeolocationGenerator() { {latitude || 'Lat'}, {longitude || 'Long'} -
Google Maps Location
+
Google Maps Location
@@ -266,7 +266,7 @@ export default function GeolocationGenerator() { -

+

Scanning opens the location directly in Google Maps.

diff --git a/src/app/(marketing)/tools/geolocation-qr-code/page.tsx b/src/app/(marketing)/tools/geolocation-qr-code/page.tsx index cd7ce9b..83aea22 100644 --- a/src/app/(marketing)/tools/geolocation-qr-code/page.tsx +++ b/src/app/(marketing)/tools/geolocation-qr-code/page.tsx @@ -211,7 +211,7 @@ export default function GeolocationQRCodePage() {
-
+
40.7128° N, 74.0060° W
diff --git a/src/app/(marketing)/tools/instagram-qr-code/InstagramGenerator.tsx b/src/app/(marketing)/tools/instagram-qr-code/InstagramGenerator.tsx index 8c8f404..78ad0df 100644 --- a/src/app/(marketing)/tools/instagram-qr-code/InstagramGenerator.tsx +++ b/src/app/(marketing)/tools/instagram-qr-code/InstagramGenerator.tsx @@ -110,7 +110,7 @@ export default function InstagramGenerator() { onChange={(e) => setUsername(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#E1306C] focus:ring-[#E1306C]" /> -

Enter your username (without @) or paste full profile link.

+

Enter your username (without @) or paste full profile link.

@@ -203,7 +203,7 @@ export default function InstagramGenerator() { {username || '@username'} -
Opens in Instagram
+
Opens in Instagram
@@ -226,7 +226,7 @@ export default function InstagramGenerator() { -

+

Scanning redirects directly to your Instagram profile.

diff --git a/src/app/(marketing)/tools/paypal-qr-code/PayPalGenerator.tsx b/src/app/(marketing)/tools/paypal-qr-code/PayPalGenerator.tsx index 0a63406..2c455ad 100644 --- a/src/app/(marketing)/tools/paypal-qr-code/PayPalGenerator.tsx +++ b/src/app/(marketing)/tools/paypal-qr-code/PayPalGenerator.tsx @@ -171,7 +171,7 @@ export default function PayPalGenerator() { onChange={(e) => setPaypalId(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#003087] focus:ring-[#003087]" /> -

+

{inputType === 'username' ? <>Find yours at paypal.me : 'The email address linked to your PayPal account' @@ -293,7 +293,7 @@ export default function PayPalGenerator() { {paypalId || 'Your PayPal'} {amount && ( -

{amount} {currency}

+

{amount} {currency}

)} @@ -317,7 +317,7 @@ export default function PayPalGenerator() { -

+

Your PayPal link is encoded directly. Static and forever free.

diff --git a/src/app/(marketing)/tools/phone-qr-code/PhoneGenerator.tsx b/src/app/(marketing)/tools/phone-qr-code/PhoneGenerator.tsx index e2c6b53..eb810eb 100644 --- a/src/app/(marketing)/tools/phone-qr-code/PhoneGenerator.tsx +++ b/src/app/(marketing)/tools/phone-qr-code/PhoneGenerator.tsx @@ -106,7 +106,7 @@ export default function PhoneGenerator() { onChange={(e) => setPhone(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#1A1265] focus:ring-[#1A1265]" /> -

Enter with country code for best results (e.g. +1).

+

Enter with country code for best results (e.g. +1).

@@ -221,7 +221,7 @@ export default function PhoneGenerator() { -

+

Scanning initiates a call on any mobile phone.

diff --git a/src/app/(marketing)/tools/sms-qr-code/SMSGenerator.tsx b/src/app/(marketing)/tools/sms-qr-code/SMSGenerator.tsx index 1c57d8c..11ef166 100644 --- a/src/app/(marketing)/tools/sms-qr-code/SMSGenerator.tsx +++ b/src/app/(marketing)/tools/sms-qr-code/SMSGenerator.tsx @@ -120,7 +120,7 @@ export default function SMSGenerator() { onChange={(e) => setMessage(e.target.value)} maxLength={160} /> -

{message.length}/160

+

{message.length}/160

@@ -214,7 +214,7 @@ export default function SMSGenerator() { {phone || 'Number'} -
+
{message || 'Your message...'}
@@ -240,7 +240,7 @@ export default function SMSGenerator() {
-

+

Opens the messaging app with text pre-filled.

diff --git a/src/app/(marketing)/tools/teams-qr-code/TeamsGenerator.tsx b/src/app/(marketing)/tools/teams-qr-code/TeamsGenerator.tsx index e308197..927c190 100644 --- a/src/app/(marketing)/tools/teams-qr-code/TeamsGenerator.tsx +++ b/src/app/(marketing)/tools/teams-qr-code/TeamsGenerator.tsx @@ -152,7 +152,7 @@ export default function TeamsGenerator() { onChange={(e) => setMeetingUrl(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#6264A7] focus:ring-[#6264A7]" /> -

+

Copy the meeting link from your Teams calendar invite.

@@ -166,7 +166,7 @@ export default function TeamsGenerator() { onChange={(e) => setUserEmail(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#6264A7] focus:ring-[#6264A7]" /> -

+

The person's work email to start a Teams chat.

@@ -269,7 +269,7 @@ export default function TeamsGenerator() { {linkType === 'meeting' ? 'Teams Meeting' : (userEmail || 'Teams Chat')} -

+

{linkType === 'meeting' ? 'Join Meeting' : 'Start Chat'}

@@ -294,7 +294,7 @@ export default function TeamsGenerator() { -

+

Works with Microsoft Teams desktop and mobile apps.

diff --git a/src/app/(marketing)/tools/teams-qr-code/page.tsx b/src/app/(marketing)/tools/teams-qr-code/page.tsx index 1fb9c41..6b2f6d8 100644 --- a/src/app/(marketing)/tools/teams-qr-code/page.tsx +++ b/src/app/(marketing)/tools/teams-qr-code/page.tsx @@ -200,7 +200,7 @@ export default function TeamsQRCodePage() {
Team Standup
-
Daily at 9:00 AM
+
Daily at 9:00 AM
diff --git a/src/app/(marketing)/tools/text-qr-code/TextGenerator.tsx b/src/app/(marketing)/tools/text-qr-code/TextGenerator.tsx index 85062ad..0af88f2 100644 --- a/src/app/(marketing)/tools/text-qr-code/TextGenerator.tsx +++ b/src/app/(marketing)/tools/text-qr-code/TextGenerator.tsx @@ -221,7 +221,7 @@ export default function TextGenerator() {
-

+

Your text stays on your device. Nothing is sent to servers.

diff --git a/src/app/(marketing)/tools/tiktok-qr-code/TikTokGenerator.tsx b/src/app/(marketing)/tools/tiktok-qr-code/TikTokGenerator.tsx index 0cf2b5c..6bfec27 100644 --- a/src/app/(marketing)/tools/tiktok-qr-code/TikTokGenerator.tsx +++ b/src/app/(marketing)/tools/tiktok-qr-code/TikTokGenerator.tsx @@ -110,7 +110,7 @@ export default function TiktokGenerator() { onChange={(e) => setUsername(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-black focus:ring-black" /> -

Enter your TikTok handle (e.g. @charlidamelio).

+

Enter your TikTok handle (e.g. @charlidamelio).

@@ -203,7 +203,7 @@ export default function TiktokGenerator() { {username || '@username'} -
Opens in TikTok
+
Opens in TikTok
@@ -226,7 +226,7 @@ export default function TiktokGenerator() { -

+

Scanning redirects directly to your TikTok profile.

diff --git a/src/app/(marketing)/tools/twitter-qr-code/TwitterGenerator.tsx b/src/app/(marketing)/tools/twitter-qr-code/TwitterGenerator.tsx index c2ce7f1..d64dc77 100644 --- a/src/app/(marketing)/tools/twitter-qr-code/TwitterGenerator.tsx +++ b/src/app/(marketing)/tools/twitter-qr-code/TwitterGenerator.tsx @@ -110,7 +110,7 @@ export default function TwitterGenerator() { onChange={(e) => setUsername(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-black focus:ring-black" /> -

Enter your X (Twitter) handle to create a profile link.

+

Enter your X (Twitter) handle to create a profile link.

@@ -203,7 +203,7 @@ export default function TwitterGenerator() { {username || '@username'} -
Opens in X (Twitter)
+
Opens in X (Twitter)
@@ -226,7 +226,7 @@ export default function TwitterGenerator() { -

+

Scanning redirects directly to the X profile.

diff --git a/src/app/(marketing)/tools/url-qr-code/URLGenerator.tsx b/src/app/(marketing)/tools/url-qr-code/URLGenerator.tsx index 4c2260d..bc2a90e 100644 --- a/src/app/(marketing)/tools/url-qr-code/URLGenerator.tsx +++ b/src/app/(marketing)/tools/url-qr-code/URLGenerator.tsx @@ -104,7 +104,7 @@ export default function URLGenerator() { onChange={(e) => setUrl(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#4F46E5] focus:ring-[#4F46E5]" /> -

Include https:// for best results.

+

Include https:// for best results.

@@ -219,7 +219,7 @@ export default function URLGenerator() { -

+

Your link is encoded directly. Static and forever free.

diff --git a/src/app/(marketing)/tools/vcard-qr-code/VCardGenerator.tsx b/src/app/(marketing)/tools/vcard-qr-code/VCardGenerator.tsx index f6253dd..a772b4a 100644 --- a/src/app/(marketing)/tools/vcard-qr-code/VCardGenerator.tsx +++ b/src/app/(marketing)/tools/vcard-qr-code/VCardGenerator.tsx @@ -299,7 +299,7 @@ export default function VCardGenerator() { {firstName || 'First'} {lastName || 'Last'} -
{company || 'Company Name'}
+
{company || 'Company Name'}
@@ -322,7 +322,7 @@ export default function VCardGenerator() { -

+

Scanning adds this contact to the address book instantly.

diff --git a/src/app/(marketing)/tools/whatsapp-qr-code/WhatsAppGenerator.tsx b/src/app/(marketing)/tools/whatsapp-qr-code/WhatsAppGenerator.tsx index 61d41f6..7be5967 100644 --- a/src/app/(marketing)/tools/whatsapp-qr-code/WhatsAppGenerator.tsx +++ b/src/app/(marketing)/tools/whatsapp-qr-code/WhatsAppGenerator.tsx @@ -115,7 +115,7 @@ export default function WhatsappGenerator() { onChange={(e) => setPhone(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#25D366] focus:ring-[#25D366]" /> -

Include country code (e.g. 1 for US, 44 for UK). No '+' symbol.

+

Include country code (e.g. 1 for US, 44 for UK). No '+' symbol.

@@ -218,7 +218,7 @@ export default function WhatsappGenerator() { {phone ? `+${phone}` : 'Number'} -
Starts WhatsApp Chat
+
Starts WhatsApp Chat
@@ -241,7 +241,7 @@ export default function WhatsappGenerator() { -

+

Scanning starts a chat with this number instantly.

diff --git a/src/app/(marketing)/tools/whatsapp-qr-code/page.tsx b/src/app/(marketing)/tools/whatsapp-qr-code/page.tsx index 3829dc9..57caf5f 100644 --- a/src/app/(marketing)/tools/whatsapp-qr-code/page.tsx +++ b/src/app/(marketing)/tools/whatsapp-qr-code/page.tsx @@ -210,12 +210,12 @@ export default function WhatsappQRCodePage() { {/* Chat Bubble Right */}
Hi! I'd like to book an appointment. -
10:42 AM ✓✓
+
10:42 AM ✓✓
{/* Chat Bubble Left */}
Sure! What time works for you? -
10:43 AM
+
10:43 AM
diff --git a/src/app/(marketing)/tools/wifi-qr-code/WiFiGenerator.tsx b/src/app/(marketing)/tools/wifi-qr-code/WiFiGenerator.tsx index 2cea310..9d304e8 100644 --- a/src/app/(marketing)/tools/wifi-qr-code/WiFiGenerator.tsx +++ b/src/app/(marketing)/tools/wifi-qr-code/WiFiGenerator.tsx @@ -282,7 +282,7 @@ export default function WiFiGenerator() { -

+

Your credentials stay on your device. Nothing is sent to servers.

diff --git a/src/app/(marketing)/tools/youtube-qr-code/YouTubeGenerator.tsx b/src/app/(marketing)/tools/youtube-qr-code/YouTubeGenerator.tsx index 482d7e1..f827a0e 100644 --- a/src/app/(marketing)/tools/youtube-qr-code/YouTubeGenerator.tsx +++ b/src/app/(marketing)/tools/youtube-qr-code/YouTubeGenerator.tsx @@ -103,7 +103,7 @@ export default function YoutubeGenerator() { onChange={(e) => setUrl(e.target.value)} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#FF0000] focus:ring-[#FF0000]" /> -

Paste a link to any video, channel, or playlist.

+

Paste a link to any video, channel, or playlist.

@@ -196,7 +196,7 @@ export default function YoutubeGenerator() { {url ? 'YouTube Content' : 'youtube.com'} -
Opens in YouTube App
+
Opens in YouTube App
@@ -219,7 +219,7 @@ export default function YoutubeGenerator() { -

+

Scanning redirects directly to the video or channel.

diff --git a/src/app/(marketing)/tools/zoom-qr-code/ZoomGenerator.tsx b/src/app/(marketing)/tools/zoom-qr-code/ZoomGenerator.tsx index 89618fd..31bb1e9 100644 --- a/src/app/(marketing)/tools/zoom-qr-code/ZoomGenerator.tsx +++ b/src/app/(marketing)/tools/zoom-qr-code/ZoomGenerator.tsx @@ -136,7 +136,7 @@ export default function ZoomGenerator() { onChange={(e) => setMeetingId(e.target.value.replace(/\D/g, ''))} className="h-12 text-base rounded-xl border-slate-200 focus:border-[#2D8CFF] focus:ring-[#2D8CFF]" /> -

The 10-11 digit meeting ID from your Zoom invite.

+

The 10-11 digit meeting ID from your Zoom invite.

@@ -254,7 +254,7 @@ export default function ZoomGenerator() { {formatMeetingId(meetingId) || 'Meeting ID'} {passcode && ( -

Passcode: {passcode}

+

Passcode: {passcode}

)}
@@ -278,7 +278,7 @@ export default function ZoomGenerator() { -

+

Your meeting ID is encoded directly. Static and forever free.

diff --git a/src/app/(marketing)/tools/zoom-qr-code/page.tsx b/src/app/(marketing)/tools/zoom-qr-code/page.tsx index 755a125..cd98c4e 100644 --- a/src/app/(marketing)/tools/zoom-qr-code/page.tsx +++ b/src/app/(marketing)/tools/zoom-qr-code/page.tsx @@ -200,7 +200,7 @@ export default function ZoomQRCodePage() {
Team Standup
-
ID: 123 456 7890
+
ID: 123 456 7890
diff --git a/src/components/marketing/AIComingSoonBanner.tsx b/src/components/marketing/AIComingSoonBanner.tsx index 0a9292e..2d8c56c 100644 --- a/src/components/marketing/AIComingSoonBanner.tsx +++ b/src/components/marketing/AIComingSoonBanner.tsx @@ -1,216 +1,216 @@ -'use client'; - -import React, { useState } from 'react'; -import { Sparkles, Brain, TrendingUp, MessageSquare, Palette, ArrowRight, Mail, CheckCircle2, Lock } from 'lucide-react'; -import Link from 'next/link'; -import { motion } from 'framer-motion'; - -const AIComingSoonBanner = () => { - const [email, setEmail] = useState(''); - const [submitted, setSubmitted] = useState(false); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(''); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setLoading(true); - setError(''); - - try { - const response = await fetch('/api/newsletter/subscribe', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ email }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || 'Failed to subscribe'); - } - - setSubmitted(true); - setEmail(''); - } catch (err) { - setError(err instanceof Error ? err.message : 'Something went wrong. Please try again.'); - } finally { - setLoading(false); - } - }; - - const features = [ - { - icon: Brain, - category: 'Smart QR Generation', - items: [ - 'AI-powered content optimization', - 'Intelligent design suggestions', - 'Auto-generate vCard from LinkedIn', - 'Smart URL shortening with SEO', - ], - }, - { - icon: TrendingUp, - category: 'Advanced Analytics & Insights', - items: [ - 'AI-powered scan predictions', - 'Anomaly detection', - 'Natural language analytics queries', - 'Automated insights reports', - ], - }, - { - icon: MessageSquare, - category: 'Smart Content Management', - items: [ - 'AI chatbot for instant support', - 'Automated QR categorization', - 'Smart bulk QR generation', - 'Content recommendations', - ], - }, - { - icon: Palette, - category: 'Creative & Marketing', - items: [ - 'AI-generated custom QR designs', - 'Marketing copy generation', - 'A/B testing suggestions', - 'Campaign optimization', - ], - }, - ]; - - return ( -
- {/* Animated Background Orbs (matching Hero) */} -
-
-
-
-
- -
- {/* Header */} - {/* Header */} - -
- - - Coming Soon - -
- -

- The Future of QR Codes is{' '} - - AI-Powered - -

- -

- Revolutionary AI features to transform how you create, manage, and optimize QR codes -

-
- - {/* Features Grid */} -
- {features.map((feature, index) => ( - -
- -
- -

- {feature.category} -

- -
    - {feature.items.map((item, itemIndex) => ( -
  • -
    - {item} -
  • - ))} -
-
- ))} -
- - {/* Email Capture */} - - {!submitted ? ( - <> -
-
- - { - setEmail(e.target.value); - setError(''); - }} - placeholder="your@email.com" - required - disabled={loading} - className="w-full pl-12 pr-4 py-3 rounded-xl bg-white border border-gray-200 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 outline-none transition-all" - /> -
- -
- {error && ( -

{error}

- )} -

- Be the first to know when AI features launch -

- - ) : ( -
- - - You're on the list! We'll notify you when AI features launch. - -
- )} -
-
-
-
- ); -}; - -export default AIComingSoonBanner; +'use client'; + +import React, { useState } from 'react'; +import { Sparkles, Brain, TrendingUp, MessageSquare, Palette, ArrowRight, Mail, CheckCircle2, Lock } from 'lucide-react'; +import Link from 'next/link'; +import { motion } from 'framer-motion'; + +const AIComingSoonBanner = () => { + const [email, setEmail] = useState(''); + const [submitted, setSubmitted] = useState(false); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + setError(''); + + try { + const response = await fetch('/api/newsletter/subscribe', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ email }), + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error(data.error || 'Failed to subscribe'); + } + + setSubmitted(true); + setEmail(''); + } catch (err) { + setError(err instanceof Error ? err.message : 'Something went wrong. Please try again.'); + } finally { + setLoading(false); + } + }; + + const features = [ + { + icon: Brain, + category: 'Smart QR Generation', + items: [ + 'AI-powered content optimization', + 'Intelligent design suggestions', + 'Auto-generate vCard from LinkedIn', + 'Smart URL shortening with SEO', + ], + }, + { + icon: TrendingUp, + category: 'Advanced Analytics & Insights', + items: [ + 'AI-powered scan predictions', + 'Anomaly detection', + 'Natural language analytics queries', + 'Automated insights reports', + ], + }, + { + icon: MessageSquare, + category: 'Smart Content Management', + items: [ + 'AI chatbot for instant support', + 'Automated QR categorization', + 'Smart bulk QR generation', + 'Content recommendations', + ], + }, + { + icon: Palette, + category: 'Creative & Marketing', + items: [ + 'AI-generated custom QR designs', + 'Marketing copy generation', + 'A/B testing suggestions', + 'Campaign optimization', + ], + }, + ]; + + return ( +
+ {/* Animated Background Orbs (matching Hero) */} +
+
+
+
+
+ +
+ {/* Header */} + {/* Header */} + +
+ + + Coming Soon + +
+ +

+ The Future of QR Codes is{' '} + + AI-Powered + +

+ +

+ Revolutionary AI features to transform how you create, manage, and optimize QR codes +

+
+ + {/* Features Grid */} +
+ {features.map((feature, index) => ( + +
+ +
+ +

+ {feature.category} +

+ +
    + {feature.items.map((item, itemIndex) => ( +
  • +
    + {item} +
  • + ))} +
+
+ ))} +
+ + {/* Email Capture */} + + {!submitted ? ( + <> +
+
+ + { + setEmail(e.target.value); + setError(''); + }} + placeholder="your@email.com" + required + disabled={loading} + className="w-full pl-12 pr-4 py-3 rounded-xl bg-white border border-gray-200 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 outline-none transition-all" + /> +
+ +
+ {error && ( +

{error}

+ )} +

+ Be the first to know when AI features launch +

+ + ) : ( +
+ + + You're on the list! We'll notify you when AI features launch. + +
+ )} +
+
+
+
+ ); +}; + +export default AIComingSoonBanner; diff --git a/src/components/marketing/FAQ.tsx b/src/components/marketing/FAQ.tsx index 3fa7b6b..69b793c 100644 --- a/src/components/marketing/FAQ.tsx +++ b/src/components/marketing/FAQ.tsx @@ -1,92 +1,92 @@ -'use client'; - -import React, { useState } from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { Card } from '@/components/ui/Card'; - -interface FAQProps { - t: any; // i18n translation function -} - -export const FAQ: React.FC = ({ t }) => { - const [openIndex, setOpenIndex] = useState(null); - - const questions = [ - 'account', - 'static_vs_dynamic', - 'forever', - 'file_type', - 'analytics', - ]; - - return ( -
-
- -

- {t.faq.title} -

-
- -
- {questions.map((key, index) => ( - - setOpenIndex(openIndex === index ? null : index)}> -
-
-

- {t.faq.questions[key].question} -

- -
- - - {openIndex === index && ( - -
- {t.faq.questions[key].answer} -
-
- )} -
-
-
-
- ))} -
- - -
-
- ); -}; \ No newline at end of file +'use client'; + +import React, { useState } from 'react'; +import { motion, AnimatePresence } from 'framer-motion'; +import { Card } from '@/components/ui/Card'; + +interface FAQProps { + t: any; // i18n translation function +} + +export const FAQ: React.FC = ({ t }) => { + const [openIndex, setOpenIndex] = useState(null); + + const questions = [ + 'account', + 'static_vs_dynamic', + 'forever', + 'file_type', + 'analytics', + ]; + + return ( +
+
+ +

+ {t.faq.title} +

+
+ +
+ {questions.map((key, index) => ( + + setOpenIndex(openIndex === index ? null : index)}> +
+
+

+ {t.faq.questions[key].question} +

+ +
+ + + {openIndex === index && ( + +
+ {t.faq.questions[key].answer} +
+
+ )} +
+
+
+
+ ))} +
+ + +
+
+ ); +}; diff --git a/src/components/marketing/Features.tsx b/src/components/marketing/Features.tsx index 0a7b532..d701366 100644 --- a/src/components/marketing/Features.tsx +++ b/src/components/marketing/Features.tsx @@ -1,85 +1,85 @@ -'use client'; - -import React from 'react'; -import { motion } from 'framer-motion'; -import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'; - -interface FeaturesProps { - t: any; // i18n translation function -} - -export const Features: React.FC = ({ t }) => { - const features = [ - { - key: 'analytics', - icon: ( - - ), - color: 'text-blue-600 bg-blue-100', - }, - { - key: 'customization', - icon: ( - - ), - color: 'text-purple-600 bg-purple-100', - }, - { - key: 'unlimited', - icon: ( - - ), - color: 'text-green-600 bg-green-100', - }, - ]; - - return ( -
-
- -

- {t.features.title} -

-
- -
- {features.map((feature, index) => ( - - - -
- {feature.icon} -
- {t.features[feature.key].title} -
- -

- {t.features[feature.key].description} -

-
-
-
- ))} -
-
-
- ); -}; \ No newline at end of file +'use client'; + +import React from 'react'; +import { motion } from 'framer-motion'; +import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'; + +interface FeaturesProps { + t: any; // i18n translation function +} + +export const Features: React.FC = ({ t }) => { + const features = [ + { + key: 'analytics', + icon: ( + + ), + color: 'text-blue-600 bg-blue-100', + }, + { + key: 'customization', + icon: ( + + ), + color: 'text-purple-600 bg-purple-100', + }, + { + key: 'unlimited', + icon: ( + + ), + color: 'text-green-600 bg-green-100', + }, + ]; + + return ( +
+
+ +

+ {t.features.title} +

+
+ +
+ {features.map((feature, index) => ( + + + +
+ {feature.icon} +
+ {t.features[feature.key].title} +
+ +

+ {t.features[feature.key].description} +

+
+
+
+ ))} +
+
+
+ ); +}; diff --git a/src/components/marketing/FreeToolsGrid.tsx b/src/components/marketing/FreeToolsGrid.tsx index afb98a1..f717479 100644 --- a/src/components/marketing/FreeToolsGrid.tsx +++ b/src/components/marketing/FreeToolsGrid.tsx @@ -47,7 +47,7 @@ const TOOLS = [ name: 'Text', description: 'Display plain text', href: '/tools/text-qr-code', - color: 'text-slate-500', + color: 'text-slate-600', bg: 'bg-slate-50' }, { @@ -240,7 +240,7 @@ export function FreeToolsGrid() {

{tool.name}

-

+

{tool.description}

diff --git a/src/components/marketing/Hero.tsx b/src/components/marketing/Hero.tsx index b5bceb7..4b61d30 100644 --- a/src/components/marketing/Hero.tsx +++ b/src/components/marketing/Hero.tsx @@ -1,155 +1,155 @@ -'use client'; - -import React from 'react'; -import Link from 'next/link'; -import { Button } from '@/components/ui/Button'; -import { Badge } from '@/components/ui/Badge'; -import { Card } from '@/components/ui/Card'; -import { motion } from 'framer-motion'; -import { Globe, User, MapPin, Phone, CheckCircle2, ArrowRight } from 'lucide-react'; - -interface HeroProps { - t: any; // i18n translation function -} - -export const Hero: React.FC = ({ t }) => { - const templateCards = [ - { title: 'URL/Website', color: 'bg-blue-500/10 text-blue-600', icon: Globe }, - { title: 'Contact Card', color: 'bg-purple-500/10 text-purple-600', icon: User }, - { title: 'Location', color: 'bg-green-500/10 text-green-600', icon: MapPin }, - { title: 'Phone Number', color: 'bg-pink-500/10 text-pink-600', icon: Phone }, - ]; - - const containerjs = { - hidden: { opacity: 0 }, - show: { - opacity: 1, - transition: { - staggerChildren: 0.1 - } - } - }; - - const itemjs = { - hidden: { opacity: 0, y: 20 }, - show: { opacity: 1, y: 0 } - }; - - return ( -
- {/* Animated Background Orbs */} -
- {/* Orb 1 - Blue (top-left) */} -
- - {/* Orb 2 - Purple (top-right) */} -
- - {/* Orb 3 - Pink (bottom-left) */} -
- - {/* Orb 4 - Cyan (center-right) */} -
-
- -
-
- {/* Left Content */} -
- - {t.hero.badge} - - - -

- {t.hero.title} -

- -

- {t.hero.subtitle} -

- -
- {t.hero.features.map((feature: string, index: number) => ( - -
- -
- {feature} -
- ))} -
-
- - - - - - - - - -
- - {/* Right Preview Widget */} -
- - {templateCards.map((card, index) => ( - - -
- -
-

{card.title}

-
-
- ))} -
- - {/* Floating Badge */} - - - - - - {t.hero.engagement_badge} - -
-
-
- - {/* Smooth Gradient Fade Transition */} -
-
- ); -}; \ No newline at end of file +'use client'; + +import React from 'react'; +import Link from 'next/link'; +import { Button } from '@/components/ui/Button'; +import { Badge } from '@/components/ui/Badge'; +import { Card } from '@/components/ui/Card'; +import { motion } from 'framer-motion'; +import { Globe, User, MapPin, Phone, CheckCircle2, ArrowRight } from 'lucide-react'; + +interface HeroProps { + t: any; // i18n translation function +} + +export const Hero: React.FC = ({ t }) => { + const templateCards = [ + { title: 'URL/Website', color: 'bg-blue-500/10 text-blue-600', icon: Globe }, + { title: 'Contact Card', color: 'bg-purple-500/10 text-purple-600', icon: User }, + { title: 'Location', color: 'bg-green-500/10 text-green-600', icon: MapPin }, + { title: 'Phone Number', color: 'bg-pink-500/10 text-pink-600', icon: Phone }, + ]; + + const containerjs = { + hidden: { opacity: 0 }, + show: { + opacity: 1, + transition: { + staggerChildren: 0.1 + } + } + }; + + const itemjs = { + hidden: { opacity: 0, y: 20 }, + show: { opacity: 1, y: 0 } + }; + + return ( +
+ {/* Animated Background Orbs */} +
+ {/* Orb 1 - Blue (top-left) */} +
+ + {/* Orb 2 - Purple (top-right) */} +
+ + {/* Orb 3 - Pink (bottom-left) */} +
+ + {/* Orb 4 - Cyan (center-right) */} +
+
+ +
+
+ {/* Left Content */} +
+ + {t.hero.badge} + + + +

+ {t.hero.title} +

+ +

+ {t.hero.subtitle} +

+ +
+ {t.hero.features.map((feature: string, index: number) => ( + +
+ +
+ {feature} +
+ ))} +
+
+ + + + + + + + + +
+ + {/* Right Preview Widget */} +
+ + {templateCards.map((card, index) => ( + + +
+ +
+

{card.title}

+
+
+ ))} +
+ + {/* Floating Badge */} + + + + + + {t.hero.engagement_badge} + +
+
+
+ + {/* Smooth Gradient Fade Transition */} +
+
+ ); +}; diff --git a/src/components/marketing/InstantGenerator.tsx b/src/components/marketing/InstantGenerator.tsx index 82d72b7..259c1ca 100644 --- a/src/components/marketing/InstantGenerator.tsx +++ b/src/components/marketing/InstantGenerator.tsx @@ -1,282 +1,282 @@ -'use client'; - -import React, { useState } from 'react'; -import { QRCodeSVG } from 'qrcode.react'; -import { motion } from 'framer-motion'; -import { Card } from '@/components/ui/Card'; -import { Input } from '@/components/ui/Input'; -import { Button } from '@/components/ui/Button'; -import { Badge } from '@/components/ui/Badge'; -import { calculateContrast } from '@/lib/utils'; - -interface InstantGeneratorProps { - t: any; // i18n translation function -} - -export const InstantGenerator: React.FC = ({ t }) => { - const [url, setUrl] = useState('https://example.com'); - const [foregroundColor, setForegroundColor] = useState('#000000'); - const [backgroundColor, setBackgroundColor] = useState('#FFFFFF'); - const [cornerStyle, setCornerStyle] = useState('square'); - const [size, setSize] = useState(200); - - const contrast = calculateContrast(foregroundColor, backgroundColor); - const hasGoodContrast = contrast >= 4.5; - - const downloadQR = (format: 'svg' | 'png') => { - const svg = document.querySelector('#instant-qr-preview svg'); - if (!svg || !url) return; - - if (format === 'svg') { - const svgData = new XMLSerializer().serializeToString(svg); - const blob = new Blob([svgData], { type: 'image/svg+xml' }); - const downloadUrl = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = downloadUrl; - a.download = 'qrcode.svg'; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(downloadUrl); - } else { - // Convert SVG to PNG using Canvas - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - const img = new Image(); - const svgData = new XMLSerializer().serializeToString(svg); - const blob = new Blob([svgData], { type: 'image/svg+xml' }); - const url = URL.createObjectURL(blob); - - img.onload = () => { - canvas.width = size; - canvas.height = size; - if (ctx) { - ctx.fillStyle = backgroundColor; - ctx.fillRect(0, 0, size, size); - ctx.drawImage(img, 0, 0, size, size); - } - canvas.toBlob((blob) => { - if (blob) { - const downloadUrl = URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = downloadUrl; - a.download = 'qrcode.png'; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - URL.revokeObjectURL(downloadUrl); - } - }); - URL.revokeObjectURL(url); - }; - img.src = url; - } - }; - - return ( -
-
-
- -

- {t.generator.title} -

-
- -
- {/* Left Form */} - - - setUrl(e.target.value)} - placeholder={t.generator.url_placeholder} - className="transition-all focus:ring-2 focus:ring-primary-500/20" - /> - -
-
- -
- setForegroundColor(e.target.value)} - className="w-14 h-12 rounded border border-gray-300 cursor-pointer" - aria-label="Foreground color picker" - /> - setForegroundColor(e.target.value)} - className="flex-1" - aria-label="Foreground color hex value" - /> -
-
- -
- -
- setBackgroundColor(e.target.value)} - className="w-14 h-12 rounded border border-gray-300 cursor-pointer" - aria-label="Background color picker" - /> - setBackgroundColor(e.target.value)} - className="flex-1" - aria-label="Background color hex value" - /> -
-
-
- -
-
- - -
- -
- - setSize(Number(e.target.value))} - className="w-full accent-primary-600" - aria-label={`QR code size: ${size} pixels`} - /> - -
-
- -
- - {hasGoodContrast ? t.generator.contrast_good : 'Low contrast'} - -
- Contrast: {contrast.toFixed(1)}:1 -
-
- -
- - -
- - -
-
- - {/* Right Preview */} - - {/* Artistic Curved Lines Background */} -
- - - - - - - - - - - - - - - -
-
- - {/* Decorative Orbs */} -
-
- -
-

{t.generator.live_preview}

-
- {url ? ( -
- -
- ) : ( -
- Enter URL -
- )} -
-
- {url || 'https://example.com'} -
-
{t.generator.demo_note}
-
-
-
-
-
- ); -}; \ No newline at end of file +'use client'; + +import React, { useState } from 'react'; +import { QRCodeSVG } from 'qrcode.react'; +import { motion } from 'framer-motion'; +import { Card } from '@/components/ui/Card'; +import { Input } from '@/components/ui/Input'; +import { Button } from '@/components/ui/Button'; +import { Badge } from '@/components/ui/Badge'; +import { calculateContrast } from '@/lib/utils'; + +interface InstantGeneratorProps { + t: any; // i18n translation function +} + +export const InstantGenerator: React.FC = ({ t }) => { + const [url, setUrl] = useState('https://example.com'); + const [foregroundColor, setForegroundColor] = useState('#000000'); + const [backgroundColor, setBackgroundColor] = useState('#FFFFFF'); + const [cornerStyle, setCornerStyle] = useState('square'); + const [size, setSize] = useState(200); + + const contrast = calculateContrast(foregroundColor, backgroundColor); + const hasGoodContrast = contrast >= 4.5; + + const downloadQR = (format: 'svg' | 'png') => { + const svg = document.querySelector('#instant-qr-preview svg'); + if (!svg || !url) return; + + if (format === 'svg') { + const svgData = new XMLSerializer().serializeToString(svg); + const blob = new Blob([svgData], { type: 'image/svg+xml' }); + const downloadUrl = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = downloadUrl; + a.download = 'qrcode.svg'; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(downloadUrl); + } else { + // Convert SVG to PNG using Canvas + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + const img = new Image(); + const svgData = new XMLSerializer().serializeToString(svg); + const blob = new Blob([svgData], { type: 'image/svg+xml' }); + const url = URL.createObjectURL(blob); + + img.onload = () => { + canvas.width = size; + canvas.height = size; + if (ctx) { + ctx.fillStyle = backgroundColor; + ctx.fillRect(0, 0, size, size); + ctx.drawImage(img, 0, 0, size, size); + } + canvas.toBlob((blob) => { + if (blob) { + const downloadUrl = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = downloadUrl; + a.download = 'qrcode.png'; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(downloadUrl); + } + }); + URL.revokeObjectURL(url); + }; + img.src = url; + } + }; + + return ( +
+
+
+ +

+ {t.generator.title} +

+
+ +
+ {/* Left Form */} + + + setUrl(e.target.value)} + placeholder={t.generator.url_placeholder} + className="transition-all focus:ring-2 focus:ring-primary-500/20" + /> + +
+
+ +
+ setForegroundColor(e.target.value)} + className="w-14 h-12 rounded border border-gray-300 cursor-pointer" + aria-label="Foreground color picker" + /> + setForegroundColor(e.target.value)} + className="flex-1" + aria-label="Foreground color hex value" + /> +
+
+ +
+ +
+ setBackgroundColor(e.target.value)} + className="w-14 h-12 rounded border border-gray-300 cursor-pointer" + aria-label="Background color picker" + /> + setBackgroundColor(e.target.value)} + className="flex-1" + aria-label="Background color hex value" + /> +
+
+
+ +
+
+ + +
+ +
+ + setSize(Number(e.target.value))} + className="w-full accent-primary-600" + aria-label={`QR code size: ${size} pixels`} + /> + +
+
+ +
+ + {hasGoodContrast ? t.generator.contrast_good : 'Low contrast'} + +
+ Contrast: {contrast.toFixed(1)}:1 +
+
+ +
+ + +
+ + +
+
+ + {/* Right Preview */} + + {/* Artistic Curved Lines Background */} +
+ + + + + + + + + + + + + + + +
+
+ + {/* Decorative Orbs */} +
+
+ +
+

{t.generator.live_preview}

+
+ {url ? ( +
+ +
+ ) : ( +
+ Enter URL +
+ )} +
+
+ {url || 'https://example.com'} +
+
{t.generator.demo_note}
+
+
+
+
+
+ ); +}; diff --git a/src/components/marketing/Pricing.tsx b/src/components/marketing/Pricing.tsx index 911b8fc..2655f6d 100644 --- a/src/components/marketing/Pricing.tsx +++ b/src/components/marketing/Pricing.tsx @@ -1,141 +1,141 @@ -'use client'; - -import React, { useState } from 'react'; -import { motion } from 'framer-motion'; -import Link from 'next/link'; -import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'; -import { Button } from '@/components/ui/Button'; -import { Badge } from '@/components/ui/Badge'; -import { BillingToggle } from '@/components/ui/BillingToggle'; - -interface PricingProps { - t: any; // i18n translation function -} - -export const Pricing: React.FC = ({ t }) => { - const [billingPeriod, setBillingPeriod] = useState<'month' | 'year'>('month'); - - const plans = [ - { - key: 'free', - popular: false, - }, - { - key: 'pro', - popular: true, - }, - { - key: 'business', - popular: false, - }, - ]; - - return ( -
-
- -

- {t.pricing.title} -

-

- {t.pricing.subtitle} -

-
- -
- -
- -
- {plans.map((plan, index) => ( - - - {plan.popular && ( -
- - {t.pricing[plan.key].badge} - -
- )} - - - - {t.pricing[plan.key].title} - -
-
- - {plan.key === 'free' - ? t.pricing[plan.key].price - : billingPeriod === 'month' - ? t.pricing[plan.key].price - : plan.key === 'pro' - ? '€90' - : '€290'} - - - {plan.key === 'free' - ? t.pricing[plan.key].period - : billingPeriod === 'month' - ? t.pricing[plan.key].period - : 'per year'} - -
- {billingPeriod === 'year' && plan.key !== 'free' && ( - - Save 16% - - )} -
-
- - -
    - {t.pricing[plan.key].features.map((feature: string, index: number) => ( -
  • - - - - {feature} -
  • - ))} -
- -
- - - -
-
-
-
- ))} -
-
-
- ); -}; \ No newline at end of file +'use client'; + +import React, { useState } from 'react'; +import { motion } from 'framer-motion'; +import Link from 'next/link'; +import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'; +import { Button } from '@/components/ui/Button'; +import { Badge } from '@/components/ui/Badge'; +import { BillingToggle } from '@/components/ui/BillingToggle'; + +interface PricingProps { + t: any; // i18n translation function +} + +export const Pricing: React.FC = ({ t }) => { + const [billingPeriod, setBillingPeriod] = useState<'month' | 'year'>('month'); + + const plans = [ + { + key: 'free', + popular: false, + }, + { + key: 'pro', + popular: true, + }, + { + key: 'business', + popular: false, + }, + ]; + + return ( +
+
+ +

+ {t.pricing.title} +

+

+ {t.pricing.subtitle} +

+
+ +
+ +
+ +
+ {plans.map((plan, index) => ( + + + {plan.popular && ( +
+ + {t.pricing[plan.key].badge} + +
+ )} + + + + {t.pricing[plan.key].title} + +
+
+ + {plan.key === 'free' + ? t.pricing[plan.key].price + : billingPeriod === 'month' + ? t.pricing[plan.key].price + : plan.key === 'pro' + ? '€90' + : '€290'} + + + {plan.key === 'free' + ? t.pricing[plan.key].period + : billingPeriod === 'month' + ? t.pricing[plan.key].period + : 'per year'} + +
+ {billingPeriod === 'year' && plan.key !== 'free' && ( + + Save 16% + + )} +
+
+ + +
    + {t.pricing[plan.key].features.map((feature: string, index: number) => ( +
  • + + + + {feature} +
  • + ))} +
+ +
+ + + +
+
+
+
+ ))} +
+
+
+ ); +}; diff --git a/src/components/marketing/StaticVsDynamic.tsx b/src/components/marketing/StaticVsDynamic.tsx index 2579cf7..6128112 100644 --- a/src/components/marketing/StaticVsDynamic.tsx +++ b/src/components/marketing/StaticVsDynamic.tsx @@ -1,98 +1,98 @@ -'use client'; - -import React from 'react'; -import { motion } from 'framer-motion'; -import { CheckCircle2 } from 'lucide-react'; -import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'; -import { Badge } from '@/components/ui/Badge'; - -interface StaticVsDynamicProps { - t: any; // i18n translation function -} - -export const StaticVsDynamic: React.FC = ({ t }) => { - return ( -
-
-
-

- {t.static_vs_dynamic.title} -

-

- {t.static_vs_dynamic.description} -

-
- -
- {/* Static QR Codes */} - - - -
- {t.static_vs_dynamic.static.title} - {t.static_vs_dynamic.static.subtitle} -
-

{t.static_vs_dynamic.static.description}

-
- -
    - {t.static_vs_dynamic.static.features.map((feature: string, index: number) => ( -
  • -
    - -
    - {feature} -
  • - ))} -
-
-
-
- - {/* Dynamic QR Codes */} - - -
-
- - - - -
-
- -
- {t.static_vs_dynamic.dynamic.title} - {t.static_vs_dynamic.dynamic.subtitle} -
-

{t.static_vs_dynamic.dynamic.description}

-
- -
    - {t.static_vs_dynamic.dynamic.features.map((feature: string, index: number) => ( -
  • -
    - -
    - {feature} -
  • - ))} -
-
-
-
-
-
-
- ); -}; \ No newline at end of file +'use client'; + +import React from 'react'; +import { motion } from 'framer-motion'; +import { CheckCircle2 } from 'lucide-react'; +import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'; +import { Badge } from '@/components/ui/Badge'; + +interface StaticVsDynamicProps { + t: any; // i18n translation function +} + +export const StaticVsDynamic: React.FC = ({ t }) => { + return ( +
+
+
+

+ {t.static_vs_dynamic.title} +

+

+ {t.static_vs_dynamic.description} +

+
+ +
+ {/* Static QR Codes */} + + + +
+ {t.static_vs_dynamic.static.title} + {t.static_vs_dynamic.static.subtitle} +
+

{t.static_vs_dynamic.static.description}

+
+ +
    + {t.static_vs_dynamic.static.features.map((feature: string, index: number) => ( +
  • +
    + +
    + {feature} +
  • + ))} +
+
+
+
+ + {/* Dynamic QR Codes */} + + +
+
+ + + + +
+
+ +
+ {t.static_vs_dynamic.dynamic.title} + {t.static_vs_dynamic.dynamic.subtitle} +
+

{t.static_vs_dynamic.dynamic.description}

+
+ +
    + {t.static_vs_dynamic.dynamic.features.map((feature: string, index: number) => ( +
  • +
    + +
    + {feature} +
  • + ))} +
+
+
+
+
+
+
+ ); +}; diff --git a/src/components/marketing/StatsStrip.tsx b/src/components/marketing/StatsStrip.tsx index 82aa87f..75c779b 100644 --- a/src/components/marketing/StatsStrip.tsx +++ b/src/components/marketing/StatsStrip.tsx @@ -1,35 +1,35 @@ -'use client'; - -import React from 'react'; - -interface StatsStripProps { - t: any; // i18n translation function -} - -export const StatsStrip: React.FC = ({ t }) => { - const stats = [ - { key: 'users', value: '1,240+', label: t.trust.users }, - { key: 'codes', value: '8,500+', label: t.trust.codes }, - { key: 'scans', value: '1.2M+', label: t.trust.scans }, - { key: 'countries', value: '120+', label: t.trust.countries }, - ]; - - return ( -
-
-
- {stats.map((stat, index) => ( -
-
- {stat.value} -
-
- {stat.label} -
-
- ))} -
-
-
- ); -}; \ No newline at end of file +'use client'; + +import React from 'react'; + +interface StatsStripProps { + t: any; // i18n translation function +} + +export const StatsStrip: React.FC = ({ t }) => { + const stats = [ + { key: 'users', value: '1,240+', label: t.trust.users }, + { key: 'codes', value: '8,500+', label: t.trust.codes }, + { key: 'scans', value: '1.2M+', label: t.trust.scans }, + { key: 'countries', value: '120+', label: t.trust.countries }, + ]; + + return ( +
+
+
+ {stats.map((stat, index) => ( +
+
+ {stat.value} +
+
+ {stat.label} +
+
+ ))} +
+
+
+ ); +}; diff --git a/src/components/marketing/TemplateCards.tsx b/src/components/marketing/TemplateCards.tsx index a8b97c4..5d56cd3 100644 --- a/src/components/marketing/TemplateCards.tsx +++ b/src/components/marketing/TemplateCards.tsx @@ -1,70 +1,70 @@ -'use client'; - -import React from 'react'; -import { Card } from '@/components/ui/Card'; -import { Button } from '@/components/ui/Button'; - -interface TemplateCardsProps { - t: any; // i18n translation function -} - -export const TemplateCards: React.FC = ({ t }) => { - const templates = [ - { - key: 'restaurant', - title: t.templates.restaurant, - icon: '🍽️', - color: 'bg-red-50 border-red-200', - iconBg: 'bg-red-100', - }, - { - key: 'business', - title: t.templates.business, - icon: '💼', - color: 'bg-blue-50 border-blue-200', - iconBg: 'bg-blue-100', - }, - { - key: 'vcard', - title: t.templates.vcard, - icon: '👤', - color: 'bg-purple-50 border-purple-200', - iconBg: 'bg-purple-100', - }, - { - key: 'event', - title: t.templates.event, - icon: '🎫', - color: 'bg-green-50 border-green-200', - iconBg: 'bg-green-100', - }, - ]; - - return ( -
-
-
-

- {t.templates.title} -

-
- -
- {templates.map((template) => ( - -
- {template.icon} -
-

- {template.title} -

- -
- ))} -
-
-
- ); -}; \ No newline at end of file +'use client'; + +import React from 'react'; +import { Card } from '@/components/ui/Card'; +import { Button } from '@/components/ui/Button'; + +interface TemplateCardsProps { + t: any; // i18n translation function +} + +export const TemplateCards: React.FC = ({ t }) => { + const templates = [ + { + key: 'restaurant', + title: t.templates.restaurant, + icon: '🍽️', + color: 'bg-red-50 border-red-200', + iconBg: 'bg-red-100', + }, + { + key: 'business', + title: t.templates.business, + icon: '💼', + color: 'bg-blue-50 border-blue-200', + iconBg: 'bg-blue-100', + }, + { + key: 'vcard', + title: t.templates.vcard, + icon: '👤', + color: 'bg-purple-50 border-purple-200', + iconBg: 'bg-purple-100', + }, + { + key: 'event', + title: t.templates.event, + icon: '🎫', + color: 'bg-green-50 border-green-200', + iconBg: 'bg-green-100', + }, + ]; + + return ( +
+
+
+

+ {t.templates.title} +

+
+ +
+ {templates.map((template) => ( + +
+ {template.icon} +
+

+ {template.title} +

+ +
+ ))} +
+
+
+ ); +};