├── .eslintrc.cjs
├── .gitignore
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
└── vite.svg
├── src
├── App.css
├── App.tsx
├── assets
│ ├── icons
│ │ ├── index.tsx
│ │ └── src
│ │ │ ├── icon-cancel.tsx
│ │ │ ├── icon-checkmark.tsx
│ │ │ ├── icon-congrats.tsx
│ │ │ ├── icon-degree.tsx
│ │ │ ├── icon-down-arrow-lg.tsx
│ │ │ ├── icon-down-arrow-sm.tsx
│ │ │ ├── icon-down-arrow.tsx
│ │ │ ├── icon-google.tsx
│ │ │ ├── icon-grey-heart.tsx
│ │ │ ├── icon-language.tsx
│ │ │ ├── icon-left-arrow.tsx
│ │ │ ├── icon-lock.tsx
│ │ │ ├── icon-mail.tsx
│ │ │ ├── icon-map.tsx
│ │ │ ├── icon-ok.tsx
│ │ │ ├── icon-outlook.tsx
│ │ │ ├── icon-plus.tsx
│ │ │ ├── icon-right-arrow-lg.tsx
│ │ │ ├── icon-right-arrow.tsx
│ │ │ ├── icon-search.tsx
│ │ │ ├── icon-star.tsx
│ │ │ ├── icon-toolbox.tsx
│ │ │ ├── icon-up-arrow.tsx
│ │ │ ├── icon-user.tsx
│ │ │ └── icon-white-heart.tsx
│ └── imgs
│ │ ├── index.tsx
│ │ └── src
│ │ ├── admin-avatar-lg.png
│ │ ├── admin-avatar.png
│ │ ├── bg-signup.jpg
│ │ ├── img-banner.jpg
│ │ ├── img-card-lg-01.png
│ │ ├── img-card-lg-02.png
│ │ ├── img-card-lg-03.png
│ │ ├── img-card-md-01.png
│ │ ├── img-card-md-02.png
│ │ ├── img-card-md-03.png
│ │ ├── img-card-md-04.png
│ │ ├── table-user-avatar.png
│ │ └── user-avatar.png
├── components
│ ├── avatar
│ │ ├── avatar.tsx
│ │ └── index.tsx
│ ├── button
│ │ ├── button.tsx
│ │ └── index.tsx
│ ├── card
│ │ ├── card.tsx
│ │ └── index.tsx
│ ├── checkbox
│ │ ├── checkbox.tsx
│ │ └── index.tsx
│ ├── dropdown
│ │ ├── dropdown.tsx
│ │ └── index.tsx
│ ├── input
│ │ ├── index.tsx
│ │ └── input.tsx
│ ├── modal
│ │ ├── index.tsx
│ │ └── modal.tsx
│ ├── radio-group
│ │ ├── index.tsx
│ │ └── radio-group.tsx
│ ├── select
│ │ ├── index.tsx
│ │ └── select.tsx
│ ├── slider
│ │ ├── index.tsx
│ │ └── slider.tsx
│ ├── switch
│ │ ├── index.tsx
│ │ └── switch.tsx
│ ├── table
│ │ ├── index.tsx
│ │ └── table.tsx
│ ├── textarea
│ │ ├── index.tsx
│ │ └── textarea.tsx
│ └── tour-stepper
│ │ ├── index.tsx
│ │ └── tour-stepper.tsx
├── index.css
├── layout
│ ├── index.tsx
│ └── nav.tsx
├── main.tsx
├── pages
│ ├── admin
│ │ ├── analytics.tsx
│ │ ├── dashboard.tsx
│ │ ├── index.tsx
│ │ ├── requests.tsx
│ │ ├── settings.tsx
│ │ └── werknemers.tsx
│ ├── all-courses
│ │ └── all-courses.tsx
│ ├── auth
│ │ ├── layout
│ │ │ └── index.tsx
│ │ ├── new-password
│ │ │ └── index.tsx
│ │ ├── reset-password
│ │ │ └── index.tsx
│ │ └── signin
│ │ │ └── index.tsx
│ └── overview
│ │ ├── components
│ │ ├── banner.tsx
│ │ └── tour.tsx
│ │ └── index.tsx
├── router
│ └── index.tsx
└── vite-env.d.ts
├── tailwind.config.js
├── tsconfig.json
├── tsconfig.node.json
├── vercel.json
└── vite.config.ts
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | 'plugin:react-hooks/recommended',
8 | ],
9 | ignorePatterns: ['dist', '.eslintrc.cjs'],
10 | parser: '@typescript-eslint/parser',
11 | plugins: ['react-refresh'],
12 | rules: {
13 | 'react-refresh/only-export-components': [
14 | 'warn',
15 | { allowConstantExport: true },
16 | ],
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React + TypeScript + Vite
2 |
3 | This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4 |
5 | Currently, two official plugins are available:
6 |
7 | - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8 | - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9 |
10 | ## Expanding the ESLint configuration
11 |
12 | If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13 |
14 | - Configure the top-level `parserOptions` property like this:
15 |
16 | ```js
17 | export default {
18 | // other rules...
19 | parserOptions: {
20 | ecmaVersion: 'latest',
21 | sourceType: 'module',
22 | project: ['./tsconfig.json', './tsconfig.node.json'],
23 | tsconfigRootDir: __dirname,
24 | },
25 | }
26 | ```
27 |
28 | - Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
29 | - Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
30 | - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
31 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Vite + React + TS
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ace-academy",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0",
15 | "react-router-dom": "^6.20.1"
16 | },
17 | "devDependencies": {
18 | "@types/react": "^18.2.43",
19 | "@types/react-dom": "^18.2.17",
20 | "@typescript-eslint/eslint-plugin": "^6.14.0",
21 | "@typescript-eslint/parser": "^6.14.0",
22 | "@vitejs/plugin-react": "^4.2.1",
23 | "autoprefixer": "^10.4.16",
24 | "eslint": "^8.55.0",
25 | "eslint-plugin-react-hooks": "^4.6.0",
26 | "eslint-plugin-react-refresh": "^0.4.5",
27 | "postcss": "^8.4.32",
28 | "tailwindcss": "^3.3.6",
29 | "typescript": "^5.2.2",
30 | "vite": "^5.0.8"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/App.css
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import './App.css'
2 | import Router from './router'
3 | import { BrowserRouter } from 'react-router-dom';
4 | import AppLayout from './layout';
5 |
6 | function App() {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 | )
14 | }
15 |
16 | export default App
17 |
--------------------------------------------------------------------------------
/src/assets/icons/index.tsx:
--------------------------------------------------------------------------------
1 | import IconGoogle from './src/icon-google.tsx'
2 | import IconOutlook from './src/icon-outlook.tsx'
3 | import IconMail from './src/icon-mail.tsx'
4 | import IconLock from './src/icon-lock.tsx'
5 | import IconCheckMark from './src/icon-checkmark.tsx'
6 | import IconDownArrow from './src/icon-down-arrow.tsx'
7 | import IconDegree from './src/icon-degree.tsx'
8 | import IconMap from './src/icon-map.tsx'
9 | import IconToolbox from './src/icon-toolbox.tsx'
10 | import IconCongrats from './src/icon-congrats.tsx'
11 | import IconSearch from './src/icon-search.tsx'
12 | import IconStar from './src/icon-star.tsx'
13 | import IconWhiteHeart from './src/icon-white-heart.tsx'
14 | import IconGreyHeart from './src/icon-grey-heart.tsx'
15 | import IconLeftArrow from './src/icon-left-arrow.tsx'
16 | import IconRightArrow from './src/icon-right-arrow.tsx'
17 | import IconLgRightArrow from './src/icon-right-arrow-lg.tsx'
18 | import IconLgDownArrow from './src/icon-down-arrow-lg.tsx'
19 | import IconSmDownArrow from './src/icon-down-arrow-sm.tsx'
20 | import IconUpArrow from './src/icon-up-arrow.tsx'
21 | import IconLanguage from './src/icon-language.tsx'
22 | import IconUser from './src/icon-user.tsx'
23 | import IconOk from './src/icon-ok.tsx'
24 | import IconCancel from './src/icon-cancel.tsx'
25 | import IconPlus from './src/icon-plus.tsx'
26 |
27 | export {
28 | IconGoogle,
29 | IconOutlook,
30 | IconMail,
31 | IconLock,
32 | IconCheckMark,
33 | IconDownArrow,
34 | IconDegree,
35 | IconMap,
36 | IconToolbox,
37 | IconCongrats,
38 | IconSearch,
39 | IconStar,
40 | IconWhiteHeart,
41 | IconGreyHeart,
42 | IconLeftArrow,
43 | IconRightArrow,
44 | IconLgDownArrow,
45 | IconUpArrow,
46 | IconLanguage,
47 | IconSmDownArrow,
48 | IconLgRightArrow,
49 | IconUser,
50 | IconOk,
51 | IconCancel,
52 | IconPlus
53 | }
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-cancel.tsx:
--------------------------------------------------------------------------------
1 | const IconCancel = () => {
2 | return (
3 |
7 | )
8 | }
9 |
10 | export default IconCancel
11 |
12 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-checkmark.tsx:
--------------------------------------------------------------------------------
1 | const IconCheckMark = () => {
2 | return (
3 |
72 | );
73 | };
74 |
75 | export default IconCheckMark;
76 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-congrats.tsx:
--------------------------------------------------------------------------------
1 | const IconCongrats = () => {
2 | return (
3 |
12 | )
13 | }
14 |
15 | export default IconCongrats
16 |
17 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-degree.tsx:
--------------------------------------------------------------------------------
1 | const IconDegree = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconDegree
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-down-arrow-lg.tsx:
--------------------------------------------------------------------------------
1 | const IconLgDownArrow = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconLgDownArrow
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-down-arrow-sm.tsx:
--------------------------------------------------------------------------------
1 | const IconWhiteHeart = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconWhiteHeart
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-down-arrow.tsx:
--------------------------------------------------------------------------------
1 | const IconDownArrow = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconDownArrow
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-google.tsx:
--------------------------------------------------------------------------------
1 | const IconGoogle = () => {
2 | return (
3 |
8 | )
9 | }
10 |
11 | export default IconGoogle
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-grey-heart.tsx:
--------------------------------------------------------------------------------
1 | const IconGreyHeart = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconGreyHeart
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-language.tsx:
--------------------------------------------------------------------------------
1 | const IconLanguage = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconLanguage
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-left-arrow.tsx:
--------------------------------------------------------------------------------
1 | const IconLeftArrow = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconLeftArrow
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-lock.tsx:
--------------------------------------------------------------------------------
1 | const IconLock = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconLock
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-mail.tsx:
--------------------------------------------------------------------------------
1 | const IconMail = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconMail
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-map.tsx:
--------------------------------------------------------------------------------
1 | const IconMap = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconMap
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-ok.tsx:
--------------------------------------------------------------------------------
1 | const IconOk = () => {
2 | return (
3 |
7 | )
8 | }
9 |
10 | export default IconOk
11 |
12 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-outlook.tsx:
--------------------------------------------------------------------------------
1 | const IconOutlook = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconOutlook
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-plus.tsx:
--------------------------------------------------------------------------------
1 | const IconPlus = () => {
2 | return (
3 |
7 | )
8 | }
9 |
10 | export default IconPlus
11 |
12 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-right-arrow-lg.tsx:
--------------------------------------------------------------------------------
1 | const IconRightArrowLg = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconRightArrowLg
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-right-arrow.tsx:
--------------------------------------------------------------------------------
1 | const IconRightArrow = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconRightArrow
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-search.tsx:
--------------------------------------------------------------------------------
1 | const IconSearch = () => {
2 | return (
3 |
9 | )
10 | }
11 |
12 | export default IconSearch
13 |
14 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-star.tsx:
--------------------------------------------------------------------------------
1 | const IconStar = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconStar
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-toolbox.tsx:
--------------------------------------------------------------------------------
1 | const IconToolbox = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconToolbox
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-up-arrow.tsx:
--------------------------------------------------------------------------------
1 | const IconUpArrow = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconUpArrow
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-user.tsx:
--------------------------------------------------------------------------------
1 | const IconUser = () => {
2 | return (
3 |
7 | )
8 | }
9 |
10 | export default IconUser
11 |
12 |
--------------------------------------------------------------------------------
/src/assets/icons/src/icon-white-heart.tsx:
--------------------------------------------------------------------------------
1 | const IconWhiteHeart = () => {
2 | return (
3 |
6 | )
7 | }
8 |
9 | export default IconWhiteHeart
10 |
11 |
--------------------------------------------------------------------------------
/src/assets/imgs/index.tsx:
--------------------------------------------------------------------------------
1 | import BgSignUp from './src/bg-signup.jpg'
2 | import CardImgLg01 from './src/img-card-lg-01.png'
3 | import CardImgLg02 from './src/img-card-lg-02.png'
4 | import CardImgLg03 from './src/img-card-lg-03.png'
5 | import CardImgMd01 from './src/img-card-md-01.png'
6 | import CardImgMd02 from './src/img-card-md-02.png'
7 | import CardImgMd03 from './src/img-card-md-03.png'
8 | import CardImgMd04 from './src/img-card-md-04.png'
9 | import BannerImg from './src/img-banner.jpg'
10 | import UserAvatar from './src/user-avatar.png'
11 | import AdminAvatar from './src/admin-avatar.png'
12 | import TableUserAvatar from './src/table-user-avatar.png'
13 | import AdminAvatarLg from './src/admin-avatar-lg.png'
14 |
15 | export {
16 | BgSignUp,
17 | CardImgLg01,
18 | CardImgLg02,
19 | CardImgLg03,
20 | CardImgMd01,
21 | CardImgMd02,
22 | CardImgMd03,
23 | CardImgMd04,
24 | BannerImg,
25 | UserAvatar,
26 | AdminAvatar,
27 | TableUserAvatar,
28 | AdminAvatarLg
29 | }
--------------------------------------------------------------------------------
/src/assets/imgs/src/admin-avatar-lg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/admin-avatar-lg.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/admin-avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/admin-avatar.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/bg-signup.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/bg-signup.jpg
--------------------------------------------------------------------------------
/src/assets/imgs/src/img-banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/img-banner.jpg
--------------------------------------------------------------------------------
/src/assets/imgs/src/img-card-lg-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/img-card-lg-01.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/img-card-lg-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/img-card-lg-02.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/img-card-lg-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/img-card-lg-03.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/img-card-md-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/img-card-md-01.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/img-card-md-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/img-card-md-02.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/img-card-md-03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/img-card-md-03.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/img-card-md-04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/img-card-md-04.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/table-user-avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/table-user-avatar.png
--------------------------------------------------------------------------------
/src/assets/imgs/src/user-avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JamesWangDev/ace-academy-react/4f61355a27d241223595f17657ad45d9944c603e/src/assets/imgs/src/user-avatar.png
--------------------------------------------------------------------------------
/src/components/avatar/avatar.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback, useState, useRef, useEffect } from "react";
2 | import { IconLgDownArrow, IconUpArrow, IconLanguage } from "../../assets/icons";
3 | import { Button } from "../button";
4 | import { useNavigate } from "react-router-dom";
5 |
6 | interface AvatarProps {
7 | isAdmin?: boolean;
8 | img: string;
9 | status: "online" | "offline";
10 | }
11 |
12 | const Avatar = ({img, status, isAdmin}: AvatarProps) => {
13 | const [showPanel, setShowPanel] = useState(false)
14 | const selectRef = useRef(null);
15 |
16 | useEffect(() => {
17 | setShowPanel(false)
18 | }, [isAdmin])
19 |
20 | useEffect(() => {
21 | document.addEventListener('mousedown', handleClickOutside);
22 |
23 | return () => {
24 | document.removeEventListener('mousedown', handleClickOutside);
25 | };
26 | }, []);
27 |
28 | const handleClickOutside = (event: MouseEvent) => {
29 | if (selectRef.current && !selectRef.current.contains(event.target as Node)) {
30 | setShowPanel(false);
31 | }
32 | };
33 |
34 | const handleClickAvatar = useCallback(() => {
35 | setShowPanel(prev => !prev)
36 | }, [setShowPanel])
37 |
38 | return (
39 |
40 |
41 |
42 |

43 | {!isAdmin &&
}
44 |
45 |
{showPanel ? : }
46 |
47 | {showPanel &&
}
48 |
49 | )
50 | }
51 |
52 | interface OptionsPanelProps {
53 | isAdmin?: boolean;
54 | img: string;
55 | }
56 |
57 | const OptionsPanel = ({img, isAdmin}: OptionsPanelProps) => {
58 | const navigate = useNavigate();
59 |
60 | return (
61 |
62 |
63 |

64 |
65 |
Arnand Siem
66 |
Koppert
67 |
68 |
69 |
81 | )
82 | }
83 |
84 | export default Avatar
--------------------------------------------------------------------------------
/src/components/avatar/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Avatar } from './avatar'
--------------------------------------------------------------------------------
/src/components/button/button.tsx:
--------------------------------------------------------------------------------
1 | interface ButtonProps {
2 | className?: string;
3 | type?: "default" | "primary" | "success" | "warning";
4 | icon?: React.ReactNode;
5 | label: string;
6 | onClick?: () => void;
7 | disabled?: boolean;
8 | rounded?: boolean;
9 | size?: "md" | "lg";
10 | }
11 |
12 | const Button = ({className, type = "default", icon, disabled = false, label, onClick, rounded = false, size = "lg"}: ButtonProps) => {
13 | const types = {
14 | default: `bg-white text-midblack ${!rounded && "hover:border-midgrey hover:bg-tangerine border border-black"}`,
15 | primary: `bg-primary-500 hover:bg-primary-400 ${rounded ? "text-midblack" : "text-white"} border border-primary-500`,
16 | success: `bg-success hover:bg-success ${rounded ? "text-midblack" : "text-white"} border border-success`,
17 | warning: `bg-warning hover:bg-warning ${rounded ? "text-midblack" : "text-white"} border border-warning`,
18 | }
19 | let buttonClassName = `px-6.5 ${size === "lg" ? "h-16" : "h-11"} flex ${rounded ? "rounded-15" : "rounded-2.5"} disabled:cursor-not-allowed disabled:bg-disabled-bg disabled:text-disabled-text disabled:border-disabled-text ${types[type]} ${className}`
20 | return (
21 |
27 | )
28 | }
29 |
30 | export default Button
--------------------------------------------------------------------------------
/src/components/button/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Button } from './button'
--------------------------------------------------------------------------------
/src/components/card/card.tsx:
--------------------------------------------------------------------------------
1 | import { IconStar, IconWhiteHeart, IconGreyHeart } from "../../assets/icons";
2 |
3 | export interface CardProps {
4 | className?: string;
5 | data: CardData;
6 | }
7 |
8 | export interface CardData {
9 | price: number;
10 | name: string;
11 | title: string;
12 | like: boolean;
13 | ratings: number;
14 | img: string;
15 | size: "md" | "lg";
16 | }
17 |
18 | const Card = ({className, data}: CardProps) => {
19 | const {price, name, title, like, ratings, img, size} = data
20 | const cardClassName = `flex flex-col ${size === "lg" ? "w-101 h-80 " : " w-75 h-90"} rounded-2.5 bg-white shadow-custom3 cursor-pointer ${className}`
21 | return (
22 |
23 |
24 |

25 |
${price}
26 |
27 |
28 |
29 |
{name}
30 |
{title}
31 |
32 |
33 |
34 |
35 | {ratings}/5
36 |
37 |
38 |
39 | {like ? : }
40 |
41 |
42 |
43 |
44 |
45 | )
46 | }
47 |
48 | export default Card
--------------------------------------------------------------------------------
/src/components/card/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Card } from './card'
--------------------------------------------------------------------------------
/src/components/checkbox/checkbox.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 |
3 | interface CheckboxProps {
4 | className?: string;
5 | label?: string;
6 | }
7 |
8 | const Checkbox = ({className, label}: CheckboxProps) => {
9 | const checkboxClassName = `flex items-center ${className}`
10 | const [isChecked, setChecked] = useState(false);
11 |
12 | const handleCheckboxChange = () => {
13 | setChecked(!isChecked);
14 | };
15 |
16 | return (
17 |
18 |
25 |
47 |
48 | )
49 | }
50 |
51 | export default Checkbox
--------------------------------------------------------------------------------
/src/components/checkbox/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Checkbox } from './checkbox'
--------------------------------------------------------------------------------
/src/components/dropdown/dropdown.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useRef, useEffect } from 'react';
2 | import { IconDownArrow, IconRightArrow } from '../../assets/icons';
3 |
4 | interface DropdownProps {
5 | options: string[];
6 | label?: string;
7 | className?: string;
8 | }
9 |
10 | const Dropdown: React.FC = ({ options, label, className }) => {
11 | const [isOpen, setIsOpen] = useState(false);
12 | const selectRef = useRef(null);
13 |
14 | useEffect(() => {
15 | document.addEventListener('mousedown', handleClickOutside);
16 |
17 | return () => {
18 | document.removeEventListener('mousedown', handleClickOutside);
19 | };
20 | }, []);
21 |
22 | const handleClickOutside = (event: MouseEvent) => {
23 | if (selectRef.current && !selectRef.current.contains(event.target as Node)) {
24 | setIsOpen(false);
25 | }
26 | };
27 |
28 | const dropdownClasses = `block ${className}`;
29 |
30 | return (
31 |
32 |
33 |
40 | {isOpen && (
41 |
42 | {options.map((option) => (
43 | -
47 | {option}
48 |
49 |
50 | ))}
51 |
52 | )}
53 |
54 |
55 | );
56 | };
57 |
58 | export default Dropdown;
59 |
--------------------------------------------------------------------------------
/src/components/dropdown/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Dropdown } from './dropdown'
--------------------------------------------------------------------------------
/src/components/input/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Input } from './input'
--------------------------------------------------------------------------------
/src/components/input/input.tsx:
--------------------------------------------------------------------------------
1 | interface InputProps {
2 | className?: string;
3 | label?: string;
4 | icon?: React.ReactNode;
5 | placeholder?: string;
6 | isRequired?: boolean;
7 | type?: "default" | "rounded"
8 | }
9 |
10 | const Input = ({className, label, icon, placeholder, isRequired = false, type = "default"}: InputProps) => {
11 | const inputClassName = `block ${className}`
12 |
13 | return (
14 |
15 | {label &&
16 | {label}
17 |
}
18 |
19 | {icon &&
{icon}
}
20 |
21 |
22 |
23 | )
24 | }
25 |
26 | export default Input
--------------------------------------------------------------------------------
/src/components/modal/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Modal } from './modal'
--------------------------------------------------------------------------------
/src/components/modal/modal.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from "react";
2 |
3 | interface ModalProps {
4 | classNames? : string;
5 | children: React.ReactNode;
6 | visible: boolean;
7 | setVisible: (value: boolean) => void;
8 | }
9 |
10 | const Modal = ({classNames, children, visible, setVisible}: ModalProps) => {
11 | const selectRef = useRef(null);
12 |
13 | useEffect(() => {
14 | document.addEventListener('mousedown', handleClickOutside);
15 |
16 | return () => {
17 | document.removeEventListener('mousedown', handleClickOutside);
18 | };
19 | }, []);
20 |
21 | const handleClickOutside = (event: MouseEvent) => {
22 | if (selectRef.current && !selectRef.current.contains(event.target as Node)) {
23 | setVisible(false);
24 | }
25 | };
26 |
27 |
28 | const modalClassNames = `p-16 w-131 my-auto justify-center bg-white items-center overflow-x-hidden overflow-y-auto inset-0 z-50 my-auto rounded-5 shadow-custom ${classNames}`;
29 |
30 | return (
31 | <>
32 | {visible &&
33 |
34 | {children}
35 |
36 |
37 |
}
38 | >
39 | )
40 | }
41 |
42 | export default Modal
--------------------------------------------------------------------------------
/src/components/radio-group/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as RadioGroup } from './radio-group'
--------------------------------------------------------------------------------
/src/components/radio-group/radio-group.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 |
3 | interface CustomRadioGroupProps {
4 | className?: string;
5 | label?: string;
6 | options: RadioOption[]
7 | }
8 |
9 | interface RadioOption {
10 | value: string;
11 | label: string;
12 | }
13 |
14 | const CustomRadioGroup = ({className, label, options}: CustomRadioGroupProps) => {
15 | const [selectedOption, setSelectedOption] = useState(null);
16 |
17 | const handleOptionChange = (option: string) => {
18 | setSelectedOption(option);
19 | };
20 |
21 | const radioClassName = `${className}`
22 |
23 | return (
24 |
25 | {label &&
26 | {label}
27 |
}
28 |
29 | {options.map((option) => (
30 |
handleOptionChange(option.value)}
34 | >
35 |
38 |
39 |
40 | ))}
41 |
42 |
43 | );
44 | };
45 |
46 | export default CustomRadioGroup;
47 |
--------------------------------------------------------------------------------
/src/components/select/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Select } from './select'
--------------------------------------------------------------------------------
/src/components/select/select.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useRef, useEffect } from 'react';
2 | import { IconDownArrow } from '../../assets/icons';
3 |
4 | interface CustomSelectProps {
5 | options: string[];
6 | label?: string;
7 | className?: string;
8 | placeholder?: string;
9 | icon?: React.ReactNode;
10 | }
11 |
12 | const CustomSelect: React.FC = ({ options, label, icon, className, placeholder }) => {
13 | const [selectedOption, setSelectedOption] = useState(null);
14 | const [isOpen, setIsOpen] = useState(false);
15 | const selectRef = useRef(null);
16 |
17 | const handleOptionClick = (option: string) => {
18 | setSelectedOption(option);
19 | setIsOpen(false);
20 | };
21 |
22 | const handleClickOutside = (event: MouseEvent) => {
23 | if (selectRef.current && !selectRef.current.contains(event.target as Node)) {
24 | setIsOpen(false);
25 | }
26 | };
27 |
28 | useEffect(() => {
29 | document.addEventListener('mousedown', handleClickOutside);
30 |
31 | return () => {
32 | document.removeEventListener('mousedown', handleClickOutside);
33 | };
34 | }, []);
35 |
36 | const customSelectClasses = `block ${className}`;
37 |
38 | return (
39 |
40 | {label && (
41 |
42 | {label}
43 |
44 | )}
45 |
46 |
54 | {isOpen && (
55 |
56 | {options.map((option) => (
57 | - handleOptionClick(option)}
61 | >
62 | {option}
63 |
64 | ))}
65 |
66 | )}
67 |
68 |
69 | );
70 | };
71 |
72 | export default CustomSelect;
73 |
--------------------------------------------------------------------------------
/src/components/slider/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Slider } from './slider'
--------------------------------------------------------------------------------
/src/components/slider/slider.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { CardData } from '../card/card';
3 | import Card from '../card/card';
4 | import { IconLeftArrow, IconLgRightArrow } from '../../assets/icons';
5 |
6 | interface SliderProps {
7 | className?: string;
8 | cards: CardData[];
9 | cardsPerPage: number;
10 | label?: string;
11 | }
12 |
13 | const Slider: React.FC = ({ cards, cardsPerPage, label, className }) => {
14 | const [currentPage, setCurrentPage] = useState(1);
15 |
16 | const totalPages = Math.ceil(cards.length / cardsPerPage);
17 |
18 | const startIndex = (currentPage - 1) * cardsPerPage;
19 | const endIndex = startIndex + cardsPerPage;
20 |
21 | const visibleCards = cards.slice(startIndex, endIndex);
22 |
23 | const handleNextPage = () => {
24 | setCurrentPage((prevPage) => Math.min(prevPage + 1, totalPages));
25 | };
26 |
27 | const handlePrevPage = () => {
28 | setCurrentPage((prevPage) => Math.max(prevPage - 1, 1));
29 | };
30 |
31 | const pages = Array.from({ length: totalPages }, (_, index) => index);
32 |
33 | const sliderClassName = `mx-auto w-fit ${className}`
34 |
35 | return (
36 |
37 |
38 | {label}
39 |
40 |
41 |
42 | {visibleCards.map((card, index) => (
43 |
44 |
45 |
46 | ))}
47 |
48 |
49 |
50 |
56 |
62 |
63 |
64 |
65 |
66 |
67 | {pages.map((page: number) => {
68 | return (
69 | <>
70 | { page === currentPage - 1 ?
71 | :
72 | }
73 | >
74 | )
75 | })}
76 |
77 |
78 | );
79 | };
80 |
81 | export default Slider;
82 |
--------------------------------------------------------------------------------
/src/components/switch/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Switch } from './switch'
--------------------------------------------------------------------------------
/src/components/switch/switch.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | interface SwitchProps {
4 | label?: string;
5 | checked: boolean;
6 | onChange: (checked: boolean) => void;
7 | }
8 |
9 | const Switch: React.FC = ({ label, checked, onChange }) => {
10 | const handleToggle = () => {
11 | onChange(!checked);
12 | };
13 |
14 | return (
15 |
16 |
23 | {label &&
{label}}
24 |
25 | );
26 | };
27 |
28 | export default Switch;
29 |
--------------------------------------------------------------------------------
/src/components/table/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as Table } from './table'
--------------------------------------------------------------------------------
/src/components/table/table.tsx:
--------------------------------------------------------------------------------
1 | // CustomTable.tsx
2 | import React, { useState } from 'react';
3 |
4 | interface TableColumn {
5 | header: string;
6 | width?: string;
7 | }
8 |
9 | interface TableProps {
10 | columns: TableColumn[];
11 | data: any[][];
12 | showCheckbox?: boolean;
13 | }
14 |
15 | const CustomTable: React.FC = ({ columns, data, showCheckbox }) => {
16 | const [selectedRows, setSelectedRows] = useState>(new Set());
17 |
18 | const handleSelectAll = () => {
19 | if (selectedRows.size === data.length) {
20 | setSelectedRows(new Set());
21 | } else {
22 | const allRows = Array.from({ length: data.length }, (_, index) => index);
23 | setSelectedRows(new Set(allRows));
24 | }
25 | };
26 |
27 | const handleRowCheckboxClick = (rowIndex: number) => {
28 | setSelectedRows((prevSelectedRows) => {
29 | const newSelectedRows = new Set(prevSelectedRows);
30 | if (newSelectedRows.has(rowIndex)) {
31 | newSelectedRows.delete(rowIndex);
32 | } else {
33 | newSelectedRows.add(rowIndex);
34 | }
35 | return newSelectedRows;
36 | });
37 | };
38 |
39 | return (
40 |
79 | );
80 | };
81 |
82 | export default CustomTable;
83 |
--------------------------------------------------------------------------------
/src/components/textarea/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as TextArea } from './textarea'
--------------------------------------------------------------------------------
/src/components/textarea/textarea.tsx:
--------------------------------------------------------------------------------
1 | interface TextAreaProps {
2 | label?: string;
3 | className?: string;
4 | placeholder?: string;
5 | }
6 |
7 | const TextArea = ({label, className, placeholder}: TextAreaProps) => {
8 | const textAreaClassName = `${className}`
9 |
10 | return (
11 |
12 | {label &&
13 | {label}
14 |
}
15 |
16 |
17 |
18 |
19 | )
20 | }
21 |
22 | export default TextArea
--------------------------------------------------------------------------------
/src/components/tour-stepper/index.tsx:
--------------------------------------------------------------------------------
1 | export { default as TourStepper } from './tour-stepper'
--------------------------------------------------------------------------------
/src/components/tour-stepper/tour-stepper.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "../button";
2 | import { useState, useCallback, useEffect } from 'react'
3 |
4 | interface TourStepperProps {
5 | classNames? : string;
6 | stepComponents: React.ReactNode[];
7 | }
8 |
9 | const TourStepper = ({classNames, stepComponents}: TourStepperProps) => {
10 | const modalClassNames = `p-16 w-131 my-auto justify-center bg-white items-center overflow-x-hidden overflow-y-auto inset-0 z-50 my-auto rounded-5 shadow-custom ${classNames}`;
11 | const stepsCount = stepComponents?.length;
12 | const [currentStep, setCurrentStep] = useState(0)
13 | const [showTour, setShowTour] = useState(true)
14 |
15 | useEffect(() => {
16 | if(showTour) document.body.style.overflow = 'hidden';
17 |
18 | return () => {
19 | document.body.style.overflow = 'auto';
20 | };
21 | }, [showTour])
22 |
23 | const handleNextStep = useCallback(() => {
24 | setCurrentStep(prevStep => prevStep + 1);
25 | }, [setCurrentStep])
26 |
27 | const handlePrevStep = useCallback(() => {
28 | setCurrentStep(prevStep => prevStep - 1);
29 | }, [setCurrentStep])
30 |
31 | const handleCloseTour = useCallback(() => {
32 | setShowTour(false)
33 | }, [showTour, setShowTour])
34 |
35 | return (
36 | <>
37 | {showTour &&
38 |
39 |
40 |
41 |
42 |
43 | {stepComponents[currentStep]}
44 |
45 |
46 | {currentStep !== stepsCount - 1 && }
47 |
48 |
49 |
50 |
51 |
}
52 | >
53 | )
54 | }
55 |
56 | interface StepperProps {
57 | count: number;
58 | currentStep: number;
59 | }
60 |
61 | const Stepper = ({ count, currentStep }: StepperProps) => {
62 | const steps = Array.from({ length: count }, (_, index) => index);
63 |
64 | return (
65 |
66 | {steps.map((step) => (
67 |
68 | ))}
69 |
70 | );
71 | };
72 |
73 | export default TourStepper
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
--------------------------------------------------------------------------------
/src/layout/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMemo } from "react";
2 | import Nav from "./nav";
3 | import { useLocation } from "react-router-dom";
4 |
5 | interface AppLayoutProps {
6 | children: React.ReactNode;
7 | }
8 |
9 | const AppLayout = ({children}: AppLayoutProps) => {
10 | const location = useLocation()
11 |
12 | const isShowNav = useMemo(() => !['/signin', 'reset-password', 'new-password'].includes(location.pathname), [location.pathname])
13 | const isAdmin = useMemo(() => location.pathname.includes('/admin'), [location.pathname])
14 |
15 | return (
16 |
17 | {isShowNav &&
}
18 |
19 | {children}
20 |
21 |
22 | )
23 | }
24 |
25 | export default AppLayout
--------------------------------------------------------------------------------
/src/layout/nav.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react";
2 | import { useNavigate, NavLink, useLocation } from "react-router-dom";
3 | import { Input } from "../components/input";
4 | import { IconSearch } from "../assets/icons";
5 | import { Avatar } from "../components/avatar";
6 | import { UserAvatar, AdminAvatar } from "../assets/imgs";
7 | import { IconWhiteHeart, IconUser } from "../assets/icons";
8 |
9 | interface NavProps {
10 | isAdmin?: boolean;
11 | }
12 |
13 | const Nav = ({isAdmin} : NavProps) => {
14 | const navigate = useNavigate()
15 | const navigation = useLocation()
16 | const pathName = navigation.pathname
17 |
18 | const gotoHome = useCallback(() => {
19 | navigate('/overview')
20 | }, [navigate])
21 |
22 | const gotoAllCourses = useCallback(() => {
23 | navigate('/all-courses')
24 | }, [navigate])
25 |
26 | return (
27 | <>
28 |
29 |
30 |
ACE ACADEMY
31 | {!isAdmin &&
} />}
32 |
33 |
34 | {!isAdmin &&
35 | All courses
36 | My courses
37 |
}
38 |
41 |
42 |
43 | {isAdmin &&
44 | Dashboard
45 | werknemers
46 | requests
47 | analytics
48 | settings
49 |
}
50 | >
51 | )
52 | }
53 |
54 | export default Nav
--------------------------------------------------------------------------------
/src/main.tsx:
--------------------------------------------------------------------------------
1 | import ReactDOM from 'react-dom/client'
2 | import App from './App.tsx'
3 | import React from 'react'
4 | import './index.css'
5 |
6 | ReactDOM.createRoot(document.getElementById('root')!).render(
7 |
8 |
9 | ,
10 | )
11 |
--------------------------------------------------------------------------------
/src/pages/admin/analytics.tsx:
--------------------------------------------------------------------------------
1 | const Analytics = () => {
2 | return (
3 | <>
4 | Analytics
5 | >
6 | )
7 | }
8 |
9 | export default Analytics
--------------------------------------------------------------------------------
/src/pages/admin/dashboard.tsx:
--------------------------------------------------------------------------------
1 | const Dashboard = () => {
2 | return (
3 | <>
4 | Dashboard
5 | >
6 | )
7 | }
8 |
9 | export default Dashboard
--------------------------------------------------------------------------------
/src/pages/admin/index.tsx:
--------------------------------------------------------------------------------
1 | import { Routes, Route } from "react-router-dom"
2 | import Dashboard from "./dashboard"
3 | import Werknemers from "./werknemers"
4 | import Requests from "./requests"
5 | import Analytics from "./analytics"
6 | import Settings from "./settings"
7 |
8 | const Admin = () => {
9 | return (
10 |
11 | } />
12 | } />
13 | } />
14 | } />
15 | } />
16 |
17 | )
18 | }
19 |
20 | export default Admin
--------------------------------------------------------------------------------
/src/pages/admin/requests.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from "react";
2 | import { Table } from "../../components/table";
3 | import { TableUserAvatar } from "../../assets/imgs";
4 | import { IconOk, IconCancel } from "../../assets/icons";
5 | import { Modal } from "../../components/modal";
6 | import { Button } from "../../components/button";
7 | import { TextArea } from "../../components/textarea";
8 |
9 | const Requests = () => {
10 | const [approveModal, setApproveModal] = useState(false)
11 | const [denyModal, setDenyModal] = useState(false)
12 |
13 | const handleApproveModal = useCallback((value: boolean) => () => {
14 | setApproveModal(value)
15 | }, [approveModal, setApproveModal])
16 |
17 | const handleDenyModal = useCallback((value: boolean) => () => {
18 | setDenyModal(value)
19 | }, [denyModal, setDenyModal])
20 |
21 | const tableColumns = [
22 | { header: '', width: '5%' },
23 | { header: 'Naam', width: '20%' },
24 | { header: 'Course', width: '20%' },
25 | { header: 'Date', width: '20%' },
26 | { header: 'Price', width: '15%' },
27 | { header: '', width: '20%' },
28 | ];
29 | const tableData = [
30 | [, 'John Doe', 'Arnand', '28/11/2023', '€ 245', ],
31 | [, 'John Doe', 'Arnand', '28/11/2023', '€ 245', ],
32 | [, 'John Doe', 'Arnand', '28/11/2023', '€ 245', ],
33 | [, 'John Doe', 'Arnand', '28/11/2023', '€ 245', ],
34 | [, 'John Doe', 'Arnand', '28/11/2023', '€ 245', ],
35 | ];
36 |
37 | return (
38 | <>
39 | Employees
40 |
43 |
44 |
45 |
46 |
47 |
Approve request
48 |
Are you sure you want to approve this request?
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | >
70 | )
71 | }
72 |
73 | const UserAvatar = () => {
74 | return (
75 |
76 | )
77 | }
78 |
79 | interface ViewUserProps {
80 | handleApprove: (value: boolean) => () => void;
81 | handleDeny: (value: boolean) => () => void;
82 | }
83 |
84 | const ViewUser = ({handleApprove, handleDeny}: ViewUserProps) => {
85 | return (
86 |
87 |
88 |
89 |
90 |
91 | )
92 | }
93 |
94 |
95 | export default Requests
--------------------------------------------------------------------------------
/src/pages/admin/settings.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from "react";
2 | import { AdminAvatarLg, UserAvatar } from "../../assets/imgs"
3 | import { Switch } from "../../components/switch";
4 | import { Input } from "../../components/input";
5 | import { IconSearch, IconPlus } from "../../assets/icons";
6 | import { Button } from "../../components/button";
7 | import { Checkbox } from "../../components/checkbox";
8 |
9 | const Settings = () => {
10 | const [checked, setChecked] = useState(true)
11 |
12 | const handSwitch = useCallback(() => {
13 | setChecked(prev => !prev)
14 | }, [setChecked])
15 |
16 | return (
17 | <>
18 |
19 |
Account settings
20 |
21 |
22 |
23 |
24 |
27 | info@koppert.nl
28 | Verified
29 | }
30 | />
31 |
34 | accounts@koppert.nl
35 | Verified
36 | }
37 | />
38 |
41 |
42 | €2500
43 | }
44 | />
45 | Not specified} />
46 |
49 | HR
50 | Finance
51 | IT
52 | Productior
53 | Overig
54 | }
55 | />
56 |
59 | KVK
60 | Adress
61 | Place
62 | Place
63 | BTW number
64 | }
65 | divider={false}
66 | />
67 |
68 |
69 |
70 |
71 |
Admin members
72 |
73 |
74 | } />
75 | } />
76 |
77 |
84 |
85 |
86 |
87 |
88 |
89 |

