feat: add Записаться button to group cards with pre-filled Instagram DM
- BookingModal now accepts optional groupInfo for pre-filled message - Trainer profile: each group card has Записаться button - Schedule group view: each group card has Записаться button - Message includes class type, trainer, days, and time Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useMemo, useCallback } from "react";
|
||||
import { BookingModal } from "@/components/ui/BookingModal";
|
||||
import { CalendarDays, Users, LayoutGrid } from "lucide-react";
|
||||
import { SectionHeading } from "@/components/ui/SectionHeading";
|
||||
import { Reveal } from "@/components/ui/Reveal";
|
||||
@@ -28,6 +29,7 @@ export function Schedule({ data: schedule, classItems }: ScheduleProps) {
|
||||
const [filterStatus, setFilterStatus] = useState<StatusFilter>("all");
|
||||
const [filterTime, setFilterTime] = useState<TimeFilter>("all");
|
||||
const [filterDaySet, setFilterDaySet] = useState<Set<string>>(new Set());
|
||||
const [bookingGroup, setBookingGroup] = useState<string | null>(null);
|
||||
|
||||
const isAllMode = locationMode === "all";
|
||||
|
||||
@@ -329,9 +331,15 @@ export function Schedule({ data: schedule, classItems }: ScheduleProps) {
|
||||
filterTrainer={filterTrainer}
|
||||
setFilterTrainer={setFilterTrainerFromCard}
|
||||
showLocation={isAllMode}
|
||||
onBook={setBookingGroup}
|
||||
/>
|
||||
</Reveal>
|
||||
)}
|
||||
<BookingModal
|
||||
open={bookingGroup !== null}
|
||||
onClose={() => setBookingGroup(null)}
|
||||
groupInfo={bookingGroup ?? undefined}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ interface GroupViewProps {
|
||||
filterTrainer: string | null;
|
||||
setFilterTrainer: (trainer: string | null) => void;
|
||||
showLocation?: boolean;
|
||||
onBook?: (groupInfo: string) => void;
|
||||
}
|
||||
|
||||
export function GroupView({
|
||||
@@ -65,6 +66,7 @@ export function GroupView({
|
||||
filterTrainer,
|
||||
setFilterTrainer,
|
||||
showLocation,
|
||||
onBook,
|
||||
}: GroupViewProps) {
|
||||
const groups = buildGroups(filteredDays);
|
||||
|
||||
@@ -177,6 +179,14 @@ export function GroupView({
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{onBook && (
|
||||
<button
|
||||
onClick={() => onBook(`${group.type}, ${group.trainer}, ${group.slots.map(s => s.dayShort).join("/")} ${group.slots[0]?.time ?? ""}`)}
|
||||
className="w-full mt-3 rounded-xl bg-gold/15 border border-gold/25 py-2 text-xs font-semibold text-gold-dark dark:text-gold hover:bg-gold/25 transition-colors cursor-pointer"
|
||||
>
|
||||
Записаться
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState, useEffect, useRef, useCallback } from "react";
|
||||
import Image from "next/image";
|
||||
import { ArrowLeft, Instagram, Trophy, GraduationCap, ExternalLink, X, Award, Scale, Clock, MapPin } from "lucide-react";
|
||||
import type { TeamMember, RichListItem, VictoryItem, ScheduleLocation } from "@/types/content";
|
||||
import { BookingModal } from "@/components/ui/BookingModal";
|
||||
|
||||
interface TeamProfileProps {
|
||||
member: TeamMember;
|
||||
@@ -11,6 +12,7 @@ interface TeamProfileProps {
|
||||
|
||||
export function TeamProfile({ member, onBack, schedule }: TeamProfileProps) {
|
||||
const [lightbox, setLightbox] = useState<string | null>(null);
|
||||
const [bookingGroup, setBookingGroup] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
function handleKeyDown(e: KeyboardEvent) {
|
||||
@@ -177,7 +179,7 @@ export function TeamProfile({ member, onBack, schedule }: TeamProfileProps) {
|
||||
</span>
|
||||
<ScrollRow>
|
||||
{uniqueGroups.map((g, i) => (
|
||||
<div key={i} className="w-44 shrink-0 rounded-xl border border-white/[0.08] bg-white/[0.03] p-3 space-y-1.5">
|
||||
<div key={i} className="w-48 shrink-0 rounded-xl border border-white/[0.08] bg-white/[0.03] p-3 space-y-1.5">
|
||||
<p className="text-xs font-semibold uppercase tracking-wider text-white/80">{g.type}</p>
|
||||
<div className="flex items-center gap-1.5 text-xs text-white/50">
|
||||
<Clock size={11} />
|
||||
@@ -195,6 +197,12 @@ export function TeamProfile({ member, onBack, schedule }: TeamProfileProps) {
|
||||
Набор открыт
|
||||
</span>
|
||||
)}
|
||||
<button
|
||||
onClick={() => setBookingGroup(`${g.type}, ${g.days.join("/")} ${g.time}`)}
|
||||
className="w-full mt-1 rounded-lg bg-gold/15 border border-gold/25 py-1.5 text-[11px] font-semibold text-gold hover:bg-gold/25 transition-colors cursor-pointer"
|
||||
>
|
||||
Записаться
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</ScrollRow>
|
||||
@@ -274,6 +282,12 @@ export function TeamProfile({ member, onBack, schedule }: TeamProfileProps) {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<BookingModal
|
||||
open={bookingGroup !== null}
|
||||
onClose={() => setBookingGroup(null)}
|
||||
groupInfo={bookingGroup ?? undefined}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,9 +8,10 @@ import { siteContent } from "@/data/content";
|
||||
interface BookingModalProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
groupInfo?: string;
|
||||
}
|
||||
|
||||
export function BookingModal({ open, onClose }: BookingModalProps) {
|
||||
export function BookingModal({ open, onClose, groupInfo }: BookingModalProps) {
|
||||
const { contact } = siteContent;
|
||||
const [name, setName] = useState("");
|
||||
const [phone, setPhone] = useState("+375 ");
|
||||
@@ -65,7 +66,8 @@ export function BookingModal({ open, onClose }: BookingModalProps) {
|
||||
(e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
// Build Instagram DM message with pre-filled text
|
||||
const message = `Здравствуйте! Меня зовут ${name}, хочу записаться на занятие. Мой телефон: ${phone}`;
|
||||
const groupText = groupInfo ? ` (${groupInfo})` : "";
|
||||
const message = `Здравствуйте! Меня зовут ${name}, хочу записаться на занятие${groupText}. Мой телефон: ${phone}`;
|
||||
const instagramUrl = `https://ig.me/m/blackheartdancehouse?text=${encodeURIComponent(message)}`;
|
||||
window.open(instagramUrl, "_blank");
|
||||
setSubmitted(true);
|
||||
|
||||
Reference in New Issue
Block a user