🚀 Initial commit: Versão atual do TrackSteel APP

This commit is contained in:
2026-03-18 21:17:53 +00:00
commit bde410c9ad
633 changed files with 108150 additions and 0 deletions
@@ -0,0 +1,118 @@
import React from 'react';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Edit, Copy } from 'lucide-react';
import { EstoqueMaterial, useDuplicarMaterial } from '@/hooks/useEstoque';
import { EstoqueTableHeader } from '../EstoqueTableHeader';
import { ScrollableTable } from '@/components/ui/ScrollableTable';
interface EstoqueDesktopTableProps {
materiais: EstoqueMaterial[];
selectedMaterials: EstoqueMaterial[];
onSelectMaterial: (material: EstoqueMaterial, isSelected: boolean) => void;
onEditMaterial: (material: EstoqueMaterial) => void;
onSelectAll: (e: React.ChangeEvent<HTMLInputElement>) => void;
isAllSelected: () => boolean;
sortField: any;
sortOrder: any;
onSort: (field: any) => void;
getStatusColor: (status: string) => string;
}
export const EstoqueDesktopTable: React.FC<EstoqueDesktopTableProps> = ({
materiais,
selectedMaterials,
onSelectMaterial,
onEditMaterial,
onSelectAll,
isAllSelected,
sortField,
sortOrder,
onSort,
getStatusColor
}) => {
const duplicarMaterial = useDuplicarMaterial();
const handleDuplicarMaterial = (material: EstoqueMaterial) => {
duplicarMaterial.mutate(material);
};
return (
<div className="hidden sm:block">
<div className="w-full overflow-x-auto">
<Table>
<TableHeader>
<EstoqueTableHeader
sortField={sortField}
sortOrder={sortOrder}
onSort={onSort}
isAllSelected={isAllSelected()}
onSelectAll={onSelectAll}
/>
</TableHeader>
<TableBody>
{materiais.map((material) => {
const pesoTotal = (material.quantidade_total || 0) * (material.peso_unitario || 0);
return (
<TableRow key={material.id} className="h-auto min-h-[3rem]">
<TableCell className="py-2 px-1 w-8">
<input
type="checkbox"
className="w-3 h-3"
checked={selectedMaterials.some(m => m.id === material.id)}
onChange={(e) => onSelectMaterial(material, e.target.checked)}
/>
</TableCell>
<TableCell className="text-xs py-2 px-2 w-80">
<div className="break-words whitespace-normal leading-tight max-w-full">
{material.descricao}
</div>
</TableCell>
<TableCell className="text-xs py-2 px-2 w-24">{material.lote_atual || '-'}</TableCell>
<TableCell className="text-xs py-2 px-2 w-32">{material.tipos_materia_prima?.nome || '-'}</TableCell>
<TableCell className="text-xs py-2 px-2 w-16">{material.unidade}</TableCell>
<TableCell className="text-xs py-2 px-2 w-16">{material.comprimento || '-'}</TableCell>
<TableCell className="text-xs py-2 px-2 font-medium w-20">{material.quantidade_total}</TableCell>
<TableCell className="text-xs py-2 px-2 font-medium text-blue-600 w-20">{pesoTotal.toFixed(1)}</TableCell>
<TableCell className="text-xs py-2 px-2 font-medium text-green-600 w-20">{material.quantidade_disponivel}</TableCell>
<TableCell className="text-xs py-2 px-2 font-medium text-orange-600 w-20">{material.quantidade_empenhada}</TableCell>
<TableCell className="py-2 px-2 w-24">
<Badge variant="outline" className={`${getStatusColor(material.status)} text-xs`}>
{material.status}
</Badge>
</TableCell>
<TableCell className="py-2 px-2 w-20">
<div className="flex items-center gap-1">
<Button
variant="ghost"
size="sm"
onClick={() => onEditMaterial(material)}
className="h-6 w-6 p-1"
title="Editar material"
>
<Edit className="h-3 w-3" />
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => handleDuplicarMaterial(material)}
className="h-6 w-6 p-1 text-blue-600 hover:text-blue-700"
title="Duplicar material"
disabled={duplicarMaterial.isPending}
>
<Copy className="h-3 w-3" />
</Button>
</div>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
</div>
);
};
@@ -0,0 +1,124 @@
import React from 'react';
import { Card, CardContent } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Edit, Copy } from 'lucide-react';
import { EstoqueMaterial, useDuplicarMaterial } from '@/hooks/useEstoque';
interface EstoqueMobileViewProps {
materiais: EstoqueMaterial[];
selectedMaterials: EstoqueMaterial[];
onSelectMaterial: (material: EstoqueMaterial, isSelected: boolean) => void;
onEditMaterial: (material: EstoqueMaterial) => void;
getStatusColor: (status: string) => string;
}
export const EstoqueMobileView: React.FC<EstoqueMobileViewProps> = ({
materiais,
selectedMaterials,
onSelectMaterial,
onEditMaterial,
getStatusColor
}) => {
const duplicarMaterial = useDuplicarMaterial();
const handleDuplicarMaterial = (material: EstoqueMaterial) => {
duplicarMaterial.mutate(material);
};
return (
<div className="sm:hidden space-y-4">
{materiais.map((material) => {
const pesoTotal = (material.quantidade_total || 0) * (material.peso_unitario || 0);
return (
<Card key={material.id} className="relative">
<CardContent className="p-4">
<div className="flex items-start justify-between mb-3">
<div className="flex items-center space-x-2">
<input
type="checkbox"
className="w-4 h-4"
checked={selectedMaterials.some(m => m.id === material.id)}
onChange={(e) => onSelectMaterial(material, e.target.checked)}
/>
<div className="flex-1">
<h3 className="font-medium text-sm text-foreground leading-tight">
{material.descricao}
</h3>
<p className="text-xs text-muted-foreground mt-1">
Código: {material.codigo}
</p>
</div>
</div>
<div className="flex items-center gap-1 ml-2">
<Button
variant="ghost"
size="sm"
onClick={() => onEditMaterial(material)}
className="h-7 w-7 p-1"
title="Editar material"
>
<Edit className="h-3 w-3" />
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => handleDuplicarMaterial(material)}
className="h-7 w-7 p-1 text-blue-600 hover:text-blue-700"
title="Duplicar material"
disabled={duplicarMaterial.isPending}
>
<Copy className="h-3 w-3" />
</Button>
</div>
</div>
<div className="grid grid-cols-2 gap-2 text-xs">
<div>
<span className="text-muted-foreground">Lote:</span>
<span className="ml-1 font-medium">{material.lote_atual || '-'}</span>
</div>
<div>
<span className="text-muted-foreground">Tipo:</span>
<span className="ml-1 font-medium">{material.tipos_materia_prima?.nome || '-'}</span>
</div>
<div>
<span className="text-muted-foreground">Unidade:</span>
<span className="ml-1 font-medium">{material.unidade}</span>
</div>
<div>
<span className="text-muted-foreground">Comprimento:</span>
<span className="ml-1 font-medium">{material.comprimento || '-'}</span>
</div>
<div>
<span className="text-muted-foreground">Qtd Total:</span>
<span className="ml-1 font-medium">{material.quantidade_total}</span>
</div>
<div>
<span className="text-muted-foreground">Peso Total:</span>
<span className="ml-1 font-medium text-blue-600">{pesoTotal.toFixed(1)}</span>
</div>
<div>
<span className="text-muted-foreground">Disponível:</span>
<span className="ml-1 font-medium text-green-600">{material.quantidade_disponivel}</span>
</div>
<div>
<span className="text-muted-foreground">Empenhada:</span>
<span className="ml-1 font-medium text-orange-600">{material.quantidade_empenhada}</span>
</div>
</div>
<div className="flex justify-between items-center mt-3">
<Badge variant="outline" className={`${getStatusColor(material.status)} text-xs`}>
{material.status}
</Badge>
</div>
</CardContent>
</Card>
);
})}
</div>
);
};