Files
SR-SYSTEM/docs/feature-implementation-plan.md
T
2026-06-02 13:50:39 +09:00

38 KiB

SR System — Feature Implementation Plan

Analysis date: 2026-05-26 Scope: Calendar, Notifications, User Profile, ADMIN/MANAGER Management


Executive Summary

Feature Existing Backend New Backend Frontend Priority Effort
Calendar None Calendar aggregation endpoint CalendarPage + CalendarWidget P2 5d
Notifications Full (read, mark-read, unread count) Add link_url field to Notification entity NotificationDropdown P1 2d
User Profile Partial (getMe, portfolio, dispatch-history) ChangePassword endpoint + Extended EmployeeSummary ProfilePage P1 4d
ADMIN/MANAGER Partial (employee CRUD, report listing) Dispatch CRUD, CommonCode CRUD, Report summary aggregations EmployeeEditModal, DispatchManager, ReportDashboard, SettingsPage P1 (Reports), P2 (Dispatch), P2 (Settings) 8d total

Total estimated effort: 19 days (full-time, single dev). Parallel work possible — Admin features and Profile can be developed concurrently with Calendar and Notifications.


1. Calendar Feature

1.1 Current State Analysis

Aspect Status
Header Calendar icon Route: /issues (no calendar relevance)
Backend calendar endpoint Does not exist
Data with dates Ticket.dueDate, Report.targetDate, Project.startDate/endDate, DispatchHistory.startDate/endDate
Frontend calendar page Does not exist

The Header component (line 65):

<button onClick={() => router.push('/issues')} ...>
  <Calendar className="w-5 h-5" />
</button>

1.2 What's Missing

  1. Backend: Calendar aggregation endpoint — No single endpoint to fetch events across domains. Need:

    • GET /api/v1/calendar?start=YYYY-MM-DD&end=YYYY-MM-DD — returns unified events
    • Events aggregated from: Ticket due dates, Report target dates, Dispatch start/end dates
  2. Backend: Calendar event entity — No dedicated schedule/schedule_type entity. Two options:

    • Option A (Recommended): Aggregation endpoint that queries existing entities (Ticket, Report, DispatchHistory) and returns a unified DTO. Zero schema change.
    • Option B: New Schedule entity with schedule_type (MEETING, DEADLINE, MILESTONE) — more flexible but adds complexity.
  3. Frontend: Calendar page (/app/(main)/calendar/page.tsx) — Full calendar view with month/week/day modes.

  4. Frontend: Calendar event types — Ticket due dates, report deadlines, dispatch milestones.

1.3 Design Proposal

1.3.1 Backend: Calendar Aggregation Endpoint

New DTO: CalendarEventDto

public record CalendarEventDto(
    String eventType,      // TICKET_DUE, REPORT_DUE, DISPATCH_START, DISPATCH_END
    Long sourceId,         // ticketId / reportId / dispatchId
    String title,
    String description,
    LocalDate eventDate,
    String color,          // semantic color per type
    String linkUrl         // navigation URL (/issues/123, /work-reports/456, etc.)
) {}

New Controller Method (in a new CalendarController or added to an existing controller):

@GetMapping("/api/v1/calendar")
@PreAuthorize("hasAnyRole('EMPLOYEE','MANAGER','ADMIN')")
ResponseEntity<ApiResponse<List<CalendarEventDto>>> getCalendar(
    @RequestParam @DateTimeFormat(iso=ISO.DATE) LocalDate start,
    @RequestParam @DateTimeFormat(iso=ISO.DATE) LocalDate end,
    @CurrentUser Employee currentUser)

New Service: CalendarService

  • Queries TicketRepository.findByDueDateBetweenAndRequester_EmpId(start, end, empId) (for employee) or all tickets (for manager/admin)
  • Queries ReportRepository.findByTargetDateBetweenAndUser_EmpId(start, end, empId) or all
  • Queries DispatchHistoryRepository.findByStartDateBetween(start, end) (only active, DISPATCHED)
  • Merges results into List<CalendarEventDto>

Event color mapping:

