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. 37
      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 {data : AuthorCount} = useSWR(APP_BASE_URL+'' , defaultFetcher);
const { data : TotalCourses } = 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 + '/api/public/stats/total-courses' , defaultFetcher)
console.log(AuthorCount , TotalCourses)
return(
<div className="bg-gray-50 border-t">
<div className="container mx-auto px-4 sm:px-6 lg:px-8 py-16">
@ -19,11 +21,11 @@ const CommunitySection = () => {
</p>
<div className="grid grid-cols-2 gap-4 text-center">
<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>
</div>
<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>
</div>
</div>

@ -5,7 +5,8 @@ import Image from 'next/image';
import useSWR from "swr"
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 (
<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">
@ -40,7 +41,7 @@ const HeroSection: React.FC = () => {
/>
</div>
<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>
</div>
</div>

@ -3,7 +3,7 @@ import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/com
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
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 { routes } from '@/lib/routes';
import { useToast } from '@/hooks/use-toast';
@ -82,8 +82,8 @@ export default function LoginForm() {
},[router])
return (
<div className="flex items-center justify-center min-h-[60vh] border border-purple-700/20 shadow shadow-purple-700/40">
<Card className="w-full max-w-md shadow-lg border-0">
<div className="flex items-center justify-center min-h-[60vh]">
<Card className="w-full max-w-md border border-purple-700/20 shadow shadow-purple-700/40">
<CardHeader className="space-y-3">
<CardTitle className="text-2xl font-bold text-purple-600">Login</CardTitle>
<CardDescription className="text-gray-600">
@ -127,7 +127,14 @@ export default function LoginForm() {
type="submit"
className="w-full h-11 bg-purple-600 hover:bg-purple-700 text-white font-semibold"
>
Login
{
loading ?
<>
<Loader />
Login
</>
: 'Login'
}
</Button>
<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"
const EnrolledCourseTabContent : React.FC = () => {
const { data } = useSWR(APP_BASE_URL + '/' , defaultFetcher);
const { data } = useSWR(APP_BASE_URL + '/api/course/enrolled' , defaultFetcher);
return (
<>

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

@ -20,7 +20,7 @@ const MyCoursesWrapper = () => {
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"
>
Enrolled Course List
Enrolled Course
</TabsTrigger>
<TabsTrigger
value="action-form"

@ -26,12 +26,12 @@ const Header = () => {
<div className="container mx-auto px-4">
<div className="flex items-center justify-between py-4">
{/* 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'/>
<h1 className="brand-logo text-purple-700 font-bold text-2xl">
EDU CONNECT
EduCONNECT
</h1>
</div>
</Link>
<SearchBar />
<div className='flex gap-8'>
<DesktopNav />

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

@ -5,7 +5,8 @@ export const routes = {
DASHBOARD_ROUTE : '/admin/dashboard',
PROFILE_ROUTE : '/user/profile',
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']

Loading…
Cancel
Save