Shoham Fellner

Selected Work
Case Study

Procurement Planning System

IDF Teleprocessing Corps · via Inford-Team · 2024-2026

Built from scratch to replace the legacy platform behind the Ground Forces' annual budget.

RoleLead Frontend Developer & UX/UI
Stack

[React] [TypeScript] [TanStack Query] [SAP Gateway]

Design Files
Requirement planning - catalogue view
Reconstruction
Procurement Planning System interface

Interface reconstructed with generic labels and sample data. Not the production system.

01

The Stakes

Roughly twenty people use this system. What they enter becomes the annual procurement plan for the IDF Ground Forces - what gets bought, what gets repaired, what sits in reserve.

The user count is not the measure here. The budget behind each line is. And it replaced the legacy platform outright rather than a module at a time, which meant the new system had to carry the whole planning process on its own from the day it went in.

02

My Role

I led frontend development inside an Agile team and owned the UX/UI process end to end - research, Figma, and the implementation that followed it.

The backend was a separate SAP Gateway team. The data contracts between us were designed together rather than handed down, which is the reason several of the decisions below were possible at all.

03

The Problem

Procurement planning is not one screen. It is dozens of interlocking views over the same catalogue: requirement tables tens of thousands of rows deep, dashboards pulling from several unrelated sources, and forms whose fields depend on what kind of item you happen to be planning for.

Any one of those, built the obvious way, stalls the entire screen. The work was deciding where to put the boundaries so that no single slow thing could take the rest of the page down with it.

04

Decisions

Every widget owns its own data

Constraint
The dashboard reads from several unrelated sources, each with its own shape and its own latency.
Decision
Each widget fetches, caches and parses its own data through TanStack Query, with its own loading and error state.
Trade-off
More query keys to keep coherent, and a genuine “refresh everything” has to be built deliberately rather than coming for free. In exchange, one failing source degrades one widget instead of the page.

Virtualization on the client, paging on the server

Constraint
Requirement tables run to tens of thousands of rows, and planners scroll them rather than query them.
Decision
List virtualization so the DOM only ever holds what is on screen, with pagination handled server-side.
Trade-off
Browser find stops working across the full set, and sorting can no longer be done in the client. Both had to move to the server, which is work you sign up for the moment you virtualize.

Forms generated from a schema, not hand-built

Constraint
Which fields a planner sees depends on the material type, and the rules behind that change over time.
Decision
Dynamic, schema-driven forms built on React Hook Form, so a category is data rather than a new screen.
Trade-off
A level of indirection between the bug you see and the code that caused it. Worth paying once; not worth paying if the schema had been static.

Shaping the contract instead of the response

Constraint
What SAP Gateway returns naturally and what the interface needs are not the same shape.
Decision
Design the schema and the data contract together with the backend team, rather than reshaping every response in the client.
Trade-off
Slower to agree on, and it needs a backend team willing to have the conversation. It kept the same data from living twice in two different shapes.
05

Evidence

The system itself is not public. What follows is the design work behind it, rebuilt with generic labels and sample data.

Each widget loads and fails on its own.
Tens of thousands of rows, constant scroll cost.
Tens of thousands of rows, constant scroll cost.
Fields resolve from the material type.
Fields resolve from the material type.
Query boundaries between UI and SAP Gateway.
Query boundaries between UI and SAP Gateway.
06

Outcome

Delivered as the replacement for the legacy platform, taken from research through to production inside an Agile cycle.

The MVP was deployed to production, with planners executing the annual procurement cycle in parallel with the legacy system to validate data integrity and workflows under real-world conditions.

07

What I'd Change

I would introduce a Backend-for-Frontend (BFF) layer to offload heavy data parsing. We handled complex calculations on the client due to infrastructure constraints, which introduced unavoidable overhead to initial load times.

Additionally, rather than stretching a rigid SAP Gateway data structure to serve multiple dashboard components, I would enforce purpose-built data contracts. Reusing a single structure across too many contexts added unnecessary complexity to the client-side state.