Event Type Color Icon
TICKET_DUE #3B82F6 (blue) Ticket
REPORT_DUE #10B981 (green) FileText
DISPATCH_START #F59E0B (amber) Play
DISPATCH_END #EF4444 (red) Stop

1.3.2 Frontend: Calendar Page

Route: /calendar

Design:

┌─────────────────────────────────────────────────────────────────┐
│ Calendar                                    ◀ 2026.05 ▶ Today   │
├──┬────┬────┬────┬────┬────┬────┐                              │
│S │ M  │ T  │ W  │ T  │ F  │ S  │                              │
├──┼────┼────┼────┼────┼────┼────┤                              │
│  │    │    │    │    │ 1  │ 2  │                              │
│  │    │    │    │    │ ●  │    │                              │
│  │ 4  │ 5  │ 6  │ 7  │ 8  │ 9  │                              │
│  │ ●  │ ●  │    │ ■  │    │    │                              │
│  │ 11 │ 12 │ 13 │ 14 │ 15 │ 16 │                              │
│  │    │ ▲  │ ●  │    │    │ ■  │                              │
│  │ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │                              │
│  │    │    │ ●  │    │    │    │                              │
│  │ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │                              │
│  │    │    │ ■  │    │    │    │                              │
├──┴────┴────┴────┴────┴────┴────┤                              │
│ Legend:   ● Report Due   ■ Dispatch   ▲ Ticket Due            │
└─────────────────────────────────────────────────────────────────┘

Components to create:

  • src/app/(main)/calendar/page.tsx — Main calendar page
  • src/components/calendar/CalendarGrid.tsx — Month grid view (no external library — custom CSS Grid, 7-column)
  • src/components/calendar/CalendarEvent.tsx — Event chip with color dot + title (truncated)
  • src/components/calendar/EventDetailPanel.tsx — Slide-over or modal showing event details
  • src/components/calendar/CalendarWidget.tsx — Mini calendar widget for dashboard (optional, P3)

Added to sidebar:

{ name: 'Calendar', href: '/calendar', icon: Calendar }

1.4 Implementation Plan — Calendar

Step Task File(s) Effort
1 Create CalendarEventDto record backend/.../dto/CalendarEventDto.java 0.3d
2 Create CalendarService with aggregation logic backend/.../service/CalendarService.java 0.7d
3 Create CalendarController endpoint backend/.../controller/CalendarController.java 0.3d
4 Add calendarService to frontend services src/services/calendarService.ts 0.3d
5 Add CalendarEvent type to frontend types src/types/index.ts 0.2d
6 Build CalendarGrid component src/components/calendar/CalendarGrid.tsx 1.5d
7 Build CalendarEvent chip component src/components/calendar/CalendarEvent.tsx 0.5d
8 Build EventDetailPanel slide-over src/components/calendar/EventDetailPanel.tsx 0.5d
9 Build /calendar page src/app/(main)/calendar/page.tsx 0.5d
10 Update Header Calendar icon to /calendar src/components/layout/Header.tsx 0.1d
11 Add Calendar to Sidebar src/components/layout/Sidebar.tsx 0.1d
Total 5 days

2. Notification System

2.1 Current State Analysis

Aspect Status
Backend API ✅ Full: GET /notifications, GET /notifications/unread, PUT /notifications/{id}/read
Frontend notificationStore ✅ Polls unread count (30s interval), fetches list, marks as read
Notification entity fields notificationId, type, title, message, isRead, createdAt
Bell icon behavior Calls fetchNotifications() on click but no dropdown/modal renders
Missing link_url field — no way to navigate to related entity from notification

2.2 What's Missing

  1. Frontend: NotificationDropdown component — Bell click should show a dropdown listing recent notifications.
  2. Frontend: Click-to-navigate — Clicking a notification should navigate to the relevant page (ticket detail, report, etc.).
  3. Backend: linkUrl field — Notification entity has type but no link to the source entity.

2.3 Design Proposal

2.3.1 Backend: Add linkUrl to Notification Entity

Migration:

ALTER TABLE tb_notification ADD COLUMN link_url VARCHAR(500);

Entity update (Notification.java):

@Column(name = "link_url", length = 500)
private String linkUrl;

