🎨 Improved edit links page with responsive card grid layout

📱 Mobile & Desktop Optimization:
- Responsive grid layout: 1 card (mobile) → 2 cards (tablet) → 3 cards (desktop) → 4 cards (large screens)
- Better card design with improved spacing and hover effects
- Enhanced mobile experience with optimized touch targets

🔧 UI/UX Improvements:
- Modern card-based layout instead of stacked list
- Website logos with fallback icons for better visual recognition
- Improved button placement and iconography
- Better responsive breakpoints for different screen sizes

 Visual Enhancements:
- Smooth hover animations and shadow effects
- Better logo positioning with placeholder icons
- Optimized spacing and typography for mobile devices
- Professional card design with rounded corners and subtle shadows

This update provides a much cleaner and more organized view of links, especially on mobile devices where the cards stack properly and buttons are easily accessible.
This commit is contained in:
2025-08-01 11:52:06 -04:00
parent ccf8b49f95
commit 1f0420c6b3
2 changed files with 165 additions and 28 deletions

View File

@@ -135,20 +135,41 @@
margin-bottom: 20px;
}
.links-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 15px;
margin-top: 20px;
}
.link-item {
background: white;
border: 1px solid #e9ecef;
border-radius: 8px;
border-radius: 12px;
padding: 20px;
margin-bottom: 15px;
margin-bottom: 0;
display: flex;
justify-content: space-between;
align-items: flex-start;
flex-direction: column;
gap: 15px;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.link-item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
border-color: #667eea;
}
.link-item.editing {
border-color: #667eea;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2);
}
.link-header {
display: flex;
align-items: flex-start;
gap: 12px;
}
.link-content {
@@ -156,9 +177,25 @@
}
.link-logo {
width: 32px;
height: 32px;
border-radius: 6px;
width: 40px;
height: 40px;
border-radius: 8px;
flex-shrink: 0;
object-fit: cover;
background: #f8f9fa;
border: 1px solid #e9ecef;
}
.link-icon-placeholder {
width: 40px;
height: 40px;
border-radius: 8px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 18px;
flex-shrink: 0;
}
@@ -253,12 +290,93 @@
}
@media (max-width: 768px) {
body {
padding: 10px;
}
.container {
border-radius: 10px;
}
.header {
padding: 20px 15px;
}
.header h1 {
font-size: 1.8em;
}
.main-content {
grid-template-columns: 1fr;
gap: 20px;
padding: 20px 15px;
}
.form-section {
padding: 20px 15px;
}
.links-grid {
grid-template-columns: 1fr;
gap: 12px;
}
.link-item {
padding: 15px;
}
.link-header {
gap: 10px;
}
.link-logo,
.link-icon-placeholder {
width: 35px;
height: 35px;
}
.link-title {
font-size: 1.1em;
}
.link-actions {
flex-direction: column;
gap: 8px;
}
.link-actions .btn-small {
width: 100%;
text-align: center;
}
.page-actions {
flex-direction: column;
padding: 15px;
gap: 10px;
}
.page-actions .btn {
width: 100%;
text-align: center;
margin-right: 0;
}
}
@media (min-width: 769px) and (max-width: 1024px) {
.links-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1025px) {
.links-grid {
grid-template-columns: repeat(3, 1fr);
}
}
@media (min-width: 1400px) {
.links-grid {
grid-template-columns: repeat(4, 1fr);
}
}
</style>
@@ -310,28 +428,35 @@
<div class="links-section">
<h2>Current Links ({{ page.links|length }})</h2>
<div id="links-container">
<div class="links-grid" id="links-container">
{% if page.links %}
{% for link in page.links %}
<div class="link-item" data-link-id="{{ link.id }}">
<div class="link-content">
<div class="link-display">
<div class="link-title">{{ link.title }}</div>
{% if link.description %}
<div class="link-description">{{ link.description }}</div>
{% endif %}
<div class="link-url" data-url="{{ link.url }}">{{ link.url }}</div>
<div class="link-display">
<div class="link-header">
<div class="link-icon-placeholder" style="display: flex;">🔗</div>
<img class="link-logo" src="" alt="" style="display: none;" onerror="this.style.display='none'">
<div class="link-content">
<div class="link-title">{{ link.title }}</div>
{% if link.description %}
<div class="link-description">{{ link.description }}</div>
{% endif %}
<div class="link-url" data-url="{{ link.url }}">{{ link.url }}</div>
</div>
</div>
{% if link.short_url %}
<div class="short-url-display" style="margin-top: 8px; padding: 8px; background: #e3f2fd; border-radius: 5px; border-left: 3px solid #2196f3;">
<div class="short-url-display" style="margin-top: 12px; padding: 10px; background: #e3f2fd; border-radius: 8px; border-left: 3px solid #2196f3;">
<small style="color: #1976d2; font-weight: 600;">🔗 Short URL:</small>
<br>
<a href="{{ link.short_url }}" target="_blank" style="color: #1976d2; text-decoration: none; font-family: monospace;">{{ link.short_url }}</a>
<button class="btn-copy" onclick="copyToClipboard('{{ link.short_url }}')" style="margin-left: 10px; padding: 2px 8px; background: #2196f3; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 0.8em;">Copy</button>
<a href="{{ link.short_url }}" target="_blank" style="color: #1976d2; text-decoration: none; font-family: monospace; font-size: 0.9em;">{{ link.short_url }}</a>
<button class="btn-copy" onclick="copyToClipboard('{{ link.short_url }}')" style="margin-left: 8px; padding: 3px 8px; background: #2196f3; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 0.8em;">Copy</button>
</div>
{% endif %}
<div class="link-actions">
<button class="btn btn-small btn-secondary" onclick="editLink('{{ link.id }}')">Edit</button>
<button class="btn btn-small btn-danger" onclick="deleteLink('{{ link.id }}')">Delete</button>
<button class="btn btn-small btn-secondary" onclick="editLink('{{ link.id }}')">✏️ Edit</button>
<button class="btn btn-small btn-danger" onclick="deleteLink('{{ link.id }}')">🗑️ Delete</button>
</div>
</div>
@@ -349,15 +474,14 @@
<textarea class="edit-description">{{ link.description or '' }}</textarea>
</div>
<div class="link-actions">
<button class="btn btn-small btn-success" onclick="saveLink('{{ link.id }}')">Save</button>
<button class="btn btn-small btn-secondary" onclick="cancelEdit('{{ link.id }}')">Cancel</button>
<button class="btn btn-small btn-success" onclick="saveLink('{{ link.id }}')">💾 Save</button>
<button class="btn btn-small btn-secondary" onclick="cancelEdit('{{ link.id }}')">Cancel</button>
</div>
</div>
<img class="link-logo" src="" alt="" style="display: none;" onerror="this.style.display='none'">
</div>
{% endfor %}
{% else %}
<div class="empty-state">
<div class="empty-state" style="grid-column: 1 / -1;">
<div class="icon">📝</div>
<h3>No links yet</h3>
<p>Add your first link using the form on the left.</p>
@@ -426,13 +550,26 @@
function setLogosForLinks() {
document.querySelectorAll('.link-url[data-url]').forEach(linkElement => {
const url = linkElement.getAttribute('data-url');
const logoImg = linkElement.closest('.link-item').querySelector('.link-logo');
const linkItem = linkElement.closest('.link-item');
const logoImg = linkItem.querySelector('.link-logo');
const placeholder = linkItem.querySelector('.link-icon-placeholder');
const logoSrc = getWebsiteLogo(url);
if (logoSrc && logoImg) {
logoImg.src = logoSrc;
logoImg.style.display = 'block';
logoImg.alt = new URL(url.startsWith('http') ? url : 'https://' + url).hostname;
// Show logo and hide placeholder when loaded
logoImg.onload = function() {
logoImg.style.display = 'block';
if (placeholder) placeholder.style.display = 'none';
};
// Show placeholder if logo fails to load
logoImg.onerror = function() {
logoImg.style.display = 'none';
if (placeholder) placeholder.style.display = 'flex';
};
}
});
}

View File

@@ -432,7 +432,7 @@
<div class="stat-label">Page Views</div>
</div>
<div class="stat-item">
<div class="stat-number">{{ page.links|sum(attribute='click_count') or 0 }}</div>
<div class="stat-number">{{ page.links|sum(attribute='clicks') or 0 }}</div>
<div class="stat-label">Total Clicks</div>
</div>
</div>
@@ -500,7 +500,7 @@
{% endif %}
<div class="link-url">{{ link.short_url if link.short_url else link.url }}</div>
<div style="margin-top: 10px; font-size: 0.85em; color: #666;">
<strong>Clicks:</strong> {{ link.click_count or 0 }} |
<strong>Clicks:</strong> {{ link.clicks or 0 }} |
<strong>Added:</strong> {{ link.created_at or 'N/A' }}
</div>
</div>