Skip to content

Commit c02035e

Browse files
committed
重新設計書籍資源頁面
- 簡化 products.md 內容,移除冗長的表格 - 新增「繁體中文翻譯」精選區塊,突顯我們翻譯的書籍 - 新增分類篩選:Bitcoin / Lightning / 白皮書 / 其他 - 新增語言篩選:繁中 / 英文 - 產品卡片增加分類和語言標籤 - 改善空白狀態顯示和篩選重置功能 - 調整卡片比例從 3:4 改為 4:3
1 parent e719973 commit c02035e

File tree

2 files changed

+359
-97
lines changed

2 files changed

+359
-97
lines changed

_layouts/product-category.html

Lines changed: 355 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,375 @@
11
---
22
layout: default
3-
show_sidebar: false
3+
hide_hero: true
44
---
55

6-
<div class="columns is-multiline">
6+
<div class="max-w-7xl mx-auto">
7+
<!-- Compact Header Section -->
8+
<header class="mb-8 pb-6 border-b border-cp-dark-400">
9+
<div class="flex flex-col md:flex-row md:items-end justify-between gap-4">
10+
<div>
11+
<h1 class="text-2xl md:text-3xl font-bold font-mono text-cp-green-500 mb-2">
12+
{{ page.title }}
13+
</h1>
14+
{% if page.subtitle %}
15+
<p class="text-base text-cp-dark-600 font-mono">
16+
{{ page.subtitle }}
17+
</p>
18+
{% endif %}
19+
{% if content != "" %}
20+
<div class="mt-3 text-cp-dark-700 text-sm">
21+
{{ content }}
22+
</div>
23+
{% endif %}
24+
</div>
25+
<!-- Quick Stats -->
26+
<div class="flex items-center gap-6 text-sm font-mono">
27+
<div class="text-center">
28+
<div class="text-xl font-bold text-cp-green-400">{{ site.products.size }}</div>
29+
<div class="text-xs text-cp-dark-600">項目</div>
30+
</div>
31+
<div class="text-center">
32+
<div class="text-xl font-bold text-cp-green-400">FREE</div>
33+
<div class="text-xs text-cp-dark-600">開源</div>
34+
</div>
35+
</div>
36+
</div>
37+
</header>
38+
39+
<!-- Filter Bar -->
40+
<div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 mb-8 p-4 card">
41+
<div class="flex flex-wrap items-center gap-2">
42+
<span class="text-sm text-cp-dark-600 font-mono mr-2">分類:</span>
43+
<button class="filter-btn active px-3 py-1.5 text-xs font-mono border border-cp-green-500 text-cp-green-500 rounded transition-colors" data-filter="all">
44+
全部
45+
</button>
46+
<button class="filter-btn px-3 py-1.5 text-xs font-mono border border-cp-dark-400 rounded hover:border-cp-green-500 hover:text-cp-green-500 transition-colors" data-filter="bitcoin">
47+
Bitcoin
48+
</button>
49+
<button class="filter-btn px-3 py-1.5 text-xs font-mono border border-cp-dark-400 rounded hover:border-cp-green-500 hover:text-cp-green-500 transition-colors" data-filter="lightning">
50+
Lightning
51+
</button>
52+
<button class="filter-btn px-3 py-1.5 text-xs font-mono border border-cp-dark-400 rounded hover:border-cp-green-500 hover:text-cp-green-500 transition-colors" data-filter="whitepaper">
53+
白皮書
54+
</button>
55+
<button class="filter-btn px-3 py-1.5 text-xs font-mono border border-cp-dark-400 rounded hover:border-cp-green-500 hover:text-cp-green-500 transition-colors" data-filter="other">
56+
其他
57+
</button>
58+
</div>
759