Service update — When creating notifications, set linkUrl:

Type linkUrl Example
TICKET_ASSIGNED /issues/123
TICKET_RESOLVED /issues/123
REPORT_APPROVED /work-reports/456
REPORT_REJECTED /work-reports/456
SLA_WARNING /issues/789
EQUIPMENT_ASSIGNED /itam/123

2.3.2 Frontend: Notification Dropdown

Component: NotificationDropdown.tsx

┌─────────────────────────────────┐
│ Notifications            [x]    │  ← Header: "Notifications" + close button
├─────────────────────────────────┤
│ 🔵 Ticket #123 assigned to you  │  ← Unread: blue left border
│   2 minutes ago          →      │
├─────────────────────────────────┤
│ ✅ Report #456 approved         │  ← Read: no left border
│   1 hour ago              →      │
├─────────────────────────────────┤
│ ⚠️ SLA Warning: #789 Overdue    │  ← Critical: red left border
│   3 hours ago             →      │
├─────────────────────────────────┤
│                                 │
│         View All            ↗   │  ← Link to full notification page
└─────────────────────────────────┘

Behavior:

  • Dropdown slides down from bell icon (absolute positioned)
  • Shows latest 10 notifications
  • Click notification → markAsRead(id) + navigate to linkUrl
  • Click "View All" → /notifications page (optional, P3)
  • Click outside → close dropdown
  • Escape key → close dropdown

Layout:

  • Max height: 400px, overflow-y: auto
  • Each item: 12px padding, border-bottom, hover bg-gray-50
  • Width: 360px
  • Unread items: bg-indigo-50/30, blue dot (6px) left
  • Categories: Icon + title (bold 13px) + time ago (gray 11px)

2.4 Implementation Plan — Notifications

Step Task File(s) Effort
1 Add linkUrl column to Notification entity Notification.java + migration 0.3d
2 Update NotificationListener to set linkUrl backend/.../listener/NotificationListener.java 0.3d
3 Add linkUrl to frontend Notification type src/types/index.ts 0.1d
4 Build NotificationDropdown component src/components/layout/NotificationDropdown.tsx 1.0d
5 Integrate into Header (replace bell onClick) src/components/layout/Header.tsx 0.2d
6 Add mark-all-as-read endpoint (optional) Backend + service 0.2d
Total 2 days

3. User Profile Management

3.1 Current State Analysis

Aspect Status
GET /api/v1/employees/me ✅ Returns EmployeeSummary (empId, name, email, roleCode, dispatchStatus)
GET /api/v1/employees/{empId}/dispatch-histories ✅ Returns DispatchHistory[]
GET /api/v1/employees/{empId}/portfolio ✅ Returns PortfolioResponse[] (with reports + resolved tickets)
PUT /api/v1/employees/{empId} ✅ Admin-only update endpoint
Change password endpoint Missing
Extended profile info (phone, empStatus, joinedDate) Missing from /me (EmployeeSummary is minimal)
/profile page Does not exist

3.2 What's Missing

  1. Backend: PUT /api/v1/employees/me/password — Change password endpoint for current user.
  2. Backend: Extended /me response — EmployeeSummary is too minimal. Need phone, empStatus, joinedDate, dispatchStatus label.
  3. Frontend: /profile page — View/edit profile, change password, view dispatch history, view portfolio.
  4. Frontend: Profile editing — Allow user to edit their own name, email, phone (or restrict to admin-only for certain fields).

3.3 Design Proposal

3.3.1 Backend: Change Password Endpoint

New DTO: ChangePasswordRequest

public record ChangePasswordRequest(
    @NotBlank String currentPassword,
    @NotBlank @Size(min=8) String newPassword
) {}

New Endpoint in AuthController or EmployeeController:

@PutMapping("/api/v1/employees/me/password")
@PreAuthorize("hasAnyRole('EMPLOYEE','MANAGER','ADMIN')")
ResponseEntity<ApiResponse<Void>> changePassword(
    @Valid @RequestBody ChangePasswordRequest request,
    @CurrentUser Employee currentUser)

Logic:

  1. Verify currentPassword matches stored hash
  2. Encode newPassword and save
  3. Invalidate existing tokens (optional — add token_version field)

