File size: 3,548 Bytes
4fd1234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
// Thin wrappers around the /api/... contract in frontend/API_CONTRACT.md.
// All calls are relative (e.g. "/api/lessons") so they work both:
//  - in dev, via the Vite proxy (vite.config.js -> http://localhost:7861)
//  - in production, served same-origin by app_custom.py at /custom/

const BASE = '/api'

async function request(path, options = {}) {
  const res = await fetch(`${BASE}${path}`, {
    headers: options.body instanceof FormData ? undefined : { 'Content-Type': 'application/json' },
    ...options,
  })
  if (!res.ok) {
    let detail = res.statusText
    try {
      const data = await res.json()
      detail = data.error || data.detail || detail
    } catch {
      /* ignore */
    }
    throw new Error(detail)
  }
  return res.json()
}

const get = (path) => request(path)
const post = (path, body) =>
  request(path, { method: 'POST', body: body instanceof FormData ? body : JSON.stringify(body ?? {}) })
const put = (path, body) => request(path, { method: 'PUT', body: JSON.stringify(body ?? {}) })
const patch = (path, body) => request(path, { method: 'PATCH', body: JSON.stringify(body ?? {}) })
const del = (path) => request(path, { method: 'DELETE' })

// Lessons
export const listLessons = () => get('/lessons')
export const getLesson = (id) => get(`/lessons/${id}`)
export const saveLesson = (text, annotations) => post('/lessons', { text, annotations })
export const updateLesson = (id, text, annotations) => put(`/lessons/${id}`, { text, annotations })
export const renameLesson = (id, title) => patch(`/lessons/${id}/title`, { title })
export const deleteLesson = (id) => del(`/lessons/${id}`)

// Resources
export const listResources = () => get('/resources')
export const updateResourceLinks = (pageId, links) => put(`/resources/${pageId}/links`, { links })

// Annotation / word card
export const annotate = (text, colorsOn) => post('/annotate', { text, colors_on: colorsOn })
export const renderAnnotations = (annotations, colorsOn) => post('/render', { annotations, colors_on: colorsOn })
export const wordCard = (token, meanings) => post('/word-card', { ...token, meanings })

// Gender Checker
export const genderCheck = (word) => post('/gender-check', { word })

// Translator
export const translateText = (text, direction, lessonText) =>
  post('/translate', { text, direction, lesson_text: lessonText })

// Chat
export const sendChat = (message, history, lessonText) =>
  post('/chat', { message, history, lesson_text: lessonText })

// Exercises — coach (mixed set)
export const generateCoachSet = (lessonText, topic) => post('/exercises/coach', { lesson_text: lessonText, topic })
export const checkCoachExercise = (exercise, answer) => post('/exercises/coach/check', { exercise, answer })

// Exercises — dialogue
export const startDialogue = (lessonText, topic) => post('/exercises/dialogue', { lesson_text: lessonText, topic })
export const sendDialogueReply = (dialogue, replies, reply) =>
  post('/exercises/dialogue/reply', { dialogue, replies, reply })

// Exercises — visual
export const generateSampleVisualExercise = (lessonText, topic) =>
  post('/exercises/visual/sample', { lesson_text: lessonText, topic })

// Exercises — pronunciation
export const getPronunciationTarget = (lessonText, topic, avoid) =>
  post('/exercises/pronunciation/target', { lesson_text: lessonText, topic, avoid })
export const checkPronunciation = (target, transcription) =>
  post('/exercises/pronunciation/check', { target, transcription })

// Summary
export const getSummary = () => get('/summary')