Compare commits
No commits in common. '6afb2a7cfbbe2f36250de330e97d974f60b8df19' and 'e70d869b76f0e0c10db0a5d04ad22ead6658439e' have entirely different histories.
6afb2a7cfb
...
e70d869b76
@ -1,21 +1,4 @@ |
|||||||
/** @type {import('next').NextConfig} */ |
/** @type {import('next').NextConfig} */ |
||||||
const nextConfig = { |
const nextConfig = {}; |
||||||
images: { |
|
||||||
remotePatterns: [ |
|
||||||
{ |
|
||||||
protocol: 'https', |
|
||||||
hostname: '**', |
|
||||||
port: '', |
|
||||||
pathname: '**', |
|
||||||
search: '', |
|
||||||
}, |
|
||||||
], |
|
||||||
}, |
|
||||||
webpack: (config) => { |
|
||||||
config.resolve.alias.canvas = false; |
|
||||||
|
|
||||||
return config; |
|
||||||
}, |
|
||||||
}; |
|
||||||
|
|
||||||
export default nextConfig; |
export default nextConfig; |
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,53 +0,0 @@ |
|||||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" |
|
||||||
import { Button } from "@/components/ui/button" |
|
||||||
import { Card, CardContent } from "@/components/ui/card" |
|
||||||
import { CourseData } from "@/helpers/apiSchema/course.schema" |
|
||||||
|
|
||||||
|
|
||||||
interface CourseDetailHeroSectionProps { |
|
||||||
courseData: CourseData; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
const CourseDetailHeroSection: React.FC<CourseDetailHeroSectionProps> = ({courseData}) => { |
|
||||||
return( |
|
||||||
<div className="bg-purple-700 text-white"> |
|
||||||
<div className="container mx-auto px-4 py-12"> |
|
||||||
<div className="grid md:grid-cols-2 gap-8 items-center"> |
|
||||||
<div className="space-y-4"> |
|
||||||
<h1 className="text-3xl font-bold">{courseData.title}</h1> |
|
||||||
<p className="text-blue-100">{courseData.description}</p> |
|
||||||
|
|
||||||
|
|
||||||
<div className="flex items-center space-x-4"> |
|
||||||
<Avatar className="h-12 w-12"> |
|
||||||
<AvatarImage src={courseData.instructor.avatar} className='aspect-1/1'/> |
|
||||||
<AvatarFallback>SJ</AvatarFallback> |
|
||||||
</Avatar> |
|
||||||
<div> |
|
||||||
<div className="font-semibold">{courseData.instructor.name}</div> |
|
||||||
<div className="text-sm text-blue-100">{courseData.instructor.title}</div> |
|
||||||
<div>Published at {courseData?.lastUpdated}</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
{/* course image */} |
|
||||||
<Card className="bg-white"> |
|
||||||
<CardContent className="p-6 space-y-4"> |
|
||||||
<img |
|
||||||
src="https://placehold.co/600x400" |
|
||||||
alt="Course Preview" |
|
||||||
className="w-full rounded-lg" |
|
||||||
/> |
|
||||||
<Button className="w-full text-lg h-12 bg-purple-700"> |
|
||||||
Enroll Now |
|
||||||
</Button> |
|
||||||
</CardContent> |
|
||||||
</Card> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
export default CourseDetailHeroSection |
|
@ -1,56 +0,0 @@ |
|||||||
import { Card, CardContent } from "@/components/ui/card" |
|
||||||
import { CourseData } from "@/helpers/apiSchema/course.schema" |
|
||||||
import { BookOpen, Clock, MessageSquare, Users } from "lucide-react" |
|
||||||
|
|
||||||
|
|
||||||
const CourseDetailStats :React.FC<{courseData : CourseData}> = ({courseData}) => { |
|
||||||
return( |
|
||||||
<> |
|
||||||
<div className="mx-auto container py-8"> |
|
||||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4"> |
|
||||||
<Card> |
|
||||||
<CardContent className="p-4 flex items-center space-x-4"> |
|
||||||
<Clock className="h-8 w-8 text-blue-500" /> |
|
||||||
<div> |
|
||||||
<div className="text-sm text-gray-500">Duration</div> |
|
||||||
<div className="font-semibold">{courseData.duration}</div> |
|
||||||
</div> |
|
||||||
</CardContent> |
|
||||||
</Card> |
|
||||||
|
|
||||||
<Card> |
|
||||||
<CardContent className="p-4 flex items-center space-x-4"> |
|
||||||
<Users className="h-8 w-8 text-green-500" /> |
|
||||||
<div> |
|
||||||
<div className="text-sm text-gray-500">Enrolled</div> |
|
||||||
<div className="font-semibold">{courseData.enrolledStudents} students</div> |
|
||||||
</div> |
|
||||||
</CardContent> |
|
||||||
</Card> |
|
||||||
|
|
||||||
<Card> |
|
||||||
<CardContent className="p-4 flex items-center space-x-4"> |
|
||||||
<MessageSquare className="h-8 w-8 text-purple-500" /> |
|
||||||
<div> |
|
||||||
<div className="text-sm text-gray-500">Reviews</div> |
|
||||||
<div className="font-semibold">{courseData.rating} ({courseData.totalReviews})</div> |
|
||||||
</div> |
|
||||||
</CardContent> |
|
||||||
</Card> |
|
||||||
|
|
||||||
<Card> |
|
||||||
<CardContent className="p-4 flex items-center space-x-4"> |
|
||||||
<BookOpen className="h-8 w-8 text-orange-500" /> |
|
||||||
<div> |
|
||||||
<div className="text-sm text-gray-500">Completion</div> |
|
||||||
<div className="font-semibold">{courseData.completionRate}%</div> |
|
||||||
</div> |
|
||||||
</CardContent> |
|
||||||
</Card> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</> |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
export default CourseDetailStats |
|
@ -1,58 +0,0 @@ |
|||||||
'use client'; |
|
||||||
import React from 'react'; |
|
||||||
import { Card, CardContent } from "@/components/ui/card"; |
|
||||||
import { Progress } from "@/components/ui/progress"; |
|
||||||
import CourseDetailHeroSection from './CourseDetailHeroSection'; |
|
||||||
import CourseDetailStats from './CourseDetailStats'; |
|
||||||
import CourseMedia from './CourseMedia'; |
|
||||||
import CourseProgress from './CourseProgress'; |
|
||||||
import TryPDF from './TryPDF'; |
|
||||||
|
|
||||||
const CourseIndividualContentWrapper : React.FC = () => { |
|
||||||
// Dummy course data
|
|
||||||
const courseData = { |
|
||||||
title: "Advanced JavaScript Programming", |
|
||||||
instructor: { |
|
||||||
name: "Dr. Sarah Johnson", |
|
||||||
title: "Senior Software Engineer", |
|
||||||
avatar: "https://placehold.co/600x400" |
|
||||||
}, |
|
||||||
description: "Master modern JavaScript concepts including ES6+, async programming, and advanced frameworks. This comprehensive course covers everything from basic concepts to advanced topics in JavaScript development.", |
|
||||||
category: "Programming", |
|
||||||
duration: "12 weeks", |
|
||||||
enrolledStudents: 1234, |
|
||||||
rating: 4.8, |
|
||||||
totalReviews: 456, |
|
||||||
completionRate: 85, |
|
||||||
lastUpdated: "2024-01-10", |
|
||||||
chapters: [ |
|
||||||
{ title: "Introduction to ES6+", duration: "2.5 hours", isCompleted: true }, |
|
||||||
{ title: "Async Programming", duration: "3 hours", isCompleted: true }, |
|
||||||
{ title: "Advanced DOM Manipulation", duration: "2 hours", isCompleted: false }, |
|
||||||
{ title: "Modern Frameworks Overview", duration: "4 hours", isCompleted: false } |
|
||||||
], |
|
||||||
requirements: [ |
|
||||||
"Basic understanding of JavaScript", |
|
||||||
"Familiarity with web development concepts", |
|
||||||
"Node.js installed on your computer" |
|
||||||
] |
|
||||||
}; |
|
||||||
|
|
||||||
return ( |
|
||||||
<div className="min-h-screen bg-gray-50"> |
|
||||||
{/* Hero Section */} |
|
||||||
<CourseDetailHeroSection courseData={courseData}/> |
|
||||||
|
|
||||||
{/* Course Stats */} |
|
||||||
<CourseDetailStats courseData={courseData}/> |
|
||||||
|
|
||||||
<CourseProgress courseData={courseData}/> |
|
||||||
|
|
||||||
{/* Course Content */} |
|
||||||
<CourseMedia courseData={courseData}/> |
|
||||||
|
|
||||||
</div> |
|
||||||
); |
|
||||||
}; |
|
||||||
|
|
||||||
export default CourseIndividualContentWrapper; |
|
@ -1,39 +0,0 @@ |
|||||||
import { Card, CardContent } from "@/components/ui/card" |
|
||||||
import { Progress } from "@/components/ui/progress" |
|
||||||
import { CourseData } from "@/helpers/apiSchema/course.schema" |
|
||||||
import PDFFlipBook from "./CoursePDFHolder" |
|
||||||
import CustomPDFViewer from "./TryPDF" |
|
||||||
import DiscussionSection from "@/components/elements/DiscussionForm" |
|
||||||
|
|
||||||
const CourseMedia : React.FC<{courseData : CourseData}> = ({courseData}) => { |
|
||||||
return( |
|
||||||
<div className="container mx-auto py-8"> |
|
||||||
<div className="grid md:grid-cols-3 gap-8"> |
|
||||||
{/* Main Content */} |
|
||||||
<div className="md:col-span-2 space-y-8"> |
|
||||||
<Card> |
|
||||||
<CardContent className="p-6"> |
|
||||||
<h2 className="text-xl font-semibold mb-4">Course Content</h2> |
|
||||||
<CustomPDFViewer /> |
|
||||||
</CardContent> |
|
||||||
</Card> |
|
||||||
</div> |
|
||||||
|
|
||||||
|
|
||||||
{/* Sidebar */} |
|
||||||
<div className="space-y-6"> |
|
||||||
<Card> |
|
||||||
<CardContent className="p-6"> |
|
||||||
<h3 className="text-lg font-semibold mb-4">Discussions</h3> |
|
||||||
<DiscussionSection /> |
|
||||||
</CardContent> |
|
||||||
</Card> |
|
||||||
|
|
||||||
|
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
export default CourseMedia |
|
@ -1,149 +0,0 @@ |
|||||||
'use client' |
|
||||||
import React, { forwardRef, useState, useEffect } from 'react'; |
|
||||||
import HTMLFlipBook from 'react-pageflip'; |
|
||||||
import { pdfjs, Document, Page as ReactPdfPage } from 'react-pdf'; |
|
||||||
|
|
||||||
// Configure PDF.js worker globally
|
|
||||||
pdfjs.GlobalWorkerOptions.workerSrc = new URL( |
|
||||||
'pdfjs-dist/build/pdf.worker.min.mjs', |
|
||||||
import.meta.url, |
|
||||||
).toString(); |
|
||||||
|
|
||||||
interface PageProps { |
|
||||||
pageNumber: number; |
|
||||||
width: number; |
|
||||||
} |
|
||||||
|
|
||||||
interface PDFFlipBookProps { |
|
||||||
pdfUrl: string; |
|
||||||
width?: number; |
|
||||||
height?: number; |
|
||||||
numPages?: number; |
|
||||||
} |
|
||||||
|
|
||||||
const DEFAULT_WIDTH = 300; |
|
||||||
const DEFAULT_HEIGHT = 424; |
|
||||||
|
|
||||||
const Page = forwardRef<HTMLDivElement, PageProps>(({ pageNumber, width }, ref) => { |
|
||||||
const [pageError, setPageError] = useState<string | null>(null); |
|
||||||
|
|
||||||
return ( |
|
||||||
<div ref={ref} style={{ background: 'white' }}> |
|
||||||
<ReactPdfPage |
|
||||||
pageNumber={pageNumber} |
|
||||||
width={width} |
|
||||||
loading={ |
|
||||||
<div className="flex items-center justify-center p-4"> |
|
||||||
<div>Loading page {pageNumber}...</div> |
|
||||||
</div> |
|
||||||
} |
|
||||||
error={ |
|
||||||
pageError && ( |
|
||||||
<div className="text-red-500 p-4"> |
|
||||||
Error loading page {pageNumber}: {pageError} |
|
||||||
</div> |
|
||||||
) |
|
||||||
} |
|
||||||
onLoadError={(error) => setPageError(error.message)} |
|
||||||
/> |
|
||||||
</div> |
|
||||||
); |
|
||||||
}); |
|
||||||
|
|
||||||
Page.displayName = 'Page'; |
|
||||||
|
|
||||||
const PDFFlipBook: React.FC<PDFFlipBookProps> = ({ |
|
||||||
pdfUrl, |
|
||||||
width = DEFAULT_WIDTH, |
|
||||||
height = DEFAULT_HEIGHT, |
|
||||||
numPages = 3, |
|
||||||
}) => { |
|
||||||
const [totalPages, setTotalPages] = useState<number>(0); |
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(true); |
|
||||||
const [error, setError] = useState<string | null>(null); |
|
||||||
|
|
||||||
const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => { |
|
||||||
console.log('PDF loaded successfully with', numPages, 'pages'); |
|
||||||
setTotalPages(numPages); |
|
||||||
setIsLoading(false); |
|
||||||
}; |
|
||||||
|
|
||||||
const onDocumentLoadError = (error: Error) => { |
|
||||||
console.error('Error loading PDF:', error); |
|
||||||
setError(error.message); |
|
||||||
setIsLoading(false); |
|
||||||
}; |
|
||||||
|
|
||||||
const LoadingComponent = () => ( |
|
||||||
<div className="flex items-center justify-center p-4"> |
|
||||||
<div className="text-center"> |
|
||||||
<div className="text-lg font-medium">Loading PDF...</div> |
|
||||||
<div className="text-sm text-gray-500">Please wait</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
); |
|
||||||
|
|
||||||
const ErrorComponent = ({ message }: { message: string }) => ( |
|
||||||
<div className="flex items-center justify-center p-4"> |
|
||||||
<div className="text-center text-red-500"> |
|
||||||
<div className="text-lg font-medium">Error loading PDF</div> |
|
||||||
<div className="text-sm">{message}</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
); |
|
||||||
|
|
||||||
if (error) { |
|
||||||
return <ErrorComponent message={error} />; |
|
||||||
} |
|
||||||
|
|
||||||
return ( |
|
||||||
<Document |
|
||||||
file={pdfUrl} |
|
||||||
onLoadSuccess={onDocumentLoadSuccess} |
|
||||||
onLoadError={onDocumentLoadError} |
|
||||||
loading={<LoadingComponent />} |
|
||||||
error={<ErrorComponent message="Failed to load PDF" />} |
|
||||||
options={{ |
|
||||||
cMapUrl: 'cmaps/', |
|
||||||
cMapPacked: true, |
|
||||||
standardFontDataUrl: 'standard_fonts/', |
|
||||||
}} |
|
||||||
> |
|
||||||
{isLoading ? ( |
|
||||||
<LoadingComponent /> |
|
||||||
) : ( |
|
||||||
<HTMLFlipBook |
|
||||||
style={{}} |
|
||||||
width={width} |
|
||||||
height={height} |
|
||||||
size="fixed" |
|
||||||
minWidth={0} |
|
||||||
maxWidth={0} |
|
||||||
minHeight={0} |
|
||||||
maxHeight={0} |
|
||||||
drawShadow={true} |
|
||||||
flippingTime={1000} |
|
||||||
usePortrait={true} |
|
||||||
startZIndex={0} |
|
||||||
autoSize={true} |
|
||||||
maxShadowOpacity={1} |
|
||||||
showCover={false} |
|
||||||
mobileScrollSupport={true} |
|
||||||
className="pdf-flipbook" |
|
||||||
startPage={0} |
|
||||||
swipeDistance={0} |
|
||||||
showPageCorners={true} |
|
||||||
disableFlipByClick={false} |
|
||||||
clickEventForward={true} |
|
||||||
useMouseEvents={true} |
|
||||||
> |
|
||||||
{Array.from(new Array(Math.min(totalPages, numPages)), (_, index) => ( |
|
||||||
<Page key={index + 1} pageNumber={index + 1} width={width} /> |
|
||||||
))} |
|
||||||
</HTMLFlipBook> |
|
||||||
)} |
|
||||||
</Document> |
|
||||||
); |
|
||||||
}; |
|
||||||
|
|
||||||
export default PDFFlipBook; |
|
@ -1,22 +0,0 @@ |
|||||||
import CommonContainer from "@/components/elements/CommonContainer" |
|
||||||
import { Card, CardContent } from "@/components/ui/card" |
|
||||||
import { Progress } from "@/components/ui/progress" |
|
||||||
import { CourseData } from "@/helpers/apiSchema/course.schema" |
|
||||||
|
|
||||||
const CourseProgress :React.FC<{courseData : CourseData}> = ({courseData}) => { |
|
||||||
return( |
|
||||||
<CommonContainer className="!px-0"> |
|
||||||
<Card> |
|
||||||
<CardContent className="py-6"> |
|
||||||
<h3 className="text-lg font-semibold mb-4">Your Progress</h3> |
|
||||||
<Progress value={courseData.completionRate} className="mb-2 " /> |
|
||||||
<p className="text-sm text-gray-500 text-center"> |
|
||||||
{courseData.completionRate}% Complete |
|
||||||
</p> |
|
||||||
</CardContent> |
|
||||||
</Card> |
|
||||||
</CommonContainer> |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
export default CourseProgress |
|
@ -1,97 +0,0 @@ |
|||||||
import { Button } from '@/components/ui/button'; |
|
||||||
import React, { useEffect, useState } from 'react'; |
|
||||||
|
|
||||||
export default function CustomPDFViewer() { |
|
||||||
const [currentPage, setCurrentPage] = useState(1); |
|
||||||
const [totalPages, setTotalPages] = useState(0); |
|
||||||
const [loading, setLoading] = useState(true); |
|
||||||
const [error, setError] = useState<string | null>(null); |
|
||||||
const [pageUrl, setPageUrl] = useState(''); |
|
||||||
|
|
||||||
// Mock function to fetch PDF page as image URL
|
|
||||||
// In a real implementation, you would use a backend service to convert PDF pages to images
|
|
||||||
const fetchPageImage = async (pageNumber : number) => { |
|
||||||
setLoading(true); |
|
||||||
try { |
|
||||||
// Simulating API call delay
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 500)); |
|
||||||
// Using placeholder image for demonstration
|
|
||||||
setPageUrl(`https://placehold.co/600x400?text=Page ${pageNumber}`); |
|
||||||
setTotalPages(5); // Mock total pages
|
|
||||||
setLoading(false); |
|
||||||
} catch (err) { |
|
||||||
setError('Failed to load PDF page'); |
|
||||||
setLoading(false); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
fetchPageImage(currentPage); |
|
||||||
}, [currentPage]); |
|
||||||
|
|
||||||
const goToPreviousPage = () => { |
|
||||||
if (currentPage > 1) { |
|
||||||
setCurrentPage(prev => prev - 1); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
const goToNextPage = () => { |
|
||||||
if (currentPage < totalPages) { |
|
||||||
setCurrentPage(prev => prev + 1); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
return ( |
|
||||||
<div className="flex flex-col items-center w-full max-w-3xl mx-auto p-4"> |
|
||||||
{/* Page Display */} |
|
||||||
<div className="relative w-full h-auto bg-gray-100 rounded-lg shadow-lg mb-4"> |
|
||||||
{loading ? ( |
|
||||||
<div className=" inset-0 flex items-center justify-center min-h-96"> |
|
||||||
<div className="text-lg text-gray-600">Loading page {currentPage}...</div> |
|
||||||
</div> |
|
||||||
) : error ? ( |
|
||||||
<div className="absolute inset-0 flex items-center justify-center"> |
|
||||||
<div className="text-lg text-red-600">{error}</div> |
|
||||||
</div> |
|
||||||
) : ( |
|
||||||
<img
|
|
||||||
src={pageUrl}
|
|
||||||
alt={`Page ${currentPage}`} |
|
||||||
className="w-full h-auto object-contain rounded-lg" |
|
||||||
/> |
|
||||||
)} |
|
||||||
</div> |
|
||||||
|
|
||||||
{/* Navigation Controls */} |
|
||||||
<div className="flex items-center gap-4 mt-6"> |
|
||||||
<Button |
|
||||||
onClick={goToPreviousPage} |
|
||||||
disabled={currentPage <= 1 || loading} |
|
||||||
className={`px-4 py-2 rounded-lg ${ |
|
||||||
currentPage <= 1 || loading |
|
||||||
? 'bg-purple-700/50 cursor-not-allowed' |
|
||||||
: 'bg-purple-700 hover:bg-purple-500 text-white' |
|
||||||
} transition-colors`}
|
|
||||||
> |
|
||||||
Previous |
|
||||||
</Button> |
|
||||||
|
|
||||||
<div className="text-lg font-medium"> |
|
||||||
Page {currentPage} of {totalPages} |
|
||||||
</div> |
|
||||||
|
|
||||||
<Button |
|
||||||
onClick={goToNextPage} |
|
||||||
disabled={currentPage >= totalPages || loading} |
|
||||||
className={`px-4 py-2 rounded-lg ${ |
|
||||||
currentPage >= totalPages || loading |
|
||||||
? 'bg-purple-700/50 cursor-not-allowed' |
|
||||||
: 'bg-purple-700 hover:bg-purple-500 text-white' |
|
||||||
} transition-colors`}
|
|
||||||
> |
|
||||||
Next |
|
||||||
</Button> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
); |
|
||||||
} |
|
Binary file not shown.
@ -1,18 +0,0 @@ |
|||||||
'use client' |
|
||||||
|
|
||||||
import AppContextProvider from "@/helpers/context/AppContextProvider" |
|
||||||
import CommonView from "@/views/CommonView" |
|
||||||
import CourseIndividualContentWrapper from "./_partials/CourseIndividualContentWrapper" |
|
||||||
|
|
||||||
const CourseDetailPage : React.FC = () => { |
|
||||||
return( |
|
||||||
<AppContextProvider> |
|
||||||
<CommonView> |
|
||||||
|
|
||||||
<CourseIndividualContentWrapper /> |
|
||||||
</CommonView> |
|
||||||
</AppContextProvider> |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
export default CourseDetailPage |
|
@ -1,98 +0,0 @@ |
|||||||
// src/components/DiscussionList.tsx
|
|
||||||
"use client"; |
|
||||||
|
|
||||||
import React, { useState } from "react"; |
|
||||||
import { useSearchParams } from "next/navigation"; |
|
||||||
import Image from "next/image"; |
|
||||||
import { Card, CardContent } from "@/components/ui/card"; |
|
||||||
|
|
||||||
const SearchFeature: React.FC = () => { |
|
||||||
const [searchQuery, setSearchQuery] = useState(""); |
|
||||||
const searchParams = useSearchParams(); |
|
||||||
|
|
||||||
const discussions = [ |
|
||||||
{ |
|
||||||
id: 1, |
|
||||||
title: "Introduction to Computer Science", |
|
||||||
description: |
|
||||||
"Learn the basics of programming and computer science concepts", |
|
||||||
publishedDate: "2025-01-10", |
|
||||||
enrolledStudent: 156, |
|
||||||
activeDiscussionCount: 23, |
|
||||||
publishedBy: "Prof. Smith", |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: 2, |
|
||||||
title: "Advanced Mathematics", |
|
||||||
description: "Covering calculus, linear algebra and statistics", |
|
||||||
publishedDate: "2025-01-09", |
|
||||||
enrolledStudent: 89, |
|
||||||
activeDiscussionCount: 15, |
|
||||||
publishedBy: "Dr. Johnson", |
|
||||||
}, |
|
||||||
{ |
|
||||||
id: 3, |
|
||||||
title: "Digital Marketing Fundamentals", |
|
||||||
description: "Understanding modern marketing strategies", |
|
||||||
publishedDate: "2025-01-08", |
|
||||||
enrolledStudent: 234, |
|
||||||
activeDiscussionCount: 45, |
|
||||||
publishedBy: "Prof. Williams", |
|
||||||
}, |
|
||||||
]; |
|
||||||
|
|
||||||
return ( |
|
||||||
<div className="container mx-auto p-6 space-y-6"> |
|
||||||
{/* Discussion Cards */} |
|
||||||
<div className="space-y-4"> |
|
||||||
{discussions.map((discussion) => ( |
|
||||||
<Card |
|
||||||
key={discussion.id} |
|
||||||
className="hover:shadow-lg transition-shadow" |
|
||||||
> |
|
||||||
<CardContent className="p-6 flex gap-4"> |
|
||||||
<div > |
|
||||||
<Image src="https://placehold.jp/400x250.png"alt="placeholder" width={400} height={250} className="w-[400] h-auto rounded-2xl"/> |
|
||||||
</div> |
|
||||||
<div> |
|
||||||
<div className="flex items-start justify-between"> |
|
||||||
<div className="space-y-2"> |
|
||||||
<h3 className="text-xl font-semibold text-purple-700"> |
|
||||||
{discussion.title} |
|
||||||
</h3> |
|
||||||
<p className="text-gray-600">{discussion.description}</p> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div className="mt-4 flex flex-wrap gap-4 text-sm text-gray-500"> |
|
||||||
<span className="flex items-center"> |
|
||||||
<span className="font-medium">Published:</span> |
|
||||||
<span className="ml-1">{discussion.publishedDate}</span> |
|
||||||
</span> |
|
||||||
<span className="flex items-center"> |
|
||||||
<span className="font-medium">Enrolled:</span> |
|
||||||
<span className="ml-1"> |
|
||||||
{discussion.enrolledStudent} students |
|
||||||
</span> |
|
||||||
</span> |
|
||||||
<span className="flex items-center"> |
|
||||||
<span className="font-medium">Active Discussions:</span> |
|
||||||
<span className="ml-1"> |
|
||||||
{discussion.activeDiscussionCount} |
|
||||||
</span> |
|
||||||
</span> |
|
||||||
<span className="flex items-center"> |
|
||||||
<span className="font-medium">Published by:</span> |
|
||||||
<span className="ml-1">{discussion.publishedBy}</span> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</CardContent> |
|
||||||
</Card> |
|
||||||
))} |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
); |
|
||||||
}; |
|
||||||
|
|
||||||
export default SearchFeature; |
|
@ -1,16 +0,0 @@ |
|||||||
'use client' |
|
||||||
import AppContextProvider from "@/helpers/context/AppContextProvider" |
|
||||||
import SearchFeature from "./_partials/SearchFeature" |
|
||||||
import CommonView from "@/views/CommonView" |
|
||||||
|
|
||||||
const SearchFeatureIndexPage : React.FC = () => { |
|
||||||
return( |
|
||||||
<AppContextProvider> |
|
||||||
<CommonView> |
|
||||||
<SearchFeature /> |
|
||||||
</CommonView> |
|
||||||
</AppContextProvider> |
|
||||||
) |
|
||||||
} |
|
||||||
|
|
||||||
export default SearchFeatureIndexPage |
|
@ -1,24 +0,0 @@ |
|||||||
export interface CourseData { |
|
||||||
title: string; |
|
||||||
instructor: { |
|
||||||
name: string; |
|
||||||
title: string; |
|
||||||
avatar: string; |
|
||||||
}; |
|
||||||
description: string; |
|
||||||
category: string; |
|
||||||
duration: string; |
|
||||||
enrolledStudents: number; |
|
||||||
rating: number; |
|
||||||
totalReviews: number; |
|
||||||
completionRate: number; |
|
||||||
lastUpdated: string; |
|
||||||
chapters: Chapter[]; |
|
||||||
requirements: string[]; |
|
||||||
} |
|
||||||
|
|
||||||
interface Chapter { |
|
||||||
title: string; |
|
||||||
duration: string; |
|
||||||
isCompleted: boolean; |
|
||||||
} |
|
Loading…
Reference in new issue