From 231a85ffa40bb2302147281aa29891f55b48a879 Mon Sep 17 00:00:00 2001 From: Timo Knuth Date: Thu, 16 Apr 2026 19:34:26 +0200 Subject: [PATCH] Popup free generatoren --- .../BarcodeGeneratorClient.tsx | 7 +- .../call-qr-code-generator/PhoneGenerator.tsx | 6 ++ .../tools/crypto-qr-code/CryptoGenerator.tsx | 6 ++ .../tools/email-qr-code/EmailGenerator.tsx | 6 ++ .../tools/event-qr-code/EventGenerator.tsx | 6 ++ .../facebook-qr-code/FacebookGenerator.tsx | 6 ++ .../GeolocationGenerator.tsx | 6 ++ .../GoogleReviewGenerator.tsx | 6 ++ .../instagram-qr-code/InstagramGenerator.tsx | 6 ++ .../tools/paypal-qr-code/PayPalGenerator.tsx | 6 ++ .../tools/sms-qr-code/SMSGenerator.tsx | 6 ++ .../tools/teams-qr-code/TeamsGenerator.tsx | 6 ++ .../tools/text-qr-code/TextGenerator.tsx | 6 ++ .../tools/tiktok-qr-code/TikTokGenerator.tsx | 6 ++ .../twitter-qr-code/TwitterGenerator.tsx | 6 ++ .../tools/url-qr-code/URLGenerator.tsx | 6 ++ .../tools/vcard-qr-code/VCardGenerator.tsx | 6 ++ .../whatsapp-qr-code/WhatsAppGenerator.tsx | 6 ++ .../tools/wifi-qr-code/WiFiGenerator.tsx | 6 ++ .../youtube-qr-code/YouTubeGenerator.tsx | 6 ++ .../tools/zoom-qr-code/ZoomGenerator.tsx | 6 ++ .../marketing/PostDownloadPopup.tsx | 99 +++++++++++++++++++ 22 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 src/components/marketing/PostDownloadPopup.tsx diff --git a/src/app/(main)/(marketing)/tools/barcode-generator/BarcodeGeneratorClient.tsx b/src/app/(main)/(marketing)/tools/barcode-generator/BarcodeGeneratorClient.tsx index 49104ec..71ace98 100644 --- a/src/app/(main)/(marketing)/tools/barcode-generator/BarcodeGeneratorClient.tsx +++ b/src/app/(main)/(marketing)/tools/barcode-generator/BarcodeGeneratorClient.tsx @@ -11,6 +11,7 @@ import { showToast } from '@/components/ui/Toast'; import { cn } from '@/lib/utils'; import { toPng, toSvg, toBlob } from 'html-to-image'; import { trackEvent } from '@/components/PostHogProvider'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -54,6 +55,7 @@ export default function BarcodeGeneratorClient() { const [lineColor, setLineColor] = useState('#000000'); const [frameType, setFrameType] = useState('none'); const [error, setError] = useState(null); + const [showPopup, setShowPopup] = useState(false); const barcodeRef = useRef(null); @@ -109,6 +111,7 @@ export default function BarcodeGeneratorClient() { document.body.removeChild(link); showToast(`Barcode downloaded as ${extension.toUpperCase()}`, 'success'); + if (shouldShowDownloadPopup()) setShowPopup(true); trackEvent('barcode_downloaded', { format: format, extension: extension, @@ -118,7 +121,6 @@ export default function BarcodeGeneratorClient() { console.error('Download failed', err); showToast('Download failed', 'error'); } - }; const copyBarcode = async () => { if (!barcodeRef.current) return; @@ -160,6 +162,8 @@ export default function BarcodeGeneratorClient() { ]; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -453,5 +457,6 @@ export default function BarcodeGeneratorClient() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/call-qr-code-generator/PhoneGenerator.tsx b/src/app/(main)/(marketing)/tools/call-qr-code-generator/PhoneGenerator.tsx index a7cae48..fa786c2 100644 --- a/src/app/(main)/(marketing)/tools/call-qr-code-generator/PhoneGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/call-qr-code-generator/PhoneGenerator.tsx @@ -13,6 +13,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -45,6 +46,7 @@ export default function PhoneGenerator() { const [phone, setPhone] = useState(''); const [qrColor, setQrColor] = useState(BRAND.richBlue); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -74,6 +76,7 @@ export default function PhoneGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -82,6 +85,8 @@ export default function PhoneGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -243,5 +248,6 @@ export default function PhoneGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/crypto-qr-code/CryptoGenerator.tsx b/src/app/(main)/(marketing)/tools/crypto-qr-code/CryptoGenerator.tsx index 08ec6ff..dacb2b2 100644 --- a/src/app/(main)/(marketing)/tools/crypto-qr-code/CryptoGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/crypto-qr-code/CryptoGenerator.tsx @@ -15,6 +15,7 @@ import { Input } from '@/components/ui/Input'; import { Select } from '@/components/ui/Select'; import { cn } from '@/lib/utils'; import AdBanner from '@/components/ads/AdBanner'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -58,6 +59,7 @@ export default function CryptoGenerator() { const [qrMode, setQrMode] = useState<'universal' | 'wallet'>('universal'); const [qrColor, setQrColor] = useState('#F7931A'); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -123,6 +125,7 @@ export default function CryptoGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -131,6 +134,8 @@ export default function CryptoGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -370,5 +375,6 @@ export default function CryptoGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/email-qr-code/EmailGenerator.tsx b/src/app/(main)/(marketing)/tools/email-qr-code/EmailGenerator.tsx index c45643c..3396ec0 100644 --- a/src/app/(main)/(marketing)/tools/email-qr-code/EmailGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/email-qr-code/EmailGenerator.tsx @@ -14,6 +14,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -43,6 +44,7 @@ const FRAME_OPTIONS = [ export default function EmailGenerator() { const [formData, setFormData] = useState({ + const [showPopup, setShowPopup] = useState(false); email: '', subject: '', body: '' @@ -88,6 +90,7 @@ export default function EmailGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -100,6 +103,8 @@ export default function EmailGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -292,5 +297,6 @@ export default function EmailGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/event-qr-code/EventGenerator.tsx b/src/app/(main)/(marketing)/tools/event-qr-code/EventGenerator.tsx index ce836b9..7cf66f4 100644 --- a/src/app/(main)/(marketing)/tools/event-qr-code/EventGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/event-qr-code/EventGenerator.tsx @@ -15,6 +15,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -51,6 +52,7 @@ export default function EventGenerator() { const [qrColor, setQrColor] = useState(BRAND.primary); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -102,6 +104,7 @@ export default function EventGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -110,6 +113,8 @@ export default function EventGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -326,5 +331,6 @@ export default function EventGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/facebook-qr-code/FacebookGenerator.tsx b/src/app/(main)/(marketing)/tools/facebook-qr-code/FacebookGenerator.tsx index 2a00d7d..65c32a0 100644 --- a/src/app/(main)/(marketing)/tools/facebook-qr-code/FacebookGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/facebook-qr-code/FacebookGenerator.tsx @@ -14,6 +14,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -46,6 +47,7 @@ export default function FacebookGenerator() { const [url, setUrl] = useState(''); const [qrColor, setQrColor] = useState('#1877F2'); // Default to FB Blue const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -73,6 +75,7 @@ export default function FacebookGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -81,6 +84,8 @@ export default function FacebookGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -243,5 +248,6 @@ export default function FacebookGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/geolocation-qr-code/GeolocationGenerator.tsx b/src/app/(main)/(marketing)/tools/geolocation-qr-code/GeolocationGenerator.tsx index 84efdb3..80e8541 100644 --- a/src/app/(main)/(marketing)/tools/geolocation-qr-code/GeolocationGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/geolocation-qr-code/GeolocationGenerator.tsx @@ -14,6 +14,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -46,6 +47,7 @@ export default function GeolocationGenerator() { const [longitude, setLongitude] = useState(''); const [qrColor, setQrColor] = useState(BRAND.primary); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -76,6 +78,7 @@ export default function GeolocationGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -101,6 +104,8 @@ export default function GeolocationGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -288,5 +293,6 @@ export default function GeolocationGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/google-review-qr-code/GoogleReviewGenerator.tsx b/src/app/(main)/(marketing)/tools/google-review-qr-code/GoogleReviewGenerator.tsx index bcf4e6e..7d6c316 100644 --- a/src/app/(main)/(marketing)/tools/google-review-qr-code/GoogleReviewGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/google-review-qr-code/GoogleReviewGenerator.tsx @@ -6,6 +6,7 @@ import { toPng } from 'html-to-image'; import { Star, Download, AlertCircle } from 'lucide-react'; import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; const QR_COLORS = [ { name: 'Google Blue', value: '#1A73E8' }, @@ -41,6 +42,7 @@ export default function GoogleReviewGenerator() { const [qrColor, setQrColor] = useState('#1A73E8'); const [frameType, setFrameType] = useState('review'); const [error, setError] = useState(''); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -76,12 +78,15 @@ export default function GoogleReviewGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const frameLabel = FRAME_OPTIONS.find(f => f.id === frameType && f.id !== 'none')?.label ?? null; const isReady = reviewUrl && !error && isValidGoogleReviewLink(reviewUrl); return ( + <> + setShowPopup(false)} />
@@ -209,5 +214,6 @@ export default function GoogleReviewGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/instagram-qr-code/InstagramGenerator.tsx b/src/app/(main)/(marketing)/tools/instagram-qr-code/InstagramGenerator.tsx index 78ad0df..c8957bc 100644 --- a/src/app/(main)/(marketing)/tools/instagram-qr-code/InstagramGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/instagram-qr-code/InstagramGenerator.tsx @@ -13,6 +13,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -45,6 +46,7 @@ export default function InstagramGenerator() { const [username, setUsername] = useState(''); const [qrColor, setQrColor] = useState('#E1306C'); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -78,6 +80,7 @@ export default function InstagramGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -86,6 +89,8 @@ export default function InstagramGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -248,5 +253,6 @@ export default function InstagramGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/paypal-qr-code/PayPalGenerator.tsx b/src/app/(main)/(marketing)/tools/paypal-qr-code/PayPalGenerator.tsx index 9d62d02..b11beef 100644 --- a/src/app/(main)/(marketing)/tools/paypal-qr-code/PayPalGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/paypal-qr-code/PayPalGenerator.tsx @@ -14,6 +14,7 @@ import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { Select } from '@/components/ui/Select'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors - PayPal Blue const BRAND = { @@ -64,6 +65,7 @@ export default function PayPalGenerator() { const [currency, setCurrency] = useState('EUR'); const [qrColor, setQrColor] = useState(BRAND.primary); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -114,6 +116,7 @@ export default function PayPalGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -122,6 +125,8 @@ export default function PayPalGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -338,5 +343,6 @@ export default function PayPalGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/sms-qr-code/SMSGenerator.tsx b/src/app/(main)/(marketing)/tools/sms-qr-code/SMSGenerator.tsx index 11ef166..7bce37e 100644 --- a/src/app/(main)/(marketing)/tools/sms-qr-code/SMSGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/sms-qr-code/SMSGenerator.tsx @@ -13,6 +13,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -46,6 +47,7 @@ export default function SMSGenerator() { const [message, setMessage] = useState(''); const [qrColor, setQrColor] = useState(BRAND.primary); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -76,6 +78,7 @@ export default function SMSGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -84,6 +87,8 @@ export default function SMSGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -262,5 +267,6 @@ export default function SMSGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/teams-qr-code/TeamsGenerator.tsx b/src/app/(main)/(marketing)/tools/teams-qr-code/TeamsGenerator.tsx index 927c190..6ad7369 100644 --- a/src/app/(main)/(marketing)/tools/teams-qr-code/TeamsGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/teams-qr-code/TeamsGenerator.tsx @@ -14,6 +14,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors - Microsoft Teams Purple const BRAND = { @@ -53,6 +54,7 @@ export default function TeamsGenerator() { const [userEmail, setUserEmail] = useState(''); const [qrColor, setQrColor] = useState(BRAND.primary); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -96,6 +98,7 @@ export default function TeamsGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -104,6 +107,8 @@ export default function TeamsGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -314,5 +319,6 @@ export default function TeamsGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/text-qr-code/TextGenerator.tsx b/src/app/(main)/(marketing)/tools/text-qr-code/TextGenerator.tsx index 0af88f2..d7b63ff 100644 --- a/src/app/(main)/(marketing)/tools/text-qr-code/TextGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/text-qr-code/TextGenerator.tsx @@ -13,6 +13,7 @@ import { } from 'lucide-react'; import { Button } from '@/components/ui/Button'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -45,6 +46,7 @@ export default function TextGenerator() { const [text, setText] = useState(''); const [qrColor, setQrColor] = useState(BRAND.richBlue); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -72,6 +74,7 @@ export default function TextGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -80,6 +83,8 @@ export default function TextGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -241,5 +246,6 @@ export default function TextGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/tiktok-qr-code/TikTokGenerator.tsx b/src/app/(main)/(marketing)/tools/tiktok-qr-code/TikTokGenerator.tsx index 6bfec27..2cfe4c4 100644 --- a/src/app/(main)/(marketing)/tools/tiktok-qr-code/TikTokGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/tiktok-qr-code/TikTokGenerator.tsx @@ -14,6 +14,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -45,6 +46,7 @@ export default function TiktokGenerator() { const [username, setUsername] = useState(''); const [qrColor, setQrColor] = useState('#000000'); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -78,6 +80,7 @@ export default function TiktokGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -86,6 +89,8 @@ export default function TiktokGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -248,5 +253,6 @@ export default function TiktokGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/twitter-qr-code/TwitterGenerator.tsx b/src/app/(main)/(marketing)/tools/twitter-qr-code/TwitterGenerator.tsx index d64dc77..b7d37cb 100644 --- a/src/app/(main)/(marketing)/tools/twitter-qr-code/TwitterGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/twitter-qr-code/TwitterGenerator.tsx @@ -13,6 +13,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -45,6 +46,7 @@ export default function TwitterGenerator() { const [username, setUsername] = useState(''); const [qrColor, setQrColor] = useState('#000000'); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -78,6 +80,7 @@ export default function TwitterGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -86,6 +89,8 @@ export default function TwitterGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -248,5 +253,6 @@ export default function TwitterGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/url-qr-code/URLGenerator.tsx b/src/app/(main)/(marketing)/tools/url-qr-code/URLGenerator.tsx index f726890..af911db 100644 --- a/src/app/(main)/(marketing)/tools/url-qr-code/URLGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/url-qr-code/URLGenerator.tsx @@ -15,6 +15,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -46,6 +47,7 @@ export default function URLGenerator() { const [url, setUrl] = useState(''); const [qrColor, setQrColor] = useState(BRAND.primary); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -72,6 +74,7 @@ export default function URLGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -80,6 +83,8 @@ export default function URLGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -241,5 +246,6 @@ export default function URLGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/vcard-qr-code/VCardGenerator.tsx b/src/app/(main)/(marketing)/tools/vcard-qr-code/VCardGenerator.tsx index a772b4a..5cac1b0 100644 --- a/src/app/(main)/(marketing)/tools/vcard-qr-code/VCardGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/vcard-qr-code/VCardGenerator.tsx @@ -18,6 +18,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -63,6 +64,7 @@ export default function VCardGenerator() { const [qrColor, setQrColor] = useState(BRAND.primary); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -108,6 +110,7 @@ export default function VCardGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -116,6 +119,8 @@ export default function VCardGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -344,5 +349,6 @@ export default function VCardGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/whatsapp-qr-code/WhatsAppGenerator.tsx b/src/app/(main)/(marketing)/tools/whatsapp-qr-code/WhatsAppGenerator.tsx index 7be5967..bd0a779 100644 --- a/src/app/(main)/(marketing)/tools/whatsapp-qr-code/WhatsAppGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/whatsapp-qr-code/WhatsAppGenerator.tsx @@ -15,6 +15,7 @@ import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; import { Textarea } from '@/components/ui/Textarea'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; @@ -49,6 +50,7 @@ export default function WhatsappGenerator() { const [message, setMessage] = useState(''); const [qrColor, setQrColor] = useState('#25D366'); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -83,6 +85,7 @@ export default function WhatsappGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -91,6 +94,8 @@ export default function WhatsappGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -263,5 +268,6 @@ export default function WhatsappGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/wifi-qr-code/WiFiGenerator.tsx b/src/app/(main)/(marketing)/tools/wifi-qr-code/WiFiGenerator.tsx index 541f382..e94eea2 100644 --- a/src/app/(main)/(marketing)/tools/wifi-qr-code/WiFiGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/wifi-qr-code/WiFiGenerator.tsx @@ -17,6 +17,7 @@ import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { Select } from '@/components/ui/Select'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -55,6 +56,7 @@ export default function WiFiGenerator() { // Customization const [qrColor, setQrColor] = useState(BRAND.primary); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -84,6 +86,7 @@ export default function WiFiGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -92,6 +95,8 @@ export default function WiFiGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -303,5 +308,6 @@ export default function WiFiGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/youtube-qr-code/YouTubeGenerator.tsx b/src/app/(main)/(marketing)/tools/youtube-qr-code/YouTubeGenerator.tsx index f827a0e..958daa2 100644 --- a/src/app/(main)/(marketing)/tools/youtube-qr-code/YouTubeGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/youtube-qr-code/YouTubeGenerator.tsx @@ -13,6 +13,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors const BRAND = { @@ -44,6 +45,7 @@ export default function YoutubeGenerator() { const [url, setUrl] = useState(''); const [qrColor, setQrColor] = useState('#FF0000'); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -71,6 +73,7 @@ export default function YoutubeGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -79,6 +82,8 @@ export default function YoutubeGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -241,5 +246,6 @@ export default function YoutubeGenerator() {
+ ); } diff --git a/src/app/(main)/(marketing)/tools/zoom-qr-code/ZoomGenerator.tsx b/src/app/(main)/(marketing)/tools/zoom-qr-code/ZoomGenerator.tsx index 31bb1e9..c9e2c2c 100644 --- a/src/app/(main)/(marketing)/tools/zoom-qr-code/ZoomGenerator.tsx +++ b/src/app/(main)/(marketing)/tools/zoom-qr-code/ZoomGenerator.tsx @@ -13,6 +13,7 @@ import { import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { cn } from '@/lib/utils'; +import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup'; // Brand Colors - Zoom Blue const BRAND = { @@ -46,6 +47,7 @@ export default function ZoomGenerator() { const [useDirectLink, setUseDirectLink] = useState(false); // Default to web URL for compatibility const [qrColor, setQrColor] = useState(BRAND.primary); const [frameType, setFrameType] = useState('none'); + const [showPopup, setShowPopup] = useState(false); const qrRef = useRef(null); @@ -103,6 +105,7 @@ export default function ZoomGenerator() { } catch (err) { console.error('Download failed', err); } + if (shouldShowDownloadPopup()) setShowPopup(true); }; const getFrameLabel = () => { @@ -111,6 +114,8 @@ export default function ZoomGenerator() { }; return ( + <> + setShowPopup(false)} />
{/* Main Generator Card */} @@ -298,5 +303,6 @@ export default function ZoomGenerator() {
+ ); } diff --git a/src/components/marketing/PostDownloadPopup.tsx b/src/components/marketing/PostDownloadPopup.tsx new file mode 100644 index 0000000..f573a54 --- /dev/null +++ b/src/components/marketing/PostDownloadPopup.tsx @@ -0,0 +1,99 @@ +'use client'; + +import React, { useEffect, useRef } from 'react'; +import Link from 'next/link'; +import { X, Zap, BarChart2, RefreshCw, Palette } from 'lucide-react'; +import { Button } from '@/components/ui/Button'; + +interface PostDownloadPopupProps { + open: boolean; + onClose: () => void; +} + +const BENEFITS = [ + { icon: RefreshCw, text: 'Edit the link anytime — QR stays the same' }, + { icon: BarChart2, text: 'See who scans, when & where' }, + { icon: Palette, text: 'Custom colors, logo & frames' }, + { icon: Zap, text: 'Free plan included — upgrade anytime for more' }, +]; + +const LS_KEY = 'qrm_download_popup_seen'; + +export function shouldShowDownloadPopup(): boolean { + try { return !localStorage.getItem(LS_KEY); } catch { return false; } +} + +export function markDownloadPopupSeen(): void { + try { localStorage.setItem(LS_KEY, '1'); } catch { /* ignore */ } +} + +export default function PostDownloadPopup({ open, onClose }: PostDownloadPopupProps) { + const overlayRef = useRef(null); + + useEffect(() => { + if (!open) return; + markDownloadPopupSeen(); + const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; + document.addEventListener('keydown', onKey); + return () => document.removeEventListener('keydown', onKey); + }, [open, onClose]); + + if (!open) return null; + + return ( +
{ if (e.target === overlayRef.current) onClose(); }} + > +
+ + {/* Header */} +
+ +
+ +
+

Your QR code is downloading!

+

+ Want to make it smarter — for free? +

+
+ + {/* Benefits */} +
+ {BENEFITS.map(({ icon: Icon, text }) => ( +
+
+ +
+ {text} +
+ ))} +
+ + {/* CTAs */} +
+ + + + +
+
+
+ ); +}