Improve the inventory page 3
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user