Add timezone support to all reports pages

- Add timezone selector with auto-detection of browser local timezone
- Add manual timezone selection options for major world timezones
- Implement client-side timezone conversion using JavaScript Intl.DateTimeFormat
- Update all datetime displays to use data-utc-datetime attribute for automatic conversion
- All reports pages now support timezone filtering and display
- Timezone options: Auto (Browser Local), UTC, and 14 major world timezones
parent 6a24111a
...@@ -1554,6 +1554,7 @@ def reports(): ...@@ -1554,6 +1554,7 @@ def reports():
sort_by = request.args.get('sort_by', 'sync_timestamp') sort_by = request.args.get('sort_by', 'sync_timestamp')
sort_order = request.args.get('sort_order', 'desc') sort_order = request.args.get('sort_order', 'desc')
export_format = request.args.get('export', '').strip() export_format = request.args.get('export', '').strip()
timezone_filter = request.args.get('timezone', 'auto').strip()
# Pagination # Pagination
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
...@@ -1835,7 +1836,8 @@ def reports(): ...@@ -1835,7 +1836,8 @@ def reports():
'end_time': end_time_filter, 'end_time': end_time_filter,
'sort_by': sort_by, 'sort_by': sort_by,
'sort_order': sort_order, 'sort_order': sort_order,
'per_page': per_page 'per_page': per_page,
'timezone': timezone_filter
}) })
except Exception as e: except Exception as e:
...@@ -1860,7 +1862,8 @@ def reports(): ...@@ -1860,7 +1862,8 @@ def reports():
'end_time': '', 'end_time': '',
'sort_by': 'sync_timestamp', 'sort_by': 'sync_timestamp',
'sort_order': 'desc', 'sort_order': 'desc',
'per_page': 50 'per_page': 50,
'timezone': 'auto'
}) })
@csrf.exempt @csrf.exempt
...@@ -2453,6 +2456,7 @@ def client_report_detail(client_id): ...@@ -2453,6 +2456,7 @@ def client_report_detail(client_id):
end_date_filter = request.args.get('end_date', '').strip() end_date_filter = request.args.get('end_date', '').strip()
start_time_filter = request.args.get('start_time', '').strip() start_time_filter = request.args.get('start_time', '').strip()
end_time_filter = request.args.get('end_time', '').strip() end_time_filter = request.args.get('end_time', '').strip()
timezone_filter = request.args.get('timezone', 'auto').strip()
# Pagination # Pagination
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
...@@ -2575,7 +2579,8 @@ def client_report_detail(client_id): ...@@ -2575,7 +2579,8 @@ def client_report_detail(client_id):
'end_date': end_date_filter, 'end_date': end_date_filter,
'start_time': start_time_filter, 'start_time': start_time_filter,
'end_time': end_time_filter, 'end_time': end_time_filter,
'per_page': per_page 'per_page': per_page,
'timezone': timezone_filter
}) })
except Exception as e: except Exception as e:
...@@ -2604,6 +2609,7 @@ def match_report_detail(client_id, match_id): ...@@ -2604,6 +2609,7 @@ def match_report_detail(client_id, match_id):
end_date_filter = request.args.get('end_date', '').strip() end_date_filter = request.args.get('end_date', '').strip()
start_time_filter = request.args.get('start_time', '').strip() start_time_filter = request.args.get('start_time', '').strip()
end_time_filter = request.args.get('end_time', '').strip() end_time_filter = request.args.get('end_time', '').strip()
timezone_filter = request.args.get('timezone', 'auto').strip()
# Pagination # Pagination
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
...@@ -2718,7 +2724,8 @@ def match_report_detail(client_id, match_id): ...@@ -2718,7 +2724,8 @@ def match_report_detail(client_id, match_id):
'end_date': end_date_filter, 'end_date': end_date_filter,
'start_time': start_time_filter, 'start_time': start_time_filter,
'end_time': end_time_filter, 'end_time': end_time_filter,
'per_page': per_page 'per_page': per_page,
'timezone': timezone_filter
}) })
except Exception as e: except Exception as e:
...@@ -2739,6 +2746,7 @@ def bet_detail(client_id, match_id, bet_uuid): ...@@ -2739,6 +2746,7 @@ def bet_detail(client_id, match_id, bet_uuid):
end_date_filter = request.args.get('end_date', '').strip() end_date_filter = request.args.get('end_date', '').strip()
start_time_filter = request.args.get('start_time', '').strip() start_time_filter = request.args.get('start_time', '').strip()
end_time_filter = request.args.get('end_time', '').strip() end_time_filter = request.args.get('end_time', '').strip()
timezone_filter = request.args.get('timezone', 'auto').strip()
# Check if user has access to this client # Check if user has access to this client
if current_user.is_admin: if current_user.is_admin:
...@@ -2781,7 +2789,8 @@ def bet_detail(client_id, match_id, bet_uuid): ...@@ -2781,7 +2789,8 @@ def bet_detail(client_id, match_id, bet_uuid):
'start_date': start_date_filter, 'start_date': start_date_filter,
'end_date': end_date_filter, 'end_date': end_date_filter,
'start_time': start_time_filter, 'start_time': start_time_filter,
'end_time': end_time_filter 'end_time': end_time_filter,
'timezone': timezone_filter
}) })
except Exception as e: except Exception as e:
......
...@@ -203,7 +203,9 @@ ...@@ -203,7 +203,9 @@
<div class="card bg-gradient-warning text-white mb-3 shadow-sm border-0 h-100"> <div class="card bg-gradient-warning text-white mb-3 shadow-sm border-0 h-100">
<div class="card-body"> <div class="card-body">
<h6 class="card-title mb-1 text-white-50">Bet DateTime</h6> <h6 class="card-title mb-1 text-white-50">Bet DateTime</h6>
<h5 class="mb-0 fw-bold">{{ bet.bet_datetime.strftime('%Y-%m-%d %H:%M:%S') if bet.bet_datetime else '' }}</h5> <h5 class="mb-0 fw-bold datetime-display" data-utc-datetime="{{ bet.bet_datetime.isoformat() if bet.bet_datetime else '' }}">
{{ bet.bet_datetime.strftime('%Y-%m-%d %H:%M:%S') if bet.bet_datetime else '' }}
</h5>
</div> </div>
</div> </div>
</div> </div>
...@@ -211,8 +213,27 @@ ...@@ -211,8 +213,27 @@
<!-- Bet Details Table --> <!-- Bet Details Table -->
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
<h5 class="mb-0"><i class="fas fa-list me-2"></i>Bet Details</h5> <h5 class="mb-0"><i class="fas fa-list me-2"></i>Bet Details</h5>
<div class="timezone-selector">
<span>Timezone:</span>
<select id="timezone" onchange="changeTimezone()">
<option value="auto" {% if filters.timezone == 'auto' or not filters.timezone %}selected{% endif %}>Auto (Browser Local)</option>
<option value="UTC" {% if filters.timezone == 'UTC' %}selected{% endif %}>UTC</option>
<option value="America/New_York" {% if filters.timezone == 'America/New_York' %}selected{% endif %}>New York (EST/EDT)</option>
<option value="America/Los_Angeles" {% if filters.timezone == 'America/Los_Angeles' %}selected{% endif %}>Los Angeles (PST/PDT)</option>
<option value="America/Chicago" {% if filters.timezone == 'America/Chicago' %}selected{% endif %}>Chicago (CST/CDT)</option>
<option value="Europe/London" {% if filters.timezone == 'Europe/London' %}selected{% endif %}>London (GMT/BST)</option>
<option value="Europe/Paris" {% if filters.timezone == 'Europe/Paris' %}selected{% endif %}>Paris (CET/CEST)</option>
<option value="Europe/Berlin" {% if filters.timezone == 'Europe/Berlin' %}selected{% endif %}>Berlin (CET/CEST)</option>
<option value="Asia/Tokyo" {% if filters.timezone == 'Asia/Tokyo' %}selected{% endif %}>Tokyo (JST)</option>
<option value="Asia/Shanghai" {% if filters.timezone == 'Asia/Shanghai' %}selected{% endif %}>Shanghai (CST)</option>
<option value="Asia/Dubai" {% if filters.timezone == 'Asia/Dubai' %}selected{% endif %}>Dubai (GST)</option>
<option value="Asia/Singapore" {% if filters.timezone == 'Asia/Singapore' %}selected{% endif %}>Singapore (SGT)</option>
<option value="Australia/Sydney" {% if filters.timezone == 'Australia/Sydney' %}selected{% endif %}>Sydney (AEST/AEDT)</option>
<option value="Pacific/Auckland" {% if filters.timezone == 'Pacific/Auckland' %}selected{% endif %}>Auckland (NZST/NZDT)</option>
</select>
</div>
</div> </div>
<div class="card-body"> <div class="card-body">
{% if bet_details %} {% if bet_details %}
...@@ -264,4 +285,64 @@ ...@@ -264,4 +285,64 @@
</div> </div>
</div> </div>
</div> </div>
{% block extra_js %}
<script>
function changeTimezone() {
const timezone = document.getElementById('timezone').value;
const url = new URL(window.location.href);
url.searchParams.set('timezone', timezone);
window.location.href = url.toString();
}
function convertToTimezone(utcString, timezone) {
if (!utcString) return '';
try {
const date = new Date(utcString);
const options = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: timezone
};
return new Intl.DateTimeFormat('en-US', options).format(date);
} catch (e) {
console.error('Error converting timezone:', e);
return utcString;
}
}
function updateTimezoneDisplays() {
const timezoneSelect = document.getElementById('timezone');
let timezone = timezoneSelect ? timezoneSelect.value : 'auto';
// If auto, use browser's local timezone
if (timezone === 'auto') {
try {
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (e) {
console.error('Error detecting timezone:', e);
timezone = 'UTC';
}
}
// Update all datetime displays
const datetimeDisplays = document.querySelectorAll('.datetime-display');
datetimeDisplays.forEach(display => {
const utcDatetime = display.getAttribute('data-utc-datetime');
if (utcDatetime) {
const converted = convertToTimezone(utcDatetime, timezone);
display.textContent = converted;
}
});
}
// Run on page load
document.addEventListener('DOMContentLoaded', function() {
updateTimezoneDisplays();
});
</script>
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -315,6 +315,31 @@ ...@@ -315,6 +315,31 @@
</div> </div>
</div> </div>
<!-- Timezone Selection -->
<div class="row mb-3">
<div class="col-md-4">
<label for="timezone" class="form-label fw-semibold">
<i class="fas fa-globe me-1"></i> Timezone
</label>
<select class="form-select" id="timezone" name="timezone">
<option value="auto" {% if filters.timezone == 'auto' or not filters.timezone %}selected{% endif %}>Auto (Browser Local)</option>
<option value="UTC" {% if filters.timezone == 'UTC' %}selected{% endif %}>UTC</option>
<option value="America/New_York" {% if filters.timezone == 'America/New_York' %}selected{% endif %}>America/New York (EST/EDT)</option>
<option value="America/Los_Angeles" {% if filters.timezone == 'America/Los_Angeles' %}selected{% endif %}>America/Los Angeles (PST/PDT)</option>
<option value="America/Chicago" {% if filters.timezone == 'America/Chicago' %}selected{% endif %}>America/Chicago (CST/CDT)</option>
<option value="Europe/London" {% if filters.timezone == 'Europe/London' %}selected{% endif %}>Europe/London (GMT/BST)</option>
<option value="Europe/Paris" {% if filters.timezone == 'Europe/Paris' %}selected{% endif %}>Europe/Paris (CET/CEST)</option>
<option value="Europe/Berlin" {% if filters.timezone == 'Europe/Berlin' %}selected{% endif %}>Europe/Berlin (CET/CEST)</option>
<option value="Asia/Tokyo" {% if filters.timezone == 'Asia/Tokyo' %}selected{% endif %}>Asia/Tokyo (JST)</option>
<option value="Asia/Shanghai" {% if filters.timezone == 'Asia/Shanghai' %}selected{% endif %}>Asia/Shanghai (CST)</option>
<option value="Asia/Singapore" {% if filters.timezone == 'Asia/Singapore' %}selected{% endif %}>Asia/Singapore (SGT)</option>
<option value="Asia/Dubai" {% if filters.timezone == 'Asia/Dubai' %}selected{% endif %}>Asia/Dubai (GST)</option>
<option value="Australia/Sydney" {% if filters.timezone == 'Australia/Sydney' %}selected{% endif %}>Australia/Sydney (AEST/AEDT)</option>
<option value="Africa/Johannesburg" {% if filters.timezone == 'Africa/Johannesburg' %}selected{% endif %}>Africa/Johannesburg (SAST)</option>
</select>
</div>
</div>
<!-- Time Filters (Always Visible) --> <!-- Time Filters (Always Visible) -->
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-3"> <div class="col-md-3">
...@@ -407,7 +432,9 @@ ...@@ -407,7 +432,9 @@
<td>{{ report.match_id }}</td> <td>{{ report.match_id }}</td>
<td>{{ report.match_number }}</td> <td>{{ report.match_number }}</td>
<td><code>{{ report.fixture_id }}</code></td> <td><code>{{ report.fixture_id }}</code></td>
<td>{{ report.match_datetime.strftime('%Y-%m-%d %H:%M:%S') if report.match_datetime else '' }}</td> <td class="datetime-display" data-utc-datetime="{{ report.match_datetime.isoformat() if report.match_datetime else '' }}">
{{ report.match_datetime.strftime('%Y-%m-%d %H:%M:%S') if report.match_datetime else '' }}
</td>
<td class="text-center">{{ report.total_bets }}</td> <td class="text-center">{{ report.total_bets }}</td>
<td class="text-center text-success">{{ report.winning_bets }}</td> <td class="text-center text-success">{{ report.winning_bets }}</td>
<td class="text-center text-danger">{{ report.losing_bets }}</td> <td class="text-center text-danger">{{ report.losing_bets }}</td>
...@@ -525,6 +552,89 @@ function changePerPage() { ...@@ -525,6 +552,89 @@ function changePerPage() {
url.searchParams.set('page', '1'); url.searchParams.set('page', '1');
window.location.href = url.toString(); window.location.href = url.toString();
} }
// Convert UTC datetime string to selected timezone
function convertToTimezone(utcString, timezone) {
if (!utcString) return '';
try {
const date = new Date(utcString);
const options = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: timezone
};
return new Intl.DateTimeFormat('en-US', options).format(date);
} catch (e) {
console.error('Error converting timezone:', e);
return utcString;
}
}
// Update all datetime displays to selected timezone
function updateTimezoneDisplays() {
const timezoneSelect = document.getElementById('timezone');
if (!timezoneSelect) return;
let timezone = timezoneSelect.value;
// If 'auto', use browser timezone
if (timezone === 'auto') {
try {
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (e) {
console.log('Could not detect browser timezone:', e);
timezone = 'UTC';
}
}
// Store timezone in localStorage for persistence
localStorage.setItem('selectedTimezone', timezone);
// Find all elements with data-utc-datetime attribute and convert them
const datetimeElements = document.querySelectorAll('[data-utc-datetime]');
datetimeElements.forEach(element => {
const utcString = element.getAttribute('data-utc-datetime');
if (utcString) {
element.textContent = convertToTimezone(utcString, timezone);
}
});
}
// Auto-detect and set browser timezone on page load
document.addEventListener('DOMContentLoaded', function() {
const timezoneSelect = document.getElementById('timezone');
if (timezoneSelect) {
// Try to get the browser's timezone
try {
const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
// Check if the browser timezone is in our options
const options = Array.from(timezoneSelect.options).map(opt => opt.value);
if (options.includes(browserTimezone)) {
// Only set to browser timezone if current selection is 'auto' or empty
if (timezoneSelect.value === 'auto' || !timezoneSelect.value) {
timezoneSelect.value = browserTimezone;
}
}
} catch (e) {
console.log('Could not detect browser timezone:', e);
}
// Add event listener for timezone change
timezoneSelect.addEventListener('change', function() {
updateTimezoneDisplays();
});
// Update timezone displays on page load
updateTimezoneDisplays();
}
});
</script> </script>
{% endblock %} {% endblock %}
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -266,7 +266,10 @@ ...@@ -266,7 +266,10 @@
<strong>Fixture ID:</strong> <code>{{ match_report.fixture_id }}</code> <strong>Fixture ID:</strong> <code>{{ match_report.fixture_id }}</code>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<strong>Match DateTime:</strong> {{ match_report.match_datetime.strftime('%Y-%m-%d %H:%M:%S') if match_report.match_datetime else '' }} <strong>Match DateTime:</strong>
<span class="datetime-display" data-utc-datetime="{{ match_report.match_datetime.isoformat() if match_report.match_datetime else '' }}">
{{ match_report.match_datetime.strftime('%Y-%m-%d %H:%M:%S') if match_report.match_datetime else '' }}
</span>
</div> </div>
<div class="col-md-6 mb-3"> <div class="col-md-6 mb-3">
<strong>Actual Result:</strong> {{ match_report.actual_result }} <strong>Actual Result:</strong> {{ match_report.actual_result }}
...@@ -291,10 +294,11 @@ ...@@ -291,10 +294,11 @@
<!-- Bets Table --> <!-- Bets Table -->
<div class="card"> <div class="card">
<div class="card-header d-flex justify-content-between align-items-center"> <div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
<h5 class="mb-0 fw-semibold"> <h5 class="mb-0 fw-semibold">
<i class="fas fa-list me-2 text-primary"></i>Bets for this Match <i class="fas fa-list me-2 text-primary"></i>Bets for this Match
</h5> </h5>
<div class="d-flex gap-3 align-items-center flex-wrap">
<div class="per-page-selector"> <div class="per-page-selector">
<span>Show:</span> <span>Show:</span>
<select id="perPage" onchange="changePerPage()"> <select id="perPage" onchange="changePerPage()">
...@@ -305,6 +309,26 @@ ...@@ -305,6 +309,26 @@
</select> </select>
<span>per page</span> <span>per page</span>
</div> </div>
<div class="timezone-selector">
<span>Timezone:</span>
<select id="timezone" onchange="changeTimezone()">
<option value="auto" {% if filters.timezone == 'auto' or not filters.timezone %}selected{% endif %}>Auto (Browser Local)</option>
<option value="UTC" {% if filters.timezone == 'UTC' %}selected{% endif %}>UTC</option>
<option value="America/New_York" {% if filters.timezone == 'America/New_York' %}selected{% endif %}>New York (EST/EDT)</option>
<option value="America/Los_Angeles" {% if filters.timezone == 'America/Los_Angeles' %}selected{% endif %}>Los Angeles (PST/PDT)</option>
<option value="America/Chicago" {% if filters.timezone == 'America/Chicago' %}selected{% endif %}>Chicago (CST/CDT)</option>
<option value="Europe/London" {% if filters.timezone == 'Europe/London' %}selected{% endif %}>London (GMT/BST)</option>
<option value="Europe/Paris" {% if filters.timezone == 'Europe/Paris' %}selected{% endif %}>Paris (CET/CEST)</option>
<option value="Europe/Berlin" {% if filters.timezone == 'Europe/Berlin' %}selected{% endif %}>Berlin (CET/CEST)</option>
<option value="Asia/Tokyo" {% if filters.timezone == 'Asia/Tokyo' %}selected{% endif %}>Tokyo (JST)</option>
<option value="Asia/Shanghai" {% if filters.timezone == 'Asia/Shanghai' %}selected{% endif %}>Shanghai (CST)</option>
<option value="Asia/Dubai" {% if filters.timezone == 'Asia/Dubai' %}selected{% endif %}>Dubai (GST)</option>
<option value="Asia/Singapore" {% if filters.timezone == 'Asia/Singapore' %}selected{% endif %}>Singapore (SGT)</option>
<option value="Australia/Sydney" {% if filters.timezone == 'Australia/Sydney' %}selected{% endif %}>Sydney (AEST/AEDT)</option>
<option value="Pacific/Auckland" {% if filters.timezone == 'Pacific/Auckland' %}selected{% endif %}>Auckland (NZST/NZDT)</option>
</select>
</div>
</div>
</div> </div>
<div class="card-body"> <div class="card-body">
{% if bets %} {% if bets %}
...@@ -326,7 +350,9 @@ ...@@ -326,7 +350,9 @@
{% for bet in bets %} {% for bet in bets %}
<tr> <tr>
<td><code>{{ bet.uuid }}</code></td> <td><code>{{ bet.uuid }}</code></td>
<td>{{ bet.bet_datetime.strftime('%Y-%m-%d %H:%M:%S') if bet.bet_datetime else '' }}</td> <td class="datetime-display" data-utc-datetime="{{ bet.bet_datetime.isoformat() if bet.bet_datetime else '' }}">
{{ bet.bet_datetime.strftime('%Y-%m-%d %H:%M:%S') if bet.bet_datetime else '' }}
</td>
<td>{{ bet.match_number }}</td> <td>{{ bet.match_number }}</td>
<td class="text-end">{{ "{:,.2f}".format(bet.total_amount) if bet.total_amount else '0.00' }}</td> <td class="text-end">{{ "{:,.2f}".format(bet.total_amount) if bet.total_amount else '0.00' }}</td>
<td class="text-center">{{ bet.bet_count }}</td> <td class="text-center">{{ bet.bet_count }}</td>
...@@ -418,6 +444,64 @@ function changePerPage() { ...@@ -418,6 +444,64 @@ function changePerPage() {
url.searchParams.set('page', '1'); url.searchParams.set('page', '1');
window.location.href = url.toString(); window.location.href = url.toString();
} }
function changeTimezone() {
const timezone = document.getElementById('timezone').value;
const url = new URL(window.location.href);
url.searchParams.set('timezone', timezone);
window.location.href = url.toString();
}
function convertToTimezone(utcString, timezone) {
if (!utcString) return '';
try {
const date = new Date(utcString);
const options = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: timezone
};
return new Intl.DateTimeFormat('en-US', options).format(date);
} catch (e) {
console.error('Error converting timezone:', e);
return utcString;
}
}
function updateTimezoneDisplays() {
const timezoneSelect = document.getElementById('timezone');
let timezone = timezoneSelect ? timezoneSelect.value : 'auto';
// If auto, use browser's local timezone
if (timezone === 'auto') {
try {
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (e) {
console.error('Error detecting timezone:', e);
timezone = 'UTC';
}
}
// Update all datetime displays
const datetimeDisplays = document.querySelectorAll('.datetime-display');
datetimeDisplays.forEach(display => {
const utcDatetime = display.getAttribute('data-utc-datetime');
if (utcDatetime) {
const converted = convertToTimezone(utcDatetime, timezone);
display.textContent = converted;
}
});
}
// Run on page load
document.addEventListener('DOMContentLoaded', function() {
updateTimezoneDisplays();
});
</script> </script>
{% endblock %} {% endblock %}
{% endblock %} {% endblock %}
\ No newline at end of file
...@@ -334,6 +334,31 @@ ...@@ -334,6 +334,31 @@
</div> </div>
</div> </div>
<!-- Timezone Selection -->
<div class="row mb-3">
<div class="col-md-4">
<label for="timezone" class="form-label fw-semibold">
<i class="fas fa-globe me-1"></i> Timezone
</label>
<select class="form-select" id="timezone" name="timezone">
<option value="auto" {% if filters.timezone == 'auto' or not filters.timezone %}selected{% endif %}>Auto (Browser Local)</option>
<option value="UTC" {% if filters.timezone == 'UTC' %}selected{% endif %}>UTC</option>
<option value="America/New_York" {% if filters.timezone == 'America/New_York' %}selected{% endif %}>America/New York (EST/EDT)</option>
<option value="America/Los_Angeles" {% if filters.timezone == 'America/Los_Angeles' %}selected{% endif %}>America/Los Angeles (PST/PDT)</option>
<option value="America/Chicago" {% if filters.timezone == 'America/Chicago' %}selected{% endif %}>America/Chicago (CST/CDT)</option>
<option value="Europe/London" {% if filters.timezone == 'Europe/London' %}selected{% endif %}>Europe/London (GMT/BST)</option>
<option value="Europe/Paris" {% if filters.timezone == 'Europe/Paris' %}selected{% endif %}>Europe/Paris (CET/CEST)</option>
<option value="Europe/Berlin" {% if filters.timezone == 'Europe/Berlin' %}selected{% endif %}>Europe/Berlin (CET/CEST)</option>
<option value="Asia/Tokyo" {% if filters.timezone == 'Asia/Tokyo' %}selected{% endif %}>Asia/Tokyo (JST)</option>
<option value="Asia/Shanghai" {% if filters.timezone == 'Asia/Shanghai' %}selected{% endif %}>Asia/Shanghai (CST)</option>
<option value="Asia/Singapore" {% if filters.timezone == 'Asia/Singapore' %}selected{% endif %}>Asia/Singapore (SGT)</option>
<option value="Asia/Dubai" {% if filters.timezone == 'Asia/Dubai' %}selected{% endif %}>Asia/Dubai (GST)</option>
<option value="Australia/Sydney" {% if filters.timezone == 'Australia/Sydney' %}selected{% endif %}>Australia/Sydney (AEST/AEDT)</option>
<option value="Africa/Johannesburg" {% if filters.timezone == 'Africa/Johannesburg' %}selected{% endif %}>Africa/Johannesburg (SAST)</option>
</select>
</div>
</div>
<!-- Time Filters (Always Visible) --> <!-- Time Filters (Always Visible) -->
<div class="row mb-3"> <div class="row mb-3">
<div class="col-md-6"> <div class="col-md-6">
...@@ -540,6 +565,89 @@ function changePerPage() { ...@@ -540,6 +565,89 @@ function changePerPage() {
url.searchParams.set('page', '1'); url.searchParams.set('page', '1');
window.location.href = url.toString(); window.location.href = url.toString();
} }
// Convert UTC datetime string to selected timezone
function convertToTimezone(utcString, timezone) {
if (!utcString) return '';
try {
const date = new Date(utcString);
const options = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: timezone
};
return new Intl.DateTimeFormat('en-US', options).format(date);
} catch (e) {
console.error('Error converting timezone:', e);
return utcString;
}
}
// Update all datetime displays to selected timezone
function updateTimezoneDisplays() {
const timezoneSelect = document.getElementById('timezone');
if (!timezoneSelect) return;
let timezone = timezoneSelect.value;
// If 'auto', use browser timezone
if (timezone === 'auto') {
try {
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (e) {
console.log('Could not detect browser timezone:', e);
timezone = 'UTC';
}
}
// Store timezone in localStorage for persistence
localStorage.setItem('selectedTimezone', timezone);
// Find all elements with data-utc-datetime attribute and convert them
const datetimeElements = document.querySelectorAll('[data-utc-datetime]');
datetimeElements.forEach(element => {
const utcString = element.getAttribute('data-utc-datetime');
if (utcString) {
element.textContent = convertToTimezone(utcString, timezone);
}
});
}
// Auto-detect and set browser timezone on page load
document.addEventListener('DOMContentLoaded', function() {
const timezoneSelect = document.getElementById('timezone');
if (timezoneSelect) {
// Try to get the browser's timezone
try {
const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
// Check if the browser timezone is in our options
const options = Array.from(timezoneSelect.options).map(opt => opt.value);
if (options.includes(browserTimezone)) {
// Only set to browser timezone if current selection is 'auto' or empty
if (timezoneSelect.value === 'auto' || !timezoneSelect.value) {
timezoneSelect.value = browserTimezone;
}
}
} catch (e) {
console.log('Could not detect browser timezone:', e);
}
// Add event listener for timezone change
timezoneSelect.addEventListener('change', function() {
updateTimezoneDisplays();
});
// Update timezone displays on page load
updateTimezoneDisplays();
}
});
</script> </script>
{% endblock %} {% endblock %}
{% endblock %} {% endblock %}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment