Skip to content

Commit fdefc3c

Browse files
committed
Update to React 19.0.0, fix hook refactoring bugs
1 parent 773a65e commit fdefc3c

File tree

10 files changed

+656
-623
lines changed

10 files changed

+656
-623
lines changed

app/find/page.tsx

+4-6
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@ import { Suspense, useEffect, useState } from 'react';
88
import { useSatellite } from '@/hooks/useSatellite';
99
import { usePermissions } from '@/hooks/usePermissions';
1010
import { useMotion } from '@/hooks/useMotion';
11+
import { useTracking } from '@/hooks/useTracking';
1112

1213
import LocationError from '@/components/manualLocation';
1314
import Error from '@/components/error';
14-
1515
import ManualLocation from '@/components/manualLocation';
1616
import DirectionGuide from '@/components/directionGuide';
1717
import Input from '@/components/ui/input';
1818
import Loader from '@/components/ui/loader';
1919
import PermissionRequest from '@/components/permissionRequest';
2020
import { formatDate } from '@/lib/utils';
21-
import { useTracking } from '@/hooks/useTracking';
2221

2322
function FindSatellite() {
2423
// Query params for satellite ID
@@ -33,8 +32,7 @@ function FindSatellite() {
3332
const { satData, error: satDataError } = useSatellite(satelliteId);
3433
const { permissionGranted, requestPermission, error: permissionError } = usePermissions();
3534

36-
const { motionData, error: locationError, setManualLocation } = useMotion(permissionGranted);
37-
if (locationError) { setShowManualLocation(true); } // if error with location fetch, show page to manually input location
35+
const { motionData, error: locationError, setError: setLocationError, setManualLocation } = useMotion(permissionGranted);
3836

3937
const { trackingStatus, satPosition } = useTracking(motionData, satData);
4038

@@ -48,8 +46,8 @@ function FindSatellite() {
4846
return (
4947
<ManualLocation
5048
error={locationError}
49+
setError={setLocationError}
5150
setManualLocation={setManualLocation}
52-
setShowManualLocation={setShowManualLocation}
5351
/>
5452
);
5553
}
@@ -111,7 +109,7 @@ function FindSatellite() {
111109
</div>
112110

113111
<div className="mt-12 flex items-center justify-center gap-10">
114-
<DirectionGuide satData={satData} />
112+
<DirectionGuide trackingStatus={trackingStatus} />
115113
</div>
116114
</div>
117115
</div>

components/directionGuide.tsx

+7-10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
const DirectionGuide = ({ satData }: { satData: SatelliteData }) => {
1+
import { translateElevation } from "@/lib/utils";
2+
import { TrackingStatus } from "@/types/oritentation";
3+
4+
const DirectionGuide = ({ trackingStatus }: { trackingStatus: TrackingStatus }) => {
25
return (
36
<>
47
<div className="flex items-center justify-center">
58
<div
69
className='absolute w-28 h-28 z-20 transform -translate-x-1/2'
710
style={{
8-
transform: `rotate(${(satData.azimuthDifference - 55).toFixed(1)}deg) translateX(100%)`,
11+
transform: `rotate(${(trackingStatus.azimuthDifference - 55).toFixed(1)}deg) translateX(100%)`,
912
}}
1013
>
1114
<div className='flex items-center'>
@@ -35,9 +38,9 @@ const DirectionGuide = ({ satData }: { satData: SatelliteData }) => {
3538
<div className="border-2 border-dashed border-white/50 w-0 h-44 bg-transparent"></div>
3639
<div className='w-4 rounded-sm bg-gray-400 absolute h-[2px]'></div>
3740
<div
38-
className={`w-7 rounded-sm ${Math.abs(satData.elevationDifference) < 15 ? 'bg-[#00ff73]' : 'bg-red-500'} absolute h-1`}
41+
className={`w-7 rounded-sm ${Math.abs(trackingStatus.elevationDifference) < 15 ? 'bg-[#00ff73]' : 'bg-red-500'} absolute h-1`}
3942
style={{
40-
translate: `0px ${calcEleveationTranslate(satData.elevationDifference).toFixed(0)}px`,
43+
translate: `0px ${translateElevation(trackingStatus.elevationDifference).toFixed(0)}px`,
4144
}}
4245
></div>
4346
</div>
@@ -46,10 +49,4 @@ const DirectionGuide = ({ satData }: { satData: SatelliteData }) => {
4649
);
4750
};
4851

49-
const calcEleveationTranslate = (elevation: number) => {
50-
if (elevation < 0) return (elevation / 1.4);
51-
if (elevation > 0) return (elevation / 1.4);
52-
return 0;
53-
}
54-
5552
export default DirectionGuide;

components/manualLocation.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useState } from "react";
22

3-
export default function ManualLocation({ error, setShowManualLocation, setManualLocation }) {
3+
export default function ManualLocation({ error, setError }) {
44
const [longitude, setLongitude] = useState<string | undefined>();
55
const [latitude, setLatitude] = useState<string | undefined>();
66

@@ -18,7 +18,7 @@ export default function ManualLocation({ error, setShowManualLocation, setManual
1818
className="mt-4 flex w-40 cursor-pointer items-center justify-center rounded-md border-2 border-white/50 bg-[#1fa95d] py-2 font-medium"
1919
onClick={() => {
2020
setManualLocation(parseFloat(latitude || '0'), parseFloat(longitude || '0'));
21-
setShowManualLocation(false);
21+
setError(null);
2222
}}
2323
>
2424
Submit location

hooks/useMotion.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { MotionData } from '@/types/oritentation';
22
import { useState, useEffect } from 'react';
33

4-
export function useMotion(permissionGranted: boolean) {
4+
export function useMotion(motionPermissionGranted: boolean) {
55
const [motionData, setMotionData] = useState<MotionData>({
66
location: { latitude: 0, longitude: 0, altitude: 0 },
77
gyroscope: { alpha: null, beta: null, gamma: null },
@@ -17,8 +17,10 @@ export function useMotion(permissionGranted: boolean) {
1717
};
1818

1919
useEffect(() => {
20-
if (!permissionGranted) return;
20+
// Check if motion permission has been granted before continuing
21+
if (!motionPermissionGranted) return;
2122

23+
// Receive device orientation event and update resulting motion data
2224
const handleDeviceOrientation = (event: DeviceOrientationEvent) => {
2325
const { alpha, beta, gamma, webkitCompassHeading } = event;
2426

@@ -36,6 +38,9 @@ export function useMotion(permissionGranted: boolean) {
3638
}));
3739
};
3840

41+
// Fetch geolocation data with web API
42+
// NOTE: Has built in permission request API
43+
// https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/getCurrentPosition
3944
const fetchLocation = () => {
4045
navigator.geolocation.getCurrentPosition(
4146
(position) => {
@@ -48,17 +53,16 @@ export function useMotion(permissionGranted: boolean) {
4853
(error) => {
4954
setLocationError(error.message);
5055
},
51-
{ timeout: 10000, enableHighAccuracy: true, maximumAge: 0 }
56+
{ timeout: 7000, enableHighAccuracy: true, maximumAge: 0 }
5257
);
5358
};
5459

55-
window.addEventListener('deviceorientation', handleDeviceOrientation);
5660
fetchLocation();
57-
61+
window.addEventListener('deviceorientation', handleDeviceOrientation);
5862
return () => {
5963
window.removeEventListener('deviceorientation', handleDeviceOrientation);
6064
};
61-
}, [permissionGranted]);
65+
}, [motionPermissionGranted]);
6266

63-
return { motionData, error, setMotionData };
67+
return { motionData, error, setError, setManualLocation };
6468
}

hooks/useSatellite.ts

+22-22
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,31 @@ export function useSatellite(satelliteId: string) {
1313
const [error, setError] = useState<string | null>(null);
1414

1515
// Fetch TLE data from the API
16-
const fetchSatelliteData = useCallback(async () => {
17-
if (!satelliteId) return;
18-
19-
try {
20-
const response = await fetch(`/api/satellite/${satelliteId}`);
21-
if (!response.ok) setError('Failed to fetch satellite data.');
22-
23-
const data = await response.json();
24-
const tleLines = data.tle.split('\r\n');
25-
if (tleLines.length !== 2 || !data.info.satname) {
26-
setError('Invalid TLE data.');
16+
useEffect(() => {
17+
const fetchSatelliteData = useCallback(async () => {
18+
if (!satelliteId) return;
19+
20+
try {
21+
const response = await fetch(`/api/satellite/${satelliteId}`);
22+
if (!response.ok) setError('Failed to fetch satellite data.');
23+
24+
const data = await response.json();
25+
const tleLines = data.tle.split('\r\n');
26+
if (tleLines.length !== 2 || !data.info.satname) {
27+
setError('Invalid TLE data.');
28+
}
29+
30+
setSatData({
31+
name: data.info.satname,
32+
tle: { line1: tleLines[0], line2: tleLines[1] }
33+
});
34+
} catch (err: any) {
35+
setError(err.message);
2736
}
37+
}, [satelliteId]);
2838

29-
setSatData({
30-
name: data.info.satname,
31-
tle: { line1: tleLines[0], line2: tleLines[1] }
32-
});
33-
} catch (err: any) {
34-
setError(err.message);
35-
}
36-
}, [satelliteId]);
37-
38-
useEffect(() => {
3939
fetchSatelliteData();
40-
}, [fetchSatelliteData]);
40+
}, []);
4141

4242
return { satData, error };
4343
}

lib/utils.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/**
2+
* Formats a given date into a string with the format 'MM/DD/YY, HH:MM'.
3+
* If the date is null, it returns null.
4+
*
5+
* @param date - The date to format.
6+
* @returns The formatted date string or null if the date is null.
7+
*/
18
export function formatDate(date: Date | null): string | null {
29
if (!date) return null;
310

@@ -10,6 +17,24 @@ export function formatDate(date: Date | null): string | null {
1017
});
1118
}
1219

20+
/**
21+
* Converts an angle from radians to degrees.
22+
*
23+
* @param radians - The angle in radians.
24+
* @returns The angle in degrees.
25+
*/
1326
export const radiansToDegrees = (radians: number) => {
1427
return radians * (180 / Math.PI);
15-
};
28+
};
29+
30+
/**
31+
* Translates an elevation value to a valid pixel value to display on screen in the direction guide component.
32+
*
33+
* @param elevation - The elevation value to translate.
34+
* @returns The translated elevation value (in correct pixel unit range)
35+
*/
36+
export const translateElevation = (elevation: number) => {
37+
if (elevation < 0) return (elevation / 1.4);
38+
if (elevation > 0) return (elevation / 1.4);
39+
return 0;
40+
}

next-env.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
/// <reference types="next/image-types/global" />
33

44
// NOTE: This file should not be edited
5-
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
5+
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"dependencies": {
1313
"@vercel/analytics": "^1.3.1",
1414
"next": "^15.1.0",
15-
"react": "^18",
15+
"react": "^19.0.0",
1616
"react-dom": "^18",
1717
"react-loader-spinner": "^6.1.6",
1818
"react-starfield-animation": "^1.0.1",

tsconfig.json

+19-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
{
22
"compilerOptions": {
3-
"lib": ["dom", "dom.iterable", "esnext"],
3+
"lib": [
4+
"dom",
5+
"dom.iterable",
6+
"esnext"
7+
],
48
"allowJs": true,
59
"skipLibCheck": true,
610
"strict": true,
@@ -18,9 +22,19 @@
1822
}
1923
],
2024
"paths": {
21-
"@/*": ["./*"]
22-
}
25+
"@/*": [
26+
"./*"
27+
]
28+
},
29+
"target": "ES2017"
2330
},
24-
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
25-
"exclude": ["node_modules"]
31+
"include": [
32+
"next-env.d.ts",
33+
"**/*.ts",
34+
"**/*.tsx",
35+
".next/types/**/*.ts"
36+
],
37+
"exclude": [
38+
"node_modules"
39+
]
2640
}

0 commit comments

Comments
 (0)