Tejaswi/9 UI confirmation modal - #21
Conversation
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…tejaavula076/urBackend into tejaswi/9-ui-confirmation-modal
…tejaavula076/urBackend into tejaswi/9-ui-confirmation-modal
|
@tejaavula076 is attempting to deploy a commit to the Yash Pouranik's projects Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughAdds Tailwind CSS to the frontend build and introduces a reusable ConfirmationModal component; replaces inline browser confirms with modal-driven flows and refactors Database and ProjectSettings pages to use modal confirmations and reorganized state/components. Changes
Sequence DiagramsequenceDiagram
participant User
participant UI as App Page\n(Database / ProjectSettings)
participant Modal as ConfirmationModal
participant API as Backend API
User->>UI: Click "Delete" on item
UI->>UI: set showModal=true, selectedId=itemId
UI->>Modal: render(open=true)
Modal->>User: show overlay with Cancel/Delete
User->>Modal: Click Cancel
Modal->>UI: onCancel()
UI->>UI: set showModal=false
alt User confirms deletion
User->>Modal: Click Delete
Modal->>UI: onConfirm()
UI->>API: DELETE /resource/:id
API-->>UI: 200 OK
UI->>UI: remove item from state, set showModal=false
UI->>User: show success toast / refresh view
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @frontend/src/pages/Database.jsx:
- Around line 303-315: The ConfirmationModal is currently rendered as a child of
the <table>, which is invalid HTML; move the conditional rendering of
ConfirmationModal (the block using showModal, ConfirmationModal, onConfirm
calling handleDelete(selectedId) and setShowModal(false), and onCancel calling
setShowModal(false)) so it is placed immediately after the closing </table> (or
elsewhere outside the table wrapper) while keeping the same props and state
references (showModal, handleDelete, selectedId, setShowModal) to preserve
behavior.
🧹 Nitpick comments (9)
frontend/src/index.css (1)
523-529: Consider using Tailwind utility classes directly in JSX.These custom CSS classes define simple padding and width values that could be expressed using Tailwind utilities directly on the component elements (e.g.,
p-4,p-1,w-20). This would improve consistency with the Tailwind-first approach being adopted.Additionally, the
.confirmationModalBtnclass has inconsistent indentation.🔧 Suggested formatting fix if keeping custom classes
.confirmationModal{ padding: 1rem; } .confirmationModalBtn{ - padding: 5px; - width: 5rem; - + padding: 5px; + width: 5rem; }frontend/package.json (1)
13-13: Consider moving Tailwind packages to devDependencies.
@tailwindcss/vite(4.1.18) is introduced as a new runtime integration for Tailwind with Vite, andtailwindcss(4.1.18) is added as a styling framework dependency. Both packages are build-time tools that process CSS during development and build phases—they don't run in the browser. Moving them todevDependencieswould better reflect their purpose and reduce production bundle analysis noise.♻️ Suggested fix
"dependencies": { - "@tailwindcss/vite": "^4.1.18", "axios": "^1.13.2", "lucide-react": "^0.554.0", "react": "^19.2.0", "react-dom": "^19.2.0", "react-hot-toast": "^2.6.0", "react-router-dom": "^7.9.6", - "recharts": "^3.5.1", - "tailwindcss": "^4.1.18" + "recharts": "^3.5.1" }, "devDependencies": { "@eslint/js": "^9.39.1", + "@tailwindcss/vite": "^4.1.18", "@types/react": "^19.2.5","globals": "^16.5.0", + "tailwindcss": "^4.1.18", "vite": "^7.2.4" }Also applies to: 20-21
frontend/src/pages/ConfirmationModal.jsx (2)
7-47: Add accessibility attributes for screen readers.The modal has
id="modal-title"andid="modal-description"but they're not connected via ARIA attributes. This impacts screen reader users.♿ Proposed accessibility improvements
<div className="fixed inset-0 bg-black/50 flex items-center justify-center" onClick={onCancel} + role="dialog" + aria-modal="true" + aria-labelledby="modal-title" + aria-describedby="modal-description" >
38-43: Consider making confirm button text configurable.The button text is hardcoded as "Delete", limiting reusability for non-delete confirmations. Consider adding a
confirmTextprop with a default value.♻️ Proposed change
-function ConfirmationModal({ open, title, message, onConfirm, onCancel }) { +function ConfirmationModal({ open, title, message, onConfirm, onCancel, confirmText = "Delete" }) {<button onClick={onConfirm} className="btn btn-danger confirmationModalBtn" > - Delete + {confirmText} </button>frontend/src/pages/Database.jsx (3)
42-45: Consider renamingfetchShowModalfor clarity.The name
fetchShowModalimplies it fetches data, but it only sets state to show the modal. A clearer name likeopenDeleteModalorshowDeleteConfirmationwould better convey the intent.♻️ Proposed rename
- const fetchShowModal = (id) => { + const openDeleteModal = (id) => { setShowModal(true); setSelectedId(id); };Then update the usage on line 295:
- onClick={() => fetchShowModal(row._id)} + onClick={() => openDeleteModal(row._id)}
65-67: Consider capturing the error for debugging.The catch block discards the error object. Capturing it would help with debugging failed requests.
♻️ Proposed change
- } catch { + } catch (err) { + console.error(err); toast.error("Failed to load project"); }
188-250: Inner function components recreate on each render.
Sidebar,TableView,JsonView, andSkeletonLoaderare defined inside the parent component, causing them to be recreated on every render. This breaks referential equality and can cause unnecessary re-renders of child components.For this use case with simple UI components, the impact is minimal, but for better performance and testability, consider extracting them outside
Databaseor memoizing them.frontend/src/pages/ProjectSettings.jsx (2)
69-72: Remove commented-out dead code.This commented-out confirmation logic is no longer needed since the modal now handles confirmation. Remove it to keep the codebase clean.
🧹 Proposed cleanup
const handleDeleteProject = async () => { if (deleteConfirm !== project.name) return toast.error("Project name does not match"); - // // if ( - // // !confirm("Final warning: This will delete the project and all its data.") - // // ) - // return; - try {
326-331: Project data not refreshed after config update.After successful configuration,
isConfiguredwon't reflect the new state until the page is refreshed. The UI masks this by hiding the form, but the underlyingprojectstate is stale.Consider accepting an
onSuccesscallback prop to trigger a project refresh from the parent, or update the localprojectprop optimistically.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
backend/package-lock.jsonis excluded by!**/package-lock.jsonfrontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
backend/package.jsonfrontend/index.htmlfrontend/package.jsonfrontend/src/index.cssfrontend/src/pages/ConfirmationModal.jsxfrontend/src/pages/Database.jsxfrontend/src/pages/ProjectSettings.jsxfrontend/vite.config.js
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/pages/Database.jsx (5)
frontend/src/pages/ProjectDetails.jsx (3)
useParams(13-13)useAuth(15-15)project(17-17)frontend/src/context/AuthContext.jsx (3)
useAuth(38-38)useAuth(38-38)token(6-6)frontend/src/components/Layout/Header.jsx (1)
useAuth(5-5)frontend/src/components/Layout/MainLayout.jsx (1)
isSidebarOpen(9-9)frontend/src/config.js (2)
API_URL(2-2)API_URL(2-2)
🔇 Additional comments (7)
backend/package.json (1)
31-31: LGTM!The trailing newline ensures POSIX compliance and is a good formatting practice.
frontend/src/index.css (1)
2-2: LGTM!The
@import "tailwindcss";directive is the correct Tailwind CSS v4 syntax, replacing the legacy@tailwind base; @tailwind components; @tailwind utilities;approach.frontend/vite.config.js (1)
3-3: LGTM!The Tailwind CSS v4 Vite plugin is correctly imported and registered. This is the recommended integration approach for Tailwind v4 with Vite, replacing the need for PostCSS configuration.
Also applies to: 6-6
frontend/index.html (1)
1-1: LGTM!Good HTML formatting improvements:
- Uppercase
<!DOCTYPE html>follows the standard convention- Self-closing tags (
/>) provide consistency with JSX syntax used elsewhere in the project- Multi-line formatting for the Google Fonts link improves readability
Also applies to: 9-14
frontend/src/pages/Database.jsx (1)
99-115: LGTM!The delete handler correctly integrates with the confirmation modal flow, updates local state optimistically after deletion, and provides appropriate error handling with toast notifications.
frontend/src/pages/ProjectSettings.jsx (2)
286-297: LGTM!The confirmation modal integration for project deletion is well-implemented. The flow properly guards against accidental deletion by requiring name confirmation before enabling the button, then showing the modal for final confirmation.
45-63: LGTM!The rename handler has proper validation, loading state management, and optimistically updates local state after a successful API call. The button's disabled state (line 177) correctly prevents unnecessary requests.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (9)
frontend/src/pages/Database.jsx (9)
14-18: Unused imports detected.The
SearchandMoreVerticalicons are imported from lucide-react but do not appear to be used anywhere in the component. Consider removing them to keep the imports clean.🧹 Suggested cleanup
import { Database as DbIcon, Plus, Trash2, RefreshCw, Code, Table as TableIcon, - Search, Menu, X, ChevronRight, - MoreVertical, FileText, } from "lucide-react";
42-45: Consider renamingfetchShowModalfor clarity.The function name
fetchShowModalsuggests it fetches data, but it only sets state to show the modal. A name likeopenDeleteModalorshowDeleteConfirmationwould better convey its purpose.✏️ Suggested rename
- const fetchShowModal = (id) => { + const openDeleteModal = (id) => { setShowModal(true); setSelectedId(id); };
65-67: Error details are discarded.The catch block shows a toast but discards the error object, making debugging harder. Consider logging the error.
🔍 Suggested improvement
- } catch { + } catch (err) { + console.error("Failed to load project:", err); toast.error("Failed to load project"); }
99-115: ClearselectedIdafter deletion to prevent stale state.After a successful delete,
selectedIdstill holds the deleted document's ID. While not immediately problematic, clearing it maintains cleaner state management.🧹 Suggested improvement
setData((prev) => prev.filter((item) => item._id !== id)); + setSelectedId(null); toast.success("Document deleted");
188-250: Inner component definitions cause unnecessary re-renders.
Sidebar,TableView,JsonView, andSkeletonLoaderare defined inside theDatabasecomponent, meaning they are recreated on every render. This defeats React's reconciliation and can cause performance issues or loss of local state.Consider either:
- Moving these to separate files or outside the component
- Converting them to inline JSX if they're simple enough
- Using
useMemoto memoize them (less ideal)
304-315: Modal placement may cause unexpected dismissal.The
ConfirmationModalis rendered insideTableView, which only renders whenviewMode === "table". If a user opens the delete modal and somehow switches to JSON view, the modal will unmount unexpectedly.Consider moving the modal to the main return block alongside the "Add Document" modal for consistent behavior.
♻️ Suggested approach
Move the confirmation modal outside of
TableViewto the main JSX, similar to howisAddModalOpenmodal is handled at lines 457-495:{/* At the end of the main return, alongside the Add Document modal */} {showModal && ( <ConfirmationModal open={showModal} title="Delete Record" message="Are you sure you want to delete this record? This action cannot be undone." onConfirm={() => { handleDelete(selectedId); setShowModal(false); }} onCancel={() => setShowModal(false)} /> )}
456-495: Consider adding accessibility attributes to the modal.The "Add Document" modal lacks focus trapping, Escape key handling, and proper ARIA attributes. While not blocking, these improvements would enhance accessibility.
Key additions to consider:
role="dialog"andaria-modal="true"on modal contentaria-labelledbypointing to the modal title- Escape key handler to close modal
- Focus trap to keep keyboard navigation within modal
353-358: Add accessible labels to icon-only buttons.The menu trigger button and other icon-only buttons lack accessible labels for screen reader users.
♿ Suggested improvement
<button className="btn-icon hide-desktop menu-trigger" onClick={() => setIsSidebarOpen(true)} + aria-label="Open sidebar menu" > <Menu size={20} /> </button>Apply similar
aria-labelattributes to other icon-only buttons like the delete button, refresh button, and close buttons.
497-861: Consider extracting styles to a separate CSS file or using Tailwind classes.The 350+ lines of inline CSS embedded in the JSX impacts maintainability and causes the styles to be re-parsed on every render. Since Tailwind CSS is already a project dependency, consider:
- Moving styles to a dedicated CSS file (e.g.,
Database.cssorDatabase.module.css)- Replacing custom styles with Tailwind utility classes where applicable
Note that some utility classes defined here (
.mb-4,.text-muted,.opacity-20) duplicate Tailwind's built-in utilities.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
frontend/src/pages/Database.jsx
🔇 Additional comments (4)
frontend/src/pages/Database.jsx (4)
91-97: LGTM!The effect correctly handles collection changes with proper dependency management. The mobile sidebar auto-close on selection is a good UX touch.
146-164: LGTM!The dynamic input rendering based on field types is well-structured. The Boolean select with an empty default option works well with the
requiredattribute for validation.
319-336: LGTM!The
JsonViewandSkeletonLoadercomponents are simple and functional. The skeleton provides good loading UX feedback.
117-144: No changes needed. Thedatetime-localinput type already returns ISO 8601 formatted strings, which the backend correctly validates usingDate.parse(). The frontend and backend are consistent in handling Date fields as strings, so explicit conversion is unnecessary.Likely an incorrect or invalid review comment.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
yash-pouranik
left a comment
There was a problem hiding this comment.
Thanku for the PR @tejaavula076 , it works well, merging it.
for more - join discord - https://discord.gg/CXJjvJkNWn
🚀 Pull Request Description
Fixes # (issue number)
🛠️ Type of Change
🧪 Testing & Validation
Backend Verification:
npm testin thebackend/directory and all tests passed.Frontend Verification:
npm run lintin thefrontend/directory.📸 Screenshots / Recordings (Optional)
✅ Checklist
Built with ❤️ for urBackend.
Summary by CodeRabbit
New Features
Style
Other
✏️ Tip: You can customize this high-level summary in your review settings.