Files
bookshelf/books/screens/Library.tsx
Yuriy Panov 3004f712f3 initial
2026-02-02 17:12:25 +06:00

109 lines
5.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState } from 'react';
import { Book, AppScreen } from '../types';
interface LibraryProps {
books: Book[];
onBookClick: (book: Book) => void;
onAddClick: () => void;
}
export const Library: React.FC<LibraryProps> = ({ books, onBookClick, onAddClick }) => {
const [search, setSearch] = useState('');
const filteredBooks = books.filter(b =>
b.title.toLowerCase().includes(search.toLowerCase()) ||
b.author.toLowerCase().includes(search.toLowerCase())
);
return (
<div className="flex flex-col h-full bg-background-dark">
<header className="sticky top-0 z-30 bg-background-dark/95 backdrop-blur-md border-b border-white/5 pb-2 pt-4">
<div className="flex items-center px-4 py-3 justify-between">
<div className="w-10"></div>
<h2 className="text-xl font-bold leading-tight tracking-tight flex-1 text-center">Книжная полка</h2>
<div className="w-10 flex justify-end">
<button className="text-white hover:text-primary transition-colors">
<span className="material-symbols-outlined">notifications</span>
</button>
</div>
</div>
<div className="px-4 pb-2">
<div className="flex w-full items-stretch rounded-xl h-12 bg-surface-highlight shadow-sm ring-1 ring-white/5 focus-within:ring-2 focus-within:ring-primary transition-all">
<div className="text-text-muted flex items-center justify-center pl-4 pr-2">
<span className="material-symbols-outlined text-[20px]">search</span>
</div>
<input
className="flex w-full min-w-0 flex-1 bg-transparent text-white focus:outline-none placeholder:text-text-muted text-base font-normal"
placeholder="Поиск по названию или автору..."
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
</div>
</div>
</header>
<div className="px-4 pt-2 pb-24 flex-1">
<div className="flex flex-col gap-4 mb-6">
<div className="flex h-10 w-full items-center justify-center rounded-lg bg-surface-highlight p-1">
<button className="flex-1 h-full rounded-md bg-background-dark shadow-sm text-sm font-medium text-white">Все книги</button>
<button className="flex-1 h-full text-sm font-medium text-text-muted">Категории</button>
</div>
<div className="flex gap-3 overflow-x-auto no-scrollbar pb-1">
<button className="flex h-9 items-center justify-center gap-x-2 rounded-full bg-surface-highlight border border-white/5 px-4">
<span className="material-symbols-outlined text-[18px]">sort</span>
<span className="text-white text-sm font-medium">Сортировка</span>
</button>
<button className="flex h-9 items-center justify-center gap-x-2 rounded-full bg-surface-highlight border border-white/5 px-4">
<span className="material-symbols-outlined text-[18px]">filter_list</span>
<span className="text-white text-sm font-medium">Фильтр</span>
</button>
<button className="flex h-9 items-center justify-center gap-x-2 rounded-full bg-surface-highlight border border-white/5 px-4 whitespace-nowrap">
<span className="text-white text-sm font-medium">Непрочитанные</span>
</button>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
{filteredBooks.map((book) => (
<div key={book.id} className="flex flex-col gap-2 group cursor-pointer" onClick={() => onBookClick(book)}>
<div className="relative w-full aspect-[2/3] rounded-lg overflow-hidden shadow-md group-hover:shadow-xl transition-all duration-300 bg-surface-dark">
<img src={book.coverUrl || 'https://picsum.photos/seed/placeholder/400/600'} className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105" alt={book.title} />
{book.status === 'reading' && (
<div className="absolute bottom-0 left-0 right-0 h-1 bg-black/50">
<div className="h-full bg-primary" style={{ width: `${book.progress || 0}%` }}></div>
</div>
)}
{book.status === 'done' && (
<div className="absolute top-2 left-2 bg-primary/90 text-white text-[10px] font-bold px-2 py-0.5 rounded-full backdrop-blur-sm">DONE</div>
)}
{book.isFavorite && (
<div className="absolute top-2 right-2 bg-black/60 backdrop-blur-sm rounded-full p-1">
<span className="material-symbols-outlined text-white text-[14px] fill-current">favorite</span>
</div>
)}
</div>
<div>
<h3 className="text-white text-base font-semibold leading-tight line-clamp-1">{book.title}</h3>
<p className="text-text-muted text-sm font-normal leading-normal line-clamp-1">{book.author}</p>
</div>
</div>
))}
</div>
</div>
<button
onClick={onAddClick}
className="fixed bottom-24 right-5 z-40 bg-primary text-white w-14 h-14 rounded-full shadow-lg shadow-primary/40 flex items-center justify-center hover:scale-110 active:scale-95 transition-all"
>
<span className="material-symbols-outlined text-[28px]">add</span>
</button>
</div>
);
};