> ## Documentation Index
> Fetch the complete documentation index at: https://devperez08-platform-list-anime-54.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# React Components

> Documentation for all React components in the EpiNeko application

## Component Architecture

EpiNeko uses client-side React components with TypeScript for type safety. All components are organized by feature area and follow consistent patterns.

## Anime Components

### AnimeCard

Display component for anime thumbnails in lists and grids.

<Accordion title="Props Interface">
  ```typescript theme={null}
  interface AnimeCardProps {
    mal_id: number;      // MyAnimeList ID
    image: string;       // Poster image URL
    title: string;       // Anime title
    score?: string;      // Rating score (optional)
    onClick?: () => void; // Click handler (optional)
  }
  ```
</Accordion>

**Features:**

* Hover animations with scale and shadow effects
* Rating badge overlay on hover
* Fallback image for loading errors
* Responsive sizing (w-44 on mobile, w-56 on desktop)
* 2:3 aspect ratio for consistent layout

**Usage Example:**

```tsx theme={null}
import AnimeCard from '@/components/anime/AnimeCard';

<AnimeCard
  mal_id={anime.mal_id}
  image={anime.images.webp.large_image_url}
  title={anime.title}
  score={anime.score?.toString()}
  onClick={() => handleAnimeClick(anime)}
/>
```

<Tip>
  The component includes automatic error handling that displays a placeholder with the anime title if the image fails to load.
</Tip>

***

### AnimeDetailsModal

Full-screen modal for displaying detailed anime information.

<Accordion title="Props Interface">
  ```typescript theme={null}
  interface AnimeDetailsModalProps {
    isOpen: boolean;
    onClose: () => void;
    anime: {
      mal_id: number;
      title: string;
      image: string;
      backdrop?: string;
      synopsis: string;
      score: string;
      episodes: string;
      status: string;
      genres: string[];
    } | null;
  }
  ```
</Accordion>

**Features:**

* Backdrop blur with fade-in animation
* Responsive two-column layout (poster + details)
* Genre tags display
* Library integration (add/remove functionality)
* Auto-dismiss on backdrop click
* Loading states during library operations

**Implementation Details:**

The modal checks library status on mount and provides add/remove functionality:

```tsx theme={null}
// Library status check
useEffect(() => {
  if (isOpen && anime) {
    const item = await getLibraryItem(anime.mal_id);
    setIsInLibrary(!!item);
  }
}, [isOpen, anime]);
```

**Key Sections:**

1. **Left Side**: Anime poster with gradient overlay
2. **Right Side**: Title, metadata, genres, synopsis, and action buttons
3. **Close Button**: Positioned top-right with circular styling

<Note>
  The modal requires user authentication for library operations. Unauthenticated users see an alert when attempting to add anime.
</Note>

***

### EpisodeList

Interactive episode list with watch progress tracking.

<Accordion title="Props Interface">
  ```typescript theme={null}
  interface EpisodeListProps {
    animeId: number;        // Jikan API anime ID
    totalEpisodes: number | null; // Total episode count
    title: string;          // Anime title
    imageUrl: string;       // Cover image URL
  }
  ```
</Accordion>

**Features:**

* Fetches episode data from Jikan API
* Tracks watched episodes count
* Checkmark toggle for episode completion
* Visual distinction for watched episodes (emerald theme)
* Automatic library creation on first interaction
* Progress counter display
* Handles missing episode data gracefully

**State Management:**

```typescript theme={null}
const [episodes, setEpisodes] = useState<JikanEpisode[]>([]);
const [watchedCount, setWatchedCount] = useState<number>(0);
const [isInLibrary, setIsInLibrary] = useState(false);
```

**Episode Toggle Logic:**

```typescript theme={null}
const handleToggleEpisode = async (episodeNum: number) => {
  const newCount = watchedCount === episodeNum ? episodeNum - 1 : episodeNum;
  const isCompleted = totalEpisodes ? newCount >= totalEpisodes : false;
  const newStatus: LibraryStatus = isCompleted ? 'completed' : 'watching';
  
  // Optimistic UI update
  setWatchedCount(newCount);
  
  // Persist to database
  await updateLibraryItem(animeId, { 
    episodes_watched: newCount,
    status: newStatus
  });
};
```

<Warning>
  Episode marking requires authentication. The component shows an alert if a user attempts to mark episodes without logging in.
</Warning>

***

### LibraryButton

Comprehensive library management button with status dropdown.

<Accordion title="Props Interface">
  ```typescript theme={null}
  interface LibraryButtonProps {
    animeId: number;   // Jikan API anime ID
    title: string;     // Anime title
    imageUrl: string;  // Cover image URL
  }
  ```
</Accordion>

**Features:**

* Add/remove from library
* Status dropdown (watching, completed, plan\_to\_watch, dropped)
* Visual feedback for library state
* Loading states during operations
* Automatic page refresh after updates

**Available Statuses:**

```typescript theme={null}
type LibraryStatus = 'watching' | 'completed' | 'plan_to_watch' | 'dropped';

const statusLabels: Record<LibraryStatus, string> = {
  watching: '📺 VIENDO',
  completed: '✅ COMPLETADO',
  plan_to_watch: '⏳ PENDIENTE',
  dropped: '❌ ABANDONADO'
};
```

