Add favorite cards display on homepage
- Fetch and display users' favorite cards at the top of homepage - Filter users with fav \!== '0' to avoid empty display - Use useQueries to fetch multiple users' cards in parallel - Display cards in grid layout with owner username below - Cards are shown above the user list section 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		| @@ -85,18 +85,6 @@ export default function DocsPage({ isEnglish = false, page }: DocsPageProps) { | |||||||
|           </tbody> |           </tbody> | ||||||
|         </table> |         </table> | ||||||
|  |  | ||||||
|         <h3>{isEnglish ? 'Battle' : '対戦について'}</h3> |  | ||||||
|         <p><code>@yui.syui.ai /card -b</code></p> |  | ||||||
|         <p>{isEnglish ? 'Random match, one of the top 3 cards on hand will be chosen at random' : 'ランダムマッチ、手持ちの上位3枚のうち1枚がランダムで選ばれます'}</p> |  | ||||||
|  |  | ||||||
|         <h3>Mastodon</h3> |  | ||||||
|         <p> |  | ||||||
|           <code> |  | ||||||
|             <a href="https://mstdn.syui.ai/@yui" target="_blank" rel="noopener noreferrer"> |  | ||||||
|               @yui@syui.ai |  | ||||||
|             </a> /card |  | ||||||
|           </code> |  | ||||||
|         </p> |  | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
|   }; |   }; | ||||||
| @@ -112,4 +100,4 @@ export default function DocsPage({ isEnglish = false, page }: DocsPageProps) { | |||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,6 +1,8 @@ | |||||||
| import { useQuery } from '@tanstack/react-query'; | import { useQuery, useQueries } from '@tanstack/react-query'; | ||||||
| import Navigation from '../common/Navigation'; | import Navigation from '../common/Navigation'; | ||||||
| import { fetchUsers } from '../../utils/api'; | import { fetchUsers, fetchUserCards } from '../../utils/api'; | ||||||
|  | import SpecialCard from '../card/SpecialCard'; | ||||||
|  | import type { Card } from '../../types'; | ||||||
|  |  | ||||||
| export default function HomePage() { | export default function HomePage() { | ||||||
|    |    | ||||||
| @@ -9,6 +11,30 @@ export default function HomePage() { | |||||||
|     queryFn: () => fetchUsers() |     queryFn: () => fetchUsers() | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|  |   // Get all users with fav cards | ||||||
|  |   const usersWithFav = users?.data?.filter(user => user.fav && user.fav !== '0') || []; | ||||||
|  |    | ||||||
|  |   // Fetch cards for each user with fav | ||||||
|  |   const favCardQueries = useQueries({ | ||||||
|  |     queries: usersWithFav.map(user => ({ | ||||||
|  |       queryKey: ['userCards', user.id], | ||||||
|  |       queryFn: () => fetchUserCards(user.id), | ||||||
|  |       enabled: !!user.id | ||||||
|  |     })) | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   // Extract fav cards | ||||||
|  |   const favCards: { user: typeof usersWithFav[0], card: Card }[] = []; | ||||||
|  |   usersWithFav.forEach((user, index) => { | ||||||
|  |     const userCards = favCardQueries[index]?.data?.data; | ||||||
|  |     if (userCards && user.fav) { | ||||||
|  |       const favCard = userCards.find(card => card.id === parseInt(user.fav)); | ||||||
|  |       if (favCard) { | ||||||
|  |         favCards.push({ user, card: favCard }); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |  | ||||||
|   if (isLoading) { |   if (isLoading) { | ||||||
|     return ( |     return ( | ||||||
|       <div className="min-h-screen flex items-center justify-center"> |       <div className="min-h-screen flex items-center justify-center"> | ||||||
| @@ -28,6 +54,25 @@ export default function HomePage() { | |||||||
|           <a href="/docs" className="btn">help</a> |           <a href="/docs" className="btn">help</a> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|  |         {/* Favorite Cards Section */} | ||||||
|  |         {favCards.length > 0 && ( | ||||||
|  |           <div className="mb-8"> | ||||||
|  |             <h2 className="text-xl font-bold mb-4">Favorite Cards</h2> | ||||||
|  |             <div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4"> | ||||||
|  |               {favCards.map(({ user, card }) => ( | ||||||
|  |                 <div key={`${user.id}-${card.id}`}> | ||||||
|  |                   <SpecialCard card={card} /> | ||||||
|  |                   <div className="text-center text-sm mt-2"> | ||||||
|  |                     <a href={`/${user.username}`} className="text-gray-600 hover:text-primary"> | ||||||
|  |                       @{user.username} | ||||||
|  |                     </a> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               ))} | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |         )} | ||||||
|  |  | ||||||
|         {users?.data && Array.isArray(users.data) && users.data.length > 0 && ( |         {users?.data && Array.isArray(users.data) && users.data.length > 0 && ( | ||||||
|           <div className="bg-white rounded-lg p-6"> |           <div className="bg-white rounded-lg p-6"> | ||||||
|             <div className="grid gap-4"> |             <div className="grid gap-4"> | ||||||
|   | |||||||
| @@ -52,6 +52,16 @@ export const fetchUserCards = async (userId: number, itemsPerPage = 8000): Promi | |||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export const fetchCardById = async (cardId: number): Promise<Card | null> => { | ||||||
|  |   try { | ||||||
|  |     const response = await api.get(`cards/${cardId}`); | ||||||
|  |     return response.data; | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error('Failed to fetch card by ID:', error); | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
| export const fetchUser = async (userId: number): Promise<{ data: User }> => { | export const fetchUser = async (userId: number): Promise<{ data: User }> => { | ||||||
|   const response = await api.get(`users/${userId}`); |   const response = await api.get(`users/${userId}`); | ||||||
|   return response.data; |   return response.data; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user