ayush 6 months ago
parent 716e5cffb4
commit 4b622f15c3
  1. 10
      frontend/edu-connect/src/app/_partials/CommunitySection.tsx
  2. 5
      frontend/edu-connect/src/app/_partials/HeroSection.tsx
  3. 15
      frontend/edu-connect/src/app/auth/login/_partials/LoginForm.tsx
  4. 46
      frontend/edu-connect/src/app/courses/page.tsx
  5. 2
      frontend/edu-connect/src/app/my-courses/_partials/EnrolledCourseList.tsx
  6. 48
      frontend/edu-connect/src/app/my-courses/_partials/MyCoursesListTabContent.tsx
  7. 2
      frontend/edu-connect/src/app/my-courses/_partials/myCoursesTabWrapper.tsx
  8. 6
      frontend/edu-connect/src/components/common/Header/header.tsx
  9. 39
      frontend/edu-connect/src/components/elements/CourseCard.tsx
  10. 3
      frontend/edu-connect/src/lib/routes.ts

@ -6,8 +6,10 @@ import useSWR from 'swr'
const CommunitySection = () => { const CommunitySection = () => {
const {data : AuthorCount} = useSWR(APP_BASE_URL+'' , defaultFetcher); const {data : AuthorCount} = useSWR(APP_BASE_URL+'/api/public/stats/total-authors' , defaultFetcher);
const { data : TotalCourses } = useSWR(APP_BASE_URL + '' , defaultFetcher) const { data : TotalCourses } = useSWR(APP_BASE_URL + '/api/public/stats/total-courses' , defaultFetcher)
console.log(AuthorCount , TotalCourses)
return( return(
<div className="bg-gray-50 border-t"> <div className="bg-gray-50 border-t">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-16"> <div className="container mx-auto px-4 sm:px-6 lg:px-8 py-16">
@ -19,11 +21,11 @@ const CommunitySection = () => {
</p> </p>
<div className="grid grid-cols-2 gap-4 text-center"> <div className="grid grid-cols-2 gap-4 text-center">
<div className="bg-white p-4 rounded-lg shadow-sm border border-purple-700"> <div className="bg-white p-4 rounded-lg shadow-sm border border-purple-700">
<p className="text-2xl font-bold text-purple-600">{}+</p> <p className="text-2xl font-bold text-purple-600">{AuthorCount?.totalAuthors}+</p>
<p className="text-gray-600">Expert Contributors</p> <p className="text-gray-600">Expert Contributors</p>
</div> </div>
<div className="bg-white p-4 rounded-lg shadow-sm border border-purple-700"> <div className="bg-white p-4 rounded-lg shadow-sm border border-purple-700">
<p className="text-2xl font-bold text-purple-600">1000+</p> <p className="text-2xl font-bold text-purple-600">{TotalCourses?.totalCourses}+</p>
<p className="text-gray-600">Research-Based Courses</p> <p className="text-gray-600">Research-Based Courses</p>
</div> </div>
</div> </div>

@ -5,7 +5,8 @@ import Image from 'next/image';
import useSWR from "swr" import useSWR from "swr"
const HeroSection: React.FC = () => { const HeroSection: React.FC = () => {
const {data : TotalUserCount } = useSWR(APP_BASE_URL + '/api/user/count' , defaultFetcher) const {data : TotalUserCount } = useSWR(APP_BASE_URL + '/api/public/stats/total-users' , defaultFetcher)
console.log(TotalUserCount)
return ( return (
<div className="bg-gradient-to-br from-purple-900 to-indigo-900 text-white"> <div className="bg-gradient-to-br from-purple-900 to-indigo-900 text-white">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-24"> <div className="container mx-auto px-4 sm:px-6 lg:px-8 py-24">
@ -40,7 +41,7 @@ const HeroSection: React.FC = () => {
/> />
</div> </div>
<div className="absolute -bottom-4 -right-4 bg-purple-700 text-white p-4 rounded-lg shadow-lg"> <div className="absolute -bottom-4 -right-4 bg-purple-700 text-white p-4 rounded-lg shadow-lg">
<p className="font-bold">{}+</p> <p className="font-bold">{TotalUserCount?.totalUsers}+</p>
<p className="text-sm">Active Learners</p> <p className="text-sm">Active Learners</p>
</div> </div>
</div> </div>

@ -3,7 +3,7 @@ import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/com
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { EyeIcon, EyeOffIcon } from 'lucide-react'; import { EyeIcon, EyeOffIcon, Loader } from 'lucide-react';
import Link from 'next/link'; import Link from 'next/link';
import { routes } from '@/lib/routes'; import { routes } from '@/lib/routes';
import { useToast } from '@/hooks/use-toast'; import { useToast } from '@/hooks/use-toast';
@ -82,8 +82,8 @@ export default function LoginForm() {
},[router]) },[router])
return ( return (
<div className="flex items-center justify-center min-h-[60vh] border border-purple-700/20 shadow shadow-purple-700/40"> <div className="flex items-center justify-center min-h-[60vh]">
<Card className="w-full max-w-md shadow-lg border-0"> <Card className="w-full max-w-md border border-purple-700/20 shadow shadow-purple-700/40">
<CardHeader className="space-y-3"> <CardHeader className="space-y-3">
<CardTitle className="text-2xl font-bold text-purple-600">Login</CardTitle> <CardTitle className="text-2xl font-bold text-purple-600">Login</CardTitle>
<CardDescription className="text-gray-600"> <CardDescription className="text-gray-600">
@ -127,7 +127,14 @@ export default function LoginForm() {
type="submit" type="submit"
className="w-full h-11 bg-purple-600 hover:bg-purple-700 text-white font-semibold" className="w-full h-11 bg-purple-600 hover:bg-purple-700 text-white font-semibold"
> >
Login {
loading ?
<>
<Loader />
Login
</>
: 'Login'
}
</Button> </Button>
<div className="text-center text-sm text-gray-600"> <div className="text-center text-sm text-gray-600">

@ -0,0 +1,46 @@
'use client'
import { PageHeading } from "@/components/(dashboard)/ui/title"
import CommonContainer from "@/components/elements/CommonContainer"
import CourseCard from "@/components/elements/CourseCard"
import AppContextProvider from "@/helpers/context/AppContextProvider"
import { defaultFetcher } from "@/helpers/fetch.helper"
import { APP_BASE_URL } from "@/utils/constants"
import CommonView from "@/views/CommonView"
import React from "react"
import useSWR from "swr"
const AllCourseList : React.FC = () => {
const { data } = useSWR(APP_BASE_URL + '/api/course/listAll' , defaultFetcher)
console.log(data)
return(
<AppContextProvider>
<CommonView>
<CommonContainer>
<PageHeading>All Courses</PageHeading>
<div className="grid grid-cols-4 gap-4 mt-8">
{
data?.data?.length && data?.data?.map((course) => {
return(
<CourseCard
id={course?.id}
image={APP_BASE_URL + course?.coverImage}
title={course?.name}
category={course?.category?.name}
instructor={{
image : APP_BASE_URL + course?.author?.pfpFilename ,
name :course?.author?.firstName
}}
/>
)
})
}
</div>
</CommonContainer>
</CommonView>
</AppContextProvider>
)
}
export default AllCourseList

@ -5,7 +5,7 @@ import Image from "next/image"
import useSWR from "swr" import useSWR from "swr"
const EnrolledCourseTabContent : React.FC = () => { const EnrolledCourseTabContent : React.FC = () => {
const { data } = useSWR(APP_BASE_URL + '/' , defaultFetcher); const { data } = useSWR(APP_BASE_URL + '/api/course/enrolled' , defaultFetcher);
return ( return (
<> <>

@ -1,3 +1,4 @@
import { Badge } from "@/components/ui/badge"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { defaultFetcher } from "@/helpers/fetch.helper" import { defaultFetcher } from "@/helpers/fetch.helper"
import { APP_BASE_URL } from "@/utils/constants" import { APP_BASE_URL } from "@/utils/constants"
@ -5,7 +6,8 @@ import Image from "next/image"
import useSWR from "swr" import useSWR from "swr"
const MyCoursesListTabContent = () => { const MyCoursesListTabContent = () => {
const { data } = useSWR(APP_BASE_URL + '/' , defaultFetcher); const { data } = useSWR(APP_BASE_URL + '/api/course/myCourses' , defaultFetcher);
console.log(data)
return ( return (
<> <>
@ -20,7 +22,7 @@ const MyCoursesListTabContent = () => {
<> <>
<Card <Card
key={course.id} key={course.id}
className="hover:shadow-lg transition-shadow" className="hover:shadow-lg transition-shadow mb-4"
> >
<CardContent className="p-6 flex gap-4"> <CardContent className="p-6 flex gap-4">
<div > <div >
@ -30,7 +32,7 @@ const MyCoursesListTabContent = () => {
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div className="space-y-2"> <div className="space-y-2">
<h3 className="text-xl font-semibold text-purple-700"> <h3 className="text-xl font-semibold text-purple-700">
{course.title} {course.name}
</h3> </h3>
<p className="text-gray-600">{course.description}</p> <p className="text-gray-600">{course.description}</p>
</div> </div>
@ -38,25 +40,35 @@ const MyCoursesListTabContent = () => {
<div className="mt-4 flex flex-wrap gap-4 text-sm text-gray-500"> <div className="mt-4 flex flex-wrap gap-4 text-sm text-gray-500">
<span className="flex items-center"> <span className="flex items-center">
<span className="font-medium">Published:</span> <span className="ml-1">{
<span className="ml-1">{course.publishedDate}</span> course.publishedDate == '1'
</span> ? <Badge variant={'success'}>Published</Badge>
<span className="flex items-center"> : course.publishedDate == '1'
<span className="font-medium">Enrolled:</span> ? <Badge variant={'default'}>Pending</Badge>
<span className="ml-1"> : <Badge variant={'destructive'}>Rejected</Badge>
{course.enrolledStudent} students }
</span> </span>
</span> </span>
</div>
<div className="mt-2 flex gap-4">
<span className="flex items-center"> <span className="flex items-center">
<span className="font-medium">Active Discussions:</span> <span className="font-medium">Enrolled:</span>
<span className="ml-1"> <span className="ml-1">
{course.activeDiscussionCount} {course.totalEnrolled ?? 0} students
</span>
</span>
<span className="flex items-center">
<span className="font-medium"></span>
<span className="ml-1">
{course.activeDiscussionCount ?? 0} discussions
</span>
</span>
<span className="flex items-center">
<span className="font-medium">Published by:</span>
<span className="ml-1">{course?.author?.firstName ?? '-'}</span>
</span> </span>
</span>
<span className="flex items-center">
<span className="font-medium">Published by:</span>
<span className="ml-1">{course.publishedBy}</span>
</span>
</div> </div>
</div> </div>
</CardContent> </CardContent>

@ -20,7 +20,7 @@ const MyCoursesWrapper = () => {
value="enrolled" value="enrolled"
className="justify-start w-full px-3 py-2 text-left data-[state=active]:bg-gray-50 data-[state=active]:border data-[state=active]:border-purple-700/50 rounded-md" className="justify-start w-full px-3 py-2 text-left data-[state=active]:bg-gray-50 data-[state=active]:border data-[state=active]:border-purple-700/50 rounded-md"
> >
Enrolled Course List Enrolled Course
</TabsTrigger> </TabsTrigger>
<TabsTrigger <TabsTrigger
value="action-form" value="action-form"

@ -26,12 +26,12 @@ const Header = () => {
<div className="container mx-auto px-4"> <div className="container mx-auto px-4">
<div className="flex items-center justify-between py-4"> <div className="flex items-center justify-between py-4">
{/* Logo */} {/* Logo */}
<div className='flex gap-2 items-center'> <Link href={routes.INDEX_PAGE} className='flex gap-2 items-center'>
<Image src={BrandLogo} width={50} height={30} alt={'brand_logo'} className='bg-blend-darken'/> <Image src={BrandLogo} width={50} height={30} alt={'brand_logo'} className='bg-blend-darken'/>
<h1 className="brand-logo text-purple-700 font-bold text-2xl"> <h1 className="brand-logo text-purple-700 font-bold text-2xl">
EDU CONNECT EduCONNECT
</h1> </h1>
</div> </Link>
<SearchBar /> <SearchBar />
<div className='flex gap-8'> <div className='flex gap-8'>
<DesktopNav /> <DesktopNav />

@ -8,10 +8,10 @@ interface CourseInterface {
id : string , id : string ,
image :string | null image :string | null
title : string title : string
category : string category ?: string
lessons : string lessons ?: string
duration : string duration? : string
instructor : { instructor ?: {
image : string image : string
name : string name : string
} }
@ -28,20 +28,23 @@ const CourseCard : React.FC<CourseInterface> = ({
}) => { }) => {
return( return(
<Card key={id} className="overflow-hidden"> <Card key={id} className="overflow-hidden">
<div className="relative"> <Link href={routes?.COURSE_INDIVIDUAL_PAGE.replace(':id',id)}>
<img <div className="relative">
src={image!}
alt={title} <img
className="w-full h-48 object-cover" src={image!}
/> alt={title}
<span className="absolute top-4 left-4 bg-purple-700/90 text-white px-3 py-1 rounded-full text-sm"> className="w-full h-48 object-cover"
{category} />
</span> <span className="absolute top-4 left-4 bg-purple-700/90 text-white px-3 py-1 rounded-full text-sm">
{/* <button className="absolute top-4 right-4 p-2 bg-white/90 rounded-full hover:bg-white"> {category}
<Heart className="w-4 h-4 fill-red-500 text-red-500" /> </span>
</button> */} {/* <button className="absolute top-4 right-4 p-2 bg-white/90 rounded-full hover:bg-white">
</div> <Heart className="w-4 h-4 fill-red-500 text-red-500" />
</button> */}
</div>
</Link>
<CardContent className="p-6"> <CardContent className="p-6">
<div className="flex gap-4 text-sm text-gray-600 mb-3"> <div className="flex gap-4 text-sm text-gray-600 mb-3">
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">

@ -5,7 +5,8 @@ export const routes = {
DASHBOARD_ROUTE : '/admin/dashboard', DASHBOARD_ROUTE : '/admin/dashboard',
PROFILE_ROUTE : '/user/profile', PROFILE_ROUTE : '/user/profile',
MY_COURSES_INDEX : '/my-courses', MY_COURSES_INDEX : '/my-courses',
USER_INDEX_PAGE : '/admin/users' USER_INDEX_PAGE : '/admin/users',
COURSE_INDIVIDUAL_PAGE : '/course/show/:id'
} }
export const privateRoutes = ['/user/profile'] export const privateRoutes = ['/user/profile']

Loading…
Cancel
Save