3.3.2 Backend: Extended EmployeeSummary

Update EmployeeSummary to include:

public record EmployeeSummary(
    Long empId,
    String loginId,
    String name,
    String email,
    String phone,           // NEW
    RoleCode roleCode,
    EmpStatus empStatus,    // NEW
    DispatchStatus dispatchStatus,
    LocalDate joinedDate,   // NEW
    LocalDate leftDate      // NEW (nullable)
) {}

3.3.3 Frontend: Profile Page Design

URL: /profile

For EMPLOYEE (own profile):

┌─────────────────────────────────────────────────────┐
│ [Avatar]  김민수                                     │
│           파견직원  ·  재직중  ·  파견중               │
│                                                      │
│ ┌─ Personal Info ─────────────────────────────────┐  │
│ │  Login ID:    minsu.kim                          │  │
│ │  Name:        김민수                             │  │
│ │  Email:       minsu@example.com                  │  │
│ │  Phone:       010-1234-5678                      │  │
│ │  Joined:      2024-03-01                         │  │
│ │  Status:      ACTIVE (DISPATCHED)                │  │
│ │  [Edit Info]  [Change Password]                  │  │
│ └──────────────────────────────────────────────────┘  │
│                                                      │
│ ┌─ Dispatch History ──────────────────────────────┐  │
│ │  Timeline with projects, dates, roles            │  │
│ └──────────────────────────────────────────────────┘  │
│                                                      │
│ ┌─ Portfolio Summary ─────────────────────────────┐  │
│ │  Aggregated stats: projects, tickets, reports    │  │
│ └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────┘

For MANAGER/ADMIN viewing another employee:

  • URL: /profile/[empId]
  • Same layout but with employee selector/dropdown at top
  • Manager can view but not edit (unless admin)
  • Admin can edit fields

3.3.4 Components to Create

Component Description
src/app/(main)/profile/page.tsx Own profile view
src/app/(main)/profile/[empId]/page.tsx View other employee's profile (MANAGER/ADMIN)
src/components/profile/ProfileCard.tsx Personal info card with edit/change-password buttons
src/components/profile/EditProfileModal.tsx Modal for editing personal info (admin only or self?)
src/components/profile/ChangePasswordModal.tsx Modal with current/new/confirm password fields
src/components/profile/DispatchTimeline.tsx Reuse timeline from /dispatch page
src/components/profile/PortfolioStats.tsx Summary stats cards (total projects, total tickets resolved, etc.)

3.4 Implementation Plan — User Profile

Step Task File(s) Effort
1 Create ChangePasswordRequest DTO Backend dto 0.1d
2 Add changePassword to AuthService AuthService.java 0.3d
3 Add PUT /employees/me/password endpoint AuthController.java or EmployeeController.java 0.2d
4 Extend EmployeeSummary to include phone, empStatus, joinedDate EmployeeSummary.java + EmployeeService.toSummary() 0.2d
5 Add getMeFull() and changePassword() to employeeService src/services/employeeService.ts 0.2d
6 Build ProfileCard component src/components/profile/ProfileCard.tsx 0.5d
7 Build ChangePasswordModal component src/components/profile/ChangePasswordModal.tsx 0.5d
8 Build EditProfileModal component (admin-only for role/status changes; self-service for email/phone) src/components/profile/EditProfileModal.tsx 0.5d
9 Build PortfolioStats component src/components/profile/PortfolioStats.tsx 0.3d
10 Build /profile page src/app/(main)/profile/page.tsx 0.8d
11 Build /profile/[empId] page (manager/admin view) src/app/(main)/profile/[empId]/page.tsx 0.4d
12 Make user avatar/name in Header clickable → /profile src/components/layout/Header.tsx 0.1d
Total 4 days

4. ADMIN/MANAGER Management Features

4.1 Current State Analysis

4.1.1 Employee CRUD

