supervisor step3
This commit is contained in:
171
supervisor/html/js/main.js
Normal file
171
supervisor/html/js/main.js
Normal file
@ -0,0 +1,171 @@
|
||||
// js/main.js
|
||||
|
||||
// EventBus
|
||||
const EventBus = {
|
||||
listeners: {},
|
||||
|
||||
on(event, callback) {
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
this.listeners[event].push(callback);
|
||||
},
|
||||
|
||||
emit(event, data) {
|
||||
if (this.listeners[event]) {
|
||||
this.listeners[event].forEach(callback => callback(data));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// NotificationService
|
||||
class NotificationService {
|
||||
constructor() {
|
||||
this.toastElement = document.getElementById('toast');
|
||||
}
|
||||
|
||||
showMessage(message, type = 'info') {
|
||||
this.toastElement.textContent = message;
|
||||
this.toastElement.className = `fixed bottom-4 right-4 px-6 py-3 rounded shadow-lg ${
|
||||
type === 'error' ? 'bg-red-500' : 'bg-green-500'
|
||||
} text-white`;
|
||||
|
||||
this.toastElement.classList.remove('hidden');
|
||||
|
||||
setTimeout(() => {
|
||||
this.toastElement.classList.add('hidden');
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
showError(message) {
|
||||
this.showMessage(message, 'error');
|
||||
}
|
||||
|
||||
showSuccess(message) {
|
||||
this.showMessage(message, 'success');
|
||||
}
|
||||
}
|
||||
|
||||
// ApiClient
|
||||
class ApiClient {
|
||||
constructor({ baseUrl, authToken, csrfToken }) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.authToken = authToken;
|
||||
this.csrfToken = csrfToken;
|
||||
}
|
||||
|
||||
async request(endpoint, options = {}) {
|
||||
const url = `${this.baseUrl}${endpoint}`;
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Token ${this.authToken}`,
|
||||
'X-CSRF-Token': this.csrfToken
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
...options,
|
||||
headers: {
|
||||
...headers,
|
||||
...options.headers
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (contentType && contentType.includes("application/json")) {
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
return await response.text();
|
||||
} catch (error) {
|
||||
console.error('API request failed:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// API methods
|
||||
async getEvents() {
|
||||
return this.request('/new-events/');
|
||||
}
|
||||
|
||||
async getZekkenNumbers(eventCode) {
|
||||
return this.request(`/zekken_numbers/${eventCode}`);
|
||||
}
|
||||
|
||||
async getTeamInfo(zekkenNumber) {
|
||||
return this.request(`/team_info/${zekkenNumber}/`);
|
||||
}
|
||||
|
||||
// ... その他のAPI methods
|
||||
}
|
||||
|
||||
// PointsCalculator
|
||||
class PointsCalculator {
|
||||
calculate({ checkins, latePoints = 0 }) {
|
||||
const totalPoints = this.calculateTotalPoints(checkins);
|
||||
const buyPoints = this.calculateBuyPoints(checkins);
|
||||
|
||||
return {
|
||||
totalPoints,
|
||||
buyPoints,
|
||||
latePoints,
|
||||
finalPoints: totalPoints + buyPoints + latePoints
|
||||
};
|
||||
}
|
||||
|
||||
calculateTotalPoints(checkins) {
|
||||
return checkins.reduce((total, checkin) => {
|
||||
if (checkin.validate_location && !checkin.buy_flag) {
|
||||
return total + (checkin.checkin_point || 0);
|
||||
}
|
||||
return total;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
calculateBuyPoints(checkins) {
|
||||
return checkins.reduce((total, checkin) => {
|
||||
if (checkin.validate_location && checkin.buy_flag) {
|
||||
return total + (checkin.buy_point || 0);
|
||||
}
|
||||
return total;
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// SupervisorPanel - メインアプリケーションクラス
|
||||
class SupervisorPanel {
|
||||
constructor(options) {
|
||||
this.element = options.element;
|
||||
this.apiClient = new ApiClient(options.apiConfig);
|
||||
this.notification = new NotificationService();
|
||||
this.pointsCalculator = new PointsCalculator();
|
||||
this.eventBus = EventBus;
|
||||
|
||||
this.state = {
|
||||
currentEvent: null,
|
||||
currentZekken: null,
|
||||
teamData: null,
|
||||
checkins: []
|
||||
};
|
||||
}
|
||||
|
||||
// ... SupervisorPanelの実装 ...
|
||||
}
|
||||
|
||||
// アプリケーションの初期化
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const app = new SupervisorPanel({
|
||||
element: document.getElementById('app'),
|
||||
apiConfig: {
|
||||
baseUrl: '/api',
|
||||
authToken: localStorage.getItem('authToken'),
|
||||
csrfToken: document.querySelector('meta[name="csrf-token"]').content
|
||||
}
|
||||
});
|
||||
|
||||
app.initialize();
|
||||
});
|
||||
Reference in New Issue
Block a user