Problem & Context
What Needed to Change.
Telecom network operations and performance data — equipment deployments such as OPTIM, COMBAT, Massive MIMO and repeaters, plus revenue, profitability, OPEX, traffic payload, and subscriber metrics — is spread across regions and time periods, making it hard to see how each network event or action affected the business. This dashboard provides a single authenticated web interface that aggregates events and KPIs for the Java–Bali area and its regions (Jawa Timur, Jawa Tengah, Bali Nusra), with filters for month, category, and action, so users can compare baselines against event-period results instead of manually reconciling reports.
Built for telecom network operations and engineering teams to monitor network deployment programs (OPTIM, COMBAT, CMON, EasyMacro, Massive MIMO, and Repeaters) and track their regional performance and revenue impact across Area Jawa Bali.
Constraints & Tradeoffs
The Shape of the Decision Space.
Constraints
- Every data request must carry a Firebase ID token in the Authorization header, so all API modules gate calls on an authenticated currentUser and throw if no session exists
- The frontend is a pure client-side SPA with no backend code in this repository; all aggregation, filtering, sorting, and pagination logic lives behind an external REST API consumed via VITE_API_BASE_URL
- Sorting, searching, and pagination for the event table are delegated to the server (page, limit, sortBy, sortOrder, searchQuery params), so the UI must stay in sync with server-side pagination state rather than sorting locally
- The app must work in both light and dark themes with a fixed brand palette (primary red #e20012) implemented through MUI/Toolpad theming
- Configuration is environment-driven: Firebase project keys and the API base URL are injected through Vite environment variables, with no hardcoded endpoints
Tradeoffs
- Backend-for-frontend separation: keeping the SPA thin and pushing all aggregation to a separate API simplified the client but couples every screen to network latency and token lifecycle — mitigated by an API warmup ping on the sign-in page
- Server-side over client-side table operations: delegating search/sort/pagination to the API scales to large event datasets but requires extra request plumbing and a 500ms debounced search to avoid request spam
- Parallel dashboard fetching with Promise.all across four region endpoints plus filter endpoints renders the full KPI grid in one pass, at the cost of firing many simultaneous authenticated requests on every filter change
- Client-managed Firebase ID token with browser-session persistence simplified session handling but required explicit token refresh logic (onIdTokenChanged / force refresh) and careful redirect flows on sign-out
Architecture
A Deliberately Legible System.
- 01
Sign-in & session
User signs in via Firebase Authentication (email/password, browserSessionPersistence, password-reset flow); the sign-in page also fires a warmup request to the backend /other/warmup endpoint and redirects authenticated users to /dashboard.
- 02
Route protection
A ProtectedRoute component backed by react-firebase-hooks blocks the /dashboard route for unauthenticated users, while an AuthContext tracks user and ID token via onIdTokenChanged.
- 03
Token acquisition
For every data call, the active Firebase user issues a fresh ID token (getIdToken), which is attached as a Bearer token in the Authorization header of each Axios request.
- 04
API layer
Typed service modules under src/api (tableData, graphData, eventsAreaData, eventsRegionEJ/CJ/BNData, actionSummary, month/category/action filters, clearCache) call REST endpoints on VITE_API_BASE_URL and map responses into TypeScript interfaces.
- 05
Server-side aggregation
The external backend (not in this repo) performs filtering, sorting, pagination, and baseline/event/delta metric computation; the frontend renders returned pagination metadata and nested Metric objects directly.
- 06
Dashboard rendering
The Dashboard view fetches filters, action summary, and four regional event aggregates in parallel with Promise.all, then formats values (de-DE locale, Mio/PB units) into MUI KPI cards with month/category/action multi-select filters.
- 07
Charts & table views
ApexCharts renders 12-month area charts per region (revenue, profitability, OPEX, payload, users with toggle buttons), while the MUI data table renders server-paginated events with baseline/event/delta tooltips per metric.
- 08
Deployment
Vite builds the SPA to dist/, which firebase.json serves on the Firebase Hosting site 'dashboard-netproductivity' with SPA rewrites to index.html; a Vercel deployment is also linked from the GitHub repo.
Screens & States
The Interface in Context.



Results
What the Dashboard Delivers.
- Deployed a working authenticated dashboard (Firebase Hosting site 'dashboard-netproductivity', plus a linked Vercel deployment) serving sign-in, dashboard, graph, and table views
- Implemented 12 typed API service modules covering KPI aggregates, monthly graph series, action summaries, filter options, cache clearing, and server-paginated event tables
- Delivered a filterable KPI dashboard aggregating event counts, revenue, profitability, OPEX, payload, and users for one area and three regions, with growth indicators and light/dark theming
- Built a server-driven events table with debounced search, sortable columns, pagination, and baseline/event/delta metric tooltips
Lessons
What I Would Carry Forward.
- Centralizing auth in an AuthContext and reusing one token-acquisition pattern across all API modules keeps Firebase token handling consistent — every service follows the same check-user, get-token, attach-header flow
- Delegating table search/sort/pagination to the server keeps the client simple but demands careful state synchronization — pairing a debounced search input with server-driven pagination prevents redundant requests
- Fanning out regional dashboard requests with Promise.all is a pragmatic way to populate a multi-card KPI grid in one render cycle when the backend exposes one endpoint per region
- Driving all configuration through Vite environment variables (Firebase keys, API base URL) kept secrets and environment switching out of the source code, making the same build deployable to both Firebase Hosting and Vercel