pkmntrade.club/theme/templates/account/dashboard.html

228 lines
No EOL
12 KiB
HTML

{% extends "base.html" %}
{% load i18n static crispy_forms_tags gravatar %}
{% block head_title %}{{ _('Dashboard') }}{% endblock %}
{% block content %}
<div class="container mx-auto" x-data="{ activeTab: '{{ active_tab|default:'dash' }}' }">
<!-- Tab Navigation -->
<div class="tabs tabs-border mb-8">
<button type="button" :class="{'tab': true, 'tab-active': activeTab === 'dash'}" @click="activeTab = 'dash'">{{ _('Dash') }}</button>
<button type="button" :class="{'tab': true, 'tab-active': activeTab === 'dashboard_offers'}" @click="activeTab = 'dashboard_offers'">{{ _('Your Trade Offers') }} ({{ dashboard_offers_paginated.page_obj.count }})</button>
<button type="button" :class="{'tab': true, 'tab-active': activeTab === 'waiting_on_you'}" @click="activeTab = 'waiting_on_you'">{{ _('Waiting on You') }} ({{ trade_acceptances_waiting_paginated.page_obj.count }})</button>
<button type="button" :class="{'tab': true, 'tab-active': activeTab === 'waiting_on_them'}" @click="activeTab = 'waiting_on_them'">{{ _('Waiting on Them') }} ({{ other_party_trade_acceptances_paginated.page_obj.count }})</button>
<button type="button" :class="{'tab': true, 'tab-active': activeTab === 'trade_history'}" @click="activeTab = 'trade_history'">{{ _('Trade History') }}</button>
<button type="button" :class="{'tab': true, 'tab-active': activeTab === 'profile'}" @click="activeTab = 'profile'">{{ _('Profile') }}</button>
<button type="button" :class="{'tab': true, 'tab-active': activeTab === 'friend_codes'}" @click="activeTab = 'friend_codes'">{{ _('Friend Codes') }}</button>
<button type="button" :class="{'tab': true, 'tab-active': activeTab === 'settings'}" @click="activeTab = 'settings'">{{ _('Settings') }}</button>
</div>
<!-- Tab Panels -->
<!-- Dash Tab - Dashboard Summary -->
<div x-show="activeTab === 'dash'">
<div class="card bg-base-100 shadow-xl mb-4">
<div class="card-body">
<h2 class="card-title mb-2">{{ _('Trade Summary') }}</h2>
<div class="flex flex-col md:flex-row justify-center gap-4">
<div class="stats shadow-lg bg-base-300">
<div class="stat">
<div class="stat-title">{{ _('Your Reputation') }}</div>
<div class="stat-value">{{ request.user.reputation_score }}</div>
<div class="stat-desc">{{ _('Current Score') }}</div>
</div>
<div class="stat">
<div class="stat-title">{{ _('Your Trade Offers') }}</div>
<div class="stat-value">{{ dashboard_offers_paginated.page_obj.count }}</div>
<div class="stat-desc">{{ _('Active Offers') }}</div>
</div>
</div>
<div class="stats shadow-lg bg-base-300">
<div class="stat">
<div class="stat-title">{{ _('Waiting on You') }}</div>
<div class="stat-value">{{ trade_acceptances_waiting_paginated.page_obj.count }}</div>
<div class="stat-desc">{{ _('Pending Requests') }}</div>
</div>
<div class="stat">
<div class="stat-title">{{ _('Waiting on Them') }}</div>
<div class="stat-value">{{ other_party_trade_acceptances_paginated.page_obj.count }}</div>
<div class="stat-desc">{{ _('Pending Responses') }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title mb-2">{{ _('Quick Actions') }}</h2>
<div class="flex flex-wrap gap-4">
<a href="{% url 'trade_offer_create' %}" class="btn btn-primary grow">{{ _('Create New Offer') }}</a>
<a href="{% url 'trade_offer_list' %}" class="btn btn-secondary grow">{{ _('View All Offers') }}</a>
<a href="{% url 'account_logout' %}" class="btn btn-warning grow">{{ _('Sign Out') }}</a>
</div>
</div>
</div>
</div>
<!-- Your Trade Offers Tab -->
<div x-show="activeTab === 'dashboard_offers'" x-data="tradeOffersPagination('{% url 'dashboard' %}?ajax_section=dashboard_offers')">
{% include 'trades/_trade_offer_list.html' with offers=dashboard_offers_paginated.object_list page_obj=dashboard_offers_paginated.page_obj %}
</div>
<!-- Waiting on You Tab -->
<div x-show="activeTab === 'waiting_on_you'" x-data="tradeOffersPagination('{% url 'dashboard' %}?ajax_section=waiting_acceptances')">
{% include 'trades/_trade_offer_list.html' with offers=trade_acceptances_waiting_paginated.object_list page_obj=trade_acceptances_waiting_paginated.page_obj %}
</div>
<!-- Waiting on Them Tab -->
<div x-show="activeTab === 'waiting_on_them'" x-data="tradeOffersPagination('{% url 'dashboard' %}?ajax_section=other_party_acceptances')">
{% include 'trades/_trade_offer_list.html' with offers=other_party_trade_acceptances_paginated.object_list page_obj=other_party_trade_acceptances_paginated.page_obj %}
</div>
<!-- Trade History Tab -->
<div x-show="activeTab === 'trade_history'">
<div class="divider">{{ _('Closed Offers') }} ({{ closed_offers_paginated.page_obj.count }})</div>
<div class="mb-8">
{% include 'trades/_trade_offer_list.html' with offers=closed_offers_paginated.object_list page_obj=closed_offers_paginated.page_obj %}
</div>
<div class="divider">{{ _('Closed Acceptances') }} ({{ closed_acceptances_paginated.page_obj.count }})</div>
<div class="mb-8">
{% include 'trades/_trade_offer_list.html' with offers=closed_acceptances_paginated.object_list page_obj=closed_acceptances_paginated.page_obj %}
</div>
<div class="divider">{{ _('Rejected by Them') }} ({{ rejected_by_them_paginated.page_obj.count }})</div>
<div class="mb-8">
{% include 'trades/_trade_offer_list.html' with offers=rejected_by_them_paginated.object_list page_obj=rejected_by_them_paginated.page_obj %}
</div>
<div class="divider">{{ _('Rejected by Me') }} ({{ rejected_by_me_paginated.page_obj.count }})</div>
<div class="mb-8">
{% include 'trades/_trade_offer_list.html' with offers=rejected_by_me_paginated.object_list page_obj=rejected_by_me_paginated.page_obj %}
</div>
</div>
<!-- Profile Tab -->
<div x-show="activeTab === 'profile'">
<div class="card card-border bg-base-100 shadow-lg mx-auto p-6 mb-4">
{% with gravatar_profile=request.user.email|gravatar_profile_data %}
<div class="hovercard-profile mb-4 text-center">
<div class="avatar block mx-auto max-w-32">
<div class="rounded-full">
{{ request.user.email|gravatar:128 }}
</div>
</div>
<a href="https://gravatar.com/profile/avatars" target="_blank" rel="noopener noreferrer" class="btn btn-primary mt-4">
Edit Avatar on Gravatar
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="size-4">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
</svg>
</a>
</div>
{% endwith %}
<div class="divider"></div>
<h2 class="text-base font-semibold pt-0">What is Gravatar?</h2>
<p class="mb-4 text-sm">Gravatar (Globally Recognized Avatar) is a free service that links your email address to a profile picture. Many websites, including this one, use Gravatar to display your preferred avatar automatically.</p>
<h2 class="text-base font-semibold">How does it work?</h2>
<p class="mb-4 text-sm">If you've set up a Gravatar, your profile picture will appear here whenever you use your email on supported sites. If you don't have a Gravatar yet, you'll see a default randomly-generated avatar instead.</p>
<h2 class="text-base font-semibold">Is it safe? What about privacy?</h2>
<p class="mb-4 text-sm">Gravatar is completely optional, opt-in, and prioritizes your security and privacy. Your email is never visible to anyone and only a hashed version is shown on the page and sent to Gravatar, protecting your identity while ensuring that your email address is not exposed to bots or scrapers.</p>
<h2 class="text-base font-semibold">Want to update or add a Gravatar?</h2>
<p class="mb-4 text-sm">Go to Gravatar.com to set up or change your avatar. Your updates will appear here once saved!</p>
</div>
</div>
<!-- Friend Codes Tab -->
<div x-show="activeTab === 'friend_codes'">
<div class="card card-border bg-base-100 shadow-lg mx-auto p-6 mb-4">
{% if friend_codes %}
<ul class="space-y-2">
{% for code in friend_codes %}
<li class="w-full grid grid-cols-2 grid-rows-2 md:grid-cols-8 md:grid-rows-1 items-center {% if code.is_default %}bg-green-200 dark:bg-green-300 dark:text-base-100{% else %}bg-base-100 dark:bg-base-900 dark:text-white{% endif %} p-4 rounded shadow">
<div class="row-start-1 md:col-span-3">
<span class="align-baseline"><a href="{% url 'edit_friend_code' code.id %}" class="link link-hover">{{ code.in_game_name }}</a></span>
{% if code.is_default %}
<span class="badge badge-success ml-2 align-baseline">Default</span>
{% endif %}
</div>
<div class="row-start-2 col-start-1 md:row-start-1 md:col-span-3 {% if not code.is_default %}mr-4{% endif %}">
<span class="font-mono text-sm sm:text-base align-baseline">{{ code.friend_code }}</span>
</div>
<div class="row-start-2 col-start-2 md:row-start-1 md:col-span-2 flex justify-end space-x-2">
{% if not code.is_default %}
<form method="post" action="{% url 'change_default_friend_code' code.id %}">
{% csrf_token %}
<button type="submit" class="btn btn-secondary btn-sm align-baseline">Set Default</button>
</form>
{% endif %}
<a href="{% url 'delete_friend_code' code.id %}" class="btn btn-error btn-sm align-baseline">Delete</a>
</div>
</li>
{% endfor %}
</ul>
{% else %}
<p>You do not have any friend codes added yet.</p>
{% endif %}
<div class="mt-4 flex justify-end">
<a href="{% url 'add_friend_code' %}" class="btn btn-primary">Add a New Friend Code</a>
</div>
</div>
</div>
<!-- Settings Tab -->
<div x-show="activeTab === 'settings'">
<div class="card card-border bg-base-100 shadow-lg mx-auto p-6 mb-4">
<form method="post" action="{% url 'dashboard' %}">
{% csrf_token %}
{{ settings_form|crispy }}
<div class="flex justify-end">
<button type="submit" name="update_settings" class="btn btn-success mt-4">{{ _('Save Settings') }}</button>
</div>
</form>
</div>
</div>
</div>
<script>
function tradeOffersPagination(baseUrl) {
return {
baseUrl: baseUrl,
_hasChangePageListener: false,
loadPage(page) {
let url = new URL(this.baseUrl, window.location.origin);
url.searchParams.set("page", page);
fetch(url, {
headers: { 'X-Requested-With': 'XMLHttpRequest' }
})
.then(response => response.text())
.then(html => {
this.$el.innerHTML = html;
this.init();
window.processMarqueeElements && window.processMarqueeElements();
});
},
init() {
if (!this._hasChangePageListener) {
this.$el.addEventListener('change-page', event => {
let page = event.detail.page;
this.loadPage(page);
});
this._hasChangePageListener = true;
}
this.$el.querySelectorAll("a.ajax-page-link").forEach(link => {
link.addEventListener("click", (event) => {
event.preventDefault();
let page = link.getAttribute("data-page");
this.loadPage(page);
});
});
}
}
}
</script>
{% endblock %}