Files
Portalweb/src/components/forms/OrderSearchForm.tsx
JuruSysadmin af154c3f7f first
2025-06-17 13:41:48 -03:00

208 lines
7.1 KiB
TypeScript

"use client";
import { OrderSearchParams, orderSearchParamsSchema } from "@/src/schemas";
import { useZodForm } from "@/src/hooks";
interface OrderSearchFormProps {
onSearch: (params: OrderSearchParams) => void;
isLoading?: boolean;
}
export function OrderSearchForm({ onSearch, isLoading = false }: OrderSearchFormProps) {
const {
values,
errors,
handleChange,
handleSubmit,
resetForm
} = useZodForm(orderSearchParamsSchema, {}, onSearch);
return (
<form onSubmit={handleSubmit} className="space-y-5 bg-white p-5 rounded-lg shadow" aria-label="Formulário de busca de pedidos">
<h2 className="text-lg font-semibold text-gray-700 mb-3 border-b pb-2">Busca de Pedidos</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-4 gap-y-5">
{/* Número do Pedido */}
<div className="space-y-1">
<label htmlFor="orderId" className="text-sm font-medium text-gray-700">
Número do Pedido
</label>
<input
type="number"
id="orderId"
name="orderId"
value={values.orderId || ""}
onChange={handleChange}
min="1"
inputMode="numeric"
className={`w-full rounded border p-2 text-sm ${
errors.orderId ? "border-red-500" : "border-gray-300"
}`}
placeholder="Número do pedido"
/>
{errors.orderId && (
<p className="text-red-500 text-xs">{errors.orderId}</p>
)}
</div>
{/* Cliente ID */}
<div className="space-y-1">
<label htmlFor="customerId" className="text-sm font-medium text-gray-700">
ID do Cliente
</label>
<input
type="number"
id="customerId"
name="customerId"
value={values.customerId || ""}
onChange={handleChange}
min="1"
inputMode="numeric"
className={`w-full rounded border p-2 text-sm ${
errors.customerId ? "border-red-500" : "border-gray-300"
}`}
placeholder="ID do cliente"
/>
{errors.customerId && (
<p className="text-red-500 text-xs">{errors.customerId}</p>
)}
</div>
{/* Número da Nota Fiscal */}
<div className="space-y-1">
<label htmlFor="invoiceNumber" className="text-sm font-medium text-gray-700">
Número da Nota Fiscal
</label>
<input
type="text"
id="invoiceNumber"
name="invoiceNumber"
value={values.invoiceNumber || ""}
onChange={handleChange}
className={`w-full rounded border p-2 text-sm ${
errors.invoiceNumber ? "border-red-500" : "border-gray-300"
}`}
placeholder="Número da NF"
/>
{errors.invoiceNumber && (
<p className="text-red-500 text-xs">{errors.invoiceNumber}</p>
)}
</div>
{/* Status */}
<div className="space-y-1">
<label htmlFor="status" className="text-sm font-medium text-gray-700">
Status
</label>
<select
id="status"
name="status"
value={values.status || ""}
onChange={handleChange}
className={`w-full rounded border p-2 text-sm ${
errors.status ? "border-red-500" : "border-gray-300"
}`}
>
<option value="">Selecione o status</option>
<option value="Aberto">Aberto</option>
<option value="Em Processamento">Em Processamento</option>
<option value="Faturado">Faturado</option>
<option value="Entregue">Entregue</option>
<option value="Cancelado">Cancelado</option>
</select>
{errors.status && (
<p className="text-red-500 text-xs">{errors.status}</p>
)}
</div>
{/* Data Inicial */}
<div className="space-y-1">
<label htmlFor="createDateIni" className="text-sm font-medium text-gray-700">
Data Inicial
</label>
<input
type="date"
id="createDateIni"
name="createDateIni"
value={values.createDateIni || ""}
onChange={handleChange}
max={values.createDateEnd || undefined}
className={`w-full rounded border p-2 text-sm ${
errors.createDateIni ? "border-red-500" : "border-gray-300"
}`}
/>
{errors.createDateIni && (
<p className="text-red-500 text-xs">{errors.createDateIni}</p>
)}
</div>
{/* Data Final */}
<div className="space-y-1">
<label htmlFor="createDateEnd" className="text-sm font-medium text-gray-700">
Data Final
</label>
<input
type="date"
id="createDateEnd"
name="createDateEnd"
value={values.createDateEnd || ""}
onChange={handleChange}
min={values.createDateIni || undefined}
className={`w-full rounded border p-2 text-sm ${
errors.createDateEnd ? "border-red-500" : "border-gray-300"
}`}
/>
{errors.createDateEnd && (
<p className="text-red-500 text-xs">{errors.createDateEnd}</p>
)}
</div>
{/* Local de Entrega */}
<div className="space-y-1">
<label htmlFor="deliveryLocal" className="text-sm font-medium text-gray-700">
Local de Entrega
</label>
<input
type="text"
id="deliveryLocal"
name="deliveryLocal"
value={values.deliveryLocal || ""}
onChange={handleChange}
className={`w-full rounded border p-2 text-sm ${
errors.deliveryLocal ? "border-red-500" : "border-gray-300"
}`}
placeholder="Local de entrega"
/>
{errors.deliveryLocal && (
<p className="text-red-500 text-xs">{errors.deliveryLocal}</p>
)}
</div>
</div>
<div className="flex flex-col sm:flex-row items-center justify-between border-t pt-4 mt-2">
<p className="text-xs text-gray-500 mb-3 sm:mb-0">Todos os campos são opcionais</p>
<div className="flex justify-end space-x-3">
<button
type="button"
onClick={resetForm}
className="px-4 py-2 bg-gray-200 text-gray-700 rounded hover:bg-gray-300 transition-colors"
disabled={isLoading}
>
Limpar
</button>
<button
type="submit"
disabled={isLoading}
className={`px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700 transition-colors flex items-center justify-center min-w-[100px] ${
isLoading ? "opacity-70 cursor-not-allowed" : ""
}`}
aria-busy={isLoading}
>
{isLoading ? "Buscando..." : "Buscar"}
</button>
</div>
</div>
</form>
);
}