├── .eslintrc.json
├── .gitignore
├── .prettierrc.json
├── .vscode
└── settings.json
├── README.md
├── next-env.d.ts
├── next.config.js
├── package.json
├── public
├── favicon.ico
├── images
│ ├── avatars
│ │ ├── 1.jpg
│ │ ├── 2.jpg
│ │ ├── 3.jpg
│ │ ├── 4.jpg
│ │ └── 5.jpg
│ ├── certificate.png
│ ├── companies
│ │ ├── airbnb.png
│ │ ├── google.png
│ │ ├── grab.png
│ │ └── microsoft.png
│ ├── course-space-shape.svg
│ ├── courses
│ │ ├── a9e7b27a0c5e986a22416d79e2e9dba9.jpg
│ │ ├── alvaro-reyes-qWwpHwip31M-unsplash.jpg
│ │ ├── annie-spratt-QckxruozjRg-unsplash.jpg
│ │ ├── christopher-gower-m_HRfLhgABo-unsplash.jpg
│ │ ├── grovemade-RvPDe41lYBA-unsplash.jpg
│ │ ├── sai-kiran-anagani-5Ntkpxqt54Y-unsplash.jpg
│ │ ├── stillness-inmotion-Jh6aQX-25Uo-unsplash.jpg
│ │ ├── stillness-inmotion-YSCCnRGrD-4-unsplash.jpg
│ │ └── true-agency-o4UhdLv5jbQ-unsplash.jpg
│ ├── daniel-korpai-pKRNxEguRgM-unsplash.jpg
│ ├── headline-curve.svg
│ ├── home-feature.png
│ ├── home-hero.jpg
│ ├── home-testimonial.png
│ ├── icons
│ │ ├── dribbble.svg
│ │ ├── github.svg
│ │ ├── instagram.svg
│ │ ├── twitter.svg
│ │ └── youtube.svg
│ ├── image_processing20220419-31825-1yzr3x9.png
│ ├── mentors
│ │ ├── christian-buehner-DItYlc26zVI-unsplash.jpg
│ │ ├── jonas-kakaroto-KIPqvvTOC1s-unsplash.jpg
│ │ ├── noah-buscher-8A7fD6Y5VF8-unsplash.jpg
│ │ └── philip-martin-5aGUyCW_PJw-unsplash.jpg
│ └── shape.png
└── vercel.svg
├── src
├── components
│ ├── course
│ │ ├── course-card-item.tsx
│ │ └── index.ts
│ ├── footer
│ │ ├── footer-navigation.tsx
│ │ ├── footer-section-title.tsx
│ │ ├── footer-social-links.tsx
│ │ ├── footer.tsx
│ │ └── index.ts
│ ├── header
│ │ ├── header.tsx
│ │ └── index.ts
│ ├── hello.tsx
│ ├── home
│ │ ├── feature.data.tsx
│ │ ├── feature.tsx
│ │ ├── hero.tsx
│ │ ├── index.ts
│ │ ├── mentors.data.ts
│ │ ├── mentors.tsx
│ │ ├── newsletter.tsx
│ │ ├── popular-course.data.ts
│ │ ├── popular-courses.tsx
│ │ ├── testimonial.data.ts
│ │ └── testimonial.tsx
│ ├── layout
│ │ ├── index.ts
│ │ └── main-layout.tsx
│ ├── logo
│ │ ├── index.ts
│ │ └── logo.tsx
│ ├── mentor
│ │ ├── index.ts
│ │ └── mentor-card-item.tsx
│ ├── navigation
│ │ ├── auth-navigation.tsx
│ │ ├── index.ts
│ │ ├── navigation.data.ts
│ │ └── navigation.tsx
│ ├── styled-button
│ │ ├── index.ts
│ │ └── styled-button.tsx
│ └── testimonial
│ │ ├── index.ts
│ │ └── testimonial-item.tsx
├── config
│ └── theme
│ │ ├── index.ts
│ │ ├── palette-base.ts
│ │ ├── palette-dark.ts
│ │ ├── palette-light.ts
│ │ ├── shadows.ts
│ │ └── typography.ts
├── interfaces
│ ├── course.ts
│ ├── layout.ts
│ ├── mentor.ts
│ ├── navigation.ts
│ ├── social-link.ts
│ ├── testimonial.ts
│ └── user.ts
├── pages
│ ├── _app.tsx
│ ├── _document.tsx
│ └── index.tsx
├── providers
│ ├── index.ts
│ └── mui-provider.tsx
├── styles
│ ├── globals.css
│ └── react-slick.css
└── utils
│ ├── emotion-cache.ts
│ └── index.ts
├── tsconfig.json
└── yarn.lock
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es2021": true
5 | },
6 | "extends": ["plugin:@typescript-eslint/recommended", "next", "next/core-web-vitals", "prettier"],
7 | "parser": "@typescript-eslint/parser",
8 | "parserOptions": {
9 | "ecmaFeatures": {
10 | "jsx": true
11 | },
12 | "ecmaVersion": 12,
13 | "sourceType": "module"
14 | },
15 | "plugins": ["@typescript-eslint"],
16 | "rules": {
17 | "prefer-const": "error",
18 | "react/jsx-props-no-spreading": "off",
19 | "@typescript-eslint/explicit-function-return-type": ["error", { "allowExpressions": true }],
20 | "react/jsx-filename-extension": ["warn", { "extensions": [".tsx"] }]
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.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 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "useTabs": false,
4 | "tabWidth": 2,
5 | "semi": false,
6 | "singleQuote": true,
7 | "endOfLine": "auto",
8 | "printWidth": 120
9 | }
10 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.defaultFormatter": "esbenp.prettier-vscode",
4 | "editor.codeActionsOnSave": {
5 | "source.fixAll.eslint": true
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
7 |
8 | 
9 |
10 | **Coursespace** is a free landing page template built on top of Material UI and fully coded in **React**.
11 | Simple & light is designed to provide all the basic components using the `sx` prop for a developer need to create landing page for Online Course product.
12 |
13 | ## Live Demo
14 |
15 | Take a look the live demo here 👉 [https://coursespace.vercel.app/](https://coursespace.vercel.app/)
16 |
17 | ## Getting Started
18 |
19 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
20 |
21 | First, run the development server:
22 |
23 | ```bash
24 | npm run dev
25 | # or
26 | yarn dev
27 | ```
28 |
29 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
30 |
31 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
32 |
33 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
34 |
35 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
36 |
37 | ## Learn More
38 |
39 | To learn more about Next.js, take a look at the following resources:
40 |
41 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
42 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
43 |
44 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
45 |
46 | ## Deploy on Vercel
47 |
48 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
49 |
50 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
51 |
52 | ## Credits
53 |
54 | - [Unsplash](https://unsplash.com/)
55 | - [Icons8](https://icons8.com/)
56 | - [MUI](https://mui.com/)
57 | - [React Slick](https://github.com/akiran/react-slick)
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | Designed by
66 |
67 | Alfian Ramadhan
68 |
69 |
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | }
5 |
6 | module.exports = nextConfig
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "coursespace-landing-page",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@emotion/cache": "^11.7.1",
13 | "@emotion/react": "^11.9.0",
14 | "@emotion/server": "^11.4.0",
15 | "@emotion/styled": "^11.8.1",
16 | "@mui/icons-material": "^5.6.2",
17 | "@mui/material": "^5.6.2",
18 | "next": "12.1.5",
19 | "react": "18.0.0",
20 | "react-dom": "18.0.0",
21 | "react-scroll": "^1.8.7",
22 | "react-slick": "^0.29.0",
23 | "slick-carousel": "^1.8.1"
24 | },
25 | "devDependencies": {
26 | "@types/node": "17.0.25",
27 | "@types/react": "18.0.6",
28 | "@types/react-dom": "18.0.2",
29 | "@types/react-scroll": "^1.8.3",
30 | "@types/react-slick": "^0.23.8",
31 | "@typescript-eslint/eslint-plugin": "^5.20.0",
32 | "@typescript-eslint/parser": "^5.20.0",
33 | "eslint": "8.14.0",
34 | "eslint-config-next": "12.1.5",
35 | "eslint-config-prettier": "^8.5.0",
36 | "eslint-import-resolver-typescript": "^2.7.1",
37 | "eslint-plugin-import": "^2.26.0",
38 | "eslint-plugin-prettier": "^4.0.0",
39 | "prettier": "^2.6.2",
40 | "typescript": "4.6.3"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/favicon.ico
--------------------------------------------------------------------------------
/public/images/avatars/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/avatars/1.jpg
--------------------------------------------------------------------------------
/public/images/avatars/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/avatars/2.jpg
--------------------------------------------------------------------------------
/public/images/avatars/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/avatars/3.jpg
--------------------------------------------------------------------------------
/public/images/avatars/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/avatars/4.jpg
--------------------------------------------------------------------------------
/public/images/avatars/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/avatars/5.jpg
--------------------------------------------------------------------------------
/public/images/certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/certificate.png
--------------------------------------------------------------------------------
/public/images/companies/airbnb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/companies/airbnb.png
--------------------------------------------------------------------------------
/public/images/companies/google.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/companies/google.png
--------------------------------------------------------------------------------
/public/images/companies/grab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/companies/grab.png
--------------------------------------------------------------------------------
/public/images/companies/microsoft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/companies/microsoft.png
--------------------------------------------------------------------------------
/public/images/course-space-shape.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/public/images/courses/a9e7b27a0c5e986a22416d79e2e9dba9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/courses/a9e7b27a0c5e986a22416d79e2e9dba9.jpg
--------------------------------------------------------------------------------
/public/images/courses/alvaro-reyes-qWwpHwip31M-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/courses/alvaro-reyes-qWwpHwip31M-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/courses/annie-spratt-QckxruozjRg-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/courses/annie-spratt-QckxruozjRg-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/courses/christopher-gower-m_HRfLhgABo-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/courses/christopher-gower-m_HRfLhgABo-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/courses/grovemade-RvPDe41lYBA-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/courses/grovemade-RvPDe41lYBA-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/courses/sai-kiran-anagani-5Ntkpxqt54Y-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/courses/sai-kiran-anagani-5Ntkpxqt54Y-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/courses/stillness-inmotion-Jh6aQX-25Uo-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/courses/stillness-inmotion-Jh6aQX-25Uo-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/courses/stillness-inmotion-YSCCnRGrD-4-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/courses/stillness-inmotion-YSCCnRGrD-4-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/courses/true-agency-o4UhdLv5jbQ-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/courses/true-agency-o4UhdLv5jbQ-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/daniel-korpai-pKRNxEguRgM-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/daniel-korpai-pKRNxEguRgM-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/headline-curve.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/public/images/home-feature.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/home-feature.png
--------------------------------------------------------------------------------
/public/images/home-hero.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/home-hero.jpg
--------------------------------------------------------------------------------
/public/images/home-testimonial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/home-testimonial.png
--------------------------------------------------------------------------------
/public/images/icons/dribbble.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/icons/github.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/icons/instagram.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/icons/twitter.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/icons/youtube.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/image_processing20220419-31825-1yzr3x9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/image_processing20220419-31825-1yzr3x9.png
--------------------------------------------------------------------------------
/public/images/mentors/christian-buehner-DItYlc26zVI-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/mentors/christian-buehner-DItYlc26zVI-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/mentors/jonas-kakaroto-KIPqvvTOC1s-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/mentors/jonas-kakaroto-KIPqvvTOC1s-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/mentors/noah-buscher-8A7fD6Y5VF8-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/mentors/noah-buscher-8A7fD6Y5VF8-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/mentors/philip-martin-5aGUyCW_PJw-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/mentors/philip-martin-5aGUyCW_PJw-unsplash.jpg
--------------------------------------------------------------------------------
/public/images/shape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hiriski/coursespace-landing-page/a80b98e4aa3150b1f8970597abb767654f36a686/public/images/shape.png
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/src/components/course/course-card-item.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Image from 'next/image'
3 | import Box from '@mui/material/Box'
4 | import Rating from '@mui/material/Rating'
5 | import Typography from '@mui/material/Typography'
6 | import IconButton, { iconButtonClasses } from '@mui/material/IconButton'
7 | import ArrowForward from '@mui/icons-material/ArrowForward'
8 | import { Course } from '@/interfaces/course'
9 |
10 | interface Props {
11 | item: Course
12 | }
13 |
14 | const CourseCardItem: FC = ({ item }) => {
15 | return (
16 |
22 | theme.transitions.create(['box-shadow']),
28 | '&:hover': {
29 | boxShadow: 2,
30 | [`& .${iconButtonClasses.root}`]: {
31 | backgroundColor: 'primary.main',
32 | color: 'primary.contrastText',
33 | boxShadow: 2,
34 | },
35 | },
36 | }}
37 | >
38 |
46 |
47 |
48 |
49 |
50 | {item.title}
51 |
52 |
53 |
54 |
55 | ({item.ratingCount})
56 |
57 |
58 |
59 |
60 |
61 |
62 | {'$' + item.price}
63 |
64 | / course
65 |
66 |
70 |
71 |
72 |
73 |
74 |
75 | )
76 | }
77 |
78 | export default CourseCardItem
79 |
--------------------------------------------------------------------------------
/src/components/course/index.ts:
--------------------------------------------------------------------------------
1 | export { default as CourseCardItem } from './course-card-item'
2 |
--------------------------------------------------------------------------------
/src/components/footer/footer-navigation.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Link from 'next/link'
3 | import Grid from '@mui/material/Grid'
4 | import MuiLink from '@mui/material/Link'
5 | import type { Navigation } from '@/interfaces/navigation'
6 | import { navigations as headerNavigations } from '@/components/navigation/navigation.data'
7 | import { FooterSectionTitle } from '@/components/footer'
8 |
9 | const courseMenu: Array = [
10 | {
11 | label: 'UI/UX Design',
12 | path: '#',
13 | },
14 | {
15 | label: 'Mobile Development',
16 | path: '#',
17 | },
18 | {
19 | label: 'Machine Learning',
20 | path: '#',
21 | },
22 | {
23 | label: 'Web Development',
24 | path: '#',
25 | },
26 | ]
27 |
28 | const pageMenu = headerNavigations
29 |
30 | const companyMenu: Array = [
31 | { label: 'Contact Us', path: '#' },
32 | { label: 'Privacy & Policy', path: '#' },
33 | { label: 'Term & Condition', path: '#' },
34 | { label: 'FAQ', path: '#' },
35 | ]
36 |
37 | interface NavigationItemProps {
38 | label: string
39 | path: string
40 | }
41 |
42 | const NavigationItem: FC = ({ label, path }) => {
43 | return (
44 |
45 |
53 | {label}
54 |
55 |
56 | )
57 | }
58 |
59 | const FooterNavigation: FC = () => {
60 | return (
61 |
62 |
63 |
64 | {courseMenu.map(({ label, path }, index) => (
65 |
66 | ))}
67 |
68 |
69 |
70 | {pageMenu.map(({ label, path }, index) => (
71 |
72 | ))}
73 |
74 |
75 |
76 | {companyMenu.map(({ label, path }, index) => (
77 |
78 | ))}
79 |
80 |
81 | )
82 | }
83 |
84 | export default FooterNavigation
85 |
--------------------------------------------------------------------------------
/src/components/footer/footer-section-title.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Box from '@mui/material/Box'
3 | import Typography from '@mui/material/Typography'
4 |
5 | interface Props {
6 | title: string
7 | }
8 |
9 | const FooterSectionTitle: FC = ({ title }: Props) => {
10 | return (
11 |
18 |
19 | {title}
20 |
21 |
22 | )
23 | }
24 |
25 | export default FooterSectionTitle
26 |
--------------------------------------------------------------------------------
/src/components/footer/footer-social-links.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Box from '@mui/material/Box'
3 | import Link from '@mui/material/Link'
4 | import { SocialLink } from '@/interfaces/social-link'
5 |
6 | export const socialLinks: SocialLink[] = [
7 | {
8 | name: 'Instagram',
9 | link: '#',
10 | icon: '/images/icons/instagram.svg',
11 | },
12 | {
13 | name: 'YouTube',
14 | link: '#',
15 | icon: '/images/icons/youtube.svg',
16 | },
17 | {
18 | name: 'Twitter',
19 | link: '#',
20 | icon: '/images/icons/twitter.svg',
21 | },
22 | {
23 | name: 'Dribbble',
24 | link: 'https://dribbble.com/shots/18114471-Coursespace-Online-Course-Landing-Page',
25 | icon: '/images/icons/dribbble.svg',
26 | },
27 | {
28 | name: 'Github',
29 | link: 'https://github.com/hiriski/coursespace-landing-page',
30 | icon: '/images/icons/github.svg',
31 | },
32 | ]
33 |
34 | interface SocialLinkItemProps {
35 | item: SocialLink
36 | }
37 |
38 | const SocialLinkItem: FC = ({ item }) => (
39 |
47 |
69 | {/* eslint-disable-next-line */}
70 |
71 |
72 |
73 | )
74 |
75 | // default
76 | const SocialLinks: FC = () => {
77 | return (
78 |
79 |
89 | {socialLinks.map((item) => {
90 | return
91 | })}
92 |
93 |
94 | )
95 | }
96 |
97 | export default SocialLinks
98 |
--------------------------------------------------------------------------------
/src/components/footer/footer.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Box from '@mui/material/Box'
3 | import Grid from '@mui/material/Grid'
4 | import Container from '@mui/material/Container'
5 | import Typography from '@mui/material/Typography'
6 | import { FooterNavigation, FooterSocialLinks } from '@/components/footer'
7 |
8 | const Footer: FC = () => {
9 | return (
10 |
14 |
15 |
16 |
17 |
18 |
19 | Coursespace
20 |
21 |
22 | Coursespace is an online learning platform that has been operating since 2018 until now.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | )
34 | }
35 |
36 | export default Footer
37 |
--------------------------------------------------------------------------------
/src/components/footer/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Footer } from './footer'
2 | export { default as FooterSectionTitle } from './footer-section-title'
3 | export { default as FooterNavigation } from './footer-navigation'
4 | export { default as FooterSocialLinks } from './footer-social-links'
5 |
--------------------------------------------------------------------------------
/src/components/header/header.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC, useState } from 'react'
2 | import Box from '@mui/material/Box'
3 | import Container from '@mui/material/Container'
4 | import IconButton from '@mui/material/IconButton'
5 | import useMediaQuery from '@mui/material/useMediaQuery'
6 | import { Logo } from '@/components/logo'
7 | import { Navigation, AuthNavigation } from '@/components/navigation'
8 | import { useTheme } from '@mui/material/styles'
9 | import { Menu, Close } from '@mui/icons-material'
10 |
11 | const Header: FC = () => {
12 | const [visibleMenu, setVisibleMenu] = useState(false)
13 | const { breakpoints } = useTheme()
14 | const matchMobileView = useMediaQuery(breakpoints.down('md'))
15 |
16 | return (
17 |
18 |
19 |
20 |
21 |
22 | setVisibleMenu(!visibleMenu)}>
23 |
24 |
25 |
26 | theme.transitions.create(['top']),
35 | ...(matchMobileView && {
36 | py: 6,
37 | backgroundColor: 'background.paper',
38 | zIndex: 'appBar',
39 | position: 'fixed',
40 | height: { xs: '100vh', md: 'auto' },
41 | top: visibleMenu ? 0 : '-120vh',
42 | left: 0,
43 | }),
44 | }}
45 | >
46 | {/* Magic space */}
47 |
48 |
49 | {visibleMenu && matchMobileView && (
50 | setVisibleMenu(!visibleMenu)}
57 | >
58 |
59 |
60 | )}
61 |
62 |
63 |
64 |
65 | )
66 | }
67 |
68 | export default Header
69 |
--------------------------------------------------------------------------------
/src/components/header/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Header } from './header'
2 |
--------------------------------------------------------------------------------
/src/components/hello.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Box from '@mui/material/Box'
3 | import Typography from '@mui/material/Typography'
4 |
5 | interface Props {
6 | name: string
7 | }
8 |
9 | const Hello: FC = ({ name }) => {
10 | return (
11 |
12 | Hello {name}
13 |
14 | )
15 | }
16 |
17 | export default Hello
18 |
--------------------------------------------------------------------------------
/src/components/home/feature.data.tsx:
--------------------------------------------------------------------------------
1 | import React, { ReactNode } from 'react'
2 | import ArtTrackIcon from '@mui/icons-material/ArtTrack'
3 | import AttachMoneyIcon from '@mui/icons-material/AttachMoney'
4 | import LocalLibraryIcon from '@mui/icons-material/LocalLibrary'
5 | import ContactSupportIcon from '@mui/icons-material/ContactSupport'
6 |
7 | interface Data {
8 | title: string
9 | description: string
10 | icon?: ReactNode
11 | }
12 |
13 | export const data: Data[] = [
14 | {
15 | title: 'Easy Accessable',
16 | description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore',
17 | icon: ,
18 | },
19 | {
20 | title: 'More Affordable Cost',
21 | description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore',
22 | icon: ,
23 | },
24 | {
25 | title: 'Flexible Study Time',
26 | description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore',
27 | icon: ,
28 | },
29 | {
30 | title: 'Consultation With Mentor',
31 | description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore',
32 | icon: ,
33 | },
34 | ]
35 |
--------------------------------------------------------------------------------
/src/components/home/feature.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Image from 'next/image'
3 | import Box from '@mui/material/Box'
4 | import Grid from '@mui/material/Grid'
5 | import { styled } from '@mui/material/styles'
6 | import Container from '@mui/material/Container'
7 | import Typography from '@mui/material/Typography'
8 | import CircularProgress from '@mui/material/CircularProgress'
9 | import LinearProgress, { linearProgressClasses } from '@mui/material/LinearProgress'
10 | import { data } from './feature.data'
11 |
12 | interface LinearProgressProps {
13 | order: number
14 | }
15 |
16 | const BorderLinearProgress = styled(LinearProgress, {
17 | shouldForwardProp: (prop) => prop !== 'color',
18 | })(({ theme, order }) => ({
19 | height: 6,
20 | borderRadius: 5,
21 | [`&.${linearProgressClasses.colorPrimary}`]: {
22 | backgroundColor: theme.palette.grey[200],
23 | },
24 | [`& .${linearProgressClasses.bar}`]: {
25 | borderRadius: 5,
26 | ...(order === 1 && {
27 | backgroundColor: '#f303ff',
28 | }),
29 | ...(order === 2 && {
30 | backgroundColor: '#26e8bd',
31 | }),
32 | ...(order === 3 && {
33 | backgroundColor: '#0063ff',
34 | }),
35 | },
36 | }))
37 |
38 | const HomeFeature: FC = () => {
39 | return (
40 |
41 |
42 |
43 |
44 |
45 |
46 |
60 |
61 | Lorem ipsum dolor
62 |
63 |
64 |
65 | UI/UI Design
66 |
67 |
68 |
69 |
70 |
71 | Mobile Development
72 |
73 |
74 |
75 |
76 |
77 | Web Development
78 |
79 |
80 |
81 |
82 |
83 |
97 |
106 | Lorem ipsum
107 |
108 | Lorem ipsum
109 |
110 |
120 |
121 | 75%
122 |
123 |
130 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
156 | Make your{' '}
157 |
167 | Learning
168 |
177 | {/* eslint-disable-next-line @next/next/no-img-element */}
178 |
179 |
180 |
181 | Enjoyable
182 |
183 |
184 |
185 | Set the way of learning according to your wishes with some of the benefits that you get us, so you on
186 | enjoy the lessons that we provide.
187 |
188 |
189 |
190 | {data.map(({ title, description, icon }, index) => (
191 |
192 |
193 |
209 | {icon}
210 |
211 |
212 |
213 | {title}
214 |
215 |
216 | {description}
217 |
218 |
219 |
220 |
221 | ))}
222 |
223 |
224 |
225 |
226 |
227 | )
228 | }
229 |
230 | export default HomeFeature
231 |
--------------------------------------------------------------------------------
/src/components/home/hero.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Image from 'next/image'
3 | import Box from '@mui/material/Box'
4 | import Grid from '@mui/material/Grid'
5 | import Container from '@mui/material/Container'
6 | import Typography from '@mui/material/Typography'
7 | import { Link as ScrollLink } from 'react-scroll'
8 | import { StyledButton } from '@/components/styled-button'
9 | import PlayArrowIcon from '@mui/icons-material/PlayArrow'
10 |
11 | interface Exp {
12 | label: string
13 | value: string
14 | }
15 | interface ExpItemProps {
16 | item: Exp
17 | }
18 |
19 | const exps: Array = [
20 | {
21 | label: 'Students',
22 | value: '10K+',
23 | },
24 | {
25 | label: 'Quality Course',
26 | value: '20+',
27 | },
28 | {
29 | label: 'Experience Mentors',
30 | value: '10+',
31 | },
32 | ]
33 |
34 | const ExpItem: FC = ({ item }) => {
35 | const { value, label } = item
36 | return (
37 |
38 |
41 | {value}
42 |
43 |
44 | {label}
45 |
46 |
47 | )
48 | }
49 |
50 | const HomeHero: FC = () => {
51 | return (
52 |
53 |
54 |
55 |
56 |
65 |
66 |
76 |
86 | Improve{' '}
87 |
96 | {/* eslint-disable-next-line */}
97 |
98 |
99 |
100 | your{' '}
101 |
116 | Skill
117 |
118 |
119 |
123 |
127 |
131 |
132 |
133 | {' '}
134 |
135 | with Different Way
136 |
137 |
138 |
139 |
140 | {
141 | "Let's take an online course to improve your skills in a different way, you can set your own study time according to your learning speed. So you san study comfortable and absorb tge material easily."
142 | }
143 |
144 |
145 |
146 |
147 |
148 | Get Started
149 |
150 |
151 |
152 | }>
153 | Watch Video
154 |
155 |
156 |
157 |
158 |
159 |
160 | {/* Sertificate badge */}
161 |
177 |
190 |
191 |
192 |
193 |
197 | Certificate
198 |
199 |
200 | There are certificates for all courses.
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 | {/* Experience */}
211 |
212 |
213 | {exps.map((item) => (
214 |
215 |
216 |
217 | ))}
218 |
219 |
220 |
221 |
222 | )
223 | }
224 |
225 | export default HomeHero
226 |
--------------------------------------------------------------------------------
/src/components/home/index.ts:
--------------------------------------------------------------------------------
1 | export { default as HomeHero } from './hero'
2 | export { default as HomePopularCourse } from './popular-courses'
3 | export { default as HomeFeature } from './feature'
4 | export { default as HomeTestimonial } from './testimonial'
5 | export { default as HomeOurMentors } from './mentors'
6 | export { default as HomeNewsLetter } from './newsletter'
7 |
--------------------------------------------------------------------------------
/src/components/home/mentors.data.ts:
--------------------------------------------------------------------------------
1 | import type { Mentor } from '@/interfaces/mentor'
2 |
3 | export const data: Array = [
4 | {
5 | id: 1,
6 | photo: '/images/mentors/christian-buehner-DItYlc26zVI-unsplash.jpg',
7 | name: 'Jhon Dwirian',
8 | category: 'UI/UX Design',
9 | description:
10 | 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
11 | company: {
12 | name: 'Grab',
13 | logo: '/images/companies/grab.png',
14 | },
15 | },
16 | {
17 | id: 2,
18 | photo: '/images/mentors/jonas-kakaroto-KIPqvvTOC1s-unsplash.jpg',
19 | name: 'Leon S Kennedy',
20 | category: 'Machine Learning',
21 | description:
22 | 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
23 | company: {
24 | name: 'Google',
25 | logo: '/images/companies/google.png',
26 | },
27 | },
28 | {
29 | id: 3,
30 | photo: '/images/mentors/noah-buscher-8A7fD6Y5VF8-unsplash.jpg',
31 | name: 'Nguyễn Thuy',
32 | category: 'Android Development',
33 | description:
34 | 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
35 | company: {
36 | name: 'Airbnb',
37 | logo: '/images/companies/airbnb.png',
38 | },
39 | },
40 | {
41 | id: 4,
42 | photo: '/images/mentors/philip-martin-5aGUyCW_PJw-unsplash.jpg',
43 | name: 'Rizki Known',
44 | category: 'Fullstack Development',
45 | description:
46 | 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
47 | company: {
48 | name: 'Microsoft',
49 | logo: '/images/companies/microsoft.png',
50 | },
51 | },
52 | ]
53 |
--------------------------------------------------------------------------------
/src/components/home/mentors.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Box from '@mui/material/Box'
3 | import Slider, { Settings } from 'react-slick'
4 | import Container from '@mui/material/Container'
5 | import Typography from '@mui/material/Typography'
6 | import IconButton from '@mui/material/IconButton'
7 | import useMediaQuery from '@mui/material/useMediaQuery'
8 | import { useTheme, styled } from '@mui/material/styles'
9 | import IconArrowBack from '@mui/icons-material/ArrowBack'
10 | import IconArrowForward from '@mui/icons-material/ArrowForward'
11 | import { MentorCardItem } from '@/components/mentor'
12 | import { data } from './mentors.data'
13 |
14 | interface SliderArrowArrow {
15 | onClick?: () => void
16 | type: 'next' | 'prev'
17 | className?: 'string'
18 | }
19 |
20 | const SliderArrow: FC = (props) => {
21 | const { onClick, type, className } = props
22 | return (
23 |
39 | {type === 'next' ? : }
40 |
41 | )
42 | }
43 |
44 | const StyledDots = styled('ul')(({ theme }) => ({
45 | '&.slick-dots': {
46 | position: 'absolute',
47 | left: 0,
48 | bottom: -20,
49 | paddingLeft: theme.spacing(1),
50 | textAlign: 'left',
51 | '& li': {
52 | marginRight: theme.spacing(2),
53 | '&.slick-active>div': {
54 | backgroundColor: theme.palette.primary.main,
55 | },
56 | },
57 | },
58 | }))
59 |
60 | const HomeOurMentors: FC = () => {
61 | const { breakpoints } = useTheme()
62 | const matchMobileView = useMediaQuery(breakpoints.down('md'))
63 |
64 | const sliderConfig: Settings = {
65 | infinite: true,
66 | // autoplay: true,
67 | speed: 300,
68 | slidesToShow: matchMobileView ? 1 : 3,
69 | slidesToScroll: 1,
70 | prevArrow: ,
71 | nextArrow: ,
72 | dots: true,
73 | appendDots: (dots) => {dots} ,
74 | customPaging: () => (
75 |
76 | ),
77 | }
78 |
79 | return (
80 |
94 |
95 |
96 | Our Expert Mentors
97 |
98 |
99 |
100 | {data.map((item) => (
101 |
102 | ))}
103 |
104 |
105 |
106 | )
107 | }
108 |
109 | export default HomeOurMentors
110 |
--------------------------------------------------------------------------------
/src/components/home/newsletter.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Box from '@mui/material/Box'
3 | import InputBase from '@mui/material/InputBase'
4 | import Container from '@mui/material/Container'
5 | import Typography from '@mui/material/Typography'
6 | import { StyledButton } from '../styled-button'
7 |
8 | const HomeNewsLetter: FC = () => {
9 | return (
10 |
11 |
12 |
21 |
22 | Subscribe to Our News Letter
23 |
24 | Subscribe to our newsletter to get information about our courses.
25 |
26 |
36 |
48 |
49 |
50 | Subscribe
51 |
52 |
53 |
54 |
55 |
56 |
57 | )
58 | }
59 |
60 | export default HomeNewsLetter
61 |
--------------------------------------------------------------------------------
/src/components/home/popular-course.data.ts:
--------------------------------------------------------------------------------
1 | import type { Course } from '@/interfaces/course'
2 |
3 | export const data: Array = [
4 | {
5 | id: 1,
6 | cover: '/images/courses/a9e7b27a0c5e986a22416d79e2e9dba9.jpg',
7 | title: 'Android Development from Zeo to Hero',
8 | rating: 5,
9 | ratingCount: 8,
10 | price: 25,
11 | category: 'Beginner',
12 | },
13 | {
14 | id: 2,
15 | cover: '/images/courses/alvaro-reyes-qWwpHwip31M-unsplash.jpg',
16 | title: 'UI/UX Complete Guide',
17 | rating: 5,
18 | ratingCount: 15,
19 | price: 20,
20 | category: 'Intermediate',
21 | },
22 | {
23 | id: 3,
24 | cover: '/images/courses/christopher-gower-m_HRfLhgABo-unsplash.jpg',
25 | title: 'Mastering Data Modeling Fundamentals',
26 | rating: 4,
27 | ratingCount: 7,
28 | price: 30,
29 | category: 'Beginner',
30 | },
31 | {
32 | id: 4,
33 | cover: '/images/courses/true-agency-o4UhdLv5jbQ-unsplash.jpg',
34 | title: 'The Complete Guide Docker and Kubernetes',
35 | rating: 4,
36 | ratingCount: 12,
37 | price: 30,
38 | category: 'Intermediate',
39 | },
40 | {
41 | id: 5,
42 | cover: '/images/courses/stillness-inmotion-Jh6aQX-25Uo-unsplash.jpg',
43 | title: 'Modern React with MUI & Redux',
44 | rating: 4,
45 | ratingCount: 32,
46 | price: 35,
47 | category: 'Intermediate',
48 | },
49 | {
50 | id: 6,
51 | cover: '/images/courses/stillness-inmotion-YSCCnRGrD-4-unsplash.jpg',
52 | title: 'Ethical Hacking Bootcamp Zero to Mastery',
53 | rating: 5,
54 | ratingCount: 14,
55 | price: 35,
56 | category: 'Beginner',
57 | },
58 | {
59 | id: 7,
60 | cover: '/images/courses/grovemade-RvPDe41lYBA-unsplash.jpg',
61 | title: 'Adobe Lightroom For Beginners: Complete Photo Editing',
62 | rating: 4,
63 | ratingCount: 6,
64 | price: 25,
65 | category: 'Beginner',
66 | },
67 | ]
68 |
--------------------------------------------------------------------------------
/src/components/home/popular-courses.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Box from '@mui/material/Box'
3 | import Grid from '@mui/material/Grid'
4 | import Slider, { Settings } from 'react-slick'
5 | import Container from '@mui/material/Container'
6 | import Typography from '@mui/material/Typography'
7 | import { useTheme, styled } from '@mui/material/styles'
8 | import { IconButton, useMediaQuery } from '@mui/material'
9 | import IconArrowBack from '@mui/icons-material/ArrowBack'
10 | import IconArrowForward from '@mui/icons-material/ArrowForward'
11 |
12 | import { data } from './popular-course.data'
13 | import { CourseCardItem } from '@/components/course'
14 |
15 | interface SliderArrowArrow {
16 | onClick?: () => void
17 | type: 'next' | 'prev'
18 | className?: 'string'
19 | }
20 |
21 | const SliderArrow: FC = (props) => {
22 | const { onClick, type, className } = props
23 | return (
24 |
40 | {type === 'next' ? : }
41 |
42 | )
43 | }
44 |
45 | const StyledDots = styled('ul')(({ theme }) => ({
46 | '&.slick-dots': {
47 | position: 'absolute',
48 | left: 0,
49 | bottom: -20,
50 | paddingLeft: theme.spacing(1),
51 | textAlign: 'left',
52 | '& li': {
53 | marginRight: theme.spacing(2),
54 | '&.slick-active>div': {
55 | backgroundColor: theme.palette.primary.main,
56 | },
57 | },
58 | },
59 | }))
60 |
61 | const HomePopularCourse: FC = () => {
62 | const { breakpoints } = useTheme()
63 | const matchMobileView = useMediaQuery(breakpoints.down('md'))
64 |
65 | const sliderConfig: Settings = {
66 | infinite: true,
67 | autoplay: true,
68 | speed: 300,
69 | slidesToShow: matchMobileView ? 1 : 3,
70 | slidesToScroll: 1,
71 | prevArrow: ,
72 | nextArrow: ,
73 | dots: true,
74 | appendDots: (dots) => {dots} ,
75 | customPaging: () => (
76 |
77 | ),
78 | }
79 |
80 | return (
81 |
92 |
93 |
94 |
95 |
104 |
105 | Most Popular Courses
106 |
107 |
108 |
109 |
110 |
111 |
112 | {data.map((item) => (
113 |
114 | ))}
115 |
116 |
117 |
118 |
119 |
120 | )
121 | }
122 |
123 | export default HomePopularCourse
124 |
--------------------------------------------------------------------------------
/src/components/home/testimonial.data.ts:
--------------------------------------------------------------------------------
1 | import type { Testimonial } from '@/interfaces/testimonial'
2 |
3 | export const data: Array = [
4 | {
5 | id: 1,
6 | title: 'Detailed learning materials',
7 | content:
8 | 'Classes that provide very detailed material in term of making UI UX Design starting team making low and hight quality, system designs, using data layout and make prototypes and testing.',
9 | user: {
10 | id: 1,
11 | name: 'Luis Sera',
12 | professional: 'UI/UX Engineer',
13 | photo: '1.jpg',
14 | },
15 | },
16 | {
17 | id: 2,
18 | title: 'Best Quality Online Course!',
19 | content:
20 | 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
21 | user: {
22 | id: 1,
23 | name: 'Riski',
24 | professional: 'Software Engineer',
25 | photo: '2.jpg',
26 | },
27 | },
28 | {
29 | id: 3,
30 | title: 'Very complete class',
31 | content:
32 | 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
33 | user: {
34 | id: 1,
35 | name: 'Nguyễn Văn',
36 | professional: 'FullStack Designer',
37 | photo: '3.jpg',
38 | },
39 | },
40 | {
41 | id: 4,
42 | title: 'Great Quality!',
43 | content:
44 | 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
45 | user: {
46 | id: 1,
47 | name: 'Diana Jordan',
48 | professional: 'SEO Expert',
49 | photo: '4.jpg',
50 | },
51 | },
52 | {
53 | id: 5,
54 | title: 'Detailed learning materials',
55 | content:
56 | 'Classes that provide very detailed material in term of making UI UX Design starting team making low and hight quality, system designs, using data layout and make prototypes and testing.',
57 | user: {
58 | id: 1,
59 | name: 'Ashley Graham',
60 | professional: 'Back-End Developer',
61 | photo: '5.jpg',
62 | },
63 | },
64 | ]
65 |
--------------------------------------------------------------------------------
/src/components/home/testimonial.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC, useRef } from 'react'
2 | import Image from 'next/image'
3 | import Box from '@mui/material/Box'
4 | import Grid from '@mui/material/Grid'
5 | import Slider, { Settings } from 'react-slick'
6 | import Container from '@mui/material/Container'
7 | import Typography from '@mui/material/Typography'
8 | import IconButton from '@mui/material/IconButton'
9 | import { styled } from '@mui/material/styles'
10 | import IconArrowBack from '@mui/icons-material/ArrowBack'
11 | import IconArrowForward from '@mui/icons-material/ArrowForward'
12 |
13 | import { TestimonialItem } from '@/components/testimonial'
14 | import { data } from './testimonial.data'
15 |
16 | interface SliderArrowArrow {
17 | onClick?: () => void
18 | type: 'next' | 'prev'
19 | className?: 'string'
20 | }
21 |
22 | const SliderArrow: FC = (props) => {
23 | const { onClick, type, className } = props
24 | return (
25 |
41 | {type === 'next' ? : }
42 |
43 | )
44 | }
45 |
46 | const StyledSlickContainer = styled('div')(() => ({
47 | position: 'relative',
48 |
49 | '& .slick-list': { marginLeft: '-30px', marginBottom: '24px' },
50 | }))
51 |
52 | const HomeTestimonial: FC = () => {
53 | const sliderRef = useRef(null)
54 |
55 | const sliderConfig: Settings = {
56 | infinite: true,
57 | autoplay: true,
58 | speed: 300,
59 | slidesToShow: 1,
60 | slidesToScroll: 1,
61 | prevArrow: ,
62 | nextArrow: ,
63 | }
64 |
65 | return (
66 |
67 |
68 |
69 |
70 |
81 | Testimonial What our{' '}
82 |
92 | Students{' '}
93 |
101 | {/* eslint-disable-next-line @next/next/no-img-element */}
102 |
103 |
104 |
105 | Say
106 |
107 |
108 |
109 |
110 | {data.map((item, index) => (
111 |
112 | ))}
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | )
125 | }
126 |
127 | export default HomeTestimonial
128 |
--------------------------------------------------------------------------------
/src/components/layout/index.ts:
--------------------------------------------------------------------------------
1 | export { default as MainLayout } from './main-layout'
2 |
--------------------------------------------------------------------------------
/src/components/layout/main-layout.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC, ReactNode } from 'react'
2 | import Box from '@mui/material/Box'
3 | import { Footer } from '@/components/footer'
4 | import { Header } from '@/components/header'
5 |
6 | interface Props {
7 | children: ReactNode
8 | }
9 |
10 | const MainLayout: FC = ({ children }) => {
11 | return (
12 |
13 |
14 | {children}
15 |
16 |
17 | )
18 | }
19 |
20 | export default MainLayout
21 |
--------------------------------------------------------------------------------
/src/components/logo/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Logo } from './logo'
2 |
--------------------------------------------------------------------------------
/src/components/logo/logo.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import { Box, Typography } from '@mui/material'
3 |
4 | interface Props {
5 | onClick?: () => void
6 | variant?: 'primary' | 'secondary'
7 | }
8 |
9 | const Logo: FC = ({ onClick, variant }) => {
10 | return (
11 |
12 |
17 | Coursespace
18 |
19 |
20 | )
21 | }
22 |
23 | Logo.defaultProps = {
24 | variant: 'primary',
25 | }
26 |
27 | export default Logo
28 |
--------------------------------------------------------------------------------
/src/components/mentor/index.ts:
--------------------------------------------------------------------------------
1 | export { default as MentorCardItem } from './mentor-card-item'
2 |
--------------------------------------------------------------------------------
/src/components/mentor/mentor-card-item.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Image from 'next/image'
3 | import Box from '@mui/material/Box'
4 | import Typography from '@mui/material/Typography'
5 |
6 | import { Mentor } from '@/interfaces/mentor'
7 |
8 | interface Props {
9 | item: Mentor
10 | }
11 |
12 | const MentorCardItem: FC = ({ item }) => {
13 | return (
14 |
20 | theme.transitions.create(['box-shadow']),
26 | '&:hover': {
27 | boxShadow: 2,
28 | },
29 | }}
30 | >
31 |
40 |
41 |
42 |
43 |
44 | {item.name}
45 |
46 | {item.category}
47 |
48 | {item.description}
49 |
50 |
51 | {/* eslint-disable-next-line */}
52 |
53 |
54 |
55 |
56 |
57 | )
58 | }
59 | export default MentorCardItem
60 |
--------------------------------------------------------------------------------
/src/components/navigation/auth-navigation.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Box from '@mui/material/Box'
3 | import { StyledButton } from '@/components/styled-button'
4 |
5 | const AuthNavigation: FC = () => {
6 | return (
7 |
8 |
9 | Sign In
10 |
11 | Sign Up
12 |
13 | )
14 | }
15 |
16 | export default AuthNavigation
17 |
--------------------------------------------------------------------------------
/src/components/navigation/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Navigation } from './navigation'
2 | export { default as AuthNavigation } from './auth-navigation'
3 |
--------------------------------------------------------------------------------
/src/components/navigation/navigation.data.ts:
--------------------------------------------------------------------------------
1 | import type { Navigation } from '@/interfaces/navigation'
2 |
3 | export const navigations: Navigation[] = [
4 | {
5 | label: 'Home',
6 | path: '#', // '/',
7 | },
8 | {
9 | label: 'Courses',
10 | path: 'popular-course', // '/popular-course',
11 | },
12 | {
13 | label: 'Testimonial',
14 | path: 'testimonial', // '/testimonial',
15 | },
16 | {
17 | label: 'Mentor',
18 | path: 'mentors', // '/mentors',
19 | },
20 | ]
21 |
--------------------------------------------------------------------------------
/src/components/navigation/navigation.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Box from '@mui/material/Box'
3 | import { Link as ScrollLink } from 'react-scroll'
4 | import { navigations } from './navigation.data'
5 |
6 | const Navigation: FC = () => {
7 | return (
8 |
9 | {navigations.map(({ path: destination, label }) => (
10 | div': { display: 'none' },
34 |
35 | '&.current>div': { display: 'block' },
36 |
37 | '&:hover': {
38 | color: 'primary.main',
39 | '&>div': {
40 | display: 'block',
41 | },
42 | },
43 | }}
44 | >
45 |
53 | {/* eslint-disable-next-line */}
54 |
55 |
56 | {label}
57 |
58 | ))}
59 |
60 | )
61 | }
62 |
63 | export default Navigation
64 |
--------------------------------------------------------------------------------
/src/components/styled-button/index.ts:
--------------------------------------------------------------------------------
1 | export { default as StyledButton } from './styled-button'
2 |
--------------------------------------------------------------------------------
/src/components/styled-button/styled-button.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC, ReactNode } from 'react'
2 | import Box from '@mui/material/Box'
3 | import { Theme } from '@mui/material'
4 | import { styled } from '@mui/material/styles'
5 | import { ButtonProps } from '@mui/material/Button'
6 | import { fontFamily } from '@/config/theme/typography'
7 |
8 | interface BaseButtonProps extends Pick {
9 | variant?: 'contained' | 'outlined' | 'text'
10 | color?: 'default' | 'primary' | 'secondary' | 'dark' | 'light'
11 | size?: 'small' | 'medium' | 'large'
12 | disableHoverEffect?: boolean
13 | }
14 | interface StyledButtonRootProps extends BaseButtonProps {
15 | theme?: Theme
16 | }
17 |
18 | const StyledButtonRoot = styled('button', {
19 | shouldForwardProp: (prop) =>
20 | prop !== 'variant' && prop !== 'color' && prop !== 'size' && prop !== 'disableHoverEffect',
21 | })(({ theme, color, variant, size, disableHoverEffect }) => ({
22 | fontFamily,
23 | cursor: 'pointer',
24 | minWidth: 40,
25 | fontSize: 14,
26 | fontWeight: 500,
27 | lineHeight: 1.5,
28 | letterSpacing: 1,
29 | borderRadius: Number(theme.shape.borderRadius) * 3,
30 |
31 | display: 'inline-flex',
32 | alignItems: 'center',
33 | userSelect: 'none',
34 | transform: 'unset',
35 | position: 'relative',
36 | overflow: 'hidden',
37 | border: 'none',
38 | whiteSpace: 'nowrap',
39 | WebkitTapHighlightColor: 'transparent',
40 | verticalAlign: 'middle',
41 | outline: 'none !important',
42 | transition: theme.transitions.create(['transform']),
43 |
44 | // hover
45 | '&:hover': {
46 | ...(!disableHoverEffect && {
47 | transform: 'translateY(-3px)',
48 | }),
49 | },
50 |
51 | '& svg': {
52 | fontSize: 20,
53 | },
54 |
55 | // sizes and variants
56 | ...(size === 'small' &&
57 | variant === 'outlined' && {
58 | padding: '4px 10px',
59 | }),
60 | ...(size === 'medium' &&
61 | variant === 'outlined' && {
62 | padding: '6px 14px',
63 | }),
64 | ...(size === 'large' &&
65 | variant === 'outlined' && {
66 | padding: '10px 18px',
67 | fontSize: 15,
68 | }),
69 |
70 | ...(size === 'small' &&
71 | variant !== 'outlined' && {
72 | padding: '6px 12px',
73 | }),
74 | ...(size === 'medium' &&
75 | variant !== 'outlined' && {
76 | padding: '8px 16px',
77 | }),
78 | ...(size === 'large' &&
79 | variant !== 'outlined' && {
80 | padding: '12px 20px',
81 | fontSize: 15,
82 | }),
83 |
84 | // variants
85 | ...(variant !== 'contained' && {
86 | backgroundColor: 'transparent',
87 | boxShadow: 'none !important',
88 | }),
89 |
90 | // colors & varians
91 | ...(color === 'default' &&
92 | variant === 'contained' && {
93 | backgroundColor: theme.palette.text.primary,
94 | color: theme.palette.primary.contrastText,
95 | }),
96 | ...(color === 'primary' &&
97 | variant === 'contained' && {
98 | backgroundColor: theme.palette.primary.main,
99 | color: theme.palette.primary.contrastText,
100 | boxShadow: '0 6px 22px 0 rgb(18 124 113 / 12%)',
101 | }),
102 | ...(color === 'secondary' &&
103 | variant === 'contained' && {
104 | backgroundColor: theme.palette.secondary.main,
105 | color: theme.palette.primary.contrastText,
106 | }),
107 | ...(color === 'dark' &&
108 | variant === 'contained' && {
109 | backgroundColor: '#313d56',
110 | color: theme.palette.primary.contrastText,
111 | }),
112 | ...(color === 'light' &&
113 | variant === 'contained' && {
114 | backgroundColor: theme.palette.primary.contrastText,
115 | color: theme.palette.text.primary,
116 | }),
117 |
118 | ...(color === 'primary' &&
119 | variant === 'outlined' && {
120 | border: `2px solid ${theme.palette.primary.main}`,
121 | color: theme.palette.primary.main,
122 | }),
123 | ...(color === 'secondary' &&
124 | variant === 'outlined' && {
125 | border: `2px solid ${theme.palette.secondary.main}`,
126 | color: theme.palette.secondary.main,
127 | }),
128 | ...(color === 'dark' &&
129 | variant === 'outlined' && {
130 | border: `2px solid #313d56`,
131 | color: '#313d56',
132 | }),
133 | ...(color === 'light' &&
134 | variant === 'outlined' && {
135 | border: `2px solid #313d56`,
136 | color: `#313d56`,
137 | }),
138 |
139 | ...(color === 'primary' &&
140 | variant === 'text' && {
141 | color: theme.palette.primary.main,
142 | }),
143 | ...(color === 'secondary' &&
144 | variant === 'text' && {
145 | color: theme.palette.secondary.main,
146 | }),
147 | ...(color === 'dark' &&
148 | variant === 'text' && {
149 | color: '#313d56',
150 | }),
151 | ...(color === 'light' &&
152 | variant === 'text' && {
153 | color: theme.palette.primary.contrastText,
154 | }),
155 | }))
156 |
157 | interface Props extends BaseButtonProps {
158 | children: ReactNode
159 | }
160 |
161 | const StyledButton: FC = (props: Props) => {
162 | const { children, onClick, disableHoverEffect, startIcon, endIcon, ...rest } = props
163 | return (
164 |
165 | {startIcon && (
166 |
167 | {startIcon}
168 |
169 | )}
170 | {children}
171 | {endIcon && (
172 |
173 | {endIcon}
174 |
175 | )}
176 |
177 | )
178 | }
179 |
180 | StyledButton.defaultProps = {
181 | color: 'primary',
182 | variant: 'contained',
183 | size: 'medium',
184 | disableHoverEffect: false,
185 | }
186 |
187 | export default StyledButton
188 |
--------------------------------------------------------------------------------
/src/components/testimonial/index.ts:
--------------------------------------------------------------------------------
1 | export { default as TestimonialItem } from './testimonial-item'
2 |
--------------------------------------------------------------------------------
/src/components/testimonial/testimonial-item.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Image from 'next/image'
3 | import Box from '@mui/material/Box'
4 | import Typography from '@mui/material/Typography'
5 | import { Testimonial } from '@/interfaces/testimonial'
6 |
7 | interface Props {
8 | item: Testimonial
9 | }
10 |
11 | const TestimonialItem: FC = ({ item }) => {
12 | return (
13 |
14 |
15 |
16 | {item.title}
17 |
18 | {item.content}
19 |
20 |
33 |
46 |
53 |
54 |
55 | {item.user.name}
56 |
57 | {item.user.professional}
58 |
59 |
60 |
61 |
62 | )
63 | }
64 | export default TestimonialItem
65 |
--------------------------------------------------------------------------------
/src/config/theme/index.ts:
--------------------------------------------------------------------------------
1 | import { createTheme as createMuiTheme, Theme } from '@mui/material/styles'
2 |
3 | import typography from './typography'
4 | import paletteBase from './palette-base'
5 | import paletteLight from './palette-light'
6 | import paletteDark from './palette-dark'
7 | import shadows from './shadows'
8 |
9 | // default
10 | const createTheme = (darkMode?: boolean): Theme => {
11 | const palette = darkMode ? { ...paletteBase, ...paletteDark } : { ...paletteBase, ...paletteLight }
12 | return createMuiTheme({
13 | palette,
14 | typography,
15 | shadows,
16 | })
17 | }
18 |
19 | const theme = createTheme(false)
20 |
21 | export { paletteBase, paletteLight, paletteDark, typography, shadows }
22 | export default theme
23 |
--------------------------------------------------------------------------------
/src/config/theme/palette-base.ts:
--------------------------------------------------------------------------------
1 | import { PaletteOptions } from '@mui/material'
2 |
3 | const paletteBase: Partial = {
4 | primary: {
5 | light: '#9FF1D2',
6 | main: '#127C71',
7 | dark: '#0D6A69',
8 | contrastText: '#fbfbfb',
9 | },
10 | secondary: {
11 | light: '#FDE6A8',
12 | main: '#ffaf35',
13 | dark: '#D0821C',
14 | contrastText: '#fbfbfb',
15 | },
16 | }
17 |
18 | export default paletteBase
19 |
--------------------------------------------------------------------------------
/src/config/theme/palette-dark.ts:
--------------------------------------------------------------------------------
1 | import { PaletteOptions } from '@mui/material'
2 | import { grey } from '@mui/material/colors'
3 |
4 | const paletteDark: PaletteOptions = {
5 | mode: 'dark',
6 | background: {
7 | default: grey[900],
8 | paper: '#222128',
9 | },
10 | text: {
11 | primary: grey[100],
12 | secondary: grey[200],
13 | disabled: grey[300],
14 | },
15 | }
16 |
17 | export default paletteDark
18 |
--------------------------------------------------------------------------------
/src/config/theme/palette-light.ts:
--------------------------------------------------------------------------------
1 | import { PaletteOptions } from '@mui/material'
2 | import { grey, common } from '@mui/material/colors'
3 |
4 | const palette: PaletteOptions = {
5 | mode: 'light',
6 | background: {
7 | default: '#f2f5f5', //'#fdfdfd',
8 | paper: common.white,
9 | },
10 | text: {
11 | primary: grey[900],
12 | secondary: '#717171', // grey[700],
13 | disabled: grey[500],
14 | },
15 | }
16 |
17 | export default palette
18 |
--------------------------------------------------------------------------------
/src/config/theme/shadows.ts:
--------------------------------------------------------------------------------
1 | import { Shadows } from '@mui/material/styles/shadows'
2 |
3 | const shadows: Shadows = [
4 | 'none',
5 | '0 10px 10px 0 rgb(0 0 0 / 3%)',
6 | '0 15px 15px 0 rgb(0 0 0 / 5%)',
7 | '0 22px 22px 0 rgb(0 0 0 /6%)',
8 | '0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)',
9 | '0px 3px 5px -1px rgba(0,0,0,0.2),0px 5px 8px 0px rgba(0,0,0,0.14),0px 1px 14px 0px rgba(0,0,0,0.12)',
10 | '0px 3px 5px -1px rgba(0,0,0,0.2),0px 6px 10px 0px rgba(0,0,0,0.14),0px 1px 18px 0px rgba(0,0,0,0.12)',
11 | '0px 4px 5px -2px rgba(0,0,0,0.2),0px 7px 10px 1px rgba(0,0,0,0.14),0px 2px 16px 1px rgba(0,0,0,0.12)',
12 | '0px 5px 5px -3px rgba(0,0,0,0.2),0px 8px 10px 1px rgba(0,0,0,0.14),0px 3px 14px 2px rgba(0,0,0,0.12)',
13 | '0px 5px 6px -3px rgba(0,0,0,0.2),0px 9px 12px 1px rgba(0,0,0,0.14),0px 3px 16px 2px rgba(0,0,0,0.12)',
14 | '0px 6px 6px -3px rgba(0,0,0,0.2),0px 10px 14px 1px rgba(0,0,0,0.14),0px 4px 18px 3px rgba(0,0,0,0.12)',
15 | '0px 6px 7px -4px rgba(0,0,0,0.2),0px 11px 15px 1px rgba(0,0,0,0.14),0px 4px 20px 3px rgba(0,0,0,0.12)',
16 | '0px 7px 8px -4px rgba(0,0,0,0.2),0px 12px 17px 2px rgba(0,0,0,0.14),0px 5px 22px 4px rgba(0,0,0,0.12)',
17 | '0px 7px 8px -4px rgba(0,0,0,0.2),0px 13px 19px 2px rgba(0,0,0,0.14),0px 5px 24px 4px rgba(0,0,0,0.12)',
18 | '0px 7px 9px -4px rgba(0,0,0,0.2),0px 14px 21px 2px rgba(0,0,0,0.14),0px 5px 26px 4px rgba(0,0,0,0.12)',
19 | '0px 8px 9px -5px rgba(0,0,0,0.2),0px 15px 22px 2px rgba(0,0,0,0.14),0px 6px 28px 5px rgba(0,0,0,0.12)',
20 | '0px 8px 10px -5px rgba(0,0,0,0.2),0px 16px 24px 2px rgba(0,0,0,0.14),0px 6px 30px 5px rgba(0,0,0,0.12)',
21 | '0px 8px 11px -5px rgba(0,0,0,0.2),0px 17px 26px 2px rgba(0,0,0,0.14),0px 6px 32px 5px rgba(0,0,0,0.12)',
22 | '0px 9px 11px -5px rgba(0,0,0,0.2),0px 18px 28px 2px rgba(0,0,0,0.14),0px 7px 34px 6px rgba(0,0,0,0.12)',
23 | '0px 9px 12px -6px rgba(0,0,0,0.2),0px 19px 29px 2px rgba(0,0,0,0.14),0px 7px 36px 6px rgba(0,0,0,0.12)',
24 | '0px 10px 13px -6px rgba(0,0,0,0.2),0px 20px 31px 3px rgba(0,0,0,0.14),0px 8px 38px 7px rgba(0,0,0,0.12)',
25 | '0px 10px 13px -6px rgba(0,0,0,0.2),0px 21px 33px 3px rgba(0,0,0,0.14),0px 8px 40px 7px rgba(0,0,0,0.12)',
26 | '0px 10px 14px -6px rgba(0,0,0,0.2),0px 22px 35px 3px rgba(0,0,0,0.14),0px 8px 42px 7px rgba(0,0,0,0.12)',
27 | '0px 11px 14px -7px rgba(0,0,0,0.2),0px 23px 36px 3px rgba(0,0,0,0.14),0px 9px 44px 8px rgba(0,0,0,0.12)',
28 | '0px 11px 15px -7px rgba(0,0,0,0.2),0px 24px 38px 3px rgba(0,0,0,0.14),0px 9px 46px 8px rgba(0,0,0,0.12)',
29 | ]
30 |
31 | export default shadows
32 |
--------------------------------------------------------------------------------
/src/config/theme/typography.ts:
--------------------------------------------------------------------------------
1 | import { TypographyOptions } from '@mui/material/styles/createTypography'
2 |
3 | export const fontFamily = [
4 | '"Cabin",-apple-system, BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"',
5 | ].join(',')
6 |
7 | const headingLineHeight = 1.4
8 |
9 | const typography: TypographyOptions = {
10 | fontFamily,
11 | fontWeightLight: 400,
12 | fontWeightRegular: 400,
13 | fontWeightMedium: 600,
14 | fontWeightBold: 700,
15 | h1: {
16 | fontSize: 34,
17 | lineHeight: headingLineHeight,
18 | fontWeight: 700,
19 | },
20 | h2: {
21 | fontSize: 28,
22 | lineHeight: headingLineHeight,
23 | fontWeight: 700,
24 | },
25 | h3: {
26 | fontSize: 24,
27 | lineHeight: headingLineHeight,
28 | fontWeight: 700,
29 | },
30 | h4: {
31 | fontSize: 22,
32 | lineHeight: headingLineHeight,
33 | fontWeight: 700,
34 | },
35 | h5: {
36 | fontSize: 17,
37 | lineHeight: headingLineHeight,
38 | fontWeight: 600,
39 | },
40 | h6: {
41 | fontSize: 15,
42 | lineHeight: headingLineHeight,
43 | fontWeight: 600,
44 | },
45 | body1: {
46 | fontSize: '1rem',
47 | },
48 | body2: {
49 | fontSize: '0.9rem',
50 | },
51 | subtitle1: {
52 | fontSize: '0.85rem',
53 | },
54 | subtitle2: {
55 | fontSize: '0.8rem',
56 | },
57 | }
58 |
59 | export default typography
60 |
--------------------------------------------------------------------------------
/src/interfaces/course.ts:
--------------------------------------------------------------------------------
1 | export interface Course {
2 | id: number | string
3 | title: string
4 | cover: string
5 | rating: number
6 | ratingCount: number
7 | price: number
8 | category: string
9 | }
10 |
--------------------------------------------------------------------------------
/src/interfaces/layout.ts:
--------------------------------------------------------------------------------
1 | import { NextPage } from 'next'
2 | import { ReactElement, ReactNode } from 'react'
3 |
4 | export type NextPageWithLayout = NextPage & {
5 | getLayout?: (page: ReactElement) => ReactNode
6 | }
7 |
--------------------------------------------------------------------------------
/src/interfaces/mentor.ts:
--------------------------------------------------------------------------------
1 | import type { User } from './user'
2 |
3 | export interface Mentor extends Omit {
4 | description?: string
5 | category: string
6 | company?: {
7 | name: string
8 | logo: string
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/interfaces/navigation.ts:
--------------------------------------------------------------------------------
1 | export interface Navigation {
2 | label: string
3 | path: string
4 | }
5 |
--------------------------------------------------------------------------------
/src/interfaces/social-link.ts:
--------------------------------------------------------------------------------
1 | export interface SocialLink {
2 | name: string
3 | link: string
4 | icon?: string
5 | }
6 |
--------------------------------------------------------------------------------
/src/interfaces/testimonial.ts:
--------------------------------------------------------------------------------
1 | import type { User } from './user'
2 |
3 | export interface Testimonial {
4 | id: number | string
5 | title: string
6 | content: string
7 | user: User
8 | }
9 |
--------------------------------------------------------------------------------
/src/interfaces/user.ts:
--------------------------------------------------------------------------------
1 | export interface User {
2 | id: number | string
3 | name: string
4 | photo?: string
5 | professional?: string
6 | }
7 |
--------------------------------------------------------------------------------
/src/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import Head from 'next/head'
3 | import type { AppProps } from 'next/app'
4 | import { CssBaseline } from '@mui/material'
5 | import { EmotionCache } from '@emotion/cache'
6 | import { CacheProvider } from '@emotion/react'
7 | import { createEmotionCache } from '@/utils'
8 | import { MUIProvider } from '@/providers'
9 | import 'slick-carousel/slick/slick.css'
10 | import '@/styles/globals.css'
11 | import '@/styles/react-slick.css'
12 | import { NextPageWithLayout } from '@/interfaces/layout'
13 | // import 'slick-carousel/slick/slick-theme.css'
14 |
15 | // Client-side cache, shared for the whole session of the user in the browser.
16 | const clientSideEmotionCache = createEmotionCache()
17 |
18 | type AppPropsWithLayout = AppProps & {
19 | emotionCache: EmotionCache
20 | Component: NextPageWithLayout
21 | }
22 |
23 | const App: FC = (props: AppPropsWithLayout) => {
24 | const { Component, emotionCache = clientSideEmotionCache, pageProps } = props
25 |
26 | // Use the layout defined at the page level, if available
27 | const getLayout = Component.getLayout || ((page) => page)
28 |
29 | return (
30 |
31 |
32 |
33 | React Coursespace
34 |
35 |
36 | {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
37 |
38 | {getLayout( )}
39 |
40 |
41 | )
42 | }
43 |
44 | export default App
45 |
--------------------------------------------------------------------------------
/src/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import theme from '@/config/theme'
3 | import { NextComponentType } from 'next'
4 | import { AppInitialProps } from 'next/app'
5 | import { EmotionCache } from '@emotion/cache'
6 | import { createEmotionCache } from '@/utils'
7 | import createEmotionServer from '@emotion/server/create-instance'
8 | import { AppContextType, AppPropsType } from 'next/dist/shared/lib/utils'
9 | import Document, { Html, Head, Main, NextScript, DocumentContext } from 'next/document'
10 |
11 | interface DocumentProps {
12 | emotionStylesTags: any[]
13 | }
14 |
15 | class MyDocument extends Document {
16 | render(): any {
17 | return (
18 |
19 |
20 |
21 |
22 |
23 |
24 | {/* PWA primary color */}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
38 | {/* Inject MUI styles first to match with the prepend: true configuration. */}
39 | {this.props.emotionStylesTags}
40 |
41 |
42 |
43 |
44 |
45 |
46 | )
47 | }
48 | }
49 |
50 | // `getInitialProps` belongs to `_document` (instead of `_app`),
51 | // it's compatible with static-site generation (SSG).
52 | MyDocument.getInitialProps = async (ctx: DocumentContext) => {
53 | // Resolution order
54 | //
55 | // On the server:
56 | // 1. app.getInitialProps
57 | // 2. page.getInitialProps
58 | // 3. document.getInitialProps
59 | // 4. app.render
60 | // 5. page.render
61 | // 6. document.render
62 | //
63 | // On the server with error:
64 | // 1. document.getInitialProps
65 | // 2. app.render
66 | // 3. page.render
67 | // 4. document.render
68 | //
69 | // On the client
70 | // 1. app.getInitialProps
71 | // 2. page.getInitialProps
72 | // 3. app.render
73 | // 4. page.render
74 |
75 | const originalRenderPage = ctx.renderPage
76 |
77 | // You can consider sharing the same emotion cache between all the SSR requests to speed up performance.
78 | // However, be aware that it can have global side effects.
79 | const cache = createEmotionCache()
80 | const { extractCriticalToChunks } = createEmotionServer(cache)
81 |
82 | ctx.renderPage = () =>
83 | originalRenderPage({
84 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
85 | // @ts-ignore
86 | enhanceApp: (
87 | App: NextComponentType
88 | ) =>
89 | function EnhanceApp(props) {
90 | // console.log('props ->', props)
91 | return
92 | },
93 | })
94 |
95 | const initialProps = await Document.getInitialProps(ctx)
96 | // This is important. It prevents emotion to render invalid HTML.
97 | // See https://github.com/mui/material-ui/issues/26561#issuecomment-855286153
98 | const emotionStyles = extractCriticalToChunks(initialProps.html)
99 | const emotionStyleTags = emotionStyles.styles.map((style) => (
100 |
106 | ))
107 |
108 | return {
109 | ...initialProps,
110 | emotionStyleTags,
111 | }
112 | }
113 |
114 | export default MyDocument
115 |
--------------------------------------------------------------------------------
/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import dynamic from 'next/dynamic'
3 | import { NextPageWithLayout } from '@/interfaces/layout'
4 | import { MainLayout } from '@/components/layout'
5 | // import { HomeFeature, HomeHero, HomePopularCourse, HomeTestimonial, HomeOurMentors, DynamicHomeNewsLetter } from '@/components/home'
6 |
7 | const DynamicHomeHero = dynamic(() => import('../components/home/hero'))
8 | const DynamicHomeFeature = dynamic(() => import('../components/home/feature'))
9 | const DynamicHomePopularCourse = dynamic(() => import('../components/home/popular-courses'))
10 | const DynamicHomeTestimonial = dynamic(() => import('../components/home/testimonial'))
11 | const DynamicHomeOurMentors = dynamic(() => import('../components/home/mentors'))
12 | const DynamicHomeNewsLetter = dynamic(() => import('../components/home/newsletter'))
13 |
14 | const Home: NextPageWithLayout = () => {
15 | return (
16 | <>
17 |
18 |
19 |
20 |
21 |
22 |
23 | >
24 | )
25 | }
26 |
27 | Home.getLayout = (page) => {page}
28 |
29 | export default Home
30 |
--------------------------------------------------------------------------------
/src/providers/index.ts:
--------------------------------------------------------------------------------
1 | export { default as MUIProvider } from './mui-provider'
2 |
--------------------------------------------------------------------------------
/src/providers/mui-provider.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC, ReactNode } from 'react'
2 | import { ThemeProvider } from '@mui/material'
3 |
4 | import theme from '@/config/theme'
5 |
6 | interface Props {
7 | children: ReactNode
8 | }
9 |
10 | const MUIProvider: FC = ({ children }) => {
11 | return {children}
12 | }
13 |
14 | export default MUIProvider
15 |
--------------------------------------------------------------------------------
/src/styles/globals.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --color-background: #f5f5f9;
3 | --color-scrollbar: rgb(224, 224, 224);
4 | --color-scrollbar-hover: #bbb;
5 | }
6 |
7 | ::-webkit-scrollbar {
8 | width: 6px;
9 | height: 6px;
10 | }
11 | ::-webkit-scrollbar-track,
12 | ::-webkit-scrollbar-corner {
13 | background: var(--color-background);
14 | border-radius: 10px;
15 | }
16 | ::-webkit-scrollbar-thumb {
17 | background: var(--color-scrollbar);
18 | border-radius: 10px;
19 | }
20 | ::-webkit-scrollbar-track,
21 | ::-webkit-scrollbar-corner {
22 | background: var(--color-background);
23 | border-radius: 10px;
24 | }
25 |
26 | body {
27 | /* background-color: var(--color-background); */
28 | background-color: '#fff';
29 | }
30 |
31 | @-webkit-keyframes click_animation {
32 | from {
33 | -webkit-transform: scale(1);
34 | transform: scale(1);
35 | opacity: 0.3;
36 | }
37 | to {
38 | -webkit-transform: scale(5);
39 | transform: scale(5);
40 | opacity: 0;
41 | }
42 | }
43 |
44 | @keyframes click_animation {
45 | from {
46 | -webkit-transform: scale(1);
47 | transform: scale(1);
48 | opacity: 0.3;
49 | }
50 | to {
51 | -webkit-transform: scale(5);
52 | transform: scale(5);
53 | opacity: 0;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/styles/react-slick.css:
--------------------------------------------------------------------------------
1 | /* Arrows */
2 | .slick-prev,
3 | .slick-next {
4 | position: absolute;
5 | /*top: 50%;*/
6 | bottom: -56px;
7 |
8 | /*display: block;*/
9 |
10 | /*-webkit-transform: translate(0, -50%);*/
11 | /*-ms-transform: translate(0, -50%);*/
12 | /*transform: translate(0, -50%);*/
13 |
14 | /*cursor: pointer;*/
15 |
16 | /*border: none;*/
17 | /*outline: none;*/
18 | }
19 | /* .slick-prev:hover,
20 | .slick-prev:focus,
21 | .slick-next:hover,
22 | .slick-next:focus {
23 | outline: none;
24 | background: transparent;
25 | } */
26 | /*.slick-prev:hover:before,*/
27 | /*.slick-prev:focus:before,*/
28 | /*.slick-next:hover:before,*/
29 | /*.slick-next:focus:before*/
30 | /*{*/
31 | /* opacity: 1;*/
32 | /*}*/
33 | .slick-prev.slick-disabled:before,
34 | .slick-next.slick-disabled:before {
35 | opacity: 0.25;
36 | }
37 |
38 | .slick-prev {
39 | left: -12px;
40 | }
41 | [dir='rtl'] .slick-prev {
42 | left: 0;
43 | left: auto;
44 | }
45 |
46 | .slick-next {
47 | /*right: -25px;*/
48 | left: 100px;
49 | }
50 | [dir='rtl'] .slick-next {
51 | right: auto;
52 | left: -25px;
53 | }
54 |
55 | /* Dots */
56 | .slick-dotted.slick-slider {
57 | margin-bottom: 30px;
58 | }
59 |
60 | .slick-dots {
61 | position: absolute;
62 | bottom: -25px;
63 |
64 | display: block;
65 |
66 | width: 100%;
67 | padding: 0;
68 | margin: 0;
69 |
70 | list-style: none;
71 |
72 | text-align: center;
73 | }
74 | .slick-dots li {
75 | position: relative;
76 |
77 | display: inline-block;
78 |
79 | width: 20px;
80 | height: 20px;
81 | margin: 0 5px;
82 | padding: 0;
83 |
84 | cursor: pointer;
85 | }
86 | .slick-dots li button {
87 | line-height: 0;
88 |
89 | display: block;
90 |
91 | width: 20px;
92 | height: 20px;
93 | padding: 5px;
94 |
95 | cursor: pointer;
96 |
97 | border: 0;
98 | outline: none;
99 | background: transparent;
100 | }
101 | .slick-dots li button:hover,
102 | .slick-dots li button:focus {
103 | outline: none;
104 | }
105 | .slick-dots li button:hover:before,
106 | .slick-dots li button:focus:before {
107 | opacity: 1;
108 | }
109 | .slick-dots li button:before {
110 | font-size: 6px;
111 | line-height: 20px;
112 |
113 | position: absolute;
114 | top: 0;
115 | left: 0;
116 |
117 | width: 20px;
118 | height: 20px;
119 |
120 | content: '•';
121 | text-align: center;
122 |
123 | opacity: 0.25;
124 | color: black;
125 |
126 | -webkit-font-smoothing: antialiased;
127 | -moz-osx-font-smoothing: grayscale;
128 | }
129 | .slick-dots li.slick-active button:before {
130 | opacity: 0.75;
131 | color: black;
132 | }
133 |
--------------------------------------------------------------------------------
/src/utils/emotion-cache.ts:
--------------------------------------------------------------------------------
1 | import createCache, { EmotionCache } from '@emotion/cache'
2 |
3 | // prepend: true moves MUI styles to the top of the so they're loaded first.
4 | // It allows developers to easily override MUI styles with other styling solutions, like CSS modules.
5 | export function createEmotionCache(): EmotionCache {
6 | return createCache({ key: 'css', prepend: true })
7 | }
8 |
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './emotion-cache'
2 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["es6", "dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "baseUrl": ".",
18 | "paths": {
19 | "@/*": ["src/*"]
20 | }
21 | },
22 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
23 | "exclude": ["node_modules"]
24 | }
25 |
--------------------------------------------------------------------------------