ge-tool/components/CheckPage.tsx
2025-12-10 13:41:43 +07:00

163 lines
5.6 KiB
TypeScript
Executable File

import React, { useState, useEffect } from 'react';
import { supabase } from '../utils/supabase';
import CheckHistory from './CheckHistory';
const CheckPage: React.FC = () => {
const [input, setInput] = useState('');
const [loading, setLoading] = useState(false);
const [currentId, setCurrentId] = useState<string | null>(null);
const [history, setHistory] = useState<any[]>([]);
useEffect(() => {
if (!currentId) return;
const channel = supabase
.channel('check_list_updates')
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'check_list',
filter: `id=eq.${currentId}`,
},
(payload) => {
if (payload.new.status === 'completed' || payload.new.status === 'failed') {
setLoading(false);
}
}
)
.subscribe();
return () => {
supabase.removeChannel(channel);
};
}, [currentId]);
// Fetch history on mount
useEffect(() => {
fetchHistory();
}, []);
const fetchHistory = async () => {
try {
const response = await fetch('/api/check/history');
const data = await response.json();
if (data.success) {
setHistory(data.data);
}
} catch (error) {
console.error('Failed to fetch history:', error);
}
};
// Subscribe to check_list changes for auto-refresh
useEffect(() => {
const channel = supabase
.channel('check_list_all')
.on(
'postgres_changes',
{
event: '*',
schema: 'public',
table: 'check_list',
},
() => {
fetchHistory();
}
)
.subscribe();
return () => {
supabase.removeChannel(channel);
};
}, []);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!input.trim()) return;
setLoading(true);
setCurrentId(null);
try {
const response = await fetch('/api/check/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ check_input: input }),
});
const data = await response.json();
if (data.success) {
setCurrentId(data.id);
// Refresh history after submission
setTimeout(() => fetchHistory(), 1000);
} else {
alert('Error: ' + data.error);
setLoading(false);
}
} catch (error) {
console.error(error);
setLoading(false);
alert('Error submitting request');
}
};
const handleDeleteHistory = async (id: string) => {
try {
const response = await fetch(`/api/check/${id}`, {
method: 'DELETE',
});
const data = await response.json();
if (data.success) {
fetchHistory();
} else {
alert('Lỗi xoá: ' + data.error);
}
} catch (error) {
console.error('Failed to delete:', error);
alert('Lỗi xoá lịch sử');
}
};
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<h1 className="text-2xl font-bold text-white mb-6">Check Upload Status (QC Subset)</h1>
<form onSubmit={handleSubmit} className="mb-8">
<div className="mb-4">
<label className="block text-sm font-medium text-slate-300 mb-2">
Input (GE ID LANG CHAP)
</label>
<textarea
value={input}
onChange={(e) => setInput(e.target.value)}
className="bg-slate-900/50 border border-slate-700 text-slate-100 text-sm rounded-lg focus:ring-indigo-500 focus:border-indigo-500 block w-full p-2.5 h-32 font-mono"
placeholder="4164 FR 3&#10;419 DE 80"
/>
</div>
<div className="flex gap-2">
<button
type="submit"
disabled={loading}
className="text-white bg-indigo-600 hover:bg-indigo-700 focus:ring-4 focus:outline-none focus:ring-indigo-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center disabled:opacity-50"
>
{loading ? 'Checking...' : 'Check'}
</button>
<button
type="button"
onClick={() => setInput('')}
disabled={loading || !input.trim()}
className="text-slate-300 bg-slate-700 hover:bg-slate-600 focus:ring-4 focus:outline-none focus:ring-slate-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center disabled:opacity-50"
>
Clear
</button>
</div>
</form>
<CheckHistory history={history} onDelete={handleDeleteHistory} />
</div>
);
};
export default CheckPage;