# Frontend Developer Integration Examples (React & TypeScript) **Language**: TypeScript / JavaScript (React 18+) --- ## 1. Complete API Client (`src/api/client.ts`) ```typescript const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'; export interface PatientContext { id: string; name?: string; age?: number; gender?: string; phone?: string; abha_id?: string; insurance_scheme?: string; dietary_habits?: string; } export interface CategoryContext { type: 'general' | 'speciality'; code: string; name: string; } export interface StartOnboardingResponse { success: boolean; session_id: string; patient_id: string; category: CategoryContext; language: string; status: string; stage: string; message: string; } export interface SendMessageResponse { success: boolean; session_id: string; stage: string; message: string; status: string; response_time_ms?: number; response_time_sec?: number; } export interface CompleteOnboardingResponse { success: boolean; session_id: string; status: string; result?: any; message: string; response_time_ms?: number; response_time_sec?: number; } /** * Generic Fetch Wrapper with Authorization & Error Handling */ async function fetchApi(endpoint: string, options: RequestInit = {}, patientId: string): Promise { const token = `test_token_${patientId}`; const headers = new Headers(options.headers || {}); headers.set('Authorization', `Bearer ${token}`); if (!(options.body instanceof FormData)) { headers.set('Content-Type', 'application/json'); } const response = await fetch(`${API_BASE_URL}${endpoint}`, { ...options, headers, }); if (!response.ok) { const errorBody = await response.json().catch(() => ({ detail: 'Network response error' })); throw new Error(errorBody.detail || `HTTP Error ${response.status}`); } return response.json(); } /** * Start Text Onboarding Session */ export async function startOnboarding( patient: PatientContext, category: CategoryContext, language: string = 'en' ): Promise { return fetchApi( '/v1/onboarding/start', { method: 'POST', body: JSON.stringify({ patient, category, language }), }, patient.id ); } /** * Send Intake Chat Message */ export async function sendMessage( sessionId: string, patientId: string, message: string ): Promise { return fetchApi( `/v1/onboarding/${sessionId}/message`, { method: 'POST', body: JSON.stringify({ message }), }, patientId ); } /** * Upload Medical Document (Report / Prescription) */ export async function uploadDocument( sessionId: string, patientId: string, file: File ): Promise { const formData = new FormData(); formData.append('file', file); return fetchApi( `/v1/documents/${sessionId}/upload`, { method: 'POST', body: formData, }, patientId ); } /** * Finalize Session & Extract Structured EHR */ export async function completeOnboarding( sessionId: string, patientId: string, confirmed: boolean = true ): Promise { return fetchApi( `/v1/onboarding/${sessionId}/complete`, { method: 'POST', body: JSON.stringify({ confirmed }), }, patientId ); } ``` --- ## 2. Voice Onboarding Hook (`src/hooks/useVoiceOnboarding.ts`) ```typescript import { useState, useRef } from 'react'; export function useVoiceOnboarding(patientId: string) { const [sessionId, setSessionId] = useState(null); const [isRecording, setIsRecording] = useState(false); const [isPlayingAudio, setIsPlayingAudio] = useState(false); const mediaRecorderRef = useRef(null); const audioChunksRef = useRef([]); const startVoiceSession = async (patient: any, language: string = 'en-IN') => { const res = await fetch('http://localhost:8000/v1/voice-onboarding/start', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer test_token_${patientId}`, }, body: JSON.stringify({ patient, category: { type: 'general', code: 'general_medicine', name: 'General Medicine' }, language, }), }); const data = await res.json(); setSessionId(data.session_id); if (data.audio_url) { playAudioResponse(data.audio_url); } return data; }; const playAudioResponse = (audioUrl: string) => { setIsPlayingAudio(true); const audio = new Audio(`http://localhost:8000${audioUrl}`); audio.onended = () => setIsPlayingAudio(false); audio.onerror = () => setIsPlayingAudio(false); audio.play(); }; const startRecording = async () => { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); const mediaRecorder = new MediaRecorder(stream); mediaRecorderRef.current = mediaRecorder; audioChunksRef.current = []; mediaRecorder.ondataavailable = (event) => { if (event.data.size > 0) audioChunksRef.current.push(event.data); }; mediaRecorder.start(); setIsRecording(true); }; const stopRecordingAndSend = async () => { if (!mediaRecorderRef.current || !sessionId) return; return new Promise((resolve) => { mediaRecorderRef.current!.onstop = async () => { setIsRecording(false); const audioBlob = new Blob(audioChunksRef.current, { type: 'audio/wav' }); const formData = new FormData(); formData.append('audio', audioBlob, 'speech.wav'); const res = await fetch(`http://localhost:8000/v1/voice-onboarding/${sessionId}/turn`, { method: 'POST', headers: { 'Authorization': `Bearer test_token_${patientId}`, }, body: formData, }); const turnData = await res.json(); if (turnData.audio_url) { playAudioResponse(turnData.audio_url); } resolve(turnData); }; mediaRecorderRef.current!.stop(); }); }; return { sessionId, isRecording, isPlayingAudio, startVoiceSession, startRecording, stopRecordingAndSend, }; } ```