feat(): Ajustes na tela de detalhes do pedido

This commit is contained in:
Keven 2025-12-16 15:07:01 -03:00
parent fca1d0c293
commit c8863e573f
29 changed files with 415 additions and 301 deletions

View file

@ -0,0 +1,11 @@
'use client';
import { useParams } from 'next/navigation';
import TServicoPedidoDetails from '@/packages/servicos/components/TServicoPedido/TServicoPedidoDetails';
export default function TServicoPedidoDetailsPage() {
const params = useParams();
return <TServicoPedidoDetails servico_pedido_id={Number(params.servicoPedidoId)} />;
}

View file

@ -0,0 +1,5 @@
import TServicoPedidoIndex from '@/packages/servicos/components/TServicoPedido/TServicoPedidoIndex';
export default function TServicoPedidoPage() {
return <TServicoPedidoIndex />;
}

View file

@ -0,0 +1,11 @@
'use client';
import { useParams } from 'next/navigation';
import TServicoPedidoForm from '@/packages/servicos/components/TServicoPedido/TServicoPedidoForm';
export default function TServicoPedidoPage() {
const params = useParams();
return <TServicoPedidoForm servico_pedido_id={Number(params.servicoPedidoId)} />;
}

View file

@ -0,0 +1,5 @@
import TServicoPedidoForm from '@/packages/servicos/components/TServicoPedido/TServicoPedidoForm';
export default function TServicoPedidoPage() {
return <TServicoPedidoForm />;
}

View file

@ -54,8 +54,12 @@ const data = {
url: '/servicos/dashboard/',
},
{
title: 'Balcão',
url: '/servicos/balcao/',
title: 'Pedidos',
url: '/servicos/pedidos/',
},
{
title: 'Certidões',
url: '/servicos/certidoes/',
},
],
},

View file

@ -1,7 +1,12 @@
'use client';
import { BookmarkX, IdCardIcon, MoreHorizontalIcon, RotateCcwIcon, TicketIcon } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import {
BookmarkX,
IdCardIcon,
MoreHorizontalIcon,
RotateCcwIcon,
TicketIcon,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { ButtonGroup } from '@/components/ui/button-group';
@ -14,84 +19,36 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { useTServicoItemPedidoAtivarHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoAtivarHook';
import { useTServicoItemPedidoCancelarHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCancelarHook';
import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce';
import { useTServicoItemPedidoListControllerHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoListControllerHook';
import TServicoItemPedidoListInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoListInterface';
import FormatMoney from '@/shared/actions/money/FormatMoney';
import { useResponse } from '@/shared/components/response/ResponseContext';
import { ServicosPedidosSituacoesBadge } from '@/shared/components/servicosPedidosSituacoes/ServicosPedidosSituacoesBadge';
import { ServicosPedidosSituacoesEnum } from '@/shared/enums/ServicosPedidosSituacoesEnum';
export default function TServicoItemPedidoList({
items,
openConfirmDialog,
}: TServicoItemPedidoListInterface) {
export default function TServicoItemPedidoList({ items, openConfirmDialog }: TServicoItemPedidoListInterface) {
const { setResponse } = useResponse();
const { cancelarTServicoItemPedido } = useTServicoItemPedidoCancelarHook();
const { ativarTServicoItemPedido } = useTServicoItemPedidoAtivarHook();
const [localItems, setLocalItems] = useState<TServicoItemPedidoInterface[]>(items || []);
useEffect(() => {
setLocalItems(items || []);
}, [items]);
const handleSituacaoTServicoItemPedido = useCallback(
async (item: TServicoItemPedidoInterface) => {
const servicoItemPedido: TServicoItemPedidoInterface = {
servico_itempedido_id: item.servico_itempedido_id,
};
let response: any = null;
switch (item.situacao) {
case 'C':
response = await ativarTServicoItemPedido(servicoItemPedido);
break;
case 'F':
response = await cancelarTServicoItemPedido(servicoItemPedido);
break;
default:
setResponse({
status: 422,
error: 'Situação',
detail: 'Situação não tratada',
});
break;
}
if (response) {
const situacao = (response as any)?.situacao;
setLocalItems((prev) =>
prev.map((i) =>
i.servico_itempedido_id === item.servico_itempedido_id ? { ...i, situacao } : i,
),
);
}
},
[ativarTServicoItemPedido, cancelarTServicoItemPedido, setResponse],
);
const { localItems, handleSituacaoTServicoItemPedido } = useTServicoItemPedidoListControllerHook(items);
return (
<Card className="card-border">
<CardHeader>
<CardTitle className="text-2xl font-semibold">Itens: {localItems?.length}</CardTitle>
<CardTitle className="text-2xl font-semibold">
Itens: {localItems.length}
</CardTitle>
</CardHeader>
<CardContent>
{/* Altura máxima + scroll vertical */}
<div className="max-h-[60vh] space-y-4 overflow-y-auto pr-1">
{localItems?.map((item) => {
{localItems.map((item) => {
const isCancelado = item.situacao === 'C';
const actionLabel = isCancelado ? 'Ativar Item' : 'Estornar Item';
const confirmTitle = isCancelado ? 'Ativação de Item' : 'Estorno de Item';
const confirmMessage = isCancelado
? `Deseja realmente ativar o item #${item.servico_itempedido_id}?`
: `Deseja realmente estornar o item #${item.servico_itempedido_id}?`;
const confirmMessage = isCancelado ? `Deseja realmente ativar o item #${item.servico_itempedido_id}?` : `Deseja realmente estornar o item #${item.servico_itempedido_id}?`;
const confirmButton = isCancelado ? 'Sim, ativar item' : 'Sim, estornar item';
const actionIcon = isCancelado ? <RotateCcwIcon /> : <BookmarkX />;
return (
@ -102,19 +59,20 @@ export default function TServicoItemPedidoList({
{/* Descrição */}
<div className="flex-1">
<h3 className="text-foreground line-clamp-2 text-sm font-bold lg:text-base">
{item.descricao} de {item.nome} -{' '}
{item.descricao} de {item.nome} {' '}
<ServicosPedidosSituacoesBadge
situacao={item.situacao as 'A' | 'F' | 'C' | null | undefined}
situacao={item.situacao as ServicosPedidosSituacoesEnum}
/>
</h3>
<h6 className="text-foreground line-clamp-2 text-sm lg:text-base">
<h6 className="text-foreground text-sm">
# {item.servico_itempedido_id}
</h6>
</div>
{/* Valores (grid compacto) */}
{/* Valores */}
<div className="mt-4 grid grid-cols-6 gap-3">
<div>
<div className="text-muted-foreground text-xs">Emolumento</div>
<div className="font-semibold">{FormatMoney(item.emolumento)}</div>
@ -140,33 +98,33 @@ export default function TServicoItemPedidoList({
<div className="font-semibold">{FormatMoney(item.valor)}</div>
</div>
{/* Ações */}
<div className="text-end">
<ButtonGroup>
<Button variant="outline">Ações</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon" aria-label="More Options">
<Button variant="outline" size="icon">
<MoreHorizontalIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-52">
<DropdownMenuGroup>
<DropdownMenuItem className="cursor-pointer">
<TicketIcon />
Imprimir Etiqueta
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuGroup>
<DropdownMenuItem className="cursor-pointer">
<IdCardIcon />
Imprimir Cartão
<DropdownMenuItem>
<TicketIcon /> Imprimir Etiqueta
</DropdownMenuItem>
<DropdownMenuItem>
<IdCardIcon /> Imprimir Cartão
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem
className={`cursor-pointer ${isCancelado ? 'text-green-600' : 'text-destructive'
}`}
variant={isCancelado ? 'default' : 'destructive'}
onClick={() =>
openConfirmDialog({
title: confirmTitle,
@ -174,9 +132,8 @@ export default function TServicoItemPedidoList({
message: confirmMessage,
confirmText: confirmButton,
cancelText: 'Cancelar',
onConfirm: () => {
handleSituacaoTServicoItemPedido(item);
},
onConfirm: () =>
handleSituacaoTServicoItemPedido(item),
})
}
>
@ -195,4 +152,4 @@ export default function TServicoItemPedidoList({
</CardContent>
</Card>
);
}
}

View file

@ -117,14 +117,14 @@ export default function TServicoPedidoColumns(
<DropdownMenuContent side="left" align="start">
<DropdownMenuGroup>
<DropdownMenuItem asChild>
<Link href={`/servicos/balcao/detalhes/${row.getValue('servico_pedido_id')}`}>
<Link href={`/servicos/pedidos/detalhes/${row.getValue('servico_pedido_id')}`}>
<EyeIcon className="mr-2 h-4 w-4" />
Detalhes
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link href={`/servicos/balcao/pedido/${row.getValue('servico_pedido_id')}`}>
<Link href={`/servicos/pedidos/pedido/${row.getValue('servico_pedido_id')}`}>
<PencilIcon className="mr-2 h-4 w-4" />
Editar
</Link>

View file

@ -1,239 +1,116 @@
'use client';
import { BookmarkX, CalendarIcon, ReceiptText, RotateCcwIcon } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import { CalendarIcon, ReceiptText } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Separator } from '@/components/ui/separator';
import TServicoItemPedidoList from '@/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoList';
import TServicoPedidoDetailsPagamento from '@/packages/servicos/components/TServicoPedido/TServicoPedidoDetailsPagamento';
import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook';
import { useTServicoPedidoAtivarHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoAtivarHook';
import { useTServicoPedidoCancelarHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoCancelarHook';
import { useTServicoPedidoShowHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook';
import { useTServicoPedidoDetailsControllerHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoDetailsControllerHook';
import TServicoPedidoDetailsInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsInterface';
import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface';
import { FormatCPF } from '@/shared/actions/CPF/FormatCPF';
import { FormatDateTime } from '@/shared/actions/dateTime/FormatDateTime';
import GetCapitalize from '@/shared/actions/text/GetCapitalize';
import GetNameInitials from '@/shared/actions/text/GetNameInitials';
import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog';
import { useResponse } from '@/shared/components/response/ResponseContext';
export default function TServicoPedidoDetails({
servico_pedido_id,
}: TServicoPedidoDetailsInterface) {
const { setResponse } = useResponse();
const { ativarTServicoPedido } = useTServicoPedidoAtivarHook();
const { cancelarTServicoPedido } = useTServicoPedidoCancelarHook();
const { TServicoItemPedido, indexTServicoItemPedido } = useTServicoItemPedidoIndexHook();
const { TServicoPedido, setTServicoPedido, showTServicoPedido } = useTServicoPedidoShowHook();
const handleSituacaoTServicoPedido = useCallback(
async (pedido: any) => {
const servicoPedido: TServicoPedidoInterface = {
servico_pedido_id: pedido.servico_pedido_id,
};
let response: any = null;
switch (pedido.situacao) {
case 'C':
response = await ativarTServicoPedido(servicoPedido);
break;
case 'F':
response = await cancelarTServicoPedido(servicoPedido);
break;
default:
setResponse({
status: 422,
error: 'Situação',
detail: 'Situação não tratada',
});
break;
}
if (response) {
pedido.situacao = response.situacao;
setTServicoPedido(pedido);
}
},
[cancelarTServicoPedido],
);
type ConfirmDialogParams = {
title: string;
description: string;
message: string;
confirmText?: string;
cancelText?: string;
onConfirm?: () => void;
onCancel?: () => void;
};
const [confirmDialog, setConfirmDialog] = useState({
isOpen: false,
title: '',
description: '',
message: '',
confirmText: 'Confirmar',
cancelText: 'Cancelar',
onConfirm: () => { },
onCancel: () => { },
});
// Função utilitária para abrir o dialog dinamicamente
const openConfirmDialog = ({
title,
description,
message,
confirmText = 'Confirmar',
cancelText = 'Cancelar',
onConfirm,
onCancel,
}: ConfirmDialogParams) => {
setConfirmDialog({
isOpen: true,
title,
description,
message,
confirmText,
cancelText,
onConfirm: () => {
onConfirm?.();
setConfirmDialog((prev) => ({ ...prev, isOpen: false }));
},
onCancel: () => {
onCancel?.();
setConfirmDialog((prev) => ({ ...prev, isOpen: false }));
},
});
};
const TServicoPedidoShowData = useCallback(async () => {
const servicoPedido: TServicoPedidoInterface = {
servico_pedido_id: servico_pedido_id,
};
const response = await showTServicoPedido(servicoPedido);
if (response.servico_pedido_id) {
TServicoPedidoItemIndexData(response.servico_pedido_id);
}
}, []);
const TServicoPedidoItemIndexData = useCallback(
async (servico_pedido_id: number) => {
await indexTServicoItemPedido({ servico_pedido_id });
},
[indexTServicoItemPedido],
);
useEffect(() => {
TServicoPedidoShowData();
}, []);
const isCancelado = String(TServicoPedido?.situacao) === 'C';
const actionLabel = isCancelado ? 'Ativar Pedido' : 'Estornar Pedido';
const actionIcon = isCancelado ? <RotateCcwIcon /> : <BookmarkX />;
const {
TServicoPedido,
TServicoItemPedido,
handleSituacaoTServicoPedido,
openConfirmDialog,
confirmDialog,
actionLabel,
} = useTServicoPedidoDetailsControllerHook(servico_pedido_id);
return (
<div>
<h3 className="mb-4 text-4xl font-bold">Pedido: #{TServicoPedido?.servico_pedido_id}</h3>
{/* Main */}
<h3 className="mb-4 text-4xl font-bold">
Pedido: #{TServicoPedido?.servico_pedido_id}
</h3>
<div className="mx-auto h-full">
<div className="flex flex-col gap-4 lg:flex-row">
{/* Left column */}
{/* Coluna esquerda */}
<div className="flex flex-auto flex-col gap-4">
<TServicoItemPedidoList
items={TServicoItemPedido}
openConfirmDialog={openConfirmDialog}
/>
<TServicoPedidoDetailsPagamento
situacao={String(TServicoPedido?.situacao ?? '')}
items={TServicoItemPedido}
/>
</div>
{/* Right column (sidebar) */}
{/* Sidebar */}
<div className="flex flex-col gap-4 lg:w-[320px] xl:w-[420px]">
<Card role="presentation" className="card-border">
<Card className="card-border">
<CardHeader>
<CardTitle className="text-2xl font-semibold">Apresentante</CardTitle>
<CardTitle className="text-2xl font-semibold">
Apresentante
</CardTitle>
</CardHeader>
<CardContent>
{/* Header com avatar e link */}
<div className="flex items-center gap-2">
{/* Foto ou Iniciais */}
<div className="flex h-10 w-10 items-center justify-center overflow-hidden rounded-full bg-gray-200">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-gray-200">
<span className="text-sm font-medium text-gray-700">
{GetNameInitials(TServicoPedido?.apresentante)}
</span>
</div>
<div className="min-w-0">
<div className="truncate font-bold">
<div>
<div className="font-bold">
{GetCapitalize(TServicoPedido?.apresentante)}
</div>
<div className="truncate font-light">
{FormatCPF(String(TServicoPedido?.cpfcnpj_apresentante))}
<div className="font-light">
{FormatCPF(
String(TServicoPedido?.cpfcnpj_apresentante),
)}
</div>
</div>
</div>
<Separator className="my-5" />
<div className="flex items-center gap-2">
<CalendarIcon className="size-5 opacity-70" />
<span className="truncate">{FormatDateTime(TServicoPedido?.data_pedido)}</span>
</div>
</CardContent>
</Card>
<Card role="presentation" className="card-border">
<CardHeader>
<CardTitle className="text-2xl font-semibold">Operador</CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-center gap-2">
{/* Foto ou Iniciais */}
<div className="flex h-10 w-10 items-center justify-center overflow-hidden rounded-full bg-gray-200">
<span className="text-sm font-medium text-gray-700">
{GetNameInitials(TServicoPedido?.login)}
</span>
</div>
<div className="min-w-0">
<div className="truncate font-bold">{GetCapitalize(TServicoPedido?.login)}</div>
<div className="truncate font-light">
{GetCapitalize(TServicoPedido?.funcao)}
</div>
</div>
<span>
{FormatDateTime(TServicoPedido?.data_pedido)}
</span>
</div>
</CardContent>
</Card>
<Card className="card-border">
<CardHeader>
<CardTitle className="text-2xl font-semibold">Controles</CardTitle>
<CardTitle className="text-2xl font-semibold">
Controles
</CardTitle>
</CardHeader>
<CardContent className="flex flex-col gap-2">
<Button
className="w-full cursor-pointer"
variant={`outline`}
variant="outline"
onClick={() =>
openConfirmDialog({
title: 'Estorno do pedido',
description: 'Confirmação necessária',
message: 'Deseja continuar com o estorno ?',
message: 'Deseja continuar com o estorno?',
confirmText: 'Sim, continuar',
cancelText: 'Cancelar',
onConfirm: () => {
handleSituacaoTServicoPedido(TServicoPedido);
},
onConfirm: () =>
handleSituacaoTServicoPedido(TServicoPedido),
})
}
>
{actionIcon} {actionLabel}
{actionLabel}
</Button>
<Button className="w-full cursor-pointer">
<Button>
<ReceiptText /> Imprimir Recibo
</Button>
</CardContent>
@ -241,7 +118,7 @@ export default function TServicoPedidoDetails({
</div>
</div>
</div>
{/* Confirma o cancelamento do pedido */}
<ConfirmDialog
isOpen={confirmDialog.isOpen}
title={confirmDialog.title}

View file

@ -3,7 +3,7 @@
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Separator } from '@/components/ui/separator';
import { useTServicoPedidoDetailsPagamentoController } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoDetailsControllerHook';
import { useTServicoPedidoDetailsPagamentoControllerHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoDetailsPagamentoControllerHook';
import TServicoPedidoDetailsPagamentoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsPagamentoInterface';
import FormatMoney from '@/shared/actions/money/FormatMoney';
import { ServicosPedidosSituacoesBadge } from '@/shared/components/servicosPedidosSituacoes/ServicosPedidosSituacoesBadge';
@ -15,7 +15,7 @@ export default function TServicoPedidoDetailsPagamento({
items,
}: TServicoPedidoDetailsPagamentoInterface) {
const { emolumento, taxa_judiciaria, valor_iss, fundesp, total } = useTServicoPedidoDetailsPagamentoController(items);
const { emolumento, taxa_judiciaria, valor_iss, fundesp, total } = useTServicoPedidoDetailsPagamentoControllerHook(items);
return (
<Card className="card-border">

View file

@ -116,7 +116,7 @@ export default function TServicoPedidoIndex() {
title={'Pedidos'}
description={'Pedidos de Autenticação/Reconhecimento'}
buttonText={'Novo pedido'}
href="/servicos/balcao/pedido"
href="/servicos/pedidos/pedido"
/>
{/* Tabela de andamentos */}
<TServicoPedidoTable

View file

@ -11,7 +11,7 @@ async function executeTServicoItemPedidoAtivarData(
return api.send({
method: Methods.PUT,
endpoint: `servicos/balcao/t_servico_itempedido/${data.servico_itempedido_id}/ativar`,
endpoint: `servicos/pedidos/t_servico_itempedido/${data.servico_itempedido_id}/ativar`,
body: data,
});
}

View file

@ -12,7 +12,7 @@ async function executeTServicoItemPedidoCancelarData(
return api.send({
method: Methods.PUT,
endpoint: `servicos/balcao/t_servico_itempedido/${data.servico_itempedido_id}/cancelar`,
endpoint: `servicos/pedidos/t_servico_itempedido/${data.servico_itempedido_id}/cancelar`,
body: data,
});
}

View file

@ -10,7 +10,7 @@ async function executeTServicoItemPedidoIndexData(
const api = new API();
return api.send({
method: Methods.GET,
endpoint: `servicos/balcao/t_servico_itempedido/pedido/${data.servico_pedido_id}`,
endpoint: `servicos/pedidos/t_servico_itempedido/pedido/${data.servico_pedido_id}`,
});
}

View file

@ -10,7 +10,7 @@ async function executeTServicoItemPedidoShowData(
const api = new API();
return api.send({
method: Methods.GET,
endpoint: `servicos/balcao/t_servico_itempedido/pedido/${data.servico_pedido_id}`,
endpoint: `servicos/pedidos/t_servico_itempedido/pedido/${data.servico_pedido_id}`,
});
}

View file

@ -11,7 +11,7 @@ async function executeTServicoPedidoAtivarData(
return api.send({
method: Methods.PUT,
endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id}/ativar`,
endpoint: `servicos/pedidos/t_servico_pedido/${data.servico_pedido_id}/ativar`,
body: data,
});
}

View file

@ -11,7 +11,7 @@ async function executeTServicoPedidoCancelarData(
return api.send({
method: Methods.PUT,
endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id}/cancelar`,
endpoint: `servicos/pedidos/t_servico_pedido/${data.servico_pedido_id}/cancelar`,
body: data,
});
}

View file

@ -12,7 +12,7 @@ async function executeTServicoPedidoDeleteData(
return api.send({
method: Methods.DELETE,
endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id}`,
endpoint: `servicos/pedidos/t_servico_pedido/${data.servico_pedido_id}`,
});
}

View file

@ -8,7 +8,7 @@ async function executeTServicoPedidoIndexData(): Promise<ApiResponseInterface> {
return api.send({
method: Methods.GET,
endpoint: `servicos/balcao/t_servico_pedido/`,
endpoint: `servicos/pedidos/t_servico_pedido/`,
});
}

View file

@ -8,7 +8,7 @@ async function executeTServicoPedidoLoadParamsData(): Promise<ApiResponseInterfa
return api.send({
method: Methods.GET,
endpoint: `servicos/balcao/t_servico_pedido/load-params`,
endpoint: `servicos/pedidos/t_servico_pedido/load-params`,
});
}

View file

@ -17,7 +17,7 @@ async function executeTServicoPedidoSaveData(
// Executa a requisição para a API com o método apropriado e envia os dados no corpo
return api.send({
method: isUpdate ? Methods.PUT : Methods.POST, // PUT se atualizar, POST se criar
endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id || ''}`, // endpoint dinâmico
endpoint: `servicos/pedidos/t_servico_pedido/${data.servico_pedido_id || ''}`, // endpoint dinâmico
body: data, // payload enviado para a API
});
}

View file

@ -10,7 +10,7 @@ async function executeTServicoPedidoShowData(
const api = new API();
return api.send({
method: Methods.GET,
endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id}`,
endpoint: `servicos/pedidos/t_servico_pedido/${data.servico_pedido_id}`,
});
}

View file

@ -0,0 +1,69 @@
'use client';
import { useCallback, useEffect, useState } from 'react';
import { useTServicoItemPedidoAtivarHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoAtivarHook';
import { useTServicoItemPedidoCancelarHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCancelarHook';
import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce';
import { useResponse } from '@/shared/components/response/ResponseContext';
export function useTServicoItemPedidoListControllerHook(items?: TServicoItemPedidoInterface[]) {
const { setResponse } = useResponse();
const { ativarTServicoItemPedido } = useTServicoItemPedidoAtivarHook();
const { cancelarTServicoItemPedido } = useTServicoItemPedidoCancelarHook();
const [localItems, setLocalItems] = useState<TServicoItemPedidoInterface[]>(items || []);
useEffect(() => {
setLocalItems(items || []);
}, [items]);
const handleSituacaoTServicoItemPedido = useCallback(
async (item: TServicoItemPedidoInterface) => {
if (!item.servico_itempedido_id) return;
let response: object;
switch (item.situacao) {
case 'C':
response = await ativarTServicoItemPedido({
servico_itempedido_id: item.servico_itempedido_id,
});
break;
case 'F':
response = await cancelarTServicoItemPedido({
servico_itempedido_id: item.servico_itempedido_id,
});
break;
default:
setResponse({
status: 422,
error: 'Situação',
detail: 'Situação não tratada',
});
return;
}
if (response?.situacao) {
setLocalItems((prev) =>
prev.map((i) =>
i.servico_itempedido_id === item.servico_itempedido_id ? { ...i, situacao: response.situacao } : i,
),
);
}
},
[ativarTServicoItemPedido, cancelarTServicoItemPedido, setResponse],
);
return {
localItems,
setLocalItems,
handleSituacaoTServicoItemPedido,
};
}

View file

@ -1,37 +1,175 @@
'use client';
import * as React from 'react';
import type { LucideIcon } from 'lucide-react';
import { BookmarkX, RotateCcwIcon } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import TServicoPedidoDetailsPagamentoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsPagamentoInterface';
import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook';
import { useTServicoPedidoAtivarHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoAtivarHook';
import { useTServicoPedidoCancelarHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoCancelarHook';
import { useTServicoPedidoShowHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook';
import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface';
import { useResponse } from '@/shared/components/response/ResponseContext';
export const useTServicoPedidoDetailsPagamentoController = (
items: TServicoPedidoDetailsPagamentoInterface['items']
) => {
type ConfirmDialogParams = {
title: string;
description: string;
message: string;
confirmText?: string;
cancelText?: string;
onConfirm?: () => void;
onCancel?: () => void;
};
// Somas por tipo de valor
const { emolumento, taxa_judiciaria, valor_iss, fundesp } = React.useMemo(() => {
return (items ?? []).reduce(
(acc, item) => {
if (item.situacao === 'F') {
acc.emolumento += item.emolumento;
acc.taxa_judiciaria += item.taxa_judiciaria;
acc.valor_iss += item.valor_iss;
acc.fundesp += item.fundesp;
}
return acc;
},
{ emolumento: 0, taxa_judiciaria: 0, valor_iss: 0, fundesp: 0 },
);
}, [items]);
export function useTServicoPedidoDetailsControllerHook(
servico_pedido_id: number,
) {
const { setResponse } = useResponse();
// Total exibido = soma dos quatro componentes
const total = emolumento + taxa_judiciaria + valor_iss + fundesp;
const { ativarTServicoPedido } = useTServicoPedidoAtivarHook();
const { cancelarTServicoPedido } = useTServicoPedidoCancelarHook();
const {
showTServicoPedido,
TServicoPedido,
setTServicoPedido,
} = useTServicoPedidoShowHook();
const { indexTServicoItemPedido, TServicoItemPedido } =
useTServicoItemPedidoIndexHook();
const [confirmDialog, setConfirmDialog] = useState({
isOpen: false,
title: '',
description: '',
message: '',
confirmText: 'Confirmar',
cancelText: 'Cancelar',
onConfirm: () => { },
onCancel: () => { },
});
useEffect(() => {
let mounted = true;
const loadPedido = async () => {
const response = await showTServicoPedido({ servico_pedido_id });
if (!mounted) return;
if (response?.servico_pedido_id) {
await indexTServicoItemPedido({
servico_pedido_id: response.servico_pedido_id,
});
}
};
if (servico_pedido_id) {
loadPedido();
}
return () => {
mounted = false;
};
}, [servico_pedido_id]);
const openConfirmDialog = useCallback(
({
title,
description,
message,
confirmText = 'Confirmar',
cancelText = 'Cancelar',
onConfirm,
onCancel,
}: ConfirmDialogParams) => {
setConfirmDialog({
isOpen: true,
title,
description,
message,
confirmText,
cancelText,
onConfirm: () => {
onConfirm?.();
setConfirmDialog((prev) => ({ ...prev, isOpen: false }));
},
onCancel: () => {
onCancel?.();
setConfirmDialog((prev) => ({ ...prev, isOpen: false }));
},
});
},
[],
);
/**
* ==========================
* AÇÕES DE SITUAÇÃO
* ==========================
*/
const handleSituacaoTServicoPedido = useCallback(
async (pedido?: TServicoPedidoInterface) => {
if (!pedido?.servico_pedido_id) return;
let response: any = null;
switch (pedido.situacao) {
case 'C':
response = await ativarTServicoPedido({
servico_pedido_id: pedido.servico_pedido_id,
});
break;
case 'F':
response = await cancelarTServicoPedido({
servico_pedido_id: pedido.servico_pedido_id,
});
break;
default:
setResponse({
status: 422,
error: 'Situação',
detail: 'Situação não tratada',
});
return;
}
if (response?.situacao) {
setTServicoPedido({
...pedido,
situacao: response.situacao,
});
}
},
[
ativarTServicoPedido,
cancelarTServicoPedido,
setResponse,
setTServicoPedido,
],
);
const isCancelado = String(TServicoPedido?.situacao) === 'C';
const actionLabel = isCancelado ? 'Ativar Pedido' : 'Estornar Pedido';
const actionIcon: LucideIcon = isCancelado
? RotateCcwIcon
: BookmarkX;
return {
emolumento,
taxa_judiciaria,
valor_iss,
fundesp,
total,
// dados
TServicoPedido,
TServicoItemPedido,
// ações
handleSituacaoTServicoPedido,
openConfirmDialog,
// dialog
confirmDialog,
// ui
isCancelado,
actionLabel,
actionIcon,
};
};
}

View file

@ -0,0 +1,37 @@
'use client';
import * as React from 'react';
import TServicoPedidoDetailsPagamentoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsPagamentoInterface';
export const useTServicoPedidoDetailsPagamentoControllerHook = (
items: TServicoPedidoDetailsPagamentoInterface['items']
) => {
// Somas por tipo de valor
const { emolumento, taxa_judiciaria, valor_iss, fundesp } = React.useMemo(() => {
return (items ?? []).reduce(
(acc, item) => {
if (item.situacao === 'F') {
acc.emolumento += item.emolumento;
acc.taxa_judiciaria += item.taxa_judiciaria;
acc.valor_iss += item.valor_iss;
acc.fundesp += item.fundesp;
}
return acc;
},
{ emolumento: 0, taxa_judiciaria: 0, valor_iss: 0, fundesp: 0 },
);
}, [items]);
// Total exibido = soma dos quatro componentes
const total = emolumento + taxa_judiciaria + valor_iss + fundesp;
return {
emolumento,
taxa_judiciaria,
valor_iss,
fundesp,
total,
};
};

View file

@ -84,7 +84,7 @@ export default function useTServicoPedidoFormControllerHook(servico_pedido_id?:
// Verifica se devo redirecionar a pagina
if (response?.servico_pedido_id > 0 && !shouldKeepFormOpen) {
router.replace(`/servicos/balcao/detalhes/${response.servico_pedido_id}`);
router.replace(`/servicos/pedidos/detalhes/${response.servico_pedido_id}`);
}
},
[saveTServicoPedido, shouldKeepFormOpen],
@ -147,7 +147,7 @@ export default function useTServicoPedidoFormControllerHook(servico_pedido_id?:
// Controle de redirecionamento
const handleConfirmCancel = useCallback(async () => {
// Redireciona o usuário
router.replace(`/servicos/balcao/`);
router.replace(`/servicos/pedidos/`);
}, []);
// Controle do formulário de cancelamento do Pedido