90 |
91 |
Arnand Siem
92 |
Product owner
93 |
94 |
95 |
96 |
97 |
98 |
99 | >
100 | )
101 | }
102 |
103 | interface SettingRowProps {
104 | name: string;
105 | value: any;
106 | divider?: boolean
107 | }
108 |
109 | const SettingRow = ({name, value, divider = true}: SettingRowProps) => {
110 | return (
111 |
112 |
113 |
{name}
114 |
{value}
115 |
116 |
117 |
118 |
119 | {divider &&
}
120 |
121 | )
122 | }
123 |
124 | export default Settings
--------------------------------------------------------------------------------
/src/pages/admin/werknemers.tsx:
--------------------------------------------------------------------------------
1 | import { Table } from "../../components/table"
2 | import { TableUserAvatar } from "../../assets/imgs";
3 |
4 | const Werknemers = () => {
5 | const tableColumns = [
6 | { header: '', width: '4.5%' },
7 | { header: 'Naam', width: '18%' },
8 | { header: 'Reports to', width: '15%' },
9 | { header: 'Budget spent', width: '15%' },
10 | { header: 'Total active time', width: '30%' },
11 | { header: '', width: '10%' },
12 | ];
13 | const tableData = [
14 | [, 'John Doe', 'Arnand', '€ 45', '1h 30 min', ],
15 | [, 'John Doe', 'Arnand', '€ 45', '1h 30 min', ],
16 | [, 'John Doe', 'Arnand', '€ 45', '1h 30 min', ],
17 | [, 'John Doe', 'Arnand', '€ 45', '1h 30 min', ],
18 | [, 'John Doe', 'Arnand', '€ 45', '1h 30 min', ],
19 | ];
20 |
21 | return (
22 | <>
23 | Employees
24 |
27 | >
28 | )
29 | }
30 |
31 | const UserAvatar = () => {
32 | return (
33 |
34 | )
35 | }
36 |
37 | const ViewUser = () => {
38 | return (
39 |
40 | )
41 | }
42 |
43 | export default Werknemers
--------------------------------------------------------------------------------
/src/pages/all-courses/all-courses.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react"
2 | import { CardData } from "../../components/card/card"
3 | import { CardImgMd01, CardImgMd02, CardImgMd03, CardImgMd04 } from "../../assets/imgs"
4 | import Card from "../../components/card/card"
5 | import { IconSmDownArrow } from "../../assets/icons"
6 | import { Dropdown } from "../../components/dropdown"
7 | import { Switch } from "../../components/switch"
8 |
9 | const mdcards: CardData[] = [
10 | {name: "Office Newb", title: "Microsoft Excel - Excel from Beginner to Advanced", ratings: 4.7, like: true, price: 240, img: CardImgMd01, size: 'md'},
11 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
12 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
13 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
14 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
15 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
16 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
17 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
18 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
19 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
20 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
21 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
22 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
23 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
24 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
25 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
26 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
27 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
28 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
29 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
30 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'}
31 | ]
32 |
33 | const dropdownOptions = [
34 | "Arts & Entertainment",
35 | "Business",
36 | "Community & Government",
37 | "Design & Style",
38 | "Food",
39 | "Home & Lifestyle",
40 | "Music",
41 | "Science & Tech",
42 | "Sports & Gaming",
43 | "Writing",
44 | ]
45 |
46 | const AllCourses = () => {
47 | const [isChecked, setIsChecked] = useState(false);
48 |
49 | const handleChange = (checked: boolean) => {
50 | setIsChecked(checked);
51 | };
52 |
53 | return (
54 |
55 |
All courses
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
167 courses available
69 |
70 | Sort by:
71 | Relevance
72 |
73 |
74 |
75 | {mdcards.map((card) => )}
76 |
77 |
78 | )
79 | }
80 |
81 | export default AllCourses
--------------------------------------------------------------------------------
/src/pages/auth/layout/index.tsx:
--------------------------------------------------------------------------------
1 | import { BgSignUp } from "../../../assets/imgs";
2 |
3 | interface AuthLayoutProps {
4 | children: React.ReactNode;
5 | }
6 |
7 | const AuthLayout = ({children}: AuthLayoutProps) => {
8 | return (
9 | <>
10 |
11 |
12 |

13 |
14 |
15 | {children}
16 |
17 |
18 | >
19 | )
20 | }
21 |
22 | export default AuthLayout
--------------------------------------------------------------------------------
/src/pages/auth/new-password/index.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useCallback } from "react"
2 | import AuthLayout from "../layout"
3 | import { Button } from "../../../components/button"
4 | import { Input } from "../../../components/input"
5 | import { IconLock, IconCheckMark } from "../../../assets/icons"
6 | import { useNavigate } from "react-router-dom"
7 |
8 | const NewPassword = () => {
9 | const navigate = useNavigate();
10 | const [isNewPass, setIsNewPass] = useState(false)
11 |
12 | const handleOnClickReset = useCallback(() => {
13 | setIsNewPass(true)
14 | }, [isNewPass])
15 |
16 | const handleOnClickLogin = useCallback(() => {
17 | navigate('/signin')
18 | }, [navigate])
19 |
20 | return (
21 |
22 | {!isNewPass ?
23 |
24 |
New password
25 |
Your password must contain at least 8 characters and 1 number
26 |
27 |
} />
28 |
} />
29 |
30 |
:
31 |
32 |
33 |
34 |
35 |
36 |
Password reset
37 |
Your password has been reset successfully
38 |
39 |
40 |
}
41 |
42 | )
43 | }
44 |
45 | export default NewPassword
--------------------------------------------------------------------------------
/src/pages/auth/reset-password/index.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from "react"
2 | import AuthLayout from "../layout"
3 | import { Button } from "../../../components/button"
4 | import { Input } from "../../../components/input"
5 | import { IconMail, IconCheckMark } from "../../../assets/icons"
6 |
7 | const ResetPassword = () => {
8 | const [isMailSent, setIsMailSent] = useState(false)
9 |
10 | const handleOnClickSendMailButton = useCallback(() => {
11 | setIsMailSent(true)
12 | }, [isMailSent])
13 |
14 | return (
15 |
16 | {!isMailSent ?
17 |
18 |
Reset your password
19 |
Enter your email and we’ll send you a link to reset your password
20 |
21 |
} />
22 |
23 |
:
24 |
25 |
26 |
27 |
28 |
29 |
Email sent
30 |
Check your email and open the link we sent to continue.
31 |
32 |
}
33 |
34 | )
35 | }
36 |
37 | export default ResetPassword
--------------------------------------------------------------------------------
/src/pages/auth/signin/index.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react"
2 | import AuthLayout from "../layout"
3 | import { Button } from "../../../components/button"
4 | import { Input } from "../../../components/input"
5 | import { Checkbox } from "../../../components/checkbox"
6 | import { IconGoogle, IconMail, IconOutlook, IconLock } from "../../../assets/icons"
7 | import { useNavigate } from "react-router-dom"
8 |
9 | const SignIn = () => {
10 | const navigate = useNavigate();
11 |
12 | const handleForgotPass = useCallback(() => {
13 | navigate('/reset-password')
14 | }, [navigate])
15 |
16 | const handleSignIn = useCallback(() => {
17 | navigate('/overview')
18 | }, [navigate])
19 |
20 | return (
21 |
22 |
23 |
Welcome back
24 |
Sign in to your account to continue
25 |
26 |
27 | } />
28 | } />
29 |
30 | Or
31 | } isRequired />
32 | } isRequired />
33 |
34 |
35 |
Forgot password?
36 |
37 |
38 |
39 | )
40 | }
41 |
42 | export default SignIn
--------------------------------------------------------------------------------
/src/pages/overview/components/banner.tsx:
--------------------------------------------------------------------------------
1 | import { BannerImg } from "../../../assets/imgs"
2 | import { Button } from "../../../components/button"
3 |
4 | const Banner = () => {
5 | return (
6 |
7 |

8 |
9 |
Welkom Jeffrey
10 |
Je hebt nog 1000 euro learn budget
11 |
"Learning never exhausts the mind."
12 |
LEONARDO DA VINCI
13 |
14 |
15 |
16 |
17 |
18 |
19 | )
20 | }
21 |
22 | export default Banner
--------------------------------------------------------------------------------
/src/pages/overview/components/tour.tsx:
--------------------------------------------------------------------------------
1 | import { TourStepper } from "../../../components/tour-stepper"
2 | import { Input } from "../../../components/input"
3 | import { IconLock, IconDegree, IconToolbox, IconMap, IconCongrats } from "../../../assets/icons"
4 | import { Select } from "../../../components/select"
5 | import { RadioGroup } from "../../../components/radio-group"
6 |
7 |
8 | const Tour = () => {
9 | const stepcomponents = [
10 | ,
11 | ,
12 | ,
13 | ,
14 | ,
15 |
16 | ]
17 |
18 | return (
19 |
20 | )
21 | }
22 |
23 | const Step1 = () => {
24 | return (
25 |
26 |
Welcome Jeffrey
27 |
Please check your mail. We’ve sent you a confirmation link.
28 |
29 | )
30 | }
31 |
32 | const Step2 = () => {
33 | return (
34 |
35 |
36 |
Create a password
37 |
Your password must be 8 characters long and contain at least one letter, one digit and one special character.
38 |
39 |
} />
40 |
} />
41 |
42 | )
43 | }
44 |
45 | const Step3 = () => {
46 | return (
47 |
48 |
Terms & Conditions
49 |
These terms and conditions outline the rules and regulations for the use of Company Name's Website, located at Website .com.
50 |
By accessing this website we assume you accept these terms and conditions. Do not continue to use Website Name if you do not agree to take all of the terms and conditions stated on this page.
51 |
52 | )
53 | }
54 |
55 | const Step4 = () => {
56 | const options = [
57 | "Primary education",
58 | "High school",
59 | "Bachelor's degree",
60 | "Master's degree",
61 | "Doctorate or higher"
62 | ]
63 |
64 | return (
65 |
72 | )
73 | }
74 |
75 | const Step5 = () => {
76 | const options1 = [
77 | {
78 | label: "Disagree",
79 | value: "Disagree"
80 | },
81 | {
82 | label: "Neutral",
83 | value: "Neutral"
84 | },
85 | {
86 | label: "Agree",
87 | value: "Agree"
88 | },
89 | ]
90 |
91 | return (
92 |
93 |
Likert-scale
94 |
95 |
96 |
97 |
98 | )
99 | }
100 |
101 | const Step6 = () => {
102 | return (
103 |
104 |
105 |
106 |
107 |
108 |
You’re ready to go!
109 |
Your account has been created successfully.
110 |
111 |
112 | )
113 | }
114 |
115 | export default Tour
--------------------------------------------------------------------------------
/src/pages/overview/index.tsx:
--------------------------------------------------------------------------------
1 | import Tour from "./components/tour"
2 | import { CardData } from "../../components/card/card"
3 | import { Slider } from "../../components/slider"
4 | import { CardImgLg01, CardImgLg02, CardImgLg03, CardImgMd01, CardImgMd02, CardImgMd03, CardImgMd04 } from "../../assets/imgs"
5 | import Banner from "./components/banner"
6 |
7 | const lgcards: CardData[] = [
8 | {name: "Frank Gehry", title: "Teaches Design and Architecture", ratings: 4.9, like: false, price: 300, img: CardImgLg01, size: 'lg'},
9 | {name: "Gordon Ramsay", title: "Take your cooking to the next level in Gordon’s masterclass", ratings: 4.9, like: true, price: 240, img: CardImgLg02, size: 'lg'},
10 | {name: "Lewis Hamilton", title: "Lewis Hamilton teaches a Winning Mindset", ratings: 4.9, like: false, price: 200, img: CardImgLg03, size: 'lg'},
11 | {name: "Lewis Hamilton", title: "Lewis Hamilton teaches a Winning Mindset", ratings: 4.9, like: false, price: 200, img: CardImgLg03, size: 'lg'},
12 | {name: "Gordon Ramsay", title: "Take your cooking to the next level in Gordon’s masterclass", ratings: 4.9, like: true, price: 240, img: CardImgLg02, size: 'lg'},
13 | {name: "Frank Gehry", title: "Teaches Design and Architecture", ratings: 4.9, like: false, price: 300, img: CardImgLg01, size: 'lg'},
14 | {name: "Gordon Ramsay", title: "Take your cooking to the next level in Gordon’s masterclass", ratings: 4.9, like: true, price: 240, img: CardImgLg02, size: 'lg'},
15 | {name: "Lewis Hamilton", title: "Lewis Hamilton teaches a Winning Mindset", ratings: 4.9, like: false, price: 200, img: CardImgLg03, size: 'lg'},
16 | {name: "Gordon Ramsay", title: "Take your cooking to the next level in Gordon’s masterclass", ratings: 4.9, like: true, price: 240, img: CardImgLg02, size: 'lg'},
17 | {name: "Frank Gehry", title: "Teaches Design and Architecture", ratings: 4.9, like: false, price: 300, img: CardImgLg01, size: 'lg'},
18 | {name: "Frank Gehry", title: "Teaches Design and Architecture", ratings: 4.9, like: false, price: 300, img: CardImgLg01, size: 'lg'},
19 | {name: "Gordon Ramsay", title: "Take your cooking to the next level in Gordon’s masterclass", ratings: 4.9, like: true, price: 240, img: CardImgLg02, size: 'lg'}
20 | ]
21 |
22 | const mdcards: CardData[] = [
23 | {name: "Office Newb", title: "Microsoft Excel - Excel from Beginner to Advanced", ratings: 4.7, like: true, price: 240, img: CardImgMd01, size: 'md'},
24 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
25 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
26 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
27 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
28 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
29 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
30 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
31 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
32 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
33 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
34 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
35 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
36 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
37 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
38 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
39 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'},
40 | {name: "Ran Segall", title: "The Complete Web Developer Course 3.0", ratings: 4.3, like: true, price: 140, img: CardImgMd03, size: 'md'},
41 | {name: "Phil Ebiner & Kevin Gardin", title: "Drawing Masterclass: Art, Sketching, Drawing Course", ratings: 4.3, like: false, price: 340, img: CardImgMd04, size: 'md'},
42 | {name: "Scrum Academy", title: "Productivity for Creators: Systems, Organization & Workflow", ratings: 4.7, like: false, price: 400, img: CardImgMd02, size: 'md'}
43 | ]
44 |
45 | const OverView = () => {
46 |
47 | return (
48 | <>
49 |
50 |
51 |
52 |
53 |
54 | >
55 | )
56 | }
57 |
58 | export default OverView
--------------------------------------------------------------------------------
/src/router/index.tsx:
--------------------------------------------------------------------------------
1 | import {Route, Routes, Navigate } from 'react-router-dom'
2 | import SignIn from '../pages/auth/signin'
3 | import ResetPassword from '../pages/auth/reset-password'
4 | import NewPassword from '../pages/auth/new-password'
5 | import OverView from '../pages/overview'
6 | import AllCourses from '../pages/all-courses/all-courses'
7 | import Admin from '../pages/admin'
8 |
9 | const Router = () => {
10 | return (
11 |
12 | } />
13 | } />
14 | } />
15 | } />
16 | } />
17 | } />
18 | } />
19 |
20 | )
21 | }
22 |
23 | export default Router
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | const defaultTheme = require('tailwindcss/defaultTheme')
3 | export default {
4 | content: [
5 | "./index.html",
6 | "./src/**/*.{js,jsx,ts,tsx}",
7 | ],
8 | theme: {
9 | fontFamily: {
10 | sans: ['Manrope', 'sans-serif'],
11 | serif: ['Manrope', 'serif'],
12 | },
13 | extend: {
14 | colors: {
15 | primary: {
16 | 500: '#F09272',
17 | 400: '#f4a286'
18 | },
19 | midblack: '#1F1F1F',
20 | tangerine: '#F5F5F5',
21 | brightgrey: '#8F8F8F',
22 | midgrey: '#525966',
23 | bannergrey: '#D9D9D9',
24 | disabled: {
25 | bg: '#f0f0f0',
26 | text: '#ccc'
27 | },
28 | semibrightgrey: '#ECECEC',
29 | success: '#5BCE00',
30 | warning: '#FF3030'
31 | },
32 | spacing: {
33 | 0.25: '1px',
34 | 0.5: '2px',
35 | 1.5: '0.3125rem', // 5px
36 | 1.6: '0.375rem', // 6px
37 | 2.5: '0.625rem', // 10px
38 | 3.25: '0.8125rem', // 13px
39 | 3.5: '0.875rem', // 14px
40 | 3.75: '0.9375rem', // 15px
41 | 4.5: '1.125rem', // 18px
42 | 6.5: '1.625rem', // 26px
43 | 7.5: '1.875rem', // 30px
44 | 9.5: '2.375rem', // 38px
45 | 11: '2.75rem', // 44px
46 | 12.5: '3.125rem', // 50px
47 | 15: '3.75rem', // 60px
48 | 22.5: '5.625rem', // 90px
49 | 23: '5.375rem', // 92px
50 | 24.5: '6.125rem', // 98px
51 | 25: '6.25rem', // 100px
52 | 30: '7.5rem', // 120px
53 | 33: '8.25rem', // 132px
54 | 35: '8.75rem', // 140px
55 | 39: '9.75rem', // 156px
56 | 66: '16.5rem', // 264px
57 | 75: '18.75rem', // 300px
58 | 77: '19.25rem', // 308px
59 | 82: '20.5rem', // 328px
60 | 86: '21.5rem', // 344px
61 | 88: '22rem', // 352px
62 | 90: '22.5rem', // 360px
63 | 101: '25.25rem', // 404px
64 | 131: '32.75rem' // 524px
65 | },
66 | borderRadius: {
67 | 1: '0.25rem', // 4px
68 | 2.5: '0.625rem', // 10px
69 | 5: '1.25rem', // 20px
70 | 7.5: '1.875rem', // 30px
71 | 12.5: '3.125rem', // 50px
72 | 15: '3.75rem', //60px
73 | 37.5: '9.375rem' // 150px
74 | },
75 | fontSize: {
76 | 13: '13px',
77 | 15: '15px',
78 | 26: '26px',
79 | 30: '30px'
80 | },
81 | boxShadow: {
82 | custom: '0px 4px 50px 10px rgba(0, 0, 0, 0.03)',
83 | custom2: '0px 4px 24px 0px rgba(0, 0, 0, 0.07)',
84 | custom3: '0px 4px 20px 0px rgba(0, 0, 0, 0.05)'
85 | },
86 | fontFamily: {
87 | "brawler": ['"Brawler"', ...defaultTheme.fontFamily.sans]
88 | }
89 | }
90 | },
91 | plugins: [],
92 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "noEmit": true,
15 | "jsx": "react-jsx",
16 |
17 | /* Linting */
18 | "strict": true,
19 | "noUnusedLocals": true,
20 | "noUnusedParameters": true,
21 | "noFallthroughCasesInSwitch": true
22 | },
23 | "include": ["src"],
24 | "references": [{ "path": "./tsconfig.node.json" }]
25 | }
26 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "skipLibCheck": true,
5 | "module": "ESNext",
6 | "moduleResolution": "bundler",
7 | "allowSyntheticDefaultImports": true
8 | },
9 | "include": ["vite.config.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "rewrites": [{ "source": "/(.*)", "destination": "/" }]
3 | }
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | })
8 |
--------------------------------------------------------------------------------