Files
clinicpro/assets/admin/components/inventory/InventoryStatCards.tsx
T
hamedandClaude Opus 4.8 519bc8d7f6 feat: port inventory (انبارداری) page from tauri to admin dashboard
Add a per-tenant (doctor/clinic) Inventory domain and admin page, ported
from clinic-pro-tauri /inventory (which was static/mock) into a real feature.

Backend (src/Inventory/):
- Entities InventoryItem, InventoryPackage, InventoryPackageItem, scoped via
  entity_type/entity_id like TenantTag. Item status is derived, package total
  and availability derived at read time.
- InventoryService (stats, package assembly, availability), thin
  InventoryController with CRUD for items and packages + categories endpoint.
- Migration + docs/api/inventory.md + functional tests (10 tests, 42 assertions).

Frontend (assets/admin/):
- InventoryPage with two tabs (کالاهای مصرفی / پکیج), stat cards, items table
  (desktop + mobile cards), packages accordion, add/edit item and package
  modals, search + category filter — pixel-matched to the tauri source.
- useInventory hook (TanStack Query), route + sidebar link for doctor/clinic.
- Vitest coverage (real data, empty state, modal, packages tab).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 13:48:29 +03:30

27 lines
1.1 KiB
TypeScript

import React from 'react';
import { ArchiveBoxIcon } from '@heroicons/react/24/outline';
import StatCard from '../ui/StatCard';
import { formatNumber } from '../../lib/utils';
import type { InventoryStats } from '../../hooks/useInventory';
const ICON = <ArchiveBoxIcon style={{ width: 20, height: 20 }} />;
/** Four headline counters — order/colors mirror the tauri InventoryCards. */
export default function InventoryStatCards({ stats }: { stats: InventoryStats }) {
return (
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',
gap: 20,
padding: '20px 0',
}}
>
<StatCard tone="violet" icon={ICON} label="تعداد کل کالاها" value={formatNumber(stats.total)} />
<StatCard tone="amber" icon={ICON} label="کالاهای کم موجود" value={formatNumber(stats.low)} />
<StatCard tone="green" icon={ICON} label="کالاهای موجود" value={formatNumber(stats.inStock)} />
<StatCard tone="pink" icon={ICON} label="کالاهای اتمام یافته" value={formatNumber(stats.outOfStock)} />
</div>
);
}