├── README.md ├── .eslintrc ├── src ├── components │ ├── ExamCard.tsx │ └── NavBar.tsx ├── pages │ ├── 404.tsx │ ├── exams │ │ ├── revise │ │ │ └── [slug].tsx │ │ ├── study │ │ │ └── [slug].tsx │ │ ├── mock-test │ │ │ └── [slug].tsx │ │ └── index.tsx │ ├── _app.tsx │ ├── _document.tsx │ ├── api │ │ └── exams │ │ │ ├── index.ts │ │ │ └── aws │ │ │ └── [...slug].ts │ └── index.tsx ├── app │ ├── theme.tsx │ └── layout.tsx ├── types │ ├── Question.ts │ ├── ExamListitem.ts │ ├── Api.ts │ ├── Exam.ts │ └── _ExamMeta.ts ├── services │ └── apiClient.ts └── utils │ └── api.ts ├── public ├── favicon.ico ├── vercel.svg ├── logo-dark.svg └── logo-light.svg ├── next.config.js ├── .prettierrc ├── next-env.d.ts ├── .gitignore ├── tsconfig.json ├── package.json └── data └── examlist.json /README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next", "next/core-web-vitals"] 3 | } 4 | -------------------------------------------------------------------------------- /src/components/ExamCard.tsx: -------------------------------------------------------------------------------- 1 | export default function ExamCard() { 2 | return
ExamCard
; 3 | } 4 | -------------------------------------------------------------------------------- /src/pages/404.tsx: -------------------------------------------------------------------------------- 1 | export default function NotFound() { 2 | return

404 - Page Not Found

; 3 | } 4 | -------------------------------------------------------------------------------- /src/pages/exams/revise/[slug].tsx: -------------------------------------------------------------------------------- 1 | export default function Revise() { 2 | return
Study
3 | } 4 | -------------------------------------------------------------------------------- /src/pages/exams/study/[slug].tsx: -------------------------------------------------------------------------------- 1 | export default function Study() { 2 | return
Study
3 | } 4 | -------------------------------------------------------------------------------- /src/pages/exams/mock-test/[slug].tsx: -------------------------------------------------------------------------------- 1 | export default function MockTest() { 2 | return
Study
3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thesohailjafri/Aws-Exam-Preparation-Material/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | images: { 3 | domains: ['res.cloudinary.com', 'imgur.com'], 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /src/app/theme.tsx: -------------------------------------------------------------------------------- 1 | import { extendTheme } from '@chakra-ui/react'; 2 | const config = { 3 | initialColorMode: 'dark', 4 | useSystemColorMode: false, 5 | }; 6 | const theme = extendTheme({ config }); 7 | export default theme; 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "semi": false, 7 | "jsxSingleQuote": true, 8 | "jsxBracketSameLine": false, 9 | "arrowParens": "always", 10 | "printWidth": 100 11 | } 12 | -------------------------------------------------------------------------------- /src/pages/exams/index.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Text } from '@chakra-ui/react'; 2 | 3 | export default function ExamsPages() { 4 | return ( 5 | 6 | 7 | Available Exams 8 | 9 | 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // NOTE: This file should not be edited 6 | // see https://nextjs.org/docs/basic-features/typescript for more information. 7 | -------------------------------------------------------------------------------- /src/types/Question.ts: -------------------------------------------------------------------------------- 1 | // Types definition for Question 2 | 3 | import { ExamType, Option } from "./_ExamMeta" 4 | 5 | 6 | export default interface Question { 7 | id: string | number; 8 | question: string; 9 | questionType: ExamType; 10 | options: Option[]; 11 | answer: string[]; 12 | answerDescription: string; 13 | answerLink: string; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Container } from '@chakra-ui/react'; 2 | import NavBar from '../components/NavBar'; 3 | 4 | export default function RootLayout({ children }: { children: React.ReactNode }) { 5 | return ( 6 | <> 7 | 8 | 9 | {children} 10 | 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { AppProps } from 'next/app'; 2 | import { ChakraProvider } from '@chakra-ui/react'; 3 | import theme from '../app/theme'; 4 | import RootLayout from '../app/layout'; 5 | 6 | function MyApp({ Component, pageProps }: AppProps) { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | } 15 | export default MyApp; 16 | -------------------------------------------------------------------------------- /src/types/ExamListitem.ts: -------------------------------------------------------------------------------- 1 | export interface ExamListitem { 2 | exam: string 3 | examCode: string 4 | examLink: string 5 | examPriceInDollar: number | string 6 | examDurationInMinutes: number | string 7 | examPassingScore: number | string 8 | examMaxScore: number | string 9 | examLanguage: string 10 | examFormat: string 11 | examType: string 12 | examAudience: string 13 | examObjectiveLink: string 14 | examImage: string 15 | examDomains: string[] 16 | } 17 | -------------------------------------------------------------------------------- /src/types/Api.ts: -------------------------------------------------------------------------------- 1 | export type Method = 2 | | 'GET' 3 | | 'DELETE' 4 | | 'HEAD' 5 | | 'OPTIONS' 6 | | 'POST' 7 | | 'PUT' 8 | | 'PATCH' 9 | | 'PURGE' 10 | | 'LINK' 11 | | 'UNLINK'; 12 | 13 | // Shape of the response when an error is thrown 14 | export interface ErrorResponse { 15 | error: { 16 | message: string; 17 | err?: any; // Sent for unhandled errors reulting in 500 18 | }; 19 | status?: number; // Sent for unhandled errors reulting in 500 20 | } 21 | -------------------------------------------------------------------------------- /src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import { ColorModeScript } from '@chakra-ui/react'; 2 | import { Html, Head, Main, NextScript } from 'next/document'; 3 | import theme from '../app/theme'; 4 | export default function Document() { 5 | return ( 6 | 7 | 8 | 9 | {/* 👇 Here's the script */} 10 | 11 |
12 | 13 | 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /.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 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | -------------------------------------------------------------------------------- /src/types/Exam.ts: -------------------------------------------------------------------------------- 1 | import { ExamType } from "./_ExamMeta" 2 | import Question from "./Question" 3 | 4 | // ExamMeta Type Definition 5 | export default interface Exam { 6 | exam: string; 7 | examCode: string; 8 | examLink: string; 9 | examPriceInDollar: number; 10 | examDurationInMinutes: number; 11 | examPassingScore: number; 12 | examMaxScore: number; 13 | examLanguage: string; 14 | examFormat: string; 15 | examType: string; 16 | examAudience: string; 17 | examObjectiveLink: string; 18 | questionTypes: ExamType[]; 19 | questions: Question[], 20 | } -------------------------------------------------------------------------------- /src/types/_ExamMeta.ts: -------------------------------------------------------------------------------- 1 | // Type definition for ExamMeta 2 | 3 | export interface Option { 4 | a: string | undefined; 5 | b: string | undefined; 6 | c: string | undefined; 7 | d: string | undefined; 8 | e: string | undefined; 9 | } 10 | 11 | export type ExamType = 'single' | 'multiple'; 12 | 13 | export type ExamDomain = 14 | | 'Cloud Computing' 15 | | 'Data Science' 16 | | 'Machine Learning' 17 | | 'Web Development' 18 | | 'Mobile Development' 19 | | 'DevOps' 20 | | 'Cyber Security' 21 | | 'Backend Development' 22 | | 'Frontend Development' 23 | | 'Other'; 24 | -------------------------------------------------------------------------------- /src/services/apiClient.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosRequestConfig } from 'axios' 2 | 3 | const axiosInstance = axios.create({ 4 | baseURL: '/api', 5 | }) 6 | 7 | class APIClient { 8 | endpoint: string 9 | constructor(endpoint: string) { 10 | this.endpoint = endpoint 11 | } 12 | 13 | getAll = async (config: AxiosRequestConfig) => { 14 | return axiosInstance.get(this.endpoint, config).then((response) => response.data) 15 | } 16 | 17 | getOne = async (slug: string) => { 18 | return axiosInstance.get(`${this.endpoint}/${slug}`).then((response) => response.data) 19 | } 20 | } 21 | 22 | export default APIClient 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["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 | "baseUrl": ".", 16 | "paths": { 17 | "@/*": ["src/*"] 18 | }, 19 | "jsx": "preserve", 20 | "incremental": true, 21 | "plugins": [ 22 | { 23 | "name": "next" 24 | } 25 | ] 26 | }, 27 | "exclude": ["node_modules", ".next", "out"], 28 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.js", ".next/types/**/*.ts"] 29 | } 30 | -------------------------------------------------------------------------------- /src/pages/api/exams/index.ts: -------------------------------------------------------------------------------- 1 | import { ExamListitem } from '@/types/ExamListitem'; 2 | import { apiHandler } from '@/utils/api'; 3 | import { promises as fs } from 'fs'; 4 | import type { NextApiRequest, NextApiResponse } from 'next'; 5 | import path from 'path'; 6 | type Data = { 7 | exams: ExamListitem[]; 8 | count: number; 9 | }; 10 | 11 | async function getExamList(req: NextApiRequest, res: NextApiResponse) { 12 | const { domain } = req.query; 13 | const dataDirectory = path.join(process.cwd(), 'data'); 14 | const fileContents = await fs.readFile(dataDirectory + '/examlist.json', 'utf8'); 15 | let data = JSON.parse(fileContents); 16 | if (domain) { 17 | data = data.filter((exam: any) => exam.domains.includes(domain)); 18 | } 19 | res.status(200).json({ exams: data, count: data.length }); 20 | } 21 | 22 | export default apiHandler({ 23 | GET: getExamList, 24 | }); 25 | -------------------------------------------------------------------------------- /src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import type { InferGetStaticPropsType, GetStaticProps } from 'next' 3 | import { ExamListitem } from '../types/ExamListitem' 4 | interface Exams { 5 | exams: ExamListitem[] 6 | count: number 7 | } 8 | 9 | export const getStaticProps = (async (context) => { 10 | const res = await fetch('http://localhost:3000/api/exams') 11 | const examsData = await res.json() 12 | return { props: { examsData } } 13 | }) satisfies GetStaticProps<{ 14 | examsData: Exams 15 | }> 16 | 17 | export default function Home({ examsData }: InferGetStaticPropsType) { 18 | console.log(examsData) 19 | 20 | return ( 21 |
22 | 23 | AWS Exam Prep App 24 | 25 |
26 |

AWS Exam Prep App

27 |
28 |
29 | ) 30 | } 31 | 32 | // read data/examlist.json and create pages for each exam 33 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aws-exam-preparation", 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 | "devDependencies": { 12 | "@types/axios": "^0.14.0", 13 | "@types/http-errors": "^2.0.2", 14 | "@types/lodash": "^4.14.199", 15 | "@types/node": "^20.7.1", 16 | "@types/react": "^18.2.23", 17 | "autoprefixer": "^10.4.16", 18 | "babel-plugin-import": "^1.13.8", 19 | "babel-plugin-macros": "^3.1.0", 20 | "babel-plugin-module-resolver": "^5.0.0", 21 | "eslint": "^8.50.0", 22 | "eslint-config-next": "^13.5.3", 23 | "typescript": "^5.2.2" 24 | }, 25 | "dependencies": { 26 | "@chakra-ui/icons": "^2.1.1", 27 | "@chakra-ui/next-js": "^2.1.5", 28 | "@chakra-ui/react": "^2.8.1", 29 | "@emotion/react": "^11.11.1", 30 | "@emotion/styled": "^11.11.0", 31 | "axios": "^1.5.1", 32 | "date-fns": "^2.30.0", 33 | "framer-motion": "^10.16.4", 34 | "http-errors": "^2.0.0", 35 | "lodash": "^4.17.21", 36 | "next": "^13.5.3", 37 | "react": "^18.2.0", 38 | "react-dom": "^18.2.0", 39 | "react-query": "^3.39.3" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/pages/api/exams/aws/[...slug].ts: -------------------------------------------------------------------------------- 1 | import { ExamListitem } from '@/types/ExamListitem' 2 | import { apiHandler } from '@/utils/api' 3 | import { promises as fs } from 'fs' 4 | import type { NextApiRequest, NextApiResponse } from 'next' 5 | import path from 'path' 6 | import exam from '..' 7 | interface Exam extends ExamListitem { 8 | questions: [] 9 | } 10 | 11 | type Query = { 12 | page?: number 13 | limit?: number 14 | view_all?: boolean 15 | } 16 | 17 | async function getExamList(req: NextApiRequest, res: NextApiResponse) { 18 | const { 19 | page = 1, // Current page number 20 | limit = 20, // Number of items per page 21 | view_all = false, // View all items 22 | }: Query = req.query 23 | 24 | let examFileLocation = req.url?.replace('/api/exam', '') 25 | examFileLocation = examFileLocation?.split('?')[0] 26 | const dataDirectory = path.join(process.cwd(), 'data') 27 | const fileContents = await fs.readFile(dataDirectory + `${examFileLocation}.json`, 'utf8') 28 | let data = JSON.parse(fileContents) 29 | if (!view_all) { 30 | data.questions = data.questions.slice((page - 1) * limit, page * limit) 31 | } 32 | 33 | res.status(200).json(data) 34 | } 35 | 36 | export default apiHandler({ 37 | GET: getExamList, 38 | }) 39 | -------------------------------------------------------------------------------- /src/utils/api.ts: -------------------------------------------------------------------------------- 1 | import createHttpError from 'http-errors'; 2 | 3 | import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'; 4 | import { ErrorResponse, Method } from '@/types/Api'; 5 | 6 | type ApiMethodHandlers = { 7 | [key in Uppercase]?: NextApiHandler; 8 | }; 9 | 10 | function errorHandler( 11 | err: { 12 | statusCode: number; 13 | message: string; 14 | expose: boolean; 15 | }, 16 | res: NextApiResponse, 17 | ) { 18 | // Errors with statusCode >= 500 are should not be exposed 19 | if (createHttpError.isHttpError(err) && err.expose) { 20 | // Handle all errors thrown by http-errors module 21 | return res.status(err.statusCode).json({ error: { message: err.message } }); 22 | } else { 23 | // default to 500 server error 24 | console.error(err); 25 | return res.status(500).json({ 26 | error: { message: 'Internal Server Error', err: err }, 27 | status: createHttpError.isHttpError(err) ? err.statusCode : 500, 28 | }); 29 | } 30 | } 31 | 32 | export function apiHandler(handler: ApiMethodHandlers) { 33 | return async (req: NextApiRequest, res: NextApiResponse) => { 34 | try { 35 | const method = req.method ? (req.method.toUpperCase() as keyof ApiMethodHandlers) : undefined; 36 | 37 | // check if handler supports current HTTP method 38 | if (!method) 39 | throw new createHttpError.MethodNotAllowed(`No method specified on path ${req.url}!`); 40 | 41 | const methodHandler = handler[method]; 42 | if (!methodHandler) 43 | throw new createHttpError.MethodNotAllowed( 44 | `Method ${req.method} Not Allowed on path ${req.url}!`, 45 | ); 46 | 47 | // call method handler 48 | await methodHandler(req, res); 49 | } catch (err: any) { 50 | // global error handler 51 | errorHandler(err, res); 52 | } 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /data/examlist.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "exam": "AWS Certified Cloud Practitioner", 4 | "examCode": "AWS-CCP", 5 | "examLink": "https://aws.amazon.com/certification/certified-cloud-practitioner/", 6 | "examPriceInDollar": "100", 7 | "examDurationInMinutes": "90", 8 | "examPassingScore": "700", 9 | "examMaxScore": "1000", 10 | "examLanguage": "English, Japanese, Korean, Simplified Chinese", 11 | "examFormat": "Multiple choice, multiple answer", 12 | "examType": "Associate", 13 | "examAudience": "Individuals who have basic knowledge of AWS Cloud", 14 | "examObjectiveLink": "https://d1.awsstatic.com/training-and-certification/docs-cloud-practitioner/AWS-Certified-Cloud-Practitioner_Exam-Guide.pdf", 15 | "examImage": "/images/aws-certified-cloud-practitioner.png", 16 | "examDomains": [ 17 | "Cloud Computing", 18 | "Data Science", 19 | "Machine Learning", 20 | "Web Development", 21 | "Mobile Development", 22 | "DevOps", 23 | "Cyber Security" 24 | ], 25 | "questionTypes": ["single", "multiple"] 26 | }, 27 | { 28 | "exam": "AWS Solutions Architect Associate", 29 | "examCode": "AWS-SAA", 30 | "examLink": "https://aws.amazon.com/certification/certified-solutions-architect-associate/", 31 | "examPriceInDollar": "150", 32 | "examDurationInMinutes": "130", 33 | "examPassingScore": "720", 34 | "examMaxScore": "1000", 35 | "examLanguage": "English, Japanese, Korean, Simplified Chinese", 36 | "examFormat": "Multiple choice, multiple answer", 37 | "examType": "Associate", 38 | "examAudience": "Individuals who have basic knowledge of AWS Cloud", 39 | "examObjectiveLink": "https://d1.awsstatic.com/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Exam-Guide.pdf", 40 | "examImage": "/images/aws-certified-solutions-architect-associate.png", 41 | "examDomains": [ 42 | "Cloud Computing", 43 | "Data Science", 44 | "Machine Learning", 45 | "Web Development", 46 | "Mobile Development", 47 | "DevOps", 48 | "Cyber Security" 49 | ] 50 | } 51 | ] 52 | -------------------------------------------------------------------------------- /src/components/NavBar.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { 4 | ChevronDownIcon, 5 | ChevronRightIcon, 6 | CloseIcon, 7 | HamburgerIcon, 8 | MoonIcon, 9 | SunIcon, 10 | } from '@chakra-ui/icons' 11 | import { 12 | Box, 13 | Button, 14 | Collapse, 15 | Flex, 16 | Icon, 17 | IconButton, 18 | Image, 19 | Popover, 20 | PopoverContent, 21 | PopoverTrigger, 22 | Stack, 23 | Text, 24 | useColorMode, 25 | useColorModeValue, 26 | useDisclosure, 27 | } from '@chakra-ui/react' 28 | import Link from 'next/link' 29 | 30 | export default function WithSubnavigation() { 31 | const { isOpen, onToggle } = useDisclosure() 32 | 33 | return ( 34 | 40 | 49 | 50 | : } 53 | variant={'ghost'} 54 | aria-label={'Toggle Navigation'} 55 | _hover={{ 56 | bg: useColorModeValue('orange.200', 'orange.800'), 57 | }} 58 | /> 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | ) 78 | } 79 | 80 | const Logo = () => { 81 | const { colorMode } = useColorMode() 82 | return ( 83 | 84 | logo 91 | 92 | ) 93 | } 94 | 95 | const DesktopNav = () => { 96 | const linkColor = useColorModeValue('black', 'white') 97 | const linkHoverColor = useColorModeValue('orange.800', 'orange.200') 98 | const popoverContentBgColor = useColorModeValue('orange.100', 'orange.900') 99 | 100 | return ( 101 | 102 | {NAV_ITEMS.map((navItem) => ( 103 | 104 | 105 | 106 | 118 | {navItem.label} 119 | 120 | 121 | 122 | {navItem.children && ( 123 | 131 | 132 | {navItem.children.map((child) => ( 133 | 134 | ))} 135 | 136 | 137 | )} 138 | 139 | 140 | ))} 141 | 142 | ) 143 | } 144 | 145 | const DesktopSubNav = ({ label, href, subLabel }: NavItem) => { 146 | return ( 147 | 148 | 149 | 150 | 151 | {label} 152 | 153 | {subLabel} 154 | 155 | 164 | 165 | 166 | 167 | 168 | ) 169 | } 170 | 171 | const MobileNav = () => { 172 | return ( 173 | 174 | {NAV_ITEMS.map((navItem) => ( 175 | 176 | ))} 177 | 178 | ) 179 | } 180 | 181 | const MobileNavItem = ({ label, children, href }: NavItem) => { 182 | const { isOpen, onToggle } = useDisclosure() 183 | const linkColor = useColorModeValue('black', 'white') 184 | const linkHoverColor = useColorModeValue('orange.800', 'orange.200') 185 | return ( 186 | 187 | 197 | 205 | {label} 206 | 207 | {children && ( 208 | 215 | )} 216 | 217 | 218 | 219 | 220 | {children && 221 | children.map((child) => ( 222 | 223 | {child.label} 224 | 225 | ))} 226 | 227 | 228 | 229 | ) 230 | } 231 | 232 | interface NavItem { 233 | label: string 234 | subLabel?: string 235 | children?: Array 236 | href?: string 237 | } 238 | 239 | const NAV_ITEMS: Array = [ 240 | { 241 | label: 'View All Exams', 242 | href: '/exams', 243 | }, 244 | { 245 | label: 'Popular Exams', 246 | href: '/exams/popular', 247 | }, 248 | { 249 | label: 'My Accessments', 250 | href: '/exams/accessments', 251 | }, 252 | { 253 | label: 'Want to Contribute?', 254 | href: 'https://github.com/thesohailjafri/Aws-Exam-Preparation-Material/issues', 255 | }, 256 | ] 257 | 258 | const ColorModeSwitch = () => { 259 | const { toggleColorMode, colorMode } = useColorMode() 260 | 261 | return ( 262 | : } 265 | variant={'ghost'} 266 | aria-label={'Toggle Navigation'} 267 | _hover={{ 268 | bg: useColorModeValue('orange.200', 'orange.800'), 269 | }} 270 | /> 271 | ) 272 | } 273 | -------------------------------------------------------------------------------- /public/logo-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/logo-light.svg: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------