fix(expedicao): suporte a modo claro e escuro no modal PecasRomaneioExpandido
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
import { Edit2, Trash2, X } from 'lucide-react';
|
import { Edit2, Trash2, Check, X, Package } from 'lucide-react';
|
||||||
import { supabase } from '@/integrations/supabase/client';
|
import { supabase } from '@/integrations/supabase/client';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { RomaneioExpedicao } from '@/hooks/useRomaneios';
|
import { RomaneioExpedicao } from '@/hooks/useRomaneios';
|
||||||
@@ -20,6 +21,7 @@ interface ItemRomaneioPeca {
|
|||||||
id: string;
|
id: string;
|
||||||
peca_id: string;
|
peca_id: string;
|
||||||
quantidade_expedida: number;
|
quantidade_expedida: number;
|
||||||
|
quantidade_max_peca?: number;
|
||||||
peso_unitario: number;
|
peso_unitario: number;
|
||||||
peso_total: number;
|
peso_total: number;
|
||||||
comprimento?: number | null;
|
comprimento?: number | null;
|
||||||
@@ -39,13 +41,16 @@ export const PecasRomaneioExpandido: React.FC<PecasRomaneioExpandidoProps> = ({
|
|||||||
|
|
||||||
const [itensPeca, setItensPeca] = useState<ItemRomaneioPeca[]>([]);
|
const [itensPeca, setItensPeca] = useState<ItemRomaneioPeca[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [editingItemId, setEditingItemId] = useState<string | null>(null);
|
||||||
|
const [editQuantidade, setEditQuantidade] = useState<string>('');
|
||||||
|
const [savingEdit, setSavingEdit] = useState(false);
|
||||||
|
|
||||||
const carregarItensPecas = async () => {
|
const carregarItensPecas = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from('itens_romaneio_pecas')
|
.from('itens_romaneio_pecas')
|
||||||
.select('*, pecas(comprimento)')
|
.select('*, pecas(comprimento, prioridade, quantidade)')
|
||||||
.eq('romaneio_id', romaneio.id)
|
.eq('romaneio_id', romaneio.id)
|
||||||
.order('marca');
|
.order('marca');
|
||||||
|
|
||||||
@@ -56,13 +61,14 @@ export const PecasRomaneioExpandido: React.FC<PecasRomaneioExpandidoProps> = ({
|
|||||||
id: item.id,
|
id: item.id,
|
||||||
peca_id: item.peca_id,
|
peca_id: item.peca_id,
|
||||||
quantidade_expedida: item.quantidade_expedida,
|
quantidade_expedida: item.quantidade_expedida,
|
||||||
|
quantidade_max_peca: item.pecas?.quantidade || undefined,
|
||||||
peso_unitario: item.peso_unitario,
|
peso_unitario: item.peso_unitario,
|
||||||
peso_total: item.peso_total,
|
peso_total: item.peso_total,
|
||||||
comprimento: item.pecas?.comprimento || item.comprimento || null,
|
comprimento: item.pecas?.comprimento || item.comprimento || null,
|
||||||
marca: item.marca,
|
marca: item.marca,
|
||||||
descricao: item.descricao || '',
|
descricao: item.descricao || '',
|
||||||
fase: item.fase || '',
|
fase: item.fase || '',
|
||||||
prioridade: 'P4'
|
prioridade: item.pecas?.prioridade || 'P4'
|
||||||
}));
|
}));
|
||||||
setItensPeca(itensFormatados);
|
setItensPeca(itensFormatados);
|
||||||
}
|
}
|
||||||
@@ -76,8 +82,10 @@ export const PecasRomaneioExpandido: React.FC<PecasRomaneioExpandidoProps> = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
|
setEditingItemId(null);
|
||||||
carregarItensPecas();
|
carregarItensPecas();
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [isOpen, romaneio.id]);
|
}, [isOpen, romaneio.id]);
|
||||||
|
|
||||||
const handleRemoverItem = async (itemId: string) => {
|
const handleRemoverItem = async (itemId: string) => {
|
||||||
@@ -99,16 +107,59 @@ export const PecasRomaneioExpandido: React.FC<PecasRomaneioExpandidoProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEditarItem = (item: ItemRomaneioPeca) => {
|
const handleEditarItem = (item: ItemRomaneioPeca) => {
|
||||||
// Funcionalidade de edição pode ser implementada aqui
|
setEditingItemId(item.id);
|
||||||
toast.info('Funcionalidade de edição em desenvolvimento');
|
setEditQuantidade(String(item.quantidade_expedida));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancelarEdicao = () => {
|
||||||
|
setEditingItemId(null);
|
||||||
|
setEditQuantidade('');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSalvarEdicao = async (item: ItemRomaneioPeca) => {
|
||||||
|
const novaQtd = parseInt(editQuantidade, 10);
|
||||||
|
if (isNaN(novaQtd) || novaQtd <= 0) {
|
||||||
|
toast.error('Informe uma quantidade válida maior que zero');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.quantidade_max_peca && novaQtd > item.quantidade_max_peca) {
|
||||||
|
toast.error(`A quantidade não pode exceder o total da peça na OF (${item.quantidade_max_peca} un)`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setSavingEdit(true);
|
||||||
|
const novoPesoTotal = novaQtd * item.peso_unitario;
|
||||||
|
const { error } = await supabase
|
||||||
|
.from('itens_romaneio_pecas')
|
||||||
|
.update({
|
||||||
|
quantidade_expedida: novaQtd,
|
||||||
|
peso_total: novoPesoTotal
|
||||||
|
})
|
||||||
|
.eq('id', item.id);
|
||||||
|
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
toast.success(`Quantidade da peça ${item.marca} atualizada para ${novaQtd} un`);
|
||||||
|
setEditingItemId(null);
|
||||||
|
setEditQuantidade('');
|
||||||
|
carregarItensPecas();
|
||||||
|
onRefresh();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao atualizar item:', error);
|
||||||
|
toast.error('Erro ao atualizar quantidade da peça');
|
||||||
|
} finally {
|
||||||
|
setSavingEdit(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPrioridadeColor = (prioridade: string) => {
|
const getPrioridadeColor = (prioridade: string) => {
|
||||||
switch (prioridade) {
|
switch (prioridade) {
|
||||||
case 'P1': return 'bg-red-100 text-red-800';
|
case 'P1': return 'bg-red-100 text-red-800 border-red-200 dark:bg-red-950/60 dark:text-red-300 dark:border-red-800';
|
||||||
case 'P2': return 'bg-orange-100 text-orange-800';
|
case 'P2': return 'bg-orange-100 text-orange-800 border-orange-200 dark:bg-orange-950/60 dark:text-orange-300 dark:border-orange-800';
|
||||||
case 'P3': return 'bg-blue-100 text-blue-800';
|
case 'P3': return 'bg-blue-100 text-blue-800 border-blue-200 dark:bg-blue-950/60 dark:text-blue-300 dark:border-blue-800';
|
||||||
default: return 'bg-gray-100 text-gray-800';
|
default: return 'bg-slate-100 text-slate-800 border-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-700';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -122,32 +173,35 @@ export const PecasRomaneioExpandido: React.FC<PecasRomaneioExpandidoProps> = ({
|
|||||||
? 'w-[95vw] max-w-none h-[95vh] m-2'
|
? 'w-[95vw] max-w-none h-[95vh] m-2'
|
||||||
: isTablet
|
: isTablet
|
||||||
? 'w-[90vw] max-w-5xl h-[90vh]'
|
? 'w-[90vw] max-w-5xl h-[90vh]'
|
||||||
: 'max-w-6xl h-[95vh]'
|
: 'max-w-6xl h-[90vh]'
|
||||||
}
|
}
|
||||||
bg-slate-900 text-white border-slate-700 overflow-hidden flex flex-col
|
bg-background text-foreground border-border shadow-xl overflow-hidden flex flex-col
|
||||||
`}>
|
`}>
|
||||||
<DialogHeader className="border-b border-slate-700 pb-3 shrink-0">
|
<DialogHeader className="border-b border-border pb-3 shrink-0 pr-6">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<DialogTitle className={`font-bold text-white ${isMobile ? 'text-lg' : 'text-xl'}`}>
|
<DialogTitle className={`font-bold text-foreground flex items-center gap-2 ${isMobile ? 'text-lg' : 'text-xl'}`}>
|
||||||
|
<Package className="h-5 w-5 text-primary shrink-0" />
|
||||||
<span className="truncate">
|
<span className="truncate">
|
||||||
Peças do Romaneio {romaneio.numero_romaneio} - OF: {romaneio.of_number}
|
Peças do Romaneio {romaneio.numero_romaneio} - OF: {romaneio.of_number}
|
||||||
</span>
|
</span>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<Button
|
|
||||||
onClick={onClose}
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
className={`text-gray-400 hover:text-white p-0 ${isMobile ? 'h-6 w-6' : 'h-8 w-8'}`}
|
|
||||||
>
|
|
||||||
<X className={isMobile ? 'h-3 w-3' : 'h-4 w-4'} />
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={`flex gap-2 mt-3 ${isMobile ? 'flex-wrap' : ''}`}>
|
<div className={`flex gap-2 mt-3 ${isMobile ? 'flex-wrap' : ''}`}>
|
||||||
<Badge variant="outline" className={`border-blue-500 text-blue-400 ${isMobile ? 'text-xs px-2 py-1' : ''}`}>
|
<Badge
|
||||||
|
variant="outline"
|
||||||
|
className={`border-blue-500/40 bg-blue-500/10 text-blue-700 dark:text-blue-400 dark:border-blue-500/50 font-semibold ${
|
||||||
|
isMobile ? 'text-xs px-2.5 py-1' : 'px-3 py-1'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
Qtd Total: {qtdTotal}
|
Qtd Total: {qtdTotal}
|
||||||
</Badge>
|
</Badge>
|
||||||
<Badge variant="outline" className={`border-green-500 text-green-400 ${isMobile ? 'text-xs px-2 py-1' : ''}`}>
|
<Badge
|
||||||
|
variant="outline"
|
||||||
|
className={`border-emerald-500/40 bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 dark:border-emerald-500/50 font-semibold ${
|
||||||
|
isMobile ? 'text-xs px-2.5 py-1' : 'px-3 py-1'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
Peso Total: {pesoTotal.toFixed(2)} kg
|
Peso Total: {pesoTotal.toFixed(2)} kg
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
@@ -156,13 +210,13 @@ export const PecasRomaneioExpandido: React.FC<PecasRomaneioExpandidoProps> = ({
|
|||||||
<div className="flex-1 min-h-0">
|
<div className="flex-1 min-h-0">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="flex justify-center items-center h-64">
|
<div className="flex justify-center items-center h-64">
|
||||||
<div className={`text-gray-400 ${isMobile ? 'text-sm' : 'text-base'}`}>
|
<div className={`text-muted-foreground ${isMobile ? 'text-sm' : 'text-base'}`}>
|
||||||
Carregando...
|
Carregando...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : itensPeca.length === 0 ? (
|
) : itensPeca.length === 0 ? (
|
||||||
<div className="flex justify-center items-center h-64">
|
<div className="flex justify-center items-center h-64">
|
||||||
<div className={`text-gray-400 ${isMobile ? 'text-sm' : 'text-base'}`}>
|
<div className={`text-muted-foreground ${isMobile ? 'text-sm' : 'text-base'}`}>
|
||||||
Nenhuma peça encontrada no romaneio
|
Nenhuma peça encontrada no romaneio
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -171,7 +225,7 @@ export const PecasRomaneioExpandido: React.FC<PecasRomaneioExpandidoProps> = ({
|
|||||||
<div className="space-y-1 p-1 pb-4">
|
<div className="space-y-1 p-1 pb-4">
|
||||||
{/* Cabeçalho da tabela - Desktop/Tablet */}
|
{/* Cabeçalho da tabela - Desktop/Tablet */}
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<div className={`grid gap-3 font-medium text-gray-400 bg-slate-800 p-3 rounded-t-md sticky top-0 z-10 ${
|
<div className={`grid gap-3 font-semibold text-muted-foreground bg-muted/80 dark:bg-slate-800/90 border border-border p-3 rounded-t-md sticky top-0 z-10 backdrop-blur-sm ${
|
||||||
isTablet ? 'grid-cols-9 text-xs' : 'grid-cols-11 text-xs'
|
isTablet ? 'grid-cols-9 text-xs' : 'grid-cols-11 text-xs'
|
||||||
}`}>
|
}`}>
|
||||||
<div>Marca</div>
|
<div>Marca</div>
|
||||||
@@ -190,120 +244,209 @@ export const PecasRomaneioExpandido: React.FC<PecasRomaneioExpandidoProps> = ({
|
|||||||
{itensPeca.map((item, index) => {
|
{itensPeca.map((item, index) => {
|
||||||
const limite = romaneio.comprimento_maximo_veiculo || 12000;
|
const limite = romaneio.comprimento_maximo_veiculo || 12000;
|
||||||
const naoCabe = Boolean(item.comprimento && item.comprimento > limite);
|
const naoCabe = Boolean(item.comprimento && item.comprimento > limite);
|
||||||
|
const isEditing = editingItemId === item.id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={item.id}>
|
<div key={item.id}>
|
||||||
{isMobile ? (
|
{isMobile ? (
|
||||||
// Layout mobile - card style
|
// Layout mobile - card style
|
||||||
<div className={`p-3 border rounded-md mb-2 ${
|
<div className={`p-3 border rounded-md mb-2 transition-colors ${
|
||||||
naoCabe ? 'border-red-500/50 bg-red-950/20' : 'border-slate-700'
|
naoCabe
|
||||||
|
? 'border-destructive/50 bg-destructive/10'
|
||||||
|
: 'border-border'
|
||||||
} ${
|
} ${
|
||||||
index % 2 === 0 ? 'bg-slate-800/20' : 'bg-slate-800/40'
|
index % 2 === 0 ? 'bg-card' : 'bg-muted/30'
|
||||||
}`}>
|
}`}>
|
||||||
<div className="flex justify-between items-start mb-2">
|
<div className="flex justify-between items-start mb-2">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="font-medium text-white text-sm flex items-center gap-1.5">
|
<div className="font-semibold text-foreground text-sm flex items-center gap-1.5">
|
||||||
{item.marca}
|
{item.marca}
|
||||||
{naoCabe && (
|
{naoCabe && (
|
||||||
<span className="text-[10px] bg-red-600 text-white font-bold px-1.5 py-0.5 rounded">
|
<span className="text-[10px] bg-destructive text-destructive-foreground font-bold px-1.5 py-0.5 rounded">
|
||||||
Excede Veículo
|
Excede Veículo
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-300 text-xs">{item.fase}</div>
|
<div className="text-muted-foreground text-xs">Fase {item.fase}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
|
{isEditing ? (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
disabled={savingEdit}
|
||||||
|
onClick={() => handleSalvarEdicao(item)}
|
||||||
|
className="h-7 w-7 p-0 text-emerald-600 dark:text-emerald-400 hover:bg-emerald-500/15"
|
||||||
|
title="Salvar quantidade"
|
||||||
|
>
|
||||||
|
<Check className="h-3.5 w-3.5" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
disabled={savingEdit}
|
||||||
|
onClick={handleCancelarEdicao}
|
||||||
|
className="h-7 w-7 p-0 text-muted-foreground hover:bg-muted"
|
||||||
|
title="Cancelar"
|
||||||
|
>
|
||||||
|
<X className="h-3.5 w-3.5" />
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => handleEditarItem(item)}
|
onClick={() => handleEditarItem(item)}
|
||||||
className="h-6 w-6 p-0 text-blue-400 hover:text-blue-300 hover:bg-blue-500/20"
|
className="h-7 w-7 p-0 text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 hover:bg-blue-500/15"
|
||||||
|
title="Editar quantidade"
|
||||||
>
|
>
|
||||||
<Edit2 className="h-3 w-3" />
|
<Edit2 className="h-3.5 w-3.5" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => handleRemoverItem(item.id)}
|
onClick={() => handleRemoverItem(item.id)}
|
||||||
className="h-6 w-6 p-0 text-red-400 hover:text-red-300 hover:bg-red-500/20"
|
className="h-7 w-7 p-0 text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300 hover:bg-red-500/15"
|
||||||
|
title="Remover peça"
|
||||||
>
|
>
|
||||||
<Trash2 className="h-3 w-3" />
|
<Trash2 className="h-3.5 w-3.5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-300 text-xs mb-2 line-clamp-2">
|
<div className="text-muted-foreground text-xs mb-2 line-clamp-2">
|
||||||
{item.descricao}
|
{item.descricao}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-4 gap-2 text-xs">
|
<div className="grid grid-cols-4 gap-2 text-xs items-center">
|
||||||
<div>
|
<div>
|
||||||
<div className="text-gray-400">Comp:</div>
|
<div className="text-muted-foreground">Comp:</div>
|
||||||
<div className={`font-mono font-medium ${naoCabe ? 'text-red-400 font-bold' : 'text-gray-300'}`}>
|
<div className={`font-mono font-medium ${naoCabe ? 'text-destructive font-bold' : 'text-foreground'}`}>
|
||||||
{item.comprimento ? `${item.comprimento}mm` : '-'}
|
{item.comprimento ? `${item.comprimento}mm` : '-'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-gray-400">Qtd:</div>
|
<div className="text-muted-foreground">Qtd:</div>
|
||||||
<div className="font-bold text-blue-400">{item.quantidade_expedida}</div>
|
{isEditing ? (
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
max={item.quantidade_max_peca}
|
||||||
|
value={editQuantidade}
|
||||||
|
onChange={(e) => setEditQuantidade(e.target.value)}
|
||||||
|
className="h-7 w-16 text-center text-xs px-1"
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="font-bold text-blue-600 dark:text-blue-400">{item.quantidade_expedida}</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-gray-400">Peso Unit:</div>
|
<div className="text-muted-foreground">Peso Unit:</div>
|
||||||
<div className="text-gray-300">{item.peso_unitario.toFixed(2)} kg</div>
|
<div className="text-foreground">{item.peso_unitario.toFixed(2)} kg</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="text-gray-400">Peso Total:</div>
|
<div className="text-muted-foreground">Peso Total:</div>
|
||||||
<div className="font-medium text-white">{item.peso_total.toFixed(2)} kg</div>
|
<div className="font-semibold text-foreground">{item.peso_total.toFixed(2)} kg</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
// Layout desktop/tablet - table style
|
// Layout desktop/tablet - table style
|
||||||
<div className={`grid gap-3 text-sm p-3 border-b border-slate-700 hover:bg-slate-800/50 transition-colors ${
|
<div className={`grid gap-3 items-center text-sm p-3 border-b border-x border-border hover:bg-muted/50 transition-colors ${
|
||||||
index % 2 === 0 ? 'bg-slate-800/20' : ''
|
index % 2 === 0 ? 'bg-card' : 'bg-muted/20'
|
||||||
} ${isTablet ? 'grid-cols-9' : 'grid-cols-11'} ${naoCabe ? 'bg-red-950/20' : ''}`}>
|
} ${isTablet ? 'grid-cols-9' : 'grid-cols-11'} ${naoCabe ? 'bg-destructive/10 border-destructive/40' : ''}`}>
|
||||||
<div className="font-medium text-white truncate flex items-center gap-1">
|
<div className="font-semibold text-foreground truncate flex items-center gap-1">
|
||||||
{item.marca}
|
{item.marca}
|
||||||
{naoCabe && <span title="Não cabe no veículo" className="text-red-400 text-xs">⚠️</span>}
|
{naoCabe && <span title="Não cabe no veículo" className="text-destructive text-xs">⚠️</span>}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-gray-300 truncate">{item.fase}</div>
|
<div className="text-muted-foreground truncate">{item.fase}</div>
|
||||||
<div className={`text-gray-300 truncate ${isTablet ? 'col-span-1' : 'col-span-2'}`}>
|
<div className={`text-foreground truncate ${isTablet ? 'col-span-1' : 'col-span-2'}`}>
|
||||||
{item.descricao}
|
{item.descricao}
|
||||||
</div>
|
</div>
|
||||||
<div className={`text-right font-mono text-xs ${naoCabe ? 'text-red-400 font-bold' : 'text-gray-300'}`}>
|
<div className={`text-right font-mono text-xs ${naoCabe ? 'text-destructive font-bold' : 'text-muted-foreground'}`}>
|
||||||
{item.comprimento ? `${item.comprimento}` : '-'}
|
{item.comprimento ? `${item.comprimento}` : '-'}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center font-bold text-blue-400">
|
<div className="text-center font-bold text-blue-600 dark:text-blue-400 flex justify-center">
|
||||||
{item.quantidade_expedida}
|
{isEditing ? (
|
||||||
|
<Input
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
max={item.quantidade_max_peca}
|
||||||
|
value={editQuantidade}
|
||||||
|
onChange={(e) => setEditQuantidade(e.target.value)}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter') handleSalvarEdicao(item);
|
||||||
|
if (e.key === 'Escape') handleCancelarEdicao();
|
||||||
|
}}
|
||||||
|
className="h-7 w-20 text-center text-xs px-1"
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
item.quantidade_expedida
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-right text-gray-300">
|
<div className="text-right text-muted-foreground">
|
||||||
{item.peso_unitario.toFixed(2)} kg
|
{item.peso_unitario.toFixed(2)} kg
|
||||||
</div>
|
</div>
|
||||||
<div className="text-right font-medium text-white">
|
<div className="text-right font-semibold text-foreground">
|
||||||
{item.peso_total.toFixed(2)} kg
|
{item.peso_total.toFixed(2)} kg
|
||||||
</div>
|
</div>
|
||||||
{!isTablet && (
|
{!isTablet && (
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<Badge className={`text-xs ${getPrioridadeColor(item.prioridade)}`}>
|
<Badge variant="outline" className={`text-xs ${getPrioridadeColor(item.prioridade)}`}>
|
||||||
{item.prioridade}
|
{item.prioridade}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className={`flex items-center justify-center gap-2 ${isTablet ? 'col-span-2' : 'col-span-2'}`}>
|
<div className={`flex items-center justify-center gap-2 ${isTablet ? 'col-span-2' : 'col-span-2'}`}>
|
||||||
|
{isEditing ? (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
disabled={savingEdit}
|
||||||
|
onClick={() => handleSalvarEdicao(item)}
|
||||||
|
className="h-7 w-7 p-0 text-emerald-600 dark:text-emerald-400 hover:bg-emerald-500/15"
|
||||||
|
title="Salvar quantidade"
|
||||||
|
>
|
||||||
|
<Check className="h-3.5 w-3.5" />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
disabled={savingEdit}
|
||||||
|
onClick={handleCancelarEdicao}
|
||||||
|
className="h-7 w-7 p-0 text-muted-foreground hover:bg-muted"
|
||||||
|
title="Cancelar edição"
|
||||||
|
>
|
||||||
|
<X className="h-3.5 w-3.5" />
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => handleEditarItem(item)}
|
onClick={() => handleEditarItem(item)}
|
||||||
className="h-7 w-7 p-0 text-blue-400 hover:text-blue-300 hover:bg-blue-500/20"
|
className="h-7 w-7 p-0 text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 hover:bg-blue-500/15"
|
||||||
|
title="Editar quantidade"
|
||||||
>
|
>
|
||||||
<Edit2 className="h-3 w-3" />
|
<Edit2 className="h-3.5 w-3.5" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onClick={() => handleRemoverItem(item.id)}
|
onClick={() => handleRemoverItem(item.id)}
|
||||||
className="h-7 w-7 p-0 text-red-400 hover:text-red-300 hover:bg-red-500/20"
|
className="h-7 w-7 p-0 text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300 hover:bg-red-500/15"
|
||||||
|
title="Remover item"
|
||||||
>
|
>
|
||||||
<Trash2 className="h-3 w-3" />
|
<Trash2 className="h-3.5 w-3.5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -315,11 +458,11 @@ export const PecasRomaneioExpandido: React.FC<PecasRomaneioExpandidoProps> = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={`flex justify-end pt-3 border-t border-slate-700 shrink-0 ${isMobile ? 'px-1' : ''}`}>
|
<div className={`flex justify-end pt-3 border-t border-border shrink-0 ${isMobile ? 'px-1' : ''}`}>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className={`border-slate-600 text-gray-300 hover:bg-slate-800 ${isMobile ? 'h-10 px-4 text-sm' : ''}`}
|
className={`font-medium text-foreground border-border hover:bg-accent hover:text-accent-foreground ${isMobile ? 'h-10 px-4 text-sm' : 'px-6'}`}
|
||||||
>
|
>
|
||||||
Fechar
|
Fechar
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user