├── .npmrc ├── tsconfig.json ├── apps ├── api │ ├── types │ │ ├── razorpay.d.ts │ │ └── custom.d.ts │ ├── nodemon.json │ ├── config │ │ ├── razorpay.ts │ │ ├── database.ts │ │ └── cloudinary.ts │ ├── models │ │ ├── sub-section-model.ts │ │ ├── section-model.ts │ │ ├── category-model.ts │ │ ├── profile-model.ts │ │ ├── course-progress-model.ts │ │ ├── rating-and-review-model.ts │ │ ├── otp-model.ts │ │ ├── course-model.ts │ │ └── user-model.ts │ ├── tsup.config.ts │ ├── utils │ │ ├── sec-to-duration.ts │ │ ├── image-uploader.ts │ │ └── mail-sender.ts │ ├── tsconfig.json │ ├── .gitignore │ ├── routes │ │ ├── contact-us-route.ts │ │ ├── payments-route.ts │ │ ├── profile-route.ts │ │ └── user-route.ts │ ├── middlewares │ │ ├── demo-middlewares.ts │ │ └── auth-middlewares.ts │ ├── package.json │ ├── controllers │ │ └── contact-us-controller.ts │ ├── mail │ │ └── templates │ │ │ ├── email-verification-mail-template.ts │ │ │ ├── password-update-mail-template.ts │ │ │ ├── payment-success-mail-template.ts │ │ │ └── course-enrollment-mail-template.ts │ └── index.ts └── web │ ├── types │ ├── category.ts │ ├── profile.ts │ └── course.ts │ ├── public │ ├── assets │ │ ├── banner.mp4 │ │ ├── login.webp │ │ ├── signup.webp │ │ ├── timeline.png │ │ ├── aboutus1.webp │ │ ├── aboutus2.webp │ │ ├── aboutus3.webp │ │ ├── founding-story.png │ │ └── instructor-pic.png │ ├── readme │ │ └── schema.png │ └── fonts │ │ └── GeistMonoVF.woff │ ├── eslint.config.js │ ├── postcss.config.mjs │ ├── lib │ └── utils.ts │ ├── app │ ├── (auth) │ │ ├── layout.tsx │ │ ├── login │ │ │ └── page.tsx │ │ └── signup │ │ │ └── page.tsx │ ├── (dashboard) │ │ ├── dashboard │ │ │ ├── edit-course │ │ │ │ └── [courseId] │ │ │ │ │ └── page.tsx │ │ │ ├── instructor │ │ │ │ └── page.tsx │ │ │ ├── add-course │ │ │ │ └── page.tsx │ │ │ ├── cart │ │ │ │ └── page.tsx │ │ │ └── my-courses │ │ │ │ └── page.tsx │ │ └── layout.tsx │ ├── loading.tsx │ ├── (course-view) │ │ ├── layout.tsx │ │ └── view-course │ │ │ └── [courseId] │ │ │ └── section │ │ │ └── [sectionId] │ │ │ └── sub-section │ │ │ └── [subsectionId] │ │ │ └── page.tsx │ ├── about │ │ └── page.tsx │ ├── not-found.tsx │ ├── layout.tsx │ ├── contact │ │ └── page.tsx │ └── page.tsx │ ├── data │ ├── constants.ts │ ├── navbar-links.ts │ ├── dashboard-links.ts │ └── footer-links.ts │ ├── components │ ├── home │ │ ├── highlighted-text.tsx │ │ ├── instructor-section.tsx │ │ └── code-blocks.tsx │ ├── ui │ │ ├── skeleton.tsx │ │ ├── arrow-right.tsx │ │ ├── label.tsx │ │ ├── textarea.tsx │ │ ├── separator.tsx │ │ ├── progress.tsx │ │ ├── input.tsx │ │ ├── toaster.tsx │ │ ├── theme-button.tsx │ │ ├── checkbox.tsx │ │ ├── badge.tsx │ │ ├── rating-stars.tsx │ │ ├── radio-group.tsx │ │ ├── avatar.tsx │ │ ├── alert.tsx │ │ ├── scroll-area.tsx │ │ ├── button.tsx │ │ ├── tabs.tsx │ │ ├── card.tsx │ │ ├── accordion.tsx │ │ ├── input-otp.tsx │ │ ├── hero-badge.tsx │ │ ├── table.tsx │ │ └── parallax-floating.tsx │ ├── theme-provider.tsx │ ├── auth │ │ ├── open-route.tsx │ │ ├── private-route.tsx │ │ ├── instructor-route.tsx │ │ ├── student-route.tsx │ │ ├── login-form.tsx │ │ └── auth-template.tsx │ ├── common │ │ ├── navbar │ │ │ ├── list-item.tsx │ │ │ ├── mobile-menu.tsx │ │ │ └── desktop-menu.tsx │ │ ├── mode-toggle.tsx │ │ ├── course-slider.tsx │ │ └── course-card.tsx │ ├── about │ │ ├── cta.tsx │ │ ├── hero-about.tsx │ │ ├── statistics.tsx │ │ └── faq.tsx │ └── dashboard │ │ ├── add-course │ │ ├── course-builder │ │ │ ├── confirmation-modal.tsx │ │ │ ├── sub-section-view.tsx │ │ │ └── section-view.tsx │ │ ├── course-information │ │ │ ├── chip-input.tsx │ │ │ └── upload.tsx │ │ └── render-steps.tsx │ │ ├── instructor │ │ └── dashboard-chart.tsx │ │ ├── edit-course │ │ └── edit-course.tsx │ │ ├── cart │ │ ├── cart-summarty.tsx │ │ └── cart-items.tsx │ │ └── course-tips.tsx │ ├── utils │ ├── api-connector.ts │ ├── avg-rating.ts │ ├── format-date.ts │ └── apis.ts │ ├── components.json │ ├── .prettierignore │ ├── next.config.mjs │ ├── .gitignore │ ├── tsconfig.json │ ├── services │ └── catalog-service.ts │ ├── store │ ├── use-course-store.tsx │ ├── use-auth-store.tsx │ ├── use-view-course-store.tsx │ ├── use-profile-store.tsx │ └── use-cart-store.tsx │ ├── hooks │ └── use-mouse-position-ref.tsx │ ├── README.md │ ├── package.json │ └── tailwind.config.ts ├── packages ├── eslint-config │ ├── README.md │ ├── base.js │ ├── package.json │ ├── react-internal.js │ └── next.js └── typescript-config │ ├── README.md │ ├── package.json │ ├── react-library.json │ ├── nextjs.json │ └── base.json ├── pnpm-workspace.yaml ├── .github ├── dependabot.yml └── PULL_REQUEST_TEMPLATE.md ├── .eslintrc.js ├── .gitignore ├── turbo.json ├── prettier.config.cjs └── package.json /.npmrc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@workspace/typescript-config/base.json" 3 | } 4 | 5 | -------------------------------------------------------------------------------- /apps/api/types/razorpay.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | Razorpay: any // or a more specific type if available 3 | } 4 | -------------------------------------------------------------------------------- /packages/eslint-config/README.md: -------------------------------------------------------------------------------- 1 | # `@workspace/eslint-config` 2 | 3 | Shared eslint configuration for the workspace. 4 | -------------------------------------------------------------------------------- /apps/web/types/category.ts: -------------------------------------------------------------------------------- 1 | export interface Category { 2 | _id: string 3 | name: string 4 | description: string 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/public/assets/banner.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/assets/banner.mp4 -------------------------------------------------------------------------------- /apps/web/public/assets/login.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/assets/login.webp -------------------------------------------------------------------------------- /apps/web/public/assets/signup.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/assets/signup.webp -------------------------------------------------------------------------------- /apps/web/public/assets/timeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/assets/timeline.png -------------------------------------------------------------------------------- /apps/web/public/readme/schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/readme/schema.png -------------------------------------------------------------------------------- /packages/typescript-config/README.md: -------------------------------------------------------------------------------- 1 | # `@workspace/typescript-config` 2 | 3 | Shared typescript configuration for the workspace. 4 | -------------------------------------------------------------------------------- /apps/web/public/assets/aboutus1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/assets/aboutus1.webp -------------------------------------------------------------------------------- /apps/web/public/assets/aboutus2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/assets/aboutus2.webp -------------------------------------------------------------------------------- /apps/web/public/assets/aboutus3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/assets/aboutus3.webp -------------------------------------------------------------------------------- /apps/web/public/fonts/GeistMonoVF.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/fonts/GeistMonoVF.woff -------------------------------------------------------------------------------- /apps/web/public/assets/founding-story.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/assets/founding-story.png -------------------------------------------------------------------------------- /apps/web/public/assets/instructor-pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AayushBharti/Zenith-Academy/HEAD/apps/web/public/assets/instructor-pic.png -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - apps/* 3 | - packages/* 4 | 5 | onlyBuiltDependencies: 6 | - "@tailwindcss/oxide" 7 | - esbuild 8 | - sharp 9 | -------------------------------------------------------------------------------- /apps/api/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": [","], 3 | "ext": ".ts,.js", 4 | "exec": "tsup --onSuccess \"node dist/index.js\"", 5 | "ignore": ["./**/*.spec.ts", "dist/*"] 6 | } 7 | -------------------------------------------------------------------------------- /apps/web/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { nextJsConfig } from "@workspace/eslint-config/next-js"; 2 | 3 | /** @type {import("eslint").Linter.Config} */ 4 | export default nextJsConfig; 5 | -------------------------------------------------------------------------------- /apps/web/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | } 7 | 8 | export default config 9 | -------------------------------------------------------------------------------- /apps/web/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /apps/api/config/razorpay.ts: -------------------------------------------------------------------------------- 1 | import Razorpay from "razorpay" 2 | 3 | export const instance = new Razorpay({ 4 | key_id: process.env.RAZORPAY_KEY as string, 5 | key_secret: process.env.RAZORPAY_SECRET as string, 6 | }) 7 | -------------------------------------------------------------------------------- /apps/web/app/(auth)/layout.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | const Layout = ({ children }: { children: React.ReactNode }) => { 4 | return
{children}
5 | } 6 | 7 | export default Layout 8 | -------------------------------------------------------------------------------- /packages/typescript-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@workspace/typescript-config", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "PROPRIETARY", 6 | "publishConfig": { 7 | "access": "public" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/typescript-config/react-library.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "React Library", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "jsx": "react-jsx", 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/data/constants.ts: -------------------------------------------------------------------------------- 1 | export const ACCOUNT_TYPE = { 2 | STUDENT: "Student", 3 | INSTRUCTOR: "Instructor", 4 | ADMIN: "Admin", 5 | } 6 | 7 | export const COURSE_STATUS = { 8 | DRAFT: "Draft", 9 | PUBLISHED: "Published", 10 | } 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Enable version updates for npm 4 | - package-ecosystem: "npm" 5 | # Look for `package.json` and `lock` files in the `root` directory 6 | directory: "/" 7 | # Check the npm registry for updates every day (weekdays) 8 | schedule: 9 | interval: "weekly" 10 | -------------------------------------------------------------------------------- /apps/api/models/sub-section-model.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose" 2 | 3 | const SubSectionSchema = new mongoose.Schema({ 4 | title: { type: String }, 5 | timeDuration: { type: String }, 6 | description: { type: String }, 7 | videoUrl: { type: String }, 8 | }) 9 | 10 | export default mongoose.model("SubSection", SubSectionSchema) 11 | -------------------------------------------------------------------------------- /apps/web/data/navbar-links.ts: -------------------------------------------------------------------------------- 1 | export const NavbarLinks = [ 2 | { 3 | title: "Home", 4 | path: "/", 5 | }, 6 | { 7 | title: "Catalog", 8 | path: "/catalog", 9 | }, 10 | { 11 | title: "About Us", 12 | path: "/about", 13 | }, 14 | { 15 | title: "Contact Us", 16 | path: "/contact", 17 | }, 18 | ] 19 | -------------------------------------------------------------------------------- /apps/api/config/database.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose" 2 | 3 | export const DBconnect = async () => { 4 | try { 5 | await mongoose.connect(process.env.MONGODB_URL as string) 6 | console.log("DB Connected Successfully") 7 | } catch (error) { 8 | console.error("DB Connection Failed:", error) 9 | process.exit(1) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/components/home/highlighted-text.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export default function HighlightText({ text }: { text?: string }) { 4 | return ( 5 | 6 | {" "} 7 | {text} 8 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This configuration only applies to the package manager root. 2 | /** @type {import("eslint").Linter.Config} */ 3 | module.exports = { 4 | ignorePatterns: ["apps/**", "packages/**"], 5 | extends: ["@workspace/eslint-config/library.js"], 6 | parser: "@typescript-eslint/parser", 7 | parserOptions: { 8 | project: true, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /apps/web/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils" 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ) 13 | } 14 | 15 | export { Skeleton } 16 | -------------------------------------------------------------------------------- /apps/web/app/(dashboard)/dashboard/edit-course/[courseId]/page.tsx: -------------------------------------------------------------------------------- 1 | import InstructorRoute from "@/components/auth/instructor-route" 2 | import EditCourse from "@/components/dashboard/edit-course/edit-course" 3 | 4 | export default function EditCoursePage() { 5 | return ( 6 | 7 | 8 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /apps/api/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, type Options } from "tsup"; 2 | 3 | export default defineConfig((options: Options) => ({ 4 | entry: ["index.ts"], 5 | clean: true, 6 | shims: true, 7 | target: "esnext", 8 | format: ["cjs"], 9 | minify: process.env.NODE_ENV === "production", 10 | loader: { 11 | ".html": "text", 12 | }, 13 | ...options, 14 | })); 15 | -------------------------------------------------------------------------------- /packages/typescript-config/nextjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Next.js", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "plugins": [{ "name": "next" }], 7 | "module": "ESNext", 8 | "moduleResolution": "Bundler", 9 | "allowJs": true, 10 | "jsx": "preserve", 11 | "noEmit": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/app/(dashboard)/dashboard/instructor/page.tsx: -------------------------------------------------------------------------------- 1 | import InstructorRoute from "@/components/auth/instructor-route" 2 | import InstructorDashboard from "@/components/dashboard/instructor/instructor-dashboard" 3 | 4 | export default function InstructorDashboardPage() { 5 | return ( 6 | 7 | 8 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /apps/web/types/profile.ts: -------------------------------------------------------------------------------- 1 | interface User { 2 | _id: string 3 | firstName: string 4 | lastName: string 5 | email: string 6 | image: string 7 | accountType: string 8 | additionalDetails: { 9 | gender: string 10 | dateOfBirth: string 11 | about: string 12 | contactNumber: string 13 | } 14 | createdAt: string 15 | updatedAt: string 16 | active: string 17 | approved: string 18 | } 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | 5 | ## Type of change 6 | 7 | - [ ] Feature 8 | - [ ] Fix 9 | - [ ] Refactor 10 | - [ ] Documentation 11 | 12 | ## Screenshots (if applicable) 13 | 14 | 15 | 16 | ## Testing 17 | 18 | 19 | 20 | ## Related issues 21 | 22 | 23 | -------------------------------------------------------------------------------- /apps/api/models/section-model.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose" 2 | 3 | // Define the Section schema 4 | const sectionSchema = new mongoose.Schema({ 5 | sectionName: { 6 | type: String, 7 | }, 8 | subSection: [ 9 | { 10 | type: mongoose.Schema.Types.ObjectId, 11 | required: true, 12 | ref: "SubSection", 13 | }, 14 | ], 15 | }) 16 | 17 | // Export the Section model 18 | export default mongoose.model("Section", sectionSchema) 19 | -------------------------------------------------------------------------------- /apps/api/models/category-model.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose" 2 | 3 | // Define the Tags schema 4 | const categorySchema = new mongoose.Schema({ 5 | name: { 6 | type: String, 7 | required: true, 8 | }, 9 | description: { type: String }, 10 | courses: [ 11 | { 12 | type: mongoose.Schema.Types.ObjectId, 13 | ref: "Course", 14 | }, 15 | ], 16 | }) 17 | 18 | // Export the Tags model 19 | export default mongoose.model("Category", categorySchema) 20 | -------------------------------------------------------------------------------- /apps/api/models/profile-model.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose" 2 | 3 | // Define the Profile schema 4 | const profileSchema = new mongoose.Schema({ 5 | gender: { 6 | type: String, 7 | }, 8 | dateOfBirth: { 9 | type: String, 10 | }, 11 | about: { 12 | type: String, 13 | trim: true, 14 | }, 15 | contactNumber: { 16 | type: Number, 17 | trim: true, 18 | }, 19 | }) 20 | 21 | // Export the Profile model 22 | export default mongoose.model("Profile", profileSchema) 23 | -------------------------------------------------------------------------------- /apps/web/components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import { ThemeProvider as NextThemesProvider } from "next-themes" 5 | 6 | export function ThemeProvider({ children }: { children: React.ReactNode }) { 7 | return ( 8 | 15 | {children} 16 | 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/utils/api-connector.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios" 2 | 3 | export const axiosInstance = axios.create({}) 4 | 5 | export const apiConnector = ( 6 | method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH", 7 | url: string, 8 | bodyData?: any, 9 | headers?: any, 10 | params?: any 11 | ) => { 12 | return axiosInstance({ 13 | method: method, 14 | url: url, 15 | data: bodyData ? bodyData : null, 16 | headers: headers ? headers : null, 17 | params: params ? params : null, 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /apps/web/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/utils/avg-rating.ts: -------------------------------------------------------------------------------- 1 | interface Rating { 2 | rating: number 3 | } 4 | 5 | export default function getAvgRating(ratingArr: Rating[]): number { 6 | if (ratingArr.length === 0) return 0 7 | 8 | const totalReviewCount = ratingArr.reduce((acc, curr) => { 9 | acc += curr.rating 10 | return acc 11 | }, 0) 12 | 13 | const multiplier = Math.pow(10, 1) 14 | const avgReviewCount = 15 | Math.round((totalReviewCount / ratingArr.length) * multiplier) / multiplier 16 | 17 | return avgReviewCount 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/.prettierignore: -------------------------------------------------------------------------------- 1 | # Build outputs 2 | .next/ 3 | out/ 4 | dist/ 5 | build/ 6 | 7 | # Dependencies 8 | node_modules/ 9 | 10 | # Environment files 11 | .env 12 | .env.local 13 | .env.development.local 14 | .env.test.local 15 | .env.production.local 16 | 17 | # Logs 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | pnpm-debug.log* 22 | lerna-debug.log* 23 | 24 | # OS 25 | .DS_Store 26 | *.tsbuildinfo 27 | 28 | # IDE 29 | .vscode/ 30 | .idea/ 31 | 32 | # Generated files 33 | *.d.ts 34 | !src/**/*.d.ts 35 | -------------------------------------------------------------------------------- /apps/api/models/course-progress-model.ts: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose" 2 | 3 | const CourseProgress = new mongoose.Schema({ 4 | courseID: { 5 | type: mongoose.Schema.Types.ObjectId, 6 | ref: "Course", 7 | }, 8 | userID: { 9 | type: mongoose.Schema.Types.ObjectId, 10 | ref: "User", 11 | }, 12 | completedVideos: [ 13 | { 14 | type: mongoose.Schema.Types.ObjectId, 15 | ref: "SubSection", 16 | }, 17 | ], 18 | }) 19 | 20 | export default mongoose.model("CourseProgress", CourseProgress) 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # Dependencies 4 | node_modules 5 | .pnp 6 | .pnp.js 7 | 8 | # Local env files 9 | .env 10 | .env.local 11 | .env.development.local 12 | .env.test.local 13 | .env.production.local 14 | 15 | # Testing 16 | coverage 17 | 18 | # Turbo 19 | .turbo 20 | 21 | # Vercel 22 | .vercel 23 | 24 | # Build Outputs 25 | .next/ 26 | out/ 27 | build 28 | dist 29 | 30 | 31 | # Debug 32 | npm-debug.log* 33 | 34 | # Misc 35 | .DS_Store 36 | *.pem 37 | -------------------------------------------------------------------------------- /apps/api/utils/sec-to-duration.ts: -------------------------------------------------------------------------------- 1 | // Helper function to convert total seconds to the duration format 2 | export function convertSecondsToDuration(totalSeconds: number): string { 3 | const hours = Math.floor(totalSeconds / 3600) 4 | const minutes = Math.floor((totalSeconds % 3600) / 60) 5 | const seconds = Math.floor((totalSeconds % 3600) % 60) 6 | 7 | if (hours > 0) { 8 | return `${hours}h ${minutes}m` 9 | } else if (minutes > 0) { 10 | return `${minutes}m ${seconds}s` 11 | } else { 12 | return `${seconds}s` 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /apps/api/types/custom.d.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 2 | import { Request } from "express" 3 | import { UploadedFile } from "express-fileupload" 4 | 5 | // Extend the Express Request interface 6 | declare global { 7 | namespace Express { 8 | interface Request { 9 | user?: { 10 | id: string 11 | email: string 12 | accountType: string 13 | } 14 | files?: { 15 | thumbnailImage?: UploadedFile 16 | videoFile?: UploadedFile 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "tasks": { 4 | "dev": { 5 | "dependsOn": ["^dev"], 6 | "cache": false, 7 | "persistent": true 8 | }, 9 | "build": { 10 | "dependsOn": ["^build"], 11 | "outputs": [".next/**", "dist/**"] 12 | }, 13 | "start": { 14 | "dependsOn": ["build"], 15 | "cache": false 16 | }, 17 | "lint": { 18 | "dependsOn": ["^lint"] 19 | }, 20 | "check-types": { 21 | "dependsOn": ["^check-types"] 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/web/app/(auth)/login/page.tsx: -------------------------------------------------------------------------------- 1 | import Template from "@/components/auth/auth-template" 2 | import OpenRoute from "@/components/auth/open-route" 3 | 4 | const Login: React.FC = () => { 5 | return ( 6 | 7 |