Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

213 feature UI changes for logon onboarding and create/upload signature #219

Merged
merged 5 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions apps/server/prisma/migrations/20241201022321_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Warnings:

- Added the required column `signatureLink` to the `Employee` table without a default value. This is not possible if the table is not empty.

*/
-- AlterTable
ALTER TABLE "Employee" ADD COLUMN "signatureLink" VARCHAR(255) NOT NULL;
1 change: 1 addition & 0 deletions apps/server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ model Employee {
firstName String @db.VarChar(255)
lastName String @db.VarChar(255)
email String @unique @db.VarChar(255)
signatureLink String @db.VarChar(255)
isAdmin Boolean @default(false) @db.Boolean
pswdHash String? @db.VarChar(255)
createdAt DateTime @default(now())
Expand Down
7 changes: 7 additions & 0 deletions apps/server/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const DIGITAL_MFA_ID_BADGE_REQUEST_UUID = uuidv4();
const TRAVEL_AUTHORIZATION_UUID = uuidv4();

const DEV_FORM_DOC_LINK = 'http://localhost:3002/test.pdf';
const DEV_SIGNATURE_LINK = 'http://localhost:3002/signature.png';

// type definition for employee data used in upsertEmployee
type EmployeeData = {
Expand All @@ -47,6 +48,7 @@ type EmployeeData = {
lastName: string;
email: string;
positionId: string;
signatureLink: string;
};

// update or insert employee to database based on the employee id
Expand All @@ -59,6 +61,7 @@ async function upsertEmployee(empData: EmployeeData) {
firstName: empData.firstName,
lastName: empData.lastName,
email: empData.email,
signatureLink: empData.signatureLink,
position: {
connect: { id: empData.positionId },
},
Expand Down Expand Up @@ -383,27 +386,31 @@ async function main() {
lastName: 'Zhang',
email: '[email protected]',
positionId: CHIEF_OF_STAFF_UUID,
signatureLink: DEV_SIGNATURE_LINK,
},
{
id: KAI_ZHENG_UUID,
firstName: 'Kai',
lastName: 'Zheng',
email: '[email protected]',
positionId: CHIEF_FIN_OFFICER_UUID,
signatureLink: DEV_SIGNATURE_LINK,
},
{
id: ANGELA_WEIGL_UUID,
firstName: 'Angela',
lastName: 'Weigl',
email: '[email protected]',
positionId: AGG_DIR_UUID,
signatureLink: DEV_SIGNATURE_LINK,
},
{
id: ANSHUL_SHIRUDE_UUID,
firstName: 'Anshul',
lastName: 'Shirude',
email: '[email protected]',
positionId: CHIEF_LEARNING_ENGAGEMENT_UUID,
signatureLink: DEV_SIGNATURE_LINK,
},
];

Expand Down
1 change: 1 addition & 0 deletions apps/server/src/app.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export class AppController {
lastName: employeeDto.lastName,
email: employeeDto.email,
password: employeeDto.password,
signatureLink: employeeDto.signatureLink,
positionId: '',
};

Expand Down
3 changes: 3 additions & 0 deletions apps/server/src/auth/auth.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe('AuthService', () => {
firstName: 'First',
lastName: 'Last',
positionId: 'positionId',
signatureLink: 'signatureLink',
position: {
id: 'positionId',
name: 'Manager',
Expand Down Expand Up @@ -72,6 +73,7 @@ describe('AuthService', () => {
firstName: 'First',
lastName: 'Last',
positionId: 'positionId',
signatureLink: 'signatureLink',
position: {
id: 'positionId',
name: 'Manager',
Expand Down Expand Up @@ -150,6 +152,7 @@ describe('AuthService', () => {
createdAt: new Date(0),
updatedAt: new Date(0),
refreshToken: null,
signatureLink: 'signatureLink',
};
const result = await service.login(user);
const decodedAccessToken = jwtService.decode(result.accessToken);
Expand Down
5 changes: 5 additions & 0 deletions apps/server/src/auth/dto/register-employee.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ export class RegisterEmployeeDto {
@IsNotEmpty()
@ApiProperty()
departmentName: string;

@IsString()
@IsNotEmpty()
@ApiProperty()
signatureLink: string;
}
5 changes: 5 additions & 0 deletions apps/server/src/employees/dto/create-employee.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ export class CreateEmployeeDto {
@MinLength(5)
@ApiProperty()
password: string;

@IsString()
@IsNotEmpty()
@ApiProperty()
signatureLink: string;
}
4 changes: 4 additions & 0 deletions apps/server/src/employees/employees.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe('EmployeesController', () => {
firstName: 'John',
lastName: 'Doe',
positionId: 'position-id',
signatureLink: 'signature-link',
position: {
id: 'position-id',
name: 'position-name',
Expand All @@ -57,6 +58,7 @@ describe('EmployeesController', () => {
firstName: 'Bilbo',
lastName: 'Baggins',
positionId: 'position-id',
signatureLink: 'signature-link',
position: {
id: 'position-id',
name: 'position-name',
Expand Down Expand Up @@ -86,6 +88,7 @@ describe('EmployeesController', () => {
firstName: 'John',
lastName: 'Doe',
positionId: 'position-id',
signatureLink: 'signature-link',
position: {
id: 'position-id',
name: 'position-name',
Expand All @@ -112,6 +115,7 @@ describe('EmployeesController', () => {
firstName: 'Bilbo',
lastName: 'Baggins',
positionId: 'position-id',
signatureLink: 'signature-link',
position: {
id: 'position-id',
name: 'position-name',
Expand Down
1 change: 1 addition & 0 deletions apps/server/src/employees/employees.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class EmployeesService {
lastName: createEmployeeDto.lastName,
email: createEmployeeDto.email,
positionId: createEmployeeDto.positionId,
signatureLink: createEmployeeDto.signatureLink,
pswdHash: await bcrypt.hash(
createEmployeeDto.password,
await bcrypt.genSalt(),
Expand Down
3 changes: 3 additions & 0 deletions apps/server/src/employees/entities/employee.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export class EmployeeBaseEntity implements Employee {
@ApiProperty()
isAdmin: boolean;

@ApiProperty()
signatureLink: string;

@Exclude()
pswdHash: string | null;

Expand Down
3 changes: 3 additions & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,12 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-dropzone": "^14.3.5",
"react-icons": "^5.3.0",
"react-pdf": "^7.7.0",
"react-query": "^3.39.3",
"react-router-dom": "^6.8.1",
"react-scripts": "^5.0.1",
"react-signature-canvas": "^1.0.6",
"typescript": "^5.2.2",
"uuid": "^9.0.0"
},
Expand All @@ -56,6 +58,7 @@
"@babel/plugin-syntax-flow": "^7.22.5",
"@babel/plugin-transform-react-jsx": "^7.22.5",
"@babel/preset-env": "^7.22.10",
"@types/react-signature-canvas": "^1.0.6",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"prettier": "^3.0.3"
Expand Down
Binary file added apps/web/public/TheChairman-Regular.otf
Binary file not shown.
1 change: 1 addition & 0 deletions apps/web/src/client/models/CreateEmployeeDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export type CreateEmployeeDto = {
positionId: string;
email: string;
password: string;
signatureLink: string;
};

1 change: 1 addition & 0 deletions apps/web/src/client/models/EmployeeBaseEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type EmployeeBaseEntity = {
lastName: string;
email: string;
isAdmin: boolean;
signatureLink: string;
positionId: string;
pswdHash: string | null;
createdAt: string;
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/client/models/EmployeeEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type EmployeeEntity = {
lastName: string;
email: string;
isAdmin: boolean;
signatureLink: string;
position: PositionBaseEntity;
positionId: string;
pswdHash: string | null;
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/client/models/RegisterEmployeeDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ export type RegisterEmployeeDto = {
password: string;
positionName: string;
departmentName: string;
signatureLink: string;
};

1 change: 1 addition & 0 deletions apps/web/src/client/models/UpdateEmployeeDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export type UpdateEmployeeDto = {
firstName?: string;
lastName?: string;
positionId?: string;
signatureLink?: string;
};

63 changes: 63 additions & 0 deletions apps/web/src/components/ButtonSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Box } from '@chakra-ui/react';

export const ButtonSwitch = ({
isToggleLeft,
onClickLeft,
onClickRight,
activeColor,
leftLabel,
rightLabel,
}: {
isToggleLeft: boolean;
onClickLeft: () => void;
onClickRight: () => void;
activeColor: string;
leftLabel: string;
rightLabel: string;
}) => {
const Button = ({
label,
side,
isActive,
onToggle,
}: {
label: string;
side: 'left' | 'right';
isActive: boolean;
onToggle: () => void;
}) => {
return (
<Box
as="button"
flex="1"
borderWidth="1px"
borderRadius={side === 'left' ? '4px 0 0 4px' : '0 4px 4px 0'}
padding="6px 12px"
fontWeight="500"
fontSize="15px"
borderColor={isActive ? activeColor : '#C0C0C0'}
color={isActive ? activeColor : '#63646B'}
Copy link
Contributor

Choose a reason for hiding this comment

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

should these colors be constants stored somewhere

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yea lets make a ticket for this next sem so we can standardize it for all components

onClick={onToggle}
>
{label}
</Box>
);
};

return (
<Box display="inline-flex">
<Button
label={leftLabel}
isActive={isToggleLeft}
side="left"
onToggle={onClickLeft}
/>
<Button
label={rightLabel}
isActive={!isToggleLeft}
side="right"
onToggle={onClickRight}
/>
</Box>
);
};
98 changes: 98 additions & 0 deletions apps/web/src/components/SignaturePad.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { Box, Flex, Input, Link } from '@chakra-ui/react';
import { useRef } from 'react';
import SignatureCanvas from 'react-signature-canvas';
import { ButtonSwitch } from '@web/components/ButtonSwitch';

interface SignaturePadProps {
createSignatureType: string;
setCreateSignatureType: (type: string) => void;
signature: string;
setSignature: (signature: string) => void;
signatureCanvas: React.RefObject<SignatureCanvas>;
onClear?: () => void;
}

export const SignaturePad = ({
createSignatureType,
setCreateSignatureType,
signature,
setSignature,
signatureCanvas,
onClear,
}: SignaturePadProps) => {
const clearSignature = () => {
if (signatureCanvas.current) {
signatureCanvas.current.clear();
}
setSignature('');
onClear?.();
};

return (
<>
<Box width="100%" display="flex" flexDirection="column">
<label htmlFor="signature">Create Signature</label>
<Flex marginTop="8px" display="flex" justifyContent={'space-between'}>
<Flex flex="1" flexDirection="column">
<ButtonSwitch
isToggleLeft={createSignatureType === 'draw'}
onClickLeft={() => setCreateSignatureType('draw')}
onClickRight={() => setCreateSignatureType('type')}
activeColor="#1367EA"
leftLabel="Draw"
rightLabel="Type"
/>
</Flex>
<Flex flex="1" justifyContent="flex-end" alignItems="flex-end">
<Link
as="button"
color="#1367EA"
fontSize="14px"
onClick={clearSignature}
>
Clear
</Link>
</Flex>
</Flex>
<Box
borderRadius="6px"
border="1px solid #C0C0C0"
marginTop="8px"
position="relative"
>
{createSignatureType === 'draw' ? (
<>
<SignatureCanvas
penColor="black"
canvasProps={{
width: 500,
height: 120,
}}
ref={signatureCanvas}
/>
<Box
position="absolute"
bottom="16px"
width="90%"
height="1px"
bg="#7C7F86"
left="50%"
transform="translateX(-50%)"
/>
</>
) : (
<Input
type="text"
placeholder="Type your signature here"
padding="8px"
borderRadius="6px"
border="1px solid #C0C0C0"
onChange={(e) => setSignature(e.target.value)}
value={signature}
/>
)}
</Box>
</Box>
</>
);
};
Loading