import { useState } from 'react' import { useTranslation } from 'react-i18next' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { useToast } from '@/components/ui/toast' import { apiClientV2 } from '@/services/apiV2' import type { ExportRule } from '@/types/apiV2' export default function SettingsPage() { const { t } = useTranslation() const { toast } = useToast() const queryClient = useQueryClient() const [isCreating, setIsCreating] = useState(false) const [editingRule, setEditingRule] = useState(null) const [formData, setFormData] = useState({ rule_name: '', confidence_threshold: 0.5, include_metadata: true, filename_pattern: '{filename}_ocr', css_template: 'default', }) // Fetch export rules const { data: exportRules, isLoading } = useQuery({ queryKey: ['exportRules'], queryFn: () => apiClientV2.getExportRules(), }) // Create rule mutation const createRuleMutation = useMutation({ mutationFn: (rule: any) => apiClientV2.createExportRule(rule), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['exportRules'] }) setIsCreating(false) resetForm() toast({ title: t('common.success'), description: '規則已建立', variant: 'success', }) }, onError: (error: any) => { toast({ title: t('common.error'), description: error.response?.data?.detail || t('errors.networkError'), variant: 'destructive', }) }, }) // Update rule mutation const updateRuleMutation = useMutation({ mutationFn: ({ ruleId, rule }: { ruleId: number; rule: any }) => apiClientV2.updateExportRule(ruleId, rule), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['exportRules'] }) setEditingRule(null) resetForm() toast({ title: t('common.success'), description: '規則已更新', variant: 'success', }) }, onError: (error: any) => { toast({ title: t('common.error'), description: error.response?.data?.detail || t('errors.networkError'), variant: 'destructive', }) }, }) // Delete rule mutation const deleteRuleMutation = useMutation({ mutationFn: (ruleId: number) => apiClientV2.deleteExportRule(ruleId), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['exportRules'] }) toast({ title: t('common.success'), description: '規則已刪除', variant: 'success', }) }, onError: (error: any) => { toast({ title: t('common.error'), description: error.response?.data?.detail || t('errors.networkError'), variant: 'destructive', }) }, }) const resetForm = () => { setFormData({ rule_name: '', confidence_threshold: 0.5, include_metadata: true, filename_pattern: '{filename}_ocr', css_template: 'default', }) } const handleCreate = () => { setIsCreating(true) setEditingRule(null) resetForm() } const handleEdit = (rule: ExportRule) => { setEditingRule(rule) setIsCreating(false) setFormData({ rule_name: rule.rule_name, confidence_threshold: rule.config_json.confidence_threshold || 0.5, include_metadata: rule.config_json.include_metadata || true, filename_pattern: rule.config_json.filename_pattern || '{filename}_ocr', css_template: rule.css_template || 'default', }) } const handleSave = () => { const ruleData = { rule_name: formData.rule_name, config_json: { confidence_threshold: formData.confidence_threshold, include_metadata: formData.include_metadata, filename_pattern: formData.filename_pattern, }, css_template: formData.css_template, } if (editingRule) { updateRuleMutation.mutate({ ruleId: editingRule.id, rule: ruleData }) } else { createRuleMutation.mutate(ruleData) } } const handleCancel = () => { setIsCreating(false) setEditingRule(null) resetForm() } const handleDelete = (ruleId: number) => { if (window.confirm('確定要刪除此規則嗎?')) { deleteRuleMutation.mutate(ruleId) } } return (

{t('settings.title')}

{!isCreating && !editingRule && ( )}
{/* Create/Edit Form */} {(isCreating || editingRule) && ( {editingRule ? t('common.edit') + ' ' + t('export.rules.title') : t('export.rules.newRule')} {/* Rule Name */}
setFormData((prev) => ({ ...prev, rule_name: e.target.value }))} className="w-full px-3 py-2 border border-gray-200 rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" placeholder="例如:高信心度匯出" />
{/* Confidence Threshold */}
setFormData((prev) => ({ ...prev, confidence_threshold: Number(e.target.value), })) } className="w-full" />
{/* Include Metadata */}
setFormData((prev) => ({ ...prev, include_metadata: e.target.checked, })) } className="w-4 h-4 border border-gray-200 rounded" />
{/* Filename Pattern */}
setFormData((prev) => ({ ...prev, filename_pattern: e.target.value, })) } className="w-full px-3 py-2 border border-gray-200 rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary" placeholder="{filename}_ocr" />
{/* CSS Template */}
{/* Actions */}
)} {/* Rules List */} {t('export.rules.title')} {isLoading ? (

{t('common.loading')}

) : exportRules && exportRules.length > 0 ? (
{exportRules.map((rule) => (

{rule.rule_name}

信心度閾值: {rule.config_json.confidence_threshold || 0.5} | CSS 樣板:{' '} {rule.css_template || 'default'}

))}
) : (

尚無匯出規則

)}
) }