Skip to content

Commit cfae249

Browse files
authored
Merge pull request #834 from Sim-sat/no-explicit-any-hooks
fix(lint): no-explicit-any for components, hooks, lib
2 parents 564eb42 + f49ec8f commit cfae249

10 files changed

Lines changed: 69 additions & 60 deletions

File tree

SparkyFitnessFrontend/src/components/ExerciseActivityDetailsEditor.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ export interface ActivityDetailKeyValuePair {
1111
id?: string; // Optional for new entries, will be generated by backend
1212
key: string; // Maps to detail_type in backend
1313
value: string; // Stored within detail_data as JSONB in backend
14-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
15-
detail_data?: any; // Add detail_data to the interface
14+
detail_data?: unknown;
1615
provider_name?: string; // Optional, will default to 'Manual' in backend
1716
detail_type?: string; // Optional, will default to 'Custom Field' in backend
1817
}

SparkyFitnessFrontend/src/components/FoodSearch/BarcodeScanner.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ interface BarcodeScannerProps {
3131
cameraFacing: 'front' | 'back';
3232
}
3333

34+
interface AdvancedMediaTrackConstraints extends MediaTrackConstraintSet {
35+
torch?: boolean;
36+
}
3437
const ENGINE_OPTIONS = [
3538
{ value: 'zxing', label: '@zxing/library' },
3639
{ value: 'html5-qrcode', label: 'html5-qrcode' },
@@ -152,8 +155,7 @@ const BarcodeScanner: React.FC<BarcodeScannerProps> = ({
152155
if (!currentTrack.current || !torchSupported || !torchEnabled) return;
153156
try {
154157
await currentTrack.current.applyConstraints({
155-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
156-
advanced: [{ torch: false } as any],
158+
advanced: [{ torch: false } as AdvancedMediaTrackConstraints],
157159
});
158160
setTorchEnabled(false);
159161
} catch (error) {
@@ -165,8 +167,7 @@ const BarcodeScanner: React.FC<BarcodeScannerProps> = ({
165167
if (!currentTrack.current || !torchSupported) return;
166168
try {
167169
await currentTrack.current.applyConstraints({
168-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
169-
advanced: [{ torch: !torchEnabled } as any],
170+
advanced: [{ torch: !torchEnabled } as AdvancedMediaTrackConstraints],
170171
});
171172
setTorchEnabled(!torchEnabled);
172173
} catch (error) {
@@ -193,8 +194,7 @@ const BarcodeScanner: React.FC<BarcodeScannerProps> = ({
193194
width: { ideal: 1280 }, // Lowering ideal might help mobile performance/compatibility
194195
frameRate: { ideal: 30 },
195196
focusMode: { ideal: 'continuous' },
196-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
197-
} as any, // Cast to allow custom properties
197+
},
198198
};
199199

200200
const start = async () => {

SparkyFitnessFrontend/src/components/FoodSearch/CustomFoodForm.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,7 @@ const sanitizeGlycemicIndexFrontend = (
134134
};
135135

136136
interface EnhancedCustomFoodFormProps {
137-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
138-
onSave: (foodData: any) => void;
137+
onSave: (foodData: Food) => void;
139138
food?: Food;
140139
initialVariants?: FoodVariant[]; // New prop for pre-populating variants
141140
visibleNutrients?: string[];

SparkyFitnessFrontend/src/components/OidcCallback.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ import { authClient } from '../lib/auth-client';
55
import { useAuth } from '../hooks/useAuth';
66
import { getErrorMessage } from '@/utils/api';
77

8+
interface ExtendedAuthUser {
9+
id: string;
10+
email: string;
11+
name: string;
12+
role?: string;
13+
}
14+
815
const OidcCallback: React.FC = () => {
916
const [error, setError] = useState<string | null>(null);
1017
const navigate = useNavigate();
@@ -31,16 +38,16 @@ const OidcCallback: React.FC = () => {
3138
}
3239

3340
if (session?.user) {
41+
const user = session.user as unknown as ExtendedAuthUser;
3442
// Synchronize local AuthContext with Better Auth session
3543
signIn(
36-
session.user.id,
37-
session.user.id, // Better Auth user is always the active user initially
38-
session.user.email,
39-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
40-
(session.user as any).role || 'user',
44+
user.id,
45+
user.id,
46+
user.email,
47+
user.role || 'user',
4148
'oidc',
42-
false, // Don't navigate automatically, we do it below
43-
session.user.name
49+
false,
50+
user.name
4451
);
4552
navigate('/');
4653
} else {

SparkyFitnessFrontend/src/components/Onboarding/OnBoardingSteps.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ export const OnboardingSteps = ({
4646
}: OnboardingStepsProps) => {
4747
const { t } = useTranslation();
4848

49-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
50-
const handleSelect = (field: keyof FormData, value: any) => {
49+
const handleSelect = (
50+
field: keyof FormData,
51+
value: string | boolean | number
52+
) => {
5153
setFormData((prev) => ({ ...prev, [field]: value }));
5254
setTimeout(() => nextStep(), 250);
5355
};

SparkyFitnessFrontend/src/hooks/Settings/useApiKeys.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,21 @@ export const useToggleApiKeyMutation = () => {
115115
});
116116
};
117117

118+
interface ApiKeyPlugin {
119+
deleteAllExpiredApiKeys: (
120+
options: Record<string, unknown>
121+
) => Promise<{ error: unknown }>;
122+
}
123+
118124
export const useCleanupApiKeysMutation = () => {
119125
const queryClient = useQueryClient();
120126
const { t } = useTranslation();
121127

122128
return useMutation({
123129
mutationFn: async () => {
124-
const { error } =
125-
await // eslint-disable-next-line @typescript-eslint/no-explicit-any
126-
(authClient.apiKey as any).deleteAllExpiredApiKeys({});
130+
const { error } = await (
131+
authClient.apiKey as unknown as ApiKeyPlugin
132+
).deleteAllExpiredApiKeys({});
127133
if (error) throw error;
128134
},
129135
onSuccess: () => {

SparkyFitnessFrontend/src/hooks/useAuth.tsx

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { useNavigate } from 'react-router-dom';
1111
import { authClient } from '../lib/auth-client';
1212
import { fetchIdentityUser, switchUserContext } from '@/api/Auth/auth';
1313

14-
interface User {
14+
export interface User {
1515
id: string;
1616
activeUserId: string;
1717
email: string;
@@ -21,6 +21,16 @@ interface User {
2121
mfaEmailEnabled: boolean;
2222
}
2323

24+
interface ExtendedSessionUser {
25+
id: string;
26+
email: string;
27+
name: string | null;
28+
activeUserId?: string;
29+
role?: string;
30+
twoFactorEnabled?: boolean;
31+
mfaEmailEnabled?: boolean;
32+
}
33+
2434
interface AuthContextType {
2535
user: User | null;
2636
loading: boolean;
@@ -47,8 +57,7 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({
4757
const [user, setUser] = useState<User | null>(null);
4858
const [isSyncing, setIsSyncing] = useState(true); // Track initial hydration
4959
const navigate = useNavigate();
50-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
51-
const prevSessionRef = React.useRef<any>(null);
60+
const prevSessionRef = React.useRef<typeof session>(null);
5261

5362
// Only show global loading during initial hydration (isSyncing).
5463
// Ignoring sessionLoading avoids unmounting components (like Auth/MFA) during background re-fetches.
@@ -60,34 +69,21 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({
6069
useEffect(() => {
6170
// Log when session changes to identify refresh triggers
6271
if (session !== prevSessionRef.current) {
63-
const prevUser = prevSessionRef.current?.user?.id;
64-
const newUser = session?.user?.id;
65-
const isSameUser = prevUser === newUser;
66-
67-
// console.log('[Auth Hook] Session update detected:', {
68-
// timestamp: new Date().toLocaleTimeString(),
69-
// isSameUser,
70-
// prevUserId: prevUser,
71-
// newUserId: newUser,
72-
// trigger: isSameUser ? 'POTENTIAL UNWANTED REFRESH' : 'USER CHANGED',
73-
// });
74-
7572
prevSessionRef.current = session;
7673
}
7774

7875
// Only process if session has actual user data AND it's different from what we have
7976
if (session?.user && (!user || user.id !== session.user.id)) {
80-
const sessionUser = {
81-
id: session.user.id,
82-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
83-
activeUserId: (session.user as any).activeUserId || session.user.id,
84-
email: session.user.email,
85-
fullName: session.user.name || null,
86-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
87-
role: (session.user as any).role || 'user',
88-
twoFactorEnabled: !!session.user.twoFactorEnabled,
89-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
90-
mfaEmailEnabled: !!(session.user as any).mfaEmailEnabled,
77+
const extUser = session.user as unknown as ExtendedSessionUser;
78+
79+
const sessionUser: User = {
80+
id: extUser.id,
81+
activeUserId: extUser.activeUserId || extUser.id,
82+
email: extUser.email,
83+
fullName: extUser.name || null,
84+
role: extUser.role || 'user',
85+
twoFactorEnabled: !!extUser.twoFactorEnabled,
86+
mfaEmailEnabled: !!extUser.mfaEmailEnabled,
9187
};
9288

9389
//console.log('[Auth Hook] Setting user state from session:', sessionUser.id);
@@ -96,8 +92,7 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({
9692
// Fetch Authoritative Data (Active Context)
9793
// This runs on every session update to ensure we are strictly in sync with the backend.
9894
fetchIdentityUser()
99-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
100-
.then((realUserData: any) => {
95+
.then((realUserData) => {
10196
setUser((prev) => {
10297
if (!prev) return prev;
10398
if (
@@ -127,7 +122,6 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({
127122
setIsSyncing(false);
128123
} else if (session?.user && user && user.id === session.user.id) {
129124
// Same user - just update 2FA status if changed
130-
// console.log('[Auth Hook] Session re-poll detected, skipping unnecessary update for same user');
131125
setIsSyncing(false);
132126
}
133127
}, [session, user]);

SparkyFitnessFrontend/src/lib/scannerEngines/QuaggaEngine.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
import Quagga from '@ericblade/quagga2';
1+
import Quagga, { InputStreamType } from '@ericblade/quagga2';
22
import type { BarcodeScannerEngine } from './EngineInterface';
33

4+
interface QuaggaInputStreamConfig {
5+
type: InputStreamType;
6+
target: HTMLElement;
7+
constraints?: MediaTrackConstraints;
8+
}
9+
410
export class QuaggaEngine implements BarcodeScannerEngine {
511
private containerElement: HTMLElement | null = null;
612
private callback: ((code: string) => void) | null = null;
@@ -18,8 +24,7 @@ export class QuaggaEngine implements BarcodeScannerEngine {
1824

1925
this.isScanning = true;
2026

21-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
22-
const liveStreamConfig: any = {
27+
const liveStreamConfig: QuaggaInputStreamConfig = {
2328
type: 'LiveStream',
2429
target: this.containerElement!,
2530
};

SparkyFitnessFrontend/src/lib/scannerEngines/ZxingEngine.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ export class ZxingEngine implements BarcodeScannerEngine {
5050
this.codeReader.decodeFromVideoDevice(
5151
this.currentDeviceId,
5252
this.videoElement,
53-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
54-
(result: Result | null, err: any) => {
53+
(result: Result | null, err: unknown) => {
5554
if (result) {
5655
const text = result.getText();
5756
if (this.callback) this.callback(text);

SparkyFitnessFrontend/src/main.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,8 @@ declare module '@tanstack/react-query' {
2929
}
3030
// helper function to allow variables in toast messages
3131
const resolveMessage = (
32-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
33-
message: string | ((...args: any[]) => string) | undefined,
34-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
35-
...args: any[]
32+
message: string | ((...args: unknown[]) => string) | undefined,
33+
...args: unknown[]
3634
): string | undefined => {
3735
if (typeof message === 'function') {
3836
return message(...args);

0 commit comments

Comments
 (0)