Skip to content

Commit

Permalink
create course,lessons,| display course,lessons
Browse files Browse the repository at this point in the history
  • Loading branch information
syedslegend786 committed May 1, 2023
1 parent 1460079 commit 161add7
Show file tree
Hide file tree
Showing 54 changed files with 2,261 additions and 44 deletions.
11 changes: 10 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,13 @@ NEXTAUTH_SECRET=123l;k12j3lk12j3kl12j3;l12kj3;l12j3
#STRIPE
STRIPE_PUBLISH_KEY=pk_test_51MUo50EhwvoKb8N0k2Q2Adcuxd7ncoDj7Va1qsWmcxbXjuJ1U6xyqHj5xLRkeuedfNNAi08bUNR4n08W0mNvclxs00j1zLJXRN
STRIPE_SECRET_KEY=sk_test_51MUo50EhwvoKb8N0BQGlnofyht55sT6HNfjoZf2ZTcRt0K7PPoJNGMdmALVD8zIzaOzbT7pbVpw5SLk7bGXfkyWg00WDeAeJPe
STRIPE_CREATE_INSTRUCTOR_REDIRECT_URL="http://localhost:3000/instructor/create-callback"
STRIPE_CREATE_INSTRUCTOR_REDIRECT_URL="http://localhost:3000/instructor/create-callback"



#AWS
AWS_SECRET_KEY=UuXHG9zp8Fz6tb8d0bPPG/+ormGh7M0Adh9ENJ5Y
AWS_ACCESS_KEY=AKIAR5X24KRRRJENNTLD
AWS_ARN=arn:aws:iam::132596388963:user/salleh_worker
AWS_LOGIN_PASSWORD=asdzxcASDZXC123123@
AWS_BUCKET_NAME=edumy
16 changes: 16 additions & 0 deletions data/linksData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
interface ILinks {
text: string,
link: string,
}


export const instructorLinksData = [
{
link: "/instructor/course/create",
text: "Create Course"
},
{
link: "/instructor",
text: "Dashboard"
}
] as ILinks[]
28 changes: 28 additions & 0 deletions layouts/InstructorLayout/InstructorLayout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { instructorLinksData } from '@/data/linksData'
import { useRouter } from 'next/router'
import React from 'react'
interface InstructorLayoutProps {
children: React.ReactElement
}


export const InstructorLayout = ({ children }: InstructorLayoutProps) => {
const router = useRouter()
return (
<div>
{
instructorLinksData.map((link, i) => (
<span
className='bg-blue-600 text-white p-2 rounded-md m-3 cursor-pointer'
key={i} onClick={() => router.push(link.link)}
>
{link.text}
</span>
))
}
{children}
</div>
)
}


1 change: 1 addition & 0 deletions layouts/InstructorLayout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './InstructorLayout'
64 changes: 58 additions & 6 deletions layouts/UserPages/UserPages.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import { makeInstructorApi } from '@/services/api/instructor'
import { Button } from '@/ui'
import { handleFrontEndResponse } from '@/utils/apiresponses'
import React from 'react'

import clsx from 'clsx'
import { useSession } from 'next-auth/react'
import Link from 'next/link'
import React, { useState } from 'react'
import { AiOutlineUser } from 'react-icons/ai'
import { FiSettings } from 'react-icons/fi'

interface UserPagesProps {
children: React.ReactElement
}
const instructorRoutes = [{
title: "Create Courses",
to: "/instructor"
}] as { title: string, to: string }[]