8-
<div class="column is-12">
9-
{{ page.content }}
60+
<!-- Language Filter -->
61+
<div class="flex items-center gap-2">
62+
<span class="text-sm text-cp-dark-600 font-mono mr-2">語言:</span>
63+
<button class="lang-btn active px-3 py-1.5 text-xs font-mono border border-cp-green-500 text-cp-green-500 rounded transition-colors" data-lang="all">
64+
全部
65+
</button>
66+
<button class="lang-btn px-3 py-1.5 text-xs font-mono border border-cp-dark-400 rounded hover:border-cp-green-500 hover:text-cp-green-500 transition-colors" data-lang="zh">
67+
繁中
68+
</button>
69+
<button class="lang-btn px-3 py-1.5 text-xs font-mono border border-cp-dark-400 rounded hover:border-cp-green-500 hover:text-cp-green-500 transition-colors" data-lang="en">
70+
英文
71+
</button>
72+
</div>
1073
</div>
1174

12-
{% assign sorted_products = site.products | sort:page.sort %}
75+
<!-- Featured Section: 翻譯書籍 -->
76+
<div class="mb-10">
77+
<div class="flex items-center gap-3 mb-6">
78+
<div class="w-1 h-6 bg-cp-green-500 rounded"></div>
79+
<h2 class="text-lg font-bold font-mono text-cp-dark-800">繁體中文翻譯</h2>
80+
<span class="px-2 py-0.5 text-xs font-mono bg-cp-green-900/30 text-cp-green-400 rounded">我們翻譯的</span>
81+
</div>
1382

14-
{% for product in sorted_products %}
15-
<div class="column is-4-desktop is-6-tablet">
83+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-8">
84+
<a href="https://mastering-bitcoin.doge.tg/" target="_blank" class="card p-4 hover:border-cp-green-500 transition-colors group">
85+
<div class="flex items-start gap-3">
86+
<div class="w-10 h-10 rounded bg-cp-green-900/30 flex items-center justify-center text-cp-green-500 shrink-0">
87+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
88+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/>
89+
</svg>
90+
</div>
91+
<div>
92+
<h3 class="font-mono font-bold text-cp-dark-800 group-hover:text-cp-green-500 transition-colors">Mastering Bitcoin</h3>
93+
<p class="text-xs text-cp-dark-600">精通比特幣 2nd</p>
94+
</div>
95+
</div>
96+
</a>
1697

17-
<a href="{{ product.url | prepend: site.baseurl }}">
98+
<a href="https://bitcoinbook-3nd-zh.doge.tg/" target="_blank" class="card p-4 hover:border-cp-green-500 transition-colors group">
99+
<div class="flex items-start gap-3">
100+
<div class="w-10 h-10 rounded bg-cp-green-900/30 flex items-center justify-center text-cp-green-500 shrink-0">
101+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
102+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/>
103+
</svg>
104+
</div>
105+
<div>
106+
<h3 class="font-mono font-bold text-cp-dark-800 group-hover:text-cp-green-500 transition-colors">Mastering Bitcoin 3rd</h3>
107+
<p class="text-xs text-cp-dark-600">精通比特幣 3rd ⭐</p>
108+
</div>
109+
</div>
110+
</a>
18111

19-
<div class="card">
112+
<a href="https://programming-bitcoin-zh.doge.tg/" target="_blank" class="card p-4 hover:border-cp-green-500 transition-colors group">
113+
<div class="flex items-start gap-3">
114+
<div class="w-10 h-10 rounded bg-cp-green-900/30 flex items-center justify-center text-cp-green-500 shrink-0">
115+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
116+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/>
117+
</svg>
118+
</div>
119+
<div>
120+
<h3 class="font-mono font-bold text-cp-dark-800 group-hover:text-cp-green-500 transition-colors">Programming Bitcoin</h3>
121+
<p class="text-xs text-cp-dark-600">比特幣編程</p>
122+
</div>
123+
</div>
124+
</a>
20125