Operation Backend Frontend
List/View ✅ GET /employees (MANAGER/ADMIN) ✅ /employees page with table view
Create ✅ POST /employees (ADMIN) ✅ Modal in /employees page
Update ✅ PUT /employees/{id} (ADMIN) ❌ Only MoreHorizontal button with no handler
Delete ✅ DELETE /employees/{id} (ADMIN) ❌ No delete UI
Search ✅ GET /employees/search ✅ Search bar in /employees

Gap: Edit and delete functionality missing from frontend. The MoreHorizontal button (line 454-456 in employees/page.tsx) is a blank <button> with no click handler.

4.1.2 Dispatch Assignment

Operation Backend Frontend
Create dispatch ❌ No endpoint ❌ No page
List dispatch by employee ✅ GET /employees/{id}/dispatch-histories ❌ Only shown in employee's own /dispatch page
List all dispatches ❌ No endpoint ❌ No management view
Link employee to project ❌ No endpoint ❌

Gap: There is NO controller/service method for creating a DispatchHistory. The DispatchHistoryService exists but only has repository calls, no create/update methods. MANAGER/ADMIN have no way to assign employees to projects.

4.1.3 Report Monitoring Dashboard

Operation Backend Frontend
List all reports ✅ ReportController (MANAGER/ADMIN see all) ✅ Works via work-reports page
Report review/approval ✅ PUT /reports/{id}/review ❌ No approval UI for managers
Pending count ❌ No aggregate endpoint Dashboard fetches totalElements from page=1 query (approximate)
Report statistics ❌ No stats endpoint ❌

Gap: Manager needs a dedicated report monitoring page showing all submitted reports in a table with quick approve/reject actions. Dashboard count is a workaround.

4.1.4 System Settings (Common Codes)

Operation Backend Frontend
List codes by group ✅ GET /common-codes/{groupCode} ❌ No page
Create/Update/Delete codes ❌ No endpoints ❌

Gap: Common code management is a pure ADMIN function. There are no CRUD endpoints for common codes and no settings page.

4.2 Design Proposals

4.2.1 Employee Edit/Delete

Frontend: EmployeeEditModal.tsx

  • Opens on MoreHorizontal click
  • Edit: name, email, roleCode, empStatus, dispatchStatus, joinedDate
  • Delete: Confirm dialog → soft delete
  • After save → refresh employee list

Add to /employees page:

// Replace blank MoreHorizontal button:
<button onClick={() => setEditingEmployee(emp)}>
  <MoreHorizontal className="w-4 h-4" />
</button>

4.2.2 Dispatch Management

Backend needs:

New Controller: DispatchHistoryController.java

@PostMapping("/api/v1/dispatch-histories")
@PreAuthorize("hasAnyRole('MANAGER','ADMIN')")
ResponseEntity<ApiResponse<DispatchHistory>> create(CreateDispatchRequest request)

@PutMapping("/api/v1/dispatch-histories/{dispatchId}")
@PreAuthorize("hasAnyRole('MANAGER','ADMIN')")
ResponseEntity<ApiResponse<DispatchHistory>> update(Long dispatchId, UpdateDispatchRequest request)

@GetMapping("/api/v1/dispatch-histories")
@PreAuthorize("hasAnyRole('MANAGER','ADMIN')")
ResponseEntity<ApiResponse<Page<DispatchHistory>>> findAll(Pageable pageable, @RequestParam(required=false) Long empId, @RequestParam(required=false) Long projectId)

New DTOs:

public record CreateDispatchRequest(
    @NotNull Long empId,
    @NotNull Long projectId,
    @NotNull LocalDate startDate,
    LocalDate endDate,
    @NotBlank String roleTitle,
    @NotNull Integer contributionRate,
    @NotBlank String individualTech,
    @NotBlank String performedTasks
) {}

Frontend: Dispatch Management Page

URL: /dispatch/manage (MANAGER/ADMIN only)

┌─────────────────────────────────────────────────────┐
│ Dispatch Management                [+ New Dispatch]  │
├─────────┬──────────┬─────────┬─────────┬────────────┤
│ Employee│ Project  │ Role    │ Period  │ Actions    │
├─────────┼──────────┼─────────┼─────────┼────────────┤
│ 김민수   │ Samsung  │ Backend │ 24.03~  │ [Edit][Del]│
│ 이영희   │ LG CNS   │ Frontend│ 24.06~  │ [Edit][Del]│
│ ...     │ ...      │ ...     │ ...     │ ...        │
└─────────┴──────────┴─────────┴─────────┴────────────┘

