Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| /* | |
| # Copyright 2025 Google LLC | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| */ | |
| import React, {useEffect, useState} from 'react'; | |
| import JourneyCard from '../components/JourneyCard'; | |
| import IconCodeBlocks from '../icons/IconCodeBlocks'; | |
| import IconBackArrow from '../icons/IconBackArrow'; | |
| import IconInfo from '../icons/IconInfo'; | |
| import styles from './JourneySelectionScreen.module.css'; | |
| import {CXR_14_CITATION} from "../data/constants.js"; | |
| import { fetchWithRetry } from '../utils/fetchWithRetry'; | |
| const JourneySelectionScreen = ({onLaunchJourney, onNavigate, onShowDetails}) => { | |
| const [journeys, setJourneys] = useState([]); | |
| const [isLoading, setIsLoading] = useState(true); | |
| const [error, setError] = useState(null); | |
| useEffect(() => { | |
| const fetchCases = async () => { | |
| try { | |
| const response = await fetchWithRetry('/api/case/stub'); | |
| if (!response.ok) { | |
| throw new Error(`Network response was not ok, couldn't load images: ${response.statusText}`); | |
| } | |
| const data = await response.json(); | |
| const formattedData = data.map(caseItem => ({ | |
| id: caseItem.id, | |
| label: `Case ${caseItem.id.padStart(2, '0')}`, | |
| imageUrl: caseItem.download_image_url | |
| })); | |
| setJourneys(formattedData); | |
| } catch (err) { | |
| setError(err.message); | |
| } finally { | |
| setIsLoading(false); | |
| } | |
| }; | |
| fetchCases(); | |
| }, []); | |
| return ( | |
| <div className={styles.pageContainer}> | |
| <div className={styles.topNav}> | |
| <button className={styles.backButton} onClick={() => onNavigate('landing')}> | |
| <IconBackArrow/> | |
| <span>Back</span> | |
| </button> | |
| <button className={styles.detailsButton} onClick={onShowDetails}> | |
| <IconCodeBlocks className={styles.detailsIcon}/> | |
| Details about this Demo | |
| </button> | |
| </div> | |
| <div className={styles.contentBox}> | |
| <div className={styles.contentHeader}> | |
| <h1 className={styles.title}>Select a Case</h1> | |
| <p className={styles.subtext}> | |
| This demo uses 2 Chest X-Rays as an example set ( | |
| <span className={styles.imageSource}> | |
| <span | |
| className="tooltip-trigger" | |
| data-tooltip-content={CXR_14_CITATION} | |
| style={{borderBottom: '1px dotted'}} | |
| > | |
| Image source: CXR-14 Dataset | |
| </span> | |
| </span> | |
| ) | |
| </p> | |
| </div> | |
| <div className={styles.journeysContainer}> | |
| {isLoading ? ( | |
| <div className={styles.statusContainer}> | |
| <div className={styles.loadingSpinner}></div> | |
| <p className={styles.statusText}>Loading available cases...</p> | |
| </div> | |
| ) : error ? ( | |
| <div className={`${styles.statusContainer} ${styles.errorContainer}`}> | |
| <p className={styles.statusText}>⚠️</p> | |
| <p className={styles.statusText}>Could not load cases. Please try again later.</p> | |
| </div> | |
| ) : ( | |
| journeys.map(journey => ( | |
| <JourneyCard | |
| key={journey.id} | |
| journey={journey} | |
| onLaunch={() => onLaunchJourney(journey)} | |
| /> | |
| )) | |
| )} | |
| </div> | |
| <br/> | |
| <p className={styles.subtext}> | |
| MedGemma utilises RAG to dynamically include additional context from | |
| <a href="https://www.who.int/publications/i/item/9241546778" target="_blank" rel="noopener noreferrer"> | |
| The WHO manual of diagnostic imaging | |
| </a> | |
| <span | |
| className="tooltip-trigger" | |
| data-tooltip-content="This demo uses MedGemma to generate a learning module for analyzing chest X-rays, leveraging a RAG system to ground every question's rationale and hint in the authoritative WHO guideline." | |
| > | |
| <IconInfo/> | |
| </span> | |
| </p> | |
| <p className={styles.subtext}> | |
| This demo is built with the assumption that the user has basic medical knowledge. The experience is designed | |
| to guide the user through a case, facilitating learning along the process. | |
| </p> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default JourneySelectionScreen; |