21-
{% if product.image %}
22-
<div class="card-image">
23-
<figure class="image is-4by3">
24-
<img src="{{ product.image }}" alt="{{ product.title }}" />
25-
</figure>
126+
<a href="https://lnbook-zh.doge.tg/" target="_blank" class="card p-4 hover:border-cp-green-500 transition-colors group">
127+
<div class="flex items-start gap-3">
128+
<div class="w-10 h-10 rounded bg-yellow-900/30 flex items-center justify-center text-yellow-500 shrink-0">
129+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
130+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
131+
</svg>
132+
</div>
133+
<div>
134+
<h3 class="font-mono font-bold text-cp-dark-800 group-hover:text-cp-green-500 transition-colors">Mastering Lightning</h3>
135+
<p class="text-xs text-cp-dark-600">精通閃電網路</p>
136+
</div>
26137
</div>
27-
{% endif %}
28-
<div class="card-content">
138+
</a>
29139

30-
<p class="title is-4">{{ product.title }}</h2>
31-
<p class="subtitle is-4">{{ product.subtitle }}</p>
32-
<p class="title is-5 has-text-right">{{ product.price }}</p>
140+
<a href="https://the-blocksize-war.doge.tg/" target="_blank" class="card p-4 hover:border-cp-green-500 transition-colors group">
141+
<div class="flex items-start gap-3">
142+
<div class="w-10 h-10 rounded bg-red-900/30 flex items-center justify-center text-red-500 shrink-0">
143+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
144+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
145+
</svg>
146+
</div>
147+
<div>
148+
<h3 class="font-mono font-bold text-cp-dark-800 group-hover:text-cp-green-500 transition-colors">The Blocksize War</h3>
149+
<p class="text-xs text-cp-dark-600">區塊大小之戰</p>
150+
</div>
151+
</div>
152+
</a>
153+
</div>
154+
</div>
155+
156+
<!-- All Products Grid -->
157+
<div class="mb-6">
158+
<div class="flex items-center gap-3 mb-6">
159+
<div class="w-1 h-6 bg-cp-dark-500 rounded"></div>
160+
<h2 class="text-lg font-bold font-mono text-cp-dark-800">所有資源</h2>
161+
</div>
162+
</div>
163+
164+
{% assign sorted_products = site.products | sort: page.sort %}
165+
166+
<div id="products-container" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
167+
{% for product in sorted_products %}
33168

169+
{% comment %} Determine category {% endcomment %}
170+
{% assign category = "other" %}
171+
{% assign title_lower = product.title | downcase %}
172+
{% assign subtitle_lower = product.subtitle | downcase %}
173+
174+
{% if title_lower contains "white paper" or title_lower contains "whitepaper" or subtitle_lower contains "白皮書" %}
175+
{% assign category = "whitepaper" %}
176+
{% elsif title_lower contains "lightning" or subtitle_lower contains "閃電" %}
177+
{% assign category = "lightning" %}
178+
{% elsif title_lower contains "bitcoin" or subtitle_lower contains "比特幣" %}
179+
{% assign category = "bitcoin" %}
180+
{% elsif title_lower contains "ethereum" or title_lower contains "monero" or subtitle_lower contains "以太" or subtitle_lower contains "門羅" %}
181+
{% assign category = "other" %}
182+
{% endif %}
183+
184+
{% comment %} Determine language {% endcomment %}
185+
{% assign lang = "en" %}
186+
{% if product.price contains "繁中" or product.price contains "Chinese" %}
187+
{% assign lang = "zh" %}
188+
{% endif %}
189+
190+
<article class="card group overflow-hidden product-card transition-all duration-300 hover:translate-y-[-2px] hover:border-cp-green-500/50"
191+
data-category="{{ category }}"
192+
data-lang="{{ lang }}">
193+
<a href="{{ product.url | relative_url }}" class="block h-full">
194+
<!-- Image Container -->
195+
<div class="relative overflow-hidden bg-cp-dark-200">
196+
{% if product.image %}
197+
<div class="aspect-[4/3] flex items-center justify-center p-4 bg-gradient-to-b from-cp-dark-100 to-cp-dark-200">
198+
<img
199+
src="{{ product.image | relative_url }}"
200+
alt="{{ product.title }}"
201+
class="max-w-full max-h-full object-contain transition-transform duration-500 group-hover:scale-105"
202+
loading="lazy"
203+
>
204+
</div>
205+
{% else %}
206+
<div class="aspect-[4/3] flex items-center justify-center bg-cp-dark-200">
207+
<svg class="w-16 h-16 text-cp-dark-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
208+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/>
209+
</svg>
210+
</div>
211+
{% endif %}
212+
213+
<!-- Category Badge -->
214+
<span class="absolute top-2 left-2 px-2 py-0.5 text-[10px] font-mono rounded
215+
{% if category == 'whitepaper' %}bg-purple-900/80 text-purple-300 border border-purple-700/50
216+
{% elsif category == 'lightning' %}bg-yellow-900/80 text-yellow-300 border border-yellow-700/50
217+
{% elsif category == 'bitcoin' %}bg-orange-900/80 text-orange-300 border border-orange-700/50
218+
{% else %}bg-cp-dark/80 text-cp-dark-600 border border-cp-dark-400{% endif %}">
219+
{% if category == 'whitepaper' %}白皮書
220+
{% elsif category == 'lightning' %}Lightning
221+
{% elsif category == 'bitcoin' %}Bitcoin
222+
{% else %}其他{% endif %}
223+
</span>
224+
225+
<!-- Language Badge -->
226+
<span class="absolute top-2 right-2 px-2 py-0.5 text-[10px] font-mono bg-cp-dark/80 text-cp-dark-600 border border-cp-dark-400 rounded">
227+
{% if lang == 'zh' %}繁中{% else %}EN{% endif %}
228+
</span>
34229
</div>
35-
</div>
36230

