Skip to content

responsive design - #17

Merged
poner2547 merged 1 commit into
developfrom
feature/responesiveMobileAndipad
Jul 31, 2026
Merged

poner2547 merged 1 commit into
developfrom
feature/responesiveMobileAndipad

Conversation

@poner2547

@poner2547 poner2547 commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Responesive design

Summary by CodeRabbit

  • New Features

    • Added responsive mobile navigation for tracking, statistics, and administration areas.
    • Added improved user-management layouts with scrollable tables, sticky headers, and responsive forms.
    • Added month-accurate date ranges to statistics charts.
    • Added single-slide behavior for urgent-ticket carousels on small screens.
  • Bug Fixes

    • Improved equipment import notifications, including success, partial-success, validation, and network error messages.
    • Ticket images now consistently open in the image viewer.
    • Location and floor expansion now prevents multiple sections from being open simultaneously.
    • Improved equipment relationship handling and partial-import reporting.
  • Style

    • Refined responsive layouts, sidebar behavior, filters, buttons, and mobile spacing across the application.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds generated project reports, responsive navigation and administration layouts, SweetAlert2 upload feedback, dynamic statistics periods, consistent ticket image modals, and improved equipment import relationship mapping.

Changes

Application updates

Layer / File(s) Summary
Generated project reports
.VSCodeCounter/2026-07-26_17-39-52/*
Added project metrics, per-file statistics, language and directory summaries, and zero-change diff reports.
Responsive navigation and sidebars
client/src/components/*, client/src/components/componentsAdmin/*, client/src/components/componentsStyles/*
Updated mobile controls, tracking drawer behavior, overlays, sidebar breakpoints, and filter status styling.
Upload feedback and statistics rendering
client/package.json, client/src/hooks/*, client/src/pages/DetailTicket.jsx, client/src/pages/Statistics.jsx, client/src/pages/pageStyles/*, client/src/utils/*
Added SweetAlert2 notifications, modal-only ticket image clicks, month-specific weekly chart ranges, defensive rendering checks, and responsive tracking/statistics layouts.
Administration layouts and expansion behavior
client/src/pages/adminPage/*
Added responsive category, location, issue, and user-management layouts. Location and floor expansion now allow one open item at a time.
Equipment import relationships and response status
server/controllers/EquipmentControllers.js
Equipment imports now resolve room records and derive floor and location relationships. Partial failures return HTTP 400 with success: false.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: cnpjb

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant useImportEquipments
  participant EquipmentControllers
  User->>useImportEquipments: submit equipment file
  useImportEquipments->>EquipmentControllers: upload equipment data
  EquipmentControllers-->>useImportEquipments: success or error response
  useImportEquipments-->>User: display SweetAlert2 notification
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary focus of the pull request, which adds responsive design updates for mobile and tablet layouts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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/responesiveMobileAndipad

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

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

@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: 9

Caution

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

⚠️ Outside diff range comments (4)
client/src/pages/adminPage/UserManagement.css (1)

134-168: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Scope the action-button selectors to UserManagement.

.btn, .btn-confirm, and .btn-cancel are global selectors. client/src/pages/adminPage/LocationManagement.jsx uses the same class names at Lines 537-542. These rules can change the location-management action layout, colors, and spacing based on stylesheet load order.

Use page-specific class names, or prefix these selectors with .user-management.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/pages/adminPage/UserManagement.css` around lines 134 - 168, The
action-button selectors in the UserManagement stylesheet are global and conflict
with LocationManagement. Scope `.btn`, `.btn-confirm`, and `.btn-cancel` under
the UserManagement page using page-specific class names or a `.user-management`
prefix, and ensure the corresponding UserManagement markup uses the scoped
selectors.
client/src/pages/adminPage/Categories.css (1)

172-180: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the stray w token.

Line 176 changes the following selector to w .categories-manage-container. The intended responsive rule does not apply, and Stylelint reports an unknown type selector.

   .categories-main-container {
     grid-template-columns: 1fr;
-  }w
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/pages/adminPage/Categories.css` around lines 172 - 180, Remove the
stray `w` token immediately after the `.categories-main-container` rule within
the `@media (max-width: 820px)` block, leaving `.categories-manage-container` as
the standalone selector so its responsive width rule applies correctly.

Source: Linters/SAST tools

server/controllers/EquipmentControllers.js (2)

140-161: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Fix the fileName/filename variable mismatch that breaks CSV uploads.

Line 140 declares filename (lowercase n). Line 161 checks fileName.endsWith('.csv'), a different, undeclared variable. Every .csv upload throws ReferenceError: fileName is not defined, which is caught by the outer try/catch and returned as a generic 500 error instead of the intended CSV-parsing flow. This predates the current diff, but it sits directly inside the uploadEquipments function this PR modifies extensively, so fix it while this code is being touched.

🐛 Proposed fix
-        } else if (fileName.endsWith('.csv')) {
+        } else if (filename.endsWith('.csv')) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/controllers/EquipmentControllers.js` around lines 140 - 161, In the
uploadEquipments function, update the CSV extension check to use the
already-declared filename variable consistently, preserving the intended CSV
parsing flow for .csv uploads.

186-208: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Keep room matching on the same normalized input as categories.

Use normalize(item.roomId) and key roomMap with normalize(r.roomName) instead of .trim() only. The Room.roomName field has no @unique constraint, so duplicate names can also silently select only the last matching room and attach equipment to the wrong room/floor.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/controllers/EquipmentControllers.js` around lines 186 - 208, The room
lookup in the room-matching flow must use the same normalization as category
matching. Update the roomMap construction to key each room with
normalize(r.roomName), and ensure item room lookups use normalize(item.roomId);
preserve the existing room object values while applying the normalized keys
consistently.
🧹 Nitpick comments (1)
client/src/pages/pageStyles/Statistics.css (1)

196-366: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consolidate the duplicated 820px and 430px rule blocks.

The @media (max-width: 820px) block (Lines 196-366) and the @media(max-width: 430px) block (Lines 368-531) repeat the same selectors and declarations almost line for line (sidebar header, mobile menu, backdrop, active nav state, card text sizing). Move the shared rules into the 820px breakpoint only, and keep the 430px breakpoint for actual overrides (for example the .Statistics-layout-content padding/margin difference at Lines 489-492). This reduces the risk of the two breakpoints drifting apart on future edits.

Also applies to: 368-531

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/pages/pageStyles/Statistics.css` around lines 196 - 366,
Consolidate the duplicated responsive styles by keeping shared selectors and
declarations for the sidebar header, mobile menu, backdrop, active navigation
state, and card text sizing in the existing `@media` (max-width: 820px) block.
Reduce the `@media` (max-width: 430px) block to genuine mobile-only overrides,
preserving differences such as the Statistics-layout-content padding and margin
adjustments.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.VSCodeCounter/2026-07-26_17-39-52/details.md:
- Line 12: Update the Markdown report generator template to emit one blank line
between every section heading and its table, ensuring regenerated reports
satisfy MD058. Apply the generated spacing in
.VSCodeCounter/2026-07-26_17-39-52/details.md lines 12-12, diff-details.md lines
12-12, diff.md lines 12-12 and 16-16, and results.md lines 12-12 and 27-27.

In @.VSCodeCounter/2026-07-26_17-39-52/results.txt:
- Line 2: Configure VSCode Counter to generate repository-relative paths, then
regenerate the reports. Update .VSCodeCounter/2026-07-26_17-39-52/results.txt at
lines 2-2, details.md at 5-5, diff-details.md at 5-5, diff.md at 5-5, diff.txt
at 2-2, results.json at 1-1, and results.md at 5-5 so no absolute directories,
usernames, or encoded absolute URI keys remain; use relative paths and redact
the Directory fields as specified.

In `@client/src/components/componentsStyles/StatisticsSidebar.css`:
- Line 78: Remove the empty .navbar-toggle rule from the stylesheet so it no
longer violates the block-no-empty lint rule.

In `@client/src/components/componentsStyles/TrackingSidebar.css`:
- Around line 179-196: Update the mobile .tracking-sidebar rule to set bottom:
0, change height to auto, and add overflow-y: auto so the drawer remains within
the viewport and its content can scroll on short screens.

In `@client/src/components/TrackingSidebar.jsx`:
- Around line 22-34: Add accessible drawer controls in the TrackingSidebar
component: give the mobile hamburger button an aria-label and aria-expanded tied
to isOpen, and render a visible or screen-reader-accessible close button using
the existing close-btn styling inside the tracking-sidebar that calls
setIsOpen(false).

In `@client/src/pages/adminPage/LocationManagement.css`:
- Line 15: Update the smallest-breakpoint media-query rules around the selectors
at lines 261–269 to target .main-location-container instead of the stale
.main-container selector, ensuring the renamed layout class receives the
intended mobile margin-top at widths of 430px or less.

In `@client/src/pages/DetailTicket.jsx`:
- Around line 126-127: Update or remove the stale comment immediately above the
onClick handler that calls setShowMoreAfterImages so it accurately describes
that the action opens the modal, regardless of image count.

In `@client/src/pages/Statistics.jsx`:
- Around line 71-78: Update the /api/manage/getTicket-stats implementation so
its weekIndex calculation uses the same week boundaries and dynamic bucket count
as getRealWeekDay in Statistics.jsx. Remove the fixed five-bucket/index-4 cap,
ensuring 4-, 5-, and 6-week months produce matching statistics arrays and labels
without dropped or duplicated values.

In `@client/src/utils/getRealWeekDay.js`:
- Around line 17-22: Remove the stray bare SVGNumberList statement from the
weekEndDate calculation block in getRealWeekDay, leaving the surrounding date
logic unchanged.

---

Outside diff comments:
In `@client/src/pages/adminPage/Categories.css`:
- Around line 172-180: Remove the stray `w` token immediately after the
`.categories-main-container` rule within the `@media (max-width: 820px)` block,
leaving `.categories-manage-container` as the standalone selector so its
responsive width rule applies correctly.

In `@client/src/pages/adminPage/UserManagement.css`:
- Around line 134-168: The action-button selectors in the UserManagement
stylesheet are global and conflict with LocationManagement. Scope `.btn`,
`.btn-confirm`, and `.btn-cancel` under the UserManagement page using
page-specific class names or a `.user-management` prefix, and ensure the
corresponding UserManagement markup uses the scoped selectors.

In `@server/controllers/EquipmentControllers.js`:
- Around line 140-161: In the uploadEquipments function, update the CSV
extension check to use the already-declared filename variable consistently,
preserving the intended CSV parsing flow for .csv uploads.
- Around line 186-208: The room lookup in the room-matching flow must use the
same normalization as category matching. Update the roomMap construction to key
each room with normalize(r.roomName), and ensure item room lookups use
normalize(item.roomId); preserve the existing room object values while applying
the normalized keys consistently.

---

Nitpick comments:
In `@client/src/pages/pageStyles/Statistics.css`:
- Around line 196-366: Consolidate the duplicated responsive styles by keeping
shared selectors and declarations for the sidebar header, mobile menu, backdrop,
active navigation state, and card text sizing in the existing `@media` (max-width:
820px) block. Reduce the `@media` (max-width: 430px) block to genuine mobile-only
overrides, preserving differences such as the Statistics-layout-content padding
and margin adjustments.
🪄 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 Plus

Run ID: 21dd1157-3323-4ef3-807b-39c375925fb4

📥 Commits

Reviewing files that changed from the base of the PR and between b6e8b1f and c91a84f.

⛔ Files ignored due to path filters (3)
  • .VSCodeCounter/2026-07-26_17-39-52/diff.csv is excluded by !**/*.csv
  • .VSCodeCounter/2026-07-26_17-39-52/results.csv is excluded by !**/*.csv
  • client/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (30)
  • .VSCodeCounter/2026-07-26_17-39-52/details.md
  • .VSCodeCounter/2026-07-26_17-39-52/diff-details.md
  • .VSCodeCounter/2026-07-26_17-39-52/diff.md
  • .VSCodeCounter/2026-07-26_17-39-52/diff.txt
  • .VSCodeCounter/2026-07-26_17-39-52/results.json
  • .VSCodeCounter/2026-07-26_17-39-52/results.md
  • .VSCodeCounter/2026-07-26_17-39-52/results.txt
  • client/package.json
  • client/src/components/Navbar.jsx
  • client/src/components/StatisticsSidebar.jsx
  • client/src/components/TrackingSidebar.jsx
  • client/src/components/componentsAdmin/AdminSidebar.jsx
  • client/src/components/componentsAdmin/Adminsidebar.css
  • client/src/components/componentsStyles/FilterProblem.css
  • client/src/components/componentsStyles/Navbar.css
  • client/src/components/componentsStyles/StatisticsSidebar.css
  • client/src/components/componentsStyles/TrackingSidebar.css
  • client/src/hooks/useImportEquipments.js
  • client/src/pages/DetailTicket.jsx
  • client/src/pages/Statistics.jsx
  • client/src/pages/adminPage/Categories.css
  • client/src/pages/adminPage/IssueManagement.jsx
  • client/src/pages/adminPage/LocationManagement.css
  • client/src/pages/adminPage/LocationManagement.jsx
  • client/src/pages/adminPage/UserManagement.css
  • client/src/pages/adminPage/UserManagement.jsx
  • client/src/pages/pageStyles/Statistics.css
  • client/src/pages/pageStyles/Tracking.css
  • client/src/utils/getRealWeekDay.js
  • server/controllers/EquipmentControllers.js

[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md)

## Files
| filename | language | code | comment | blank | total |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the generated Markdown table spacing.

Add a blank line after each section heading before its table. Update the generator template so regenerated reports pass markdownlint MD058.

  • .VSCodeCounter/2026-07-26_17-39-52/details.md#L12-L12: add spacing after ## Files.
  • .VSCodeCounter/2026-07-26_17-39-52/diff-details.md#L12-L12: add spacing after ## Files.
  • .VSCodeCounter/2026-07-26_17-39-52/diff.md#L12-L12: add spacing after ## Languages.
  • .VSCodeCounter/2026-07-26_17-39-52/diff.md#L16-L16: add spacing after ## Directories.
  • .VSCodeCounter/2026-07-26_17-39-52/results.md#L12-L12: add spacing after ## Languages.
  • .VSCodeCounter/2026-07-26_17-39-52/results.md#L27-L27: add spacing after ## Directories.
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 12-12: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)

📍 Affects 4 files
  • .VSCodeCounter/2026-07-26_17-39-52/details.md#L12-L12 (this comment)
  • .VSCodeCounter/2026-07-26_17-39-52/diff-details.md#L12-L12
  • .VSCodeCounter/2026-07-26_17-39-52/diff.md#L12-L12
  • .VSCodeCounter/2026-07-26_17-39-52/diff.md#L16-L16
  • .VSCodeCounter/2026-07-26_17-39-52/results.md#L12-L12
  • .VSCodeCounter/2026-07-26_17-39-52/results.md#L27-L27
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.VSCodeCounter/2026-07-26_17-39-52/details.md at line 12, Update the
Markdown report generator template to emit one blank line between every section
heading and its table, ensuring regenerated reports satisfy MD058. Apply the
generated spacing in .VSCodeCounter/2026-07-26_17-39-52/details.md lines 12-12,
diff-details.md lines 12-12, diff.md lines 12-12 and 16-16, and results.md lines
12-12 and 27-27.

Source: Linters/SAST tools

@@ -0,0 +1,209 @@
Date : 2026-07-26 17:39:52
Directory : c:\Users\Palmt\Desktop\Project\trouble-tracking-system-project

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Sanitize absolute paths in all generated reports.

The reports expose the developer's Windows username and local checkout structure. Configure VSCode Counter to emit repository-relative paths, then regenerate all reports.

  • .VSCodeCounter/2026-07-26_17-39-52/results.txt#L2-L2: replace the absolute directory and file paths.
  • .VSCodeCounter/2026-07-26_17-39-52/details.md#L5-L5: redact the Directory field.
  • .VSCodeCounter/2026-07-26_17-39-52/diff-details.md#L5-L5: redact the Directory field.
  • .VSCodeCounter/2026-07-26_17-39-52/diff.md#L5-L5: redact the Directory field.
  • .VSCodeCounter/2026-07-26_17-39-52/diff.txt#L2-L2: replace the absolute directory.
  • .VSCodeCounter/2026-07-26_17-39-52/results.json#L1-L1: replace encoded absolute URI keys with relative paths.
  • .VSCodeCounter/2026-07-26_17-39-52/results.md#L5-L5: redact the Directory field.
📍 Affects 7 files
  • .VSCodeCounter/2026-07-26_17-39-52/results.txt#L2-L2 (this comment)
  • .VSCodeCounter/2026-07-26_17-39-52/details.md#L5-L5
  • .VSCodeCounter/2026-07-26_17-39-52/diff-details.md#L5-L5
  • .VSCodeCounter/2026-07-26_17-39-52/diff.md#L5-L5
  • .VSCodeCounter/2026-07-26_17-39-52/diff.txt#L2-L2
  • .VSCodeCounter/2026-07-26_17-39-52/results.json#L1-L1
  • .VSCodeCounter/2026-07-26_17-39-52/results.md#L5-L5
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.VSCodeCounter/2026-07-26_17-39-52/results.txt at line 2, Configure VSCode
Counter to generate repository-relative paths, then regenerate the reports.
Update .VSCodeCounter/2026-07-26_17-39-52/results.txt at lines 2-2, details.md
at 5-5, diff-details.md at 5-5, diff.md at 5-5, diff.txt at 2-2, results.json at
1-1, and results.md at 5-5 so no absolute directories, usernames, or encoded
absolute URI keys remain; use relative paths and redact the Directory fields as
specified.

display: none;
}

.navbar-toggle {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the empty rule.

Line 78 violates Stylelint block-no-empty. Remove .navbar-toggle {} because it has no declarations.

🧰 Tools
🪛 Stylelint (17.14.1)

[error] 78-78: Empty block (block-no-empty)

(block-no-empty)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/componentsStyles/StatisticsSidebar.css` at line 78,
Remove the empty .navbar-toggle rule from the stylesheet so it no longer
violates the block-no-empty lint rule.

Source: Linters/SAST tools

Comment on lines +179 to +196
.tracking-sidebar {
position: fixed;
top: 70px;
left: 0;
width: 280px;
/* ความกว้างของเมนูตอนสไลด์ออกมา */
border-radius: 0;
/* เอาขอบมนออก */
z-index: 999;
/* ลอยอยู่หน้าสุด */
padding-top: 20px;
background-color: #ffffff !important;
box-shadow: 4px 0 15px rgba(0, 0, 0, 0.15);
/* ใส่เงาด้านขวาให้ดูมีมิติ */

