fix planet
This commit is contained in:
		
							
								
								
									
										1
									
								
								.github/workflows/gh-pages.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/gh-pages.yml
									
									
									
									
										vendored
									
									
								
							| @@ -30,5 +30,6 @@ jobs: | |||||||
|       with: |       with: | ||||||
|         github_token: ${{ secrets.GITHUB_TOKEN }} |         github_token: ${{ secrets.GITHUB_TOKEN }} | ||||||
|         publish_dir: ./dist |         publish_dir: ./dist | ||||||
|  |         force_orphan: true | ||||||
|         user_name: 'ai[bot]' |         user_name: 'ai[bot]' | ||||||
|         user_email: '138105980+yui-syui-ai[bot]@users.noreply.github.com' |         user_email: '138105980+yui-syui-ai[bot]@users.noreply.github.com' | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -7,3 +7,4 @@ package-lock.json | |||||||
| yarn.lock | yarn.lock | ||||||
| **DS_Store | **DS_Store | ||||||
| .claude | .claude | ||||||
|  | repos | ||||||
|   | |||||||
| @@ -1,14 +1,35 @@ | |||||||
| import { useQuery } from '@tanstack/react-query'; | import { useQuery, useQueryClient } from '@tanstack/react-query'; | ||||||
|  | import { useEffect } from 'react'; | ||||||
| import Navigation from '../common/Navigation'; | import Navigation from '../common/Navigation'; | ||||||
| import { fetchUsers } from '../../utils/api'; | import { fetchUsersWithCache } from '../../utils/api'; | ||||||
|  | import { api } from '../../utils/api'; | ||||||
|  |  | ||||||
| export default function HomePage() { | export default function HomePage() { | ||||||
|  |   const queryClient = useQueryClient(); | ||||||
|    |    | ||||||
|   const { data: users, isLoading } = useQuery({ |   const { data: users, isLoading } = useQuery({ | ||||||
|     queryKey: ['users'], |     queryKey: ['users'], | ||||||
|     queryFn: () => fetchUsers() |     queryFn: () => fetchUsersWithCache(), | ||||||
|  |     staleTime: 0, // Always consider data stale | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|  |   // Refresh with API data after cache load | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (users?.isFromCache) { | ||||||
|  |       // Fetch fresh data from API in background | ||||||
|  |       api.get('users?itemsPerPage=8000').then(response => { | ||||||
|  |         console.log('Background API fetch successful, got', response.data.length, 'users with planet data'); | ||||||
|  |         // Update the query cache with fresh data | ||||||
|  |         queryClient.setQueryData(['users'], { | ||||||
|  |           data: response.data, | ||||||
|  |           isFromCache: false | ||||||
|  |         }); | ||||||
|  |       }).catch(error => { | ||||||
|  |         console.error('Background API fetch failed:', error); | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   }, [users?.isFromCache, queryClient]); | ||||||
|  |  | ||||||
|   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"> | ||||||
|   | |||||||
| @@ -4,17 +4,27 @@ import Navigation from '../common/Navigation'; | |||||||
| import CardGrid from '../card/CardGrid'; | import CardGrid from '../card/CardGrid'; | ||||||
| import UserProfile from '../user/UserProfile'; | import UserProfile from '../user/UserProfile'; | ||||||
| import SpecialCard from '../card/SpecialCard'; | import SpecialCard from '../card/SpecialCard'; | ||||||
| import { fetchUsers, fetchUserCards } from '../../utils/api'; | import { fetchUsers, fetchUserCards, fetchUser } from '../../utils/api'; | ||||||
|  |  | ||||||
| export default function UserPage() { | export default function UserPage() { | ||||||
|   const { username } = useParams<{ username: string }>(); |   const { username } = useParams<{ username: string }>(); | ||||||
|    |    | ||||||
|  |   // First get users list to find the user ID | ||||||
|   const { data: users, isLoading } = useQuery({ |   const { data: users, isLoading } = useQuery({ | ||||||
|     queryKey: ['users'], |     queryKey: ['users'], | ||||||
|     queryFn: () => fetchUsers(), |     queryFn: () => fetchUsers(), | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   const user = users?.data.find(u => u.username === username); |   const userId = users?.data.find(u => u.username === username)?.id; | ||||||
|  |    | ||||||
|  |   // Then fetch full user data from API to get planet value | ||||||
|  |   const { data: userResponse } = useQuery({ | ||||||
|  |     queryKey: ['user', userId], | ||||||
|  |     queryFn: () => fetchUser(userId!), | ||||||
|  |     enabled: !!userId, | ||||||
|  |   }); | ||||||
|  |    | ||||||
|  |   const user = userResponse?.data || users?.data.find(u => u.username === username); | ||||||
|    |    | ||||||
|   const { data: cards, isLoading: cardsLoading } = useQuery({ |   const { data: cards, isLoading: cardsLoading } = useQuery({ | ||||||
|     queryKey: ['userCards', user?.id], |     queryKey: ['userCards', user?.id], | ||||||
|   | |||||||
| @@ -6,14 +6,6 @@ interface UserProfileProps { | |||||||
| } | } | ||||||
|  |  | ||||||
| export default function UserProfile({ user, cards }: UserProfileProps) { | export default function UserProfile({ user, cards }: UserProfileProps) { | ||||||
|   const formatPlanet = (planet: number) => { |  | ||||||
|     if (planet >= 1000000) { |  | ||||||
|       return `${(planet / 1000000).toFixed(2)}M`; |  | ||||||
|     } else if (planet >= 1000) { |  | ||||||
|       return `${(planet / 1000).toFixed(2)}K`; |  | ||||||
|     } |  | ||||||
|     return planet.toLocaleString(); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <div className="bg-white rounded-lg p-6 mb-8"> |     <div className="bg-white rounded-lg p-6 mb-8"> | ||||||
| @@ -38,7 +30,7 @@ export default function UserProfile({ user, cards }: UserProfileProps) { | |||||||
|         )} |         )} | ||||||
|       </h3> |       </h3> | ||||||
|  |  | ||||||
|       <div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm"> |       <div className="grid grid-cols-2 md:grid-cols-5 gap-4 text-sm"> | ||||||
|         <div> |         <div> | ||||||
|           <strong>ID:</strong> {user.id} |           <strong>ID:</strong> {user.id} | ||||||
|         </div> |         </div> | ||||||
| @@ -54,12 +46,10 @@ export default function UserProfile({ user, cards }: UserProfileProps) { | |||||||
|           <span className="icon-ai"></span> |           <span className="icon-ai"></span> | ||||||
|           {cards.filter(c => c.card >= 96 && c.card <= 121).length} |           {cards.filter(c => c.card >= 96 && c.card <= 121).length} | ||||||
|         </div> |         </div> | ||||||
|         {user.planet && ( |         <div className="flex items-center gap-1"> | ||||||
|           <div className="flex items-center gap-1"> |           <i className="fa-solid fa-earth-americas"></i> | ||||||
|             <i className="fa-solid fa-earth-americas"></i> |           {user.planet?.toLocaleString() || '0'} | ||||||
|             {formatPlanet(user.planet)} |         </div> | ||||||
|           </div> |  | ||||||
|         )} |  | ||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
|       {/* Badge Images */} |       {/* Badge Images */} | ||||||
|   | |||||||
| @@ -15,32 +15,44 @@ export const api = axios.create({ | |||||||
| // API関数 | // API関数 | ||||||
| export const fetchUsers = async (itemsPerPage = 8000): Promise<{ data: User[] }> => { | export const fetchUsers = async (itemsPerPage = 8000): Promise<{ data: User[] }> => { | ||||||
|   try { |   try { | ||||||
|     // First try to load cached users.json for fast initial loading |     // Directly fetch from API to get complete user data including planet | ||||||
|     const cachedResponse = await axios.get('/json/users.json'); |     const response = await api.get(`users?itemsPerPage=${itemsPerPage}`); | ||||||
|      |     return { data: response.data }; | ||||||
|     // Background fetch for fresh data |  | ||||||
|     setTimeout(async () => { |  | ||||||
|       try { |  | ||||||
|         await api.get(`users?itemsPerPage=${itemsPerPage}`); |  | ||||||
|       } catch (error) { |  | ||||||
|         console.error('Background fetch failed:', error); |  | ||||||
|       } |  | ||||||
|     }, 100); |  | ||||||
|      |  | ||||||
|     return { data: cachedResponse.data }; |  | ||||||
|   } catch (error) { |   } catch (error) { | ||||||
|     console.error('Failed to fetch cached users:', error); |     console.error('Failed to fetch users from API:', error); | ||||||
|     // Fallback to API if cached JSON fails |     // Fallback to cached data (but it doesn't have planet field) | ||||||
|     try { |     try { | ||||||
|       const response = await api.get(`users?itemsPerPage=${itemsPerPage}`); |       const cachedResponse = await axios.get('/json/users.json'); | ||||||
|       return { data: response.data }; |       return { data: cachedResponse.data }; | ||||||
|     } catch (apiError) { |     } catch (cacheError) { | ||||||
|       console.error('API fallback failed:', apiError); |       console.error('Cache fallback failed:', cacheError); | ||||||
|       return { data: [] }; |       return { data: [] }; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | // Fetch users with cache-first strategy for home page | ||||||
|  | export const fetchUsersWithCache = async (): Promise<{ data: User[], isFromCache?: boolean }> => { | ||||||
|  |   try { | ||||||
|  |     // First, try to get cached data | ||||||
|  |     console.log('Attempting to load cached users.json'); | ||||||
|  |     const cachedResponse = await axios.get('/json/users.json'); | ||||||
|  |     console.log('Successfully loaded cached data:', cachedResponse.data.length, 'users'); | ||||||
|  |     return { data: cachedResponse.data, isFromCache: true }; | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error('Cache read failed, fetching from API:', error); | ||||||
|  |     // If cache fails, fetch from API | ||||||
|  |     try { | ||||||
|  |       const response = await api.get('users?itemsPerPage=8000'); | ||||||
|  |       console.log('Successfully loaded from API:', response.data.length, 'users'); | ||||||
|  |       return { data: response.data, isFromCache: false }; | ||||||
|  |     } catch (apiError) { | ||||||
|  |       console.error('API fetch also failed:', apiError); | ||||||
|  |       return { data: [], isFromCache: false }; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
| export const fetchUserCards = async (userId: number, itemsPerPage = 8000): Promise<{ data: Card[] }> => { | export const fetchUserCards = async (userId: number, itemsPerPage = 8000): Promise<{ data: Card[] }> => { | ||||||
|   try { |   try { | ||||||
|     const response = await api.get(`users/${userId}/card?itemsPerPage=${itemsPerPage}`); |     const response = await api.get(`users/${userId}/card?itemsPerPage=${itemsPerPage}`); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user