Skip to content

Add feature dashboard AdminMenu Audit Issues - #7

Merged
poner2547 merged 2 commits into
developfrom
feature/Homepage
May 2, 2026
Merged

Add feature dashboard AdminMenu Audit Issues#7
poner2547 merged 2 commits into
developfrom
feature/Homepage

Conversation

@poner2547

@poner2547 poner2547 commented May 1, 2026

Copy link
Copy Markdown
Collaborator

Add Dashboard AdminMenu

Summary by CodeRabbit

  • New Features

    • Admin area: admin pages, sidebar layout and asset management UI
    • Ticket search with date-range picker and pill-style selector
    • Pending ticket list with status filters and merge workflow (confirm modal)
    • Per-ticket pending card with selection/merge and read-only behaviors
  • Style

    • Updated theme tokens, colors and responsive grid/layouts
    • Improved card, navbar and sidebar styling
  • Chores

    • Added date picker library support

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba8645eb-f341-4f02-bb0d-c7ac4a608b23

📥 Commits

Reviewing files that changed from the base of the PR and between 2f40bf1 and 4f1b74d.

📒 Files selected for processing (4)
  • client/src/components/CardPendingProblem.jsx
  • client/src/hooks/useEquipment.js
  • client/src/pages/adminPage/AuditIssues.jsx
  • server/routes/managementRoutes.js
✅ Files skipped from review due to trivial changes (1)
  • client/src/pages/adminPage/AuditIssues.jsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • client/src/hooks/useEquipment.js
  • client/src/components/CardPendingProblem.jsx

📝 Walkthrough

Walkthrough

Adds an admin portal and UI for searching/filtering tickets, merging tickets, and managing equipment; introduces new backend endpoints for equipment retrieval and ticket merging; updates Prisma timestamps to nullable; adds UI components, hooks, styles, and a react-datepicker dependency.

Changes

Admin portal + Ticket Merge

Layer / File(s) Summary
Data Shape
server/prisma/schema.prisma
Made createdAt / updatedAt nullable (DateTime? ) across models (User, Location, Floor, Room, EquipmentCategory, Equipment, TicketImage, TicketCategory, Ticket, Upvote).
Backend Core
server/controllers/managementControllers.js
Added getEquipment and mergeTickets controller functions; mergeTickets validates payload and bulk-updates child tickets to set parentTicketId.
Backend Routing & Auth
server/routes/managementRoutes.js
Wired GET /getEquipmentByadmin and PATCH /mergeTickets; added verifyToken and requireAdmin middleware to management POST routes.
Backend Service (client-side)
client/src/services/ticketService.js
New ticketService.mergeTickets(payload) performing axios.patch('/api/manage/mergeTickets').
Client Hooks / Data Fetching
client/src/hooks/useEquipment.js, client/src/hooks/useFilterDate.js, client/src/hooks/useTicketSearch.js
Added useEquipment (CRUD + refetch), useFilterDate (memoized inclusive date filtering), and useTicketSearch (search/filter logic + pending-first sort).
Pages (Admin)
client/src/pages/adminPage/AuditIssues.jsx, client/src/pages/adminPage/AssetManagement.jsx
Added AuditIssues page (search, date-range, merge-mode UI, selected list, ConfirmButton wired to merge) and AssetManagement page (equipment table using useEquipment).
Admin Layout / Navigation
client/src/components/componentsAdmin/AdminLayout.jsx, client/src/components/componentsAdmin/AdminSidebar.jsx, client/src/components/componentsAdmin/Adminsidebar.css, client/src/App.jsx, client/src/components/Navbar.jsx
Added admin layout with persistent sidebar and routed Outlet; expanded routing to admin-only /adminPage with lazy-loaded admin child routes; navbar shows admin link conditionally.
Card & List UI
client/src/components/CardPendingProblem.jsx, client/src/components/CardPendingProblem.css, client/src/components/CardFinishProblem.css, client/src/pages/Dashboard.jsx, client/src/pages/Dashboard.css
Added CardPendingProblem component with merge/select/read-only behavior and image fallback; updated finish-card image styling; Dashboard now uses search/filter hooks and renders pending/resolved sections.
Filter/Search/Date UI
client/src/components/FilterProblem.jsx, client/src/components/FilterProblem.css, client/src/components/SearchBar.jsx, client/src/components/SearchBar.css, client/src/components/DateRangeFilter.jsx, client/src/components/DateRangeFilter.css, client/package.json
Added FilterProblem, SearchBar, and DateRangeFilter (uses react-datepicker — dependency added).
Confirmation Modal
client/src/components/ConfirmButton.jsx, client/src/components/ConfirmButton.css
Added ConfirmButton modal used by merge flow (open/close, confirm/cancel callbacks).
Styling & Design Tokens
client/src/index.css, various CSS files under client/src/pages and client/src/components
Introduced status design tokens, updated base font size and theme tokens; added many CSS modules for admin pages and components.
Minor Cleanup
client/src/hooks/useTickets.js, server/controllers/ticketControllers.js
Removed debug console.log in useTickets; added trailing newline in ticketControllers.js.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant UI as Admin UI
    participant Modal as ConfirmButton
    participant API as Backend API
    participant DB as Database

    User->>UI: Select multiple tickets (toggle merge mode)
    UI->>UI: Build selected parent & children list
    User->>UI: Click "Confirm Merge"
    UI->>Modal: Open confirmation modal
    User->>Modal: Click "ยืนยัน" (confirm)
    Modal->>API: PATCH /api/manage/mergeTickets { parentId, childIds }
    API->>DB: Update child tickets' parentTicketId
    DB-->>API: Return update result
    API-->>Modal: Return success response
    Modal->>UI: Close modal, clear selection
    UI->>UI: Refresh tickets display
    UI-->>User: Show success state
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I hopped through code with eager paws,

