Fix, complete all tool updates
This commit is contained in:
@@ -1,293 +1,293 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useRef } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import {
|
||||
MapPin,
|
||||
Download,
|
||||
Check,
|
||||
Sparkles,
|
||||
Navigation,
|
||||
Globe
|
||||
} from 'lucide-react';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
// Brand Colors
|
||||
const BRAND = {
|
||||
paleGrey: '#ECFDF5', // Emerald-50
|
||||
primary: '#10B981', // Emerald-500
|
||||
primaryDark: '#047857', // Emerald-700
|
||||
};
|
||||
|
||||
// QR Color Options
|
||||
const QR_COLORS = [
|
||||
{ name: 'Emerald', value: '#10B981' },
|
||||
{ name: 'Teal', value: '#0D9488' },
|
||||
{ name: 'Classic Black', value: '#000000' },
|
||||
{ name: 'Navy', value: '#1E3A8A' },
|
||||
{ name: 'Sky', value: '#0EA5E9' },
|
||||
{ name: 'Emerald', value: '#10B981' },
|
||||
{ name: 'Rose', value: '#F43F5E' },
|
||||
];
|
||||
|
||||
// Frame Options
|
||||
const FRAME_OPTIONS = [
|
||||
{ id: 'none', label: 'No Frame' },
|
||||
{ id: 'scanme', label: 'Scan Me' },
|
||||
{ id: 'location', label: 'Location' },
|
||||
{ id: 'map', label: 'View Map' },
|
||||
];
|
||||
|
||||
export default function GeolocationGenerator() {
|
||||
const [latitude, setLatitude] = useState('');
|
||||
const [longitude, setLongitude] = useState('');
|
||||
const [qrColor, setQrColor] = useState(BRAND.primary);
|
||||
const [frameType, setFrameType] = useState('none');
|
||||
|
||||
const qrRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Using Google Maps Universal Link for best compatibility
|
||||
const qrValue = `https://www.google.com/maps/search/?api=1&query=${latitude},${longitude}`;
|
||||
|
||||
const handleDownload = async (format: 'png' | 'svg') => {
|
||||
if (!qrRef.current) return;
|
||||
try {
|
||||
if (format === 'png') {
|
||||
const { toPng } = await import('html-to-image');
|
||||
const dataUrl = await toPng(qrRef.current, { cacheBust: true, pixelRatio: 3 });
|
||||
const link = document.createElement('a');
|
||||
link.download = `location-qr-code.png`;
|
||||
link.href = dataUrl;
|
||||
link.click();
|
||||
} else {
|
||||
const svgData = qrRef.current.querySelector('svg')?.outerHTML;
|
||||
if (svgData) {
|
||||
const blob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = `location-qr-code.svg`;
|
||||
link.click();
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Download failed', err);
|
||||
}
|
||||
};
|
||||
|
||||
const getFrameLabel = () => {
|
||||
const frame = FRAME_OPTIONS.find(f => f.id === frameType);
|
||||
return frame?.id !== 'none' ? frame?.label : null;
|
||||
};
|
||||
|
||||
const getCurrentLocation = () => {
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
setLatitude(position.coords.latitude.toFixed(6));
|
||||
setLongitude(position.coords.longitude.toFixed(6));
|
||||
},
|
||||
(error) => {
|
||||
console.error("Error getting location: ", error);
|
||||
alert("Could not access location. Please enter manually.");
|
||||
}
|
||||
);
|
||||
} else {
|
||||
alert("Geolocation is not supported by this browser.");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-5xl mx-auto px-4 md:px-6">
|
||||
|
||||
{/* Main Generator Card */}
|
||||
<div className="bg-white rounded-3xl shadow-2xl shadow-slate-900/10 overflow-hidden border border-slate-100">
|
||||
<div className="grid lg:grid-cols-2">
|
||||
|
||||
{/* LEFT: Input Section */}
|
||||
<div className="p-8 lg:p-10 space-y-8 border-r border-slate-100">
|
||||
|
||||
{/* Location Details */}
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-lg font-bold text-slate-900 flex items-center gap-2">
|
||||
<MapPin className="w-5 h-5 text-[#10B981]" />
|
||||
Coordinates
|
||||
</h2>
|
||||
<Button
|
||||
onClick={getCurrentLocation}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="text-[#047857] border-[#047857]/20 hover:bg-[#047857]/5"
|
||||
>
|
||||
<Navigation className="w-3 h-3 mr-2" />
|
||||
Get Current Location
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-2">Latitude</label>
|
||||
<Input
|
||||
placeholder="40.712776"
|
||||
value={latitude}
|
||||
onChange={(e) => setLatitude(e.target.value)}
|
||||
className="h-12 text-base rounded-xl border-slate-200 focus:border-[#10B981] focus:ring-[#10B981]"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-2">Longitude</label>
|
||||
<Input
|
||||
placeholder="-74.005974"
|
||||
value={longitude}
|
||||
onChange={(e) => setLongitude(e.target.value)}
|
||||
className="h-12 text-base rounded-xl border-slate-200 focus:border-[#10B981] focus:ring-[#10B981]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs text-slate-500">
|
||||
Tip: You can copy-paste coordinates directly from Google Maps.
|
||||
(Right-click a location on standard Maps, then click the coordinates to copy).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-slate-100"></div>
|
||||
|
||||
{/* Design Options */}
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-lg font-bold text-slate-900 flex items-center gap-2">
|
||||
<Sparkles className="w-5 h-5 text-[#10B981]" />
|
||||
Design Options
|
||||
</h2>
|
||||
|
||||
{/* Color Picker */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-3">QR Code Color</label>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{QR_COLORS.map((c) => (
|
||||
<button
|
||||
key={c.name}
|
||||
onClick={() => setQrColor(c.value)}
|
||||
className={cn(
|
||||
"w-9 h-9 rounded-full border-2 flex items-center justify-center transition-all hover:scale-110",
|
||||
qrColor === c.value ? "border-slate-900 ring-2 ring-offset-2 ring-slate-200" : "border-white shadow-md"
|
||||
)}
|
||||
style={{ backgroundColor: c.value }}
|
||||
aria-label={`Select ${c.name}`}
|
||||
title={c.name}
|
||||
>
|
||||
{qrColor === c.value && <Check className="w-4 h-4 text-white" strokeWidth={3} />}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Frame Selector */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-3">Frame Label</label>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{FRAME_OPTIONS.map((frame) => (
|
||||
<button
|
||||
key={frame.id}
|
||||
onClick={() => setFrameType(frame.id)}
|
||||
className={cn(
|
||||
"py-2.5 px-3 rounded-lg text-sm font-medium transition-all border",
|
||||
frameType === frame.id
|
||||
? "bg-[#10B981] text-white border-[#10B981]"
|
||||
: "bg-slate-50 text-slate-600 border-slate-200 hover:border-slate-300"
|
||||
)}
|
||||
>
|
||||
{frame.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT: Preview Section */}
|
||||
<div className="p-8 lg:p-10 flex flex-col items-center justify-center" style={{ backgroundColor: BRAND.paleGrey }}>
|
||||
|
||||
{/* QR Card with Frame */}
|
||||
<div
|
||||
ref={qrRef}
|
||||
className="bg-white rounded-3xl shadow-xl p-8 flex flex-col items-center"
|
||||
style={{ minWidth: '320px' }}
|
||||
>
|
||||
{/* Frame Label */}
|
||||
{getFrameLabel() && (
|
||||
<div
|
||||
className="mb-5 px-8 py-2.5 rounded-full text-white font-bold text-sm tracking-widest uppercase shadow-md"
|
||||
style={{ backgroundColor: qrColor }}
|
||||
>
|
||||
{getFrameLabel()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* QR Code */}
|
||||
<div className="bg-white">
|
||||
<QRCodeSVG
|
||||
value={(latitude && longitude) ? qrValue : "https://maps.google.com"}
|
||||
size={240}
|
||||
level="M"
|
||||
includeMargin={false}
|
||||
fgColor={qrColor}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Info Preview */}
|
||||
<div className="mt-6 text-center max-w-[260px]">
|
||||
<h3 className="font-bold text-slate-900 text-lg flex items-center justify-center gap-2 truncate">
|
||||
<MapPin className="w-4 h-4 text-[#10B981] shrink-0" />
|
||||
<span className="truncate">{latitude || 'Lat'}, {longitude || 'Long'}</span>
|
||||
</h3>
|
||||
<div className="text-xs text-slate-500 mt-1">Google Maps Location</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Download Buttons */}
|
||||
<div className="flex items-center gap-3 mt-8">
|
||||
<Button
|
||||
onClick={() => handleDownload('png')}
|
||||
className="bg-[#10B981] hover:bg-[#047857] text-white shadow-lg"
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
Download PNG
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => handleDownload('svg')}
|
||||
variant="outline"
|
||||
className="border-slate-300 hover:bg-white"
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
SVG
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-slate-500 mt-4 text-center">
|
||||
Scanning opens the location directly in Google Maps.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Upsell Banner */}
|
||||
<div className="mt-8 bg-gradient-to-r from-[#10B981] to-[#047857] rounded-2xl p-6 flex flex-col sm:flex-row items-center justify-between gap-4">
|
||||
<div className="text-white text-center sm:text-left">
|
||||
<h3 className="font-bold text-lg">Need a Business Map?</h3>
|
||||
<p className="text-white/80 text-sm mt-1">
|
||||
Create a Dynamic QR Code for your business location. If you move, just update the location without reprinting.
|
||||
</p>
|
||||
</div>
|
||||
<Link href="/signup">
|
||||
<Button className="bg-white text-[#047857] hover:bg-slate-100 shrink-0 shadow-lg">
|
||||
Get Dynamic Maps
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
'use client';
|
||||
|
||||
import React, { useState, useRef } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import {
|
||||
MapPin,
|
||||
Download,
|
||||
Check,
|
||||
Sparkles,
|
||||
Navigation,
|
||||
Globe
|
||||
} from 'lucide-react';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
// Brand Colors
|
||||
const BRAND = {
|
||||
paleGrey: '#ECFDF5', // Emerald-50
|
||||
primary: '#10B981', // Emerald-500
|
||||
primaryDark: '#047857', // Emerald-700
|
||||
};
|
||||
|
||||
// QR Color Options
|
||||
const QR_COLORS = [
|
||||
{ name: 'Emerald', value: '#10B981' },
|
||||
{ name: 'Teal', value: '#0D9488' },
|
||||
{ name: 'Classic Black', value: '#000000' },
|
||||
{ name: 'Navy', value: '#1E3A8A' },
|
||||
{ name: 'Sky', value: '#0EA5E9' },
|
||||
{ name: 'Emerald', value: '#10B981' },
|
||||
{ name: 'Rose', value: '#F43F5E' },
|
||||
];
|
||||
|
||||
// Frame Options
|
||||
const FRAME_OPTIONS = [
|
||||
{ id: 'none', label: 'No Frame' },
|
||||
{ id: 'scanme', label: 'Scan Me' },
|
||||
{ id: 'location', label: 'Location' },
|
||||
{ id: 'map', label: 'View Map' },
|
||||
];
|
||||
|
||||
export default function GeolocationGenerator() {
|
||||
const [latitude, setLatitude] = useState('');
|
||||
const [longitude, setLongitude] = useState('');
|
||||
const [qrColor, setQrColor] = useState(BRAND.primary);
|
||||
const [frameType, setFrameType] = useState('none');
|
||||
|
||||
const qrRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Using Google Maps Universal Link for best compatibility
|
||||
const qrValue = `https://www.google.com/maps/search/?api=1&query=${latitude},${longitude}`;
|
||||
|
||||
const handleDownload = async (format: 'png' | 'svg') => {
|
||||
if (!qrRef.current) return;
|
||||
try {
|
||||
if (format === 'png') {
|
||||
const { toPng } = await import('html-to-image');
|
||||
const dataUrl = await toPng(qrRef.current, { cacheBust: true, pixelRatio: 3 });
|
||||
const link = document.createElement('a');
|
||||
link.download = `location-qr-code.png`;
|
||||
link.href = dataUrl;
|
||||
link.click();
|
||||
} else {
|
||||
const svgData = qrRef.current.querySelector('svg')?.outerHTML;
|
||||
if (svgData) {
|
||||
const blob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = `location-qr-code.svg`;
|
||||
link.click();
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Download failed', err);
|
||||
}
|
||||
};
|
||||
|
||||
const getFrameLabel = () => {
|
||||
const frame = FRAME_OPTIONS.find(f => f.id === frameType);
|
||||
return frame?.id !== 'none' ? frame?.label : null;
|
||||
};
|
||||
|
||||
const getCurrentLocation = () => {
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
setLatitude(position.coords.latitude.toFixed(6));
|
||||
setLongitude(position.coords.longitude.toFixed(6));
|
||||
},
|
||||
(error) => {
|
||||
console.error("Error getting location: ", error);
|
||||
alert("Could not access location. Please enter manually.");
|
||||
}
|
||||
);
|
||||
} else {
|
||||
alert("Geolocation is not supported by this browser.");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full max-w-5xl mx-auto px-4 md:px-6">
|
||||
|
||||
{/* Main Generator Card */}
|
||||
<div className="bg-white rounded-3xl shadow-2xl shadow-slate-900/10 overflow-hidden border border-slate-100">
|
||||
<div className="grid lg:grid-cols-2">
|
||||
|
||||
{/* LEFT: Input Section */}
|
||||
<div className="p-8 lg:p-10 space-y-8 border-r border-slate-100">
|
||||
|
||||
{/* Location Details */}
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-lg font-bold text-slate-900 flex items-center gap-2">
|
||||
<MapPin className="w-5 h-5 text-[#10B981]" />
|
||||
Coordinates
|
||||
</h2>
|
||||
<Button
|
||||
onClick={getCurrentLocation}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="text-[#047857] border-[#047857]/20 hover:bg-[#047857]/5"
|
||||
>
|
||||
<Navigation className="w-3 h-3 mr-2" />
|
||||
Get Current Location
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-2">Latitude</label>
|
||||
<Input
|
||||
placeholder="40.712776"
|
||||
value={latitude}
|
||||
onChange={(e) => setLatitude(e.target.value)}
|
||||
className="h-12 text-base rounded-xl border-slate-200 focus:border-[#10B981] focus:ring-[#10B981]"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-2">Longitude</label>
|
||||
<Input
|
||||
placeholder="-74.005974"
|
||||
value={longitude}
|
||||
onChange={(e) => setLongitude(e.target.value)}
|
||||
className="h-12 text-base rounded-xl border-slate-200 focus:border-[#10B981] focus:ring-[#10B981]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs text-slate-500">
|
||||
Tip: You can copy-paste coordinates directly from Google Maps.
|
||||
(Right-click a location on standard Maps, then click the coordinates to copy).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-slate-100"></div>
|
||||
|
||||
{/* Design Options */}
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-lg font-bold text-slate-900 flex items-center gap-2">
|
||||
<Sparkles className="w-5 h-5 text-[#10B981]" />
|
||||
Design Options
|
||||
</h2>
|
||||
|
||||
{/* Color Picker */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-3">QR Code Color</label>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{QR_COLORS.map((c) => (
|
||||
<button
|
||||
key={c.name}
|
||||
onClick={() => setQrColor(c.value)}
|
||||
className={cn(
|
||||
"w-9 h-9 rounded-full border-2 flex items-center justify-center transition-all hover:scale-110",
|
||||
qrColor === c.value ? "border-slate-900 ring-2 ring-offset-2 ring-slate-200" : "border-white shadow-md"
|
||||
)}
|
||||
style={{ backgroundColor: c.value }}
|
||||
aria-label={`Select ${c.name}`}
|
||||
title={c.name}
|
||||
>
|
||||
{qrColor === c.value && <Check className="w-4 h-4 text-white" strokeWidth={3} />}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Frame Selector */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-3">Frame Label</label>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{FRAME_OPTIONS.map((frame) => (
|
||||
<button
|
||||
key={frame.id}
|
||||
onClick={() => setFrameType(frame.id)}
|
||||
className={cn(
|
||||
"py-2.5 px-3 rounded-lg text-sm font-medium transition-all border",
|
||||
frameType === frame.id
|
||||
? "bg-[#10B981] text-white border-[#10B981]"
|
||||
: "bg-slate-50 text-slate-600 border-slate-200 hover:border-slate-300"
|
||||
)}
|
||||
>
|
||||
{frame.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT: Preview Section */}
|
||||
<div className="p-8 lg:p-10 flex flex-col items-center justify-center" style={{ backgroundColor: BRAND.paleGrey }}>
|
||||
|
||||
{/* QR Card with Frame */}
|
||||
<div
|
||||
ref={qrRef}
|
||||
className="bg-white rounded-3xl shadow-xl p-8 flex flex-col items-center"
|
||||
style={{ minWidth: '320px' }}
|
||||
>
|
||||
{/* Frame Label */}
|
||||
{getFrameLabel() && (
|
||||
<div
|
||||
className="mb-5 px-8 py-2.5 rounded-full text-white font-bold text-sm tracking-widest uppercase shadow-md"
|
||||
style={{ backgroundColor: qrColor }}
|
||||
>
|
||||
{getFrameLabel()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* QR Code */}
|
||||
<div className="bg-white">
|
||||
<QRCodeSVG
|
||||
value={(latitude && longitude) ? qrValue : "https://maps.google.com"}
|
||||
size={240}
|
||||
level="M"
|
||||
includeMargin={false}
|
||||
fgColor={qrColor}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Info Preview */}
|
||||
<div className="mt-6 text-center max-w-[260px]">
|
||||
<h3 className="font-bold text-slate-900 text-lg flex items-center justify-center gap-2 truncate">
|
||||
<MapPin className="w-4 h-4 text-[#10B981] shrink-0" />
|
||||
<span className="truncate">{latitude || 'Lat'}, {longitude || 'Long'}</span>
|
||||
</h3>
|
||||
<div className="text-xs text-slate-500 mt-1">Google Maps Location</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Download Buttons */}
|
||||
<div className="flex items-center gap-3 mt-8">
|
||||
<Button
|
||||
onClick={() => handleDownload('png')}
|
||||
className="bg-[#10B981] hover:bg-[#047857] text-white shadow-lg"
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
Download PNG
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => handleDownload('svg')}
|
||||
variant="outline"
|
||||
className="border-slate-300 hover:bg-white"
|
||||
>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
SVG
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-slate-500 mt-4 text-center">
|
||||
Scanning opens the location directly in Google Maps.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Upsell Banner */}
|
||||
<div className="mt-8 bg-gradient-to-r from-[#10B981] to-[#047857] rounded-2xl p-6 flex flex-col sm:flex-row items-center justify-between gap-4">
|
||||
<div className="text-white text-center sm:text-left">
|
||||
<h3 className="font-bold text-lg">Need a Business Map?</h3>
|
||||
<p className="text-white/80 text-sm mt-1">
|
||||
Create a Dynamic QR Code for your business location. If you move, just update the location without reprinting.
|
||||
</p>
|
||||
</div>
|
||||
<Link href="/signup">
|
||||
<Button className="bg-white text-[#047857] hover:bg-slate-100 shrink-0 shadow-lg">
|
||||
Get Dynamic Maps
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,360 +1,360 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import GeolocationGenerator from './GeolocationGenerator';
|
||||
import { MapPin, Shield, Zap, Smartphone, Navigation, Map, Download, Share2 } from 'lucide-react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { ToolBreadcrumb } from '@/components/seo/BreadcrumbSchema';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: 'Free Geolocation QR Code Generator | Maps & Directions | QR Master',
|
||||
description: 'Create a QR code for a specific location using Latitude and Longitude. Scanners will open Google Maps directly to your pin. Free & Precise.',
|
||||
keywords: ['location qr code', 'maps qr code', 'google maps qr generator', 'geolocation qr', 'coordinates qr code'],
|
||||
alternates: {
|
||||
canonical: 'https://qrmaster.io/tools/geolocation-qr-code',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free Geolocation QR Code Generator | QR Master',
|
||||
description: 'Navigate users to any location with a QR code. Opens directly in Google Maps.',
|
||||
type: 'website',
|
||||
url: 'https://qrmaster.io/tools/geolocation-qr-code',
|
||||
images: [{ url: '/og-geolocation-generator.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free Geolocation QR Code Generator',
|
||||
description: 'Create QR codes for maps and locations. Instant and free.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
// JSON-LD Structured Data
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
{
|
||||
'@type': 'SoftwareApplication',
|
||||
name: 'Geolocation QR Code Generator',
|
||||
applicationCategory: 'UtilitiesApplication',
|
||||
operatingSystem: 'Web Browser',
|
||||
offers: {
|
||||
'@type': 'Offer',
|
||||
price: '0',
|
||||
priceCurrency: 'USD',
|
||||
},
|
||||
aggregateRating: {
|
||||
'@type': 'AggregateRating',
|
||||
ratingValue: '4.7',
|
||||
ratingCount: '890',
|
||||
},
|
||||
description: 'Generate QR codes that open specific geographic coordinates in map applications.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create a Location QR Code',
|
||||
description: 'Create a QR code that points to a specific map location.',
|
||||
step: [
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 1,
|
||||
name: 'Get Coordinates',
|
||||
text: 'Find the Latitude and Longitude of your location (e.g., from Google Maps).',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 2,
|
||||
name: 'Enter Data',
|
||||
text: 'Paste the coordinates into the generator.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 3,
|
||||
name: 'Customize',
|
||||
text: 'Choose a color and style for your map QR code.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 4,
|
||||
name: 'Download',
|
||||
text: 'Save your QR code as a high-quality image.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 5,
|
||||
name: 'Share',
|
||||
text: 'Place it on invitations, signs, or your website.',
|
||||
},
|
||||
],
|
||||
totalTime: 'PT45S',
|
||||
},
|
||||
{
|
||||
'@type': 'FAQPage',
|
||||
mainEntity: [
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Which map app does it open?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'Our generator creates a universal Google Maps link. On most devices, this will open the Google Maps app if installed, or the browser version if not. It is the most compatible method.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'How do I find my Latitude and Longitude?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'On Google Maps desktop: Right-click any spot on the map. The first item in the menu is the coordinates. Click to copy them.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Does it work offline?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'The QR code itself can be scanned offline, but the user will likely need an internet connection to load the map and get directions.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Can I use an address instead?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'For precise results, we use coordinates. However, you can use our URL Generator and paste a link to your Google Maps address search result if you prefer.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Is it free?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'Yes, generating this location QR code is completely free and requires no signup.',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default function GeolocationQRCodePage() {
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ToolBreadcrumb toolName="Location QR Code Generator" toolSlug="geolocation-qr-code" />
|
||||
|
||||
<div className="min-h-screen" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative pt-20 pb-20 lg:pt-32 lg:pb-32 px-4 sm:px-6 lg:px-8 overflow-hidden" style={{ backgroundColor: '#047857' }}>
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||
<path d="M0 100 C 20 0 50 0 100 100 Z" fill="url(#grad1)" />
|
||||
<defs>
|
||||
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style={{ stopColor: 'white', stopOpacity: 1 }} />
|
||||
<stop offset="100%" style={{ stopColor: 'white', stopOpacity: 0 }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto grid lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
<div className="text-center lg:text-left">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10 hover:bg-white/20 transition-colors cursor-default">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-emerald-400"></span>
|
||||
</span>
|
||||
Free Tool — No Signup Required
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
Share Perfect Locations with <br className="hidden lg:block" />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-emerald-300 to-teal-300">Map QR Codes</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-indigo-100 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
Provide exact directions to your event, store, or secret spot.
|
||||
<strong className="text-white block sm:inline mt-2 sm:mt-0"> Opens directly in Google Maps.</strong>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Navigation className="w-4 h-4 text-emerald-400" />
|
||||
Exact Directions
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Zap className="w-4 h-4 text-amber-400" />
|
||||
Instant Load
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Shield className="w-4 h-4 text-purple-400" />
|
||||
No Data Saved
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Visual Abstract */}
|
||||
<div className="hidden lg:flex relative items-center justify-center min-h-[400px]">
|
||||
<div className="absolute w-[500px] h-[500px] bg-indigo-500/30 rounded-full blur-[100px] -top-20 -right-20 animate-pulse" />
|
||||
|
||||
<div className="relative w-80 h-96 bg-white/5 backdrop-blur-xl border border-white/20 rounded-3xl shadow-2xl flex flex-col items-center justify-center p-8 transform rotate-3 hover:rotate-0 transition-all duration-700 group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/10 to-transparent rounded-3xl" />
|
||||
|
||||
<div className="w-full bg-white rounded-xl shadow-lg h-32 mb-6 relative overflow-hidden grayscale group-hover:grayscale-0 transition-all duration-500">
|
||||
<div className="absolute inset-0 opacity-20 bg-[radial-gradient(#e5e7eb_1px,transparent_1px)] [background-size:16px_16px]"></div>
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
||||
<MapPin className="w-8 h-8 text-red-500 drop-shadow-lg animate-bounce" />
|
||||
</div>
|
||||
<div className="absolute bottom-2 left-2 right-2 bg-white/90 p-2 rounded text-[10px] text-slate-500 font-mono text-center">
|
||||
40.7128° N, 74.0060° W
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-44 h-44 bg-white rounded-xl p-2 shadow-inner relative overflow-hidden flex items-center justify-center">
|
||||
<QRCodeSVG value="https://www.qrmaster.net" size={160} fgColor="#0f172a" level="Q" />
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute -bottom-6 -right-6 bg-white py-3 px-5 rounded-xl shadow-xl flex items-center gap-3 transform transition-transform hover:scale-105 duration-300">
|
||||
<div className="bg-emerald-100 p-2 rounded-full">
|
||||
<Map className="w-5 h-5 text-emerald-600" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="text-[10px] text-slate-400 font-bold uppercase tracking-wider">Map</div>
|
||||
<div className="text-sm font-bold text-slate-900">Open</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GENERATOR SECTION */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 -mt-8">
|
||||
<GeolocationGenerator />
|
||||
</section>
|
||||
|
||||
{/* HOW IT WORKS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-12">
|
||||
How Geolocation QR Codes Work
|
||||
</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<MapPin className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">1. Pinpoint</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Enter exact GPS coordinates. This ensures users go to the precise spot (e.g., a specific building entrance).
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">2. Scan</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Users scan the code. It is encoded with a universal map link.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Download className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">3. Download</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Save your high-quality QR image.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">4. Scan</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Users scan the code to load coordinates.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Share2 className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">5. Go</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
They get instant directions to your spot.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FAQ SECTION */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-4">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="text-slate-600 text-center mb-10">
|
||||
Common questions about Map QR codes.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<FaqItem
|
||||
question="Why not just use an address?"
|
||||
answer="Addresses can be ambiguous or cover large areas (like a park or stadium). Coordinates point to an exact geographic spot, ensuring visitors find the specific meeting point or parking entrance."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Does it work on Apple Maps?"
|
||||
answer="Yes. While the underlying link is a Google Maps link, iOS devices usually handle these gracefully, either opening them in the Google Maps app (if installed) or the browser, where Apple Maps can often intercept directions."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Is it free?"
|
||||
answer="Yes, generating this location QR code is completely free and requires no signup."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I track who scanned it?"
|
||||
answer="Not with this static tool. If you need scan analytics (e.g., how many people scanned your storefront QR), you should use our Dynamic QR Code service."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Is it free?"
|
||||
answer="Yes, generating this location QR code is completely free and requires no signup."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
return (
|
||||
<details className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{answer}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import GeolocationGenerator from './GeolocationGenerator';
|
||||
import { MapPin, Shield, Zap, Smartphone, Navigation, Map, Download, Share2 } from 'lucide-react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { ToolBreadcrumb } from '@/components/seo/BreadcrumbSchema';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: 'Free Geolocation QR Code Generator | Maps & Directions | QR Master',
|
||||
description: 'Create a QR code for a specific location using Latitude and Longitude. Scanners will open Google Maps directly to your pin. Free & Precise.',
|
||||
keywords: ['location qr code', 'maps qr code', 'google maps qr generator', 'geolocation qr', 'coordinates qr code'],
|
||||
alternates: {
|
||||
canonical: 'https://qrmaster.io/tools/geolocation-qr-code',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free Geolocation QR Code Generator | QR Master',
|
||||
description: 'Navigate users to any location with a QR code. Opens directly in Google Maps.',
|
||||
type: 'website',
|
||||
url: 'https://qrmaster.io/tools/geolocation-qr-code',
|
||||
images: [{ url: '/og-geolocation-generator.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free Geolocation QR Code Generator',
|
||||
description: 'Create QR codes for maps and locations. Instant and free.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
// JSON-LD Structured Data
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
{
|
||||
'@type': 'SoftwareApplication',
|
||||
name: 'Geolocation QR Code Generator',
|
||||
applicationCategory: 'UtilitiesApplication',
|
||||
operatingSystem: 'Web Browser',
|
||||
offers: {
|
||||
'@type': 'Offer',
|
||||
price: '0',
|
||||
priceCurrency: 'USD',
|
||||
},
|
||||
aggregateRating: {
|
||||
'@type': 'AggregateRating',
|
||||
ratingValue: '4.7',
|
||||
ratingCount: '890',
|
||||
},
|
||||
description: 'Generate QR codes that open specific geographic coordinates in map applications.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create a Location QR Code',
|
||||
description: 'Create a QR code that points to a specific map location.',
|
||||
step: [
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 1,
|
||||
name: 'Get Coordinates',
|
||||
text: 'Find the Latitude and Longitude of your location (e.g., from Google Maps).',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 2,
|
||||
name: 'Enter Data',
|
||||
text: 'Paste the coordinates into the generator.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 3,
|
||||
name: 'Customize',
|
||||
text: 'Choose a color and style for your map QR code.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 4,
|
||||
name: 'Download',
|
||||
text: 'Save your QR code as a high-quality image.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 5,
|
||||
name: 'Share',
|
||||
text: 'Place it on invitations, signs, or your website.',
|
||||
},
|
||||
],
|
||||
totalTime: 'PT45S',
|
||||
},
|
||||
{
|
||||
'@type': 'FAQPage',
|
||||
mainEntity: [
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Which map app does it open?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'Our generator creates a universal Google Maps link. On most devices, this will open the Google Maps app if installed, or the browser version if not. It is the most compatible method.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'How do I find my Latitude and Longitude?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'On Google Maps desktop: Right-click any spot on the map. The first item in the menu is the coordinates. Click to copy them.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Does it work offline?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'The QR code itself can be scanned offline, but the user will likely need an internet connection to load the map and get directions.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Can I use an address instead?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'For precise results, we use coordinates. However, you can use our URL Generator and paste a link to your Google Maps address search result if you prefer.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Is it free?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'Yes, generating this location QR code is completely free and requires no signup.',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default function GeolocationQRCodePage() {
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ToolBreadcrumb toolName="Location QR Code Generator" toolSlug="geolocation-qr-code" />
|
||||
|
||||
<div className="min-h-screen" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative pt-20 pb-20 lg:pt-32 lg:pb-32 px-4 sm:px-6 lg:px-8 overflow-hidden" style={{ backgroundColor: '#047857' }}>
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||
<path d="M0 100 C 20 0 50 0 100 100 Z" fill="url(#grad1)" />
|
||||
<defs>
|
||||
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style={{ stopColor: 'white', stopOpacity: 1 }} />
|
||||
<stop offset="100%" style={{ stopColor: 'white', stopOpacity: 0 }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto grid lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
<div className="text-center lg:text-left">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10 hover:bg-white/20 transition-colors cursor-default">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-emerald-400"></span>
|
||||
</span>
|
||||
Free Tool — No Signup Required
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
Share Perfect Locations with <br className="hidden lg:block" />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-emerald-300 to-teal-300">Map QR Codes</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-indigo-100 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
Provide exact directions to your event, store, or secret spot.
|
||||
<strong className="text-white block sm:inline mt-2 sm:mt-0"> Opens directly in Google Maps.</strong>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Navigation className="w-4 h-4 text-emerald-400" />
|
||||
Exact Directions
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Zap className="w-4 h-4 text-amber-400" />
|
||||
Instant Load
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Shield className="w-4 h-4 text-purple-400" />
|
||||
No Data Saved
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Visual Abstract */}
|
||||
<div className="hidden lg:flex relative items-center justify-center min-h-[400px]">
|
||||
<div className="absolute w-[500px] h-[500px] bg-indigo-500/30 rounded-full blur-[100px] -top-20 -right-20 animate-pulse" />
|
||||
|
||||
<div className="relative w-80 h-96 bg-white/5 backdrop-blur-xl border border-white/20 rounded-3xl shadow-2xl flex flex-col items-center justify-center p-8 transform rotate-3 hover:rotate-0 transition-all duration-700 group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/10 to-transparent rounded-3xl" />
|
||||
|
||||
<div className="w-full bg-white rounded-xl shadow-lg h-32 mb-6 relative overflow-hidden grayscale group-hover:grayscale-0 transition-all duration-500">
|
||||
<div className="absolute inset-0 opacity-20 bg-[radial-gradient(#e5e7eb_1px,transparent_1px)] [background-size:16px_16px]"></div>
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
||||
<MapPin className="w-8 h-8 text-red-500 drop-shadow-lg animate-bounce" />
|
||||
</div>
|
||||
<div className="absolute bottom-2 left-2 right-2 bg-white/90 p-2 rounded text-[10px] text-slate-500 font-mono text-center">
|
||||
40.7128° N, 74.0060° W
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-44 h-44 bg-white rounded-xl p-2 shadow-inner relative overflow-hidden flex items-center justify-center">
|
||||
<QRCodeSVG value="https://www.qrmaster.net" size={160} fgColor="#0f172a" level="Q" />
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute -bottom-6 -right-6 bg-white py-3 px-5 rounded-xl shadow-xl flex items-center gap-3 transform transition-transform hover:scale-105 duration-300">
|
||||
<div className="bg-emerald-100 p-2 rounded-full">
|
||||
<Map className="w-5 h-5 text-emerald-600" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="text-[10px] text-slate-400 font-bold uppercase tracking-wider">Map</div>
|
||||
<div className="text-sm font-bold text-slate-900">Open</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GENERATOR SECTION */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 -mt-8">
|
||||
<GeolocationGenerator />
|
||||
</section>
|
||||
|
||||
{/* HOW IT WORKS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-12">
|
||||
How Geolocation QR Codes Work
|
||||
</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<MapPin className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">1. Pinpoint</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Enter exact GPS coordinates. This ensures users go to the precise spot (e.g., a specific building entrance).
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">2. Scan</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Users scan the code. It is encoded with a universal map link.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Download className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">3. Download</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Save your high-quality QR image.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">4. Scan</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Users scan the code to load coordinates.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Share2 className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">5. Go</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
They get instant directions to your spot.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FAQ SECTION */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-4">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="text-slate-600 text-center mb-10">
|
||||
Common questions about Map QR codes.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<FaqItem
|
||||
question="Why not just use an address?"
|
||||
answer="Addresses can be ambiguous or cover large areas (like a park or stadium). Coordinates point to an exact geographic spot, ensuring visitors find the specific meeting point or parking entrance."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Does it work on Apple Maps?"
|
||||
answer="Yes. While the underlying link is a Google Maps link, iOS devices usually handle these gracefully, either opening them in the Google Maps app (if installed) or the browser, where Apple Maps can often intercept directions."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Is it free?"
|
||||
answer="Yes, generating this location QR code is completely free and requires no signup."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I track who scanned it?"
|
||||
answer="Not with this static tool. If you need scan analytics (e.g., how many people scanned your storefront QR), you should use our Dynamic QR Code service."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Is it free?"
|
||||
answer="Yes, generating this location QR code is completely free and requires no signup."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
return (
|
||||
<details className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{answer}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user