close
Skip to content

Repository files navigation

RCA Report Builder — Airtel Nigeria / Huawei Network FME Tool

A production-grade web application built for Airtel Nigeria's Field Maintenance Engineers (FMEs) to generate Root Cause Analysis (RCA) reports for network site outages. The app processes Huawei RNATracker .xlsb availability data alongside WhatsApp-pasted fault descriptions and produces a formatted Excel report suitable for SLA compliance filing.


Why This App Exists

Airtel Nigeria FMEs manage thousands of cell sites across 37 states (including FCT). When a site goes down, the engineer must:

  1. Pull availability data from Huawei's RNATracker (.xlsb format)
  2. Read fault descriptions pasted in WhatsApp group chats (cascade format, partner headers, etc.)
  3. Classify each fault into a standardized RCA category and bucket (e.g., "I H S PASSIVE FAULT / I H S_GENERATOR")
  4. Produce an Excel report matching Airtel's SLA template format
  5. Track chronic sites and FME performance over time

Doing this manually for hundreds of sites per report is error-prone and slow. This app automates the entire pipeline — from .xlsb parsing through AI-assisted fault classification to styled .xlsx export.


How It Works — Step by Step

A 6-step wizard GUI:

Step Component What You Do
1 Upload Drop in a Huawei RNATracker .xlsb file (or split files by network)
2 Configure Pick report date, networks (2G/3G/4G), states to include, and availability threshold
3 Preview See the filtered site list with availability values; proceed when ready
4 RCA Input Paste fault descriptions from WhatsApp. The app parses them (single-site lines, ROOT+N(SITE,SITE) cascade patterns, bulk N sites (ID,ID): desc). Sends unparsed cascades to Google Gemini for AI extraction. Classifies each event using partner-first keyword engine → learned mappings → fuzzy fallback → Gemini AI
5 Review Browse all sites with their AI-assigned categories/buckets. Edit inline, filter by state/site/status, use bulk auto-correct, mark contradictions, train corrections. Voice-controlled classification also works here
6 Export Preview the Excel output per network sheet. Download a fully styled .xlsx with color-coded rows (red=unmatched, amber=low availability, green=high avail), auto-filter headers, chronic sites sheet, and summary statistics

Architecture & Tech Stack

Frontend

Layer Technology
Framework React 19 + TypeScript
Routing TanStack Router v1 (file-based, src/routes/)
Meta-framework TanStack Start (SSR-ready)
Styling Tailwind CSS v4 + Radix UI primitives
State React hooks + TanStack React Query
Charts Recharts (dashboard analytics)
Voice Web Speech API (webkitSpeechRecognition)
Icons Lucide React

Backend / Data

Layer Technology
Database Supabase (PostgreSQL)
Auth Supabase Auth (email/password)
AI Google Gemini API (server-side proxy)
Excel SheetJS (xlsx-js-style) for read/write
Server TanStack Start server functions (functions.ts)
Offline localStorage queue + auto-retry on reconnect

Key Packages

  • @supabase/supabase-js — database client + auth
  • @tanstack/react-query — server state, caching, retry
  • tailwindcss v4 — utility-first CSS
  • recharts — analytics bar/area charts
  • xlsx-js-style — styled Excel generation with fonts, fills, borders
  • radix-ui — accessible UI primitives (dialog, select, tooltip, dropdown, etc.)
  • date-fns — date formatting
  • sonner — toast notifications
  • vaul — drawer component (mobile)
  • vitest + jsdom — unit/integration testing

Routes

Path Component Purpose
/ Wizard Main 6-step report builder
/dashboard DashboardPage Analytics from export history (Recharts)
/train TrainPage AI training — CRUD keyword→category mappings
/login LoginPage Email/password auth
/admin AdminPage Database statistics, user info

RCA Classification Engine

The classification pipeline runs in strict priority order:

1. FIBER check          → "FIBER / FIBER" (absolute override)
2. Active signal check  → "HUAWEI ACTIVE FAULT / BTS FAULT or MICROWAVE"
3. Partner lock         → Partner name determines the category family
4. Bucket pick          → Keyword rules within locked category
5. Learned mappings     → User-trained keyword overrides (Supabase-backed)
6. Fuzzy fallback       → Token scoring + Levenshtein ≤ 2
7. Gemini AI            → Server-side Google Gemini for anything still unmatched

Classification Partners

Partner Category Buckets
IHS / SWAP I H S PASSIVE FAULT GENERATOR, DC POWER, AMF PANEL, THEFT, PLANNED/PROJECT WORK, AGEING DG, ACCESS
ATC / HELIOS ATC PASSIVE FAULT GENERATOR, AMF PANEL, AGEING DG, PLANNED/PROJECT WORK, DC POWER, THEFT, ACCESS, FUEL OUTAGE
PAT PAT PASSIVE FAULT GENERATOR, AMF PANEL, AGEING DG, PLANNED/PROJECT WORK, DC POWER, THEFT, PASSIVE MAINTENANCE, FUEL OUTAGE
HUAWEI / ZTE / NOKIA / ERICSSON HUAWEI ACTIVE FAULT BTS FAULT, MICROWAVE, SPARES, PLANNED/PROJECT WORK
AIRTEL / IPT AIRTEL PASSIVE FAULT GENERATOR, PLANNED/PROJECT WORK
Others (ATL, EASTCASTLE, COLOPLUS, etc.) OTHER COLLO FAULT OTHER COLLO

