Add ticket system with QR scanner and PDF generation
- Add ticket validation and check-in API endpoints - Add PDF ticket generation with QR codes (pdfkit) - Add admin QR scanner page with camera support - Add admin site settings page - Update email templates with PDF ticket download link - Add checked_in_by_admin_id field for audit tracking - Update booking success page with ticket download - Various UI improvements to events and booking pages
This commit is contained in:
@@ -31,13 +31,9 @@ export default function Footer() {
|
||||
className="h-10 w-auto"
|
||||
/>
|
||||
</Link>
|
||||
<p className="mt-3 text-gray-600 max-w-md">
|
||||
<p className="mt-3 max-w-md" style={{ color: '#002F44' }}>
|
||||
{t('footer.tagline')}
|
||||
</p>
|
||||
{/* Local SEO text */}
|
||||
<p className="mt-2 text-sm text-gray-500">
|
||||
Language Exchange Events in Asunción, Paraguay
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Quick Links */}
|
||||
@@ -84,7 +80,7 @@ export default function Footer() {
|
||||
{/* Social */}
|
||||
{socialLinks.length > 0 && (
|
||||
<div>
|
||||
<h3 className="font-semibold text-primary-dark mb-4">
|
||||
<h3 className="font-semibold mb-4" style={{ color: '#002F44' }}>
|
||||
{t('footer.social')}
|
||||
</h3>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
@@ -112,13 +108,14 @@ export default function Footer() {
|
||||
<Link
|
||||
key={link.slug}
|
||||
href={`/legal/${link.slug}`}
|
||||
className="text-gray-500 hover:text-primary-dark transition-colors text-sm"
|
||||
className="hover:opacity-70 transition-colors text-sm"
|
||||
style={{ color: '#002F44' }}
|
||||
>
|
||||
{locale === 'es' ? link.es : link.en}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
<div className="text-center text-gray-500 text-sm">
|
||||
<div className="text-center text-sm" style={{ color: '#002F44' }}>
|
||||
{t('footer.copyright', { year: currentYear })}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { useState } from 'react';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useLanguage } from '@/context/LanguageContext';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
import LanguageToggle from '@/components/LanguageToggle';
|
||||
@@ -10,6 +11,37 @@ import Button from '@/components/ui/Button';
|
||||
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline';
|
||||
import clsx from 'clsx';
|
||||
|
||||
function NavLink({ href, children }: { href: string; children: React.ReactNode }) {
|
||||
const pathname = usePathname();
|
||||
const isActive = pathname === href || (href !== '/' && pathname.startsWith(href));
|
||||
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className="font-medium transition-colors"
|
||||
style={{ color: isActive ? '#FBB82B' : '#002F44' }}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
function MobileNavLink({ href, children, onClick }: { href: string; children: React.ReactNode; onClick: () => void }) {
|
||||
const pathname = usePathname();
|
||||
const isActive = pathname === href || (href !== '/' && pathname.startsWith(href));
|
||||
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className="px-4 py-2 hover:bg-gray-50 rounded-lg font-medium"
|
||||
style={{ color: isActive ? '#FBB82B' : '#002F44' }}
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Header() {
|
||||
const { t } = useLanguage();
|
||||
const { user, isAdmin, logout } = useAuth();
|
||||
@@ -41,13 +73,9 @@ export default function Header() {
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:flex items-center gap-6">
|
||||
{navLinks.map((link) => (
|
||||
<Link
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className="text-gray-700 hover:text-primary-dark font-medium transition-colors"
|
||||
>
|
||||
<NavLink key={link.href} href={link.href}>
|
||||
{link.label}
|
||||
</Link>
|
||||
</NavLink>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -115,14 +143,13 @@ export default function Header() {
|
||||
>
|
||||
<div className="flex flex-col gap-2 pt-4">
|
||||
{navLinks.map((link) => (
|
||||
<Link
|
||||
<MobileNavLink
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className="px-4 py-2 text-gray-700 hover:bg-gray-50 rounded-lg font-medium"
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
>
|
||||
{link.label}
|
||||
</Link>
|
||||
</MobileNavLink>
|
||||
))}
|
||||
|
||||
<div className="border-t border-gray-100 mt-2 pt-4 px-4">
|
||||
|
||||
Reference in New Issue
Block a user