Vendaweb-portal/views/SalesDashboardView.tsx

324 lines
11 KiB
TypeScript

import React, { useState } from "react";
import { View } from "../types";
import DashboardDayView from "../components/dashboard/DashboardDayView";
import DashboardSellerView from "../components/dashboard/DashboardSellerView";
import OrdersView from "../components/dashboard/OrdersView";
import ProductsSoldView from "../components/dashboard/ProductsSoldView";
import PreorderView from "../components/dashboard/PreorderView";
import ConfirmDialog from "../components/ConfirmDialog";
import { shoppingService } from "../src/services/shopping.service";
interface SalesDashboardViewProps {
onNavigate: (view: View) => void;
onNewOrder?: () => void;
}
const SalesDashboardView: React.FC<SalesDashboardViewProps> = ({
onNavigate,
onNewOrder,
}) => {
const [activeTab, setActiveTab] = useState("dashboard");
const [showNewOrderDialog, setShowNewOrderDialog] = useState(false);
const [showContinueOrNewDialog, setShowContinueOrNewDialog] = useState(false);
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
// Verificar se há carrinho (itens no carrinho)
const hasCartItems = () => {
return localStorage.getItem("cart");
};
// Verificar se há dados do pedido atual
const hasOrderData = () => {
const hasCart = localStorage.getItem("cart");
const hasCustomer = localStorage.getItem("customer");
const hasAddress = localStorage.getItem("address");
const hasPaymentPlan = localStorage.getItem("paymentPlan");
const hasBilling = localStorage.getItem("billing");
const hasDataDelivery = localStorage.getItem("dataDelivery");
const hasInvoiceStore = localStorage.getItem("invoiceStore");
const hasPartner = localStorage.getItem("partner");
return (
hasCart ||
hasCustomer ||
hasAddress ||
hasPaymentPlan ||
hasBilling ||
hasDataDelivery ||
hasInvoiceStore ||
hasPartner
);
};
const handleNewOrderClick = () => {
// Se houver carrinho, perguntar se quer continuar ou iniciar novo
if (hasCartItems()) {
setShowContinueOrNewDialog(true);
return;
}
// Se não houver carrinho mas houver outros dados, mostrar confirmação normal
if (hasOrderData()) {
setShowNewOrderDialog(true);
return;
}
// Se não houver nenhum dado, limpar direto sem confirmação
if (onNewOrder) {
onNewOrder();
} else {
// Se não tiver onNewOrder, fazer a limpeza localmente
shoppingService.clearShoppingData();
onNavigate(View.PRODUCT_SEARCH);
}
};
const handleContinueOrder = () => {
// Fechar o dialog e navegar para /sales/home (já estamos na dashboard, apenas fechar)
setShowContinueOrNewDialog(false);
// Se já estamos na dashboard, não precisa navegar, apenas fechar o dialog
};
const handleStartNewOrder = () => {
// Fechar o dialog de continuar/iniciar e abrir o de confirmação
setShowContinueOrNewDialog(false);
setShowNewOrderDialog(true);
};
const handleConfirmNewOrder = () => {
if (onNewOrder) {
onNewOrder();
} else {
// Se não tiver onNewOrder, fazer a limpeza localmente
shoppingService.clearShoppingData();
onNavigate(View.PRODUCT_SEARCH);
}
setShowNewOrderDialog(false);
};
const sidebarItems = [
{
id: "new",
label: "Novo pedido",
primary: true,
action: () => onNavigate(View.PRODUCT_SEARCH),
},
{
id: "dashboard",
label: "Dashboard Venda dia",
icon: "M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z",
},
{
id: "dashboardseller",
label: "Dashboard Vendedor",
icon: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z",
},
{
id: "orders",
label: "Pedidos de venda",
icon: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2",
},
{
id: "product-order",
label: "Produtos Vendidos",
icon: "M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z",
},
{
id: "preorder",
label: "Orçamentos pendentes",
icon: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z",
primary: false,
},
];
return (
<div className="flex h-full bg-[#f8fafc] relative">
{/* Overlay para mobile quando sidebar está aberto */}
{isSidebarOpen && (
<div
className="fixed inset-0 bg-black/50 z-40 lg:hidden"
onClick={() => setIsSidebarOpen(false)}
/>
)}
{/* Sidebar Modernizada - Drawer em mobile, sidebar em desktop */}
<aside
className={`fixed lg:relative inset-y-0 left-0 z-50 lg:z-auto w-72 bg-white border-r border-slate-200 flex flex-col p-4 lg:p-6 overflow-y-auto transform transition-transform duration-300 ease-out ${
isSidebarOpen ? "translate-x-0" : "-translate-x-full lg:translate-x-0"
}`}
>
{/* Botão fechar em mobile */}
<div className="flex justify-end mb-4 lg:hidden">
<button
onClick={() => setIsSidebarOpen(false)}
className="p-2 text-slate-400 hover:text-slate-600 rounded-lg"
>
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<div className="mb-6 lg:mb-8">
<button
onClick={() => {
handleNewOrderClick();
setIsSidebarOpen(false);
}}
className="w-full bg-orange-500 text-white p-3 lg:p-4 rounded-2xl font-extrabold uppercase text-xs tracking-widest shadow-lg shadow-orange-500/20 hover:bg-orange-600 transition-all flex items-center justify-center group touch-manipulation"
>
<svg
className="w-5 h-5 mr-2 group-hover:rotate-90 transition-transform"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.5"
d="M12 4v16m8-8H4"
/>
</svg>
Novo Pedido
</button>
</div>
<nav className="flex-1 space-y-2">
{sidebarItems.slice(1).map((item) => (
<button
key={item.id}
onClick={() => {
if (item.action) {
item.action();
} else {
setActiveTab(item.id);
}
setIsSidebarOpen(false); // Fechar sidebar em mobile após seleção
}}
className={`w-full flex items-center px-4 py-3 lg:py-4 rounded-2xl text-sm font-bold transition-all touch-manipulation ${
activeTab === item.id
? "bg-[#002147] text-white shadow-xl shadow-blue-900/10"
: item.id === "preorder"
? "text-blue-600 hover:bg-blue-50 border border-blue-200"
: "text-slate-500 hover:bg-slate-50"
}`}
>
<svg
className="w-5 h-5 mr-3"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d={item.icon}
/>
</svg>
{item.label}
</button>
))}
</nav>
</aside>
{/* Botão para abrir sidebar em mobile */}
<button
onClick={() => setIsSidebarOpen(true)}
className="fixed top-20 left-4 z-30 lg:hidden bg-white p-3 rounded-xl shadow-lg border border-slate-200 text-slate-600 hover:bg-slate-50 transition-all touch-manipulation"
>
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
</button>
{/* Área de Conteúdo */}
<main className="flex-1 p-3 lg:p-6 overflow-auto custom-scrollbar">
<div className="max-w-[1400px] mx-auto">
{activeTab === "dashboard" && <DashboardDayView />}
{activeTab === "orders" && <OrdersView />}
{activeTab === "dashboardseller" && <DashboardSellerView />}
{activeTab === "product-order" && <ProductsSoldView />}
{activeTab === "preorder" && <PreorderView />}
</div>
</main>
{/* Dialog - Continuar ou Iniciar Novo Pedido */}
<ConfirmDialog
isOpen={showContinueOrNewDialog}
onClose={handleContinueOrder}
onConfirm={handleStartNewOrder}
type="info"
title="Carrinho Existente"
message={
<>
Você possui um carrinho com itens.
<br />
<br />
Deseja iniciar um novo pedido e limpar todos os dados do pedido
atual?
</>
}
confirmText="Iniciar Novo Pedido"
cancelText="Cancelar"
/>
{/* Dialog de Confirmação - Novo Pedido */}
<ConfirmDialog
isOpen={showNewOrderDialog}
onClose={() => setShowNewOrderDialog(false)}
onConfirm={handleConfirmNewOrder}
type="warning"
title="Novo Pedido"
message={
<>
Deseja iniciar um novo pedido?
<br />
<br />
<span className="text-sm font-bold text-slate-700">
Todos os dados do pedido atual serão perdidos:
</span>
<ul className="text-xs text-slate-600 mt-2 space-y-1 list-disc list-inside">
<li>Itens do carrinho</li>
<li>Dados do cliente</li>
<li>Endereço de entrega</li>
<li>Plano de pagamento</li>
<li>Dados financeiros</li>
<li>Informações de entrega</li>
</ul>
<br />
<span className="text-xs text-slate-400 block">
Esta ação não pode ser desfeita.
</span>
</>
}
confirmText="Sim, Iniciar Novo Pedido"
cancelText="Cancelar"
/>
</div>
);
};
export default SalesDashboardView;