main #6
@@ -31,7 +31,6 @@ import { WebinarsPage } from "./components/WebinarsPage";
|
|||||||
import HomePage from './pages/HomePage';
|
import HomePage from './pages/HomePage';
|
||||||
import { AboutUs } from './components/AboutUs';
|
import { AboutUs } from './components/AboutUs';
|
||||||
import { Services } from './components/Services';
|
import { Services } from './components/Services';
|
||||||
import { LearningFacilityNew } from './components/LearningFacilityNew';
|
|
||||||
import { FooterNew } from './components/FooterNew';
|
import { FooterNew } from './components/FooterNew';
|
||||||
import { Privacy } from "./pages/Privacy";
|
import { Privacy } from "./pages/Privacy";
|
||||||
import { TermsCondition } from "./pages/TermsCondition";
|
import { TermsCondition } from "./pages/TermsCondition";
|
||||||
@@ -39,6 +38,8 @@ import { FAQ } from "./pages/FAQ";
|
|||||||
import { LeadershipPipelineDevelopment } from "./components/services/LeadershipPipelineDevelopment";
|
import { LeadershipPipelineDevelopment } from "./components/services/LeadershipPipelineDevelopment";
|
||||||
import { LeadershipDevelopment } from "./components/services/LeadershipDevelopment";
|
import { LeadershipDevelopment } from "./components/services/LeadershipDevelopment";
|
||||||
import { KautilyaFacility } from "./components/KautilyaFacility";
|
import { KautilyaFacility } from "./components/KautilyaFacility";
|
||||||
|
import { LearningFacilityPage } from "./components/LearningFacilityPage";
|
||||||
|
import WebinarDetail from "./components/WebinarDetail";
|
||||||
// import EnrollPlaceholder from "./components/EnrollPlaceholder";
|
// import EnrollPlaceholder from "./components/EnrollPlaceholder";
|
||||||
// import ForgotPasswordPlaceholder from "./components/ForgotPasswordPlaceholder";
|
// import ForgotPasswordPlaceholder from "./components/ForgotPasswordPlaceholder";
|
||||||
// import DashboardPlaceholder from "./components/DashboardPlaceholder";
|
// import DashboardPlaceholder from "./components/DashboardPlaceholder";
|
||||||
@@ -85,6 +86,7 @@ export default function App() {
|
|||||||
|
|
||||||
{/* Webinars Pages */}
|
{/* Webinars Pages */}
|
||||||
<Route path="/webinars" element={<WebinarsPage />} />
|
<Route path="/webinars" element={<WebinarsPage />} />
|
||||||
|
<Route path="/webinars/:webinar_id" element={<WebinarDetail />} />
|
||||||
<Route path="/webinars-legacy" element={<WebinarsListing />} />
|
<Route path="/webinars-legacy" element={<WebinarsListing />} />
|
||||||
|
|
||||||
{/* Learning Online */}
|
{/* Learning Online */}
|
||||||
@@ -115,7 +117,7 @@ export default function App() {
|
|||||||
<Route path="/programme/:slug" element={<ProgrammeDetail />} />
|
<Route path="/programme/:slug" element={<ProgrammeDetail />} />
|
||||||
|
|
||||||
{/* Learning Facility */}
|
{/* Learning Facility */}
|
||||||
<Route path="/learning-facility" element={<LearningFacilityNew />} />
|
<Route path="/learning-facility" element={<LearningFacilityPage />} />
|
||||||
{/* Privacy policy */}
|
{/* Privacy policy */}
|
||||||
<Route path="/privacy-policy" element={<Privacy />} />
|
<Route path="/privacy-policy" element={<Privacy />} />
|
||||||
<Route path="/term-condition" element={<TermsCondition />} />
|
<Route path="/term-condition" element={<TermsCondition />} />
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ interface CTABannerSectionProps {
|
|||||||
cta_text: string;
|
cta_text: string;
|
||||||
cta_destination: string;
|
cta_destination: string;
|
||||||
description: string;
|
description: string;
|
||||||
landing_page_type: string;
|
landing_page_type?: string;
|
||||||
service_type: string | null;
|
service_type?: string | null;
|
||||||
};
|
};
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,10 @@ export function CourseCard({ course, onClick, className, onAddToCart }: CourseCa
|
|||||||
fontFamily: 'var(--font-family-base)'
|
fontFamily: 'var(--font-family-base)'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{course.title}
|
{course.title
|
||||||
|
?.split(' ')
|
||||||
|
.slice(0, 3)
|
||||||
|
.join(' ') + (course.title.split(' ').length > 3 ? '...' : '')}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{/* Course Description - Limited to 2 lines with ellipsis */}
|
{/* Course Description - Limited to 2 lines with ellipsis */}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
2106
src/components/LearningFacilityPage.tsx
Normal file
2106
src/components/LearningFacilityPage.tsx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -445,13 +445,13 @@ export function ProgrammeDetail({ slug }: ProgrammeDetailProps) {
|
|||||||
courseDetail.is_certificate_available ? 'Certified' : 'Non-Certified'
|
courseDetail.is_certificate_available ? 'Certified' : 'Non-Certified'
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
previewVideoUrl:
|
previewVideoUrl:
|
||||||
courseDetail.reviews.find((review) => review.video_url)?.video_url ||
|
(courseDetail.reviews ?? []).find((review) => review.video_url)?.video_url ||
|
||||||
mockProgrammeData.previewVideoUrl,
|
mockProgrammeData.previewVideoUrl,
|
||||||
highlights:
|
highlights:
|
||||||
courseDetail.course_learning_outcomes.slice(0, 5).map((item) => item.title) ||
|
(courseDetail.course_learning_outcomes ?? []).slice(0, 5).map((item) => item.title) ||
|
||||||
mockProgrammeData.highlights,
|
mockProgrammeData.highlights,
|
||||||
deliveryMethods: courseDetail.modules.length
|
deliveryMethods: (courseDetail.modules ?? []).length
|
||||||
? courseDetail.modules.map((module) => module.module_name)
|
? (courseDetail.modules ?? []).map((module) => module.module_name)
|
||||||
: mockProgrammeData.deliveryMethods,
|
: mockProgrammeData.deliveryMethods,
|
||||||
credentials:
|
credentials:
|
||||||
courseDetail.course_certificate?.program_title ||
|
courseDetail.course_certificate?.program_title ||
|
||||||
@@ -476,9 +476,9 @@ export function ProgrammeDetail({ slug }: ProgrammeDetailProps) {
|
|||||||
return courseDetail.modules.map((module, index) => ({
|
return courseDetail.modules.map((module, index) => ({
|
||||||
moduleNumber: index + 1,
|
moduleNumber: index + 1,
|
||||||
title: module.module_name,
|
title: module.module_name,
|
||||||
duration: `${module.lessons.length} lesson${module.lessons.length === 1 ? '' : 's'}`,
|
duration: `${(module.lessons ?? []).length} lesson${(module.lessons ?? []).length === 1 ? '' : 's'}`,
|
||||||
deliveryStyle: module.lessons.some((lesson) => !lesson.is_lock_lesson) ? 'Self-Paced' : 'Locked',
|
deliveryStyle: (module.lessons ?? []).some((lesson) => !lesson.is_lock_lesson) ? 'Self-Paced' : 'Locked',
|
||||||
topics: module.lessons.map((lesson) => lesson.lesson_title)
|
topics: (module.lessons ?? []).map((lesson) => lesson.lesson_title)
|
||||||
}));
|
}));
|
||||||
}, [courseDetail]);
|
}, [courseDetail]);
|
||||||
|
|
||||||
@@ -493,7 +493,7 @@ export function ProgrammeDetail({ slug }: ProgrammeDetailProps) {
|
|||||||
bio: member.faculty_biography,
|
bio: member.faculty_biography,
|
||||||
image: '',
|
image: '',
|
||||||
linkedinUrl: '',
|
linkedinUrl: '',
|
||||||
credentials: member.credentials.map((credential) => credential.credential_name),
|
credentials: (member.credentials ?? []).map((credential) => credential.credential_name),
|
||||||
expertise: member.expertises || []
|
expertise: member.expertises || []
|
||||||
}));
|
}));
|
||||||
}, [courseDetail]);
|
}, [courseDetail]);
|
||||||
@@ -536,7 +536,9 @@ export function ProgrammeDetail({ slug }: ProgrammeDetailProps) {
|
|||||||
|
|
||||||
const useCases = useMemo(() => {
|
const useCases = useMemo(() => {
|
||||||
if (!courseDetail?.modules?.length) return mockUseCases;
|
if (!courseDetail?.modules?.length) return mockUseCases;
|
||||||
return courseDetail.modules.flatMap((module) => module.lessons.map((lesson) => lesson.lesson_title)).slice(0, 6);
|
return courseDetail.modules
|
||||||
|
.flatMap((module) => (module.lessons ?? []).map((lesson) => lesson.lesson_title))
|
||||||
|
.slice(0, 6);
|
||||||
}, [courseDetail]);
|
}, [courseDetail]);
|
||||||
|
|
||||||
const relatedProgrammes = mockRelatedProgrammes;
|
const relatedProgrammes = mockRelatedProgrammes;
|
||||||
@@ -1006,16 +1008,8 @@ export function ProgrammeDetail({ slug }: ProgrammeDetailProps) {
|
|||||||
<Dialog open={showCertificatePreview} onOpenChange={setShowCertificatePreview}>
|
<Dialog open={showCertificatePreview} onOpenChange={setShowCertificatePreview}>
|
||||||
<DialogPortal>
|
<DialogPortal>
|
||||||
<DialogOverlay className="fixed inset-0 bg-black/70 z-[9999]" />
|
<DialogOverlay className="fixed inset-0 bg-black/70 z-[9999]" />
|
||||||
<DialogContent className="fixed left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] w-full max-w-3xl z-[9999] focus:outline-none bg-transparent border-none shadow-none p-0">
|
<DialogContent className="fixed left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] w-full max-w-4xl z-[9999] focus:outline-none bg-transparent border-none shadow-none p-0">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{/* <DialogClose asChild>
|
|
||||||
<button
|
|
||||||
className="absolute -top-12 right-0 text-white hover:bg-white/20 rounded-full p-1 z-10 focus:outline-none"
|
|
||||||
aria-label="Close"
|
|
||||||
>
|
|
||||||
<X className="w-5 h-5" />
|
|
||||||
</button>
|
|
||||||
</DialogClose> */}
|
|
||||||
|
|
||||||
{/* Certificate Card - Authentic Certificate Style */}
|
{/* Certificate Card - Authentic Certificate Style */}
|
||||||
<div className="bg-white rounded-lg shadow-2xl overflow-hidden max-h-[90vh] overflow-y-auto custom-scrollbar">
|
<div className="bg-white rounded-lg shadow-2xl overflow-hidden max-h-[90vh] overflow-y-auto custom-scrollbar">
|
||||||
|
|||||||
@@ -41,19 +41,53 @@ import {
|
|||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { motion, AnimatePresence } from 'motion/react';
|
import { motion, AnimatePresence } from 'motion/react';
|
||||||
import { navigateTo } from './Router';
|
import { navigateTo } from './Router';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
import { ImageWithFallback } from './figma/ImageWithFallback';
|
import { ImageWithFallback } from './figma/ImageWithFallback';
|
||||||
import { BrandedTag } from './about/BrandedTag';
|
import { BrandedTag } from './about/BrandedTag';
|
||||||
import { PrimaryCTAButton } from './PrimaryCTAButton';
|
import { PrimaryCTAButton } from './PrimaryCTAButton';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { getWebinarBySlug, sharedWebinarsData, type WebinarData } from '../data/webinarsData';
|
import { useGetWebinarByIdQuery } from '../redux/services/webinarApi';
|
||||||
|
|
||||||
interface WebinarDetailProps {
|
interface WebinarDetailProps {
|
||||||
params: { slug: string };
|
params?: { webinar_id: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function WebinarDetail({ params }: WebinarDetailProps) {
|
// Helper function to format date
|
||||||
// Get webinar data from shared data source
|
const formatDate = (dateTimeString: string) => {
|
||||||
const [webinar, setWebinar] = useState<WebinarData | null>(null);
|
const date = new Date(dateTimeString);
|
||||||
|
return {
|
||||||
|
date: date.toLocaleDateString('en-US', {
|
||||||
|
weekday: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric'
|
||||||
|
}),
|
||||||
|
time: date.toLocaleTimeString('en-US', {
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
hour12: true
|
||||||
|
}),
|
||||||
|
full: date
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper to get webinar status based on date and API status
|
||||||
|
const getWebinarStatus = (sessionDatetime: string, webinarStatus: string): 'upcoming' | 'live' | 'recorded' => {
|
||||||
|
const now = new Date();
|
||||||
|
const sessionDate = new Date(sessionDatetime);
|
||||||
|
|
||||||
|
if (webinarStatus === 'cancelled') return 'recorded';
|
||||||
|
if (webinarStatus === 'live') return 'live';
|
||||||
|
if (sessionDate > now) return 'upcoming';
|
||||||
|
return 'recorded';
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function WebinarDetail({ params }: WebinarDetailProps = {}) {
|
||||||
|
const routeParams = useParams<{ webinar_id: string }>();
|
||||||
|
const webinarId = routeParams.webinar_id || params?.webinar_id;
|
||||||
|
const { data: webinarData, isLoading, error } = useGetWebinarByIdQuery(webinarId as string, {
|
||||||
|
skip: !webinarId
|
||||||
|
});
|
||||||
const [timeLeft, setTimeLeft] = useState({ days: 0, hours: 0, minutes: 0, seconds: 0 });
|
const [timeLeft, setTimeLeft] = useState({ days: 0, hours: 0, minutes: 0, seconds: 0 });
|
||||||
const [isRegistered, setIsRegistered] = useState(false);
|
const [isRegistered, setIsRegistered] = useState(false);
|
||||||
const [showRegistrationForm, setShowRegistrationForm] = useState(false);
|
const [showRegistrationForm, setShowRegistrationForm] = useState(false);
|
||||||
@@ -75,22 +109,76 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
const videoRef = useRef<HTMLVideoElement>(null);
|
const videoRef = useRef<HTMLVideoElement>(null);
|
||||||
const shareMenuRef = useRef<HTMLDivElement>(null);
|
const shareMenuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// Load webinar data on component mount
|
// Transform API data to match your component's expected format
|
||||||
useEffect(() => {
|
const webinar = webinarData?.data ? {
|
||||||
const webinarData = getWebinarBySlug(params.slug);
|
id: webinarData.data.id,
|
||||||
if (webinarData) {
|
title: webinarData.data.session_title,
|
||||||
setWebinar(webinarData);
|
description: webinarData.data.description || '',
|
||||||
} else {
|
thumbnail: webinarData.data.media?.file_name
|
||||||
// Fallback: redirect to webinars page if webinar not found
|
? `/api/media/${webinarData.data.media.id}`
|
||||||
navigateTo('/webinars');
|
: '/images/default-webinar.jpg',
|
||||||
}
|
theme: webinarData.data.webinar_category_id || 'Webinar',
|
||||||
}, [params.slug]);
|
date: formatDate(webinarData.data.session_datetime).date,
|
||||||
|
time: formatDate(webinarData.data.session_datetime).time,
|
||||||
|
timezone: 'IST', // You might need to fetch timezone name from timezone_xid
|
||||||
|
duration: `${webinarData.data.duration_minutes} minutes`,
|
||||||
|
status: getWebinarStatus(webinarData.data.session_datetime, webinarData.data.webinar_status),
|
||||||
|
attendees: `${webinarData.data.max_attendee}`, // Max capacity or registered count
|
||||||
|
maxAttendees: webinarData.data.max_attendee,
|
||||||
|
registrationOpen: webinarData.data.require_registration && webinarData.data.webinar_status === 'scheduled',
|
||||||
|
recordingReady: webinarData.data.webinar_status === 'ended',
|
||||||
|
zoomUrl: '#', // Not provided in API, might need additional endpoint
|
||||||
|
recordingUrl: '#', // Not provided in API
|
||||||
|
price: 'Free', // Not in API, adjust as needed
|
||||||
|
format: 'Virtual Event',
|
||||||
|
host: {
|
||||||
|
name: webinarData.data.speakers?.[0]?.name || 'Host Name',
|
||||||
|
title: webinarData.data.speakers?.[0]?.designation || 'Host',
|
||||||
|
company: webinarData.data.speakers?.[0]?.company || '',
|
||||||
|
bio: webinarData.data.speakers?.[0]?.bio || '',
|
||||||
|
avatar: webinarData.data.speakers?.[0]?.image_url || '/images/default-avatar.jpg',
|
||||||
|
linkedin: '#'
|
||||||
|
},
|
||||||
|
panelists: webinarData.data.speakers?.filter(s => !s.is_host).map(speaker => ({
|
||||||
|
id: speaker.id,
|
||||||
|
name: speaker.name,
|
||||||
|
title: speaker.designation,
|
||||||
|
company: speaker.company,
|
||||||
|
bio: speaker.bio,
|
||||||
|
avatar: speaker.image_url || '/images/default-avatar.jpg',
|
||||||
|
linkedin: '#'
|
||||||
|
})) || [],
|
||||||
|
abstract: webinarData.data.about_this_session?.description || webinarData.data.description || '',
|
||||||
|
keyTakeaways: webinarData.data.about_this_session?.points?.map(p => p.point) || [],
|
||||||
|
agenda: webinarData.data.agenda_items?.map(item => ({
|
||||||
|
time: formatDate(item.start_time).time,
|
||||||
|
title: item.title,
|
||||||
|
description: item.description
|
||||||
|
})) || [],
|
||||||
|
faqs: [] as Array<{ question: string; answer: string }>, // Not in API response
|
||||||
|
tags: [] as string[], // Not in API response, derive from category or other fields
|
||||||
|
relatedProgrammes: webinarData.data.course_links?.map(courseLink => ({
|
||||||
|
id: courseLink.course.id,
|
||||||
|
slug: courseLink.course.course_name.toLowerCase().replace(/\s+/g, '-'),
|
||||||
|
title: courseLink.course.course_name,
|
||||||
|
description: courseLink.course.course_desc,
|
||||||
|
category: courseLink.course.course_category_name,
|
||||||
|
level: courseLink.course.retail_type === 'private' ? 'Private' : 'Public',
|
||||||
|
duration: courseLink.course.total_duration ? `${courseLink.course.total_duration} mins` : 'Self-paced',
|
||||||
|
participants: courseLink.course.total_reviews || 0,
|
||||||
|
rating: courseLink.course.avg_rating || 0,
|
||||||
|
price: courseLink.course.price ? `₹${courseLink.course.price}` : 'Free',
|
||||||
|
originalPrice: courseLink.course.best_value ? `₹${courseLink.course.best_value}` : `₹${courseLink.course.price}`,
|
||||||
|
image: courseLink.course.thumbnail_img || '/images/default-course.jpg',
|
||||||
|
bestValue: courseLink.course.best_value
|
||||||
|
})) || []
|
||||||
|
} : null;
|
||||||
|
|
||||||
// Countdown timer
|
// Countdown timer
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!webinar || webinar.status !== 'upcoming') return;
|
if (!webinar || webinar.status !== 'upcoming' || !webinarData?.data.session_datetime) return;
|
||||||
|
|
||||||
const targetDate = new Date(`${webinar.date}T${webinar.time}:00`);
|
const targetDate = new Date(webinarData.data.session_datetime);
|
||||||
|
|
||||||
const updateCountdown = () => {
|
const updateCountdown = () => {
|
||||||
const now = new Date().getTime();
|
const now = new Date().getTime();
|
||||||
@@ -110,7 +198,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
const interval = setInterval(updateCountdown, 1000);
|
const interval = setInterval(updateCountdown, 1000);
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [webinar?.date, webinar?.time, webinar?.status]);
|
}, [webinar, webinarData?.data.session_datetime]);
|
||||||
|
|
||||||
// Close share menu when clicking outside
|
// Close share menu when clicking outside
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -129,7 +217,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setIsSubmittingRegistration(true);
|
setIsSubmittingRegistration(true);
|
||||||
|
|
||||||
// Simulate API call
|
// TODO: Integrate with your registration API endpoint
|
||||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||||
|
|
||||||
setIsSubmittingRegistration(false);
|
setIsSubmittingRegistration(false);
|
||||||
@@ -163,7 +251,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
if (!webinar) return { text: 'Loading...', onClick: () => {}, disabled: true };
|
if (!webinar) return { text: 'Loading...', onClick: () => {}, disabled: true };
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const webinarDate = new Date(`${webinar.date}T${webinar.time}:00`);
|
const webinarDate = webinarData?.data.session_datetime ? new Date(webinarData.data.session_datetime) : new Date();
|
||||||
const tenMinutesBefore = new Date(webinarDate.getTime() - 10 * 60 * 1000);
|
const tenMinutesBefore = new Date(webinarDate.getTime() - 10 * 60 * 1000);
|
||||||
|
|
||||||
switch (webinar.status) {
|
switch (webinar.status) {
|
||||||
@@ -177,7 +265,10 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
if (now >= tenMinutesBefore) {
|
if (now >= tenMinutesBefore) {
|
||||||
return {
|
return {
|
||||||
text: 'Launch in Zoom',
|
text: 'Launch in Zoom',
|
||||||
onClick: () => window.open(webinar.zoomUrl, '_blank'),
|
onClick: () => {
|
||||||
|
// You'll need to get the Zoom URL from a separate endpoint
|
||||||
|
toast.info('Zoom link would open here');
|
||||||
|
},
|
||||||
disabled: false
|
disabled: false
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@@ -256,7 +347,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Show loading state while webinar data is loading
|
// Show loading state while webinar data is loading
|
||||||
if (!webinar) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen flex items-center justify-center" style={{ backgroundColor: '#FFFFFF' }}>
|
<div className="min-h-screen flex items-center justify-center" style={{ backgroundColor: '#FFFFFF' }}>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
@@ -267,7 +358,26 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show error state
|
||||||
|
if (error || !webinar) {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen flex items-center justify-center" style={{ backgroundColor: '#FFFFFF' }}>
|
||||||
|
<div className="text-center">
|
||||||
|
<AlertCircle className="w-12 h-12 text-red-500 mx-auto mb-4" />
|
||||||
|
<h2 className="text-h2 mb-2">Webinar Not Found</h2>
|
||||||
|
<p className="text-body text-gray-600 mb-6">The webinar you're looking for doesn't exist or has been removed.</p>
|
||||||
|
<PrimaryCTAButton
|
||||||
|
text="Browse Webinars"
|
||||||
|
onClick={() => navigateTo('/webinars')}
|
||||||
|
className="cta-text-black"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const ctaProps = getCTAProps();
|
const ctaProps = getCTAProps();
|
||||||
|
const sessionDateTime = webinarData?.data.session_datetime ? new Date(webinarData.data.session_datetime) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
|
<div className="min-h-screen" style={{ backgroundColor: '#FFFFFF' }}>
|
||||||
@@ -298,7 +408,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Countdown Timer for Upcoming Webinars */}
|
{/* Countdown Timer for Upcoming Webinars */}
|
||||||
{webinar.status === 'upcoming' && (
|
{webinar.status === 'upcoming' && sessionDateTime && (
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
<div className="grid grid-cols-4 gap-4 max-w-md mb-4">
|
<div className="grid grid-cols-4 gap-4 max-w-md mb-4">
|
||||||
{[
|
{[
|
||||||
@@ -318,12 +428,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-small-white opacity-80">
|
<div className="text-small-white opacity-80">
|
||||||
Starts {new Date(`${webinar.date}T${webinar.time}:00`).toLocaleDateString('en-US', {
|
Starts {webinar.date} at {webinar.time}
|
||||||
weekday: 'long',
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric'
|
|
||||||
})} at {webinar.time} {webinar.timezone}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -337,11 +442,11 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
<span className="text-small font-medium">LIVE NOW</span>
|
<span className="text-small font-medium">LIVE NOW</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-small-white">
|
<div className="text-small-white">
|
||||||
{webinar.attendees} people watching
|
Max capacity: {webinar.maxAttendees} attendees
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-body-lg-white">
|
<div className="text-body-lg-white">
|
||||||
Session in progress • Ends at {webinar.endTime} {webinar.timezone}
|
Session in progress
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -356,7 +461,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-body-lg-white">
|
<div className="text-body-lg-white">
|
||||||
Session held on {new Date(`${webinar.date}T${webinar.time}:00`).toLocaleDateString('en-US', {
|
Session held on {sessionDateTime?.toLocaleDateString('en-US', {
|
||||||
month: 'long',
|
month: 'long',
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
year: 'numeric'
|
year: 'numeric'
|
||||||
@@ -425,7 +530,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
<div className="flex items-center gap-2 text-muted">
|
<div className="flex items-center gap-2 text-muted">
|
||||||
<Users className="w-4 h-4" />
|
<Users className="w-4 h-4" />
|
||||||
<span className="text-small">
|
<span className="text-small">
|
||||||
{webinar.attendees} {webinar.status === 'live' ? 'watching' : 'registered'}
|
{webinar.attendees} {webinar.status === 'live' ? 'watching' : 'capacity'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -445,45 +550,49 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
{webinar.abstract}
|
{webinar.abstract}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div>
|
{webinar.keyTakeaways.length > 0 && (
|
||||||
<h3 className="text-h3 mb-4">What You'll Learn</h3>
|
<div>
|
||||||
<ul className="space-y-3">
|
<h3 className="text-h3 mb-4">What You'll Learn</h3>
|
||||||
{webinar.keyTakeaways.map((takeaway, index) => (
|
<ul className="space-y-3">
|
||||||
<li key={index} className="flex items-start gap-3">
|
{webinar.keyTakeaways.map((takeaway, index) => (
|
||||||
<CheckCircle className="w-5 h-5 text-[#04045B] mt-0.5 flex-shrink-0" />
|
<li key={index} className="flex items-start gap-3">
|
||||||
<span className="text-body">{takeaway}</span>
|
<CheckCircle className="w-5 h-5 text-[#04045B] mt-0.5 flex-shrink-0" />
|
||||||
</li>
|
<span className="text-body">{takeaway}</span>
|
||||||
))}
|
</li>
|
||||||
</ul>
|
))}
|
||||||
</div>
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Agenda Timeline */}
|
{/* Agenda Timeline */}
|
||||||
<section>
|
{webinar.agenda.length > 0 && (
|
||||||
<h2 className="text-h2 mb-6">Session Agenda</h2>
|
<section>
|
||||||
<div className="space-y-6">
|
<h2 className="text-h2 mb-6">Session Agenda</h2>
|
||||||
{webinar.agenda.map((item, index) => (
|
<div className="space-y-6">
|
||||||
<div key={index} className="flex gap-6">
|
{webinar.agenda.map((item, index) => (
|
||||||
<div className="flex flex-col items-center">
|
<div key={index} className="flex gap-6">
|
||||||
<div className="w-4 h-4 bg-[#04045B] rounded-full" />
|
<div className="flex flex-col items-center">
|
||||||
{index < webinar.agenda.length - 1 && (
|
<div className="w-4 h-4 bg-[#04045B] rounded-full" />
|
||||||
<div className="w-0.5 h-16 bg-gray-200 mt-2" />
|
{index < webinar.agenda.length - 1 && (
|
||||||
)}
|
<div className="w-0.5 h-16 bg-gray-200 mt-2" />
|
||||||
</div>
|
)}
|
||||||
<div className="flex-1 pb-8">
|
</div>
|
||||||
<div className="flex flex-col sm:flex-row sm:items-center gap-2 mb-2">
|
<div className="flex-1 pb-8">
|
||||||
<Badge variant="outline" className="w-fit text-[#04045B] border-[#04045B]">
|
<div className="flex flex-col sm:flex-row sm:items-center gap-2 mb-2">
|
||||||
{item.time}
|
<Badge variant="outline" className="w-fit text-[#04045B] border-[#04045B]">
|
||||||
</Badge>
|
{item.time}
|
||||||
<h3 className="text-h4">{item.title}</h3>
|
</Badge>
|
||||||
|
<h3 className="text-h4">{item.title}</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-body text-muted">{item.description}</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-body text-muted">{item.description}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
))}
|
</div>
|
||||||
</div>
|
</section>
|
||||||
</section>
|
)}
|
||||||
|
|
||||||
{/* Host & Panelists */}
|
{/* Host & Panelists */}
|
||||||
<section>
|
<section>
|
||||||
@@ -503,14 +612,16 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
<h3 className="text-h4 mb-1">{webinar.host.name}</h3>
|
<h3 className="text-h4 mb-1">{webinar.host.name}</h3>
|
||||||
<p className="text-small text-[#04045B] font-medium">HOST</p>
|
<p className="text-small text-[#04045B] font-medium">HOST</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
{webinar.host.linkedin !== '#' && (
|
||||||
variant="ghost"
|
<Button
|
||||||
size="sm"
|
variant="ghost"
|
||||||
onClick={() => window.open(webinar.host.linkedin, '_blank')}
|
size="sm"
|
||||||
className="text-[#04045B] hover:bg-[#04045B] hover:text-white"
|
onClick={() => window.open(webinar.host.linkedin, '_blank')}
|
||||||
>
|
className="text-[#04045B] hover:bg-[#04045B] hover:text-white"
|
||||||
<ExternalLink className="w-4 h-4" />
|
>
|
||||||
</Button>
|
<ExternalLink className="w-4 h-4" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-small text-muted mb-1">{webinar.host.title}</p>
|
<p className="text-small text-muted mb-1">{webinar.host.title}</p>
|
||||||
<p className="text-small text-muted">{webinar.host.company}</p>
|
<p className="text-small text-muted">{webinar.host.company}</p>
|
||||||
@@ -535,14 +646,16 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
<h3 className="text-h4 mb-1">{panelist.name}</h3>
|
<h3 className="text-h4 mb-1">{panelist.name}</h3>
|
||||||
<p className="text-small text-[#F8C301] font-medium">SPEAKER</p>
|
<p className="text-small text-[#F8C301] font-medium">SPEAKER</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
{panelist.linkedin !== '#' && (
|
||||||
variant="ghost"
|
<Button
|
||||||
size="sm"
|
variant="ghost"
|
||||||
onClick={() => window.open(panelist.linkedin, '_blank')}
|
size="sm"
|
||||||
className="text-[#04045B] hover:bg-[#04045B] hover:text-white"
|
onClick={() => window.open(panelist.linkedin, '_blank')}
|
||||||
>
|
className="text-[#04045B] hover:bg-[#04045B] hover:text-white"
|
||||||
<ExternalLink className="w-4 h-4" />
|
>
|
||||||
</Button>
|
<ExternalLink className="w-4 h-4" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-small text-muted mb-1">{panelist.title}</p>
|
<p className="text-small text-muted mb-1">{panelist.title}</p>
|
||||||
<p className="text-small text-muted">{panelist.company}</p>
|
<p className="text-small text-muted">{panelist.company}</p>
|
||||||
@@ -604,7 +717,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
<div className="text-center mb-6">
|
<div className="text-center mb-6">
|
||||||
<div className="text-h3 mb-2">{webinar.price}</div>
|
<div className="text-h3 mb-2">{webinar.price}</div>
|
||||||
<div className="text-small text-muted">
|
<div className="text-small text-muted">
|
||||||
{webinar.maxAttendees - parseInt(webinar.attendees.replace(/\D/g, '')) || 0} spots remaining
|
{webinar.maxAttendees} spots available
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -612,15 +725,8 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Calendar className="w-5 h-5 text-[#04045B]" />
|
<Calendar className="w-5 h-5 text-[#04045B]" />
|
||||||
<div>
|
<div>
|
||||||
<div className="text-body font-medium">
|
<div className="text-body font-medium">{webinar.date}</div>
|
||||||
{new Date(`${webinar.date}T${webinar.time}:00`).toLocaleDateString('en-US', {
|
<div className="text-small text-muted">{webinar.time}</div>
|
||||||
weekday: 'long',
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'long',
|
|
||||||
day: 'numeric'
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div className="text-small text-muted">{webinar.time} {webinar.timezone}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -636,7 +742,7 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
|
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Users className="w-5 h-5 text-[#04045B]" />
|
<Users className="w-5 h-5 text-[#04045B]" />
|
||||||
<div className="text-body">{webinar.attendees} registered</div>
|
<div className="text-body">Capacity: {webinar.attendees} attendees</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -863,9 +969,9 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
{/* Add to Cart Button - Outline Blue */}
|
{/* Add to Cart Button - Outline Blue */}
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={(e) => {
|
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
// Add to cart functionality would go here
|
toast.info('Add to cart functionality would go here');
|
||||||
}}
|
}}
|
||||||
className="flex-1 flex items-center justify-center gap-2 h-11 rounded-lg transition-all duration-200 font-medium"
|
className="flex-1 flex items-center justify-center gap-2 h-11 rounded-lg transition-all duration-200 font-medium"
|
||||||
style={{
|
style={{
|
||||||
@@ -877,11 +983,11 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
borderWidth: '2px'
|
borderWidth: '2px'
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
e.currentTarget.style.backgroundColor = '#04045B';
|
e.currentTarget.style.backgroundColor = '#04045B';
|
||||||
e.currentTarget.style.color = 'white';
|
e.currentTarget.style.color = 'white';
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
e.currentTarget.style.backgroundColor = 'transparent';
|
e.currentTarget.style.backgroundColor = 'transparent';
|
||||||
e.currentTarget.style.color = '#04045B';
|
e.currentTarget.style.color = '#04045B';
|
||||||
}}
|
}}
|
||||||
@@ -901,10 +1007,10 @@ export default function WebinarDetail({ params }: WebinarDetailProps) {
|
|||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
border: 'none'
|
border: 'none'
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
e.currentTarget.style.backgroundColor = '#030359';
|
e.currentTarget.style.backgroundColor = '#030359';
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
e.currentTarget.style.backgroundColor = '#04045B';
|
e.currentTarget.style.backgroundColor = '#04045B';
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ export function Webinars() {
|
|||||||
const WebinarCard = ({ webinar }: { webinar: WebinarItem }) => {
|
const WebinarCard = ({ webinar }: { webinar: WebinarItem }) => {
|
||||||
const handleCardClick = () => {
|
const handleCardClick = () => {
|
||||||
if (webinar.webinar_status !== 'cancelled') {
|
if (webinar.webinar_status !== 'cancelled') {
|
||||||
navigateTo(`/webinar/${webinar.id}`);
|
navigateTo(`/webinars/${webinar.id}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ export const aboutUsApi = createApi({
|
|||||||
// ✅ GET About Us
|
// ✅ GET About Us
|
||||||
getAboutUs: builder.query<AboutUsData, void>({
|
getAboutUs: builder.query<AboutUsData, void>({
|
||||||
query: () => ({
|
query: () => ({
|
||||||
url: "/admin/about-us",
|
url: "/guest/about-us",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ export const blogApi = createApi({
|
|||||||
if (tag_id && tag_id !== "all") params.tag_id = tag_id;
|
if (tag_id && tag_id !== "all") params.tag_id = tag_id;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: "/admin/blogs/list",
|
url: "/guest/blogs/list",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
params,
|
params,
|
||||||
};
|
};
|
||||||
@@ -114,7 +114,7 @@ export const blogApi = createApi({
|
|||||||
|
|
||||||
getBlogByID: builder.query<BlogItem, string>({
|
getBlogByID: builder.query<BlogItem, string>({
|
||||||
query: (id) => ({
|
query: (id) => ({
|
||||||
url: `/admin/blogs/list/${id}`,
|
url: `/guest/blogs/list/${id}`,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
}),
|
}),
|
||||||
transformResponse: (response: BlogByIdResponse) => response.data,
|
transformResponse: (response: BlogByIdResponse) => response.data,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const contactUsApi = createApi({
|
|||||||
// GET Lead Categories
|
// GET Lead Categories
|
||||||
getLeadCategories: builder.query({
|
getLeadCategories: builder.query({
|
||||||
query: ({ limit = 10, offset = 0, status = "active" }) => ({
|
query: ({ limit = 10, offset = 0, status = "active" }) => ({
|
||||||
url: "admin/prepopulate/lead-categories/list",
|
url: "guest/prepopulate/lead-categories/list",
|
||||||
params: {
|
params: {
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
@@ -23,7 +23,7 @@ export const contactUsApi = createApi({
|
|||||||
// CREATE Lead
|
// CREATE Lead
|
||||||
createLead: builder.mutation({
|
createLead: builder.mutation({
|
||||||
query: (body) => ({
|
query: (body) => ({
|
||||||
url: "admin/leads/create",
|
url: "guest/leads/create",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body,
|
body,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -321,8 +321,8 @@ export const courseApi = createApi({
|
|||||||
const queryString = searchParams.toString();
|
const queryString = searchParams.toString();
|
||||||
|
|
||||||
return queryString
|
return queryString
|
||||||
? `admin/course/public/list?${queryString}`
|
? `guest/course/public/list?${queryString}`
|
||||||
: `admin/course/public/list`;
|
: `guest/course/public/list`;
|
||||||
},
|
},
|
||||||
|
|
||||||
providesTags: (result) =>
|
providesTags: (result) =>
|
||||||
@@ -348,15 +348,15 @@ export const courseApi = createApi({
|
|||||||
}
|
}
|
||||||
const queryString = searchParams.toString();
|
const queryString = searchParams.toString();
|
||||||
return queryString
|
return queryString
|
||||||
? `admin/prepopulate/course-categories/list?${queryString}`
|
? `guest/prepopulate/course-categories/list?${queryString}`
|
||||||
: `admin/prepopulate/course-categories/list`;
|
: `guest/prepopulate/course-categories/list`;
|
||||||
},
|
},
|
||||||
providesTags: ["CourseCategories"],
|
providesTags: ["CourseCategories"],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// GET Course By Id
|
// GET Course By Id
|
||||||
getcoursebyid: builder.query<CourseDetailResponse, string>({
|
getcoursebyid: builder.query<CourseDetailResponse, string>({
|
||||||
query: (course_id) => `admin/course/${course_id}`,
|
query: (course_id) => `guest/course/${course_id}`,
|
||||||
providesTags: (_result, _error, course_id) => [{ type: "Course", id: course_id }],
|
providesTags: (_result, _error, course_id) => [{ type: "Course", id: course_id }],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -368,4 +368,5 @@ export const {
|
|||||||
useGetCoursesQuery,
|
useGetCoursesQuery,
|
||||||
useGetCourseCategoriesQuery,
|
useGetCourseCategoriesQuery,
|
||||||
useGetcoursebyidQuery,
|
useGetcoursebyidQuery,
|
||||||
|
|
||||||
} = courseApi;
|
} = courseApi;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const faqApi = createApi({
|
|||||||
// GET FAQs LIST
|
// GET FAQs LIST
|
||||||
getFaqs: builder.query({
|
getFaqs: builder.query({
|
||||||
query: ({ limit = 10, offset = 0, search_term, content_status, content_category_xid }) => ({
|
query: ({ limit = 10, offset = 0, search_term, content_status, content_category_xid }) => ({
|
||||||
url: "admin/faq/list",
|
url: "guest/faq/list",
|
||||||
params: {
|
params: {
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
@@ -25,7 +25,7 @@ export const faqApi = createApi({
|
|||||||
// GET category TAGS LIST
|
// GET category TAGS LIST
|
||||||
getFaqCategories: builder.query({
|
getFaqCategories: builder.query({
|
||||||
query: ({ limit = 10, offset = 0, search_query }) => ({
|
query: ({ limit = 10, offset = 0, search_query }) => ({
|
||||||
url: "admin/prepopulate/content-categories/list",
|
url: "guest/prepopulate/content-categories/list",
|
||||||
params: {
|
params: {
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export const homepageApi = createApi({
|
|||||||
{ landing_page_type: "home" | "services" | "about_us" }
|
{ landing_page_type: "home" | "services" | "about_us" }
|
||||||
>({
|
>({
|
||||||
query: ({ landing_page_type }) => ({
|
query: ({ landing_page_type }) => ({
|
||||||
url: "/admin/home-page/list",
|
url: "/guest/home-page/list",
|
||||||
params: { landing_page_type },
|
params: { landing_page_type },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ export const homepageApi = createApi({
|
|||||||
|
|
||||||
getFeaturedBlogs: builder.query({
|
getFeaturedBlogs: builder.query({
|
||||||
query: ({ limit = 3 }) => ({
|
query: ({ limit = 3 }) => ({
|
||||||
url: `/admin/blogs/featured?limit=${limit}`,
|
url: `/guest/blogs/featured?limit=${limit}`,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
}),
|
}),
|
||||||
transformResponse: (response: any) => {
|
transformResponse: (response: any) => {
|
||||||
|
|||||||
@@ -14,7 +14,15 @@ export interface KautilyaPageResponse {
|
|||||||
subtext: string;
|
subtext: string;
|
||||||
cta_text: string;
|
cta_text: string;
|
||||||
cta_destination: string;
|
cta_destination: string;
|
||||||
|
images: Array<{ // ✅ FIX ADDED
|
||||||
|
id: string;
|
||||||
|
hero_section_xid: string;
|
||||||
|
image_url: string;
|
||||||
|
alt_text: string;
|
||||||
|
display_order: number;
|
||||||
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
our_story: {
|
our_story: {
|
||||||
id: string;
|
id: string;
|
||||||
tag: string;
|
tag: string;
|
||||||
@@ -22,6 +30,7 @@ export interface KautilyaPageResponse {
|
|||||||
content: string;
|
content: string;
|
||||||
image_url: string;
|
image_url: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
why_choose_us: {
|
why_choose_us: {
|
||||||
id: string;
|
id: string;
|
||||||
tag: string;
|
tag: string;
|
||||||
@@ -40,6 +49,7 @@ export interface KautilyaPageResponse {
|
|||||||
}>;
|
}>;
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
facility_features: {
|
facility_features: {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
@@ -58,6 +68,7 @@ export interface KautilyaPageResponse {
|
|||||||
}>;
|
}>;
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
visual_tour: {
|
visual_tour: {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
@@ -75,6 +86,7 @@ export interface KautilyaPageResponse {
|
|||||||
}>;
|
}>;
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
daily_experience: {
|
daily_experience: {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
@@ -88,6 +100,7 @@ export interface KautilyaPageResponse {
|
|||||||
display_order: number;
|
display_order: number;
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
||||||
cta_section: {
|
cta_section: {
|
||||||
id: string;
|
id: string;
|
||||||
background_image_url: string;
|
background_image_url: string;
|
||||||
@@ -97,6 +110,7 @@ export interface KautilyaPageResponse {
|
|||||||
description: string;
|
description: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
errors: any;
|
errors: any;
|
||||||
correlation_id: string;
|
correlation_id: string;
|
||||||
}
|
}
|
||||||
@@ -111,7 +125,7 @@ export const learningFacilityApi = createApi({
|
|||||||
{ }
|
{ }
|
||||||
>({
|
>({
|
||||||
query: ({ }) => ({
|
query: ({ }) => ({
|
||||||
url: "/admin/kautilya-page/get",
|
url: "/guest/kautilya-page/get",
|
||||||
}),
|
}),
|
||||||
transformResponse: (response: KautilyaPageResponse) => response.data,
|
transformResponse: (response: KautilyaPageResponse) => response.data,
|
||||||
providesTags: [{ type: "KautilyaPage", id: "LIST" }],
|
providesTags: [{ type: "KautilyaPage", id: "LIST" }],
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const sercicesApi = createApi({
|
|||||||
|
|
||||||
getServiceList: builder.query<any, { service_type: string }>({
|
getServiceList: builder.query<any, { service_type: string }>({
|
||||||
query: ({ service_type }) => ({
|
query: ({ service_type }) => ({
|
||||||
url: `/admin/service-page/list`,
|
url: `/guest/service-page/list`,
|
||||||
params: { service_type },
|
params: { service_type },
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -50,6 +50,92 @@ export interface WebinarListParams {
|
|||||||
sortBy?: "most_popular" | "newest" | "oldest" | "title" | "duration";
|
sortBy?: "most_popular" | "newest" | "oldest" | "title" | "duration";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface WebinarDetailResponse {
|
||||||
|
success: boolean;
|
||||||
|
status: number;
|
||||||
|
message: string;
|
||||||
|
data: {
|
||||||
|
id: string;
|
||||||
|
session_title: string;
|
||||||
|
description: string | null;
|
||||||
|
session_datetime: string;
|
||||||
|
duration_minutes: number;
|
||||||
|
timezone_xid: string;
|
||||||
|
webinar_category_id: string;
|
||||||
|
max_attendee: number;
|
||||||
|
passcode: string;
|
||||||
|
require_registration: boolean;
|
||||||
|
recurring_webinar: boolean;
|
||||||
|
webinar_status: "scheduled" | "live" | "ended" | "cancelled";
|
||||||
|
type: string;
|
||||||
|
media: {
|
||||||
|
id: string;
|
||||||
|
file_name: string;
|
||||||
|
file_type: string;
|
||||||
|
file_extension: string;
|
||||||
|
} | null;
|
||||||
|
about_this_session: {
|
||||||
|
description: string;
|
||||||
|
points: Array<{
|
||||||
|
id: string;
|
||||||
|
about_id: string;
|
||||||
|
point: string;
|
||||||
|
sort_order: number;
|
||||||
|
}>;
|
||||||
|
} | null;
|
||||||
|
agenda_items: Array<{
|
||||||
|
id: string;
|
||||||
|
webinar_xid: string;
|
||||||
|
start_time: string;
|
||||||
|
end_time: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
}>;
|
||||||
|
speakers: Array<{
|
||||||
|
id: string;
|
||||||
|
webinar_xid: string;
|
||||||
|
name: string;
|
||||||
|
designation: string;
|
||||||
|
company: string;
|
||||||
|
bio: string;
|
||||||
|
image_url: string;
|
||||||
|
is_host: boolean;
|
||||||
|
}>;
|
||||||
|
faqs: any;
|
||||||
|
course_links: Array<{
|
||||||
|
id: string;
|
||||||
|
webinar_xid: string;
|
||||||
|
course_xid: string;
|
||||||
|
display_order: number;
|
||||||
|
course: {
|
||||||
|
id: string;
|
||||||
|
course_name: string;
|
||||||
|
course_desc: string;
|
||||||
|
thumbnail_img: string;
|
||||||
|
course_category_xid: string;
|
||||||
|
course_category_name: string;
|
||||||
|
best_value: number;
|
||||||
|
avg_rating: number;
|
||||||
|
total_reviews: number;
|
||||||
|
retail_type: string;
|
||||||
|
price: number;
|
||||||
|
is_certificate_available: boolean;
|
||||||
|
course_status: string;
|
||||||
|
updated_at: string;
|
||||||
|
total_duration: number | null;
|
||||||
|
no_of_modules: number;
|
||||||
|
media_id: string | null;
|
||||||
|
media_file_type: string | null;
|
||||||
|
media_file_extension: string | null;
|
||||||
|
media_file_name: string | null;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
errors: any;
|
||||||
|
correlation_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ================= API ================= */
|
/* ================= API ================= */
|
||||||
|
|
||||||
export const webinarApi = createApi({
|
export const webinarApi = createApi({
|
||||||
@@ -115,14 +201,18 @@ export const webinarApi = createApi({
|
|||||||
params.append("sort_by", sortBy);
|
params.append("sort_by", sortBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
return `/admin/webinars/list?${params.toString()}`;
|
return `/guest/webinars/list?${params.toString()}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
providesTags: ["Webinar"],
|
providesTags: ["Webinar"],
|
||||||
}),
|
}),
|
||||||
|
getWebinarById: builder.query<WebinarDetailResponse, string>({
|
||||||
|
query: (webinarId) => `/guest/webinars/${webinarId}`,
|
||||||
|
providesTags: (result, error, id) => [{ type: "Webinar", id }],
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
/* ================= EXPORT HOOK ================= */
|
/* ================= EXPORT HOOK ================= */
|
||||||
|
|
||||||
export const { useWebinarListQuery } = webinarApi;
|
export const { useWebinarListQuery, useGetWebinarByIdQuery } = webinarApi;
|
||||||
Reference in New Issue
Block a user