137 lines
5.4 KiB
HTML
137 lines
5.4 KiB
HTML
|
|
{% extends "base.html" %}
|
|||
|
|
|
|||
|
|
{% block content %}
|
|||
|
|
<div class="card mb-3" style="background: var(--black); color: var(--cream);">
|
|||
|
|
<div class="card-body" style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 20px;">
|
|||
|
|
<div>
|
|||
|
|
<p style="font-size: 12px; letter-spacing: 2px; text-transform: uppercase; opacity: 0.7; margin-bottom: 5px;">Профиль</p>
|
|||
|
|
<h2 style="font-family: 'Playfair Display', serif; font-size: 36px; color: var(--cream); margin: 0;">
|
|||
|
|
{{ user.username }}
|
|||
|
|
</h2>
|
|||
|
|
</div>
|
|||
|
|
<div style="display: flex; gap: 40px; align-items: center;">
|
|||
|
|
<div style="text-align: center;">
|
|||
|
|
<p style="font-size: 12px; letter-spacing: 1px; text-transform: uppercase; opacity: 0.7;">ID</p>
|
|||
|
|
<p style="font-size: 24px; font-weight: 700; color: var(--yellow);">#{{ user.id }}</p>
|
|||
|
|
</div>
|
|||
|
|
<div style="text-align: center;">
|
|||
|
|
<p style="font-size: 12px; letter-spacing: 1px; text-transform: uppercase; opacity: 0.7;">Баланс</p>
|
|||
|
|
<p style="font-size: 24px; font-weight: 700; color: var(--yellow);">{{ user.balance }} ₽</p>
|
|||
|
|
</div>
|
|||
|
|
<div style="text-align: center;">
|
|||
|
|
<p style="font-size: 12px; letter-spacing: 1px; text-transform: uppercase; opacity: 0.7;">Работ</p>
|
|||
|
|
<p style="font-size: 24px; font-weight: 700; color: var(--yellow);">{{ artworks|length }}</p>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<h3 class="section-title">Коллекция</h3>
|
|||
|
|
|
|||
|
|
{% if artworks %}
|
|||
|
|
<div class="grid grid-3">
|
|||
|
|
{% for art in artworks %}
|
|||
|
|
<div class="card">
|
|||
|
|
<div class="card-header" style="display: flex; justify-content: space-between; align-items: center;">
|
|||
|
|
<span>#{{ art.id }}</span>
|
|||
|
|
{% if art.is_private %}
|
|||
|
|
<span style="background: var(--red); color: white; padding: 2px 8px; font-size: 10px;">ПРИВАТНАЯ</span>
|
|||
|
|
{% endif %}
|
|||
|
|
</div>
|
|||
|
|
<div class="card-body">
|
|||
|
|
<h5 class="card-title">{{ art.title }}</h5>
|
|||
|
|
<div class="art-preview mb-2" style="height: 160px;">
|
|||
|
|
<canvas id="profile-art-{{ art.id }}" width="350" height="160"></canvas>
|
|||
|
|
</div>
|
|||
|
|
{% if art.signature %}
|
|||
|
|
<div class="artwork-signature mb-2" style="padding: 8px; background: #f0f0f0; border-left: 3px solid var(--red); font-style: italic; font-size: 13px;">
|
|||
|
|
{{ art.signature }}
|
|||
|
|
</div>
|
|||
|
|
{% endif %}
|
|||
|
|
<div class="text-price mb-1">
|
|||
|
|
{{ art.price }} <span>₽</span>
|
|||
|
|
</div>
|
|||
|
|
<p class="text-muted mb-2">{{ art.created_at[:16] if art.created_at else 'Недавно' }}</p>
|
|||
|
|
<a href="{{ url_for('artwork_settings', artwork_id=art.id) }}" class="btn btn-outline btn-small">Настройки</a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
{% endfor %}
|
|||
|
|
</div>
|
|||
|
|
{% else %}
|
|||
|
|
<div class="info-block">
|
|||
|
|
<p>У вас пока нет работ. <a href="{{ url_for('index') }}" style="color: var(--yellow);">Создайте первую!</a></p>
|
|||
|
|
</div>
|
|||
|
|
{% endif %}
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
const profileArtworksData = {{ artworks|tojson }};
|
|||
|
|
|
|||
|
|
function drawArt(canvas, artData) {
|
|||
|
|
try {
|
|||
|
|
const ctx = canvas.getContext('2d');
|
|||
|
|
const shapes = JSON.parse(artData);
|
|||
|
|
|
|||
|
|
ctx.fillStyle = '#F5F0E6';
|
|||
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|||
|
|
|
|||
|
|
const scale = canvas.width / 100;
|
|||
|
|
|
|||
|
|
shapes.forEach(shape => {
|
|||
|
|
ctx.save();
|
|||
|
|
ctx.fillStyle = shape.color;
|
|||
|
|
ctx.strokeStyle = shape.color;
|
|||
|
|
ctx.lineWidth = 3;
|
|||
|
|
|
|||
|
|
const x = shape.x * scale;
|
|||
|
|
const y = shape.y * scale;
|
|||
|
|
const w = shape.width * scale;
|
|||
|
|
const h = shape.height * scale;
|
|||
|
|
const angle = (shape.angle || 0) * Math.PI / 180;
|
|||
|
|
|
|||
|
|
const cx = x + w / 2;
|
|||
|
|
const cy = y + h / 2;
|
|||
|
|
|
|||
|
|
if (shape.type === 'rectangle' || shape.type === 'rotated_rect') {
|
|||
|
|
ctx.translate(cx, cy);
|
|||
|
|
ctx.rotate(angle);
|
|||
|
|
ctx.fillRect(-w/2, -h/2, w, h);
|
|||
|
|
} else if (shape.type === 'circle') {
|
|||
|
|
ctx.beginPath();
|
|||
|
|
ctx.arc(cx, cy, Math.min(w, h) / 2, 0, Math.PI * 2);
|
|||
|
|
ctx.fill();
|
|||
|
|
} else if (shape.type === 'triangle') {
|
|||
|
|
ctx.translate(cx, cy);
|
|||
|
|
ctx.rotate(angle);
|
|||
|
|
ctx.beginPath();
|
|||
|
|
ctx.moveTo(0, -h/2);
|
|||
|
|
ctx.lineTo(w/2, h/2);
|
|||
|
|
ctx.lineTo(-w/2, h/2);
|
|||
|
|
ctx.closePath();
|
|||
|
|
ctx.fill();
|
|||
|
|
} else if (shape.type === 'line') {
|
|||
|
|
ctx.translate(cx, cy);
|
|||
|
|
ctx.rotate(angle);
|
|||
|
|
ctx.beginPath();
|
|||
|
|
ctx.moveTo(-w/2, 0);
|
|||
|
|
ctx.lineTo(w/2, 0);
|
|||
|
|
ctx.lineWidth = h || 4;
|
|||
|
|
ctx.stroke();
|
|||
|
|
}
|
|||
|
|
ctx.restore();
|
|||
|
|
});
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('Error:', e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|||
|
|
profileArtworksData.forEach(art => {
|
|||
|
|
const canvas = document.getElementById('profile-art-' + art.id);
|
|||
|
|
if (canvas) {
|
|||
|
|
drawArt(canvas, art.data);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
{% endblock %}
|