Voice Control

The VoiceController component (Chrome/Edge only) uses webkitSpeechRecognition for hands-free operation:

  • Navigation — "go to step 3", "next", "back", "go to review"
  • State selection — "pick Anambra and Lagos", "remove Delta"
  • Threshold — "set availability to 95"
  • Filter — "show Anambra", "show site AB123", "show only unmatched"
  • Classify — "site AB123 is ATC passive fault"
  • Bulk classify — "classify all unmatched as ATC passive fault"
  • Read aloud — "read unmatched sites", "what's unmatched"
  • Summary — "how many sites", "my progress"
  • Database — "how many in supabase", "how many saved"

Data Flow

RNATracker .xlsb ──→ xlsbParser.ts ──→ rna.worker.ts (Web Worker)
                                          │
                              SiteRow[] with availability, state, partner
                                          │
                              Step3Preview (filter by network/state/threshold)
                                          │
WhatsApp text ──→ textParser.ts ──→ RcaEvent[] (single, cascade, bulk)
                     │                     │
               unparsed cascades      partnerClassify.ts
                     │                     │ (fiber→active→partner→bucket)
               geminiClassify.ts           │
               (Google Gemini AI)     learned mappings (Supabase)
                                          │
                                     fallback.ts (fuzzy Levenshtein)
                                          │
                                 ReviewRow[] with category + bucket
                                          │
                              exporter.ts ──→ styled .xlsx report

Offline Support

  • Failed Supabase writes (classifications, corrections) are queued in localStorage
  • Queue auto-retries when the browser detects connectivity (navigator.onLine + online/offline events)
  • UI shows offline badge with pending count
  • Draft state auto-saved to localStorage via useWizardDraft hook — no data loss on refresh

Database Schema (Supabase / PostgreSQL)

Table Purpose RLS
rca_learned_mappings User-trained keyword→category/bucket mappings User-scoped
rca_corrections User corrections (for audit trail) User-scoped
rca_export_history Past export data for dashboard analytics User-scoped

All tables use Row-Level Security — users only see their own data. Auth is email/password via Supabase Auth.


Analytics Dashboard

At /dashboard, pulls from rca_export_history with:

  • Filterable by date range (30/60/90d presets), network, state
  • Stat cards: total rows, unique sites, reports run, match rate
  • High-level split: Active / Passive / Others
  • Category breakdown bar chart (Recharts)
  • Top 8 recurring fault buckets
  • Trend area chart (sites per report, last 14)
  • FME performance table (sites handled, avg availability, unresolved)
  • Chronic sites table (appeared in 3+ reports)
  • CSV/Excel export

AI Training Page (/train)

  • View all learned keyword→category mappings with hit counts
  • Add single mapping manually (keyword + category + bucket selectors)
  • Bulk import from Excel/CSV/TSV files
  • Import patterns from past export history (requires 2+ occurrences)
  • Search, sort, paginate (50/page), inline edit, remove
  • Real-time sync to Supabase

Testing

npm test              # vitest run (21 tests across 3 files)
npm run test:watch    # watch mode
Test file What it covers
tests/storage.test.ts normaliseDescription (abbreviation expansion, phonetic typos), getLearnedMap, getFmeMap
tests/chronicDetection.test.ts detectChronicSites (threshold, empty, bad data)
tests/integration.test.ts Full end-to-end: parse WhatsApp text with cascades → classify by partner → detect contradictions → build preview rows → build workbook. Plus baseSiteId normalization and classification edge cases

Getting Started

Prerequisites

  • Node.js ≥ 20
  • npm ≥ 10
  • A Supabase project (free tier works)
  • A Google Gemini API key

Setup

# 1. Install dependencies
npm install

# 2. Configure environment
# Copy src/.env to .env and fill in:
#   SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, GEMINI_API_KEY

# 3. Run database migration
# Apply supabase-migration-rls.sql in your Supabase SQL editor

# 4. Start dev server
npm run dev
# Opens at http://localhost:5173

Build for Production

npm run build
npm run preview

Project Structure

