Files
znakovni.hr/packages/frontend/src/pages/Dictionary.tsx
johnny2211 8bdd4f6368 Add Znakopis feature with document and sentence management
- Implemented Znakopis page with document and sentence CRUD operations
- Added backend routes for documents and sentences
- Created UI components for sentence editing and display
- Added sentence store for state management
- Integrated select component for document selection
- Updated README with Phase 3 completion status
- Removed obsolete fix-colors.md file
2026-01-17 18:50:53 +01:00

111 lines
2.9 KiB
TypeScript

import { useState, useEffect } from 'react';
import { Layout } from '../components/layout/Layout';
import { FilterBar } from '../components/dictionary/FilterBar';
import { WordGrid } from '../components/dictionary/WordGrid';
import { WordDetailModal } from '../components/dictionary/WordDetailModal';
import { Term, TermFilters } from '../types/term';
import { fetchTerms } from '../lib/termApi';
import { useSentenceStore } from '../stores/sentenceStore';
import { useNavigate } from 'react-router-dom';
import { toast } from 'sonner';
function Dictionary() {
const navigate = useNavigate();
const addToken = useSentenceStore((state) => state.addToken);
const [terms, setTerms] = useState<Term[]>([]);
const [loading, setLoading] = useState(true);
const [selectedTerm, setSelectedTerm] = useState<Term | null>(null);
const [filters, setFilters] = useState<TermFilters>({
query: '',
wordType: '',
cefrLevel: '',
page: 1,
limit: 20,
});
const [pagination, setPagination] = useState({
page: 1,
limit: 20,
total: 0,
totalPages: 0,
});
useEffect(() => {
loadTerms();
}, [filters]);
const loadTerms = async () => {
try {
setLoading(true);
const response = await fetchTerms(filters);
setTerms(response.terms);
setPagination(response.pagination);
} catch (error) {
console.error('Failed to load terms:', error);
} finally {
setLoading(false);
}
};
const handleFilterChange = (newFilters: TermFilters) => {
setFilters(newFilters);
};
const handlePageChange = (page: number) => {
setFilters({ ...filters, page });
};
const handleTermInfo = (term: Term) => {
setSelectedTerm(term);
};
const handleAddToSentence = (term: Term) => {
addToken(term);
toast.success(`Dodano: "${term.wordText}"`, {
description: 'Riječ je dodana u rečenicu. Idite na Znakopis za uređivanje.',
action: {
label: 'Idi na Znakopis',
onClick: () => navigate('/znakopis'),
},
});
};
return (
<Layout>
<div className="space-y-6">
{/* Header */}
<div>
<h1 className="text-3xl font-bold text-gray-900 mb-2">Rječnik</h1>
<p className="text-gray-600">
Pretražite i pregledajte hrvatski znakovni jezik
</p>
</div>
{/* Filters */}
<FilterBar filters={filters} onFilterChange={handleFilterChange} />
{/* Word Grid */}
<WordGrid
terms={terms}
loading={loading}
onInfo={handleTermInfo}
onAddToSentence={handleAddToSentence}
pagination={pagination}
onPageChange={handlePageChange}
/>
{/* Word Detail Modal */}
<WordDetailModal
term={selectedTerm}
open={!!selectedTerm}
onClose={() => setSelectedTerm(null)}
onAddToSentence={handleAddToSentence}
/>
</div>
</Layout>
);
}
export default Dictionary;