From eab5303c0f39a3bbbedd099f4286f66a2ed671cd Mon Sep 17 00:00:00 2001 From: johnny2211 Date: Sun, 18 Jan 2026 15:21:23 +0100 Subject: [PATCH] Fix bugs and add features to Znakopis document management - Fix API endpoint for creating pages (documents/:id/pages) - Fix sentence deletion functionality - Add CreateDocumentDialog component for better UX - Improve document and sentence management UI - Update seed data and backend routes - Clean up documentation files (remove videos.md, videosentence.md) - Add comprehensive bug tracking in fixbugsaddfeatures.md --- fixbugsaddfeatures.md | 277 ++++++++ packages/backend/prisma/seed.ts | 8 +- packages/backend/src/routes/sentences.ts | 8 +- .../znakopis/CreateDocumentDialog.tsx | 78 +++ .../src/components/znakopis/DocumentPanel.tsx | 183 +++++- packages/frontend/src/lib/documentApi.ts | 4 +- packages/frontend/src/pages/Login.tsx | 9 +- packages/frontend/src/pages/VideoSentence.tsx | 11 +- packages/frontend/src/pages/Znakopis.tsx | 110 +++- videos.md | 216 ------- videosentence.md | 608 ------------------ 11 files changed, 643 insertions(+), 869 deletions(-) create mode 100644 fixbugsaddfeatures.md create mode 100644 packages/frontend/src/components/znakopis/CreateDocumentDialog.tsx delete mode 100644 videos.md delete mode 100644 videosentence.md diff --git a/fixbugsaddfeatures.md b/fixbugsaddfeatures.md new file mode 100644 index 0000000..cd78dd6 --- /dev/null +++ b/fixbugsaddfeatures.md @@ -0,0 +1,277 @@ +# Znakopis Page - Bug Fixes and Feature Additions + +## Overview +This document outlines the bugs to fix and features to add to the Znakopis page for document and sentence management. + +--- + +## πŸ› BUG FIXES + +### Bug 1: Sentence Deletion Error +**Issue:** When loading a document and trying to delete a sentence, an error occurs and the sentence is not deleted. + +**Root Cause:** The API endpoint path is incorrect in the frontend. +- Frontend calls: `/api/sentences/${sentenceId}` (via `documentApi.deleteSentence()`) +- Backend expects: `/api/sentences/:sentenceId` +- Backend route is registered at: `app.use('/api', sentenceRoutes)` in `server.ts` +- This means the actual endpoint is: `/api/sentences/:sentenceId` βœ… + +**Investigation Needed:** +1. Check browser console for the exact error message +2. Verify the sentence ID is being passed correctly +3. Check if authentication is working properly +4. Verify the backend route is handling the DELETE request correctly + +**Files to Check:** +- `packages/frontend/src/lib/documentApi.ts` - Line 121-123 (deleteSentence method) +- `packages/backend/src/routes/sentences.ts` - Line 169-199 (DELETE endpoint) +- `packages/frontend/src/pages/Znakopis.tsx` - Line 129-144 (handleDeleteSentence) +- `packages/frontend/src/components/znakopis/DocumentPanel.tsx` - Line 119-125 (delete button) + +**Fix Steps:** +1. Add error logging to identify the exact issue +2. Verify the sentence ID format (should be UUID string) +3. Ensure the DELETE request includes authentication credentials +4. Test the endpoint directly to confirm it works +5. Add better error handling and user feedback + +--- + +### Bug 2: Incorrect API Endpoint for Creating Pages +**Issue:** The frontend uses wrong endpoint path for creating pages. + +**Current State:** +- Frontend calls: `/api/${documentId}/pages` (Line 88 in documentApi.ts) +- Backend expects: `/api/documents/:documentId/pages` (Line 205 in sentences.ts) + +**Fix Required:** +- Update `packages/frontend/src/lib/documentApi.ts` line 88 +- Change from: `api.post(\`/api/${documentId}/pages\`, { title })` +- Change to: `api.post(\`/api/documents/${documentId}/pages\`, { title })` + +--- + +### Bug 3: Incorrect API Endpoint for Creating Sentences +**Issue:** The frontend uses wrong endpoint path for creating sentences. + +**Current State:** +- Frontend calls: `/api/${documentId}/pages/${pageIndex}/sentences` (Line 99 in documentApi.ts) +- Backend expects: `/api/documents/:documentId/pages/:pageIndex/sentences` (Line 11 in sentences.ts) + +**Fix Required:** +- Update `packages/frontend/src/lib/documentApi.ts` line 99 +- Change from: `api.post(\`/api/${documentId}/pages/${pageIndex}/sentences\`, data)` +- Change to: `api.post(\`/api/documents/${documentId}/pages/${pageIndex}/sentences\`, data)` + +--- + +## ✨ NEW FEATURES + +### Feature 1: Delete Document Functionality +**Description:** Add ability to delete documents from the Znakopis page. + +**Backend:** Already implemented βœ… +- Endpoint: `DELETE /api/documents/:id` (Line 236 in documents.ts) +- Method: `documentApi.deleteDocument(id)` already exists (Line 82 in documentApi.ts) + +**Frontend Changes Needed:** + +1. **Update DocumentPanel Component** (`packages/frontend/src/components/znakopis/DocumentPanel.tsx`): + - Add `onDeleteDocument` prop to interface (Line 6-15) + - Add delete button in the document info section (around Line 56-65) + - Use Trash2 icon from lucide-react (already imported) + - Add confirmation dialog before deletion + +2. **Update Znakopis Page** (`packages/frontend/src/pages/Znakopis.tsx`): + - Add `handleDeleteDocument` function (similar to handleDeleteSentence) + - Pass handler to DocumentPanel component + - After deletion: + - Clear selectedDocument state + - Reload documents list + - Show success toast + - Handle errors with error toast + +3. **UI/UX Considerations:** + - Add confirmation dialog: "Jeste li sigurni da ΕΎelite obrisati ovaj dokument?" + - Show document title in confirmation + - Disable delete button while deleting (loading state) + - Clear current tokens if deleting the selected document + +--- + +### Feature 2: Edit Document Name +**Description:** Allow users to edit document title and description. + +**Backend:** Already implemented βœ… +- Endpoint: `PATCH /api/documents/:id` (Line 174 in documents.ts) +- Method: `documentApi.updateDocument(id, data)` already exists (Line 76 in documentApi.ts) + +**Frontend Changes Needed:** + +1. **Update DocumentPanel Component** (`packages/frontend/src/components/znakopis/DocumentPanel.tsx`): + - Add `onUpdateDocument` prop to interface + - Add edit mode state for document title and description + - Add edit button (Pencil icon from lucide-react) + - When in edit mode: + - Show input field for title + - Show textarea for description + - Show Save and Cancel buttons + - When not in edit mode: + - Show title and description as text + - Show edit button + +2. **Update Znakopis Page** (`packages/frontend/src/pages/Znakopis.tsx`): + - Add `handleUpdateDocument` function + - Accept documentId, title, and description + - Call `documentApi.updateDocument()` + - Reload document after update + - Update documents list + - Show success/error toast + +3. **UI/UX Considerations:** + - Inline editing for better UX + - Validate title is not empty + - Show loading state while saving + - Revert changes on cancel + - Auto-focus title input when entering edit mode + +--- + +### Feature 3: Name Document on Creation +**Description:** Allow users to provide a custom name when creating a new document instead of auto-generated name. + +**Current Behavior:** +- Auto-generates name: `Dokument ${new Date().toLocaleDateString('hr-HR')}` +- Creates with description: "Novi dokument" + +**Proposed Changes:** + +1. **Add Document Creation Dialog:** + - Create new component: `CreateDocumentDialog.tsx` + - Use Dialog component from UI library + - Include: + - Title input field (required) + - Description textarea (optional) + - Create and Cancel buttons + +2. **Update Znakopis Page** (`packages/frontend/src/pages/Znakopis.tsx`): + - Add state for dialog open/closed + - Modify "Novi dokument" button to open dialog + - Update `handleSaveDocument`: + - If no document selected, check if user wants to create new or use dialog + - Option 1: Always show dialog for new documents + - Option 2: Show dialog only when clicking "Novi dokument", auto-create when saving first sentence + - Pass document data from dialog to createDocument API + +3. **Alternative Approach (Simpler):** + - Add inline form in DocumentPanel when no document is selected + - Show title and description inputs + - First save creates document with provided info + - If fields empty, use default values + +4. **UI/UX Considerations:** + - Default title could be: "Novi dokument" (user can change) + - Placeholder for description: "Dodajte opis dokumenta..." + - Validate title is not empty + - Show character count for title (max 255) + +--- + +## πŸ“‹ IMPLEMENTATION CHECKLIST + +### Phase 1: Bug Fixes (Priority: HIGH) +- [ ] Fix API endpoint for creating pages (documentApi.ts line 88) +- [ ] Fix API endpoint for creating sentences (documentApi.ts line 99) +- [ ] Debug and fix sentence deletion error + - [ ] Add console logging to identify error + - [ ] Verify authentication is working + - [ ] Test endpoint directly + - [ ] Fix any issues found + - [ ] Add better error handling + +### Phase 2: Delete Document Feature (Priority: HIGH) +- [ ] Add onDeleteDocument prop to DocumentPanel interface +- [ ] Add delete button to DocumentPanel UI +- [ ] Implement confirmation dialog +- [ ] Add handleDeleteDocument function in Znakopis page +- [ ] Test deletion flow +- [ ] Verify state updates correctly after deletion + +### Phase 3: Edit Document Name (Priority: MEDIUM) +- [ ] Add onUpdateDocument prop to DocumentPanel interface +- [ ] Add edit mode state to DocumentPanel +- [ ] Implement inline editing UI (title and description) +- [ ] Add edit/save/cancel buttons +- [ ] Add handleUpdateDocument function in Znakopis page +- [ ] Add validation for title +- [ ] Test edit flow +- [ ] Verify state updates correctly after edit + +### Phase 4: Name Document on Creation (Priority: MEDIUM) +- [ ] Decide on approach (dialog vs inline form) +- [ ] Create CreateDocumentDialog component (if using dialog approach) +- [ ] Update "Novi dokument" button behavior +- [ ] Add form validation +- [ ] Update handleSaveDocument or create separate handler +- [ ] Test document creation with custom name +- [ ] Ensure backward compatibility (auto-name if not provided) + +--- + +## πŸ§ͺ TESTING REQUIREMENTS + +### For Each Bug Fix: +1. Test the specific scenario that was failing +2. Verify error messages are clear and helpful +3. Test edge cases (empty data, invalid IDs, etc.) +4. Verify authentication is required + +### For Each Feature: +1. Test happy path (normal usage) +2. Test validation (empty fields, too long text, etc.) +3. Test error handling (network errors, server errors) +4. Test UI states (loading, success, error) +5. Test on different screen sizes (responsive design) +6. Verify Croatian language text is correct + +--- + +## πŸ“ NOTES FOR IMPLEMENTATION + +1. **Consistency:** Follow existing patterns in the codebase +2. **Error Handling:** Always show user-friendly error messages in Croatian +3. **Loading States:** Show loading indicators for async operations +4. **Confirmation Dialogs:** Use for destructive actions (delete) +5. **Toast Messages:** Use Sonner toast for feedback (already imported) +6. **Icons:** Use lucide-react icons (already in use) +7. **Styling:** Use existing Tailwind classes for consistency +8. **TypeScript:** Ensure all types are properly defined +9. **API Calls:** Always handle errors with try-catch +10. **State Management:** Update all relevant state after API calls + +--- + +## πŸ” FILES TO MODIFY + +### Bug Fixes: +1. `packages/frontend/src/lib/documentApi.ts` - Fix API endpoints +2. `packages/frontend/src/pages/Znakopis.tsx` - Improve error handling +3. `packages/backend/src/routes/sentences.ts` - Verify DELETE endpoint (if needed) + +### Features: +1. `packages/frontend/src/components/znakopis/DocumentPanel.tsx` - Add delete and edit UI +2. `packages/frontend/src/pages/Znakopis.tsx` - Add handlers for delete and edit +3. `packages/frontend/src/components/znakopis/CreateDocumentDialog.tsx` - New file (if using dialog approach) +4. `packages/frontend/src/components/ui/dialog.tsx` - May need to create if not exists + +--- + +## ⚠️ IMPORTANT CONSIDERATIONS + +1. **Data Loss Prevention:** Always confirm before deleting documents +2. **Concurrent Edits:** Consider what happens if document is edited while viewing +3. **Permissions:** Verify user owns document before allowing edit/delete +4. **Validation:** Ensure title is not empty and within length limits +5. **Accessibility:** Ensure all interactive elements are keyboard accessible +6. **Mobile:** Test on mobile devices for touch interactions + diff --git a/packages/backend/prisma/seed.ts b/packages/backend/prisma/seed.ts index 3addb73..ebe6a5d 100644 --- a/packages/backend/prisma/seed.ts +++ b/packages/backend/prisma/seed.ts @@ -7,10 +7,12 @@ async function main() { console.log('🌱 Starting database seed...'); // Create admin user - const adminPasswordHash = await bcrypt.hash('admin123', 10); + const adminPasswordHash = await bcrypt.hash('novinet01', 10); const admin = await prisma.user.upsert({ where: { email: 'admin@znakovni.hr' }, - update: {}, + update: { + passwordHash: adminPasswordHash, // Update password if user exists + }, create: { email: 'admin@znakovni.hr', displayName: 'Administrator', @@ -23,7 +25,7 @@ async function main() { console.log('βœ… Created admin user:', admin.email); console.log(' Email: admin@znakovni.hr'); - console.log(' Password: admin123'); + console.log(' Password: novinet01'); // Create a demo regular user const demoPasswordHash = await bcrypt.hash('demo123', 10); diff --git a/packages/backend/src/routes/sentences.ts b/packages/backend/src/routes/sentences.ts index 467215d..32b6c41 100644 --- a/packages/backend/src/routes/sentences.ts +++ b/packages/backend/src/routes/sentences.ts @@ -8,7 +8,7 @@ const router = Router(); * POST /api/documents/:documentId/pages/:pageIndex/sentences * Create a new sentence on a page */ -router.post('/:documentId/pages/:pageIndex/sentences', isAuthenticated, async (req: Request, res: Response) => { +router.post('/documents/:documentId/pages/:pageIndex/sentences', isAuthenticated, async (req: Request, res: Response) => { try { const { documentId, pageIndex } = req.params; const userId = req.user?.id; @@ -97,7 +97,7 @@ router.post('/:documentId/pages/:pageIndex/sentences', isAuthenticated, async (r * PATCH /api/sentences/:sentenceId/tokens * Update tokens in a sentence (reorder, add, remove) */ -router.patch('/:sentenceId/tokens', isAuthenticated, async (req: Request, res: Response) => { +router.patch('/sentences/:sentenceId/tokens', isAuthenticated, async (req: Request, res: Response) => { try { const { sentenceId } = req.params; const userId = req.user?.id; @@ -166,7 +166,7 @@ router.patch('/:sentenceId/tokens', isAuthenticated, async (req: Request, res: R * DELETE /api/sentences/:sentenceId * Delete a sentence */ -router.delete('/:sentenceId', isAuthenticated, async (req: Request, res: Response) => { +router.delete('/sentences/:sentenceId', isAuthenticated, async (req: Request, res: Response) => { try { const { sentenceId } = req.params; const userId = req.user?.id; @@ -202,7 +202,7 @@ router.delete('/:sentenceId', isAuthenticated, async (req: Request, res: Respons * POST /api/documents/:documentId/pages * Create a new page in a document */ -router.post('/:documentId/pages', isAuthenticated, async (req: Request, res: Response) => { +router.post('/documents/:documentId/pages', isAuthenticated, async (req: Request, res: Response) => { try { const { documentId } = req.params; const userId = req.user?.id; diff --git a/packages/frontend/src/components/znakopis/CreateDocumentDialog.tsx b/packages/frontend/src/components/znakopis/CreateDocumentDialog.tsx new file mode 100644 index 0000000..4463139 --- /dev/null +++ b/packages/frontend/src/components/znakopis/CreateDocumentDialog.tsx @@ -0,0 +1,78 @@ +import { useState } from 'react'; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '../ui/dialog'; +import { Button } from '../ui/button'; +import { Input } from '../ui/input'; + +interface CreateDocumentDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + onCreate: (title: string, description: string) => void; +} + +export function CreateDocumentDialog({ open, onOpenChange, onCreate }: CreateDocumentDialogProps) { + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + + const handleCreate = () => { + if (!title.trim()) return; + onCreate(title, description); + // Reset form + setTitle(''); + setDescription(''); + }; + + const handleCancel = () => { + onOpenChange(false); + // Reset form + setTitle(''); + setDescription(''); + }; + + return ( + + + + Novi dokument + + Unesite naziv i opis novog dokumenta. + + +
+
+ + setTitle(e.target.value)} + placeholder="Novi dokument" + maxLength={255} + autoFocus + /> +

{title.length}/255 znakova

+
+
+ +