/* 💡 พระเอกอยู่ตรงนี้: สไลด์เก็บไปทางซ้ายสุดขอบ */
transform: translateX(-100%);
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the mobile drawer within the viewport.

At this breakpoint, the drawer starts at top: 70px and retains height: 100vh. Its bottom extends below the viewport. The drawer has no overflow-y rule, so menu content can become unreachable on short screens.

Set bottom: 0, use height: auto, and add overflow-y: auto.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/componentsStyles/TrackingSidebar.css` around lines 179
- 196, Update the mobile .tracking-sidebar rule to set bottom: 0, change height
to auto, and add overflow-y: auto so the drawer remains within the viewport and
its content can scroll on short screens.

Comment on lines +22 to +34
<button className="mobile-hamburger-btn" onClick={() => setIsOpen(true)}>
<LuPanelLeftClose className='nav-toggle-icon' />
</button>

{/* ปุ่มพิเศษ: รอประเมิน */}
<div className="special-menu-container">
<button
className={`sidebar-menu-btn review-btn ${activeTab === 'review' ? 'active' : ''}`}
onClick={() => onTabChange('review')}
>
<label>รอประเมิน<span className="personal-count"> ({counts.review ?? 0}) </span></label>
<span className="badge-exclamation">!</span>
</button>
<div
className={`sidebar-overlay ${isOpen ? 'active' : ''}`}
onClick={() => setIsOpen(false)}
></div>

<aside className={`tracking-sidebar ${isOpen ? 'open' : ''}`}>
<div className="tracking-sidebar-header">
<img src="/rmutk-logo.png" alt="Logo" />
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add an accessible drawer close action.

The icon-only button has no accessible name. The overlay at Line 26 is not keyboard reachable. The CSS defines .close-btn, but this component does not render it. A keyboard user can open the drawer but cannot close it without selecting another tab.

Add aria-label, aria-expanded, and a visible or screen-reader-accessible close button inside the drawer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/TrackingSidebar.jsx` around lines 22 - 34, Add
accessible drawer controls in the TrackingSidebar component: give the mobile
hamburger button an aria-label and aria-expanded tied to isOpen, and render a
visible or screen-reader-accessible close button using the existing close-btn
styling inside the tracking-sidebar that calls setIsOpen(false).

}