Merged tickets neatly without a pause,
Dates and searches, a sidebar to show,
Equipment lists in tidy rows,
Tokens gleam, the portal grows! 🎩

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main changes: adding admin dashboard features including an admin menu and audit issues page with related components and functionality.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/Homepage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
client/src/pages/Dashboard.css (1)

26-33: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the custom-property typo.

var(---text-color-main) is invalid, so the color declaration is ignored. On a green button background, that can leave the text/icon unreadable.

Suggested fix
-    color: var(---text-color-main);
+    color: var(--text-color-light);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/pages/Dashboard.css` around lines 26 - 33, The .scroll-btn CSS
rule uses an invalid custom property name var(---text-color-main) causing the
color to be ignored; open the Dashboard.css file and in the .scroll-btn selector
(class name ".scroll-btn") replace the triple-dash token with the correct custom
property name (use var(--text-color-main)) so the button text/icon color is
applied properly and remains readable against the green background.
client/src/pages/DetailTicket.css (1)

1-12: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid hard-coding the detail panel height.

The new 300px/250px heights will clip longer descriptions and make the layout brittle on smaller screens. Let the content drive the height, or switch these to min-height values.

Suggested fix
-    height: 300px;
+    min-height: 300px;
...
-    height: 250px;
+    min-height: 250px;
...
-    height: 250px;
+    height: auto;

Also applies to: 58-73

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/pages/DetailTicket.css` around lines 1 - 12, The CSS for the
detail panel (.container-detail) uses a fixed height (height: 300px) which clips
variable content; replace the fixed height with a content-driven rule such as
removing height or using min-height (e.g., min-height: 300px) so the panel can
grow with longer descriptions, and make the same change for the other panel
rules referenced (the blocks around lines 58-73 that also set fixed heights) to
avoid brittle layouts on smaller screens.
🟡 Minor comments (9)
client/src/components/CardPendingProblem.css-1-2 (1)

1-2: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove the empty selector block.

p,span {} is now a lint error (block-no-empty) and will fail style checks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/CardPendingProblem.css` around lines 1 - 2, Remove the
empty CSS rule for the selector "p,span" in CardPendingProblem.css; locate the
block "p,span { }" and delete it (or add the intended style declarations if the
empty block was left as a placeholder) so the file no longer contains an empty
selector that triggers the block-no-empty lint error.
server/controllers/managementControllers.js-140-175 (1)

140-175: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Return 200 for the equipment listing.

getEquipment is read-only, so 201 Created is the wrong status code. The error strings also still say “creating equipment”, which makes logs misleading.

Suggested fix
-        res.status(201).json(equipments);
+        res.status(200).json(equipments);
...
-        console.error('Error creating equipment:', error);
-        res.status(500).json({ error: 'Failed to create equipment  ' });
+        console.error('Error fetching equipment:', error);
+        res.status(500).json({ error: 'Failed to fetch equipment' });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/controllers/managementControllers.js` around lines 140 - 175, The
getEquipment controller is using the wrong HTTP status and misleading log text;
change res.status(201).json(equipments) to res.status(200).json(equipments) and
update the catch block messages in getEquipment (both console.error and the JSON
error payload) to refer to "retrieving/listing equipment" (or similar) instead
of "creating equipment" to accurately reflect the read operation; ensure
references to prisma.equipment.findMany remain unchanged.
client/src/index.css-56-72 (1)

56-72: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Keep a compatibility alias for --status-yellow.

Removing this token breaks client/src/components/CardPendingProblem.css:22, which still uses it for the default badge background. Either migrate that consumer in the same PR or keep an alias until the old reference is gone.

Suggested fix
   --status-pending-bg: `#f1c40f`; 
   --status-pending-text: `#453505`;
+  --status-yellow: var(--status-pending-bg);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/index.css` around lines 56 - 72, Add a compatibility alias for the
removed token by defining --status-yellow (and --status-yellow-text) in the root
CSS to point to the new pending variables (e.g., --status-yellow:
var(--status-pending-bg); --status-yellow-text: var(--status-pending-text);) so
existing consumers like CardPendingProblem.css that reference --status-yellow
keep working until they are migrated to
--status-pending-bg/--status-pending-text.
client/src/components/Navbar.jsx-8-8 (1)

8-8: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove debug logging from render path

console.log here is a debug artifact and should be removed before merge.

Cleanup
-    console.log("Current User Role:", user?.role);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/Navbar.jsx` at line 8, Remove the debug console.log
from the render path in Navbar.jsx: delete the line that logs "Current User
Role:" using user?.role (the stray console.log in the Navbar component render).
If runtime debugging is still desired, move logging into a useEffect hook or a
dev-only guard so it does not execute on every render.
client/src/pages/DetailTicket.jsx-105-107 (1)

105-107: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

ticket.admin does not match the current ticket payload shape

DetailTicket renders operator info from ticket.admin, but the current ticket list payload exposes adminId (not admin), so this block is skipped in normal flows.