37-
</a>
231+
<!-- Content -->
232+
<div class="p-4">
233+
<h2 class="text-sm font-bold font-mono text-cp-dark-800 group-hover:text-cp-green-500 transition-colors mb-1 line-clamp-1">
234+
{{ product.title }}
235+
</h2>
236+
237+
{% if product.subtitle %}
238+
<p class="text-xs text-cp-dark-600 line-clamp-1 mb-2">
239+
{{ product.subtitle }}
240+
</p>
241+
{% endif %}
242+
243+
{% if product.description %}
244+
<p class="text-xs text-cp-dark-500 line-clamp-2">
245+
{{ product.description | truncate: 60 }}
246+
</p>
247+
{% endif %}
248+
</div>
249+
</a>
250+
</article>
251+
{% endfor %}
252+
</div>
253+
254+
<!-- Empty State -->
255+
<div id="empty-state" class="hidden text-center py-16">
256+
<svg class="w-16 h-16 text-cp-dark-400 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
257+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
258+
</svg>
259+
<p class="text-cp-dark-600 font-mono">沒有符合條件的資源</p>
260+
<button onclick="resetFilters()" class="mt-4 text-cp-green-500 hover:underline font-mono text-sm">
261+
清除篩選
262+
</button>
263+
</div>
38264

265+
<!-- CTA -->
266+
<div class="mt-12 text-center p-6 card">
267+
<p class="text-cp-dark-600 font-mono mb-4">
268+
想要貢獻翻譯或回報問題?
269+
</p>
270+
<a href="https://github.com/cypherpunks-core" target="_blank" rel="noopener noreferrer" class="inline-flex items-center gap-2 text-cp-green-500 hover:text-cp-green-400 font-mono text-sm">
271+
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
272+
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.477 2 2 6.477 2 12c0 4.42 2.865 8.17 6.839 9.49.5.092.682-.217.682-.482 0-.237-.008-.866-.013-1.7-2.782.604-3.369-1.34-3.369-1.34-.454-1.156-1.11-1.464-1.11-1.464-.908-.62.069-.608.069-.608 1.003.07 1.531 1.03 1.531 1.03.892 1.529 2.341 1.087 2.91.831.092-.646.35-1.086.636-1.336-2.22-.253-4.555-1.11-4.555-4.943 0-1.091.39-1.984 1.029-2.683-.103-.253-.446-1.27.098-2.647 0 0 .84-.269 2.75 1.025A9.578 9.578 0 0112 6.836c.85.004 1.705.114 2.504.336 1.909-1.294 2.747-1.025 2.747-1.025.546 1.377.203 2.394.1 2.647.64.699 1.028 1.592 1.028 2.683 0 3.842-2.339 4.687-4.566 4.935.359.309.678.919.678 1.852 0 1.336-.012 2.415-.012 2.743 0 .267.18.578.688.48C19.138 20.167 22 16.418 22 12c0-5.523-4.477-10-10-10z"/>
273+
</svg>
274+
前往 GitHub
275+
</a>
39276
</div>
40-
{% endfor %}
41277
</div>
42278

