mirror of
https://github.com/danilo-znamerovszkij/c-atlas.git
synced 2025-12-23 22:17:53 -05:00
✨ add loading state functionality to ItemDetailsPanel and improve routing logic with caching
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
border-left: 1px solid rgba(148, 163, 184, 0.2);
|
||||
box-shadow: -10px 0 30px rgba(0, 0, 0, 0.3),
|
||||
inset 0 0 50px rgba(59, 130, 246, 0.05);
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
z-index: 1000;
|
||||
overflow-y: auto;
|
||||
transform: translateX(0);
|
||||
@@ -124,7 +124,7 @@
|
||||
}
|
||||
|
||||
.item-content {
|
||||
animation: slideInUp 0.5s ease-out;
|
||||
animation: slideInUp 0.2s ease-out;
|
||||
|
||||
.item-header {
|
||||
margin-bottom: 24px;
|
||||
@@ -218,7 +218,7 @@
|
||||
}
|
||||
|
||||
.theory-content {
|
||||
animation: slideInUp 0.5s ease-out;
|
||||
animation: slideInUp 0.2s ease-out;
|
||||
|
||||
.theory-header {
|
||||
margin-bottom: 28px;
|
||||
@@ -558,6 +558,40 @@
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-content {
|
||||
animation: slideInUp 0.5s ease-out;
|
||||
text-align: center;
|
||||
padding: 48px 24px;
|
||||
|
||||
.theory-breadcrumb {
|
||||
color: #fcd771;
|
||||
font-size: 14px;
|
||||
margin-bottom: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid rgba(148, 163, 184, 0.2);
|
||||
border-top: 3px solid #fcd771;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto 16px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: #fcd771;
|
||||
margin-bottom: 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #94a3b8;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -595,6 +629,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive adjustments
|
||||
@media (max-width: 1024px) {
|
||||
.item-details-panel {
|
||||
|
||||
@@ -649,6 +649,41 @@ export class ItemDetailsPanel {
|
||||
}
|
||||
}
|
||||
|
||||
public showLoading(category: string, theory: string) {
|
||||
this.isVisible = true
|
||||
const panel = this.container.querySelector('.item-details-panel')
|
||||
panel?.classList.add('visible')
|
||||
panel?.setAttribute('aria-hidden', 'false')
|
||||
|
||||
// Convert theory slug to display name
|
||||
const theoryName = theory.replace(/-/g, ' ')
|
||||
.split(' ')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ')
|
||||
|
||||
// Convert category slug to display name
|
||||
const categoryName = category.charAt(0).toUpperCase() + category.slice(1)
|
||||
|
||||
// Update the title
|
||||
const titleElement = this.container.querySelector('#item-title')
|
||||
if (titleElement) {
|
||||
titleElement.textContent = theoryName
|
||||
}
|
||||
|
||||
// Update the content with loading message and breadcrumb
|
||||
const infoElement = this.container.querySelector('#item-info')
|
||||
if (infoElement) {
|
||||
infoElement.innerHTML = `
|
||||
<div class="loading-content">
|
||||
<div class="theory-breadcrumb">${categoryName} • ${theoryName}</div>
|
||||
<div class="loading-spinner"></div>
|
||||
<h3>Loading theory data...</h3>
|
||||
<p>Please wait while we fetch the detailed information.</p>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
public hide() {
|
||||
this.isVisible = false
|
||||
const panel = this.container.querySelector('.item-details-panel')
|
||||
|
||||
@@ -61,6 +61,11 @@ itemDetailsPanel.setCloseCallback(() => {
|
||||
router.goHome()
|
||||
})
|
||||
|
||||
// Set up loading callback to show loading state
|
||||
router.setLoadingCallback((category, theory) => {
|
||||
itemDetailsPanel.showLoading(category, theory)
|
||||
})
|
||||
|
||||
// Set up routing callback to show theory data when URL changes
|
||||
router.setTheoryChangeCallback((theory, error) => {
|
||||
if (theory) {
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import type { TheoryData } from '../types/theory'
|
||||
import { generateSlug } from './slugUtils'
|
||||
|
||||
// Simple cache for theory data
|
||||
const theoryCache = new Map<string, TheoryData>()
|
||||
|
||||
async function loadTheoryByName(theoryName: string): Promise<TheoryData> {
|
||||
// Check cache first
|
||||
if (theoryCache.has(theoryName)) {
|
||||
return theoryCache.get(theoryName)!
|
||||
}
|
||||
const fileName = `${theoryName}.json`
|
||||
const filePath = `/data/${fileName}`
|
||||
|
||||
@@ -12,6 +18,8 @@ async function loadTheoryByName(theoryName: string): Promise<TheoryData> {
|
||||
throw new Error(`Failed to load theory data: ${response.statusText}`)
|
||||
}
|
||||
const theoryData = await response.json() as TheoryData
|
||||
// Cache the result
|
||||
theoryCache.set(theoryName, theoryData)
|
||||
return theoryData
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to load theory data: ${error}`)
|
||||
@@ -22,6 +30,7 @@ export class Router {
|
||||
private static instance: Router
|
||||
private currentTheory: TheoryData | null = null
|
||||
private onTheoryChange: ((theory: TheoryData | null, error?: string) => void) | null = null
|
||||
private onLoading: ((category: string, theory: string) => void) | null = null
|
||||
|
||||
private constructor() {
|
||||
this.setupPopstateListener()
|
||||
@@ -39,6 +48,10 @@ export class Router {
|
||||
this.onTheoryChange = callback
|
||||
}
|
||||
|
||||
public setLoadingCallback(callback: (category: string, theory: string) => void) {
|
||||
this.onLoading = callback
|
||||
}
|
||||
|
||||
private setupPopstateListener() {
|
||||
window.addEventListener('popstate', () => {
|
||||
this.parseCurrentURL()
|
||||
@@ -53,6 +66,9 @@ export class Router {
|
||||
const category = segments[0]
|
||||
const theory = segments[1]
|
||||
|
||||
// Show loading state with category and theory info
|
||||
this.onLoading?.(category, theory)
|
||||
|
||||
try {
|
||||
const theoryData = await this.loadTheory(category, theory)
|
||||
this.currentTheory = theoryData
|
||||
|
||||
Reference in New Issue
Block a user