Skip to content

Commit

Permalink
Added redux and began the skeleton loading
Browse files Browse the repository at this point in the history
- Added redux
- Added the auth, user, quiz and event slices
- Made the skeleton loading for the quiz and event main page
  • Loading branch information
ctrl-plus-w committed Aug 17, 2021
1 parent 8ca92bc commit a51463e
Show file tree
Hide file tree
Showing 32 changed files with 2,121 additions and 2,012 deletions.
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = {
reactStrictMode: true,
}
};
3,175 changes: 1,324 additions & 1,851 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,21 @@
},
"dependencies": {
"@heroicons/react": "^1.0.3",
"@reduxjs/toolkit": "^1.6.1",
"axios": "^0.21.1",
"clsx": "^1.1.1",
"cookie": "^0.4.1",
"next": "11.0.1",
"react": "17.0.2",
"react-cookie": "^4.0.3",
"react-dom": "17.0.2",
"react-redux": "^7.2.4",
"redux": "^4.1.1",
"uuid": "^8.3.2"
},
"devDependencies": {
"@types/axios": "^0.14.0",
"@types/react": "17.0.15",
"@types/react-redux": "^7.1.18",
"@types/uuid": "^8.3.1",
"@typescript-eslint/eslint-plugin": "^4.28.5",
"@typescript-eslint/parser": "^4.28.5",
Expand Down
13 changes: 7 additions & 6 deletions src/components/elements/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import React from 'react';

interface IProps {
level?: number;
regular?: boolean;
children?: React.ReactNode;
color?: 'white' | 'black' | 'red';
}

const Title: FunctionComponent<IProps> = ({ level, children, color = 'black' }: IProps) => {
const Title: FunctionComponent<IProps> = ({ level, children, regular, color = 'black' }: IProps) => {
const getColor = (): string => {
switch (color) {
case 'black':
Expand All @@ -22,19 +23,19 @@ const Title: FunctionComponent<IProps> = ({ level, children, color = 'black' }:

switch (level) {
case 1:
return <h1 className={`text-${getColor()} font-semibold text-3xl`}>{children}</h1>;
return <h1 className={`text-${getColor()} ${regular ? 'font-regular' : 'font-semibold'} text-3xl`}>{children}</h1>;

case 2:
return <h2 className={`text-${getColor()} font-semibold text-2xl`}>{children}</h2>;
return <h2 className={`text-${getColor()} ${regular ? 'font-regular' : 'font-semibold'} text-2xl`}>{children}</h2>;

case 3:
return <h3 className={`text-${getColor()} font-semibold text-xl`}>{children}</h3>;
return <h3 className={`text-${getColor()} ${regular ? 'font-regular' : 'font-semibold'} text-xl`}>{children}</h3>;

case 4:
return <h4 className={`text-${getColor()} font-medium text-xl`}>{children}</h4>;
return <h4 className={`text-${getColor()} ${regular ? 'font-regular' : 'font-medium'} text-xl`}>{children}</h4>;

default:
return <h1 className={`text-${getColor()} font-semibold text-3xl`}>{children}</h1>;
return <h1 className={`text-${getColor()} ${regular ? 'font-regular' : 'font-semibold'} text-3xl`}>{children}</h1>;
}
};

Expand Down
26 changes: 26 additions & 0 deletions src/components/layouts/DefaultSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { FunctionComponent } from 'react';

import Head from 'next/head';
import React from 'react';
import clsx from 'clsx';

interface IProps {
title: string;
children?: React.ReactNode;
display?: 'row' | 'col';
center?: boolean;
}

const Layout: FunctionComponent<IProps> = ({ title, children, center = false, display = 'col' }: IProps) => {
return (
<div className={clsx([`w-full h-full flex flex-${display}`, center && 'justify-center items-center'])}>
<Head>
<title>{title}</title>
</Head>

{children}
</div>
);
};

export default Layout;
35 changes: 35 additions & 0 deletions src/components/layouts/ProfessorDashboardSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useRouter } from 'next/dist/client/router';
import { FunctionComponent } from 'react';

import React from 'react';

import LayoutSkeleton from '@layout/DefaultSkeleton';

import MenuSkeleton from '@skeleton/MenuSkeleton';

import PROFESSOR_MENU from '@constant/professorMenu';

interface IProps {
children?: React.ReactNode;
}

const ProfessorDashboardSkeletonLayout: FunctionComponent<IProps> = ({ children }: IProps) => {
const router = useRouter();

const linkMapper = (links: ILink[]) =>
links.map(({ path, active: _, ...rest }) => ({
active: path === '/professor' ? router.pathname === path : router.pathname.startsWith(path),
path,
...rest,
}));

return (
<LayoutSkeleton title="Professor Dashboard" display="row">
<MenuSkeleton logoutButton={true} links={linkMapper(PROFESSOR_MENU.links)} />

<div className="flex flex-col flex-grow overflow-y-scroll">{children}</div>
</LayoutSkeleton>
);
};

export default ProfessorDashboardSkeletonLayout;
28 changes: 28 additions & 0 deletions src/components/skeletons/ContainerSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { FunctionComponent } from 'react';

import React from 'react';

import TitleSkeleton from '@skeleton/TitleSkeleton';
import TextSkeleton from '@skeleton/TextSkeleton';

interface IProps {
children?: React.ReactNode;
subtitle?: boolean;
breadcrumb?: boolean;
}

const ContainerSkeleton: FunctionComponent<IProps> = ({ children, breadcrumb = false, subtitle = false }: IProps) => {
return (
<div className="relative flex flex-col py-12 px-12 h-full">
<div className="flex flex-col items-start">
{breadcrumb && <TextSkeleton width={32} height={5} className="mb-2" />}
<TitleSkeleton />
{subtitle && <TextSkeleton width={32} height={6} className="mt-2" />}
</div>

{children}
</div>
);
};

export default ContainerSkeleton;
27 changes: 27 additions & 0 deletions src/components/skeletons/IconSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ReactElement } from 'react';

import React from 'react';

interface IProps {
size?: number;
color?: 'gray' | 'blue' | 'red';
}

const IconSkeleton = ({ size = 5, color = 'gray' }: IProps): ReactElement => {
const getColor = () => {
switch (color) {
case 'blue':
return 'from-blue-400 to-blue-200';

case 'red':
return 'from-red-400 to-red-200';

default:
return 'from-gray-300 to-gray-100 ';
}
};

return <div className={`w-${size} h-${size} bg-gradient-to-br rounded ${getColor()}`}></div>;
};

export default IconSkeleton;
36 changes: 36 additions & 0 deletions src/components/skeletons/MenuSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { v4 as uuidv4 } from 'uuid';

import type { FunctionComponent } from 'react';

import React from 'react';

import IconSkeleton from '@skeleton/IconSkeleton';

interface IProps {
links: Array<ILink>;
logoutButton?: boolean;
}

const MenuSkeleton: FunctionComponent<IProps> = ({ links, logoutButton = false }: IProps) => {
return (
<div className="flex flex-col justify-between px-10 py-16 border-r border-gray-300 flex-shrink-0 flex-grow-0">
<div className="flex justify-start mb-16">
<IconSkeleton size={7} />
</div>

<ul className="flex flex-col gap-6 h-full">
{links.map(({ active }) => (
<IconSkeleton size={6} key={uuidv4()} color={active ? 'blue' : 'gray'} />
))}

{logoutButton && (
<li className="mt-auto text-gray-black">
<IconSkeleton size={6} />
</li>
)}
</ul>
</div>
);
};

export default MenuSkeleton;
66 changes: 66 additions & 0 deletions src/components/skeletons/TableSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { v4 as uuidv4 } from 'uuid';

import { ReactElement, useState } from 'react';

import React from 'react';
import clsx from 'clsx';

import TextSkeleton from '@skeleton/TextSkeleton';
import IconSkeleton from '@skeleton/IconSkeleton';

import { randomSizeArray } from '@util/generate.utils';
import { random } from '@util/array.utils';

interface IProps {
attributes: Array<[name: string, attribute: string]>;
}

const TableSkeleton = ({ attributes }: IProps): ReactElement => {
const generateTable = () =>
randomSizeArray(1, 9, 0).map((el) => {
const xArr = [];

for (let i = 0; i < attributes.length; i++) {
xArr.push(random([24, 28, 32, 36, 40, 44, 48]));
}

return xArr;
});

const [fakeDataArray] = useState(generateTable());

return (
<table className="table-fixed w-full mt-14">
<thead>
<tr>
{attributes.map(([name, slug]) => (
<td className={clsx(['px-4 py-3 text-black border-t border-gray-300 text-sm'], slug === 'id' && 'w-2/24')} key={uuidv4()}>
{slug === 'id' ? <TextSkeleton width={12} height={5} /> : <TextSkeleton randomWidth max={48} height={5} />}
</td>
))}
<td className="w-2/24 px-4 py-3 text-black border-t border-gray-300 text-sm"></td>
</tr>
</thead>

<tbody>
{fakeDataArray.map((arr) => (
<tr key={uuidv4()}>
{attributes.map(([name, slug], index) => (
<td className={clsx(['px-4 py-3 text-black border-t border-gray-300 text-sm'], slug === 'id' && 'w-2/24')} key={uuidv4()}>
{slug === 'id' ? <TextSkeleton width={12} height={5} /> : <TextSkeleton width={arr[index]} height={5} />}
</td>
))}

<td className="px-4 py-3 text-black border-t border-gray-300 text-sm" key={uuidv4()}>
<div className="flex justify-center w-full">
<IconSkeleton size={5} color="red" />
</div>
</td>
</tr>
))}
</tbody>
</table>
);
};

export default TableSkeleton;
25 changes: 25 additions & 0 deletions src/components/skeletons/TextSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ReactElement, useState } from 'react';

import React from 'react';
import clsx from 'clsx';

import { random } from '@util/array.utils';

interface IProps {
width?: number;
height?: number;

randomWidth?: boolean;
max?: number;

className?: string;
}

const WIDTHS = [24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96];

const TextSkeleton = ({ width = 96, height = 4, randomWidth, max, className }: IProps): ReactElement => {
const [textWidth] = useState(randomWidth ? random(max ? WIDTHS.filter((el) => el <= max) : WIDTHS) : width);
return <div className={clsx([`h-${height} w-${textWidth} bg-gradient-to-br from-gray-300 to-gray-100 rounded`, className])}></div>;
};

export default TextSkeleton;
30 changes: 30 additions & 0 deletions src/components/skeletons/TitleSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { FunctionComponent, useState } from 'react';

import React from 'react';

interface IProps {
level?: number;
}

const TitleSkeleton: FunctionComponent<IProps> = ({ level }: IProps) => {
const [className] = useState('w-80 text-transparent bg-gradient-to-br from-gray-300 to-gray-100 rounded');

switch (level) {
case 1:
return <div className={`h-9 ${className}`}></div>;

case 2:
return <div className={`h-8 ${className}`}></div>;

case 3:
return <div className={`h-7 ${className}`}></div>;

case 4:
return <div className={`h-7 ${className}`}></div>;

default:
return <div className={`h-9 ${className}`}></div>;
}
};

export default TitleSkeleton;
26 changes: 0 additions & 26 deletions src/constants/adminMenu.ts

This file was deleted.

Loading

1 comment on commit a51463e

@vercel
Copy link

@vercel vercel bot commented on a51463e Aug 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.