102 lines
3.8 KiB
HTML
102 lines
3.8 KiB
HTML
|
|
{% extends "base.html" %}
|
||
|
|
{% block title %}Settings — diora{% endblock %}
|
||
|
|
|
||
|
|
{% block content %}
|
||
|
|
<div class="settings-container">
|
||
|
|
<h1 class="settings-title">Settings</h1>
|
||
|
|
|
||
|
|
{% if lastfm_error %}
|
||
|
|
<div class="message message-error">{{ lastfm_error }}</div>
|
||
|
|
{% endif %}
|
||
|
|
|
||
|
|
<!-- Last.fm section -->
|
||
|
|
<section class="settings-section">
|
||
|
|
<h2>Last.fm</h2>
|
||
|
|
{% if has_lastfm %}
|
||
|
|
<div class="lastfm-connected">
|
||
|
|
<p class="connected-status">
|
||
|
|
Connected as <strong>{{ profile.lastfm_username }}</strong>
|
||
|
|
</p>
|
||
|
|
<form method="post" class="settings-form" id="scrobble-form">
|
||
|
|
{% csrf_token %}
|
||
|
|
<label class="checkbox-label">
|
||
|
|
<input type="checkbox" name="lastfm_scrobble" id="lastfm_scrobble"
|
||
|
|
{% if profile.lastfm_scrobble %}checked{% endif %}
|
||
|
|
onchange="document.getElementById('scrobble-form').submit()">
|
||
|
|
Scrobble tracks to Last.fm
|
||
|
|
</label>
|
||
|
|
</form>
|
||
|
|
<form method="post" action="{% url 'lastfm_disconnect' %}" class="inline-form" style="margin-top: 1rem;">
|
||
|
|
{% csrf_token %}
|
||
|
|
<button type="submit" class="btn btn-danger">Disconnect Last.fm</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
{% else %}
|
||
|
|
<p class="lastfm-description">
|
||
|
|
Connect your Last.fm account to automatically scrobble the tracks you listen to.
|
||
|
|
</p>
|
||
|
|
<a href="{% url 'lastfm_connect' %}" class="btn btn-lastfm">Connect Last.fm</a>
|
||
|
|
{% endif %}
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<!-- Background section -->
|
||
|
|
<section class="settings-section">
|
||
|
|
<h2>Background</h2>
|
||
|
|
{% if request.user.profile.background_image %}
|
||
|
|
<p>
|
||
|
|
<img src="{{ request.user.profile.background_image.url }}" class="bg-preview" alt="Your background">
|
||
|
|
</p>
|
||
|
|
<form method="post" action="{% url 'delete_background' %}" class="inline-form">
|
||
|
|
{% csrf_token %}
|
||
|
|
<button type="submit" class="btn btn-danger">Remove background</button>
|
||
|
|
</form>
|
||
|
|
<p style="margin-top:12px;">Upload a new image to replace it:</p>
|
||
|
|
{% else %}
|
||
|
|
<p class="lastfm-description">Upload a custom background image (JPG, PNG or WebP, max 5 MB).</p>
|
||
|
|
{% endif %}
|
||
|
|
<div style="margin-top:8px; display:flex; align-items:center; gap:10px;">
|
||
|
|
<label class="btn" for="bg-upload-input">Choose file</label>
|
||
|
|
<input type="file" id="bg-upload-input" accept=".jpg,.jpeg,.png,.webp" style="display:none;" onchange="uploadBackground(this)">
|
||
|
|
<span id="bg-upload-status" style="font-size:0.85rem; color:#888;"></span>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<!-- Account section -->
|
||
|
|
<section class="settings-section">
|
||
|
|
<h2>Account</h2>
|
||
|
|
<p>Logged in as <strong>{{ request.user.username }}</strong></p>
|
||
|
|
<form method="post" action="{% url 'logout' %}" class="inline-form">
|
||
|
|
{% csrf_token %}
|
||
|
|
<button type="submit" class="btn">Logout</button>
|
||
|
|
</form>
|
||
|
|
</section>
|
||
|
|
</div>
|
||
|
|
{% endblock %}
|
||
|
|
|
||
|
|
{% block extra_js %}
|
||
|
|
<style>
|
||
|
|
.bg-preview { max-width: 240px; max-height: 135px; object-fit: cover; border-radius: 4px; border: 1px solid #333; }
|
||
|
|
</style>
|
||
|
|
<script>
|
||
|
|
function getCsrfToken() {
|
||
|
|
return document.cookie.split('; ').find(r => r.startsWith('csrftoken='))?.split('=')[1] || '';
|
||
|
|
}
|
||
|
|
async function uploadBackground(input) {
|
||
|
|
const file = input.files[0];
|
||
|
|
if (!file) return;
|
||
|
|
const status = document.getElementById('bg-upload-status');
|
||
|
|
status.textContent = 'Uploading…';
|
||
|
|
const form = new FormData();
|
||
|
|
form.append('file', file);
|
||
|
|
form.append('csrfmiddlewaretoken', getCsrfToken());
|
||
|
|
try {
|
||
|
|
const res = await fetch('/accounts/background/upload/', { method: 'POST', body: form });
|
||
|
|
const data = await res.json();
|
||
|
|
if (data.ok) { location.reload(); }
|
||
|
|
else { status.textContent = data.error || 'Upload failed'; }
|
||
|
|
} catch (e) { status.textContent = 'Upload failed'; }
|
||
|
|
input.value = '';
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
{% endblock %}
|