Improve the inventory page 3

This commit is contained in:
Urtzi Alfaro
2025-09-18 08:06:32 +02:00
parent dcb3ce441b
commit ae77a0e1c5
31 changed files with 2376 additions and 1774 deletions

View File

@@ -1,20 +1,20 @@
import React, { useState, useMemo } from 'react';
import { Plus, AlertTriangle, Package, CheckCircle, Eye, Clock, Euro, ArrowRight, Minus, Edit, Trash2 } from 'lucide-react';
import { Plus, AlertTriangle, Package, CheckCircle, Eye, Clock, Euro, ArrowRight, Minus, Edit, Trash2, Archive, TrendingUp, History } from 'lucide-react';
import { Button, Input, Card, StatsGrid, StatusCard, getStatusColor } from '../../../../components/ui';
import { LoadingSpinner } from '../../../../components/shared';
import { formatters } from '../../../../components/ui/Stats/StatsPresets';
import { PageHeader } from '../../../../components/layout';
import {
CreateItemModal,
QuickViewModal,
AddStockModal,
UseStockModal,
HistoryModal,
StockLotsModal,
EditItemModal,
CreateIngredientModal,
ShowInfoModal,
StockHistoryModal,
BatchModal,
DeleteIngredientModal
} from '../../../../components/domain/inventory';
import { useIngredients, useStockAnalytics, useStockMovements, useStockByIngredient, useCreateIngredient, useSoftDeleteIngredient, useHardDeleteIngredient } from '../../../../api/hooks/inventory';
// Import AddStockModal separately since we need it for adding batches
import AddStockModal from '../../../../components/domain/inventory/AddStockModal';
import { useIngredients, useStockAnalytics, useStockMovements, useStockByIngredient, useCreateIngredient, useSoftDeleteIngredient, useHardDeleteIngredient, useAddStock, useConsumeStock, useUpdateIngredient, useTransformationsByIngredient } from '../../../../api/hooks/inventory';
import { useCurrentTenant } from '../../../../stores/tenant.store';
import { IngredientResponse, StockCreate, StockMovementCreate, IngredientCreate } from '../../../../api/types/inventory';
@@ -23,14 +23,12 @@ const InventoryPage: React.FC = () => {
const [selectedItem, setSelectedItem] = useState<IngredientResponse | null>(null);
// Modal states for focused actions
const [showCreateItem, setShowCreateItem] = useState(false);
const [showQuickView, setShowQuickView] = useState(false);
const [showAddStock, setShowAddStock] = useState(false);
const [showUseStock, setShowUseStock] = useState(false);
const [showHistory, setShowHistory] = useState(false);
const [showStockLots, setShowStockLots] = useState(false);
const [showEdit, setShowEdit] = useState(false);
const [showCreateIngredient, setShowCreateIngredient] = useState(false);
const [showInfo, setShowInfo] = useState(false);
const [showStockHistory, setShowStockHistory] = useState(false);
const [showBatches, setShowBatches] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [showAddBatch, setShowAddBatch] = useState(false);
const currentTenant = useCurrentTenant();
const tenantId = currentTenant?.id || '';
@@ -39,6 +37,9 @@ const InventoryPage: React.FC = () => {
const createIngredientMutation = useCreateIngredient();
const softDeleteMutation = useSoftDeleteIngredient();
const hardDeleteMutation = useHardDeleteIngredient();
const addStockMutation = useAddStock();
const consumeStockMutation = useConsumeStock();
const updateIngredientMutation = useUpdateIngredient();
// API Data
const {
@@ -69,10 +70,10 @@ const InventoryPage: React.FC = () => {
selectedItem?.id,
50,
0,
{ enabled: !!selectedItem?.id && showHistory }
{ enabled: !!selectedItem?.id && showStockHistory }
);
// Stock lots for stock lots modal
// Stock lots for stock lots modal and history modal
const {
data: stockLotsData,
isLoading: stockLotsLoading,
@@ -81,17 +82,31 @@ const InventoryPage: React.FC = () => {
tenantId,
selectedItem?.id || '',
false, // includeUnavailable
{ enabled: !!selectedItem?.id && showStockLots }
{ enabled: !!selectedItem?.id && showBatches }
);
// Debug stock lots data
console.log('Stock lots hook state:', {
// Transformations for history modal (not currently used in new design)
const {
data: transformationsData,
isLoading: transformationsLoading
} = useTransformationsByIngredient(
tenantId,
selectedItem?.id || '',
50, // limit
{ enabled: false } // Disabled for now since transformations not shown in new modals
);
// Debug data
console.log('Inventory data debug:', {
selectedItem: selectedItem?.id,
showStockLots,
showBatches,
showStockHistory,
stockLotsData,
stockLotsLoading,
stockLotsError,
enabled: !!selectedItem?.id && showStockLots
transformationsData,
transformationsLoading,
enabled: !!selectedItem?.id && showBatches
});
@@ -267,41 +282,22 @@ const InventoryPage: React.FC = () => {
};
// Focused action handlers
const handleQuickView = (ingredient: IngredientResponse) => {
const handleShowInfo = (ingredient: IngredientResponse) => {
setSelectedItem(ingredient);
setShowQuickView(true);
setShowInfo(true);
};
const handleAddStock = (ingredient: IngredientResponse) => {
const handleShowStockHistory = (ingredient: IngredientResponse) => {
setSelectedItem(ingredient);
setShowAddStock(true);
setShowStockHistory(true);
};
const handleUseStock = (ingredient: IngredientResponse) => {
const handleShowBatches = (ingredient: IngredientResponse) => {
setSelectedItem(ingredient);
setShowUseStock(true);
setShowBatches(true);
};
const handleHistory = (ingredient: IngredientResponse) => {
setSelectedItem(ingredient);
setShowHistory(true);
};
const handleStockLots = (ingredient: IngredientResponse) => {
console.log('🔍 Opening stock lots for ingredient:', {
id: ingredient.id,
name: ingredient.name,
current_stock: ingredient.current_stock,
category: ingredient.category
});
setSelectedItem(ingredient);
setShowStockLots(true);
};
const handleEdit = (ingredient: IngredientResponse) => {
setSelectedItem(ingredient);
setShowEdit(true);
};
// This function is now replaced by handleShowBatches
const handleDelete = (ingredient: IngredientResponse) => {
setSelectedItem(ingredient);
@@ -310,7 +306,7 @@ const InventoryPage: React.FC = () => {
// Handle new item creation
const handleNewItem = () => {
setShowCreateItem(true);
setShowCreateIngredient(true);
};
// Handle creating a new ingredient
@@ -329,19 +325,32 @@ const InventoryPage: React.FC = () => {
// Modal action handlers
const handleAddStockSubmit = async (stockData: StockCreate) => {
console.log('Add stock:', stockData);
// TODO: Implement API call
if (!tenantId) {
throw new Error('No tenant ID available');
}
return addStockMutation.mutateAsync({
tenantId,
stockData
});
};
const handleUseStockSubmit = async (movementData: StockMovementCreate) => {
console.log('Use stock:', movementData);
// TODO: Implement API call
if (!tenantId) {
throw new Error('No tenant ID available');
}
return consumeStockMutation.mutateAsync({
tenantId,
consumptionData: {
ingredient_id: movementData.ingredient_id,
quantity: Number(movementData.quantity),
reference_number: movementData.reference_number,
notes: movementData.notes
}
});
};
const handleUpdateIngredient = async (id: string, updateData: any) => {
console.log('Update ingredient:', id, updateData);
// TODO: Implement API call
};
// Delete handlers using mutation hooks
const handleSoftDelete = async (ingredientId: string) => {
@@ -557,49 +566,29 @@ const InventoryPage: React.FC = () => {
color: statusConfig.color
} : undefined}
actions={[
// Primary action - Most common user need
// Primary action - View item details
{
label: currentStock === 0 ? 'Agregar Stock' : 'Ver Detalles',
icon: currentStock === 0 ? Plus : Eye,
variant: currentStock === 0 ? 'primary' : 'outline',
label: 'Ver Detalles',
icon: Eye,
variant: 'primary',
priority: 'primary',
onClick: () => currentStock === 0 ? handleAddStock(ingredient) : handleQuickView(ingredient)
},
// Secondary primary - Quick access to other main action
{
label: currentStock === 0 ? 'Ver Info' : 'Agregar',
icon: currentStock === 0 ? Eye : Plus,
variant: 'outline',
priority: 'primary',
onClick: () => currentStock === 0 ? handleQuickView(ingredient) : handleAddStock(ingredient)
},
// Secondary actions - Most used operations
{
label: 'Lotes',
icon: Package,
priority: 'secondary',
onClick: () => handleStockLots(ingredient)
},
{
label: 'Usar',
icon: Minus,
priority: 'secondary',
onClick: () => handleUseStock(ingredient)
onClick: () => handleShowInfo(ingredient)
},
// Stock history action - Icon button
{
label: 'Historial',
icon: Clock,
icon: History,
priority: 'secondary',
onClick: () => handleHistory(ingredient)
onClick: () => handleShowStockHistory(ingredient)
},
// Least common action
// Batch management action
{
label: 'Editar',
icon: Edit,
label: 'Ver Lotes',
icon: Package,
priority: 'secondary',
onClick: () => handleEdit(ingredient)
onClick: () => handleShowBatches(ingredient)
},
// Destructive action - separated for safety
// Destructive action
{
label: 'Eliminar',
icon: Trash2,
@@ -637,48 +626,39 @@ const InventoryPage: React.FC = () => {
{/* Focused Action Modals */}
{/* Create Item Modal - doesn't need selectedItem */}
<CreateItemModal
isOpen={showCreateItem}
onClose={() => setShowCreateItem(false)}
{/* Create Ingredient Modal - doesn't need selectedItem */}
<CreateIngredientModal
isOpen={showCreateIngredient}
onClose={() => setShowCreateIngredient(false)}
onCreateIngredient={handleCreateIngredient}
/>
{selectedItem && (
<>
<QuickViewModal
isOpen={showQuickView}
<ShowInfoModal
isOpen={showInfo}
onClose={() => {
setShowQuickView(false);
setShowInfo(false);
setSelectedItem(null);
}}
ingredient={selectedItem}
/>
onSave={async (updatedData) => {
if (!tenantId || !selectedItem) {
throw new Error('Missing tenant ID or selected item');
}
<AddStockModal
isOpen={showAddStock}
onClose={() => {
setShowAddStock(false);
setSelectedItem(null);
return updateIngredientMutation.mutateAsync({
tenantId,
ingredientId: selectedItem.id,
updateData: updatedData
});
}}
ingredient={selectedItem}
onAddStock={handleAddStockSubmit}
/>
<UseStockModal
isOpen={showUseStock}
<StockHistoryModal
isOpen={showStockHistory}
onClose={() => {
setShowUseStock(false);
setSelectedItem(null);
}}
ingredient={selectedItem}
onUseStock={handleUseStockSubmit}
/>
<HistoryModal
isOpen={showHistory}
onClose={() => {
setShowHistory(false);
setShowStockHistory(false);
setSelectedItem(null);
}}
ingredient={selectedItem}
@@ -686,25 +666,26 @@ const InventoryPage: React.FC = () => {
loading={movementsLoading}
/>
<StockLotsModal
isOpen={showStockLots}
<BatchModal
isOpen={showBatches}
onClose={() => {
setShowStockLots(false);
setShowBatches(false);
setSelectedItem(null);
}}
ingredient={selectedItem}
stockLots={stockLotsData || []}
batches={stockLotsData || []}
loading={stockLotsLoading}
/>
<EditItemModal
isOpen={showEdit}
onClose={() => {
setShowEdit(false);
setSelectedItem(null);
onAddBatch={() => {
setShowAddBatch(true);
}}
onEditBatch={async (batchId, updateData) => {
// TODO: Implement edit batch functionality
console.log('Edit batch:', batchId, updateData);
}}
onMarkAsWaste={async (batchId) => {
// TODO: Implement mark as waste functionality
console.log('Mark as waste:', batchId);
}}
ingredient={selectedItem}
onUpdateIngredient={handleUpdateIngredient}
/>
<DeleteIngredientModal
@@ -718,6 +699,15 @@ const InventoryPage: React.FC = () => {
onHardDelete={handleHardDelete}
isLoading={softDeleteMutation.isPending || hardDeleteMutation.isPending}
/>
<AddStockModal
isOpen={showAddBatch}
onClose={() => {
setShowAddBatch(false);
}}
ingredient={selectedItem}
onAddStock={handleAddStockSubmit}
/>
</>
)}
</div>