279+
<script>
280+
document.addEventListener('DOMContentLoaded', function() {
281+
const filterBtns = document.querySelectorAll('.filter-btn');
282+
const langBtns = document.querySelectorAll('.lang-btn');
283+
const cards = document.querySelectorAll('.product-card');
284+
const emptyState = document.getElementById('empty-state');
285+
const container = document.getElementById('products-container');
286+
287+
let currentCategory = 'all';
288+
let currentLang = 'all';
289+
290+
function updateDisplay() {
291+
let visibleCount = 0;
292+
293+
cards.forEach(card => {
294+
const cardCategory = card.dataset.category;
295+
const cardLang = card.dataset.lang;
296+
297+
const categoryMatch = currentCategory === 'all' || cardCategory === currentCategory;
298+
const langMatch = currentLang === 'all' || cardLang === currentLang;
299+
300+
if (categoryMatch && langMatch) {
301+
card.style.display = '';
302+
visibleCount++;
303+
} else {
304+
card.style.display = 'none';
305+
}
306+
});
307+
308+
if (visibleCount === 0) {
309+
emptyState.classList.remove('hidden');
310+
container.classList.add('hidden');
311+
} else {
312+
emptyState.classList.add('hidden');
313+
container.classList.remove('hidden');
314+
}
315+
}
316+
317+
// Category filter
318+
filterBtns.forEach(btn => {
319+
btn.addEventListener('click', function() {
320+
currentCategory = this.dataset.filter;
321+
322+
filterBtns.forEach(b => {
323+
b.classList.remove('border-cp-green-500', 'text-cp-green-500', 'active');
324+
b.classList.add('border-cp-dark-400');
325+
});
326+
this.classList.add('border-cp-green-500', 'text-cp-green-500', 'active');
327+
this.classList.remove('border-cp-dark-400');
328+
329+
updateDisplay();
330+
});
331+
});
332+
333+
// Language filter
334+
langBtns.forEach(btn => {
335+
btn.addEventListener('click', function() {
336+
currentLang = this.dataset.lang;
337+
338+
langBtns.forEach(b => {
339+
b.classList.remove('border-cp-green-500', 'text-cp-green-500', 'active');
340+
b.classList.add('border-cp-dark-400');
341+
});
342+
this.classList.add('border-cp-green-500', 'text-cp-green-500', 'active');
343+
this.classList.remove('border-cp-dark-400');
344+
345+
updateDisplay();
346+
});
347+
});
348+
349+
// Reset filters function
350+
window.resetFilters = function() {
351+
currentCategory = 'all';
352+
currentLang = 'all';
353+
354+
filterBtns.forEach(b => {
355+
b.classList.remove('border-cp-green-500', 'text-cp-green-500', 'active');
356+
b.classList.add('border-cp-dark-400');
357+
if (b.dataset.filter === 'all') {
358+
b.classList.add('border-cp-green-500', 'text-cp-green-500', 'active');
359+
b.classList.remove('border-cp-dark-400');
360+
}
361+
});
362+
363+
langBtns.forEach(b => {
364+
b.classList.remove('border-cp-green-500', 'text-cp-green-500', 'active');
365+
b.classList.add('border-cp-dark-400');
366+
if (b.dataset.lang === 'all') {
367+
b.classList.add('border-cp-green-500', 'text-cp-green-500', 'active');
368+
b.classList.remove('border-cp-dark-400');
369+
}
370+
});
371+
372+
updateDisplay();
373+
};
374+
});
375+
</script>

0 commit comments

Comments
 (0)