Spaces:
Running
Running
File size: 9,596 Bytes
8f2336a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | import { getInstructors, addInstructor, removeInstructor, checkInstructorPermission } from "../services/auth.js";
import { auth } from "../services/firebase.js";
export function renderInstructorAdminView() {
return `
<div class="min-h-screen p-6 pb-20">
<header class="flex justify-between items-center mb-10 bg-gray-800 bg-opacity-50 p-4 rounded-xl border border-gray-700 backdrop-blur-sm">
<div class="flex items-center space-x-4">
<button id="back-instructor-btn" class="bg-gray-700 hover:bg-gray-600 text-white p-2 rounded-lg transition-all">
← 回講師端
</button>
<h1 class="text-2xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-indigo-400 to-purple-600">
講師權限管理
</h1>
</div>
<button id="add-instructor-btn" class="bg-indigo-600 hover:bg-indigo-500 text-white font-bold py-2 px-6 rounded-lg transition-all shadow-lg">
+ 新增講師
</button>
</header>
<div class="bg-gray-800 rounded-xl border border-gray-700 overflow-hidden shadow-2xl">
<table class="w-full text-left border-collapse">
<thead>
<tr class="bg-gray-900/50">
<th class="p-4 border-b border-gray-700 font-bold text-gray-400">Email (帳號)</th>
<th class="p-4 border-b border-gray-700 font-bold text-gray-400">姓名</th>
<th class="p-4 border-b border-gray-700 font-bold text-gray-400">權限</th>
<th class="p-4 border-b border-gray-700 font-bold text-gray-400 text-right">操作</th>
</tr>
</thead>
<tbody id="instructors-list">
<tr><td colspan="4" class="p-8 text-center text-gray-500">載入中...</td></tr>
</tbody>
</table>
</div>
<!-- Add/Edit Modal -->
<div id="instructor-modal" class="fixed inset-0 bg-black bg-opacity-80 backdrop-blur-sm hidden flex items-center justify-center z-50 p-4">
<div class="bg-gray-800 rounded-xl w-full max-w-lg border border-gray-700 shadow-2xl">
<div class="p-6 border-b border-gray-700">
<h3 class="text-xl font-bold text-white">新增講師</h3>
</div>
<div class="p-6 space-y-4">
<div>
<label class="block text-gray-400 mb-1">Email (Google 帳號)</label>
<input type="email" id="input-email" class="w-full bg-gray-900 border border-gray-600 rounded p-2 text-white" placeholder="example@gmail.com">
<p class="text-xs text-yellow-500 mt-1">* 必須是有效的 Google 帳號 Email</p>
</div>
<div>
<label class="block text-gray-400 mb-1">顯示名稱</label>
<input type="text" id="input-name" class="w-full bg-gray-900 border border-gray-600 rounded p-2 text-white" placeholder="王小明">
</div>
<div>
<label class="block text-gray-400 mb-2">權限設定</label>
<div class="space-y-2">
<label class="flex items-center space-x-2">
<input type="checkbox" class="perm-check rounded bg-gray-700 border-gray-600 text-indigo-500" value="create_room" checked>
<span class="text-gray-300">建立教室 (Create Room)</span>
</label>
<label class="flex items-center space-x-2">
<input type="checkbox" class="perm-check rounded bg-gray-700 border-gray-600 text-indigo-500" value="manage_instructors">
<span class="text-gray-300">管理講師 (Manage Instructors)</span>
</label>
<label class="flex items-center space-x-2">
<input type="checkbox" class="perm-check rounded bg-gray-700 border-gray-600 text-indigo-500" value="add_question">
<span class="text-gray-300">管理題目 (Manage Questions)</span>
</label>
</div>
</div>
</div>
<div class="p-6 border-t border-gray-700 flex justify-end space-x-3">
<button onclick="document.getElementById('instructor-modal').classList.add('hidden')" class="px-4 py-2 text-gray-400 hover:text-white">取消</button>
<button id="save-instructor-btn" class="bg-indigo-600 hover:bg-indigo-500 text-white px-6 py-2 rounded font-bold">新增</button>
</div>
</div>
</div>
</div>
`;
}
export function setupInstructorAdminEvents() {
// Permission Check
const user = auth.currentUser;
if (!user) {
alert("請先登入");
window.location.hash = ''; // Back to Landing
return;
}
checkInstructorPermission(user).then(inst => {
if (!inst || !inst.permissions?.includes('manage_instructors')) {
alert("您沒有權限管理講師");
window.location.hash = 'instructor';
return;
}
loadInstructorList();
}).catch(e => {
console.error(e);
alert("權限驗證失敗");
window.location.hash = 'instructor';
});
// Navigation
document.getElementById('back-instructor-btn').addEventListener('click', () => {
window.location.hash = 'instructor';
});
// Modal Handling
document.getElementById('add-instructor-btn').addEventListener('click', () => {
document.getElementById('input-email').value = '';
document.getElementById('input-name').value = '';
document.querySelectorAll('.perm-check').forEach(c => c.checked = true);
document.getElementById('instructor-modal').classList.remove('hidden');
});
// Save Logic
document.getElementById('save-instructor-btn').addEventListener('click', async () => {
const email = document.getElementById('input-email').value.trim();
const name = document.getElementById('input-name').value.trim();
const permissions = Array.from(document.querySelectorAll('.perm-check:checked')).map(c => c.value);
if (!email || !name) {
alert("請填寫完整資訊");
return;
}
try {
await addInstructor(email, name, permissions);
alert("新增成功");
document.getElementById('instructor-modal').classList.add('hidden');
loadInstructorList();
} catch (e) {
console.error(e);
alert("新增失敗: " + e.message);
}
});
// Global Helpers
window.removeInstructorConfirm = async (email) => {
if (confirm(`確定要移除講師權限 (${email}) 嗎?`)) {
try {
await removeInstructor(email);
loadInstructorList();
} catch (e) {
console.error(e);
alert("移除失敗: " + e.message);
}
}
};
}
async function loadInstructorList() {
const list = document.getElementById('instructors-list');
list.innerHTML = '<tr><td colspan="4" class="p-8 text-center text-gray-500">載入中...</td></tr>';
try {
const instructors = await getInstructors();
if (instructors.length === 0) {
list.innerHTML = '<tr><td colspan="4" class="p-8 text-center text-gray-500">目前沒有其他講師</td></tr>';
return;
}
list.innerHTML = instructors.map(inst => `
<tr class="hover:bg-gray-700/50 transition-colors border-b border-gray-800">
<td class="p-4 font-mono text-gray-300">
${inst.email}
${inst.role === 'admin' ? '<span class="ml-2 text-xs bg-red-900 text-red-300 px-2 py-0.5 rounded border border-red-700">Admin</span>' : ''}
</td>
<td class="p-4 font-bold text-white">${inst.name}</td>
<td class="p-4">
<div class="flex flex-wrap gap-1">
${(inst.permissions || []).map(p => `
<span class="text-xs bg-indigo-900/50 text-indigo-300 px-2 py-0.5 rounded border border-indigo-700">${p}</span>
`).join('')}
</div>
</td>
<td class="p-4 text-right">
${inst.role !== 'admin' ? `
<button onclick="window.removeInstructorConfirm('${inst.email}')" class="text-red-400 hover:text-white bg-red-900/20 hover:bg-red-600 px-3 py-1 rounded transition-colors text-sm">
移除
</button>
` : '<span class="text-gray-600 text-sm">不可變更</span>'}
</td>
</tr>
`).join('');
} catch (e) {
console.error(e);
list.innerHTML = '<tr><td colspan="4" class="p-8 text-center text-red-500">載入失敗</td></tr>';
}
}
|