@@ -7,9 +7,6 @@ import { featureCards } from '../data/featureCards.js';
77
88// 모든 FeatureCard 데이터 가져오기
99const allCards = featureCards ;
10-
11- // 고유한 작성자 목록 가져오기 (필터 옵션용)
12- const uniqueAuthors = [... new Set (featureCards .map (card => card .author ))];
1310---
1411
1512<Layout >
@@ -21,43 +18,13 @@ const uniqueAuthors = [...new Set(featureCards.map(card => card.author))];
2118 <!-- blazing.cpp project study posts. -->
2219 </p >
2320
24- <div class =" controls" >
25- <div class =" filter-controls" >
26- <label for =" author-filter" >Filter by Author:</label >
27- <select id =" author-filter" onchange =" applyFiltersAndSort ()" >
28- <option value =" " >All Authors</option >
29- { uniqueAuthors .map (author => (
30- <option value = { author } >
31- { author }
32- </option >
33- ))}
34- </select >
35- </div >
36-
37- <div class =" sort-controls" >
38- <label for =" sort-by" >Sort by:</label >
39- <select id =" sort-by" onchange =" applyFiltersAndSort ()" >
40- <option value =" date" selected >Date</option >
41- <option value =" author" >Author</option >
42- </select >
43-
44- <label for =" sort-order" >Order:</label >
45- <select id =" sort-order" onchange =" applyFiltersAndSort ()" >
46- <option value =" desc" selected >Descending</option >
47- <option value =" asc" >Ascending</option >
48- </select >
49- </div >
50- </div >
51-
52- <div id =" cards-container" >
53- { allCards .map ((card , index ) => (
54- <div class = " card-wrapper" data-author = { card .author } data-date = { card .date } data-index = { index } >
55- <FeatureCard
56- url = { card .url }
57- date = { card .date }
58- author = { card .author }
59- />
60- </div >
21+ <div class =" cards-container" >
22+ { allCards .map ((card ) => (
23+ <FeatureCard
24+ url = { card .url }
25+ date = { card .date }
26+ author = { card .author }
27+ />
6128 ))}
6229 </div >
6330
@@ -131,207 +98,10 @@ const uniqueAuthors = [...new Set(featureCards.map(card => card.author))];
13198 }
13299 }
133100
134- .controls {
135- display: flex;
136- justify-content: space-between;
137- align-items: center;
138- margin-bottom: 3rem;
139- padding: 1.5rem 2rem;
140- background: var(--theme-bg);
141- border: 1px solid rgba(var(--theme-primary-rgb, 79, 70, 229), 0.1);
142- border-radius: 1rem;
143- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
144- transition: all 0.3s ease;
145- }
146-
147- .controls:hover {
148- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
149- border-color: rgba(var(--theme-primary-rgb, 79, 70, 229), 0.2);
150- }
151-
152- .filter-controls, .sort-controls {
153- display: flex;
154- align-items: center;
155- gap: 1rem;
156- }
157-
158- .controls label {
159- font-weight: 500;
160- font-size: 0.875rem;
161- color: var(--theme-on-surface);
162- letter-spacing: 0.025em;
163- margin-right: 0.25rem;
164- }
165-
166- .controls select {
167- padding: 0.625rem 1rem;
168- border: 1px solid rgba(var(--theme-primary-rgb, 79, 70, 229), 0.15);
169- border-radius: 0.5rem;
170- background-color: var(--theme-bg);
171- color: var(--theme-on-bg);
172- font-size: 0.875rem;
173- font-weight: 500;
174- cursor: pointer;
175- transition: all 0.2s ease;
176- outline: none;
177- appearance: none;
178- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");
179- background-position: right 0.75rem center;
180- background-repeat: no-repeat;
181- background-size: 1rem;
182- padding-right: 2.5rem;
183- }
184-
185- .controls select:hover {
186- border-color: rgba(var(--theme-primary-rgb, 79, 70, 229), 0.3);
187- background-color: rgba(var(--theme-primary-rgb, 79, 70, 229), 0.02);
188- }
189-
190- .controls select:focus {
191- border-color: var(--theme-primary);
192- box-shadow: 0 0 0 3px rgba(var(--theme-primary-rgb, 79, 70, 229), 0.1);
193- }
194-
195- @media (max-width: 768px) {
196- .controls {
197- flex-direction: column;
198- gap: 1.5rem;
199- align-items: stretch;
200- padding: 1.25rem;
201- }
202-
203- .filter-controls, .sort-controls {
204- justify-content: space-between;
205- flex-wrap: wrap;
206- gap: 0.75rem;
207- }
208-
209- .controls select {
210- min-width: 120px;
211- }
212- }
213-
214101 /* 카드 컨테이너 레이아웃 */
215- # cards-container {
102+ . cards-container {
216103 display: flex;
217104 flex-direction: column;
218- gap: 1rem;
219- }
220-
221- .card-wrapper {
222- width: 100%;
105+ gap: 0.5rem;
223106 }
224107</style >
225-
226- <script is:inline >
227- // 모든 카드 데이터 (서버에서 가져온 데이터)
228- const allCardsData = [
229- {
230- url: "https://bayernmuller.github.io/blog/250719-javascript-vector-cosine-distance/",
231- date: "2025-07-19",
232- author: "BayernMuller"
233- },
234- {
235- url: "https://github.com/withastro/astro",
236- date: "2024-01-15",
237- author: "astro"
238- },
239- {
240- url: "https://github.com/tailwindlabs/tailwindcss",
241- date: "2024-01-10",
242- author: "tailwindlabs"
243- },
244- {
245- url: "https://github.com/vuejs/vue",
246- date: "2024-01-08",
247- author: "vuejs"
248- },
249- {
250- url: "https://github.com/facebook/react",
251- date: "2024-01-05",
252- author: "facebook"
253- },
254- {
255- url: "https://github.com/nodejs/node",
256- date: "2024-01-03",
257- author: "nodejs"
258- },
259- {
260- url: "https://astro.build/blog/astro-4/",
261- date: "2023-12-05",
262- author: "astro"
263- },
264- {
265- url: "https://tailwindcss.com/blog/tailwindcss-v3-4",
266- date: "2023-12-10",
267- author: "tailwindlabs"
268- },
269- {
270- url: "https://reactjs.org/blog/2023/03/16/introducing-react-dev.html",
271- date: "2023-03-16",
272- author: "facebook"
273- }
274- ];
275-
276- function applyFiltersAndSort() {
277- const authorFilter = document.getElementById('author-filter').value;
278- const sortBy = document.getElementById('sort-by').value;
279- const sortOrder = document.getElementById('sort-order').value;
280-
281- console.log('Filtering and sorting:', { authorFilter, sortBy, sortOrder });
282-
283- // 필터링
284- let filteredCards = allCardsData;
285- if (authorFilter) {
286- filteredCards = allCardsData.filter(card => card.author === authorFilter);
287- }
288-
289- // 정렬
290- if (sortBy === 'date') {
291- filteredCards.sort((a, b) => {
292- const dateA = new Date(a.date).getTime();
293- const dateB = new Date(b.date).getTime();
294- return sortOrder === 'desc' ? dateB - dateA : dateA - dateB;
295- });
296- } else if (sortBy === 'author') {
297- filteredCards.sort((a, b) => {
298- return sortOrder === 'desc'
299- ? b.author.localeCompare(a.author)
300- : a.author.localeCompare(b.author);
301- });
302- }
303-
304- // 카드 컨테이너 업데이트
305- updateCardsDisplay(filteredCards);
306- }
307-
308- function updateCardsDisplay(cards) {
309- const container = document.getElementById('cards-container');
310- const allWrappers = container.querySelectorAll('.card-wrapper');
311-
312- // 모든 카드 숨기기
313- allWrappers.forEach(wrapper => {
314- wrapper.style.display = 'none';
315- });
316-
317- // 필터링된 카드들을 순서대로 보이기
318- cards.forEach((card, newIndex) => {
319- // 해당 카드 찾기
320- const matchingWrapper = Array.from(allWrappers).find(wrapper =>
321- wrapper.dataset.author === card.author &&
322- wrapper.dataset.date === card.date
323- );
324-
325- if (matchingWrapper) {
326- matchingWrapper.style.display = 'block';
327- matchingWrapper.style.order = newIndex;
328- }
329- });
330- }
331-
332- // DOM 로드 후 초기화
333- document.addEventListener('DOMContentLoaded', function() {
334- console.log('DOM loaded, initializing filters');
335- applyFiltersAndSort(); // 초기 정렬 적용
336- });
337- </script >
0 commit comments