feat: add Satellite of the Day spotlight card - #148
Conversation
🤖 CodeAnt AI — Review Status
|
📝 WalkthroughWalkthroughThe dashboard gains a “Satellite of the Day” card with curated metadata, live orbital details, daily selection, and globe navigation. EarthTwin exposes an imperative satellite-focus API that updates the camera and SpotlightManager selection. ChangesSatellite of the Day spotlight
Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Warning |
| const flyToSatellite = useCallback((catalogNumber: string) => { | ||
| const viewer = viewerRef.current; | ||
| const obj = catalogMapRef.current.get(catalogNumber); | ||
| if (!viewer || viewer.isDestroyed() || !obj) return; |
There was a problem hiding this comment.
Suggestion: When the card is clicked before Cesium finishes loading its catalog, this early return discards the request entirely. Since focusRequest is only set after this check and the later catalog refresh does not replay it, the same valid click silently does nothing and cannot select the satellite once the data becomes available. Record the request before checking readiness, then consume it when the viewer and catalog are ready. [race condition]
Severity Level: Major ⚠️
- ❌ Initial VIEW ON GLOBE clicks silently do nothing.
- ⚠️ Dashboard spotlight navigation requires another click.
- ⚠️ Users receive no readiness feedback or retry.Steps of Reproduction ✅
1. Open the Dashboard, which renders the Satellite of the Day card at
frontend/src/pages/Dashboard.tsx:121-128 alongside the EarthTwin component.
2. Before Cesium initialization and catalog loading finish, click VIEW ON GLOBE; the card
invokes earthTwinRef.current?.flyToSatellite() at frontend/src/pages/Dashboard.tsx:128.
3. EarthTwin.flyToSatellite() at frontend/src/components/EarthTwin.tsx:351-354 sees either
a null viewer or an empty catalogMapRef because initialization occurs asynchronously at
lines 267-321, then returns without calling setFocusRequest().
4. Catalog loading later completes in populateEntities() at
frontend/src/components/EarthTwin.tsx:153-246, but no focus request was recorded, so
SpotlightManager never selects the requested satellite and the original click has no
effect.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/components/EarthTwin.tsx
**Line:** 351:354
**Comment:**
*Race Condition: When the card is clicked before Cesium finishes loading its catalog, this early return discards the request entirely. Since `focusRequest` is only set after this check and the later catalog refresh does not replay it, the same valid click silently does nothing and cannot select the satellite once the data becomes available. Record the request before checking readiness, then consume it when the viewer and catalog are ready.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| const pos = keplerToLatLonAlt(obj); | ||
| if (pos) { | ||
| const destination = Cesium.Cartesian3.fromDegrees(pos.lon, pos.lat, pos.alt * 1000 + 2000000); | ||
| viewer.camera.flyTo({ destination, duration: prefersReducedMotion() ? 0 : 1.5 }); | ||
| } |
There was a problem hiding this comment.
Suggestion: SpotlightCard enables this action when only semimajor axis, inclination, and period are present, but keplerToLatLonAlt also requires RAAN, argument of perigee, mean anomaly, and mean motion. For a catalog object missing any of those fields, the button opens the selection panel but does not move the camera, contradicting the View on Globe contract. The action should either use the same validity criteria as the card or provide a fallback camera position. [api mismatch]
Severity Level: Major ⚠️
- ❌ VIEW ON GLOBE fails to reposition for incomplete orbits.
- ⚠️ Spotlight selection opens at the current camera location.
- ⚠️ Card validation disagrees with globe positioning requirements.Steps of Reproduction ✅
1. On Dashboard, select a curated satellite whose live catalog response contains
semimajor_axis, inclination, and period but a null RAAN, argument of perigee, mean
anomaly, or mean motion; these fields are nullable in
frontend/src/types/satellite.ts:7-14.
2. SpotlightCard enables VIEW ON GLOBE because summarizeOrbit() only validates
semimajor_axis, inclination, and period at
frontend/src/components/SatelliteOfTheDay/SpotlightCard.tsx:19-33, and canViewOnGlobe is
based on that result at line 71.
3. Click VIEW ON GLOBE; Dashboard.tsx:128 invokes EarthTwin.flyToSatellite(), which
retrieves the object and calls keplerToLatLonAlt() at
frontend/src/components/EarthTwin.tsx:351-356.
4. keplerToLatLonAlt() returns null at frontend/src/components/EarthTwin.tsx:52-56 because
one required orbital element is missing, so the camera.flyTo() call at lines 357-360 is
skipped even though the button was enabled; setFocusRequest() still runs at line 364 and
opens selection without moving the camera.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/components/EarthTwin.tsx
**Line:** 356:360
**Comment:**
*Api Mismatch: `SpotlightCard` enables this action when only semimajor axis, inclination, and period are present, but `keplerToLatLonAlt` also requires RAAN, argument of perigee, mean anomaly, and mean motion. For a catalog object missing any of those fields, the button opens the selection panel but does not move the camera, contradicting the View on Globe contract. The action should either use the same validity criteria as the card or provide a fallback camera position.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| const obj = catalogMapRef.current?.get(focusRequest.catalogNumber) ?? null; | ||
| if (obj) selectSatellite(obj); |
There was a problem hiding this comment.
Suggestion: The external request selects any object found in catalogMapRef, but that map contains objects for which populateEntities may have skipped entity creation when keplerToLatLonAlt returned null. This can therefore display an info card and set selectedId for an object with no Cesium entity, while useSpotlightEffect cannot highlight or dim it. Verify the object exists in entitiesRef before selecting it, or defer the request until the entity map has been populated. [stale reference]
Severity Level: Major ⚠️
- ⚠️ Info card opens for an unrendered satellite.
- ⚠️ Selected globe point cannot be highlighted.
- ⚠️ Spotlight visualization becomes inconsistent with selection.Steps of Reproduction ✅
1. Load the Dashboard and allow EarthTwin.populateEntities() to receive a catalog response
at frontend/src/components/EarthTwin.tsx:157-160.
2. For an object missing required positioning fields, populateEntities() skips entity
creation at frontend/src/components/EarthTwin.tsx:178-180 when keplerToLatLonAlt() returns
null.
3. The same object is nevertheless inserted into catalogMapRef at
frontend/src/components/EarthTwin.tsx:243-245, so catalogMapRef contains the object while
entitiesRef does not.
4. Trigger a focus request for that catalog number and observe SpotlightManager.tsx:80-85
selecting the catalog object without checking entitiesRef; useSpotlightEffect.ts:109-118
then finds no active entity to highlight, while SpotlightManager still renders
SpotlightInfoCard from lines 148-150 and reports the object as selected.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/components/SatelliteSpotlight/SpotlightManager.tsx
**Line:** 82:83
**Comment:**
*Stale Reference: The external request selects any object found in `catalogMapRef`, but that map contains objects for which `populateEntities` may have skipped entity creation when `keplerToLatLonAlt` returned null. This can therefore display an info card and set `selectedId` for an object with no Cesium entity, while `useSpotlightEffect` cannot highlight or dim it. Verify the object exists in `entitiesRef` before selecting it, or defer the request until the entity map has been populated.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| const dailyIndex = useMemo(() => { | ||
| if (SPOTLIGHT_SATELLITES.length === 0) return 0; | ||
| return hashString(todayKey()) % SPOTLIGHT_SATELLITES.length; | ||
| }, []); |
There was a problem hiding this comment.
Suggestion: The empty dependency list evaluates todayKey() only on the initial mount. A Dashboard that remains open across local midnight retains the previous day's index indefinitely, so the documented daily rotation does not occur until the component is remounted. Track the date key in state/effect or otherwise invalidate the memo at the next local midnight. [logic error]
Severity Level: Major ⚠️
- ⚠️ Long-lived Dashboard tabs show yesterday's satellite.
- ⚠️ Daily spotlight rotation fails at local midnight.
- ⚠️ Users must remount the page to receive today's pick.Steps of Reproduction ✅
1. Open the Dashboard, which mounts SpotlightCard at
frontend/src/pages/Dashboard.tsx:126-128; SpotlightCard calls useSatelliteOfTheDay() at
frontend/src/components/SatelliteOfTheDay/SpotlightCard.tsx:60-61.
2. At the initial mount, useSatelliteOfTheDay() computes dailyIndex once by calling
todayKey() inside the useMemo at frontend/src/hooks/useSatelliteOfTheDay.ts:31-34.
3. Keep the Dashboard tab open across local midnight; the component remains mounted and
the empty dependency list prevents the memo callback from running again.
4. After midnight, the hook continues returning activeIndex based on the previous day's
dailyIndex at frontend/src/hooks/useSatelliteOfTheDay.ts:53, so the documented daily
rotation does not occur until the Dashboard remounts.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/hooks/useSatelliteOfTheDay.ts
**Line:** 31:34
**Comment:**
*Logic Error: The empty dependency list evaluates `todayKey()` only on the initial mount. A Dashboard that remains open across local midnight retains the previous day's index indefinitely, so the documented daily rotation does not occur until the component is remounted. Track the date key in state/effect or otherwise invalidate the memo at the next local midnight.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| let orbitType: OrbitSummary['orbitType'] = 'LEO'; | ||
| if (altitudeKm > 2000 && altitudeKm < 35000) orbitType = 'MEO'; | ||
| else if (altitudeKm >= 35000 && altitudeKm <= 36500) orbitType = 'GEO'; | ||
| else if (altitudeKm > 36500) orbitType = 'HEO'; |
There was a problem hiding this comment.
Suggestion: Orbit type cannot be determined from altitude alone: every object with altitude above 36,500 km is labeled HEO, while high-altitude circular orbits and elliptical HEO orbits with a lower semimajor axis are classified incorrectly. Use eccentricity and perigee/apogee (or the application's established classification rule) before presenting this as the live orbit regime. [incorrect condition logic]
Severity Level: Major ⚠️
- ⚠️ Satellite spotlight can display incorrect orbit classifications.
- ⚠️ Live orbital metadata becomes misleading for high-altitude objects.Steps of Reproduction ✅
1. On the dashboard, `SpotlightCard` fetches live orbital data through
`api.getCatalogObjectByNorad()` at `SpotlightCard.tsx:63-66`; the `SpaceObject` model
includes eccentricity at `services/api.ts:216-233`.
2. When the API returns an object with semimajor-axis altitude above 36,500 km,
`summarizeOrbit()` at `SpotlightCard.tsx:19-26` assigns `HEO` without examining
eccentricity, perigee, or apogee.
3. A high-altitude circular object is therefore labeled `HEO`, while an eccentric high
Earth orbit whose semimajor-axis altitude is below 36,500 km falls into `MEO` or `GEO`
instead.
4. The resulting label is rendered directly as the user-facing orbit value at
`SpotlightCard.tsx:128-132`, so the spotlight can present an incorrect orbit regime
despite using current live catalog data.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/components/SatelliteOfTheDay/SpotlightCard.tsx
**Line:** 26:26
**Comment:**
*Incorrect Condition Logic: Orbit type cannot be determined from altitude alone: every object with altitude above 36,500 km is labeled `HEO`, while high-altitude circular orbits and elliptical HEO orbits with a lower semimajor axis are classified incorrectly. Use eccentricity and perigee/apogee (or the application's established classification rule) before presenting this as the live orbit regime.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| const liveObject = liveQuery.data?.data; | ||
| const orbit = liveObject ? summarizeOrbit(liveObject) : null; | ||
| const canViewOnGlobe = liveQuery.isSuccess && orbit !== null; |
There was a problem hiding this comment.
Suggestion: The button is enabled solely from the per-object lookup, but EarthTwin builds catalogMapRef from only the first 500 catalog entries and flyToSatellite returns without action when the requested object is absent. Consequently, a successful spotlight lookup can expose an enabled “View on Globe” button that neither flies the camera nor opens the info panel. Ensure the globe can resolve the object directly or disable/report the action when it is not present in the globe dataset. [api mismatch]
Severity Level: Critical 🚨
- ❌ View-on-globe action silently does nothing for unloaded catalog objects.
- ⚠️ Spotlight navigation depends on an unrelated first-page limit.Steps of Reproduction ✅
1. Open the dashboard, where `Dashboard.tsx:128` connects the card's `onViewOnGlobe`
callback to `earthTwinRef.current?.flyToSatellite(catalogNumber)`.
2. Let `SpotlightCard` query the selected NORAD ID through `api.getCatalogObjectByNorad()`
at `SpotlightCard.tsx:63-66`; a successful response with valid orbital fields makes
`canViewOnGlobe` true at `SpotlightCard.tsx:69-71`.
3. The globe loads only `size=500&page=1` at `EarthTwin.tsx:98-101`, then builds
`catalogMapRef` from those returned objects at `EarthTwin.tsx:144-145`. Select a valid
spotlight object that is outside this first page while its direct lookup still succeeds.
4. Click `VIEW ON GLOBE` at `SpotlightCard.tsx:164-167`. `EarthTwin.flyToSatellite()`
looks up the object at `EarthTwin.tsx:252-255` and returns when it is absent, so no camera
flight occurs and no focus request reaches `SpotlightManager`; its external selection
effect at `SpotlightManager.tsx:80-85` consequently cannot open the info panel.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/components/SatelliteOfTheDay/SpotlightCard.tsx
**Line:** 69:71
**Comment:**
*Api Mismatch: The button is enabled solely from the per-object lookup, but `EarthTwin` builds `catalogMapRef` from only the first 500 catalog entries and `flyToSatellite` returns without action when the requested object is absent. Consequently, a successful spotlight lookup can expose an enabled “View on Globe” button that neither flies the camera nor opens the info panel. Ensure the globe can resolve the object directly or disable/report the action when it is not present in the globe dataset.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| const flyToSatellite = useCallback((catalogNumber: string) => { | ||
| const viewer = viewerRef.current; | ||
| const obj = catalogMapRef.current.get(catalogNumber); | ||
| if (!viewer || viewer.isDestroyed() || !obj) return; |
There was a problem hiding this comment.
Catalog scope breaks globe navigation
When the direct NORAD lookup succeeds for an object outside EarthTwin's first 500 catalog entries, the button is enabled but flyToSatellite silently returns because the object is absent from catalogMapRef, causing no camera movement, selection, panel, or error feedback.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/components/EarthTwin.tsx
Line: 354
Comment:
**Catalog scope breaks globe navigation**
When the direct NORAD lookup succeeds for an object outside EarthTwin's first 500 catalog entries, the button is enabled but `flyToSatellite` silently returns because the object is absent from `catalogMapRef`, causing no camera movement, selection, panel, or error feedback.
How can I resolve this? If you propose a fix, please make it concise.| const dailyIndex = useMemo(() => { | ||
| if (SPOTLIGHT_SATELLITES.length === 0) return 0; | ||
| return hashString(todayKey()) % SPOTLIGHT_SATELLITES.length; | ||
| }, []); |
There was a problem hiding this comment.
Daily selection freezes at mount
When Dashboard remains mounted across local midnight, the empty dependency array prevents todayKey() from being evaluated again, causing the previous day's satellite to remain selected until Dashboard remounts; resetting to Today's Pick also restores that stale index.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/hooks/useSatelliteOfTheDay.ts
Line: 31-34
Comment:
**Daily selection freezes at mount**
When Dashboard remains mounted across local midnight, the empty dependency array prevents `todayKey()` from being evaluated again, causing the previous day's satellite to remain selected until Dashboard remounts; resetting to Today's Pick also restores that stale index.
How can I resolve this? If you propose a fix, please make it concise.|
|
||
| {/* Satellite of the Day */} | ||
| <section className="px-3 md:px-6 pt-3 md:pt-6"> | ||
| <SpotlightCard onViewOnGlobe={(catalogNumber) => earthTwinRef.current?.flyToSatellite(catalogNumber)} /> |
There was a problem hiding this comment.
Globe navigation remains off-screen
When the card is visible after the preceding globe section has scrolled outside MainLayout's overflow viewport, this callback changes only Cesium camera and selection state without revealing the globe, causing the user to see no response to View on Globe.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/pages/Dashboard.tsx
Line: 128
Comment:
**Globe navigation remains off-screen**
When the card is visible after the preceding globe section has scrolled outside MainLayout's overflow viewport, this callback changes only Cesium camera and selection state without revealing the globe, causing the user to see no response to View on Globe.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/components/EarthTwin.tsx`:
- Around line 351-365: Update flyToSatellite to persist the requested catalog
number when the viewer or catalog entry is unavailable, rather than returning
permanently. After populateEntities makes the viewer and catalog entry
available, consume the pending request and perform the camera flight and
setFocusRequest; preserve the existing reduced-motion behavior and avoid losing
clicks made before catalog readiness.
In `@frontend/src/components/SatelliteOfTheDay/SpotlightCard.tsx`:
- Around line 147-151: Update the fallback rendering in SpotlightCard so
liveQuery.isError displays an error-specific message with a retry action, rather
than the catalog re-entry warning. Only show the existing “may have re-entered”
message when the query completed successfully without orbital data, and keep the
loading state excluded.
In `@frontend/src/constants/spotlightSatellites.ts`:
- Around line 87-96: Update the NOAA-19 entry in the satellite catalog to use
status "Retired" and revise its mission_summary and facts text to describe its
forecasting contribution in historical, past-tense wording rather than implying
current operation.
In `@frontend/src/hooks/useSatelliteOfTheDay.ts`:
- Around line 31-36: Update the selection state around dailyIndex and
manualIndex so the date key is stored in state and refreshed at the next
midnight, rather than relying on useMemo with empty dependencies. Recompute
dailyIndex when that date key changes, and clear manualIndex in the same
date-change flow so previews do not persist across midnight.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 52e1b838-e340-432c-b597-7f4116479f52
📒 Files selected for processing (6)
frontend/src/components/EarthTwin.tsxfrontend/src/components/SatelliteOfTheDay/SpotlightCard.tsxfrontend/src/components/SatelliteSpotlight/SpotlightManager.tsxfrontend/src/constants/spotlightSatellites.tsfrontend/src/hooks/useSatelliteOfTheDay.tsfrontend/src/pages/Dashboard.tsx
| const flyToSatellite = useCallback((catalogNumber: string) => { | ||
| const viewer = viewerRef.current; | ||
| const obj = catalogMapRef.current.get(catalogNumber); | ||
| if (!viewer || viewer.isDestroyed() || !obj) return; | ||
|
|
||
| const pos = keplerToLatLonAlt(obj); | ||
| if (pos) { | ||
| const destination = Cesium.Cartesian3.fromDegrees(pos.lon, pos.lat, pos.alt * 1000 + 2000000); | ||
| viewer.camera.flyTo({ destination, duration: prefersReducedMotion() ? 0 : 1.5 }); | ||
| } | ||
|
|
||
| // SpotlightManager owns actual selection state; this just tells it | ||
| // which satellite to lock onto and open the info panel for. | ||
| setFocusRequest({ catalogNumber, nonce: Date.now() }); | ||
| }, []); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Queue focus requests until the globe catalog is ready.
flyToSatellite returns before setFocusRequest when catalogMapRef has not populated. Since populateEntities() is asynchronous, the card can enable first and the user’s click becomes a permanent no-op. Persist a pending catalog number, then perform the camera flight and set focusRequest after the viewer and catalog entry are available.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/EarthTwin.tsx` around lines 351 - 365, Update
flyToSatellite to persist the requested catalog number when the viewer or
catalog entry is unavailable, rather than returning permanently. After
populateEntities makes the viewer and catalog entry available, consume the
pending request and perform the camera flight and setFocusRequest; preserve the
existing reduced-motion behavior and avoid losing clicks made before catalog
readiness.
| {!canViewOnGlobe && !liveQuery.isLoading && ( | ||
| <p className="text-[10px] text-status-warning mt-2"> | ||
| Live orbital data isn't currently available for this object, it may have re-entered or dropped out of the tracked catalog. | ||
| </p> | ||
| )} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Do not report API failures as a re-entry.
This branch treats liveQuery.isError exactly like a successful lookup with missing orbital data. A backend outage therefore tells users the object “may have re-entered.” Render an error-specific message and retry action for isError; reserve this catalog-missing fallback for successful incomplete responses.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/SatelliteOfTheDay/SpotlightCard.tsx` around lines 147
- 151, Update the fallback rendering in SpotlightCard so liveQuery.isError
displays an error-specific message with a retry action, rather than the catalog
re-entry warning. Only show the existing “may have re-entered” message when the
query completed successfully without orbital data, and keep the loading state
excluded.
| catalog_number: '33591', | ||
| name: 'NOAA-19', | ||
| operator: 'NOAA', | ||
| launch_date: '2009-02-06', | ||
| status: 'Active', | ||
| mission_summary: | ||
| 'The final satellite in the POES series, providing global weather imagery and atmospheric soundings for forecasting.', | ||
| facts: [ | ||
| 'Data from NOAA polar orbiters feeds directly into daily weather forecasts and hurricane tracking.', | ||
| ], |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Mark NOAA-19 as retired.
NOAA-19 was decommissioned on August 13, 2025; showing ACTIVE and present-tense operational forecasting claims is incorrect. Use Retired and adjust the summary/fact to historical wording. (ospo.noaa.gov)
Proposed fix
- status: 'Active',
+ status: 'Retired',
mission_summary:
- 'The final satellite in the POES series, providing global weather imagery and atmospheric soundings for forecasting.',
+ 'The final satellite in the POES series, which provided global weather imagery and atmospheric soundings for forecasting.',📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| catalog_number: '33591', | |
| name: 'NOAA-19', | |
| operator: 'NOAA', | |
| launch_date: '2009-02-06', | |
| status: 'Active', | |
| mission_summary: | |
| 'The final satellite in the POES series, providing global weather imagery and atmospheric soundings for forecasting.', | |
| facts: [ | |
| 'Data from NOAA polar orbiters feeds directly into daily weather forecasts and hurricane tracking.', | |
| ], | |
| catalog_number: '33591', | |
| name: 'NOAA-19', | |
| operator: 'NOAA', | |
| launch_date: '2009-02-06', | |
| status: 'Retired', | |
| mission_summary: | |
| 'The final satellite in the POES series, which provided global weather imagery and atmospheric soundings for forecasting.', | |
| facts: [ | |
| 'Data from NOAA polar orbiters feeds directly into daily weather forecasts and hurricane tracking.', | |
| ], |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/constants/spotlightSatellites.ts` around lines 87 - 96, Update
the NOAA-19 entry in the satellite catalog to use status "Retired" and revise
its mission_summary and facts text to describe its forecasting contribution in
historical, past-tense wording rather than implying current operation.
| const dailyIndex = useMemo(() => { | ||
| if (SPOTLIGHT_SATELLITES.length === 0) return 0; | ||
| return hashString(todayKey()) % SPOTLIGHT_SATELLITES.length; | ||
| }, []); | ||
|
|
||
| const [manualIndex, setManualIndex] = useState<number | null>(null); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Refresh the selection at the day boundary.
useMemo(..., []) freezes dailyIndex for the component lifetime, and a manual preview also survives midnight. Keep a date key in state, schedule its update for the next midnight, and clear manualIndex when it changes so the 24-hour rotation actually refreshes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/hooks/useSatelliteOfTheDay.ts` around lines 31 - 36, Update the
selection state around dailyIndex and manualIndex so the date key is stored in
state and refreshed at the next midnight, rather than relying on useMemo with
empty dependencies. Recompute dailyIndex when that date key changes, and clear
manualIndex in the same date-change flow so previews do not persist across
midnight.
User description
Summary
Adds a "Satellite of the Day" section to the dashboard, as requested in #143.
api.getCatalogObjectByNorad, not hardcoded.EarthTwinwith aforwardRef/imperative handle (flyToSatellite), and adding an externalfocusRequestprop toSpotlightManagerso it can lock selection from outside a globe click.Related Issue
Closes #143
Type of Change
Screenshots / Screen Recordings
(attach your 3 images here)
Note: screenshots show the fallback state since I tested without the backend running locally. Orbit stats query
/catalog/objects/{norad}live and populate normally once the backend is up. The fallback is the correctly working "no data" path, not a missing feature.Testing Performed
Breaking Changes
None. All changes are additive: new files, an optional new prop on
SpotlightManager, and aref-based imperative method onEarthTwinthat doesn't alter existing behavior.Checklist
ECSoC26 Submission
ECSoC26-L1– BeginnerCodeAnt-AI Description
Add a daily Satellite of the Day spotlight to the dashboard
What Changed
Impact
✅ Daily satellite discovery✅ Live orbital details✅ Direct navigation from dashboard to globe✅ Clear unavailable-data messaging💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.
Summary by CodeRabbit
Greptile Summary
Adds a curated daily satellite spotlight and connects its live orbital data to the dashboard globe.
Confidence Score: 2/5
The PR should not merge until globe navigation handles catalog-map misses, reveals the target section, and the daily selection updates across midnight.
The enabled navigation action can silently do nothing because its availability check and EarthTwin use different catalog scopes, successful off-screen navigation has no visible result, and the daily pick remains stale in overnight sessions.
Files Needing Attention: frontend/src/components/EarthTwin.tsx, frontend/src/hooks/useSatelliteOfTheDay.ts, frontend/src/pages/Dashboard.tsx
Important Files Changed
Sequence Diagram
sequenceDiagram participant U as User participant C as SpotlightCard participant API as Catalog API participant D as Dashboard participant E as EarthTwin participant S as SpotlightManager C->>API: getCatalogObjectByNorad(NORAD) API-->>C: Live orbital object U->>C: View on Globe C->>D: onViewOnGlobe(NORAD) D->>E: flyToSatellite(NORAD) E->>E: Lookup object in loaded catalog map alt Object is loaded E->>E: Fly Cesium camera E->>S: focusRequest S->>S: Select object and open panel else Object is absent from first page E-->>D: Return without visible action endPrompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat: add Satellite of the Day spotlight..." | Re-trigger Greptile