This commit is contained in:
@@ -965,3 +965,20 @@ export const apiExam = {
|
||||
}>;
|
||||
},
|
||||
};
|
||||
|
||||
export const apiQldt = {
|
||||
getToken: async (): Promise<{ token: string }> => {
|
||||
const res = await staffFetch('/qldt-token');
|
||||
if (!res.ok) await parseError(res, 'Không tải được token QLĐT');
|
||||
return res.json();
|
||||
},
|
||||
saveToken: async (token: string): Promise<{ ok: boolean; message: string }> => {
|
||||
const res = await staffFetch('/qldt-token', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ token }),
|
||||
});
|
||||
if (!res.ok) await parseError(res, 'Lưu token thất bại');
|
||||
return res.json();
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
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();
|
||||
@@ -85,6 +86,40 @@ export function MyAccountTab() {
|
||||
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('');
|
||||
@@ -165,6 +200,45 @@ export function MyAccountTab() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isQldtAdmin && (
|
||||
<div className="card" style={{ padding: '1.25rem' }}>
|
||||
<h2 className="section-title">Cấu hình QLĐT Token</h2>
|
||||
<p className="page-desc" style={{ marginTop: 0 }}>
|
||||
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).
|
||||
</p>
|
||||
{loadingQldt ? (
|
||||
<p style={{ color: 'var(--text-muted)' }}>Đang tải cấu hình...</p>
|
||||
) : (
|
||||
<form onSubmit={saveQldtToken} className="login-form">
|
||||
<label className="login-field">
|
||||
<span>Token QLĐT</span>
|
||||
<textarea
|
||||
style={{
|
||||
width: '100%',
|
||||
minHeight: '100px',
|
||||
fontFamily: 'monospace',
|
||||
fontSize: '0.875rem',
|
||||
padding: '0.5rem',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid var(--border-color, #ccc)',
|
||||
backgroundColor: 'var(--bg-input, #fff)',
|
||||
color: 'var(--text, #333)',
|
||||
resize: 'vertical'
|
||||
}}
|
||||
value={qldtToken}
|
||||
onChange={(e) => setQldtToken(e.target.value)}
|
||||
placeholder="Nhập JWT Token từ QLĐT..."
|
||||
required
|
||||
/>
|
||||
</label>
|
||||
{qldtErr && <div className="login-error">{qldtErr}</div>}
|
||||
{qldtMsg && <div className="login-success">{qldtMsg}</div>}
|
||||
<button type="submit" className="btn btn-primary" style={{ marginTop: '0.5rem' }}>Lưu cấu hình</button>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="card" style={{ padding: '1.25rem' }}>
|
||||
<h2 className="section-title">Đổi mật khẩu</h2>
|
||||
<form onSubmit={submitPw} className="login-form" style={{ maxWidth: 400 }}>
|
||||
|
||||
Reference in New Issue
Block a user