348 lines
14 KiB
TypeScript
348 lines
14 KiB
TypeScript
|
|
import React from "react";
|
||
|
|
import { Customer } from "../../src/services/customer.service";
|
||
|
|
import {
|
||
|
|
UserPlus,
|
||
|
|
Search,
|
||
|
|
FileText,
|
||
|
|
ArrowRight,
|
||
|
|
Link2,
|
||
|
|
User,
|
||
|
|
CheckCircle,
|
||
|
|
} from "lucide-react";
|
||
|
|
|
||
|
|
interface CustomerStepProps {
|
||
|
|
customerForm: {
|
||
|
|
name: string;
|
||
|
|
document: string;
|
||
|
|
cellPhone: string;
|
||
|
|
cep: string;
|
||
|
|
address: string;
|
||
|
|
number: string;
|
||
|
|
city: string;
|
||
|
|
state: string;
|
||
|
|
complement: string;
|
||
|
|
};
|
||
|
|
customerErrors: Record<string, string>;
|
||
|
|
selectedCustomer: Customer | null;
|
||
|
|
onFormChange: (field: string, value: string) => void;
|
||
|
|
onShowCreateModal: () => void;
|
||
|
|
onShowSearchModal: () => void;
|
||
|
|
onNext: () => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
const CustomerStep: React.FC<CustomerStepProps> = ({
|
||
|
|
customerForm,
|
||
|
|
customerErrors,
|
||
|
|
selectedCustomer,
|
||
|
|
onFormChange,
|
||
|
|
onShowCreateModal,
|
||
|
|
onShowSearchModal,
|
||
|
|
onNext,
|
||
|
|
}) => {
|
||
|
|
return (
|
||
|
|
<div className="animate-fade-in">
|
||
|
|
<div className="flex justify-between items-center mb-6">
|
||
|
|
<h3 className="text-[10px] font-black uppercase tracking-[0.2em] text-slate-400">
|
||
|
|
Informações do cliente
|
||
|
|
</h3>
|
||
|
|
<div className="flex gap-2">
|
||
|
|
<button
|
||
|
|
onClick={onShowSearchModal}
|
||
|
|
className="flex items-center gap-2 bg-slate-100 px-4 py-2 rounded-lg text-[10px] font-black uppercase tracking-widest text-[#002147] hover:bg-slate-200 transition-colors"
|
||
|
|
>
|
||
|
|
<Search className="w-4 h-4" />
|
||
|
|
Selecionar
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
onClick={onShowCreateModal}
|
||
|
|
className="flex items-center gap-2 bg-slate-100 px-4 py-2 rounded-lg text-[10px] font-black uppercase tracking-widest text-[#002147] hover:bg-slate-200 transition-colors"
|
||
|
|
>
|
||
|
|
<UserPlus className="w-4 h-4" />
|
||
|
|
Novo
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{selectedCustomer ? (
|
||
|
|
<>
|
||
|
|
{/* Cliente Selecionado */}
|
||
|
|
<div className="bg-gradient-to-br from-orange-50 to-orange-100/50 rounded-2xl p-6 border-2 border-orange-200 mb-6">
|
||
|
|
<div className="flex items-start justify-between">
|
||
|
|
<div className="flex-1">
|
||
|
|
<div className="flex items-center gap-2 mb-3">
|
||
|
|
<CheckCircle className="w-5 h-5 text-green-500" />
|
||
|
|
<h4 className="font-black text-slate-800 text-lg">
|
||
|
|
{selectedCustomer.name || "Cliente"}
|
||
|
|
</h4>
|
||
|
|
</div>
|
||
|
|
<div className="space-y-1">
|
||
|
|
{selectedCustomer.cpfCnpj && (
|
||
|
|
<p className="text-sm font-bold text-slate-700">
|
||
|
|
CPF/CNPJ: {selectedCustomer.cpfCnpj}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
{selectedCustomer.cellPhone && (
|
||
|
|
<p className="text-sm font-bold text-slate-700">
|
||
|
|
Contato: {selectedCustomer.cellPhone}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
{selectedCustomer.address && (
|
||
|
|
<p className="text-xs text-slate-600">
|
||
|
|
{selectedCustomer.address}
|
||
|
|
{selectedCustomer.number &&
|
||
|
|
`, ${selectedCustomer.number}`}
|
||
|
|
{selectedCustomer.complement &&
|
||
|
|
` - ${selectedCustomer.complement}`}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
{(selectedCustomer.city || selectedCustomer.state) && (
|
||
|
|
<p className="text-xs text-slate-600">
|
||
|
|
{selectedCustomer.city && `${selectedCustomer.city}`}
|
||
|
|
{selectedCustomer.state && `/${selectedCustomer.state}`}
|
||
|
|
{selectedCustomer.cep &&
|
||
|
|
` - CEP: ${selectedCustomer.cep}`}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<form className="space-y-4">
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||
|
|
<div className="md:col-span-2">
|
||
|
|
<label className="block text-[10px] font-black uppercase text-slate-400 mb-2">
|
||
|
|
Nome do Cliente
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={customerForm.name}
|
||
|
|
onChange={(e) => onFormChange("name", e.target.value)}
|
||
|
|
className={`w-full px-4 py-3 bg-slate-50 rounded-xl font-bold text-[#002147] border ${
|
||
|
|
customerErrors.name ? "border-red-500" : "border-slate-200"
|
||
|
|
} focus:outline-none focus:ring-2 focus:ring-orange-500/20`}
|
||
|
|
disabled
|
||
|
|
/>
|
||
|
|
{customerErrors.name && (
|
||
|
|
<p className="text-red-500 text-xs mt-1">
|
||
|
|
{customerErrors.name}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label className="block text-[10px] font-black uppercase text-slate-400 mb-2">
|
||
|
|
CPF / CNPJ
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={customerForm.document}
|
||
|
|
onChange={(e) => onFormChange("document", e.target.value)}
|
||
|
|
className={`w-full px-4 py-3 bg-slate-50 rounded-xl font-bold text-[#002147] border ${
|
||
|
|
customerErrors.document
|
||
|
|
? "border-red-500"
|
||
|
|
: "border-slate-200"
|
||
|
|
} focus:outline-none focus:ring-2 focus:ring-orange-500/20`}
|
||
|
|
disabled
|
||
|
|
/>
|
||
|
|
{customerErrors.document && (
|
||
|
|
<p className="text-red-500 text-xs mt-1">
|
||
|
|
{customerErrors.document}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
|
|
<div>
|
||
|
|
<label className="block text-[10px] font-black uppercase text-slate-400 mb-2">
|
||
|
|
CONTATO
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={customerForm.cellPhone}
|
||
|
|
onChange={(e) => onFormChange("cellPhone", e.target.value)}
|
||
|
|
className={`w-full px-4 py-3 bg-slate-50 rounded-xl font-bold text-[#002147] border ${
|
||
|
|
customerErrors.cellPhone
|
||
|
|
? "border-red-500"
|
||
|
|
: "border-slate-200"
|
||
|
|
} focus:outline-none focus:ring-2 focus:ring-orange-500/20`}
|
||
|
|
disabled
|
||
|
|
/>
|
||
|
|
{customerErrors.cellPhone && (
|
||
|
|
<p className="text-red-500 text-xs mt-1">
|
||
|
|
{customerErrors.cellPhone}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label className="block text-[10px] font-black uppercase text-slate-400 mb-2">
|
||
|
|
CEP
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={customerForm.cep}
|
||
|
|
onChange={(e) => onFormChange("cep", e.target.value)}
|
||
|
|
className={`w-full px-4 py-3 bg-slate-50 rounded-xl font-bold text-[#002147] border ${
|
||
|
|
customerErrors.cep ? "border-red-500" : "border-slate-200"
|
||
|
|
} focus:outline-none focus:ring-2 focus:ring-orange-500/20`}
|
||
|
|
disabled
|
||
|
|
/>
|
||
|
|
{customerErrors.cep && (
|
||
|
|
<p className="text-red-500 text-xs mt-1">
|
||
|
|
{customerErrors.cep}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-[10px] font-black uppercase text-slate-400 mb-2">
|
||
|
|
endereço
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={customerForm.address}
|
||
|
|
onChange={(e) => onFormChange("address", e.target.value)}
|
||
|
|
className={`w-full px-4 py-3 bg-slate-50 rounded-xl font-bold text-[#002147] border ${
|
||
|
|
customerErrors.address ? "border-red-500" : "border-slate-200"
|
||
|
|
} focus:outline-none focus:ring-2 focus:ring-orange-500/20`}
|
||
|
|
disabled
|
||
|
|
/>
|
||
|
|
{customerErrors.address && (
|
||
|
|
<p className="text-red-500 text-xs mt-1">
|
||
|
|
{customerErrors.address}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||
|
|
<div>
|
||
|
|
<label className="block text-[10px] font-black uppercase text-slate-400 mb-2">
|
||
|
|
número
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={customerForm.number}
|
||
|
|
onChange={(e) => onFormChange("number", e.target.value)}
|
||
|
|
className={`w-full px-4 py-3 bg-slate-50 rounded-xl font-bold text-[#002147] border ${
|
||
|
|
customerErrors.number
|
||
|
|
? "border-red-500"
|
||
|
|
: "border-slate-200"
|
||
|
|
} focus:outline-none focus:ring-2 focus:ring-orange-500/20`}
|
||
|
|
disabled
|
||
|
|
/>
|
||
|
|
{customerErrors.number && (
|
||
|
|
<p className="text-red-500 text-xs mt-1">
|
||
|
|
{customerErrors.number}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label className="block text-[10px] font-black uppercase text-slate-400 mb-2">
|
||
|
|
cidade
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={customerForm.city}
|
||
|
|
onChange={(e) => onFormChange("city", e.target.value)}
|
||
|
|
className={`w-full px-4 py-3 bg-slate-50 rounded-xl font-bold text-[#002147] border ${
|
||
|
|
customerErrors.city ? "border-red-500" : "border-slate-200"
|
||
|
|
} focus:outline-none focus:ring-2 focus:ring-orange-500/20`}
|
||
|
|
disabled
|
||
|
|
/>
|
||
|
|
{customerErrors.city && (
|
||
|
|
<p className="text-red-500 text-xs mt-1">
|
||
|
|
{customerErrors.city}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
<div>
|
||
|
|
<label className="block text-[10px] font-black uppercase text-slate-400 mb-2">
|
||
|
|
estado
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={customerForm.state}
|
||
|
|
onChange={(e) => onFormChange("state", e.target.value)}
|
||
|
|
className={`w-full px-4 py-3 bg-slate-50 rounded-xl font-bold text-[#002147] border ${
|
||
|
|
customerErrors.state ? "border-red-500" : "border-slate-200"
|
||
|
|
} focus:outline-none focus:ring-2 focus:ring-orange-500/20`}
|
||
|
|
disabled
|
||
|
|
/>
|
||
|
|
{customerErrors.state && (
|
||
|
|
<p className="text-red-500 text-xs mt-1">
|
||
|
|
{customerErrors.state}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label className="block text-[10px] font-black uppercase text-slate-400 mb-2">
|
||
|
|
complemento
|
||
|
|
</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={customerForm.complement}
|
||
|
|
onChange={(e) => onFormChange("complement", e.target.value)}
|
||
|
|
className="w-full px-4 py-3 bg-slate-50 rounded-xl font-bold text-[#002147] border border-slate-200 focus:outline-none focus:ring-2 focus:ring-orange-500/20"
|
||
|
|
disabled
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="flex justify-end gap-2 mt-6">
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={onShowSearchModal}
|
||
|
|
className="flex items-center gap-2 bg-slate-100 px-6 py-2 rounded-lg text-[10px] font-black uppercase tracking-widest text-[#002147] hover:bg-slate-200 transition-colors"
|
||
|
|
>
|
||
|
|
<FileText className="w-4 h-4" />
|
||
|
|
Pré-Cadastro
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={onNext}
|
||
|
|
className="flex items-center gap-2 bg-[#002147] text-white px-6 py-2 rounded-lg text-[10px] font-black uppercase tracking-widest hover:bg-[#003366] transition-colors"
|
||
|
|
>
|
||
|
|
Avançar
|
||
|
|
<ArrowRight className="w-4 h-4" />
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</form>
|
||
|
|
</>
|
||
|
|
) : (
|
||
|
|
/* Sem Cliente Selecionado */
|
||
|
|
<div className="bg-slate-50 rounded-2xl p-8 border-2 border-dashed border-slate-300 mb-6 text-center">
|
||
|
|
<div className="w-20 h-20 bg-slate-200 rounded-full flex items-center justify-center mx-auto mb-4">
|
||
|
|
<User className="w-10 h-10 text-slate-400" />
|
||
|
|
</div>
|
||
|
|
<p className="text-lg font-bold text-slate-600 mb-2">
|
||
|
|
Nenhum cliente selecionado
|
||
|
|
</p>
|
||
|
|
<p className="text-sm text-slate-500 mb-6">
|
||
|
|
Selecione um cliente existente ou cadastre um novo cliente
|
||
|
|
</p>
|
||
|
|
<div className="flex gap-3 justify-center">
|
||
|
|
<button
|
||
|
|
onClick={onShowSearchModal}
|
||
|
|
className="flex items-center gap-2 bg-[#002147] text-white px-6 py-3 rounded-xl font-black uppercase text-xs tracking-widest hover:bg-[#001a36] transition-all"
|
||
|
|
>
|
||
|
|
<Search className="w-4 h-4" />
|
||
|
|
Selecionar Cliente
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
onClick={onShowCreateModal}
|
||
|
|
className="flex items-center gap-2 bg-white border-2 border-[#002147] text-[#002147] px-6 py-3 rounded-xl font-black uppercase text-xs tracking-widest hover:bg-[#002147] hover:text-white transition-all"
|
||
|
|
>
|
||
|
|
<UserPlus className="w-4 h-4" />
|
||
|
|
Cadastrar Novo
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default CustomerStep;
|