Create Dispatch modal:

  • Employee selector (autocomplete search)
  • Project selector (dropdown from /projects/my or all projects)
  • Date range picker
  • Role title, contribution rate, tech stack, tasks

4.2.3 Report Monitoring Dashboard

URL: /work-reports/review (MANAGER/ADMIN only)

┌─────────────────────────────────────────────────────┐
│ Report Review Dashboard                              │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Submitted │ │Pending   │ │Approved  │ │Rejected  │ │
│ │   12     │ │    5     │ │   45     │ │    3     │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────┤
│ [Filter: SUBMITTED ▼] [Date: 2026-05 ▼] [Search...]│
├─────────┬─────────┬──────────┬─────────┬────────────┤
│ Employee│ Type    │ Date     │ Status  │ Action     │
├─────────┼─────────┼──────────┼─────────┼────────────┤
│ 김민수   │ DAILY   │ 05-26    │ SUBMIT  │[✅][❌][👁] │
│ 이영희   │ WEEKLY  │ 05-20    │ SUBMIT  │[✅][❌][👁] │
│ 박철수   │ MONTHLY │ 05-01    │ SUBMIT  │[✅][❌][👁] │
└─────────┴─────────┴──────────┴─────────┴────────────┘

Action buttons:

  • ✅ Approve → PUT /reports/{id}/review { status: "APPROVED" }
  • ❌ Reject → Opens rejection modal with required feedback text
  • 👁 View → Navigate to report detail

New Backend Endpoint (optional):

@GetMapping("/api/v1/reports/summary")
@PreAuthorize("hasAnyRole('MANAGER','ADMIN')")
ResponseEntity<ApiResponse<ReportSummary>> getSummary()
// Returns counts by status: { submitted, approved, rejected, draft }

4.2.4 System Settings (Common Codes)

Backend needs:

New endpoints in CommonCodeController.java:

@PostMapping
@PreAuthorize("hasRole('ADMIN')")
ResponseEntity<ApiResponse<CommonCode>> create(CommonCode code)

@PutMapping("/{codeId}")
@PreAuthorize("hasRole('ADMIN')")
ResponseEntity<ApiResponse<CommonCode>> update(Long codeId, CommonCode code)

@DeleteMapping("/{codeId}")
@PreAuthorize("hasRole('ADMIN')")
ResponseEntity<ApiResponse<Void>> delete(Long codeId)

Frontend: Settings Page

URL: /settings (ADMIN only)

┌─────────────────────────────────────────────────────┐
│ System Settings                                      │
│ ┌──────────────────────┬───────────────────────────┐ │
│ │ Common Codes         │ Code Group: [Role ▼]       │ │
│ │  ├ Group List        │ ┌──────┬──────┬────┬────┐ │ │
│ │  │ • Role            │ │ Code │ Name │Sort│    │ │ │
│ │  │ • Report Type     │ ├──────┼──────┼────┼────┤ │ │
│ │  │ • Ticket Category │ │EMPLOY│파견직원│ 1  │[✏️][🗑]│ │
│ │  │ • Equipment Type  │ │MANAG│본사관리│ 2  │[✏️][🗑]│ │
│ │  │ • ...             │ │ADMIN│최고   │ 3  │[✏️][🗑]│ │
│ │  │                   │ └──────┴──────┴────┴────┘ │ │
│ │  │                   │         [+ Add Code]       │ │
│ └──────────────────────┴───────────────────────────┘ │
│                                                      │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Other Settings                                   │ │
│ │  □ Enable email notifications                   │ │
│ │  □ Enable Slack notifications                   │ │
│ │  Default SLA hours: [48 ▼]                      │ │
│ │  [Save]                                          │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘

4.3 Implementation Plan — ADMIN/MANAGER Features

Phase A: Report Monitoring Dashboard (P1, ~2 days)

