mirror of
https://github.com/xlorepdarkhelm/numinar-coding-project.git
synced 2026-09-06 00:48:26 -04:00
Got the eslint configuration inside the pre-commit figured out.
Signed-off-by: Cliff Hill <xlorep@darkhelm.org>
This commit is contained in:
@@ -3,10 +3,8 @@ repos:
|
||||
hooks:
|
||||
- id: eslint-frontend
|
||||
name: ESLint
|
||||
entry: yarn --cwd frontend eslint .
|
||||
entry: yarn --cwd frontend node lint-staged.js
|
||||
language: system
|
||||
types: [javascript]
|
||||
files: ^frontend/src/
|
||||
- id: black
|
||||
name: black
|
||||
entry: black
|
||||
@@ -143,6 +143,9 @@ def precommit(session: Session) -> None:
|
||||
)
|
||||
session.run("pre-commit", *args)
|
||||
# Run frontend lint using yarn lint
|
||||
import os
|
||||
|
||||
os.chdir("../frontend")
|
||||
session.run("yarn", "lint", external=True)
|
||||
if args and args[0] == "install":
|
||||
activate_virtualenv_in_precommit_hooks(session)
|
||||
|
||||
1032
backend/poetry.lock
generated
1032
backend/poetry.lock
generated
File diff suppressed because it is too large
Load Diff
8
frontend/lint-staged.js
Normal file
8
frontend/lint-staged.js
Normal file
@@ -0,0 +1,8 @@
|
||||
// lint-staged.js
|
||||
const { execSync } = require("child_process");
|
||||
const files = process.argv
|
||||
.slice(2)
|
||||
.filter((f) => /^src\/.*\.(js|jsx|ts|tsx)$/.test(f));
|
||||
if (files.length) {
|
||||
execSync(`yarn eslint ${files.join(" ")}`, { stdio: "inherit" });
|
||||
}
|
||||
@@ -37,6 +37,7 @@
|
||||
"start": "react-app-rewired start",
|
||||
"build": "react-app-rewired build",
|
||||
"test": "react-app-rewired test",
|
||||
"lint": "eslint 'src/**/*.{ts,tsx}'",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
||||
@@ -25,16 +25,24 @@ describe("BookingForm", () => {
|
||||
readyState = 0;
|
||||
url = "";
|
||||
withCredentials = false;
|
||||
close() {}
|
||||
addEventListener() {}
|
||||
removeEventListener() {}
|
||||
close() {
|
||||
/* mock implementation */
|
||||
}
|
||||
addEventListener() {
|
||||
/* mock implementation */
|
||||
}
|
||||
removeEventListener() {
|
||||
/* mock implementation */
|
||||
}
|
||||
dispatchEvent() {
|
||||
return true;
|
||||
}
|
||||
onmessage: ((this: EventSource, ev: MessageEvent) => any) | null = null;
|
||||
onerror: ((this: EventSource, ev: Event) => any) | null = null;
|
||||
onopen: ((this: EventSource, ev: Event) => any) | null = null;
|
||||
onmessage: ((this: EventSource, ev: MessageEvent) => unknown) | null =
|
||||
null;
|
||||
onerror: ((this: EventSource, ev: Event) => unknown) | null = null;
|
||||
onopen: ((this: EventSource, ev: Event) => unknown) | null = null;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
window.EventSource = EventSourceMock as any;
|
||||
});
|
||||
it("renders the booking form dialog when open", () => {
|
||||
@@ -42,7 +50,12 @@ describe("BookingForm", () => {
|
||||
<RoomProvider>
|
||||
<BookingProvider>
|
||||
<UserProvider>
|
||||
<BookingForm open={true} onClose={() => {}} />
|
||||
<BookingForm
|
||||
open={true}
|
||||
onClose={() => {
|
||||
/* mock implementation */
|
||||
}}
|
||||
/>
|
||||
</UserProvider>
|
||||
</BookingProvider>
|
||||
</RoomProvider>
|
||||
|
||||
@@ -11,7 +11,15 @@ describe("RoomDetailsModal", () => {
|
||||
equipment: "TV",
|
||||
capacity: 10,
|
||||
};
|
||||
render(<RoomDetailsModal open={true} onClose={() => {}} room={room} />);
|
||||
render(
|
||||
<RoomDetailsModal
|
||||
open={true}
|
||||
onClose={() => {
|
||||
/* mock implementation */
|
||||
}}
|
||||
room={room}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByRole("dialog")).toBeInTheDocument();
|
||||
expect(screen.getByText(/Alpha Room/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -14,7 +14,13 @@ describe("RoomList", () => {
|
||||
},
|
||||
];
|
||||
render(
|
||||
<RoomList rooms={rooms} selectedRoomId={1} onSelectRoom={() => {}} />
|
||||
<RoomList
|
||||
rooms={rooms}
|
||||
selectedRoomId={1}
|
||||
onSelectRoom={() => {
|
||||
/* mock implementation */
|
||||
}}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText(/Alpha Room/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -15,7 +15,12 @@ describe("RoomSelect", () => {
|
||||
];
|
||||
render(
|
||||
<RoomProvider value={{ rooms, fetchRooms: jest.fn() }}>
|
||||
<RoomSelect selectedRoomId={"1"} onChange={() => {}} />
|
||||
<RoomSelect
|
||||
selectedRoomId={"1"}
|
||||
onChange={() => {
|
||||
/* mock implementation */
|
||||
}}
|
||||
/>
|
||||
</RoomProvider>
|
||||
);
|
||||
expect(screen.getByLabelText(/room/i)).toBeInTheDocument();
|
||||
|
||||
@@ -26,16 +26,24 @@ describe("BookingPage", () => {
|
||||
readyState = 0;
|
||||
url = "";
|
||||
withCredentials = false;
|
||||
close() {}
|
||||
addEventListener() {}
|
||||
removeEventListener() {}
|
||||
close() {
|
||||
/* mock implementation */
|
||||
}
|
||||
addEventListener() {
|
||||
/* mock implementation */
|
||||
}
|
||||
removeEventListener() {
|
||||
/* mock implementation */
|
||||
}
|
||||
dispatchEvent() {
|
||||
return true;
|
||||
}
|
||||
onmessage: ((this: EventSource, ev: MessageEvent) => any) | null = null;
|
||||
onerror: ((this: EventSource, ev: Event) => any) | null = null;
|
||||
onopen: ((this: EventSource, ev: Event) => any) | null = null;
|
||||
onmessage: ((this: EventSource, ev: MessageEvent) => unknown) | null =
|
||||
null;
|
||||
onerror: ((this: EventSource, ev: Event) => unknown) | null = null;
|
||||
onopen: ((this: EventSource, ev: Event) => unknown) | null = null;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
window.EventSource = EventSourceMock as any;
|
||||
});
|
||||
it("renders booking page heading", () => {
|
||||
|
||||
@@ -25,16 +25,24 @@ describe("ConfirmationPage", () => {
|
||||
readyState = 0;
|
||||
url = "";
|
||||
withCredentials = false;
|
||||
close() {}
|
||||
addEventListener() {}
|
||||
removeEventListener() {}
|
||||
close() {
|
||||
/* mock implementation */
|
||||
}
|
||||
addEventListener() {
|
||||
/* mock implementation */
|
||||
}
|
||||
removeEventListener() {
|
||||
/* mock implementation */
|
||||
}
|
||||
dispatchEvent() {
|
||||
return true;
|
||||
}
|
||||
onmessage: ((this: EventSource, ev: MessageEvent) => any) | null = null;
|
||||
onerror: ((this: EventSource, ev: Event) => any) | null = null;
|
||||
onopen: ((this: EventSource, ev: Event) => any) | null = null;
|
||||
onmessage: ((this: EventSource, ev: MessageEvent) => unknown) | null =
|
||||
null;
|
||||
onerror: ((this: EventSource, ev: Event) => unknown) | null = null;
|
||||
onopen: ((this: EventSource, ev: Event) => unknown) | null = null;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
window.EventSource = EventSourceMock as any;
|
||||
});
|
||||
it("renders confirmation page heading", async () => {
|
||||
|
||||
@@ -27,16 +27,24 @@ describe("LandingPage", () => {
|
||||
readyState = 0;
|
||||
url = "";
|
||||
withCredentials = false;
|
||||
close() {}
|
||||
addEventListener() {}
|
||||
removeEventListener() {}
|
||||
close() {
|
||||
/* mock implementation */
|
||||
}
|
||||
addEventListener() {
|
||||
/* mock implementation */
|
||||
}
|
||||
removeEventListener() {
|
||||
/* mock implementation */
|
||||
}
|
||||
dispatchEvent() {
|
||||
return true;
|
||||
}
|
||||
onmessage: ((this: EventSource, ev: MessageEvent) => any) | null = null;
|
||||
onerror: ((this: EventSource, ev: Event) => any) | null = null;
|
||||
onopen: ((this: EventSource, ev: Event) => any) | null = null;
|
||||
onmessage: ((this: EventSource, ev: MessageEvent) => unknown) | null =
|
||||
null;
|
||||
onerror: ((this: EventSource, ev: Event) => unknown) | null = null;
|
||||
onopen: ((this: EventSource, ev: Event) => unknown) | null = null;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
window.EventSource = EventSourceMock as any;
|
||||
});
|
||||
it("renders landing page heading", () => {
|
||||
|
||||
@@ -215,7 +215,7 @@ const BookingForm: React.FC<BookingFormProps> = ({
|
||||
// Handlers
|
||||
function handleStartChange(value: string) {
|
||||
setStart(value);
|
||||
let interval = customInterval ?? ENV.DEFAULT_BOOKING_INTERVAL_MINUTES;
|
||||
const interval = customInterval ?? ENV.DEFAULT_BOOKING_INTERVAL_MINUTES;
|
||||
const newEnd = new Date(new Date(value).getTime() + interval * 60000);
|
||||
setEnd(newEnd.toISOString());
|
||||
validateFields();
|
||||
|
||||
@@ -51,9 +51,7 @@ const CalendarView: React.FC<CalendarViewProps> = ({
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// [CalendarView] events updated log removed
|
||||
}, [events]);
|
||||
// [CalendarView] events updated log removed
|
||||
// Custom event content with tooltip
|
||||
const renderEventContent = (arg: { event: BookingEvent }) => {
|
||||
const { event } = arg;
|
||||
@@ -124,8 +122,8 @@ const CalendarView: React.FC<CalendarViewProps> = ({
|
||||
|
||||
// Always show full 24h grid in week/day view
|
||||
const calendarRef = React.useRef<FullCalendar | null>(null);
|
||||
let slotMinTime = "00:00:00";
|
||||
let slotMaxTime = "24:00:00";
|
||||
const slotMinTime = "00:00:00";
|
||||
const slotMaxTime = "24:00:00";
|
||||
const businessHours = [
|
||||
{
|
||||
daysOfWeek: [1, 2, 3, 4, 5, 6, 0], // all days
|
||||
@@ -179,8 +177,6 @@ const CalendarView: React.FC<CalendarViewProps> = ({
|
||||
});
|
||||
}
|
||||
}}
|
||||
// @ts-ignore: dateClick is a valid prop for FullCalendar, but types may be missing
|
||||
// @ts-ignore: dateClick is a valid prop for FullCalendar, but types may be missing
|
||||
dateClick={(info: { date: Date }) => {
|
||||
if (onSlotSelect) {
|
||||
// Simulate a slot selection for the whole day in month view
|
||||
|
||||
@@ -46,6 +46,6 @@ export function getEventDisplayText(
|
||||
* @returns CSS class string
|
||||
*/
|
||||
export function getRoomClass(roomId: number): string {
|
||||
let idx = roomId ? roomId % 20 : 0;
|
||||
const idx = roomId ? roomId % 20 : 0;
|
||||
return `room-color-${idx}`;
|
||||
}
|
||||
|
||||
@@ -183,9 +183,9 @@ const BookingPage: React.FC = () => {
|
||||
// 1. Use selected day, but round to nearest quarter-hour of current time (all in user's local timezone)
|
||||
const now = new Date();
|
||||
// Always construct selectedDay in local time using year/month/day from the selected date
|
||||
let baseDate = slotInfo.start ? new Date(slotInfo.start) : new Date();
|
||||
const baseDate = slotInfo.start ? new Date(slotInfo.start) : new Date();
|
||||
// Round current time to nearest quarter hour
|
||||
let minutes = now.getMinutes();
|
||||
const minutes = now.getMinutes();
|
||||
let roundedMinutes = Math.round(minutes / 15) * 15;
|
||||
let hour = now.getHours();
|
||||
if (roundedMinutes === 60) {
|
||||
@@ -193,7 +193,7 @@ const BookingPage: React.FC = () => {
|
||||
roundedMinutes = 0;
|
||||
}
|
||||
// Construct selectedDay as local time: new Date(year, month, day, hour, minute, 0, 0)
|
||||
let selectedDay = new Date(
|
||||
const selectedDay = new Date(
|
||||
baseDate.getFullYear(),
|
||||
baseDate.getMonth(),
|
||||
baseDate.getDate(),
|
||||
|
||||
@@ -66,7 +66,7 @@ const ConfirmationPage: React.FC = () => {
|
||||
* Subscribe to SSE for live booking status updates.
|
||||
*/
|
||||
React.useEffect(() => {
|
||||
let bookingId = location.state?.booking?.id || booking?.id;
|
||||
const bookingId = location.state?.booking?.id || booking?.id;
|
||||
if (!bookingId) return;
|
||||
// Always get latest booking from context
|
||||
const latestBooking = bookings.find((b: Booking) => b.id === bookingId);
|
||||
|
||||
Reference in New Issue
Block a user