**Button States:**

1. **Not in Library**: Shows "➕ AÑADIR A MI LISTA" (primary button)
2. **In Library**: Shows "✓ EN MI LISTA" (success outline) + status dropdown

**Usage Example:**

```tsx theme={null}
<LibraryButton
  animeId={anime.mal_id}
  title={anime.title}
  imageUrl={anime.images.webp.large_image_url}
/>
```

***

### SearchBar

Autocomplete search with live results from Jikan API.

**Features:**

* Debounced search (500ms delay)
* Live suggestions with anime posters
* Click-outside to close
* Loading indicator
* Links to anime detail pages
* "View all results" footer link

**Implementation:**

```tsx theme={null}
// Debounced search effect
useEffect(() => {
  const timer = setTimeout(async () => {
    if (query.length > 2) {
      setIsLoading(true);
      const res = await searchAnime(query);
      setResults(res.data.slice(0, 5)); // Show top 5 results
      setIsOpen(true);
    }
  }, 500);
  
  return () => clearTimeout(timer);
}, [query]);
```

**Result Display:**

* Anime poster thumbnail (10x14 pixels)
* Title in bold
* Type and score metadata
* Hover states for better UX

<Tip>
  The search activates after typing 3+ characters to reduce API calls and improve performance.
</Tip>

***

## Layout Components

### Navbar

Responsive navigation bar with authentication state.

<Accordion title="Props Interface">
  ```typescript theme={null}
  interface NavbarProps {
    user: User | null; // Supabase user object
  }
  ```
</Accordion>

**Features:**

* Fixed positioning with scroll-based styling
* Background blur on scroll
* Logo with hover animations
* Desktop navigation links (Inicio, Tendencias, Mi Lista)
* Integrated SearchBar
* User dropdown menu or Login button
* Profile avatar with initial letter

**Scroll Effect:**

```typescript theme={null}
const [scrolled, setScrolled] = useState(false);

useEffect(() => {
  const handleScroll = () => {
    const isScrolled = window.scrollY > 10;
    setScrolled(isScrolled);
  };
  
  window.addEventListener("scroll", handleScroll);
  return () => window.removeEventListener("scroll", handleScroll);
}, []);
```

**User Menu Items:**

* Profile (with icon)
* Settings (with icon)
* Sign Out (red theme)

***

### Footer

Site footer with navigation and branding.

**Sections:**

1. **Logo & Description**: Brand identity and tagline
2. **Quick Links**: Navigation to main pages
3. **Legal**: Terms and Privacy links
4. **Bottom Bar**: Copyright and attribution

**Responsive Layout:**

* Single column on mobile
* 4-column grid on desktop
* 2 columns for logo section

***

### MainLayout

Root layout wrapper component.

**Responsibilities:**

* Renders Navbar with current user
* Wraps children with main content area
* Renders Footer
* Fetches user authentication state from Supabase

```tsx theme={null}
export default async function MainLayout({ children }: { children: ReactNode }) {
  const supabase = await createClient();
  const { data: { user } } = await supabase.auth.getUser();

  return (
    <>
      <Navbar user={user} />
      <main className="pt-20">
        {children}
      </main>
      <Footer />
    </>
  );
}
```

***

## Component Patterns

<CardGroup cols={2}>
  <Card title="Client Components" icon="browser">
    All interactive components use `"use client"` directive
  </Card>

  <Card title="TypeScript Props" icon="code">
    Every component has a typed props interface
  </Card>

  <Card title="Error Handling" icon="shield">
    Graceful fallbacks for API failures and missing data
  </Card>

  <Card title="Loading States" icon="spinner">
    Visual feedback during async operations
  </Card>
</CardGroup>

## Styling Conventions

<Steps>
  <Step title="Tailwind Utilities">
    Primary styling method with responsive modifiers
  </Step>

  <Step title="DaisyUI Components">
    Pre-styled buttons, dropdowns, and badges
  </Step>

  <Step title="Custom Animations">
    Smooth transitions with Tailwind animate utilities
  </Step>

  <Step title="Dark Theme">
    Zinc color palette with primary accent color
  </Step>
</Steps>

## Best Practices

<Accordion title="Component Organization">
  * Keep components focused on a single responsibility
  * Extract reusable logic into custom hooks
  * Use TypeScript interfaces for all props
  * Document complex prop structures
</Accordion>

<Accordion title="State Management">
  * Use `useState` for component-local state
  * Fetch data in `useEffect` hooks
  * Implement optimistic UI updates for better UX
  * Handle loading and error states explicitly
</Accordion>

<Accordion title="Performance">
  * Debounce expensive operations (search, API calls)
  * Use `useCallback` for event handlers passed to children
  * Implement click-outside detection with refs
  * Clean up event listeners in useEffect returns
</Accordion>

## Related Documentation

<CardGroup cols={2}>
  <Card title="Services" icon="cloud" href="/development/services">
    Learn about API integration layers
  </Card>

  <Card title="Project Structure" icon="folder-tree" href="/development/project-structure">
    Understand the codebase organization
  </Card>
</CardGroup>
