Add improved production UI

This commit is contained in:
Urtzi Alfaro
2025-09-23 12:49:35 +02:00
parent 8d54202e91
commit 4ae8e14e55
35 changed files with 6848 additions and 415 deletions

View File

@@ -8,6 +8,9 @@ import StatsGrid from '../../components/ui/Stats/StatsGrid';
import RealTimeAlerts from '../../components/domain/dashboard/RealTimeAlerts';
import ProcurementPlansToday from '../../components/domain/dashboard/ProcurementPlansToday';
import ProductionPlansToday from '../../components/domain/dashboard/ProductionPlansToday';
import ProductionCostMonitor from '../../components/domain/dashboard/ProductionCostMonitor';
import EquipmentStatusWidget from '../../components/domain/dashboard/EquipmentStatusWidget';
import AIInsightsWidget from '../../components/domain/dashboard/AIInsightsWidget';
import { useTenant } from '../../stores/tenant.store';
import {
AlertTriangle,
@@ -170,6 +173,15 @@ const DashboardPage: React.FC = () => {
onViewDetails={handleViewDetails}
onViewAllPlans={handleViewAllPlans}
/>
{/* 4. Production Cost Monitor */}
<ProductionCostMonitor />
{/* 5. Equipment Status Widget */}
<EquipmentStatusWidget />
{/* 6. AI Insights Widget */}
<AIInsightsWidget />
</div>
</div>
);

View File

@@ -3,6 +3,7 @@ import { Plus, ShoppingCart, Truck, Euro, Calendar, Clock, CheckCircle, AlertCir
import { Button, Input, Card, StatsGrid, StatusCard, getStatusColor, StatusModal } from '../../../../components/ui';
import { formatters } from '../../../../components/ui/Stats/StatsPresets';
import { PageHeader } from '../../../../components/layout';
import { CreatePurchaseOrderModal } from '../../../../components/domain/procurement/CreatePurchaseOrderModal';
import {
useProcurementDashboard,
useProcurementPlans,
@@ -25,6 +26,8 @@ const ProcurementPage: React.FC = () => {
const [showGeneratePlanModal, setShowGeneratePlanModal] = useState(false);
const [showRequirementDetailsModal, setShowRequirementDetailsModal] = useState(false);
const [selectedRequirement, setSelectedRequirement] = useState<any>(null);
const [showCreatePurchaseOrderModal, setShowCreatePurchaseOrderModal] = useState(false);
const [selectedRequirementsForPO, setSelectedRequirementsForPO] = useState<any[]>([]);
const [generatePlanForm, setGeneratePlanForm] = useState({
plan_date: new Date().toISOString().split('T')[0],
planning_horizon_days: 14,
@@ -255,11 +258,16 @@ const ProcurementPage: React.FC = () => {
description="Administra planes de compras, requerimientos y análisis de procurement"
actions={[
{
id: "generate",
label: "Generar Plan",
id: "create-po",
label: "Crear Orden de Compra",
variant: "primary" as const,
icon: Plus,
onClick: () => setShowGeneratePlanModal(true)
onClick: () => {
// Open the purchase order modal with empty requirements
// This allows manual creation of purchase orders without procurement plans
setSelectedRequirementsForPO([]);
setShowCreatePurchaseOrderModal(true);
}
},
{
id: "trigger",
@@ -561,7 +569,21 @@ const ProcurementPage: React.FC = () => {
<Loader className="w-8 h-8 animate-spin text-[var(--color-primary)]" />
</div>
) : planRequirements && planRequirements.length > 0 ? (
<div className="grid gap-4">
<div className="space-y-4">
<div className="flex justify-end mb-4">
<Button
variant="primary"
onClick={() => {
// Set all requirements for PO creation
setSelectedRequirementsForPO(planRequirements);
setShowCreatePurchaseOrderModal(true);
}}
>
<Plus className="w-4 h-4 mr-2" />
Crear Orden de Compra para Todos
</Button>
</div>
{planRequirements.map((requirement) => (
<StatusCard
key={requirement.id}
@@ -619,7 +641,9 @@ const ProcurementPage: React.FC = () => {
variant: 'outline' as const,
priority: 'secondary' as const,
onClick: () => {
// TODO: Create purchase order for requirement
// Set the single requirement for PO creation
setSelectedRequirementsForPO([requirement]);
setShowCreatePurchaseOrderModal(true);
}
}
]),
@@ -954,6 +978,23 @@ const ProcurementPage: React.FC = () => {
</div>
)}
{/* Create Purchase Order Modal */}
{showCreatePurchaseOrderModal && (
<CreatePurchaseOrderModal
isOpen={showCreatePurchaseOrderModal}
onClose={() => {
setShowCreatePurchaseOrderModal(false);
setSelectedRequirementsForPO([]);
}}
requirements={selectedRequirementsForPO}
onSuccess={() => {
// Refresh the plan requirements data
setSelectedRequirementsForPO([]);
// You might want to invalidate queries here to refresh data
}}
/>
)}
{/* Requirement Details Modal */}
{showRequirementDetailsModal && selectedRequirement && (
<div className="fixed top-[var(--header-height)] left-0 right-0 bottom-0 bg-black bg-opacity-50 flex items-center justify-center z-40">

View File

@@ -5,7 +5,7 @@ import { statusColors } from '../../../../styles/colors';
import { formatters } from '../../../../components/ui/Stats/StatsPresets';
import { LoadingSpinner } from '../../../../components/shared';
import { PageHeader } from '../../../../components/layout';
import { ProductionSchedule, BatchTracker, QualityControl, CreateProductionBatchModal } from '../../../../components/domain/production';
import { ProductionSchedule, BatchTracker, QualityControl, QualityDashboard, QualityInspection, EquipmentManager, CreateProductionBatchModal } from '../../../../components/domain/production';
import { useCurrentTenant } from '../../../../stores/tenant.store';
import {
useProductionDashboard,
@@ -298,6 +298,36 @@ const ProductionPage: React.FC = () => {
>
Control de Calidad
</button>
<button
onClick={() => setActiveTab('quality-dashboard')}
className={`py-2 px-1 border-b-2 font-medium text-sm ${
activeTab === 'quality-dashboard'
? 'border-orange-500 text-[var(--color-primary)]'
: 'border-transparent text-[var(--text-tertiary)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'
}`}
>
Dashboard Calidad
</button>
<button
onClick={() => setActiveTab('quality-inspection')}
className={`py-2 px-1 border-b-2 font-medium text-sm ${
activeTab === 'quality-inspection'
? 'border-orange-500 text-[var(--color-primary)]'
: 'border-transparent text-[var(--text-tertiary)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'
}`}
>
Inspección
</button>
<button
onClick={() => setActiveTab('equipment')}
className={`py-2 px-1 border-b-2 font-medium text-sm ${
activeTab === 'equipment'
? 'border-orange-500 text-[var(--color-primary)]'
: 'border-transparent text-[var(--text-tertiary)] hover:text-[var(--text-secondary)] hover:border-[var(--border-secondary)]'
}`}
>
Equipos
</button>
</nav>
</div>
@@ -400,6 +430,18 @@ const ProductionPage: React.FC = () => {
<QualityControl />
)}
{activeTab === 'quality-dashboard' && (
<QualityDashboard />
)}
{activeTab === 'quality-inspection' && (
<QualityInspection />
)}
{activeTab === 'equipment' && (
<EquipmentManager />
)}
{/* Production Batch Modal */}
{showBatchModal && selectedBatch && (
<StatusModal