/**
* Main application component that demonstrates MentraOS authentication integration.
* This file serves as the root component for testing the mentraos-react package functionality.
*/
import React, {useState} from "react"
import {MentraAuthProvider, UseMentraAuth} from "@mentra/react"
/**
* Type definition for the API response from the notes endpoint
*/
interface NotesApiResponse {
[key: string]: any // Allow flexible response structure
}
/**
* Content component that displays authentication status and user information.
* This component consumes the MentraAuth context to show loading states,
* errors, and authenticated user data. It also provides functionality to make
* authenticated API calls to the App backend.
*
* @returns {React.JSX.Element} The rendered content based on authentication state
*/
function Content(): React.JSX.Element {
const {userId, isLoading, error, isAuthenticated, frontendToken} = UseMentraAuth()
// State for managing API call results and loading state
const [apiResult, setApiResult] = useState<NotesApiResponse | null>(null)
const [apiError, setApiError] = useState<string | null>(null)
const [isLoadingApi, setIsLoadingApi] = useState<boolean>(false)
/**
* Makes an authenticated API call to the app backend notes endpoint
* Uses the frontendToken for authorization
*/
const fetchNotesFromBackend = async (): Promise<void> => {
if (!frontendToken) {
setApiError("No frontend token available for backend call.")
return
}
setIsLoadingApi(true)
setApiError(null)
setApiResult(null)
try {
const response = await fetch(`/api/notes`, {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${frontendToken}`,
},
})
if (!response.ok) {
throw new Error(`Backend request failed: ${response.status} ${response.statusText}`)
}
const data: NotesApiResponse = await response.json()
setApiResult(data)
} catch (error) {
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"
setApiError(errorMessage)
} finally {
setIsLoadingApi(false)
}
}
// Handle loading state
if (isLoading) {
return <p>Loading authentication...</p>
}
// Handle error state
if (error) {
return <p style={{color: "red"}}>Error: {error}</p>
}
// Handle unauthenticated state
if (!isAuthenticated) {
return <p>Not authenticated. Please log in.</p>
}
// Handle authenticated state
return (
<div>
<p style={{color: "green"}}>✓ Successfully authenticated!</p>
<p>
User ID: <strong>{userId}</strong>
</p>
{/* API Testing Section */}
<div style={{marginTop: "30px", padding: "20px", border: "1px solid #ccc", borderRadius: "8px"}}>
<h2>Backend API Test</h2>
<p>Test authenticated calls to your app backend:</p>
<button
onClick={fetchNotesFromBackend}
disabled={isLoadingApi}
style={{
padding: "10px 20px",
backgroundColor: isLoadingApi ? "#ccc" : "#007bff",
color: "white",
border: "none",
borderRadius: "4px",
cursor: isLoadingApi ? "not-allowed" : "pointer",
fontSize: "16px",
}}>
{isLoadingApi ? "Loading..." : "Fetch Notes from Backend"}
</button>
{/* Display API loading state */}
{isLoadingApi && <p style={{color: "#666", marginTop: "10px"}}>Making authenticated request...</p>}
{/* Display API errors */}
{apiError && (
<div
style={{
marginTop: "15px",
padding: "10px",
backgroundColor: "#ffe6e6",
border: "1px solid #ff9999",
borderRadius: "4px",
}}>
<strong style={{color: "#cc0000"}}>API Error:</strong>
<p style={{color: "#cc0000", margin: "5px 0 0 0"}}>{apiError}</p>
</div>
)}
{/* Display API results */}
{apiResult && (
<div
style={{
marginTop: "15px",
padding: "10px",
backgroundColor: "#e6ffe6",
border: "1px solid #99ff99",
borderRadius: "4px",
}}>
<strong style={{color: "#006600"}}>API Response:</strong>
<pre
style={{
backgroundColor: "#f5f5f5",
padding: "10px",
borderRadius: "4px",
overflow: "auto",
maxHeight: "300px",
fontSize: "14px",
fontFamily: 'Monaco, Consolas, "Courier New", monospace',
}}>
{JSON.stringify(apiResult, null, 2)}
</pre>
</div>
)}
</div>
</div>
)
}
/**
* Root App component that provides authentication context to the entire application.
* This component wraps the Content component with the MentraAuthProvider
* to enable authentication functionality throughout the app.
*
* @returns {React.JSX.Element} The main application component
*/
function App(): React.JSX.Element {
return (
<MentraAuthProvider>
<div style={{padding: "20px", fontFamily: "Arial, sans-serif"}}>
<h1>MentraOS React Test App</h1>
<Content />
</div>
</MentraAuthProvider>
)
}
export default App