File size: 6,821 Bytes
a0c836f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | import axios from "axios"
// Same-origin in production (frontend served by FastAPI); localhost:8000 in dev.
// Override with VITE_API_URL if you host the API elsewhere.
const BASE_URL = import.meta.env.VITE_API_URL ?? "http://localhost:8000"
// ---------------------------------------------------------------------------
// Auth token handling (medication-adherence layer)
// ---------------------------------------------------------------------------
export const TOKEN_KEY = "pharmachat_token"
// Attach the bearer token (if any) to every request. The old chat endpoints
// simply ignore the header, so this is safe for them too.
axios.interceptors.request.use((config) => {
const token = localStorage.getItem(TOKEN_KEY)
if (token) {
config.headers = config.headers || {}
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// On 401, drop the token and bounce to login.
axios.interceptors.response.use(
(res) => res,
(error) => {
if (error?.response?.status === 401) {
localStorage.removeItem(TOKEN_KEY)
if (!window.location.pathname.startsWith("/login")) {
window.location.href = "/login"
}
}
return Promise.reject(error)
}
)
// ---------------------------------------------------------------------------
// Existing chat API (conversation create/list now scoped to the user via /v2)
// ---------------------------------------------------------------------------
export async function createConversation() {
const response = await axios.post(`${BASE_URL}/v2/conversation`)
return response.data.conversation_id
}
export async function getConversations() {
const response = await axios.get(`${BASE_URL}/v2/conversations`)
return response.data.conversations
}
export async function getMessages(conversationId) {
const response = await axios.get(`${BASE_URL}/conversations/${conversationId}/messages`)
return response.data.messages
}
export async function deleteConversation(conversationId) {
const response = await axios.delete(`${BASE_URL}/conversations/${conversationId}`)
return response.data
}
export async function sendMessage(text, imageFile, conversationId) {
let image_base64 = null
if (imageFile) {
image_base64 = await toBase64(imageFile)
}
const response = await axios.post(`${BASE_URL}/chat`, {
query: text || null,
image_base64: image_base64,
conversation_id: conversationId,
})
return response.data.response
}
function toBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => {
const base64 = reader.result.split(",")[1]
resolve(base64)
}
reader.onerror = reject
})
}
// ---------------------------------------------------------------------------
// Auth
// ---------------------------------------------------------------------------
export async function signup(name, email, password, language = "en") {
const res = await axios.post(`${BASE_URL}/auth/signup`, { name, email, password, language })
return res.data
}
export async function login(email, password) {
const res = await axios.post(`${BASE_URL}/auth/login`, { email, password })
return res.data
}
export async function getMe() {
const res = await axios.get(`${BASE_URL}/auth/me`)
return res.data.user
}
// ---------------------------------------------------------------------------
// Medications + schedule
// ---------------------------------------------------------------------------
export async function getCatalog() {
const res = await axios.get(`${BASE_URL}/medications/catalog`)
return res.data.drugs
}
export async function getDrugInfo(drugName) {
const res = await axios.get(`${BASE_URL}/medications/info/${encodeURIComponent(drugName)}`)
return res.data
}
export async function getMyMeds() {
const res = await axios.get(`${BASE_URL}/medications/mine`)
return res.data.medications
}
export async function addMyMed(drug_name, pack_quantity = null) {
const res = await axios.post(`${BASE_URL}/medications/mine`, { drug_name, pack_quantity })
return res.data
}
export async function deleteMyMed(id) {
const res = await axios.delete(`${BASE_URL}/medications/mine/${id}`)
return res.data
}
export async function generateSchedule() {
const res = await axios.post(`${BASE_URL}/schedule/generate`)
return res.data
}
export async function getSchedule() {
const res = await axios.get(`${BASE_URL}/schedule/`)
return res.data
}
export async function getToday() {
const res = await axios.get(`${BASE_URL}/schedule/today`)
return res.data.doses
}
export const SCHEDULE_ICS_URL = `${BASE_URL}/schedule/export.ics`
// ---------------------------------------------------------------------------
// Notifications / dose responses
// ---------------------------------------------------------------------------
export async function getVapidKey() {
const res = await axios.get(`${BASE_URL}/notifications/vapid-public-key`)
return res.data.public_key
}
export async function subscribePush(subscription) {
const res = await axios.post(`${BASE_URL}/notifications/subscribe`, subscription)
return res.data
}
export async function respondDose(doseId, action, snoozeMinutes = 15) {
const res = await axios.post(`${BASE_URL}/notifications/dose/${doseId}/respond`, {
action, snooze_minutes: snoozeMinutes,
})
return res.data
}
export async function getPushStatus() {
const res = await axios.get(`${BASE_URL}/notifications/status`)
return res.data
}
export async function sendTestReminder() {
const res = await axios.post(`${BASE_URL}/notifications/test`)
return res.data
}
// ---------------------------------------------------------------------------
// Gamification
// ---------------------------------------------------------------------------
export async function getGamification() {
const res = await axios.get(`${BASE_URL}/gamification/me`)
return res.data
}
export async function getLeaderboard(period = "all") {
const res = await axios.get(`${BASE_URL}/gamification/leaderboard`, { params: { period } })
return res.data.leaderboard
}
export async function getHistory() {
const res = await axios.get(`${BASE_URL}/gamification/history`)
return res.data.history
}
// ---------------------------------------------------------------------------
// Settings
// ---------------------------------------------------------------------------
export async function setLanguage(language) {
const res = await axios.put(`${BASE_URL}/settings/language`, { language })
return res.data
}
|