Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions PR-SAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# SAP S/4HANA ERP — Procurement & Approval SPA

> Closes #1 · Bounty: $1,000

## Overview

A polished SAP S/4HANA–style enterprise resource planning single-page application focused on **procurement management** and **approval workflows**. Built with the exact same stack as existing SPAs in this repo (Vite + React 19 + TypeScript strict + Tailwind v4 + dojo-hooks), fully offline with rich seed data.

## Screenshots

### Dashboard — KPI Widgets & Pending Items
Six hero KPI cards (revenue, open POs, pending approvals, budget utilization, total spend, on-time delivery) powered by `useDojoState`. Panels showing POs awaiting approval and upcoming tasks with direct navigation.

### Procurement — List, Filter & Detail Views
Full purchase order table with status/priority filters and global search. Detail view with line-item table, vendor info card, approve/reject actions, and threaded comments.

### Task Inbox — Approval Queue
Card-based task grid with status chips, progress bars, priority indicators, and cycle-status toggles. Supports filtering and empty state. Summary counts at top.

### Audit Trail — Activity Timeline
Chronological grouped timeline recording every navigation, approval, rejection, comment, and status change. Color-coded by category (procurement, approval, navigation, system). Stored in `dojo.state.auditLog` for RL verification.

## Views Implemented

| # | View | Description |
|---|------|-------------|
| 1 | **Dashboard** | 6 KPI hero widgets, pending POs panel, upcoming tasks panel |
| 2 | **Procurement List** | Filterable PO table (status, priority), global search integration |
| 3 | **PO Detail** | Line items, vendor card, approve/reject buttons, comment thread |
| 4 | **Task Inbox** | 14 approval tasks as cards, status toggle, progress bars, empty state |
| 5 | **Audit Trail** | Grouped timeline of all session actions for RL verification |

## Seed Data

- **12 purchase orders** across 7 statuses (Draft, Pending Approval, Approved, Rejected, In Delivery, Received, Cancelled)
- **10 vendors** with ratings, categories, and contact details (Siemens, Bosch, BASF, Caterpillar, 3M, ABB, Schneider, Honeywell, Mitsubishi, Emerson)
- **14 approval tasks** of 5 types (PO, Invoice, Budget Transfer, Material Request, Vendor Onboarding)
- **6 KPIs** with trend indicators
- **12 audit log entries** pre-seeded, with live additions on every user action

## Technical Stack

| Requirement | Implementation |
|-------------|---------------|
| React 19 + TypeScript strict | ✅ `tsc -b` passes with 0 errors |
| `@chakra-dev/dojo-hooks` | ✅ Single `useDojoState` in AppProvider — no bespoke stores |
| Tailwind CSS v4 via `@tailwindcss/vite` | ✅ No postcss.config.js |
| `vite-plugin-singlefile` | ✅ `dist/index.html` = 282 KB (82 KB gzipped) |
| `lucide-react` icons | ✅ Used throughout all views |
| No auth flows | ✅ Boots directly into dashboard |
| Responsive | ✅ Tested at 1280px and 1440px |
| Fully offline | ✅ All seed data embedded |

## SAP Fiori Theme

- **Sidebar**: SAP Shell dark blue (`#354a5f`) with gold hex logo accent
- **Content**: Clean white cards on `#f7f7f7` background
- **Status colors**: SAP semantic palette (positive green, negative red, critical orange, informative blue)
- **Accent**: SAP gold (`#f58b00`) for highlights and branding
- **Typography**: Clean sans-serif matching SAP Fiori design language

## State Architecture

All state lives in a single `useDojoState<AppState>()` call:

```typescript
interface AppState {
currentView: ViewId;
selectedPOId: string | null;
searchQuery: string;
purchaseOrders: PurchaseOrder[];
tasks: ApprovalTask[];
vendors: Vendor[];
kpis: KPIData;
auditLog: AuditEntry[];
sidebarCollapsed: boolean;
poStatusFilter: POStatus | "All";
poPriorityFilter: Priority | "All";
taskStatusFilter: TaskStatus | "All";
}
```

Every mutation (navigation, approval, rejection, comment, task toggle) writes to `dojo.state` and appends an audit entry — making the entire session fully traceable for RL verification via `window.dojo.state.auditLog`.

## File Structure

```
sap/app/
├── index.html
├── package.json
├── vite.config.ts
├── tsconfig.json / tsconfig.app.json / tsconfig.node.json
├── dist/index.html ← single-file build output
└── src/
├── main.tsx
├── App.tsx
├── index.css ← Tailwind v4 + SAP theme tokens
├── types/index.ts ← Full TypeScript types
├── data/seed.ts ← Rich seed data (12 POs, 10 vendors, 14 tasks)
├── store/AppProvider.tsx ← useDojoState provider + all actions
└── components/
├── Sidebar.tsx
├── TopBar.tsx
├── Dashboard.tsx
├── PurchaseOrderList.tsx
├── PurchaseOrderDetail.tsx
├── TaskInbox.tsx
└── AuditTrail.tsx
```

## Build Verification

```bash
cd sap/app
pnpm install
pnpm run build # runs tsc -b && vite build
# ✅ 0 TypeScript errors
# ✅ dist/index.html produced (single file, 282 KB)
```
24 changes: 24 additions & 0 deletions sap/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
28 changes: 28 additions & 0 deletions sap/app/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
},
}
);
17 changes: 17 additions & 0 deletions sap/app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link
rel="icon"
type="image/svg+xml"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='12' fill='%23354a5f'/%3E%3Ctext x='50' y='62' font-family='Arial,sans-serif' font-size='36' font-weight='bold' fill='white' text-anchor='middle'%3ESAP%3C/text%3E%3C/svg%3E"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SAP S/4HANA — Enterprise Resource Planning</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
34 changes: 34 additions & 0 deletions sap/app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "sap-erp",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.13",
"@chakra-dev/dojo-hooks": "^1.0.0",
"lucide-react": "^0.468.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"tailwindcss": "^4.1.13"
},
"devDependencies": {
"@eslint/js": "^9.35.0",
"@types/react": "^19.1.13",
"@types/react-dom": "^19.1.9",
"@vitejs/plugin-react": "^5.0.2",
"eslint": "^9.35.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.4.0",
"typescript": "~5.8.3",
"typescript-eslint": "^8.43.0",
"vite": "^7.1.6",
"vite-plugin-singlefile": "^2.3.0"
}
}
Loading