Supervisor update3

This commit is contained in:
2024-10-30 06:57:51 +09:00
parent d017da17d4
commit e01d2e7ea6
3 changed files with 76 additions and 85 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
rog/.DS_Store vendored

Binary file not shown.

View File

@ -60,7 +60,7 @@
<div class="text-sm text-gray-500">判定</div> <div class="text-sm text-gray-500">判定</div>
<div id="validate" class="font-semibold text-blue-600"></div> <div id="validate" class="font-semibold text-blue-600"></div>
</div> </div>
</div> </div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6"> <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
<div class="bg-gray-50 p-4 rounded-lg"> <div class="bg-gray-50 p-4 rounded-lg">
@ -86,7 +86,7 @@
<table class="min-w-full divide-y divide-gray-200"> <table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50"> <thead class="bg-gray-50">
<tr> <tr>
<th class="w-8"></th> <!-- ハンバーガーアイコン用 --> <th class="w-8"></th> <!-- ハンバーガーアイコン用 -->
<th class="px-2 py-3 text-left text-xs font-medium text-gray-500 uppercase">走行順</th> <th class="px-2 py-3 text-left text-xs font-medium text-gray-500 uppercase">走行順</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">規定写真</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">規定写真</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">撮影写真</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">撮影写真</th>
@ -95,7 +95,7 @@
<th class="px-2 py-3 text-left text-xs font-medium text-gray-500 uppercase">通過審査</th> <th class="px-2 py-3 text-left text-xs font-medium text-gray-500 uppercase">通過審査</th>
<th class="px-2 py-3 text-left text-xs font-medium text-gray-500 uppercase">買物</th> <th class="px-2 py-3 text-left text-xs font-medium text-gray-500 uppercase">買物</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">獲得点数</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">獲得点数</th>
<th class="w-8"></th> <!-- 削除ボタン用 --> <th class="w-8"></th> <!-- 削除ボタン用 -->
</tr> </tr>
</thead> </thead>
<tbody id="checkinList" class="bg-white divide-y divide-gray-200"> <tbody id="checkinList" class="bg-white divide-y divide-gray-200">
@ -106,9 +106,9 @@
<!-- アクションボタン --> <!-- アクションボタン -->
<div class="mt-6 flex justify-end space-x-4"> <div class="mt-6 flex justify-end space-x-4">
<button onclick="showAddCPModal()" class="px-4 py-2 bg-blue-500 text-white rounded"> <button onclick="showAddCPModal()" class="px-4 py-2 bg-blue-500 text-white rounded">
新規CP追加 新規CP追加
</button> </button>
<button id="saveButton" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"> <button id="saveButton" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
保存 保存
</button> </button>
@ -120,7 +120,7 @@
</div> </div>
<script> <script>
// APIのベースURLを環境に応じて設定 // APIのベースURLを環境に応じて設定
const API_BASE_URL = '/api'; const API_BASE_URL = '/api';
async function login(email, password) { async function login(email, password) {
@ -286,20 +286,22 @@
const zekkenNumber = zekkenNumberSelect.value const zekkenNumber = zekkenNumberSelect.value
// イベントとチェックインデータを取得 // イベントとチェックインデータを取得
fetch(`${API_BASE_URL}/get_team_info/${eventCode}`,{ fetch(`${API_BASE_URL}/get_team_info/${eventCode}`,{
headers: { headers: {
'Authorization': `Token ${getAuthToken()}`, 'Authorization': `Token ${getAuthToken()}`,
'Content-Type': 'application/json' 'Content-Type': 'application/json'
} }
})
.then(response => response.json()) .then(response => response.json())
.then(team => { .then(team => {
if (team.self_rogaining) { if (team.self_rogaining) {
// セルフロゲイニングの場合 // セルフロゲイニングの場合
fetch(`${API_BASE_URL}/checkins/${zekkenNumber}/${eventCode}/`, fetch(`${API_BASE_URL}/checkins/${zekkenNumber}/${eventCode}/`,{
headers: { headers: {
'Authorization': `Token ${getAuthToken()}`, 'Authorization': `Token ${getAuthToken()}`,
'Content-Type': 'application/json' 'Content-Type': 'application/json',
} }
})
.then(response => response.json()) .then(response => response.json())
.then(checkins => { .then(checkins => {
const startCheckin = checkins.find(c => c.cp_number === -1); const startCheckin = checkins.find(c => c.cp_number === -1);
@ -311,8 +313,8 @@
updateValidation(timeDiff, maxTime); updateValidation(timeDiff, maxTime);
} }
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
;
} else { } else {
// 通常のロゲイニングの場合 // 通常のロゲイニングの場合
const startTime = new Date(event.start_datetime); const startTime = new Date(event.start_datetime);
@ -331,15 +333,11 @@
display.classList.remove('hidden'); display.classList.remove('hidden');
input.classList.add('hidden'); input.classList.add('hidden');
// 判定を入れる
} }
// 判定の更新を行う補助関数 // 判定の更新を行う補助関数
function updateValidation(timeDiff, maxTime) { function updateValidation(timeDiff, maxTime) {
console.log('updateValidation',timeDiff,' > ',maxTime) console.log('updateValidation',timeDiff,' > ',maxTime)
const validateElement = document.getElementById('validate'); const validateElement = document.getElementById('validate');
if (validateElement) { if (validateElement) {
if (timeDiff > maxTime) { if (timeDiff > maxTime) {
@ -371,15 +369,14 @@
} }
async function loadEventCodes() { async function loadEventCodes() {
try { try {
const response = await fetch(`${API_BASE_URL}/new-events/`,{ const response = await fetch(`${API_BASE_URL}/new-events/`,{
headers: { headers: {
'Authorization': `Token ${getAuthToken()}`, 'Authorization': `Token ${getAuthToken()}`,
'Content-Type': 'application/json' 'Content-Type': 'application/json'
} }
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
;
if (!response.ok) { if (!response.ok) {
if (response.status === 401) { if (response.status === 401) {
@ -406,22 +403,22 @@
select.appendChild(option); select.appendChild(option);
}); });
} catch (error) { } catch (error) {
console.error('Error loading events:', error); console.error('Error loading events:', error);
// ユーザーにエラーを表示 // ユーザーにエラーを表示
const select = document.getElementById('eventCode'); const select = document.getElementById('eventCode');
select.innerHTML = '<option value="">エラー: イベントの読み込みに失敗しました</option>'; select.innerHTML = '<option value="">エラー: イベントの読み込みに失敗しました</option>';
}
}
} }
// ゼッケン番号をロードする // ゼッケン番号をロードする
function loadZekkenNumbers(eventCode) { function loadZekkenNumbers(eventCode) {
// APIからゼッケン番号を取得して選択肢を設定 // APIからゼッケン番号を取得して選択肢を設定
fetch(`${API_BASE_URL}/zekken_numbers/${eventCode}`,{ fetch(`${API_BASE_URL}/zekken_numbers/${eventCode}`,{
headers: { headers: {
'Authorization': `Token ${getAuthToken()}` 'Authorization': `Token ${getAuthToken()}`
}) }
})
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
const select = document.getElementById('zekkenNumber'); const select = document.getElementById('zekkenNumber');
@ -433,29 +430,27 @@
select.appendChild(option); select.appendChild(option);
}); });
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
}); }
// チームデータのロード // チームデータのロード
async function loadTeamData(zekkenNumber,event_code) { async function loadTeamData(zekkenNumber,event_code) {
try { try {
const [teamResponse, checkinsResponse] = await Promise.all([ const [teamResponse, checkinsResponse] = await Promise.all([
fetch(`${API_BASE_URL}/team_info/${zekkenNumber}/`, { fetch(`${API_BASE_URL}/team_info/${zekkenNumber}/`, {
headers: { headers: {
'Authorization': `Token ${getAuthToken()}` 'Authorization': `Token ${getAuthToken()}`
} }
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error)),
; fetch(`${API_BASE_URL}/checkins/${zekkenNumber}/${event_code}/`, {
fetch(`${API_BASE_URL}/checkins/${zekkenNumber}/${event_code}/`, {
headers: { headers: {
'Authorization': `Token ${getAuthToken()}` 'Authorization': `Token ${getAuthToken()}`
} }
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error))
;
]); ]);
// 各レスポンスのステータスを個別にチェック // 各レスポンスのステータスを個別にチェック
@ -558,7 +553,7 @@
} }
} }
}); });
updatePathOrders(); updatePathOrders();
// 合計ポイントの更新 // 合計ポイントの更新
document.getElementById('totalPoints').textContent = totalPoints; document.getElementById('totalPoints').textContent = totalPoints;
@ -704,8 +699,8 @@
`; `;
tbody.appendChild(tr); tbody.appendChild(tr);
}); });
updatePathOrders(); updatePathOrders();
calculatePoints(); // 総合ポイントの計算 calculatePoints(); // 総合ポイントの計算
} }
@ -718,12 +713,11 @@
try { try {
const response = await fetch(`${API_BASE_URL}/checkins/${id}`, { const response = await fetch(`${API_BASE_URL}/checkins/${id}`, {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Authorization': `Token ${getAuthToken()}` 'Authorization': `Token ${getAuthToken()}`
} }
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
;
if (response.ok) { if (response.ok) {
const row = document.querySelector(`tr[data-id="${id}"]`); const row = document.querySelector(`tr[data-id="${id}"]`);
@ -742,11 +736,11 @@
function calculatePointsForCheckin(checkin) { function calculatePointsForCheckin(checkin) {
let points = 0; let points = 0;
if (checkin.validate_location) { if (checkin.validate_location) {
if(checkin.buy_flag){ if(checkin.buy_flag){
points += Number(checkin.buy_point) || 0; points += Number(checkin.buy_point) || 0;
}else{ }else{
points += Number(checkin.checkin_point) || 0; points += Number(checkin.checkin_point) || 0;
} }
} }
return points; return points;
} }
@ -758,19 +752,19 @@
const pointCell = tr.querySelector('.point-value'); const pointCell = tr.querySelector('.point-value');
const cpNumber = tr.dataset.cpNumber; const cpNumber = tr.dataset.cpNumber;
fetch(`${API_BASE_URL}/location/${cpNumber}/`, fetch(`${API_BASE_URL}/location/${cpNumber}/`,{
headers: { headers: {
'Authorization': `Token ${getAuthToken()}` 'Authorization': `Token ${getAuthToken()}`
} }
) })
.then(response => response.json()) .then(response => response.json())
.then(location => { .then(location => {
const points = checkbox.checked ? location.checkin_point : 0; const points = checkbox.checked ? location.checkin_point : 0;
pointCell.textContent = points; pointCell.textContent = points;
calculatePoints(); // 総合ポイントの計算 calculatePoints(); // 総合ポイントの計算
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
;
} }
// 審査チェックボックス更新関数 // 審査チェックボックス更新関数
@ -785,11 +779,11 @@
points: 0 points: 0
}; };
fetch(`${API_BASE_URL}/location/${cpNumber}/`, fetch(`${API_BASE_URL}/location/${cpNumber}/`,{
headers: { headers: {
'Authorization': `Token ${getAuthToken()}` 'Authorization': `Token ${getAuthToken()}`
} }
) })
.then(response => response.json()) .then(response => response.json())
.then(location => { .then(location => {
if (checkin.validate_location) { if (checkin.validate_location) {
@ -811,8 +805,8 @@
// APIに更新を送信 // APIに更新を送信
// updateCheckinOnServer(cpNumber, checkin); // updateCheckinOnServer(cpNumber, checkin);
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
;
} }
// 買い物チェックボックス更新関数 // 買い物チェックボックス更新関数
@ -821,19 +815,18 @@
const pointCell = tr.querySelector('.point-value'); const pointCell = tr.querySelector('.point-value');
const cpNumber = tr.dataset.cpNumber; const cpNumber = tr.dataset.cpNumber;
fetch(`${API_BASE_URL}/location/${cpNumber}/`, fetch(`${API_BASE_URL}/location/${cpNumber}/`,{
headers: { headers: {
'Authorization': `Token ${getAuthToken()}` 'Authorization': `Token ${getAuthToken()}`
} }
) })
.then(response => response.json()) .then(response => response.json())
.then(location => { .then(location => {
const points = checkbox.checked ? location.buy_point : 0; const points = checkbox.checked ? location.buy_point : 0;
pointCell.textContent = points; pointCell.textContent = points;
calculatePoints(); // 総合ポイントの計算 calculatePoints(); // 総合ポイントの計算
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
;
} }
// 買い物チェックボックス更新関数 // 買い物チェックボックス更新関数
@ -848,11 +841,11 @@
points: 0 points: 0
}; };
fetch(`${API_BASE_URL}/location/${cpNumber}/`, fetch(`${API_BASE_URL}/location/${cpNumber}/`,{
headers: { headers: {
'Authorization': `Token ${getAuthToken()}` 'Authorization': `Token ${getAuthToken()}`
} }
) })
.then(response => response.json()) .then(response => response.json())
.then(location => { .then(location => {
if (checkin.validate_location) { if (checkin.validate_location) {
@ -867,8 +860,7 @@
pointCell.textContent = checkin.points; pointCell.textContent = checkin.points;
calculatePoints(); // 総合ポイントの計算 calculatePoints(); // 総合ポイントの計算
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
;
} }
// 画像拡大表示用のモーダル関数 // 画像拡大表示用のモーダル関数
@ -942,8 +934,7 @@
loadTeamData(currentZekkenNumber,eventCode); // チームデータのロード loadTeamData(currentZekkenNumber,eventCode); // チームデータのロード
closeModal(); closeModal();
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
;
} }
function closeModal() { function closeModal() {
@ -958,13 +949,13 @@
}); });
} }
// 総合ポイントの計算 // 総合ポイントの計算
function calculatePoints() { function calculatePoints() {
const rows = Array.from(document.getElementById('checkinList').children); const rows = Array.from(document.getElementById('checkinList').children);
let totalPoints = 0; // チェックインポイントの合計をクリア let totalPoints = 0; // チェックインポイントの合計をクリア
let buyPoints = 0; // 買い物ポイントの合計をクリア let buyPoints = 0; // 買い物ポイントの合計をクリア
// 各行のチェックインポイント及び買い物ポイントを合算 // 各行のチェックインポイント及び買い物ポイントを合算
rows.forEach(row => { rows.forEach(row => {
const points = parseInt(row.children[4].textContent); const points = parseInt(row.children[4].textContent);
if (!isNaN(points)) { if (!isNaN(points)) {
@ -975,13 +966,13 @@
} }
}); });
// 遅刻ポイントの計算=ゴール時刻がEventのゴール時刻を超えていたら分につき-50点を加算する。 // 遅刻ポイントの計算=ゴール時刻がEventのゴール時刻を超えていたら分につき-50点を加算する。
const latePoints = parseInt(document.getElementById('latePoints').textContent) || 0; const latePoints = parseInt(document.getElementById('latePoints').textContent) || 0;
// 総合得点を計算 // 総合得点を計算
const finalPoints = totalPoints + buyPoints - latePoints; const finalPoints = totalPoints + buyPoints - latePoints;
// 判定を更新。順位を表示、ゴール時刻を15分経過したら失格 // 判定を更新。順位を表示、ゴール時刻を15分経過したら失格
document.getElementById('totalPoints').textContent = totalPoints; document.getElementById('totalPoints').textContent = totalPoints;
document.getElementById('buyPoints').textContent = buyPoints; document.getElementById('buyPoints').textContent = buyPoints;
@ -1007,15 +998,15 @@
'Authorization': `Token ${getAuthToken()}` 'Authorization': `Token ${getAuthToken()}`
}, },
body: JSON.stringify(updates) body: JSON.stringify(updates)
}).then(response => { })
.then(response => {
if (response.ok) { if (response.ok) {
alert('保存しました'); alert('保存しました');
} else { } else {
alert('保存に失敗しました'); alert('保存に失敗しました');
} }
}) })
.catch(error => handleApiError(error)); .catch(error => handleApiError(error));
;
} }
// エラーハンドリング関数 // エラーハンドリング関数