This commit is contained in:
Yuriy Panov
2026-02-02 17:12:25 +06:00
commit 3004f712f3
19 changed files with 1157 additions and 0 deletions

132
books/App.tsx Normal file
View File

@@ -0,0 +1,132 @@
import React, { useState } from 'react';
import { AppScreen, Book } from './types';
import { INITIAL_BOOKS } from './constants';
import { Layout } from './components/Layout';
import { Library } from './screens/Library';
import { Categories } from './screens/Categories';
import { BookDetails } from './screens/BookDetails';
import { AddBook } from './screens/AddBook';
import { Scanner } from './screens/Scanner';
const App: React.FC = () => {
const [currentScreen, setCurrentScreen] = useState<AppScreen>(AppScreen.LIBRARY);
const [books, setBooks] = useState<Book[]>(INITIAL_BOOKS);
const [selectedBook, setSelectedBook] = useState<Book | null>(null);
const [prefilledData, setPrefilledData] = useState<Partial<Book> | null>(null);
const handleBookClick = (book: Book) => {
setSelectedBook(book);
setCurrentScreen(AppScreen.DETAILS);
};
const handleAddClick = () => {
setPrefilledData(null);
setCurrentScreen(AppScreen.ADD_BOOK);
};
const handleSaveBook = (bookData: Partial<Book>) => {
if (selectedBook) {
// Edit existing
setBooks(prev => prev.map(b => b.id === selectedBook.id ? { ...b, ...bookData } as Book : b));
} else {
// Add new
const newBook: Book = {
id: Math.random().toString(36).substr(2, 9),
title: bookData.title || 'Unknown',
author: bookData.author || 'Unknown',
genre: bookData.genre || 'Unknown',
annotation: bookData.annotation || '',
coverUrl: bookData.coverUrl || 'https://picsum.photos/seed/new/400/600',
status: 'want_to_read',
...bookData
} as Book;
setBooks(prev => [...prev, newBook]);
}
setCurrentScreen(AppScreen.LIBRARY);
setSelectedBook(null);
setPrefilledData(null);
};
const handleDeleteBook = (id: string) => {
setBooks(prev => prev.filter(b => b.id !== id));
setCurrentScreen(AppScreen.LIBRARY);
};
const handleDetected = (data: Partial<Book>) => {
setPrefilledData(data);
setCurrentScreen(AppScreen.ADD_BOOK);
};
const renderScreen = () => {
switch (currentScreen) {
case AppScreen.LIBRARY:
return (
<Library
books={books}
onBookClick={handleBookClick}
onAddClick={handleAddClick}
/>
);
case AppScreen.CATEGORIES:
return <Categories />;
case AppScreen.DETAILS:
return selectedBook ? (
<BookDetails
book={selectedBook}
onBack={() => setCurrentScreen(AppScreen.LIBRARY)}
onDelete={handleDeleteBook}
onEdit={(b) => {
setSelectedBook(b);
setCurrentScreen(AppScreen.ADD_BOOK);
}}
/>
) : null;
case AppScreen.ADD_BOOK:
return (
<AddBook
initialData={selectedBook || prefilledData || {}}
onSave={handleSaveBook}
onCancel={() => {
setCurrentScreen(selectedBook ? AppScreen.DETAILS : AppScreen.LIBRARY);
setPrefilledData(null);
}}
onScanClick={() => setCurrentScreen(AppScreen.SCANNER)}
/>
);
case AppScreen.SCANNER:
return (
<Scanner
onCancel={() => setCurrentScreen(AppScreen.ADD_BOOK)}
onDetected={handleDetected}
/>
);
case AppScreen.WISHLIST:
return (
<div className="p-10 text-center">
<h2 className="text-xl font-bold">Вишлист</h2>
<p className="text-text-muted mt-2">Здесь будут книги, которые вы хотите прочитать.</p>
</div>
);
case AppScreen.SETTINGS:
return (
<div className="p-10 text-center">
<h2 className="text-xl font-bold">Настройки</h2>
<p className="text-text-muted mt-2">Персонализируйте ваше приложение.</p>
</div>
);
default:
return <Library books={books} onBookClick={handleBookClick} onAddClick={handleAddClick} />;
}
};
const hideNav = [AppScreen.SCANNER, AppScreen.DETAILS, AppScreen.ADD_BOOK].includes(currentScreen);
return (
<Layout currentScreen={currentScreen} setScreen={setCurrentScreen} hideNav={hideNav}>
{renderScreen()}
</Layout>
);
};
export default App;