Skip to content
This repository was archived by the owner on Jan 28, 2026. It is now read-only.

Commit 54bf424

Browse files
author
ge85riz
committed
📝 chore(types): add missing TypeScript types for various variables
1 parent 3ecfdf1 commit 54bf424

19 files changed

Lines changed: 110 additions & 94 deletions

frontend/src/components/ProtectedRoute.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useAuth } from "../contexts/AuthContext";
33
import { Spin } from "utils/antd.tsx";
44
import type { Role } from "types/employee.ts";
55
import toast from "react-hot-toast";
6+
import React from "react";
67

78
interface ProtectedRouteProps {
89
children: React.ReactNode;
@@ -31,7 +32,7 @@ export function ProtectedRoute({ children, allowedRoles }: ProtectedRouteProps)
3132
const hasRequiredRole = user?.roles?.some(role => allowedRoles.includes(role as Role));
3233

3334
if (!hasRequiredRole) {
34-
toast.error("You are not authorized for this action.");
35+
if (user) toast.error("You are not authorized for this action.");
3536
return <Navigate to="/login" state={{ from: location }} replace />;
3637
}
3738

frontend/src/components/canvas/EventListeners.tsx

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import type { AppState } from "components/canvas/reducers/CanvasReducer.tsx";
1818
import React from "react";
1919
import type { Table } from "components/canvas/elements/Table.tsx";
2020
import type { KonvaEventObject } from "konva/lib/Node";
21-
import type { Wall } from "components/canvas/elements/Wall.tsx";
21+
import type { QuickWallProps, Wall } from "components/canvas/elements/Wall.tsx";
2222
import type { SelectionRectangleType } from "components/canvas/elements/SelectionRectangle.tsx";
2323
import { validateCanvasElementDeletion } from "components/canvas/utils/functions.tsx";
2424
import toast from "react-hot-toast";
@@ -41,7 +41,7 @@ export const handleKeyDown = (
4141
dispatch: (action: Action) => void,
4242
setSelectedIds: React.Dispatch<React.SetStateAction<UUID[]>>,
4343
setIsShiftPressed: React.Dispatch<React.SetStateAction<boolean>>,
44-
selectedIds: UUID[], setQuickWallCoordinates: any,
44+
selectedIds: UUID[], setQuickWallCoordinates: React.Dispatch<React.SetStateAction<QuickWallProps>>,
4545
state: AppState) => {
4646
// we have to skip key handling if user is typing in an input or textarea
4747
const tag = (e.target as HTMLElement).tagName.toLowerCase();
@@ -158,7 +158,7 @@ export function handleDoubleClickOnElement(
158158
export function handleMouseUp(isSelecting: React.RefObject<boolean>, selectionRectangle: SelectionRectangleType,
159159
state: AppState,
160160
stageRef: React.RefObject<Konva.Stage | null>,
161-
rectRefs: any,
161+
rectRefs: React.RefObject<Map<UUID, Konva.NodeConfig>>,
162162
dispatch: (action: Action) => void,
163163
setSelectionRectangle: React.Dispatch<React.SetStateAction<SelectionRectangleType>>,
164164
setSelectedIds: React.Dispatch<React.SetStateAction<UUID[]>>) {
@@ -184,7 +184,7 @@ export function handleMouseUp(isSelecting: React.RefObject<boolean>, selectionRe
184184
// we are checking if rectangle intersects with selection box
185185
return Konva.Util.haveIntersection(
186186
selBox,
187-
rectRefs.current.get(rect.id).getClientRect({ relativeTo: stageRef.current }),
187+
rectRefs.current.get(rect.id)!.getClientRect({ relativeTo: stageRef.current }),
188188
);
189189
});
190190
dispatch(setChairIdForManualAssignment(null));
@@ -198,7 +198,7 @@ export const handleMouseMove = (
198198
stageRef: React.RefObject<Konva.Stage | null>,
199199
isSelecting: React.RefObject<boolean>,
200200
selectionRectangle: SelectionRectangleType,
201-
setSelectionRectangle) => {
201+
setSelectionRectangle: React.Dispatch<React.SetStateAction<SelectionRectangleType>>) => {
202202

203203
const container = stageRef!.current?.container();
204204
if (container && (isShiftPressed || state.buildMode === 1)) {
@@ -224,11 +224,11 @@ export const handleMouseDown = (
224224
isSelecting: React.RefObject<boolean>,
225225
dispatch: (action: Action) => void,
226226
setSelectedIds: React.Dispatch<React.SetStateAction<UUID[]>>,
227-
setSelectionRectangle,
227+
setSelectionRectangle: React.Dispatch<React.SetStateAction<SelectionRectangleType>>,
228228
scale: number,
229229
state: AppState,
230-
quickWallCoordinates,
231-
setQuickWallCoordinates) => {
230+
quickWallCoordinates: QuickWallProps,
231+
setQuickWallCoordinates: React.Dispatch<React.SetStateAction<QuickWallProps>>) => {
232232
const stage = e.target.getStage()!;
233233
const pointer = stageRef.current!.getPointerPosition()!;
234234
isSelecting.current = e.evt.shiftKey;
@@ -294,7 +294,13 @@ export const handleDragStart = (dispatch: (action: Action) => void) => {
294294
};
295295

296296
// handle drag end for elements
297-
export const handleDragEnd = (e: Konva.KonvaEventObject<DragEvent>, el: ElementProperties, dispatch: (action: Action) => void, state: AppState, rectRefs, stageRef: React.RefObject<Konva.Stage | null>) => {
297+
export const handleDragEnd = (
298+
e: Konva.KonvaEventObject<DragEvent>,
299+
el: ElementProperties,
300+
dispatch: (action: Action) => void,
301+
state: AppState,
302+
rectRefs: React.RefObject<Map<UUID, Konva.NodeConfig>>,
303+
stageRef: React.RefObject<Konva.Stage | null>) => {
298304
const shape = e.target;
299305
const x = shape.x();
300306
const y = shape.y();
@@ -493,9 +499,13 @@ export const handleDragEnd = (e: Konva.KonvaEventObject<DragEvent>, el: ElementP
493499

494500
};
495501

496-
export const handleTransformEnd = (transformerRef, state: AppState, dispatch: (action: Action) => void, setSelectedIds: React.Dispatch<React.SetStateAction<UUID[]>>) => {
497-
const nodes = transformerRef.current!.nodes();
502+
export const handleTransformEnd = (
503+
transformerRef: React.RefObject<Konva.Transformer | null>,
504+
state: AppState,
505+
dispatch: (action: Action) => void,
506+
setSelectedIds: React.Dispatch<React.SetStateAction<UUID[]>>) => {
498507

508+
const nodes = transformerRef.current!.nodes();
499509
const selectedIds = [];
500510
const updates = [];
501511
for (const node of nodes) {
@@ -538,7 +548,7 @@ export const handleTransformEnd = (transformerRef, state: AppState, dispatch: (a
538548
};
539549
updates.push(update);
540550
}
541-
// @ts-ignore
551+
542552
dispatch(updateMultipleElements(updates));
543553
dispatch(setChairIdForManualAssignment(null));
544554
setSelectedIds(selectedIds);

frontend/src/components/canvas/KonvaCanvas.tsx

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable react-hooks/exhaustive-deps */
12
import { useCanvas } from "./contexts/CanvasContext.tsx";
23
import React, { useEffect, useMemo, useRef, useState } from "react";
34
import { Group, Layer, Stage, Transformer } from "react-konva";
@@ -11,7 +12,7 @@ import useApiService from "services/apiService.ts";
1112
import { useParams } from "react-router-dom";
1213
import StagePreview from "components/canvas/elements/StagePreview.tsx";
1314
import NeighbourArrows from "components/canvas/elements/NeighbourArrows.tsx";
14-
import SelectionRectangle from "components/canvas/elements/SelectionRectangle.tsx";
15+
import SelectionRectangle, { type SelectionRectangleType } from "components/canvas/elements/SelectionRectangle.tsx";
1516
import {
1617
handleDoubleClickOnElement,
1718
handleDragEnd,
@@ -28,12 +29,14 @@ import {
2829
handleWheel,
2930
} from "components/canvas/EventListeners.tsx";
3031
import type { Chair } from "components/canvas/elements/Chair.tsx";
32+
import type { QuickWallProps } from "components/canvas/elements/Wall.tsx";
3133

3234

3335
const TYPE_ORDER: { [key in ShapeType]: number } = {
3436
rectTable: 2,
3537
circleTable: 3,
3638
chair: 4,
39+
room: 0,
3740
wall: 1,
3841
quickWall: 1,
3942
arrow: 5,
@@ -47,7 +50,7 @@ export interface KonvaCanvasProps {
4750
isFullWidth?: boolean,
4851
}
4952

50-
function KonvaCanvas({ stageReference, schematicsUUID, isFullWidth }: KonvaCanvasProps) {
53+
export function KonvaCanvas({ stageReference, schematicsUUID, isFullWidth }: KonvaCanvasProps) {
5154
const { state, dispatch } = useCanvas();
5255
let stageRef = useRef<Konva.Stage | null>(null);
5356
let { schematicsId } = useParams();
@@ -62,18 +65,24 @@ function KonvaCanvas({ stageReference, schematicsUUID, isFullWidth }: KonvaCanva
6265
const containerRef = useRef<HTMLDivElement | null>(null);
6366
const [scale, setScale] = useState(1);
6467
const [containerSize, setContainerSize] = useState({ width: 800, height: 600 });
65-
const [quickWallCoordinates, setQuickWallCoordinates] = useState<{
66-
x1?: number;
67-
y1?: number;
68-
}>({ x1: undefined, y1: undefined });
68+
const [quickWallCoordinates, setQuickWallCoordinates] = useState<QuickWallProps>({ x1: undefined, y1: undefined });
6969
const { getSchematics } = useApiService();
7070
const [selectedIds, setSelectedIds] = useState<string[]>([]);
7171
const [initiated, setInitiated] = useState(false);
7272
const [isShiftPressed, setIsShiftPressed] = useState(false);
7373
const dragLayer = useRef<Konva.Layer | null>(null);
7474
const mainLayer = useRef<Konva.Layer | null>(null);
75-
76-
const [selectionRectangle, setSelectionRectangle] = useState({
75+
const isSelecting = useRef(false);
76+
const transformerRef = useRef<Konva.Transformer>(null);
77+
const rectRefs = useRef(new Map());
78+
// we sort elements according to their types so that they are drawn properly
79+
// this sort operation causes overhead initially but negligible afterward
80+
// we use this hash function to limit these unnecessary re-sorts to only positions/properties change
81+
const elementTypesHash = useMemo(() =>
82+
state.elements?.map(el => el.type).join(","),
83+
[state.elements],
84+
);
85+
const [selectionRectangle, setSelectionRectangle] = useState<SelectionRectangleType>({
7786
visible: false,
7887
x1: 0,
7988
y1: 0,
@@ -107,10 +116,6 @@ function KonvaCanvas({ stageReference, schematicsUUID, isFullWidth }: KonvaCanva
107116
fetchData();
108117
}, [dispatch, getSchematics, initiated, schematicsId, state.canvasPosition, state.scale]);
109118

110-
useEffect(() => {
111-
window.scrollTo(0, 0); // we have to scroll to top-left corner of the page, otherwise it looks bad
112-
}, []);
113-
114119
// Measure container size
115120
useEffect(() => {
116121
const updateContainerSize = () => {
@@ -128,20 +133,17 @@ function KonvaCanvas({ stageReference, schematicsUUID, isFullWidth }: KonvaCanva
128133
return () => window.removeEventListener("resize", updateContainerSize);
129134
}, [isFullWidth]);
130135

131-
const isSelecting = useRef(false);
132-
const transformerRef = useRef<Konva.Transformer>(null);
133-
const rectRefs = useRef(new Map());
134-
136+
// if selectedIds change, then capture them into Transformer so that we can scale or rotate them
135137
useEffect(() => {
136138
if (selectedIds.length && transformerRef.current) {
137139
const nodes = selectedIds.map(id => rectRefs.current.get(id)).filter(node => node);
138-
139140
transformerRef.current.nodes(nodes);
140141
} else if (transformerRef.current) {
141142
transformerRef.current.nodes([]);
142143
}
143144
}, [selectedIds]);
144145

146+
// if build mode changes, then reset quickwall
145147
useEffect(() => {
146148
if (state.buildMode === 0) setQuickWallCoordinates({ x1: undefined, y1: undefined });
147149
}, [state.buildMode]);
@@ -165,12 +167,6 @@ function KonvaCanvas({ stageReference, schematicsUUID, isFullWidth }: KonvaCanva
165167
};
166168
}, [dispatch, setSelectedIds, setIsShiftPressed, selectedIds, setQuickWallCoordinates, stageRef]);
167169

168-
// unnecessary re-sorts when only positions/properties change
169-
const elementTypesHash = useMemo(() =>
170-
state.elements?.map(el => el.type).join(","),
171-
[state.elements],
172-
);
173-
174170
useEffect(() => {
175171
if (state.elements?.length > 1) {
176172
state.elements.sort((a, b) => {
@@ -342,5 +338,3 @@ function KonvaCanvas({ stageReference, schematicsUUID, isFullWidth }: KonvaCanva
342338
</div>
343339
);
344340
}
345-
346-
export default KonvaCanvas;

frontend/src/components/canvas/actions/actions.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import type { Text } from "components/canvas/elements/Text.tsx";
99

1010
export interface Action {
1111
type: string;
12-
payload: any | number | string | string[];
12+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
13+
payload: number | string | string[] | any;
1314
setSelectedIds?: Dispatch<SetStateAction<string[]>>;
1415
}
1516

frontend/src/components/canvas/elements/Wall.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import { v4 as uuidv4 } from "uuid";
33
import type { ElementProperties, ShapeType, UUID } from "components/canvas/utils/constants.tsx";
44
import { handleMouseOut, handleMouseOver } from "components/canvas/utils/functions.tsx";
55

6+
export type QuickWallProps = {
7+
x1?: number;
8+
y1?: number;
9+
}
10+
611
export class Wall implements ElementProperties {
712
id: UUID;
813
type: ShapeType;

frontend/src/components/canvas/reducers/CanvasReducer.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,7 @@ export function reducer(state: AppState, action: Action) {
202202
return updated;
203203
});
204204

205-
// eslint-disable-next-line
206-
// @ts-ignore
207-
action.setSelectedIds(Object.values(idMap));
205+
if (action.setSelectedIds) action.setSelectedIds(Object.values(idMap));
208206

209207
return {
210208
...state,

frontend/src/components/canvas/utils/constants.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Arrow, ArrowRender } from "components/canvas/elements/Arrow.tsx";
55
import { Text, TextRender } from "components/canvas/elements/Text.tsx";
66

77
export type UUID = string;
8-
export type ShapeType = "chair" | "rectTable" | "circleTable" | "wall" | "quickWall" | "arrow" | "text";
8+
export type ShapeType = "chair" | "rectTable" | "circleTable" | "wall" | "quickWall" | "arrow" | "text" | "room";
99
export type AlgorithmType = "table" | "distance";
1010

1111
export const DIET_TYPE_COLORS: Record<string, string> = {
@@ -23,6 +23,21 @@ export const EMPLOYMENT_TYPE_COLORS: Record<string, string> = {
2323
THESIS: "purple",
2424
};
2525

26+
export enum DietaryPreference {
27+
VEGETARIAN = "Vegetarian",
28+
VEGAN = "Vegan",
29+
LACTOSE_FREE = "Lactose Free",
30+
FRUCTOSE_FREE = "Fructose Free",
31+
GLUTEN_FREE = "Gluten Free",
32+
}
33+
34+
export enum EmploymentType {
35+
FULLTIME = "Full Time",
36+
PARTTIME = "Part Time",
37+
WORKING_STUDENT = "Working Student",
38+
THESIS = "Thesis",
39+
}
40+
2641
export interface ElementProperties {
2742
id: UUID;
2843
type: ShapeType;

frontend/src/contexts/AuthContext.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { createContext, type ReactNode, useCallback, useContext, useEffect, useState } from "react";
2-
import type { AuthState, User, UserType } from "../types/auth";
2+
import type { AuthState, UserType } from "../types/auth";
33
import { authService } from "../services/authService";
44

55
interface AuthContextType extends AuthState {
6-
login: (credentials: User) => Promise<void>;
6+
login: (credentials: UserType) => Promise<void>;
77
logout: () => void;
88
}
99

frontend/src/pages/Employees/EmployeeForm.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { DatePicker, Form, Input, Select } from "utils/antd.tsx";
2-
import { DietaryPreference, Role } from "types/employee";
2+
import { Role } from "types/employee";
33
import { DietTypeTag } from "components/DietTypeTag.tsx";
44
import dayjs from "dayjs";
5+
import { DietaryPreference } from "components/canvas/utils/constants.tsx";
56

67
const { Option } = Select;
78

frontend/src/pages/Employees/EmployeesList.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from "@ant-design/icons";
1111
import type { ColumnsType } from "antd/es/table";
1212
import { useNavigate } from "react-router-dom";
13-
import { type Employee, getFullName, Role } from "types/employee.ts";
13+
import { type Employee, getFullName, type Profile, Role } from "types/employee.ts";
1414
import useApiService from "services/apiService.ts";
1515
import toast from "react-hot-toast";
1616
import { Breadcrumb } from "components/Breadcrumb";
@@ -326,7 +326,9 @@ export const EmployeesList = () => {
326326
const handleAddAllEmployees = async () => {
327327
if (!importedRows.length) return;
328328
// Map importedRows to EmployeeCreateDTO-like objects
329-
const payload = importedRows.map(row => ({
329+
const payload: (Omit<Employee, "profile"> & {
330+
profile: Omit<Profile, "id" | "dietTypes" | "isVisitor">
331+
})[] = importedRows.map(row => ({
330332
profile: {
331333
name: row.name.trim(),
332334
lastName: row.lastName.trim(),
@@ -353,7 +355,7 @@ export const EmployeesList = () => {
353355
employees.push(...result.insertedEmployees.map(e => ({ ...e, key: e.profile.id })));
354356
setEmployees([...employees]);
355357
}
356-
} catch (err) {
358+
} catch {
357359
toast.error("Failed to import employees");
358360
} finally {
359361
setLoading(false);

0 commit comments

Comments
 (0)