Suggested quick fallback in UI
-                            {ticket.admin && (
-                                <p>ผู้ดำเนินการ : {ticket.admin}</p>
-                            )}
+                            {(ticket.admin || ticket.adminId) && (
+                                <p>ผู้ดำเนินการ : {ticket.admin || ticket.adminId}</p>
+                            )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/pages/DetailTicket.jsx` around lines 105 - 107, DetailTicket
currently checks and renders operator info from ticket.admin but the payload
provides ticket.adminId, so the operator block is skipped; update the JSX in
DetailTicket to check for ticket.admin || ticket.adminId and render the
human-readable operator name when ticket.admin exists otherwise fall back to
displaying the adminId (or a mapped name if you have a lookup), i.e. replace the
conditional that references ticket.admin with a check for either property and
show ticket.admin when available or ticket.adminId as the fallback.
client/src/components/SearchBar.jsx-13-20 (1)

13-20: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Wire the .searchbar class so the new stylesheet actually applies.

Current markup doesn’t include a .searchbar container/class, but CSS selectors are .searchbar form, .searchbar input, .searchbar button.

Suggested fix
-  return (
-    <form onSubmit={handleSubmit}>
-      <input 
-        type="text" 
-        onChange={(e) => setSearch(e.target.value)} 
-        placeholder="ค้นหาที่นี่..." 
-      />
-      <button type="submit">ค้นหา</button>
-    </form>
-  )
+  return (
+    <div className="searchbar">
+      <form onSubmit={handleSubmit}>
+        <input 
+          type="text" 
+          onChange={(e) => setSearch(e.target.value)} 
+          placeholder="ค้นหาที่นี่..." 
+        />
+        <button type="submit">ค้นหา</button>
+      </form>
+    </div>
+  )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/SearchBar.jsx` around lines 13 - 20, The markup in
SearchBar.jsx doesn't include the "searchbar" class expected by the stylesheet;
update the component so the form (or a surrounding container) has
className="searchbar" so the CSS selectors (.searchbar form, .searchbar input,
.searchbar button) apply; locate the JSX in SearchBar.jsx where handleSubmit,
setSearch and the <form> are defined and add the className to that element (or
wrap the form in a div with className="searchbar") without changing the existing
handlers.
client/src/components/ConfirmButton.css-16-16 (1)

16-16: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix Stylelint violations in animation declarations/keyframes.

Line 16 has an extra empty line before animation, and Lines 89/94 use non-kebab-case keyframe names (fadeIn, slideUp) that violate the configured rule.

✅ Suggested lint-compliant patch
 .confirm-modal-overlay {
@@
-    
     animation: fadeIn 0.2s ease-in-out;
 }
@@
-    animation: slideUp 0.3s ease-out;
+    animation: slide-up 0.3s ease-out;
 }
