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

137 lines
6.7 KiB
TypeScript
Raw 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, useEffect } from 'react';
import { Book, AppScreen } from '../types';
interface AddBookProps {
initialData?: Partial<Book>;
onSave: (book: Partial<Book>) => void;
onCancel: () => void;
onScanClick: () => void;
}
export const AddBook: React.FC<AddBookProps> = ({ initialData, onSave, onCancel, onScanClick }) => {
const [formData, setFormData] = useState<Partial<Book>>({
title: '',
author: '',
genre: '',
annotation: '',
status: 'want_to_read',
pages: 0,
language: 'Russian',
publishedYear: new Date().getFullYear(),
rating: 5,
coverUrl: 'https://picsum.photos/seed/newbook/400/600',
...initialData
});
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
const { id, value } = e.target;
setFormData(prev => ({ ...prev, [id]: value }));
};
return (
<div className="flex flex-col h-full bg-background-dark">
<header className="sticky top-0 z-50 flex items-center justify-between px-4 py-3 bg-background-dark/90 backdrop-blur-md border-b border-white/5">
<button onClick={onCancel} className="flex items-center justify-center size-10 rounded-full hover:bg-surface-dark transition-colors text-gray-300">
<span className="material-symbols-outlined">arrow_back_ios_new</span>
</button>
<h1 className="text-lg font-bold tracking-tight text-center flex-1 pr-10">Добавить книгу</h1>
</header>
<main className="flex-1 flex flex-col p-5 gap-6 overflow-y-auto no-scrollbar pb-32">
<div className="flex justify-center w-full">
<div
onClick={onScanClick}
className="group relative flex flex-col items-center justify-center w-40 h-60 rounded-lg border-2 border-dashed border-border-dark bg-surface-dark transition-all hover:border-primary cursor-pointer overflow-hidden shadow-sm"
>
{formData.coverUrl && !formData.coverUrl.includes('picsum') ? (
<img src={formData.coverUrl} className="absolute inset-0 w-full h-full object-cover" alt="Preview" />
) : (
<div className="flex flex-col items-center gap-3 p-4 text-center z-10 transition-transform group-hover:scale-105">
<div className="size-12 rounded-full bg-primary/10 flex items-center justify-center text-primary">
<span className="material-symbols-outlined text-[28px]">add_a_photo</span>
</div>
<p className="text-xs font-medium text-gray-400 group-hover:text-primary transition-colors">Загрузить или отсканировать</p>
</div>
)}
</div>
</div>
<form className="flex flex-col gap-5">
<div className="flex flex-col gap-2">
<label className="text-sm font-semibold text-gray-200 ml-1" htmlFor="title">Название</label>
<input
id="title"
className="w-full rounded-xl border-border-dark bg-surface-dark px-4 py-3.5 text-base text-white placeholder-gray-500 focus:border-primary focus:ring-1 focus:ring-primary transition-shadow shadow-sm"
placeholder="Введите название книги"
value={formData.title}
onChange={handleChange}
/>
</div>
<div className="flex flex-col gap-2">
<label className="text-sm font-semibold text-gray-200 ml-1" htmlFor="author">Автор</label>
<input
id="author"
className="w-full rounded-xl border-border-dark bg-surface-dark px-4 py-3.5 text-base text-white placeholder-gray-500 focus:border-primary focus:ring-1 focus:ring-primary transition-shadow shadow-sm"
placeholder="Имя автора"
value={formData.author}
onChange={handleChange}
/>
</div>
<div className="flex flex-col gap-2">
<label className="text-sm font-semibold text-gray-200 ml-1" htmlFor="genre">Жанр</label>
<div className="relative">
<select
id="genre"
className="w-full appearance-none rounded-xl border-border-dark bg-surface-dark px-4 py-3.5 text-base text-white focus:border-primary focus:ring-1 focus:ring-primary transition-shadow shadow-sm pr-10 cursor-pointer"
value={formData.genre}
onChange={handleChange}
>
<option disabled value="">Выберите жанр</option>
<option value="fiction">Фантастика</option>
<option value="fantasy">Фэнтези</option>
<option value="science">Научпоп</option>
<option value="biography">Биография</option>
<option value="detective">Детектив</option>
<option value="other">Другое</option>
</select>
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-4 text-gray-400">
<span className="material-symbols-outlined">expand_more</span>
</div>
</div>
</div>
<div className="flex flex-col gap-2">
<label className="text-sm font-semibold text-gray-200 ml-1" htmlFor="annotation">Аннотация</label>
<textarea
id="annotation"
rows={4}
className="w-full rounded-xl border-border-dark bg-surface-dark px-4 py-3.5 text-base text-white placeholder-gray-500 focus:border-primary focus:ring-1 focus:ring-primary transition-shadow shadow-sm resize-none"
placeholder="О чем эта книга? Краткое описание или заметки..."
value={formData.annotation}
onChange={handleChange}
/>
</div>
</form>
</main>
<div className="fixed bottom-0 left-0 right-0 max-w-md mx-auto p-4 bg-background-dark/95 backdrop-blur-sm border-t border-white/5 z-40">
<div className="flex gap-3">
<button onClick={onCancel} className="flex-1 py-3.5 px-4 rounded-xl font-semibold text-gray-300 bg-surface-dark hover:bg-[#25422e] transition-colors">
Отмена
</button>
<button
onClick={() => onSave(formData)}
className="flex-[2] py-3.5 px-4 rounded-xl font-bold text-white bg-primary hover:bg-[#14b047] shadow-lg shadow-primary/20 transition-all active:scale-[0.98] flex items-center justify-center gap-2"
>
<span className="material-symbols-outlined text-[20px]">save</span>
Сохранить
</button>
</div>
</div>
</div>
);
};