src/
├── components/
│   ├── rca/             # RCA-specific components (Wizard, steps, VoiceController)
│   └── ui/              # Shared UI primitives (Radix-based: button, dialog, select, etc.)
├── routes/              # TanStack Router file-based routes
│   ├── __root.tsx       # Root layout (header, auth, theme toggle)
│   ├── index.tsx        # Wizard (main page)
│   ├── dashboard.tsx    # Analytics dashboard
│   ├── train.tsx        # AI training page
│   ├── login.tsx        # Auth page
│   └── admin.tsx        # Admin panel
├── lib/
│   ├── rca/             # Core business logic
│   │   ├── textParser.ts         # WhatsApp text → RcaEvent (cascade, bulk, single)
│   │   ├── partnerClassify.ts    # Partner-first classification engine
│   │   ├── geminiClassify.ts     # Google Gemini AI classification
│   │   ├── geminiProxy.functions.ts  # Server-side Gemini proxy
│   │   ├── fallback.ts           # Fuzzy token + Levenshtein fallback
│   │   ├── exporter.ts           # Styled Excel workbook builder
│   │   ├── xlsbParser.ts         # RNATracker .xlsb parser
│   │   ├── rna.worker.ts         # Web Worker for xlsb parsing
│   │   ├── storage.ts            # localStorage learned mappings + Supabase sync
│   │   ├── offlineQueue.ts       # Offline write queue + auto-retry
│   │   ├── chronicDetection.ts   # Chronic site detection (3+ appearances)
│   │   ├── whatsapp.ts           # WhatsApp summary builder
│   │   ├── whatsappPreprocess.ts # WhatsApp text pre-processing
│   │   ├── suggestions.ts        # Auto-suggestions engine
│   │   ├── auditTrail.ts         # User correction audit trail
│   │   ├── seeds.ts              # RCA_BUCKETS, highLevel mapping
│   │   ├── types.ts              # TypeScript interfaces
│   │   └── useWizardDraft.ts     # localStorage draft save/restore
│   ├── auth-context.tsx   # Supabase auth context provider
│   ├── config.server.ts   # Server-side config (env vars)
│   └── utils.ts           # cn() utility (clsx + tailwind-merge)
├── integrations/
│   └── supabase/           # Supabase client, auth middleware, types
├── hooks/                  # Custom hooks (use-mobile)
├── styles.css              # Tailwind CSS v4 + custom theme
├── router.tsx              # TanStack Router config
├── main.tsx                # Entry point
└── server.ts               # TanStack Start server entry

Key Design Decisions

Decision Rationale
Partner-first classification Airtel's SLA is partner-based; the same description "DG fail to start" maps to different buckets depending on whether IHS, ATC, or PAT manages the tower
Gemini via server proxy API key stays server-side; client calls geminiProxy server function, not Gemini directly
Local + Supabase storage Learned mappings sync in real-time but also cache locally for instant offline access
Web Worker for xlsb parsing Large .xlsb files (1000s of rows) don't block the UI thread
Voice control via webkitSpeechRecognition FMEs in the field need hands-free operation; Chrome-only due to browser API limitations
Cascade-aware text parser WhatsApp data frequently uses ROOT+N(SITE,SITE): desc format; the parser handles 4+ variants with balanced-paren support
Chronic site detection Sites appearing in 3+ reports get flagged automatically — key for SLA tracking

Questions an Employer Might Ask

What problem does this solve?

Manual RCA report creation for Airtel Nigeria's Huawei network was taking hours per report — parsing WhatsApp text, classifying each fault, formatting Excel. This app automates the entire workflow, reducing a 2-hour manual task to ~5 minutes with AI assistance.

What's the tech stack and why?

TanStack Start for SSR-ready React with file-based routing. Supabase for auth + database without managing servers. Tailwind CSS for rapid UI development. Google Gemini for AI fallback classification. SheetJS for Excel generation. Each choice prioritizes low operational overhead and fast iteration.

How does the AI classification work?

It's a cascading pipeline: fiber keywords override everything → active signals (BTS/microwave) override partner → partner name locks the category family → keyword rules pick the bucket → user-trained mappings from Supabase → fuzzy Levenshtein fallback → Gemini AI as last resort. This ensures the most common cases (90%+) are handled instantly without API calls.

How is data security handled?

Gemini API key lives server-side only — never sent to the client. Supabase RLS ensures users only see their own data. Auth is email/password with session management. No sensitive data is logged or exposed.

How is it tested?

21 tests across 3 files covering text parsing, cascade detection, partner classification, contradiction detection, site ID normalization, preview row building, workbook generation, and storage operations. Vitest with jsdom environment.

Can it work offline?

Yes. Failed Supabase writes queue to localStorage and auto-retry. Wizard drafts auto-save to localStorage. Learned mappings cache locally. Gemini AI is the only feature that requires connectivity.

How do users train the AI?

Via the /train page: add keyword→category mappings manually, import from Excel/CSV, or scan past export history for patterns. Mappings sync to Supabase in real-time and are checked first during classification.

What formats does it support?

Input: Huawei RNATracker .xlsb, WhatsApp pasted text, Excel/CSV/TSV for bulk training. Output: Styled .xlsx with per-network sheets, chronic sites sheet, summary statistics, color-coded rows, auto-filters.

Who uses this?

Airtel Nigeria Huawei network FMEs who need to file weekly/monthly SLA compliance reports. The app is tailored to their specific partner structure (IHS, ATC, PAT, Huawei, Airtel) and RCA category taxonomy.

About

a website that cuts down the work load for data analysts

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages