- Extract word type color logic into shared wordTypeColors.ts utility - Update TokenTray to use centralized color utility - Remove duplicate color logic from WordCard and SortableToken - Add color legend to Layout header for better UX - Simplify Znakopis page component
87 lines
3.0 KiB
TypeScript
87 lines
3.0 KiB
TypeScript
import { useSentenceStore } from '../../stores/sentenceStore';
|
|
import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, DragEndEvent } from '@dnd-kit/core';
|
|
import { arrayMove, SortableContext, sortableKeyboardCoordinates, horizontalListSortingStrategy } from '@dnd-kit/sortable';
|
|
import { SortableToken } from './SortableToken';
|
|
import { X } from 'lucide-react';
|
|
import { Button } from '../ui/button';
|
|
|
|
interface TokenTrayProps {
|
|
compact?: boolean;
|
|
}
|
|
|
|
export function TokenTray({ compact = false }: TokenTrayProps) {
|
|
const { currentTokens, reorderTokens, removeToken, clearTokens } = useSentenceStore();
|
|
|
|
const sensors = useSensors(
|
|
useSensor(PointerSensor),
|
|
useSensor(KeyboardSensor, {
|
|
coordinateGetter: sortableKeyboardCoordinates,
|
|
})
|
|
);
|
|
|
|
const handleDragEnd = (event: DragEndEvent) => {
|
|
const { active, over } = event;
|
|
|
|
if (over && active.id !== over.id) {
|
|
const oldIndex = currentTokens.findIndex((token) => token.id === active.id);
|
|
const newIndex = currentTokens.findIndex((token) => token.id === over.id);
|
|
|
|
const newTokens = arrayMove(currentTokens, oldIndex, newIndex);
|
|
reorderTokens(newTokens);
|
|
}
|
|
};
|
|
|
|
// Conditional styling based on compact mode
|
|
const containerClass = compact
|
|
? "bg-white rounded-lg shadow-sm p-3"
|
|
: "bg-white rounded-lg shadow p-6";
|
|
|
|
const headerClass = compact
|
|
? "text-lg font-semibold text-gray-900"
|
|
: "text-xl font-semibold text-gray-900";
|
|
|
|
const gapClass = compact ? "gap-2" : "gap-3";
|
|
|
|
return (
|
|
<div className={containerClass}>
|
|
<div className="flex justify-between items-center mb-3">
|
|
<h2 className={headerClass}>Trenutna rečenica</h2>
|
|
{currentTokens.length > 0 && (
|
|
<Button variant="outline" size="sm" onClick={clearTokens}>
|
|
<X className="h-4 w-4 mr-1" />
|
|
Očisti sve
|
|
</Button>
|
|
)}
|
|
</div>
|
|
|
|
{currentTokens.length === 0 ? (
|
|
!compact && (
|
|
<div className="text-center py-12 text-gray-500">
|
|
<p className="text-lg mb-2">Nema riječi u rečenici</p>
|
|
<p className="text-sm">Idite na Rječnik i dodajte riječi klikom na "Dodaj"</p>
|
|
</div>
|
|
)
|
|
) : (
|
|
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
|
|
<SortableContext items={currentTokens.map((t) => t.id)} strategy={horizontalListSortingStrategy}>
|
|
<div className={`flex flex-wrap ${gapClass}`}>
|
|
{currentTokens.map((token) => (
|
|
<SortableToken key={token.id} token={token} onRemove={removeToken} />
|
|
))}
|
|
</div>
|
|
</SortableContext>
|
|
</DndContext>
|
|
)}
|
|
|
|
{currentTokens.length > 0 && !compact && (
|
|
<div className="mt-6 p-4 bg-blue-50 rounded-lg">
|
|
<p className="text-sm text-blue-900">
|
|
<strong>Savjet:</strong> Povucite i ispustite riječi za promjenu redoslijeda. Kliknite "Spremi" za spremanje rečenice u dokument.
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|