Step Task File(s) Effort
1 Add ReportSummary DTO + GET /reports/summary endpoint Backend 0.3d
2 Add reportService.getSummary() to frontend services src/services/reportService.ts 0.1d
3 Build report review dashboard page src/app/(main)/work-reports/review/page.tsx 1.0d
4 Add approve/reject inline actions Same as above + modal 0.4d
5 Add navigation from dashboard "Pending Reports" card to review page src/app/(main)/page.tsx 0.1d
6 Add sidebar link for MANAGER/ADMIN (conditional render) src/components/layout/Sidebar.tsx 0.1d

Phase B: Employee Edit/Delete (P1, ~1.5 days, already mostly built on backend)

Step Task File(s) Effort
1 Build EmployeeEditModal component src/components/employees/EmployeeEditModal.tsx 0.5d
2 Add delete confirmation dialog Same component 0.2d
3 Wire MoreHorizontal button to open edit modal src/app/(main)/employees/page.tsx 0.3d
4 Refresh list after edit/delete Same page 0.2d
5 Add employee detail view (linking to /profile/[empId]) Same page 0.3d

Phase C: Dispatch Management (P2, ~3 days)

Step Task File(s) Effort
1 Create CreateDispatchRequest + UpdateDispatchRequest DTOs Backend 0.2d
2 Create DispatchHistoryController with CRUD endpoints Backend 0.5d
3 Add dispatchHistoryService.getAll(), .create(), .update(), .delete() to frontend src/services/dispatchHistoryService.ts (new) 0.3d
4 Build dispatch management page src/app/(main)/dispatch/manage/page.tsx 1.0d
5 Build create/edit dispatch modal with employee search + project select Same + modal component 0.8d
6 Add sidebar link (MANAGER/ADMIN only) src/components/layout/Sidebar.tsx 0.1d

Phase D: System Settings (P2, ~1.5 days)

Step Task File(s) Effort
1 Add POST/PUT/DELETE to CommonCodeController Backend 0.3d
2 Add create/update/delete to commonCodeService src/services/commonCodeService.ts (new) 0.2d
3 Build settings page with code group list + editor src/app/(main)/settings/page.tsx 1.0d
4 Add sidebar link (ADMIN only) src/components/layout/Sidebar.tsx 0.1d

5. Consolidated File List

5.1 Backend — Files to Create

File Feature Description
dto/CalendarEventDto.java Calendar Calendar event aggregation DTO
service/CalendarService.java Calendar Aggregation logic from Ticket, Report, Dispatch
controller/CalendarController.java Calendar GET /api/v1/calendar endpoint
dto/ChangePasswordRequest.java Profile Password change request DTO
dto/CreateDispatchRequest.java Dispatch Dispatch creation request DTO
dto/UpdateDispatchRequest.java Dispatch Dispatch update request DTO
controller/DispatchHistoryController.java Dispatch Full CRUD for dispatch histories
service/DispatchManagementService.java Dispatch Management-level dispatch operations

5.2 Backend — Files to Modify

File Feature Change
entity/Notification.java Notifications Add linkUrl column
dto/EmployeeSummary.java Profile Add phone, empStatus, joinedDate, leftDate fields
service/AuthService.java Profile Add changePassword() method
controller/AuthController.java or EmployeeController.java Profile Add PUT /employees/me/password endpoint
service/EmployeeService.java Profile Update toSummary() to include new fields
controller/ReportController.java Reports Add GET /reports/summary endpoint
controller/CommonCodeController.java Settings Add POST, PUT, DELETE endpoints
service/CommonCodeService.java Settings Add create, update, delete methods

5.3 Frontend — Files to Create

File Feature Description
src/services/calendarService.ts Calendar GET /calendar?start=&end=
src/services/dispatchHistoryService.ts Dispatch Full CRUD for dispatch histories
src/services/commonCodeService.ts Settings CRUD for common codes
src/components/calendar/CalendarGrid.tsx Calendar Monthly calendar grid component
src/components/calendar/CalendarEvent.tsx Calendar Event chip component
src/components/calendar/EventDetailPanel.tsx Calendar Event detail modal
src/components/layout/NotificationDropdown.tsx Notifications Bell dropdown component
src/components/profile/ProfileCard.tsx Profile Personal info display/edit card
src/components/profile/ChangePasswordModal.tsx Profile Password change modal
src/components/profile/EditProfileModal.tsx Profile Profile edit modal
src/components/profile/PortfolioStats.tsx Profile Portfolio summary stats
src/components/employees/EmployeeEditModal.tsx Admin Employee edit + delete modal
src/components/dispatch/DispatchFormModal.tsx Admin Create/edit dispatch form
src/app/(main)/calendar/page.tsx Calendar Calendar page
src/app/(main)/profile/page.tsx Profile Own profile page
src/app/(main)/profile/[empId]/page.tsx Profile Employee profile (manager view)
src/app/(main)/work-reports/review/page.tsx Reports Report review dashboard
src/app/(main)/dispatch/manage/page.tsx Dispatch Dispatch management page
src/app/(main)/settings/page.tsx Settings System settings page

5.4 Frontend — Files to Modify

File Feature Change
src/types/index.ts All Add Notification.linkUrl, CalendarEvent, ReportSummary, CalendarEvent types
src/services/index.ts All Export new services
src/services/employeeService.ts Profile Add getMeFull(), changePassword()
src/services/reportService.ts Reports Add getSummary()
src/components/layout/Header.tsx Calendar + Profile + Notifications Calendar → /calendar, integrate NotificationDropdown, avatar → /profile
src/components/layout/Sidebar.tsx All Add Calendar, Report Review, Settings links (with RBAC)
src/app/(main)/page.tsx Reports Link "Pending Reports" card to /work-reports/review
src/app/(main)/employees/page.tsx Admin Wire MoreHorizontal to edit modal

Week 1: Quick Wins
  Day 1-2: Notifications (Dropdown UI + linkUrl)             ← P1, ~2d
  Day 3-5: User Profile (ProfilePage + ChangePassword)       ← P1, ~4d

Week 2: Calendar + Report Management
  Day 1-3: Employee Edit/Delete (EmployeeEditModal)          ← P1, ~1.5d
  Day 3-5: Report Monitoring Dashboard                       ← P1, ~2d

Week 3: Calendar + Dispatch
  Day 1-5: Calendar (Backend aggregation + Full Calendar page) ← P2, ~5d

Week 4: Admin Features
  Day 1-3: Dispatch Management (CRUD endpoints + page)       ← P2, ~3d
  Day 4-5: System Settings (CommonCode CRUD + Settings page) ← P2, ~1.5d

Alternative — parallel by developer:

  • Dev A: Calendar (5d) + Settings (1.5d) = 6.5d
  • Dev B: Notifications (2d) + Profile (4d) = 6d
  • Dev C: Employee Edit (1.5d) + Report Dashboard (2d) + Dispatch (3d) = 6.5d
  • Total calendar time: ~1.5 weeks with 3 developers

7. Risk Assessment

Risk Impact Mitigation
Calendar aggregation performance with large datasets Medium Add DB indexes on due_date, target_date; paginate results
Notification polling load Low Already 30s interval — acceptable. Could go to 60s after 30min idle
Password change breaks existing sessions Medium Option A: Invalidate all tokens on password change. Option B: Add tokenVersion to user and check on JWT validation
DispatchHistory creation without project exists validation Medium Backend must validate project exists and is not completed/hold
Common code changes break existing dropdowns High Never hard-delete common codes — add is_active toggle instead. Frontend caches codes on load
Concurrent employee edits by multiple admins Low Add @Version optimistic lock to Employee entity

8. Quick Wins (Low Effort, High Impact)

If you only have 1 day, do these:

  1. Notification Dropdown (~2h) — Make the bell icon functional. Just build the dropdown UI, no backend changes needed. Notifications already have type/title/message.
  2. Header Calendar fix (~5min) — Change onClick={() => router.push('/issues')} to onClick={() => router.push('/calendar')} even before building the calendar page — at least the button has a logical destination.
  3. Header avatar → /profile (~5min) — Wrap the avatar/name in a Link to /profile.
  4. Employee MoreHorizontal → Edit (~2h) — Wire the existing PUT /employees/{id} backend to a simple edit form.