Skip to content

Commit bcfe3cb

Browse files
Merge pull request #120 from bg-playground/copilot/fix-eslint-peer-dependency-issue
Fix ESLint peer dependency conflict: pin to ~9.38.0
2 parents 09116c3 + 7f37848 commit bcfe3cb

14 files changed

Lines changed: 103 additions & 82 deletions

.github/workflows/frontend-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
cache-dependency-path: frontend/package-lock.json
3737

3838
- name: Install dependencies
39-
run: npm ci --legacy-peer-deps
39+
run: npm ci
4040

4141
- name: Run ESLint
4242
run: npm run lint

frontend/package-lock.json

Lines changed: 25 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
"react-router-dom": "^7.13.0"
1717
},
1818
"devDependencies": {
19-
"@eslint/js": "^9.22.0",
19+
"@eslint/js": "~9.38.0",
2020
"@tailwindcss/postcss": "^4.2.0",
2121
"@types/node": "^25.3.0",
2222
"@types/react": "^19.2.7",
2323
"@types/react-dom": "^19.2.3",
2424
"@vitejs/plugin-react": "^5.1.1",
2525
"autoprefixer": "^10.4.24",
26-
"eslint": "^9.22.0",
26+
"eslint": "~9.38.0",
2727
"eslint-plugin-react-hooks": "^7.0.1",
2828
"eslint-plugin-react-refresh": "^0.5.0",
2929
"globals": "^17.3.0",

frontend/src/components/SuggestionFilters.tsx

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
import React, { useCallback, useEffect, useRef, useState } from 'react';
2-
3-
export const DEFAULT_FILTERS = {
4-
minScore: 0,
5-
maxScore: 1,
6-
algorithm: 'all',
7-
sortBy: 'score',
8-
sortOrder: 'desc',
9-
search: '',
10-
};
11-
12-
export type Filters = typeof DEFAULT_FILTERS;
2+
import { DEFAULT_FILTERS } from '../types/filters';
3+
import type { Filters } from '../types/filters';
134

145
interface SuggestionFiltersProps {
156
filters: Filters;
@@ -19,20 +10,22 @@ interface SuggestionFiltersProps {
1910

2011
export const SuggestionFilters: React.FC<SuggestionFiltersProps> = ({ filters, onFiltersChange, onReset }) => {
2112
const [searchInput, setSearchInput] = useState(filters.search);
13+
const [prevSearch, setPrevSearch] = useState(filters.search);
2214
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
2315

16+
// Sync searchInput when filters.search is reset externally (e.g. Reset button)
17+
if (prevSearch !== filters.search) {
18+
setPrevSearch(filters.search);
19+
setSearchInput(filters.search);
20+
}
21+
2422
// Clear debounce timer on unmount
2523
useEffect(() => {
2624
return () => {
2725
if (debounceRef.current) clearTimeout(debounceRef.current);
2826
};
2927
}, []);
3028

31-
// Sync searchInput when filters.search is reset externally (e.g. Reset button)
32-
useEffect(() => {
33-
setSearchInput(filters.search);
34-
}, [filters.search]);
35-
3629
const handleSearchChange = useCallback(
3730
(value: string) => {
3831
setSearchInput(value);

frontend/src/components/Toast.tsx

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,6 @@
1-
import React, { createContext, useContext, useState, useCallback } from 'react';
2-
3-
interface Toast {
4-
id: string;
5-
message: string;
6-
type: 'success' | 'error' | 'info' | 'warning';
7-
}
8-
9-
interface ToastContextValue {
10-
toasts: Toast[];
11-
showToast: (message: string, type?: Toast['type']) => void;
12-
removeToast: (id: string) => void;
13-
}
14-
15-
const ToastContext = createContext<ToastContextValue | undefined>(undefined);
16-
17-
export const useToast = () => {
18-
const context = useContext(ToastContext);
19-
if (!context) {
20-
throw new Error('useToast must be used within a ToastProvider');
21-
}
22-
return context;
23-
};
1+
import React, { useState, useCallback } from 'react';
2+
import { ToastContext } from '../context/ToastContext';
3+
import type { Toast } from '../context/ToastContext';
244

255
export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
266
const [toasts, setToasts] = useState<Toast[]>([]);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { createContext, useContext } from 'react';
2+
3+
export interface Toast {
4+
id: string;
5+
message: string;
6+
type: 'success' | 'error' | 'info' | 'warning';
7+
}
8+
9+
export interface ToastContextValue {
10+
toasts: Toast[];
11+
showToast: (message: string, type?: Toast['type']) => void;
12+
removeToast: (id: string) => void;
13+
}
14+
15+
export const ToastContext = createContext<ToastContextValue | undefined>(undefined);
16+
17+
export const useToast = () => {
18+
const context = useContext(ToastContext);
19+
if (!context) {
20+
throw new Error('useToast must be used within a ToastProvider');
21+
}
22+
return context;
23+
};

frontend/src/pages/ManualLinksPage.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useCallback, useEffect, useState } from 'react';
22
import { linksApi } from '../api/links';
33
import { requirementsApi } from '../api/requirements';
44
import { testCasesApi } from '../api/testCases';
55
import { LinkSource, LinkType } from '../types/api';
66
import type { Link, LinkCreate, Requirement, TestCase } from '../types/api';
77
import { LoadingSpinner } from '../components/LoadingSpinner';
8-
import { useToast } from '../components/Toast';
8+
import { useToast } from '../context/ToastContext';
99

1010
export const ManualLinksPage: React.FC = () => {
1111
const [links, setLinks] = useState<Link[]>([]);
@@ -21,7 +21,7 @@ export const ManualLinksPage: React.FC = () => {
2121
});
2222
const { showToast } = useToast();
2323

24-
const loadData = async () => {
24+
const loadData = useCallback(async () => {
2525
try {
2626
setLoading(true);
2727
const [linksData, reqData, tcData] = await Promise.all([
@@ -38,11 +38,11 @@ export const ManualLinksPage: React.FC = () => {
3838
} finally {
3939
setLoading(false);
4040
}
41-
};
41+
}, [showToast]);
4242

4343
useEffect(() => {
4444
loadData();
45-
}, []);
45+
}, [loadData]);
4646

4747
const handleSubmit = async (e: React.FormEvent) => {
4848
e.preventDefault();
@@ -52,9 +52,10 @@ export const ManualLinksPage: React.FC = () => {
5252
setShowModal(false);
5353
resetForm();
5454
await loadData();
55-
} catch (error: any) {
55+
} catch (error: unknown) {
5656
console.error('Error creating link:', error);
57-
const message = error.response?.data?.detail || 'Failed to create link';
57+
const axiosError = error as { response?: { data?: { detail?: string } } };
58+
const message = axiosError?.response?.data?.detail ?? 'Failed to create link';
5859
showToast(message, 'error');
5960
}
6061
};

frontend/src/pages/MetricsDashboardPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useEffect, useState } from "react";
22
import traceabilityApi, { type Metrics } from "../api/traceability";
3-
import { useToast } from "../components/Toast";
3+
import { useToast } from "../context/ToastContext";
44
import { LoadingSpinner } from "../components/LoadingSpinner";
55

66
export default function MetricsDashboardPage() {

frontend/src/pages/RequirementsPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { requirementsApi } from '../api/requirements';
33
import { RequirementType, PriorityLevel, RequirementStatus } from '../types/api';
44
import type { Requirement, RequirementCreate, RequirementUpdate } from '../types/api';
55
import { LoadingSpinner } from '../components/LoadingSpinner';
6-
import { useToast } from '../components/Toast';
6+
import { useToast } from '../context/ToastContext';
77

88
export const RequirementsPage: React.FC = () => {
99
const [requirements, setRequirements] = useState<Requirement[]>([]);

frontend/src/pages/SuggestionDashboard.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import { testCasesApi } from '../api/testCases';
66
import { SuggestionStatus } from '../types/api';
77
import type { Suggestion, Requirement, TestCase } from '../types/api';
88
import { LoadingSpinner } from '../components/LoadingSpinner';
9-
import { useToast } from '../components/Toast';
9+
import { useToast } from '../context/ToastContext';
1010
import { KeyboardShortcutsHelp } from '../components/KeyboardShortcutsHelp';
11-
import { SuggestionFilters, DEFAULT_FILTERS } from '../components/SuggestionFilters';
12-
import type { Filters } from '../components/SuggestionFilters';
11+
import { SuggestionFilters } from '../components/SuggestionFilters';
12+
import { DEFAULT_FILTERS } from '../types/filters';
13+
import type { Filters } from '../types/filters';
1314
import { SuggestionStats } from '../components/SuggestionStats';
1415
import { SuggestionCard } from '../components/SuggestionCard';
1516
import { SuggestionPreviewModal } from '../components/SuggestionPreviewModal';

0 commit comments

Comments
 (0)