mirror of
https://codeberg.org/likwid/likwid.git
synced 2026-02-09 21:13:09 +00:00
225 lines
5.5 KiB
Text
225 lines
5.5 KiB
Text
|
|
---
|
||
|
|
import Layout from '../layouts/Layout.astro';
|
||
|
|
---
|
||
|
|
|
||
|
|
<Layout title="Communities">
|
||
|
|
<section class="communities">
|
||
|
|
<div class="header-row">
|
||
|
|
<div>
|
||
|
|
<h1>Communities</h1>
|
||
|
|
<p class="subtitle">Browse organizations and communities</p>
|
||
|
|
</div>
|
||
|
|
<a href="/communities/new" class="btn-create" id="create-btn" style="display: none;">+ Create Community</a>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="search-bar">
|
||
|
|
<input type="text" id="search-input" placeholder="Search communities..." />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div id="communities-list" class="list">
|
||
|
|
<p class="loading">Loading communities...</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script is:inline>
|
||
|
|
(function() {
|
||
|
|
var API_BASE = 'http://localhost:3000';
|
||
|
|
var allCommunities = [];
|
||
|
|
|
||
|
|
function renderCommunities(communities) {
|
||
|
|
var container = document.getElementById('communities-list');
|
||
|
|
if (!container) return;
|
||
|
|
|
||
|
|
if (!communities || communities.length === 0) {
|
||
|
|
container.innerHTML = '<div class="empty"><p>No communities found.</p></div>';
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
var html = '';
|
||
|
|
for (var i = 0; i < communities.length; i++) {
|
||
|
|
var c = communities[i];
|
||
|
|
html += '<a href="/communities/' + c.slug + '" class="community-card">' +
|
||
|
|
'<h3>' + c.name + '</h3>' +
|
||
|
|
'<p class="slug">/' + c.slug + '</p>' +
|
||
|
|
'<p class="description">' + (c.description || 'No description') + '</p>' +
|
||
|
|
'</a>';
|
||
|
|
}
|
||
|
|
container.innerHTML = html;
|
||
|
|
}
|
||
|
|
|
||
|
|
function filterCommunities(query) {
|
||
|
|
var q = query.toLowerCase().trim();
|
||
|
|
if (!q) {
|
||
|
|
renderCommunities(allCommunities);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var filtered = allCommunities.filter(function(c) {
|
||
|
|
return c.name.toLowerCase().indexOf(q) >= 0 ||
|
||
|
|
c.slug.toLowerCase().indexOf(q) >= 0 ||
|
||
|
|
(c.description && c.description.toLowerCase().indexOf(q) >= 0);
|
||
|
|
});
|
||
|
|
renderCommunities(filtered);
|
||
|
|
}
|
||
|
|
|
||
|
|
function loadCommunities() {
|
||
|
|
var container = document.getElementById('communities-list');
|
||
|
|
if (!container) return;
|
||
|
|
|
||
|
|
fetch(API_BASE + '/api/communities')
|
||
|
|
.then(function(res) {
|
||
|
|
if (!res.ok) throw new Error('HTTP ' + res.status);
|
||
|
|
return res.json();
|
||
|
|
})
|
||
|
|
.then(function(data) {
|
||
|
|
allCommunities = Array.isArray(data) ? data : (data.value || data.communities || []);
|
||
|
|
renderCommunities(allCommunities);
|
||
|
|
})
|
||
|
|
.catch(function(error) {
|
||
|
|
console.error('Failed to load communities:', error);
|
||
|
|
container.innerHTML = '<div class="error"><p>Failed to load communities.</p><p class="hint">Make sure the backend is running on localhost:3000</p></div>';
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// Initialize
|
||
|
|
loadCommunities();
|
||
|
|
|
||
|
|
// Setup search
|
||
|
|
var searchInput = document.getElementById('search-input');
|
||
|
|
if (searchInput) {
|
||
|
|
searchInput.addEventListener('input', function(e) {
|
||
|
|
filterCommunities(e.target.value);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// Show create button if logged in
|
||
|
|
var token = localStorage.getItem('token');
|
||
|
|
var createBtn = document.getElementById('create-btn');
|
||
|
|
if (token && createBtn) {
|
||
|
|
createBtn.style.display = 'block';
|
||
|
|
}
|
||
|
|
})();
|
||
|
|
</script>
|
||
|
|
</section>
|
||
|
|
</Layout>
|
||
|
|
|
||
|
|
<style>
|
||
|
|
.communities {
|
||
|
|
padding: 1.5rem 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.header-row {
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-between;
|
||
|
|
align-items: center;
|
||
|
|
margin-bottom: 2rem;
|
||
|
|
gap: 1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-create {
|
||
|
|
background: var(--color-primary);
|
||
|
|
color: var(--color-text-inverse);
|
||
|
|
padding: 0.625rem 1.25rem;
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
font-weight: 600;
|
||
|
|
font-size: 0.875rem;
|
||
|
|
white-space: nowrap;
|
||
|
|
transition: all var(--motion-fast) var(--easing-standard);
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-create:hover {
|
||
|
|
background: var(--color-primary-hover);
|
||
|
|
color: var(--color-text-inverse);
|
||
|
|
transform: translateY(-1px);
|
||
|
|
box-shadow: 0 4px 12px rgba(129, 140, 248, 0.25);
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-create:active {
|
||
|
|
transform: translateY(0);
|
||
|
|
box-shadow: var(--shadow-sm);
|
||
|
|
}
|
||
|
|
|
||
|
|
.search-bar {
|
||
|
|
margin-bottom: 1.5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.search-bar input {
|
||
|
|
width: 100%;
|
||
|
|
max-width: 400px;
|
||
|
|
border-radius: var(--radius-md);
|
||
|
|
}
|
||
|
|
|
||
|
|
.search-bar input::placeholder {
|
||
|
|
color: var(--color-text-muted);
|
||
|
|
}
|
||
|
|
|
||
|
|
h1 {
|
||
|
|
font-size: 2rem;
|
||
|
|
font-weight: 700;
|
||
|
|
letter-spacing: -0.02em;
|
||
|
|
margin-bottom: 0.25rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.subtitle {
|
||
|
|
color: var(--color-text-muted);
|
||
|
|
font-size: 0.9375rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.list {
|
||
|
|
display: grid;
|
||
|
|
gap: 1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.community-card {
|
||
|
|
display: block;
|
||
|
|
background: var(--color-surface);
|
||
|
|
border: 1px solid var(--color-border);
|
||
|
|
border-radius: var(--radius-lg);
|
||
|
|
padding: 1.25rem 1.5rem;
|
||
|
|
color: var(--color-text);
|
||
|
|
transition: all var(--motion-normal) var(--easing-standard);
|
||
|
|
}
|
||
|
|
|
||
|
|
.community-card:hover {
|
||
|
|
border-color: var(--color-border-hover);
|
||
|
|
transform: translateY(-2px);
|
||
|
|
box-shadow: var(--shadow-md);
|
||
|
|
}
|
||
|
|
|
||
|
|
.community-card h3 {
|
||
|
|
font-size: 1.125rem;
|
||
|
|
font-weight: 600;
|
||
|
|
margin-bottom: 0.25rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.slug {
|
||
|
|
color: var(--color-primary);
|
||
|
|
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
|
||
|
|
font-size: 0.8125rem;
|
||
|
|
margin-bottom: 0.5rem;
|
||
|
|
opacity: 0.9;
|
||
|
|
}
|
||
|
|
|
||
|
|
.description {
|
||
|
|
color: var(--color-text-muted);
|
||
|
|
font-size: 0.9375rem;
|
||
|
|
line-height: 1.5;
|
||
|
|
}
|
||
|
|
|
||
|
|
.loading, .empty, .error {
|
||
|
|
text-align: center;
|
||
|
|
padding: 4rem 2rem;
|
||
|
|
color: var(--color-text-muted);
|
||
|
|
background: var(--color-surface);
|
||
|
|
border: 1px solid var(--color-border);
|
||
|
|
border-radius: var(--radius-lg);
|
||
|
|
}
|
||
|
|
|
||
|
|
.hint {
|
||
|
|
font-size: 0.875rem;
|
||
|
|
margin-top: 0.5rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
.error {
|
||
|
|
color: var(--color-error);
|
||
|
|
}
|
||
|
|
</style>
|