Demande par discord au coach pour confirmer la rencontre Ajout de message automatisé discord pour avertir des nouveaux match et rappel 24h a l'avance
380 lines
15 KiB
HTML
380 lines
15 KiB
HTML
{% extends "layouts/base.html" %}
|
|
{% block title %}Edit Profile - TryoutPro{% endblock %}
|
|
{% block page_title %}Edit Profile{% endblock %}
|
|
{% block breadcrumb %}<span class="breadcrumb">Home / <a href="{{ url_for('users.profile') }}">Profile</a> / Edit</span>{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<form method="POST" action="{{ url_for('users.edit_profile') }}" class="form">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
|
|
<div class="form-row">
|
|
<div class="form-group col-6">
|
|
<label for="full_name">Full Name</label>
|
|
<input type="text" id="full_name" name="full_name" value="{{ user.full_name }}" required>
|
|
</div>
|
|
<div class="form-group col-6">
|
|
<label for="email">Email</label>
|
|
<input type="email" id="email" name="email" value="{{ user.email }}" required>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group col-6">
|
|
<label for="phone">Phone</label>
|
|
<input type="tel" id="phone" name="phone" value="{{ user.phone or '' }}">
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="section-divider">
|
|
<h4 class="section-title"><i class="fas fa-gamepad"></i> E-Sports Profile</h4>
|
|
<p class="text-muted small">Update your competitive gaming profile for tryouts.</p>
|
|
|
|
<div class="form-group">
|
|
<label><i class="fas fa-headset"></i> Games You Play</label>
|
|
<div class="checkbox-grid">
|
|
{% for game in esport_games %}
|
|
{% set games_list = user.get_games_list() %}
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" name="games" value="{{ game }}" {% if game in games_list %}checked{% endif %}>
|
|
<span>{{ game }}</span>
|
|
</label>
|
|
{% endfor %}
|
|
</div>
|
|
<small class="form-text text-muted">Select all games you're signing in for.</small>
|
|
</div>
|
|
|
|
<!-- Gamertag inputs - will be shown when game is selected -->
|
|
<div id="gamertag-section" style="display: none;">
|
|
<hr class="section-divider">
|
|
<h4 class="section-title"><i class="fas fa-chart-line"></i> Gamertags for TRN</h4>
|
|
<p class="text-muted small">Enter your gamertag for each selected game to link to your Tracker Network profile.</p>
|
|
|
|
{% for game in esport_games %}
|
|
{% set gamertag_data = user_gamertags.get(game) %}
|
|
<div class="gamertag-input-row" data-game="{{ game }}" style="display: none; margin-bottom: 15px; padding: 15px; background: #f9fafb; border-radius: 8px;">
|
|
<h5 style="margin-top: 0; margin-bottom: 10px;">{{ game }}</h5>
|
|
<div class="form-row">
|
|
<div class="form-group col-6">
|
|
<label for="gamertag_{{ game }}">Gamertag</label>
|
|
<input type="text" id="gamertag_{{ game }}" name="gamertag_{{ game }}" value="{{ gamertag_data.gamertag if gamertag_data else '' }}" placeholder="Your {{ game }} gamertag">
|
|
</div>
|
|
{% if game_platforms.get(game) %}
|
|
<div class="form-group col-6">
|
|
<label for="platform_{{ game }}">Platform</label>
|
|
<select id="platform_{{ game }}" name="platform_{{ game }}">
|
|
<option value="">Select Platform</option>
|
|
{% for platform in game_platforms[game] %}
|
|
<option value="{{ platform }}" {% if gamertag_data and gamertag_data.platform == platform %}selected{% endif %}>{{ platform }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group col-6">
|
|
<label for="discord_username"><i class="fab fa-discord"></i> Discord Username</label>
|
|
<input type="text" id="discord_username" name="discord_username" value="{{ user.discord_username or '' }}" placeholder="e.g. Name#1234">
|
|
</div>
|
|
<div class="form-group col-6">
|
|
<label for="discord_user_id"><i class="fab fa-discord"></i> Discord User ID <small>(for DMs)</small></label>
|
|
<input type="text" id="discord_user_id" name="discord_user_id" value="{{ user.discord_user_id or '' }}" placeholder="Numeric ID (e.g. 123456789012345678)">
|
|
<small class="text-muted">Enable Developer Mode in Discord → Right-click profile → Copy ID</small>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group col-6">
|
|
<label for="league_os_profile"><i class="fas fa-link"></i> League OS Connection</label>
|
|
<input type="text" id="league_os_profile" name="league_os_profile" value="{{ user.league_os_profile or '' }}" placeholder="League OS profile link or ID">
|
|
</div>
|
|
</div>
|
|
|
|
<hr class="section-divider">
|
|
<h4 class="section-title"><i class="fas fa-lock"></i> Change Password</h4>
|
|
<p class="text-muted small">Leave blank to keep your current password.</p>
|
|
<div class="form-group">
|
|
<label for="password">New Password</label>
|
|
<input type="password" id="password" name="password" placeholder="Enter new password">
|
|
</div>
|
|
|
|
{% if user.role == 'player' %}
|
|
<hr class="section-divider">
|
|
<h4 class="section-title"><i class="fas fa-clock"></i> My Disponibilities</h4>
|
|
<p class="text-muted small">Select your available time blocks for matches (5pm to 12am). Green = selected, Gray = available to select.</p>
|
|
|
|
<div id="disponibilities-grid">
|
|
<p class="text-muted">Loading...</p>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button type="button" class="btn btn-primary" onclick="saveDisponibilities()">
|
|
<i class="fas fa-save"></i> Save Disponibilities
|
|
</button>
|
|
<button type="button" class="btn btn-secondary" onclick="clearDisponibilities()">
|
|
<i class="fas fa-trash"></i> Clear All
|
|
</button>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="form-actions">
|
|
<a href="{{ url_for('users.profile') }}" class="btn btn-secondary">Cancel</a>
|
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.disponibility-grid {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 15px;
|
|
}
|
|
.disponibility-day-row {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 5px;
|
|
}
|
|
.disponibility-day-label {
|
|
width: 100px;
|
|
font-weight: bold;
|
|
}
|
|
.disponibility-time-blocks {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 5px;
|
|
}
|
|
.disponibility-time-block {
|
|
width: 80px;
|
|
height: 32px;
|
|
border-radius: 4px;
|
|
border: 1px solid #d1d5db;
|
|
background: #f3f4f6;
|
|
text-align: center;
|
|
line-height: 32px;
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
user-select: none;
|
|
transition: all 0.2s;
|
|
}
|
|
.disponibility-time-block:hover {
|
|
background: #e5e7eb;
|
|
}
|
|
.disponibility-time-block.selected {
|
|
background: #10b981;
|
|
color: white;
|
|
border-color: #059669;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
var GAME_PLATFORMS = {{ game_platforms|tojson }};
|
|
|
|
// Show/hide gamertag inputs when games are checked
|
|
function toggleGamertagInputs() {
|
|
var selectedGames = [];
|
|
document.querySelectorAll('input[name="games"]:checked').forEach(function(cb) {
|
|
selectedGames.push(cb.value);
|
|
});
|
|
|
|
if (selectedGames.length > 0) {
|
|
document.getElementById('gamertag-section').style.display = 'block';
|
|
} else {
|
|
document.getElementById('gamertag-section').style.display = 'none';
|
|
}
|
|
|
|
document.querySelectorAll('.gamertag-input-row').forEach(function(row) {
|
|
if (selectedGames.includes(row.dataset.game)) {
|
|
row.style.display = 'block';
|
|
} else {
|
|
row.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
// Initialize on page load
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Set up event listeners for game checkboxes
|
|
document.querySelectorAll('input[name="games"]').forEach(function(cb) {
|
|
cb.addEventListener('change', toggleGamertagInputs);
|
|
});
|
|
|
|
// Show gamertag inputs for already selected games
|
|
toggleGamertagInputs();
|
|
|
|
{% if user.role == 'player' %}
|
|
renderDisponibilityGrid();
|
|
{% endif %}
|
|
});
|
|
|
|
{% if user.role == 'player' %}
|
|
// Generate time slots from 5pm (17:00) to 12am (24:00)
|
|
var TIME_SLOTS = [];
|
|
for (var h = 17; h <= 24; h++) {
|
|
for (var m = 0; m < 60; m += 30) {
|
|
if (h === 24 && m > 0) continue;
|
|
var displayHour;
|
|
var displayAmpm;
|
|
if (h === 24) {
|
|
displayHour = 12;
|
|
displayAmpm = 'AM';
|
|
} else if (h > 12) {
|
|
displayHour = h - 12;
|
|
displayAmpm = 'PM';
|
|
} else {
|
|
displayHour = h;
|
|
displayAmpm = 'PM';
|
|
}
|
|
var timeStr = (h < 10 ? '0' : '') + h + ':' + (m < 10 ? '0' : '') + m;
|
|
var displayTime = displayHour + ':' + (m < 10 ? '0' : '') + m + ' ' + displayAmpm;
|
|
TIME_SLOTS.push({ time: timeStr, display: displayTime });
|
|
}
|
|
}
|
|
|
|
var DAYS = [
|
|
{ value: 0, name: 'Monday' },
|
|
{ value: 1, name: 'Tuesday' },
|
|
{ value: 2, name: 'Wednesday' },
|
|
{ value: 3, name: 'Thursday' },
|
|
{ value: 4, name: 'Friday' },
|
|
{ value: 5, name: 'Saturday' },
|
|
{ value: 6, name: 'Sunday' }
|
|
];
|
|
|
|
// Store selected slots: {day: [time, time, ...]}
|
|
var selectedSlots = {};
|
|
|
|
function renderDisponibilityGrid() {
|
|
var grid = document.getElementById('disponibilities-grid');
|
|
grid.innerHTML = '<div style="margin-bottom: 10px;"><strong>Click time blocks to select your available hours</strong></div>';
|
|
|
|
var container = document.createElement('div');
|
|
container.className = 'disponibility-grid';
|
|
|
|
DAYS.forEach(function(day) {
|
|
var dayRow = document.createElement('div');
|
|
dayRow.className = 'disponibility-day-row';
|
|
|
|
var dayLabel = document.createElement('div');
|
|
dayLabel.className = 'disponibility-day-label';
|
|
dayLabel.textContent = day.name;
|
|
dayRow.appendChild(dayLabel);
|
|
|
|
var timeBlocks = document.createElement('div');
|
|
timeBlocks.className = 'disponibility-time-blocks';
|
|
|
|
TIME_SLOTS.forEach(function(slot) {
|
|
var block = document.createElement('div');
|
|
block.className = 'disponibility-time-block';
|
|
block.dataset.day = day.value;
|
|
block.dataset.time = slot.time;
|
|
block.textContent = slot.display;
|
|
block.onclick = function() {
|
|
toggleSlot(day.value, slot.time, block);
|
|
};
|
|
timeBlocks.appendChild(block);
|
|
});
|
|
|
|
dayRow.appendChild(timeBlocks);
|
|
container.appendChild(dayRow);
|
|
});
|
|
|
|
grid.appendChild(container);
|
|
loadMyDisponibilities();
|
|
}
|
|
|
|
function toggleSlot(day, time, element) {
|
|
if (!selectedSlots[day]) selectedSlots[day] = [];
|
|
|
|
var index = selectedSlots[day].indexOf(time);
|
|
if (index > -1) {
|
|
selectedSlots[day].splice(index, 1);
|
|
element.classList.remove('selected');
|
|
} else {
|
|
selectedSlots[day].push(time);
|
|
element.classList.add('selected');
|
|
}
|
|
}
|
|
|
|
function loadMyDisponibilities() {
|
|
fetch('{{ url_for("users.get_my_disponibilities") }}')
|
|
.then(function(response) { return response.json(); })
|
|
.then(function(data) {
|
|
selectedSlots = {};
|
|
|
|
for (var day in data) {
|
|
var slots = data[day];
|
|
slots.forEach(function(slot) {
|
|
selectedSlots[day] = selectedSlots[day] || [];
|
|
selectedSlots[day].push(slot.start_time);
|
|
});
|
|
}
|
|
|
|
document.querySelectorAll('.disponibility-time-block').forEach(function(block) {
|
|
var day = block.dataset.day;
|
|
var time = block.dataset.time;
|
|
if (selectedSlots[day] && selectedSlots[day].indexOf(time) > -1) {
|
|
block.classList.add('selected');
|
|
} else {
|
|
block.classList.remove('selected');
|
|
}
|
|
});
|
|
})
|
|
.catch(function(error) {
|
|
console.error('Error loading disponibilities:', error);
|
|
});
|
|
}
|
|
|
|
function saveDisponibilities() {
|
|
var slots = [];
|
|
for (var day in selectedSlots) {
|
|
selectedSlots[day].forEach(function(time) {
|
|
slots.push({ day_of_week: parseInt(day), start_time: time });
|
|
});
|
|
}
|
|
|
|
fetch('{{ url_for("users.add_disponibilities_bulk") }}', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ slots: slots })
|
|
})
|
|
.then(function(response) { return response.json(); })
|
|
.then(function(data) {
|
|
if (data.success) {
|
|
var msg = document.createElement('div');
|
|
msg.className = 'alert alert-success';
|
|
msg.style.marginTop = '10px';
|
|
msg.innerHTML = '<i class="fas fa-check"></i> Disponibilities saved successfully!';
|
|
document.getElementById('disponibilities-grid').appendChild(msg);
|
|
setTimeout(function() { msg.remove(); }, 3000);
|
|
}
|
|
})
|
|
.catch(function(error) {
|
|
console.error('Error saving disponibilities:', error);
|
|
});
|
|
}
|
|
|
|
function clearDisponibilities() {
|
|
if (!confirm('Are you sure you want to clear all your disponibilities?')) return;
|
|
|
|
fetch('{{ url_for("users.clear_disponibilities") }}', {
|
|
method: 'POST'
|
|
})
|
|
.then(function(response) { return response.json(); })
|
|
.then(function(data) {
|
|
if (data.success) {
|
|
selectedSlots = {};
|
|
document.querySelectorAll('.disponibility-time-block').forEach(function(block) {
|
|
block.classList.remove('selected');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
{% endif %}
|
|
</script>
|
|
{% endblock %} |