.main-container {
.main-location-container {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the smallest-breakpoint selector.

Line 15 renamed the layout class, but Line 269 still targets .main-container. At widths of 430px or less, .main-location-container does not receive the intended mobile margin-top.

Proposed fix
 `@media` (max-width: 430px) {
-  .main-container {
+  .main-location-container {
     margin-top: 20px;
     grid-template-columns: 1fr;
   }

Also applies to: 261-262

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/pages/adminPage/LocationManagement.css` at line 15, Update the
smallest-breakpoint media-query rules around the selectors at lines 261–269 to
target .main-location-container instead of the stale .main-container selector,
ensuring the renamed layout class receives the intended mobile margin-top at
widths of 430px or less.

Comment on lines 126 to +127
// ถ้ารูปเดียวเปิดแท็บใหม่ ถ้ารูปเยอะเปิด Modal
onClick={() => afterImages.length === 1 ? window.open(img.imageUrl, '_blank') : setShowMoreAfterImages(true)}
onClick={() => setShowMoreAfterImages(true)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the stale comment to match the new behavior.

The comment says the image opens a new tab when there is only one image. The code on Line 127 always opens the modal regardless of image count. Update or remove the comment so it matches the current behavior.

📝 Proposed fix
-                                                    // ถ้ารูปเดียวเปิดแท็บใหม่ ถ้ารูปเยอะเปิด Modal
+                                                    // คลิกเพื่อเปิด Modal แสดงรูปทั้งหมดเสมอ
                                                     onClick={() => setShowMoreAfterImages(true)}
📝 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
// ถ้ารูปเดียวเปิดแท็บใหม่ ถ้ารูปเยอะเปิด Modal
onClick={() => afterImages.length === 1 ? window.open(img.imageUrl, '_blank') : setShowMoreAfterImages(true)}
onClick={() => setShowMoreAfterImages(true)}
// คลิกเพื่อเปิด Modal แสดงรูปทั้งหมดเสมอ
onClick={() => setShowMoreAfterImages(true)}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/pages/DetailTicket.jsx` around lines 126 - 127, Update or remove
the stale comment immediately above the onClick handler that calls
setShowMoreAfterImages so it accurately describes that the action opens the
modal, regardless of image count.

Comment on lines +71 to 78
// เรียกใช้ฟังก์ชันคำนวณวันจากไฟล์ Utils
const dynamicWeekLabels = getRealWeekDay(selectedYear, selectedMonth);
const weeksCount = dynamicWeekLabels.length;

chartCategories = dynamicWeekLabels;
finalCreated = (ticketStats?.created || Array(weeksCount).fill(0)).slice(0, weeksCount);
finalResolved = (ticketStats?.resolved || Array(weeksCount).fill(0)).slice(0, weeksCount);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Locate the getTicket-stats handler to confirm the weekly bucket count logic.
rg -n -C 10 "getTicket-stats" --type=js

Repository: CNPJB/trouble-tracking-system-project

Length of output: 175


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repository files matching Statistics/useStats/statistics/ticket stats =="
git ls-files | rg -i 'Statistics|use.*stat|ticket.*stat|stats' || true

echo
echo "== search for getRealWeekDay =="
rg -n -C 8 "getRealWeekDay|useStatistics|chartCategories|finalCreated|finalResolved|ticketStats" . || true

Repository: CNPJB/trouble-tracking-system-project

Length of output: 10369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== client/src/hooks/useStatistics.js =="
cat -n client/src/hooks/useStatistics.js | sed -n '1,120p'

echo
echo "== client/src/utils/getRealWeekDay.js =="
cat -n client/src/utils/getRealWeekDay.js | sed -n '1,160p'

echo
echo "== all getTicket-stats occurrences across tracked files and ignore-case =="
git ls-files -z | xargs -0 rg -n -C 8 "getTicket[- ]stats|ticket[- ]stats|created:|resolved:" || true

Repository: CNPJB/trouble-tracking-system-project

Length of output: 11145


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== server/controllers/statisticController.js relevant section =="
cat -n server/controllers/statisticController.js | sed -n '1,190p'

echo
echo "== getRealWeekDay behavior probe =="
node - <<'JS'
const getRealWeekDay = (year, monthIndex) => {
    const months = ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.','ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'];
    const monthStr = months[monthIndex];
    let weeks = [];
    let startDate = new Date(year, monthIndex, 1); 
    const endDate = new Date(year, monthIndex + 1, 0); 
    while (startDate <= endDate) {
        let startDay = startDate.getDate();
        let dayOfWeek = startDate.getDay();
        let daysUntilSunday = dayOfWeek === 0 ? 0 : 7 - dayOfWeek; 
        let weekEndDate = new Date(startDate);
        weekEndDate.setDate(startDate.getDate() + daysUntilSunday);
        if (weekEndDate > endDate) {
            weekEndDate = new Date(endDate);
        }
        let endDay = weekEndDate.getDate();
        weeks.push(`${startDay} - ${endDay} ${monthStr}`);
        startDate = new Date(weekEndDate);
        startDate.setDate(startDate.getDate() + 1);
    }
    return weeks;
};
for (const y of [2025, 2026]) {
    for (const m of [0,1,2,3,4,5,6,7,8,9,10,11]) {
        const labels = getRealWeekDay(y, m);
        console.log(y, m + 1, labels.length, labels.join(' | '));
    }
}
JS

Repository: CNPJB/trouble-tracking-system-project

Length of output: 8796


Make /api/manage/getTicket-stats use the same weekly buckets as getRealWeekDay.

Statistics.jsx builds month labels from getRealWeekDay, which can return 4, 5, or 6 weeks. The backend still returns 5 buckets and caps values at index 4, so 6-week months will have one series label without data/possibly duplicated data. Match weekIndex to the label slice produced by the front-end week builder.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/pages/Statistics.jsx` around lines 71 - 78, Update the
/api/manage/getTicket-stats implementation so its weekIndex calculation uses the
same week boundaries and dynamic bucket count as getRealWeekDay in
Statistics.jsx. Remove the fixed five-bucket/index-4 cap, ensuring 4-, 5-, and
6-week months produce matching statistics arrays and labels without dropped or
duplicated values.

Comment on lines +17 to +22
let weekEndDate = new Date(startDate);
weekEndDate.setDate(startDate.getDate() + daysUntilSunday);
SVGNumberList
if (weekEndDate > endDate) {
weekEndDate = new Date(endDate);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Remove the stray SVGNumberList statement.

Line 19 is a bare reference to SVGNumberList with no assignment or effect. This looks like an accidental autocomplete artifact. It does nothing in a browser context, but it references an identifier that is not defined outside the browser (for example, in Jest without jsdom). Remove the line.

🐛 Proposed fix
         let weekEndDate = new Date(startDate);
         weekEndDate.setDate(startDate.getDate() + daysUntilSunday);
-        SVGNumberList
         if (weekEndDate > endDate) {
📝 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
let weekEndDate = new Date(startDate);
weekEndDate.setDate(startDate.getDate() + daysUntilSunday);
SVGNumberList
if (weekEndDate > endDate) {
weekEndDate = new Date(endDate);
}
let weekEndDate = new Date(startDate);
weekEndDate.setDate(startDate.getDate() + daysUntilSunday);
if (weekEndDate > endDate) {
weekEndDate = new Date(endDate);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/utils/getRealWeekDay.js` around lines 17 - 22, Remove the stray
bare SVGNumberList statement from the weekEndDate calculation block in
getRealWeekDay, leaving the surrounding date logic unchanged.

@poner2547
poner2547 merged commit cb376db into develop Jul 31, 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