import { useState, useEffect } from 'react'; import { useAuth } from '../auth/AuthContext'; import { useGitHubConnection } from '../hooks/useGitHubConnection'; import { GitHubReposPanel } from './GitHubReposPanel'; import { OrganizationSection } from './OrganizationSection'; import { apiQldt } from '../api'; export function ChangePasswordPage({ forced }: { forced?: boolean }) { const { changePassword, logout } = useAuth(); const [oldPassword, setOldPassword] = useState(''); const [newPassword, setNewPassword] = useState(''); const [confirm, setConfirm] = useState(''); const [error, setError] = useState(''); const [busy, setBusy] = useState(false); const submit = async (e: React.FormEvent) => { e.preventDefault(); setError(''); if (newPassword.length < 8) { setError('Mật khẩu mới tối thiểu 8 ký tự'); return; } if (newPassword !== confirm) { setError('Xác nhận mật khẩu không khớp'); return; } setBusy(true); try { await changePassword(oldPassword, newPassword); } catch (err: any) { setError(err?.message || 'Đổi mật khẩu thất bại'); } finally { setBusy(false); } }; return (

{forced ? 'Đổi mật khẩu bắt buộc' : 'Đổi mật khẩu'}

{forced &&

Lần đăng nhập đầu tiên — vui lòng đặt mật khẩu mới trước khi tiếp tục.

}
{error &&
{error}
} {!forced && ( )}
); } export function EmailDomainsTab() { return (

Quản lý tổ chức

); } export function MyAccountTab() { const { staff, changePassword } = useAuth(); const gh = useGitHubConnection(); const [oldPw, setOldPw] = useState(''); const [newPw, setNewPw] = useState(''); const [pwMsg, setPwMsg] = useState(''); const [pwErr, setPwErr] = useState(''); // Cấu hình QLĐT Token (Chỉ cho phuocntb@rikkeiacademy.com) const isQldtAdmin = staff?.email === 'phuocntb@rikkeiacademy.com'; const [qldtToken, setQldtToken] = useState(''); const [qldtMsg, setQldtMsg] = useState(''); const [qldtErr, setQldtErr] = useState(''); const [loadingQldt, setLoadingQldt] = useState(false); useEffect(() => { if (!isQldtAdmin) return; setLoadingQldt(true); apiQldt.getToken() .then((res) => { setQldtToken(res.token || ''); }) .catch((err) => { setQldtErr(err.message || 'Lỗi khi tải token QLĐT'); }) .finally(() => { setLoadingQldt(false); }); }, [isQldtAdmin]); const saveQldtToken = async (e: React.FormEvent) => { e.preventDefault(); setQldtMsg(''); setQldtErr(''); try { await apiQldt.saveToken(qldtToken); setQldtMsg('Đã lưu cấu hình QLĐT token'); } catch (err: any) { setQldtErr(err.message || 'Lỗi khi lưu token QLĐT'); } }; const submitPw = async (e: React.FormEvent) => { e.preventDefault(); setPwErr(''); setPwMsg(''); try { await changePassword(oldPw, newPw); setPwMsg('Đã đổi mật khẩu'); setOldPw(''); setNewPw(''); } catch (e: any) { setPwErr(e?.message || 'Lỗi'); } }; const displayName = staff?.fullName?.trim() || staff?.email?.split('@')[0] || 'Tài khoản'; return (

Tài khoản của tôi

Thông tin đăng nhập, GitHub và bảo mật cá nhân.

Thông tin

{displayName}

{staff?.email}

GitHub

Kết nối tài khoản GitHub của bạn để đẩy bài nộp phòng thi lên repo riêng. Mỗi giáo viên dùng GitHub của mình — không dùng chung token server.

{gh.connected ? ( <> Đã kết nối: @{gh.githubLogin} {!gh.canDeleteRepos && ( )} ) : ( )}
{gh.connected && !gh.canDeleteRepos && (
Token hiện tại chưa có quyền delete_repo — không xóa được repo. Bấm Cấp quyền xóa repo (hoặc ngắt kết nối rồi kết nối lại).
)} {gh.error &&
{gh.error}
} {gh.message &&
{gh.message}
} {!gh.connected && (

Sau khi kết nối, vào Phòng thi → tab Bài nộp → đẩy Git (gộp hoặc từng sinh viên).

)} {gh.connected && ( <>

Repo đã tạo

)}
{isQldtAdmin && (

Cấu hình QLĐT Token

Cấu hình token đồng bộ dữ liệu lớp học, môn học và điểm danh từ Cổng đào tạo (QLĐT).

{loadingQldt ? (

Đang tải cấu hình...

) : (