- Add a unified Schedule section across all four tour categories: - Local: choose a fixed session (date+time) or flexible/by-appointment - National/International: required departure + optional return trip dates - Destruction: existing competition window, now with end>=start validation - Reuse start-date/end-date tags for every category (parser already supported them) - Fix datetime handling: dedicated toDateInput/inputToSecs helpers so date and datetime-local inputs round-trip correctly (previous mix of toLocalInput + type="date" was inconsistent) - Consistent, logical mandatory-field validation with clear required markers - Redesign the header into an immersive, category-tinted, grunge-striped banner and rebuild the category selector as elegant glowing cards - New calendar utilities (.ics + Google Calendar) and AddToCalendar component - TourDetailPage is now fully category-aware (badge, guide label, duration, SEO title) with a Schedule card + Add to Calendar for attendees - TourCard shows the schedule for all categories (time for local sessions) - Update NIP.md to document start-date/end-date across categories Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
import { CalendarPlus, Download, CalendarClock } from 'lucide-react';
|
|
import { Button } from '@/components/ui/button';
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuTrigger,
|
|
} from '@/components/ui/dropdown-menu';
|
|
import {
|
|
downloadICS,
|
|
googleCalendarUrl,
|
|
type CalendarEventInput,
|
|
} from '@/lib/calendar';
|
|
import { cn } from '@/lib/utils';
|
|
|
|
interface AddToCalendarProps {
|
|
event: CalendarEventInput;
|
|
/** Accent color for the button (category color). */
|
|
color?: string;
|
|
className?: string;
|
|
}
|
|
|
|
/**
|
|
* Small button that lets attendees drop a tour into their calendar of choice.
|
|
* Offers a native .ics download (Apple/Outlook) and a Google Calendar link.
|
|
*/
|
|
export function AddToCalendar({ event, color = '#06b6d4', className }: AddToCalendarProps) {
|
|
return (
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
className={cn('gap-2 font-bold', className)}
|
|
style={{ borderColor: `${color}55`, color }}
|
|
>
|
|
<CalendarPlus className="h-4 w-4" />
|
|
Add to Calendar
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end" className="w-52">
|
|
<DropdownMenuItem
|
|
onClick={() => downloadICS(event)}
|
|
className="cursor-pointer"
|
|
>
|
|
<Download className="h-4 w-4 mr-2" />
|
|
Apple / Outlook (.ics)
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem asChild className="cursor-pointer">
|
|
<a
|
|
href={googleCalendarUrl(event)}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
>
|
|
<CalendarClock className="h-4 w-4 mr-2" />
|
|
Google Calendar
|
|
</a>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
);
|
|
}
|