@@
-@keyframes fadeIn {
+@keyframes fade-in {
@@
-@keyframes slideUp {
+@keyframes slide-up {

Also applies to: 30-30, 89-94

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/ConfirmButton.css` at line 16, Remove the stray blank
line before the animation declaration and rename keyframes and their usages to
kebab-case to satisfy Stylelint: change keyframe identifiers fadeIn and slideUp
to fade-in and slide-up (or equivalent kebab-case) in the `@keyframes` blocks and
update all animation properties that reference those names (e.g., animation:
fadeIn 0.2s → animation: fade-in 0.2s) in ConfirmButton.css so names match and
stylelint passes.
client/src/pages/adminPage/AuditIssues.css-90-97 (1)

90-97: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove the extra blank line before gap in .audit-issues-problem.

Line 96 is flagged by Stylelint (declaration-empty-line-before). This can fail lint checks.

🧹 Minimal fix
 .audit-issues-problem{
   display: grid;
   grid-template-columns: 1fr  1fr;
   border-radius: 2rem;
   padding: 2rem;
-
   gap: 20px;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/pages/adminPage/AuditIssues.css` around lines 90 - 97, The CSS
rule .audit-issues-problem contains an extra blank line before the gap
declaration which triggers Stylelint's declaration-empty-line-before; remove the
empty line so the declarations are contiguous (e.g., ensure padding: 2rem; is
immediately followed by gap: 20px;) in the .audit-issues-problem block to
satisfy the linter.
client/src/hooks/useFilterDate.js-14-15 (1)

14-15: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Exclude null dates when a filter is active.

Returning true for missing dateField values means any active range still includes undated rows, which defeats the date filter. If you only want to keep nulls visible when no date is selected, gate this branch on startDate/endDate.

Suggested fix
-            if (!item[dateField]) return true;
+            if (!item[dateField]) return !(startDate || endDate);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/hooks/useFilterDate.js` around lines 14 - 15, The current
early-return in useFilterDate always includes items missing the dateField (if
(!item[dateField]) return true), which bypasses active date filters; change this
to only allow undated items when no date filter is set by checking startDate and
endDate on the same function: if item[dateField] is null/undefined, return true
only when both startDate and endDate are falsy (or no filter is active),
otherwise return false so undated rows are excluded while a range is active;
reference the useFilterDate function and the variables dateField, item,
startDate, endDate when making this change.
🧹 Nitpick comments (2)
client/src/components/FilterProblem.jsx (1)

5-10: ⚡ Quick win

Status filter options are incomplete for existing ticket states

This button set omits rejected and duplicate, so users cannot explicitly filter those statuses from this control.

Suggested button list update
     const buttons = [
         { id: 'all', label: 'ทั้งหมด' },
         { id: 'pending', label: 'รอรับเรื่อง' },
         { id: 'in_progress', label: 'กำลังดำเนินการ' },
         { id: 'resolved', label: 'เสร็จสิ้น' },
+        { id: 'rejected', label: 'ปฏิเสธ' },
+        { id: 'duplicate', label: 'รายการซ้ำ' },
 
     ];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/FilterProblem.jsx` around lines 5 - 10, The status
filter array defined as buttons (in FilterProblem.jsx) is missing the 'rejected'
and 'duplicate' ticket states; update the buttons constant to include objects
for id: 'rejected' and id: 'duplicate' with appropriate labels (matching the
existing language/label style) so the filter control can select those statuses
(refer to the buttons variable in FilterProblem.jsx).
client/src/components/componentsAdmin/Adminsidebar.css (1)

39-53: ⚡ Quick win

Deduplicate .nav-item.active styles.

Line 48–53 repeats the same declarations already covered by Line 40–46 (.nav-item:hover, .nav-item.active). Keeping one block avoids future drift.

♻️ Proposed cleanup
 .nav-item:hover,
 .nav-item.active {
     color: var(--tbs-green);
     border-right: 4px solid var(--tbs-green);
     background-color: rgba(55, 167, 11, 0.1);
-    /* สีเขียว TBS แบบจางๆ */
-}
-
-.nav-item.active {
-    color: var(--tbs-green);
-    border-right: 4px solid var(--tbs-green);
-    background-color: rgba(55, 167, 11, 0.1);
     /* สีเขียว TBS แบบจางๆ */
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/componentsAdmin/Adminsidebar.css` around lines 39 - 53,
Remove the duplicated `.nav-item.active` rule block and keep the combined
selector `.nav-item:hover, .nav-item.active` (which already contains the needed
declarations: color, border-right, background-color). Edit the CSS to delete the
second `.nav-item.active { ... }` block so there’s a single source of truth for
the hover/active styles and avoid future drift between `.nav-item:hover` and
`.nav-item.active`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/src/App.jsx`:
- Around line 49-51: The Management route's Suspense boundary is empty so
navigating to "/adminPage/Management" will render a blank page; fix by either
creating and importing a Management component and using it as the Suspense child
(follow the pattern used for AuditIssues and AssetManagement: add a React.lazy
import for Management and render <Management /> inside the existing Suspense),
or if the page is not ready, remove the <Route path="Management" .../> entry
entirely; ensure you reference the Route with path="Management" and the Suspense
wrapper when making the change.

In `@client/src/components/CardPendingProblem.css`:
- Around line 15-20: The CSS rule currently targets all images via the global
selector `img`; change the selector to scope the styles to the card thumbnail
only by replacing the selector `.img-card,img` with a descendant selector like
`.img-card img` (or `.pending-card img` if that class exists on the card root)
so only images inside the pending-card container receive `object-fit: cover`,
`object-position: center`, and the 150×150 sizing; keep the same property block
but remove the bare `img` selector.

In `@client/src/components/CardPendingProblem.jsx`:
- Around line 21-23: The click branch references an undefined identifier
handleClick inside the CardPendingProblem component; replace that usage with the
actual click prop (eg. onClick or onCardClick) that the component receives (and
add a no-op fallback) so clicking doesn't throw a ReferenceError — update the
component signature to include the prop (and PropTypes/TS type if present) and
change the conditional from checking handleClick to checking the received prop
(e.g., props.onClick) and invoke that instead; remove the undefined handleClick
reference from CardPendingProblem.

In `@client/src/components/componentsAdmin/AdminLayout.jsx`:
- Line 3: The import line in AdminLayout.jsx incorrectly imports a non-existent
named export `{children}` from React; remove `{children}` so the line reads
`import React from "react";` and if the AdminLayout component uses children,
ensure the component signature accepts it (e.g., function AdminLayout({ children
}) or props.children) rather than importing it from React; update any references
to use the local children prop accordingly.

In `@client/src/components/componentsAdmin/AdminSidebar.jsx`:
- Around line 28-51: The NavLink targets in AdminSidebar.jsx don't match the
registered admin routes; update the NavLink "to" props so they point to the
admin routes used in App.jsx (replace the root "/" NavLink and the three
NavLinks currently using "/tracking" with the correct admin paths).
Specifically, change the NavLink that renders FaTools (currently to="/") to the
admin management route (e.g., "/adminPage/Management" or the exact route name
used in App.jsx), and change the NavLinks that render FaUserCog, FaMapMarkedAlt,
and FaTags (currently to="/tracking") to the corresponding "/adminPage/..."
routes (e.g., "/adminPage/AssetManagement", "/adminPage/AuditIssues" or the
exact route names in App.jsx) so all NavLink "to" values match the registered
routes.

In `@client/src/components/ConfirmButton.jsx`:
- Around line 17-31: The modal markup in ConfirmButton.jsx is missing
accessibility attributes and keyboard handling; update the container element
(e.g., the element with className "confirm-modal-content" or enclosing div) to
include role="dialog" and aria-modal="true", add aria-labelledby and
aria-describedby attributes that reference unique IDs placed on the title (h3)
and message (p), and ensure those elements have matching id values; also wire an
Escape key handler (in the ConfirmButton component) that calls the provided
onCancel prop and ensure focus is moved into the dialog when it opens (e.g.,
focus the first button) and restored on close.

In `@client/src/components/DateRangeFilter.css`:
- Around line 11-20: The current CSS rule in DateRangeFilter.css removes the
default outline but provides no replacement focus indicator; add a
:focus-visible style for the same selector (the custom button rule in
DateRangeFilter.css) that restores a visible, accessible focus state — for
example use a clear outline or an elevated box-shadow and/or border color change
plus outline-offset to preserve existing layout and transition (keep transition:
all 0.2s ease-in-out). Ensure the :focus-visible rule applies only for keyboard
focus and complements the existing box-shadow/min-width/height styles so
keyboard users can see focus.

In `@client/src/components/SearchBar.jsx`:
- Line 2: Update the CSS import in SearchBar.jsx to match the actual filename
casing: replace the current import './searchBar.css' with './SearchBar.css' so
the module resolver can find the file on case-sensitive filesystems; check the
SearchBar component file (SearchBar.jsx) to ensure no other imports use
incorrect casing.

In `@client/src/hooks/useEquipment.js`:
- Around line 18-45: The client mutations addEquipment, updateEquipment, and
deleteEquipment are calling non-existent routes under /api/equipment/* and will
404, preventing fetchEquipment from being useful; either update these functions
to call the actual backend endpoints exposed by the management router (e.g., use
/api/manage/addEquipment and /api/manage/getEquipment or the correct
update/delete paths) or add matching server-side controllers/routes for update
and delete; modify the axios URLs in addEquipment, updateEquipment, and
deleteEquipment to match the backend router names (or implement corresponding
endpoints in the backend) and keep fetchEquipment in the dependency lists so the
refetch occurs after a successful mutation.

In `@client/src/hooks/useTicketSearch.js`:
- Around line 19-27: The filter builds contentToSearch from ticket fields but
uses t.subject which doesn't exist on the ticket model; update the
tickets.filter in useTicketSearch.js so it uses t.title (replace t.subject with
t.title) when composing contentToSearch, and ensure searchTerm is normalized
(e.g., .toLowerCase()) before calling contentToSearch.includes(searchTerm) so
comparisons match correctly.

In `@client/src/pages/adminPage/AssetManagement.jsx`:
- Around line 11-16: The status label map formatStatus uses keys that don't
match the backend enum (e.g., 'awaitingSale', 'sentForRepair', 'Broken') so
lookups like formatStatus[asset.status] can return undefined; update
formatStatus keys to the server values ('awaiting_sale', 'sent_for_repair',
'broken', 'active', etc.) to match asset.status, and add a safe fallback when
rendering (e.g., use formatStatus[asset.status] || 'Unknown' or similar) to
avoid undefined labels; reference the formatStatus object and the code that
accesses it via asset.status.
- Line 22: The SearchBar is rendered without the required onSearch prop and will
crash when it calls onSearch(search); add a handler in this component (e.g.,
function handleSearch(search) { /* perform filtering/fetch or update state */ })
and pass it to the SearchBar as <SearchBar onSearch={handleSearch} />; reference
the SearchBar component and ensure handleSearch implements the behavior you need
(update component state or call whatever fetch/filter function like
fetchAssets/filterAssets) to avoid the submit-time crash.

In `@client/src/pages/adminPage/AuditIssues.jsx`:
- Line 6: In AuditIssues.jsx the import uses the wrong filename casing for the
CardPendingProblem component; update the import source to match the actual
component filename (CardPendingProblem.jsx) so the imported symbol
CardPendingProblem resolves correctly on case-sensitive filesystems.

In `@client/src/pages/Dashboard.jsx`:
- Line 7: The import for the component is using the wrong case; update the
import statement that references CardpendingProblem.jsx to match the actual
component name CardPendingProblem.jsx (change the path/import to
../components/CardPendingProblem.jsx) so the symbol CardPendingProblem resolves
correctly on case-sensitive filesystems and the module loads without errors.

In `@server/controllers/managementControllers.js`:
- Around line 178-206: In mergeTickets, validate the parent before writing:
check parentId is not included in childIds (reject self-merge) and confirm the
parent exists via prisma.ticket.findUnique (return 400 if not found),
deduplicate/filter childIds to remove the parent and any duplicates, then call
prisma.ticket.updateMany with the filtered childIds and use the returned count
(result.count) to set mergedCount and to decide success vs partial/no-op; update
error messages accordingly and avoid assuming every requested child was updated.

In `@server/routes/managementRoutes.js`:
- Around line 27-29: The new management routes expose getEquipment and
mergeTickets without any authentication/authorization; protect them by adding
the appropriate auth middleware (e.g., requireAuth and requireAdmin or isAdmin)
to these routes or to the router mounting them so only authenticated admins can
call them; update the route registrations for getEquipment and mergeTickets to
include the auth middleware before the handler (or add a
router.use(authMiddleware) guard) and import the middleware used by other
protected routes to ensure consistent checks.

---

Outside diff comments:
In `@client/src/pages/Dashboard.css`:
- Around line 26-33: The .scroll-btn CSS rule uses an invalid custom property
name var(---text-color-main) causing the color to be ignored; open the
Dashboard.css file and in the .scroll-btn selector (class name ".scroll-btn")
replace the triple-dash token with the correct custom property name (use
var(--text-color-main)) so the button text/icon color is applied properly and
remains readable against the green background.

In `@client/src/pages/DetailTicket.css`:
- Around line 1-12: The CSS for the detail panel (.container-detail) uses a
fixed height (height: 300px) which clips variable content; replace the fixed
height with a content-driven rule such as removing height or using min-height
(e.g., min-height: 300px) so the panel can grow with longer descriptions, and
make the same change for the other panel rules referenced (the blocks around
lines 58-73 that also set fixed heights) to avoid brittle layouts on smaller
screens.

---

Minor comments:
In `@client/src/components/CardPendingProblem.css`:
- Around line 1-2: Remove the empty CSS rule for the selector "p,span" in
CardPendingProblem.css; locate the block "p,span { }" and delete it (or add the
intended style declarations if the empty block was left as a placeholder) so the
file no longer contains an empty selector that triggers the block-no-empty lint
error.

In `@client/src/components/ConfirmButton.css`:
- Line 16: Remove the stray blank line before the animation declaration and
rename keyframes and their usages to kebab-case to satisfy Stylelint: change
keyframe identifiers fadeIn and slideUp to fade-in and slide-up (or equivalent
kebab-case) in the `@keyframes` blocks and update all animation properties that
reference those names (e.g., animation: fadeIn 0.2s → animation: fade-in 0.2s)
in ConfirmButton.css so names match and stylelint passes.

In `@client/src/components/Navbar.jsx`:
- Line 8: Remove the debug console.log from the render path in Navbar.jsx:
delete the line that logs "Current User Role:" using user?.role (the stray
console.log in the Navbar component render). If runtime debugging is still
desired, move logging into a useEffect hook or a dev-only guard so it does not
execute on every render.

In `@client/src/components/SearchBar.jsx`:
- Around line 13-20: The markup in SearchBar.jsx doesn't include the "searchbar"
class expected by the stylesheet; update the component so the form (or a
surrounding container) has className="searchbar" so the CSS selectors
(.searchbar form, .searchbar input, .searchbar button) apply; locate the JSX in
SearchBar.jsx where handleSubmit, setSearch and the <form> are defined and add
the className to that element (or wrap the form in a div with
className="searchbar") without changing the existing handlers.

In `@client/src/hooks/useFilterDate.js`:
- Around line 14-15: The current early-return in useFilterDate always includes
items missing the dateField (if (!item[dateField]) return true), which bypasses
active date filters; change this to only allow undated items when no date filter
is set by checking startDate and endDate on the same function: if
item[dateField] is null/undefined, return true only when both startDate and
endDate are falsy (or no filter is active), otherwise return false so undated
rows are excluded while a range is active; reference the useFilterDate function
and the variables dateField, item, startDate, endDate when making this change.

In `@client/src/index.css`:
- Around line 56-72: Add a compatibility alias for the removed token by defining
--status-yellow (and --status-yellow-text) in the root CSS to point to the new
pending variables (e.g., --status-yellow: var(--status-pending-bg);
--status-yellow-text: var(--status-pending-text);) so existing consumers like
CardPendingProblem.css that reference --status-yellow keep working until they
are migrated to --status-pending-bg/--status-pending-text.

In `@client/src/pages/adminPage/AuditIssues.css`:
- Around line 90-97: The CSS rule .audit-issues-problem contains an extra blank
line before the gap declaration which triggers Stylelint's
declaration-empty-line-before; remove the empty line so the declarations are
contiguous (e.g., ensure padding: 2rem; is immediately followed by gap: 20px;)
in the .audit-issues-problem block to satisfy the linter.

In `@client/src/pages/DetailTicket.jsx`:
- Around line 105-107: DetailTicket currently checks and renders operator info
from ticket.admin but the payload provides ticket.adminId, so the operator block
is skipped; update the JSX in DetailTicket to check for ticket.admin ||
ticket.adminId and render the human-readable operator name when ticket.admin
exists otherwise fall back to displaying the adminId (or a mapped name if you
have a lookup), i.e. replace the conditional that references ticket.admin with a
check for either property and show ticket.admin when available or ticket.adminId
as the fallback.

In `@server/controllers/managementControllers.js`:
- Around line 140-175: The getEquipment controller is using the wrong HTTP
status and misleading log text; change res.status(201).json(equipments) to
res.status(200).json(equipments) and update the catch block messages in
getEquipment (both console.error and the JSON error payload) to refer to
"retrieving/listing equipment" (or similar) instead of "creating equipment" to
accurately reflect the read operation; ensure references to
prisma.equipment.findMany remain unchanged.

---

Nitpick comments:
In `@client/src/components/componentsAdmin/Adminsidebar.css`:
- Around line 39-53: Remove the duplicated `.nav-item.active` rule block and
keep the combined selector `.nav-item:hover, .nav-item.active` (which already
contains the needed declarations: color, border-right, background-color). Edit
the CSS to delete the second `.nav-item.active { ... }` block so there’s a
single source of truth for the hover/active styles and avoid future drift
between `.nav-item:hover` and `.nav-item.active`.

In `@client/src/components/FilterProblem.jsx`:
- Around line 5-10: The status filter array defined as buttons (in
FilterProblem.jsx) is missing the 'rejected' and 'duplicate' ticket states;
update the buttons constant to include objects for id: 'rejected' and id:
'duplicate' with appropriate labels (matching the existing language/label style)
so the filter control can select those statuses (refer to the buttons variable
in FilterProblem.jsx).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 71eecd19-d53c-416a-ac5a-5de4f799e2d2

📥 Commits

Reviewing files that changed from the base of the PR and between 605afce and 2f40bf1.

⛔ Files ignored due to path filters (2)
  • client/package-lock.json is excluded by !**/package-lock.json
  • server/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (35)
  • client/package.json
  • client/src/App.jsx
  • client/src/components/CardFinishProblem.css
  • client/src/components/CardPendingProblem.css
  • client/src/components/CardPendingProblem.jsx
  • client/src/components/ConfirmButton.css
  • client/src/components/ConfirmButton.jsx
  • client/src/components/DateRangeFilter.css
  • client/src/components/DateRangeFilter.jsx
  • client/src/components/FilterProblem.css
  • client/src/components/FilterProblem.jsx
  • client/src/components/Navbar.jsx
  • client/src/components/SearchBar.css
  • client/src/components/SearchBar.jsx
  • client/src/components/componentsAdmin/AdminLayout.jsx
  • client/src/components/componentsAdmin/AdminSidebar.jsx
  • client/src/components/componentsAdmin/Adminsidebar.css
  • client/src/hooks/useEquipment.js
  • client/src/hooks/useFilterDate.js
  • client/src/hooks/useTicketSearch.js
  • client/src/hooks/useTickets.js
  • client/src/index.css
  • client/src/pages/Dashboard.css
  • client/src/pages/Dashboard.jsx
  • client/src/pages/DetailTicket.css
  • client/src/pages/DetailTicket.jsx
  • client/src/pages/adminPage/AssetManagement.css
  • client/src/pages/adminPage/AssetManagement.jsx
  • client/src/pages/adminPage/AuditIssues.css
  • client/src/pages/adminPage/AuditIssues.jsx
  • client/src/services/ticketService.js
  • server/controllers/managementControllers.js
  • server/controllers/ticketControllers.js
  • server/prisma/schema.prisma
  • server/routes/managementRoutes.js

Comment thread client/src/App.jsx
Comment on lines +49 to +51
<Route path="Management" element={
<Suspense fallback={<div>Loading...</div>}></Suspense>
} />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C2 'path="Management"' client/src/App.jsx
rg -n -C2 '<Suspense[^>]*>\s*</Suspense>' client/src/App.jsx

Repository: CNPJB/trouble-tracking-system-project

Length of output: 329


🏁 Script executed:

# Get the full App.jsx file and examine the route structure
wc -l client/src/App.jsx

Repository: CNPJB/trouble-tracking-system-project

Length of output: 103


🏁 Script executed:

# Read the relevant sections of App.jsx to see the full routing context
cat -n client/src/App.jsx | head -100

Repository: CNPJB/trouble-tracking-system-project

Length of output: 3092


🏁 Script executed:

# Search for other Route definitions to understand the pattern
rg -n "path=" client/src/App.jsx | head -20

Repository: CNPJB/trouble-tracking-system-project

Length of output: 639


🏁 Script executed:

# Search for Management.jsx or Management component
fd -i "management" client/src/pages/adminPage/

Repository: CNPJB/trouble-tracking-system-project

Length of output: 175


🏁 Script executed:

# Also check the full adminPage directory structure
ls -la client/src/pages/adminPage/

Repository: CNPJB/trouble-tracking-system-project

Length of output: 461


Management route has no component—will render a blank page.

Line 49-51: The Suspense boundary is empty with no child component. Unlike AuditIssues and AssetManagement routes, no Management.jsx component exists or is imported. This will render a blank page when navigating to /adminPage/Management.

Either create and import a Management component using React.lazy (following the pattern of other admin pages), or remove this route if it's not yet needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/App.jsx` around lines 49 - 51, The Management route's Suspense
boundary is empty so navigating to "/adminPage/Management" will render a blank
page; fix by either creating and importing a Management component and using it
as the Suspense child (follow the pattern used for AuditIssues and
AssetManagement: add a React.lazy import for Management and render <Management
/> inside the existing Suspense), or if the page is not ready, remove the <Route
path="Management" .../> entry entirely; ensure you reference the Route with
path="Management" and the Suspense wrapper when making the change.

Comment on lines +15 to +20
.img-card,img{
object-fit: cover;
object-position: center;
width: 150px;
height: 150px;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Scope the image rule to this card.

The bare img selector will resize every image in the app to 150×150 with object-fit: cover. Limit this to the pending-card thumbnail only.

Suggested fix
-.img-card,img{
+.img-card,
+.img-card img{
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/CardPendingProblem.css` around lines 15 - 20, The CSS
rule currently targets all images via the global selector `img`; change the
selector to scope the styles to the card thumbnail only by replacing the
selector `.img-card,img` with a descendant selector like `.img-card img` (or
`.pending-card img` if that class exists on the card root) so only images inside
the pending-card container receive `object-fit: cover`, `object-position:
center`, and the 150×150 sizing; keep the same property block but remove the
bare `img` selector.

Comment thread client/src/components/CardPendingProblem.jsx
@@ -0,0 +1,17 @@
import { AdminSidebar } from "./AdminSidebar.jsx";
import { Outlet } from 'react-router-dom';
import React , {children} from "react";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify invalid named import pattern in admin layout files.
# Expected: occurrences of `{children}` named import should be removed.

rg -nP 'import\s+React\s*,\s*\{\s*children\s*\}\s+from\s+["'\'']react["'\'']' client/src -C2

Repository: CNPJB/trouble-tracking-system-project

Length of output: 535


🏁 Script executed:

cat -n client/src/components/componentsAdmin/AdminLayout.jsx

Repository: CNPJB/trouble-tracking-system-project

Length of output: 650


🏁 Script executed:

# Check if 'children' identifier is used anywhere in the file
rg -n '\bchildren\b' client/src/components/componentsAdmin/AdminLayout.jsx

Repository: CNPJB/trouble-tracking-system-project

Length of output: 124


🌐 Web query:

React module named exports - does React export children as named export

💡 Result:

No. React does not export the JSX “children” you pass to a component as a named export. In React, “children” is just the special prop props.children (the JSX content placed between a component’s opening and closing tags). It’s not provided by the React package as something like import { children } from 'react'. What React does provide as named exports are the helpers under React.Children (capital C), which you can import as import { Children } from 'react'; and use like Children.map, Children.count, etc.

Citations:


Remove invalid React named import: {children}

children is not a named export from the React module. This import will cause a module resolution error and prevent the component from loading.

Fix import line
-import React  , {children} from "react";
+import React from "react";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import React , {children} from "react";
import React from "react";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/componentsAdmin/AdminLayout.jsx` at line 3, The import
line in AdminLayout.jsx incorrectly imports a non-existent named export
`{children}` from React; remove `{children}` so the line reads `import React
from "react";` and if the AdminLayout component uses children, ensure the
component signature accepts it (e.g., function AdminLayout({ children }) or
props.children) rather than importing it from React; update any references to
use the local children prop accordingly.

Comment on lines +28 to +51
<NavLink to="/" className="nav-item" end>
<FaTools className="nav-icon" />
<span>Issue Management</span>
</NavLink>

<NavLink to="/adminPage/AssetManagement" className="nav-item">
<FaDesktop className="nav-icon" />
<span>Asset Management</span>
</NavLink>

<NavLink to="/tracking" className="nav-item">
<FaUserCog className="nav-icon" />
<span>User Management</span>
</NavLink>

<NavLink to="/tracking" className="nav-item">
<FaMapMarkedAlt className="nav-icon" />
<span>Location Management</span>
</NavLink>

<NavLink to="/tracking" className="nav-item">
<FaTags className="nav-icon" />
<span>Issue Categories</span>
</NavLink>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Sidebar contains route targets that don’t match registered admin routes.

Line 38, 43, and 48 point to /tracking, and Line 28 points to /. In client/src/App.jsx (Line 37–58), registered admin routes are under /adminPage/* (Management, AuditIssues, AssetManagement). These links will navigate to wrong/missing pages.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/componentsAdmin/AdminSidebar.jsx` around lines 28 - 51,
The NavLink targets in AdminSidebar.jsx don't match the registered admin routes;
update the NavLink "to" props so they point to the admin routes used in App.jsx
(replace the root "/" NavLink and the three NavLinks currently using "/tracking"
with the correct admin paths). Specifically, change the NavLink that renders
FaTools (currently to="/") to the admin management route (e.g.,
"/adminPage/Management" or the exact route name used in App.jsx), and change the
NavLinks that render FaUserCog, FaMapMarkedAlt, and FaTags (currently
to="/tracking") to the corresponding "/adminPage/..." routes (e.g.,
"/adminPage/AssetManagement", "/adminPage/AuditIssues" or the exact route names
in App.jsx) so all NavLink "to" values match the registered routes.

<div className="assetManagement-container">
<div className="filter-assetManagement-container">
<div className="audit-issues-searchbar">
<SearchBar />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pass onSearch to SearchBar to prevent submit-time crash.

Line 22 renders <SearchBar /> without the required callback; submit will call onSearch(search) and throw.

Suggested fix
-          <SearchBar />
+          <SearchBar onSearch={(query) => {
+            // TODO: hook this into equipment filtering
+            console.log('search query:', query);
+          }} />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<SearchBar />
<SearchBar onSearch={(query) => {
// TODO: hook this into equipment filtering
console.log('search query:', query);
}} />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/pages/adminPage/AssetManagement.jsx` at line 22, The SearchBar is
rendered without the required onSearch prop and will crash when it calls
onSearch(search); add a handler in this component (e.g., function
handleSearch(search) { /* perform filtering/fetch or update state */ }) and pass
it to the SearchBar as <SearchBar onSearch={handleSearch} />; reference the
SearchBar component and ensure handleSearch implements the behavior you need
(update component state or call whatever fetch/filter function like
fetchAssets/filterAssets) to avoid the submit-time crash.

Comment thread client/src/pages/adminPage/AuditIssues.jsx Outdated
import { SearchBar } from '../components/SearchBar.jsx';
import { CardFinishProblem } from '../components/CardFinishProblem'
import { FaChevronLeft, FaChevronRight } from 'react-icons/fa';
import { CardPendingProblem } from '../components/CardpendingProblem.jsx';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify actual filename casing and import usage
fd -i "CardPendingProblem.jsx"
rg -n --type=jsx "CardpendingProblem\\.jsx|CardPendingProblem\\.jsx"

Repository: CNPJB/trouble-tracking-system-project

Length of output: 172


🏁 Script executed:

#!/bin/bash
# Read the Dashboard.jsx file around line 7 to verify the import statement
cat -n client/src/pages/Dashboard.jsx | head -20

# Search for all imports/uses of CardPendingProblem (case-insensitive) across the codebase
echo "---"
rg -n "CardPendingProblem|CardpendingProblem" --type=ts --type=tsx --type=js --type=jsx

Repository: CNPJB/trouble-tracking-system-project

Length of output: 1059


🏁 Script executed:

#!/bin/bash
# Search for all references to this component with simpler grep
grep -r "CardpendingProblem\|CardPendingProblem" client/src --include="*.jsx" --include="*.js"

Repository: CNPJB/trouble-tracking-system-project

Length of output: 719


Correct import casing for CardPendingProblem.jsx to match the actual component filename.

Line 7 imports from CardpendingProblem.jsx (lowercase 'p'), but the component file is named CardPendingProblem.jsx (uppercase 'P'). This will cause module resolution failures on case-sensitive filesystems (Linux, macOS, CI environments).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/pages/Dashboard.jsx` at line 7, The import for the component is
using the wrong case; update the import statement that references
CardpendingProblem.jsx to match the actual component name CardPendingProblem.jsx
(change the path/import to ../components/CardPendingProblem.jsx) so the symbol
CardPendingProblem resolves correctly on case-sensitive filesystems and the
module loads without errors.

Comment on lines +178 to +206
export const mergeTickets = async (req, res) => {
try {
const { parentId, childIds } = req.body;

if (!parentId || !childIds || !Array.isArray(childIds) || childIds.length === 0) {
return res.status(400).json({
error: 'ข้อมูลไม่ครบถ้วน กรุณาส่งตัวแม่และตัวลูกอย่างน้อย 1 รายการ'
});
}

await prisma.ticket.updateMany({
where: {
ticketId: { in: childIds }
},
data: {
parentTicketId: parentId,
}
});
console.log(`ดำเนินการรวมปัญหา: แม่ = ${parentId}, ลูกๆ =`, childIds);

res.status(200).json({
message: 'รวมปัญหาสำเร็จเรียบร้อยแล้ว',
mergedCount: childIds.length
});
} catch (error) {
console.error('Error creating equipment:', error);
res.status(500).json({ error: 'Failed to merge ticket ' });
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate the merge target before writing.

A missing or unknown parentId will fail at the FK layer and bubble as a 500, and mergedCount currently assumes every requested child was updated. Reject self-merges / invalid parents up front and base the response on the rows actually changed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/controllers/managementControllers.js` around lines 178 - 206, In
mergeTickets, validate the parent before writing: check parentId is not included
in childIds (reject self-merge) and confirm the parent exists via
prisma.ticket.findUnique (return 400 if not found), deduplicate/filter childIds
to remove the parent and any duplicates, then call prisma.ticket.updateMany with
the filtered childIds and use the returned count (result.count) to set
mergedCount and to decide success vs partial/no-op; update error messages
accordingly and avoid assuming every requested child was updated.

Comment thread server/routes/managementRoutes.js Outdated
@poner2547
poner2547 merged commit 9f025f3 into develop May 2, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant