Spaces:
Runtime error
Runtime error
| import { createClient } from '@supabase/supabase-js' | |
| import type { Problem, LedgerProblem, StatementProblem } from '../types' | |
| const url = import.meta.env.VITE_SUPABASE_URL as string | undefined | |
| const anonKey = import.meta.env.VITE_SUPABASE_ANON_KEY as string | undefined | |
| export const isSupabaseConfigured = Boolean(url && anonKey) | |
| export const supabase = isSupabaseConfigured | |
| ? createClient(url!, anonKey!) | |
| : null | |
| /** | |
| * 第1問(仕訳)の問題を取得する。 | |
| * topic='all' または未指定のとき全論点を取得する。 | |
| * ※ isSolvable フィルタは適用しない(利息・消費税など計算問題に対応するため) | |
| */ | |
| export async function fetchProblems(topic?: string, limit = 20): Promise<Problem[]> { | |
| if (!supabase) throw new Error('Supabase が設定されていません') | |
| let query = supabase | |
| .from('jq_problems') | |
| .select('id, section, topic, difficulty, event_text, documents, symbols, debit, credit, choices, hint, explanation') | |
| .eq('section', 'journal') | |
| .limit(limit) | |
| if (topic && topic !== 'all') { | |
| query = query.eq('topic', topic) | |
| } | |
| const { data, error } = await query | |
| if (error) throw new Error(`問題の取得に失敗しました: ${error.message}`) | |
| return (data ?? []) as Problem[] | |
| } | |
| /** バンクが足りないときに Edge Function で補充生成する */ | |
| export async function generateProblems(topic: string, count = 5): Promise<Problem[]> { | |
| if (!supabase) throw new Error('Supabase が設定されていません') | |
| const { data, error } = await supabase.functions.invoke('jq-generate-problems', { | |
| body: { topic, count }, | |
| }) | |
| if (error) throw new Error(`問題の生成に失敗しました: ${error.message}`) | |
| return ((data?.problems ?? []) as Problem[]) | |
| } | |
| /** 第2問(勘定記入)問題を取得する */ | |
| export async function fetchLedgerProblems(): Promise<LedgerProblem[]> { | |
| if (!supabase) throw new Error('Supabase が設定されていません') | |
| const { data, error } = await supabase | |
| .from('jq_problems') | |
| .select('id, section, topic, event_text, documents, problem_data, hint, explanation') | |
| .eq('section', 'ledger') | |
| if (error) throw new Error(`勘定記入問題の取得に失敗しました: ${error.message}`) | |
| return (data ?? []).map((row) => { | |
| const d = row.problem_data ?? {} | |
| return { | |
| id: row.id, | |
| section: 'ledger' as const, | |
| topic: row.topic, | |
| account_name: d.account_name ?? '', | |
| event_text: row.event_text, | |
| documents: row.documents ?? undefined, | |
| word_bank: d.word_bank ?? [], | |
| rows: d.rows ?? [], | |
| hint: row.hint, | |
| explanation: row.explanation, | |
| } satisfies LedgerProblem | |
| }) | |
| } | |
| /** 第3問(財務諸表)問題を取得する */ | |
| export async function fetchStatementProblems(): Promise<StatementProblem[]> { | |
| if (!supabase) throw new Error('Supabase が設定されていません') | |
| const { data, error } = await supabase | |
| .from('jq_problems') | |
| .select('id, section, topic, event_text, documents, problem_data, hint, explanation') | |
| .eq('section', 'statement') | |
| if (error) throw new Error(`財務諸表問題の取得に失敗しました: ${error.message}`) | |
| return (data ?? []).map((row) => { | |
| const d = row.problem_data ?? {} | |
| return { | |
| id: row.id, | |
| section: 'statement' as const, | |
| topic: row.topic, | |
| event_text: row.event_text, | |
| documents: row.documents ?? undefined, | |
| bs_rows: d.bs_rows ?? [], | |
| hint: row.hint, | |
| explanation: row.explanation, | |
| } satisfies StatementProblem | |
| }) | |
| } | |
| /** プレイ結果の記録(認証済みユーザーのみ呼ぶ) */ | |
| export async function recordAttempt(problemId: string, isCorrect: boolean): Promise<void> { | |
| if (!supabase) return | |
| const { error } = await supabase | |
| .from('jq_attempts') | |
| .insert({ problem_id: problemId, is_correct: isCorrect }) | |
| if (error) console.warn('recordAttempt failed', error) | |
| } | |