const UserPagesLayout = ({ children }: UserPagesProps) => {
const [showMenu, setshowMenu] = useState(false)
const { data: session } = useSession()
const handleBecomeInstructor = async () => {
try {
const data = await makeInstructorApi()
Expand All @@ -18,12 +29,53 @@ const UserPagesLayout = ({ children }: UserPagesProps) => {
}
}
return (
<div>
<div>
<Button onClick={handleBecomeInstructor} text='Become Instructor' />
<div className='p-5'>
<div className='flex justify-between'>
<div>
<Button text='Home' />
</div>
<div className='flex items-center gap-x-5'>
{
session?.user &&
<div className='flex items-center'>
<AiOutlineUser size={20} />
{
session?.user?.name &&
<h1 className='text-sm font-semibold text-gray-600'>{session?.user?.name}</h1>
}
</div>
}
{
session?.user ?
<Button text='Logout' />
:
<Button text='Login' />
}
<div className=' relative'>
<FiSettings onClick={() => { setshowMenu(!showMenu) }} className='cursor-pointer' size={20} />
<div
className={clsx(
'hidden bg-gray-500 shadow-md p-2 right-0 h-[200px] w-[200px]',
{
"!absolute !inline z-10": showMenu
}
)}>
{
session?.user.roles.includes("instructor") ?
instructorRoutes.map((r, ri) => (
<Link href={r.to} key={ri} className='hover:bg-green-600 hover:text-white p-2 text-white cursor-pointer text-xs'>{r.title}</Link>
))
:
<h1 onClick={handleBecomeInstructor}
className='hover:bg-green-600 !w-full hover:text-white p-2 text-white cursor-pointer text-xs'
>Become Instructor</h1>
}
</div>
</div>
</div>
</div>
{children}
</div>
</div >
)
}

Expand Down
3 changes: 2 additions & 1 deletion layouts/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './UserPages'
export * from './UserPages'
export * from './InstructorLayout'
14 changes: 12 additions & 2 deletions lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,18 @@ export const authOptions: AuthOptions = {
},
secret: process.env.NEXTAUTH_SECRET as string,
callbacks: {
jwt: ({ token, user }) => {
if (user) {
jwt: async ({ token, user }) => {
const dbUser = await db.user.findFirst({
where: {
email: token.email
}
})
if (dbUser) {
token.id = dbUser.id
token.name = dbUser.name
token.email = dbUser.email
token.roles = dbUser.roles
} else {
token.id = user.id
token.name = user.name
token.email = user.email
Expand Down
12 changes: 12 additions & 0 deletions lib/aws.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import AWS from 'aws-sdk'

AWS.config.update({
apiVersion: "us-east-1",
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY as string,
secretAccessKey: process.env.AWS_SECRET_KEY as string
}
})


export const S3 = new AWS.S3()
16 changes: 13 additions & 3 deletions middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export default withAuth(
async function middleware(req) {
const token = await getToken({ req })
const isAuth = !!token
console.log("isauth===>",isAuth)
const isAuthPage =
req.nextUrl.pathname.startsWith("/auth/login") ||
req.nextUrl.pathname.startsWith("/auth/register")
Expand All @@ -18,29 +17,40 @@ export default withAuth(
return null
}


if (!isAuth) {
let from = req.nextUrl.pathname;
if (req.nextUrl.search) {
from += req.nextUrl.search;
}

return NextResponse.redirect(
new URL(`/auth/login?from=${encodeURIComponent(from)}`, req.url)
);
}

const isInstructorPage =
req.nextUrl.pathname.startsWith("/instructor")

if (isInstructorPage) {
if (isAuth && !token.roles.includes("instructor")) {
return NextResponse.redirect(new URL("/", req.url))
}
return null
}
},
{
callbacks: {
async authorized() {
// This is a work-around for handling redirect on auth pages.
// We return true here so that the middleware function above
// is always called.

return true
},
},
}
)

export const config = {
matcher: ["/:path*", "/auth/login", "/auth/register"],
matcher: ["/", "/auth/login", "/auth/register", "/instructor"],
}
27 changes: 27 additions & 0 deletions molecules/CourseLessonsList/CourseLessonsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Lesson } from '@prisma/client'
import React from 'react'
import { SingleLessonItem } from '../SingleLessonItem'
interface CourseLessonsListProps {
lessons: Lesson[]
onPreviewClicked?: (video: string) => void
}
export const CourseLessonsList = ({ lessons, onPreviewClicked }: CourseLessonsListProps) => {
const onClickItem = (video: string) => {
onPreviewClicked && onPreviewClicked(video)
}
return (
<div className='space-y-2 p-2'>
<h1 className='font-bold text-xl'>{lessons.length} Lessons</h1>
{
lessons.map((l, li) => (
<SingleLessonItem onClick={() => {
if(l.free_preview){
onClickItem(l.video)
}
}
} index={li} lesson={l} key={li} />
))
}
</div>
)
}
1 change: 1 addition & 0 deletions molecules/CourseLessonsList/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './CourseLessonsList'
24 changes: 24 additions & 0 deletions molecules/InstructorCourseCard/InstructorCourseCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react'
import { Course } from '@prisma/client'
import Image from 'next/image'
import { useRouter } from 'next/router'
interface CourseCardProps extends Course {

}
export const CourseCard = ({ category, description, id, imagePreview, name, paid, price, userId }: CourseCardProps) => {
const router = useRouter()
return (
<div onClick={() => { router.push(`/instructor/course/${id}`) }} className='cursor-pointer relative border p-2 shadow-md rounded-[16px] flex items-center gap-x-4'>
<div className='relative w-[100px] h-[100px] overflow-hidden'>
<Image quality={100} src={imagePreview} alt='' className='object-contain' fill />
</div>
<div>
<h1 className='text-blue-700 text-xl font-bold'>{name}</h1>
<p>{description}</p>
<h1>type:{paid}</h1>
<h1>price: {price}</h1>
<h1>category:{category}</h1>
</div>
</div>
)
}
1 change: 1 addition & 0 deletions molecules/InstructorCourseCard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './InstructorCourseCard'
74 changes: 74 additions & 0 deletions molecules/SingleCourseJumboTron/SingleCourseJumboTron.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Course } from '@prisma/client'
import Image from 'next/image'
import React, { useState } from 'react'
import { MdOutlineLanguage, MdSubtitles } from 'react-icons/md'
import ReactPlayer from 'react-player'
interface SingleCourseJumboTronProps {
course: (Course & {
Lesson: {
video: string;
}[];
user: {
id: string;
name: string | null;
};
})

onClickPreview?: (video: string) => void
}
export const SingleCourseJumboTron = ({
course: {
category,
description,
id,
imagePreview,
name,
paid,
price,
userId,
user,
Lesson
},
onClickPreview
}: SingleCourseJumboTronProps) => {
const [allowPlayer, setallowPlayer] = React.useState(false)
React.useEffect(() => {
if (typeof window !== "undefined") {
setallowPlayer(true)
}
}, [])
return (
<div className='min-h-[400px] bg-[#1C1D1F] flex gap-x-5 pl-28 pr-10 py-10'>
<div className='flex-[0.7] flex justify-center flex-col flex-shrink-0 '>
<h1 className='font-bold text-white text-4xl'>{name}</h1>
<p className='text-white text-xl mt-5 line-clamp-3'>{description}</p>
<div className='mt-4 text-white text-xs'>Created by <span className='text-[#89A4F5] underline underline-offset-2'>{user.name}</span></div>
<div className='flex items-center gap-x-3 mt-3'>
<div className='flex items-center gap-x-1'>
<MdOutlineLanguage className='!text-white' color='white' size={20} /><span className='text-white text-xs'>English</span>
</div>
<div className='flex items-center gap-x-1'>
<MdSubtitles className='!text-white' color='white' size={20} /><span className='text-white text-xs'>English [Auto]</span>
</div>
</div>
</div>
<div className='flex-[0.3] float-right flex items-center justify-center'>
{
(Lesson.length > 0 && allowPlayer) &&
< div className='w-[100%] aspect-video cursor-pointer' onClick={() => {
onClickPreview && onClickPreview(Lesson[0].video)
}}>
<ReactPlayer style={{
pointerEvents: "none"
}} playing={false} light={imagePreview} url={Lesson[0].video} width={"100%"} height={"100%"} />
</div>
}{
(Lesson.length === 0) &&
<div className='relative w-[100%] aspect-video'>
<Image src={imagePreview} alt='' fill className='object-cover' />
</div>
}
</div>
</div >
)
}
1 change: 1 addition & 0 deletions molecules/SingleCourseJumboTron/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './SingleCourseJumboTron'
Loading

0 comments on commit 161add7

Please sign in to comment.