668 lines
21 KiB
HTML
668 lines
21 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ user.display_name or user.username }} - SysTades{% endblock %}
|
|
|
|
{% block additional_css %}
|
|
<style>
|
|
.profile-container {
|
|
max-width: 1000px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
}
|
|
|
|
.profile-header {
|
|
background: white;
|
|
border-radius: 16px;
|
|
padding: 30px;
|
|
margin-bottom: 25px;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
border: 1px solid #e1e8ed;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.profile-header::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 120px;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
z-index: 1;
|
|
}
|
|
|
|
.profile-content {
|
|
position: relative;
|
|
z-index: 2;
|
|
}
|
|
|
|
.profile-avatar {
|
|
width: 120px;
|
|
height: 120px;
|
|
border-radius: 50%;
|
|
background: white;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 48px;
|
|
font-weight: bold;
|
|
color: #667eea;
|
|
margin: 60px auto 20px auto;
|
|
border: 4px solid white;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
}
|
|
|
|
.profile-info {
|
|
text-align: center;
|
|
color: white;
|
|
margin-bottom: 30px;
|
|
}
|
|
|
|
.profile-name {
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
margin: 0 0 8px 0;
|
|
}
|
|
|
|
.profile-username {
|
|
font-size: 18px;
|
|
opacity: 0.9;
|
|
margin: 0 0 15px 0;
|
|
}
|
|
|
|
.profile-bio {
|
|
font-size: 16px;
|
|
line-height: 1.5;
|
|
opacity: 0.95;
|
|
max-width: 600px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.profile-stats {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 40px;
|
|
background: rgba(255,255,255,0.1);
|
|
backdrop-filter: blur(10px);
|
|
border-radius: 12px;
|
|
padding: 20px;
|
|
margin-top: 25px;
|
|
}
|
|
|
|
.stat-item {
|
|
text-align: center;
|
|
color: white;
|
|
}
|
|
|
|
.stat-number {
|
|
font-size: 24px;
|
|
font-weight: 700;
|
|
display: block;
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 14px;
|
|
opacity: 0.9;
|
|
margin-top: 4px;
|
|
}
|
|
|
|
.profile-actions {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 15px;
|
|
margin-top: 25px;
|
|
}
|
|
|
|
.action-btn {
|
|
background: white;
|
|
color: #667eea;
|
|
border: none;
|
|
padding: 12px 24px;
|
|
border-radius: 25px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
text-decoration: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.action-btn:hover {
|
|
background: #f0f2f5;
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
|
|
}
|
|
|
|
.action-btn.primary {
|
|
background: #1877f2;
|
|
color: white;
|
|
}
|
|
|
|
.action-btn.primary:hover {
|
|
background: #166fe5;
|
|
}
|
|
|
|
.profile-navigation {
|
|
background: white;
|
|
border-radius: 12px;
|
|
margin-bottom: 25px;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
border: 1px solid #e1e8ed;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.nav-tabs {
|
|
display: flex;
|
|
border-bottom: 1px solid #e1e8ed;
|
|
}
|
|
|
|
.nav-tab {
|
|
flex: 1;
|
|
background: none;
|
|
border: none;
|
|
padding: 15px 20px;
|
|
cursor: pointer;
|
|
font-weight: 500;
|
|
color: #8a8a8a;
|
|
transition: all 0.2s;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.nav-tab:hover {
|
|
background: #f8f9fa;
|
|
color: #1d2129;
|
|
}
|
|
|
|
.nav-tab.active {
|
|
color: #1877f2;
|
|
border-bottom: 2px solid #1877f2;
|
|
background: #f0f2f5;
|
|
}
|
|
|
|
.profile-content-area {
|
|
background: white;
|
|
border-radius: 12px;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
border: 1px solid #e1e8ed;
|
|
min-height: 400px;
|
|
}
|
|
|
|
.posts-grid {
|
|
padding: 20px;
|
|
display: grid;
|
|
gap: 20px;
|
|
}
|
|
|
|
.post-card {
|
|
background: #f8f9fa;
|
|
border-radius: 12px;
|
|
padding: 20px;
|
|
border: 1px solid #e1e8ed;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.post-card:hover {
|
|
background: white;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.post-meta {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 15px;
|
|
margin-bottom: 15px;
|
|
color: #8a8a8a;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.post-content {
|
|
color: #1d2129;
|
|
line-height: 1.6;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.post-stats {
|
|
display: flex;
|
|
gap: 20px;
|
|
color: #8a8a8a;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.post-stat {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.empty-state {
|
|
text-align: center;
|
|
padding: 60px 20px;
|
|
color: #8a8a8a;
|
|
}
|
|
|
|
.empty-state h3 {
|
|
margin-bottom: 12px;
|
|
color: #1d2129;
|
|
}
|
|
|
|
.about-grid {
|
|
padding: 20px;
|
|
display: grid;
|
|
gap: 20px;
|
|
}
|
|
|
|
.about-section {
|
|
background: #f8f9fa;
|
|
border-radius: 12px;
|
|
padding: 20px;
|
|
border: 1px solid #e1e8ed;
|
|
}
|
|
|
|
.about-section h3 {
|
|
margin: 0 0 15px 0;
|
|
color: #1d2129;
|
|
font-size: 18px;
|
|
}
|
|
|
|
.info-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
margin-bottom: 12px;
|
|
color: #1d2129;
|
|
}
|
|
|
|
.info-row i {
|
|
color: #1877f2;
|
|
width: 20px;
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 768px) {
|
|
.profile-stats {
|
|
gap: 20px;
|
|
}
|
|
|
|
.profile-actions {
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
|
|
.nav-tabs {
|
|
overflow-x: auto;
|
|
}
|
|
}
|
|
|
|
/* Dark Mode */
|
|
[data-theme="dark"] .profile-header,
|
|
[data-theme="dark"] .profile-navigation,
|
|
[data-theme="dark"] .profile-content-area,
|
|
[data-theme="dark"] .about-section {
|
|
background: #242526;
|
|
border-color: #3a3b3c;
|
|
color: #e4e6ea;
|
|
}
|
|
|
|
[data-theme="dark"] .post-card {
|
|
background: #3a3b3c;
|
|
border-color: #4e4f50;
|
|
}
|
|
|
|
[data-theme="dark"] .post-card:hover {
|
|
background: #4e4f50;
|
|
}
|
|
|
|
[data-theme="dark"] .nav-tab {
|
|
color: #b0b3b8;
|
|
}
|
|
|
|
[data-theme="dark"] .nav-tab:hover {
|
|
background: #3a3b3c;
|
|
color: #e4e6ea;
|
|
}
|
|
|
|
[data-theme="dark"] .action-btn {
|
|
background: #3a3b3c;
|
|
color: #e4e6ea;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="profile-container">
|
|
<!-- Profile Header -->
|
|
<div class="profile-header">
|
|
<div class="profile-content">
|
|
<div class="profile-avatar">
|
|
{{ user.username[0].upper() }}
|
|
</div>
|
|
|
|
<div class="profile-info">
|
|
<h1 class="profile-name">{{ user.display_name or user.username }}</h1>
|
|
<p class="profile-username">@{{ user.username }}</p>
|
|
{% if user.bio %}
|
|
<p class="profile-bio">{{ user.bio }}</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="profile-stats">
|
|
<div class="stat-item">
|
|
<span class="stat-number">{{ user.post_count }}</span>
|
|
<div class="stat-label">Posts</div>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-number">{{ user.follower_count }}</span>
|
|
<div class="stat-label">Follower</div>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-number">{{ user.following_count }}</span>
|
|
<div class="stat-label">Folgt</div>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-number">{{ user.mindmaps|length if user.mindmaps else 0 }}</span>
|
|
<div class="stat-label">Mindmaps</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if user != current_user %}
|
|
<div class="profile-actions">
|
|
<button
|
|
class="action-btn primary"
|
|
onclick="followUser({{ user.id }})"
|
|
id="followBtn"
|
|
>
|
|
<i class="fas fa-user-plus"></i>
|
|
{% if is_following %}Gefolgt{% else %}Folgen{% endif %}
|
|
</button>
|
|
<button class="action-btn" onclick="sendMessage({{ user.id }})">
|
|
<i class="fas fa-envelope"></i>
|
|
Nachricht
|
|
</button>
|
|
</div>
|
|
{% else %}
|
|
<div class="profile-actions">
|
|
<a href="{{ url_for('settings') }}" class="action-btn">
|
|
<i class="fas fa-cog"></i>
|
|
Profil bearbeiten
|
|
</a>
|
|
<a href="{{ url_for('create_mindmap') }}" class="action-btn primary">
|
|
<i class="fas fa-plus"></i>
|
|
Neue Mindmap
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Profile Navigation -->
|
|
<div class="profile-navigation">
|
|
<div class="nav-tabs">
|
|
<button class="nav-tab active" onclick="switchTab('posts')">
|
|
<i class="fas fa-th-large"></i>
|
|
Posts
|
|
</button>
|
|
<button class="nav-tab" onclick="switchTab('mindmaps')">
|
|
<i class="fas fa-project-diagram"></i>
|
|
Mindmaps
|
|
</button>
|
|
<button class="nav-tab" onclick="switchTab('thoughts')">
|
|
<i class="fas fa-lightbulb"></i>
|
|
Gedanken
|
|
</button>
|
|
<button class="nav-tab" onclick="switchTab('about')">
|
|
<i class="fas fa-info-circle"></i>
|
|
Über
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Profile Content Area -->
|
|
<div class="profile-content-area">
|
|
<!-- Posts Tab -->
|
|
<div id="posts-tab" class="tab-content">
|
|
<div class="posts-grid">
|
|
{% if posts %}
|
|
{% for post in posts %}
|
|
<div class="post-card">
|
|
<div class="post-meta">
|
|
<span><i class="fas fa-clock"></i> {{ post.created_at.strftime('%d.%m.%Y') }}</span>
|
|
<span><i class="fas fa-eye"></i> {{ post.view_count }} Aufrufe</span>
|
|
</div>
|
|
<div class="post-content">
|
|
{{ post.content[:300] }}{% if post.content|length > 300 %}...{% endif %}
|
|
</div>
|
|
<div class="post-stats">
|
|
<div class="post-stat">
|
|
<i class="fas fa-heart"></i>
|
|
<span>{{ post.like_count }}</span>
|
|
</div>
|
|
<div class="post-stat">
|
|
<i class="fas fa-comment"></i>
|
|
<span>{{ post.comment_count }}</span>
|
|
</div>
|
|
<div class="post-stat">
|
|
<i class="fas fa-share"></i>
|
|
<span>{{ post.share_count or 0 }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% else %}
|
|
<div class="empty-state">
|
|
<h3>Noch keine Posts</h3>
|
|
<p>{% if user == current_user %}Du hast noch keine Posts erstellt.{% else %}{{ user.username }} hat noch keine Posts veröffentlicht.{% endif %}</p>
|
|
{% if user == current_user %}
|
|
<a href="{{ url_for('social_feed') }}" class="action-btn primary" style="margin-top: 15px;">
|
|
<i class="fas fa-plus"></i>
|
|
Ersten Post erstellen
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mindmaps Tab -->
|
|
<div id="mindmaps-tab" class="tab-content" style="display: none;">
|
|
<div class="posts-grid">
|
|
{% if user.mindmaps %}
|
|
{% for mindmap in user.mindmaps %}
|
|
<div class="post-card">
|
|
<div class="post-meta">
|
|
<span><i class="fas fa-clock"></i> {{ mindmap.created_at.strftime('%d.%m.%Y') }}</span>
|
|
<span><i class="fas fa-nodes"></i> {{ mindmap.public_nodes|length }} Knoten</span>
|
|
</div>
|
|
<div class="post-content">
|
|
<h4 style="margin: 0 0 10px 0; color: #1877f2;">{{ mindmap.name }}</h4>
|
|
<p>{{ mindmap.description or 'Keine Beschreibung verfügbar' }}</p>
|
|
</div>
|
|
<div class="post-stats">
|
|
<a href="{{ url_for('user_mindmap', mindmap_id=mindmap.id) }}" class="action-btn">
|
|
<i class="fas fa-eye"></i>
|
|
Anzeigen
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% else %}
|
|
<div class="empty-state">
|
|
<h3>Keine Mindmaps</h3>
|
|
<p>{% if user == current_user %}Du hast noch keine Mindmaps erstellt.{% else %}{{ user.username }} hat noch keine öffentlichen Mindmaps.{% endif %}</p>
|
|
{% if user == current_user %}
|
|
<a href="{{ url_for('create_mindmap') }}" class="action-btn primary" style="margin-top: 15px;">
|
|
<i class="fas fa-plus"></i>
|
|
Erste Mindmap erstellen
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Thoughts Tab -->
|
|
<div id="thoughts-tab" class="tab-content" style="display: none;">
|
|
<div class="posts-grid">
|
|
{% if user.thoughts %}
|
|
{% for thought in user.thoughts[:10] %}
|
|
<div class="post-card">
|
|
<div class="post-meta">
|
|
<span><i class="fas fa-clock"></i> {{ thought.created_at.strftime('%d.%m.%Y') }}</span>
|
|
<span><i class="fas fa-tag"></i> {{ thought.branch }}</span>
|
|
</div>
|
|
<div class="post-content">
|
|
<h4 style="margin: 0 0 10px 0; color: #1877f2;">{{ thought.title }}</h4>
|
|
<p>{{ thought.abstract or thought.content[:200] }}{% if (thought.abstract or thought.content)|length > 200 %}...{% endif %}</p>
|
|
</div>
|
|
<div class="post-stats">
|
|
<div class="post-stat">
|
|
<i class="fas fa-star"></i>
|
|
<span>{{ thought.average_rating or 0 }}</span>
|
|
</div>
|
|
<div class="post-stat">
|
|
<i class="fas fa-comment"></i>
|
|
<span>{{ thought.comments|length }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
{% else %}
|
|
<div class="empty-state">
|
|
<h3>Keine Gedanken</h3>
|
|
<p>{% if user == current_user %}Du hast noch keine Gedanken geteilt.{% else %}{{ user.username }} hat noch keine Gedanken veröffentlicht.{% endif %}</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- About Tab -->
|
|
<div id="about-tab" class="tab-content" style="display: none;">
|
|
<div class="about-grid">
|
|
<div class="about-section">
|
|
<h3>Grundlegende Informationen</h3>
|
|
<div class="info-row">
|
|
<i class="fas fa-user"></i>
|
|
<span>Mitglied seit {{ user.created_at.strftime('%B %Y') }}</span>
|
|
</div>
|
|
{% if user.location %}
|
|
<div class="info-row">
|
|
<i class="fas fa-map-marker-alt"></i>
|
|
<span>{{ user.location }}</span>
|
|
</div>
|
|
{% endif %}
|
|
{% if user.website %}
|
|
<div class="info-row">
|
|
<i class="fas fa-globe"></i>
|
|
<a href="{{ user.website }}" target="_blank" rel="noopener">{{ user.website }}</a>
|
|
</div>
|
|
{% endif %}
|
|
{% if user.last_login %}
|
|
<div class="info-row">
|
|
<i class="fas fa-clock"></i>
|
|
<span>Zuletzt aktiv: {{ user.last_login.strftime('%d.%m.%Y') }}</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="about-section">
|
|
<h3>Aktivitätsstatistiken</h3>
|
|
<div class="info-row">
|
|
<i class="fas fa-chart-line"></i>
|
|
<span>{{ user.post_count }} Posts erstellt</span>
|
|
</div>
|
|
<div class="info-row">
|
|
<i class="fas fa-lightbulb"></i>
|
|
<span>{{ user.thoughts|length if user.thoughts else 0 }} Gedanken geteilt</span>
|
|
</div>
|
|
<div class="info-row">
|
|
<i class="fas fa-project-diagram"></i>
|
|
<span>{{ user.mindmaps|length if user.mindmaps else 0 }} Mindmaps erstellt</span>
|
|
</div>
|
|
<div class="info-row">
|
|
<i class="fas fa-comments"></i>
|
|
<span>Aktives Community-Mitglied</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block additional_js %}
|
|
<script>
|
|
// Tab Navigation
|
|
function switchTab(tabName) {
|
|
// Alle Tabs verstecken
|
|
document.querySelectorAll('.tab-content').forEach(tab => {
|
|
tab.style.display = 'none';
|
|
});
|
|
|
|
// Alle Tab-Buttons deaktivieren
|
|
document.querySelectorAll('.nav-tab').forEach(btn => {
|
|
btn.classList.remove('active');
|
|
});
|
|
|
|
// Gewählten Tab anzeigen
|
|
document.getElementById(tabName + '-tab').style.display = 'block';
|
|
|
|
// Gewählten Tab-Button aktivieren
|
|
event.target.classList.add('active');
|
|
}
|
|
|
|
// Follow/Unfollow Funktionalität
|
|
async function followUser(userId) {
|
|
const button = document.getElementById('followBtn');
|
|
|
|
try {
|
|
const response = await fetch('/api/users/' + userId + '/follow', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
}
|
|
});
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
if (data.action === 'followed') {
|
|
button.innerHTML = '<i class="fas fa-user-check"></i> Gefolgt';
|
|
button.classList.add('following');
|
|
} else {
|
|
button.innerHTML = '<i class="fas fa-user-plus"></i> Folgen';
|
|
button.classList.remove('following');
|
|
}
|
|
} else {
|
|
alert(data.error && data.error.message ? data.error.message : 'Fehler beim Folgen');
|
|
}
|
|
} catch (error) {
|
|
console.error('Fehler beim Folgen:', error);
|
|
alert('Ein Fehler ist aufgetreten. Bitte versuche es erneut.');
|
|
}
|
|
}
|
|
|
|
// Nachricht senden (Platzhalter)
|
|
function sendMessage(userId) {
|
|
alert('Nachrichten-Feature wird bald verfügbar sein!');
|
|
}
|
|
|
|
// URL-Parameter für Tab-Navigation
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const tab = urlParams.get('tab');
|
|
|
|
if (tab) {
|
|
// Tab aus URL aktivieren
|
|
const tabButton = document.querySelector('[onclick="switchTab(\'' + tab + '\')"]');
|
|
if (tabButton) {
|
|
tabButton.click();
|
|
}
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %} |