mohd-faraz

_blogs

// blogs / 20260617.md

Dev Log: June 17 Wrap-up

2026-06-17
#Angular#Refactoring#CRM#TypeScript

Overview

Today was one of those days where a few simple bug fixes quickly spiraled into a much-needed refactor. I started out just fixing some KPI labels, but looking at the redundant code in my components was hitting my nerves, so I spent a good chunk of time generalizing how we fetch metrics.

What I Worked On

Fixing the KPI Logic

First things first, I had to address some mismatches in our customer metrics. We were labeling customers as Won when the business logic actually considers them Active, and On Hold was better described as At Risk. It’s a small change in the filter strings, but it ensures the dashboard actually reflects reality for the partners using it. I also cleaned up some date formatting in the UI—standardizing the display so it doesn't look like a raw database dump.

Killing the Boilerplate

While working on the Deals module, I realized I was writing the same subscribe block over and over again for every single KPI (Total Deals, Pipeline Value, Won Count, etc.). It was making the component files way longer than they needed to be.

I decided to move that logic into an ExtendedBaseService. Now, instead of five different functions for five different metrics, I can just call a single helper. It feels much cleaner to just pass a signal and a payload and let the service handle the rest.

// A sanitized look at the helper I added to the base service
fetchKPIMetric(
  payload: any, 
  resource: string, 
  queryType: 'GET_COUNT' | 'GET_SUM', 
  resultKey: string, 
  targetSignal: any
) {
  this.getGenericData(payload, resource, queryType).subscribe({
    next: (res: any) => {
      const val = res?.data?.[0]?.metrics?.[resultKey] ?? 0;
      targetSignal.set(Number(val));
    },
    error: () => targetSignal.set(0)
  });
}

Smarter Routing

I also spent some time making the Deals component more dynamic. Instead of creating separate components for "Won Deals" or "Pending Deals," I started using the route configuration to pass metadata. Now, the component checks the route data object to see if it should be pre-filtered for a specific status. It saves us from duplicating HTML and logic across multiple files just to change a single filter parameter.

Wrapping Up

Overall, a productive day. The codebase feels a little lighter now that the KPI logic isn't scattered everywhere. Tomorrow, I’ll probably look into standardizing the rest of the CRM modules with this new service helper. It’s a bit of grunt work, but the maintenance win is worth it.