feat: Telecom Technician-Job Scheduler with Gantt Chart (Spring Boot + React)#213
feat: Telecom Technician-Job Scheduler with Gantt Chart (Spring Boot + React)#213devin-ai-integration[bot] wants to merge 2 commits into
Conversation
- Spring Boot 3.2 backend with MySQL, JPA entities for Territory, Market, Technician, Job, Assignment - REST APIs for CRUD operations on all entities - Gantt chart API endpoint for technician-job schedule data - React 18 frontend with dhtmlx-gantt for interactive Gantt chart - Territory/market search panel with date picker - Drag-and-drop rescheduling with backend persistence - Color-coded task types (job types, travel, breaks) - Auto-seeded demo data for Ohio, Texas, California territories
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
… market filter - Add @JsonIgnoreProperties on Assignment entity relationships to prevent ByteBuddyInterceptor serialization errors when updating assignments via API - Convert marketIds array to stable string key in GanttChart useEffect dependency to prevent unnecessary re-renders
| } else { | ||
| assignments = assignmentRepository.findByAssignmentDate(date); | ||
| technicians = new ArrayList<>(); |
There was a problem hiding this comment.
🔴 GanttService returns empty data when no territory/market filter despite fetching assignments
In GanttService.getGanttData, the else branch (lines 39-41) fetches assignments from the database via findByAssignmentDate(date), but sets technicians to an empty ArrayList. Since the loop at line 50 iterates only over technicians to build the response, no Gantt tasks are ever produced — the fetched assignments are silently discarded. The API endpoint at GanttController.java:23-24 allows both territoryId and marketIds to be omitted (required = false), so this branch is reachable. Any caller hitting /api/gantt?date=... without filters receives an empty response even when assignments exist for that date.
Prompt for agents
In GanttService.getGanttData, the else branch (lines 39-41) fetches assignments via findByAssignmentDate(date) but sets technicians to an empty list. Since the loop at line 50 iterates only over technicians to build the result, no tasks are ever produced from those assignments.
The fix should either:
1. Also fetch all technicians in the else branch (e.g., technicianRepository.findAll()) so assignments are actually rendered, OR
2. Derive the technician list from the fetched assignments (extracting unique technicians from the assignment list), OR
3. Return an empty response intentionally — but then the assignments should not be fetched either, to avoid unnecessary DB queries.
Option 2 would be the most robust as it ensures the technician list is always consistent with the assignments fetched.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const [markets, setMarkets] = useState([]); | ||
| const [selectedTerritory, setSelectedTerritory] = useState(''); | ||
| const [selectedMarkets, setSelectedMarkets] = useState([]); | ||
| const [selectedDate, setSelectedDate] = useState(new Date().toISOString().split('T')[0]); |
There was a problem hiding this comment.
🟡 Default date uses UTC instead of local timezone, showing wrong date for US users in evening
At SearchPanel.js:9, the default date is computed as new Date().toISOString().split('T')[0]. toISOString() converts to UTC, so for users in negative UTC offset timezones (e.g., US Eastern at UTC-5, Pacific at UTC-8), the default date will be tomorrow's date during evening/night hours. For example, a user in US Eastern at 8 PM on April 1 would see April 2 as the default date, since 8 PM EDT = midnight UTC April 2. This is a telecom field supervisor tool likely used in US timezones, so this will regularly show the wrong default date.
| const [selectedDate, setSelectedDate] = useState(new Date().toISOString().split('T')[0]); | |
| const [selectedDate, setSelectedDate] = useState(() => { | |
| const d = new Date(); | |
| return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; | |
| }); |
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Adds a full-stack telecom technician-to-job scheduling application with an interactive Gantt chart UI. This is a greenfield project added alongside the existing repo contents.
Backend (
backend/): Spring Boot 3.2 + MySQL + JPATerritory → Market → Technician,Job,Assignment/api/ganttendpoint that assembles the schedule viewDataSeederauto-populates demo data (3 territories, 7 markets, 8 technicians, 16 jobs, ~60 assignments) usingLocalDate.now()Frontend (
frontend/): React 18 + dhtmlx-ganttSearchPanel: territory dropdown → cascading market multi-select → date pickerGanttChart: renders technician rows with color-coded task bars (jobs, travel, breaks); supports drag-move/resize to reschedule and double-click to update status — both persist viaPUT /api/assignments/{id}Updates since last revision
@JsonIgnoreProperties({"market", "hibernateLazyInitializer", "handler"})toAssignment.technicianandAssignment.jobrelationships. Without this,PUT /api/assignments/{id}threwInvalidDefinitionExceptionforByteBuddyInterceptorwhen serializing the response.marketIdsarray prop to a stable string key (marketIds.join(',')) in theGanttChartuseEffectdependency array. Previously, React's reference comparison on the array caused the effect to not re-fire correctly when switching market selections.Demo Recording
View original video (rec-be5932a5cbc14f1a97372b3f7a26de2c-edited.mp4)
Tested: Ohio territory (6 technicians), Columbus market filter (3 technicians), Texas territory switch (2 technicians), drag-to-reschedule with backend persistence.
Review & Testing Checklist for Human
application.propertiescontainstechjob/techjob123in plaintext. Acceptable for local demo only; must be externalized (env vars / Spring profiles) before any shared deployment.TechnicianController.create,JobController.create,MarketController.createcastMap<String, Object>values via.toString()with no null checks. Send a payload missing a required field and verify the error response is reasonable.Assignmententity serialization is now fixed, butTechnician.marketis stillLAZYwithFetchType.EAGERonly on theAssignmentside. TestGET /api/techniciansdirectly and verify noLazyInitializationExceptionoccurs.mvn spring-boot:runinbackend/, runnpm startinfrontend/, select Ohio territory, pick today's date, click Search, and verify the Gantt chart renders with technician rows and colored task bars. Drag a task bar and confirm the change persists on page refresh.Notes
DataSeederseeds assignments forLocalDate.now()only — the Gantt chart will appear empty for any other date.window.prompt()— functional but not production-quality.http://localhost:3000; will need adjustment for any non-local deployment.app_dotnet-angular-microservicesrepo as a separatebackend/+frontend/tree; it has no relationship to the existing .NET/Angular codebase.Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/52bccc96e664447f943e6b972a8a0c71