Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 10 additions & 9 deletions src/components/inventory/risk/RiskTooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { forwardRef } from 'react';
import { cn } from '@/lib/utils';

interface RiskChartDataPoint {
fullDate?: string;
Expand All @@ -25,36 +24,38 @@ export const RiskTooltip = forwardRef<
<div className="mb-2 border-b border-white/5 pb-1.5">
<p className="text-tooltip-header">{data.fullDate}</p>
</div>

<div className="space-y-1.5">
<div className="flex items-center justify-between gap-4">
<span className="text-white/50">Estoque Atual</span>
<span className="font-bold tabular-nums">
{data.stockClose != null ? data.stockClose.toLocaleString('pt-BR') : '—'}
{typeof data.stockClose === 'number' ? data.stockClose.toLocaleString('pt-BR') : '—'}
</span>
</div>

{(data.depleted || data.restocked) && (
<div className="grid grid-cols-2 gap-2 border-t border-white/5 pt-1.5">
{data.depleted !== null && data.depleted > 0 && (
{typeof data.depleted === 'number' && data.depleted > 0 && (
<div className="space-y-0.5">
<span className="text-tooltip-header !text-destructive/80">Saídas</span>
<p className="font-bold text-destructive tabular-nums">-{data.depleted}</p>
<p className="font-bold tabular-nums text-destructive">-{data.depleted}</p>
</div>
)}
{data.restocked !== null && data.restocked > 0 && (
{typeof data.restocked === 'number' && data.restocked > 0 && (
<div className="space-y-0.5">
<span className="text-tooltip-header !text-primary/80">Entradas</span>
<p className="font-bold text-primary tabular-nums">+{data.restocked}</p>
<p className="font-bold tabular-nums text-primary">+{data.restocked}</p>
</div>
)}
</div>
)}

{data.restockDetected && (
<div className="mt-1 flex items-center gap-1.5 rounded bg-primary/10 px-1 py-0.5 border border-primary/20">
<div className="mt-1 flex items-center gap-1.5 rounded border border-primary/20 bg-primary/10 px-1 py-0.5">
<div className="h-1 w-1 animate-pulse rounded-full bg-primary" />
<span className="text-tooltip-header !text-primary !opacity-100">Reposição Detectada</span>
<span className="text-tooltip-header !text-primary !opacity-100">
Reposição Detectada
</span>
</div>
)}
</div>
Expand Down
20 changes: 9 additions & 11 deletions src/components/products/ProductCategoryBadges.test.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { ComponentProps } from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { ProductCategoryBadges } from './ProductCategoryBadges';
import { BrowserRouter } from 'react-router-dom';
import { TooltipProvider } from '@/components/ui/tooltip';
import { describe, it, expect, vi, beforeEach } from 'vitest';


const mockNavigate = vi.fn();

// Mock do hook useCategoryIcons
Expand All @@ -25,8 +25,7 @@ vi.mock('react-router-dom', async () => {
};
});

const defaultProps = {

const defaultProps: ComponentProps<typeof ProductCategoryBadges> = {
category: { id: 'cat-1', name: 'Squeeze' },
groups: [
{ id: 'cat-2', name: 'Garrafas' },
Expand All @@ -47,11 +46,10 @@ const renderComponent = (props = defaultProps) => {
<TooltipProvider>
<ProductCategoryBadges {...props} />
</TooltipProvider>
</BrowserRouter>
</BrowserRouter>,
);
};


describe('ProductCategoryBadges', () => {
beforeEach(() => {
vi.clearAllMocks();
Expand All @@ -68,15 +66,15 @@ describe('ProductCategoryBadges', () => {
renderComponent();
const mainCategory = screen.getByText('Squeeze').parentElement;
if (mainCategory) fireEvent.click(mainCategory);

expect(mockNavigate).toHaveBeenCalledWith('/filtros?categories=uuid-123');
});

it('deve usar o id local se categoryUuid não for fornecido', () => {
renderComponent({ ...defaultProps, categoryUuid: null });
const mainCategory = screen.getByText('Squeeze').parentElement;
if (mainCategory) fireEvent.click(mainCategory);

expect(mockNavigate).toHaveBeenCalledWith('/filtros?categories=cat-1');
});

Expand Down Expand Up @@ -130,10 +128,10 @@ describe('ProductCategoryBadges', () => {
});

it('não deve renderizar nada se não houver categorias', () => {
const { container } = renderComponent({
...defaultProps,
category: null as any,
groups: []
const { container } = renderComponent({
...defaultProps,
category: null as unknown as ComponentProps<typeof ProductCategoryBadges>['category'],
groups: [],
});
expect(container.firstChild).toBeNull();
});
Expand Down
10 changes: 8 additions & 2 deletions src/contexts/ThemeContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ interface ThemeProviderProps {
children: ReactNode;
defaultTheme?: Theme;
storageKey?: string;
tooltipStorageKey?: string;
}

export function ThemeProvider({
Expand Down Expand Up @@ -117,8 +118,11 @@ export function ThemeProvider({
});
};

if (typeof document !== 'undefined' && 'startViewTransition' in document) {
(document as any).startViewTransition(apply);
const docWithViewTransition = document as Document & {
startViewTransition?: (callback: () => void) => void;
};
if (typeof document !== 'undefined' && docWithViewTransition.startViewTransition) {
docWithViewTransition.startViewTransition(apply);
} else {
apply();
}
Comment on lines +121 to 128
Expand Down Expand Up @@ -159,8 +163,10 @@ export function useTheme() {
return {
theme: 'light',
actualTheme: 'light',
tooltipStyle: 'standard',
setTheme: () => {},
toggleTheme: () => {},
setTooltipStyle: () => {},
isFallback: true,
} as ThemeContextType;
}
Expand Down
1 change: 1 addition & 0 deletions src/pages/filters/useFiltersPageState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ export function useFiltersPageState() {
hasCategoryFilter,
categoryFilteredProductIds,
isLoadingCategoryFilter,
categoryFilterError,
hasColorFilter,
colorFilteredProductIds,
isLoadingColorFilter,
Expand Down
55 changes: 29 additions & 26 deletions src/tests/B2BProductDetailFlow.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { render, screen, fireEvent } from '@testing-library/react';
import { ProductDetailHero } from '@/pages/products/product-detail/ProductDetailHero';
import { BrowserRouter } from 'react-router-dom';
import { TooltipProvider } from '@/components/ui/tooltip';
Expand Down Expand Up @@ -38,7 +38,7 @@ vi.mock('@/hooks/products/useCategoryIcons', () => ({
}));

vi.mock('@/components/products/SingleVariantPicker', () => ({
SingleVariantPicker: ({ onSelect }: { onSelect: (v: any) => void }) => (
SingleVariantPicker: ({ onSelect }: { onSelect: (v: unknown) => void }) => (
<button onClick={() => onSelect({ color_name: 'Azul', color_hex: '#00F' })}>
Mock Variant
</button>
Expand All @@ -62,20 +62,20 @@ const mockProduct: Product = {
category: { id: 1, name: 'Brindes' },
category_id: 'cat-uuid-1',
supplier: { id: 'supp-1', name: 'Fornecedor A' },
tags: {
publicoAlvo: ['Executivos'],
datasComemorativas: [],
endomarketing: [],
ramo: [],
nicho: []
tags: {
publicoAlvo: ['Executivos'],
datasComemorativas: [],
endomarketing: [],
ramo: [],
nicho: [],
},
priceUpdatedAt: new Date().toISOString(),
leadTimeDays: 5,
} as any;
} as unknown as Product;
Comment on lines 71 to +74

const queryClient = new QueryClient();

const renderPDP = (tags = {}) => {
const renderPDP = () => {
return render(
<QueryClientProvider client={queryClient}>
<BrowserRouter>
Expand All @@ -92,11 +92,10 @@ const renderPDP = (tags = {}) => {
onOpenPackagingModal={() => {}}
onOpenFutureStock={() => {}}
onOpenSupplierComparison={() => {}}
tags={tags}
/>
</TooltipProvider>
</BrowserRouter>
</QueryClientProvider>
</QueryClientProvider>,
);
};

Expand All @@ -107,47 +106,51 @@ describe('B2B Product Detail Flow Integration', () => {

it('Fluxo 1: Adicionar ao Carrinho (Quick Add)', async () => {
renderPDP();

const cartButton = screen.getByText('Carrinho');
fireEvent.click(cartButton);

const variantButton = await screen.findByText('Mock Variant');
fireEvent.click(variantButton);

const confirmAdd = await screen.findByTestId('product-card-add-to-cart');
fireEvent.click(confirmAdd);

expect(mockAddToActiveCart).toHaveBeenCalledWith(expect.objectContaining({
product_id: 'prod-123',
quantity: 50,
color_name: 'Azul'
}));
expect(mockAddToActiveCart).toHaveBeenCalledWith(
expect.objectContaining({
product_id: 'prod-123',
quantity: 50,
color_name: 'Azul',
}),
);
});

it('Fluxo 2: Navegação por Categorias', () => {
renderPDP();
const categoryBadge = screen.getByText('Brindes');
fireEvent.click(categoryBadge.parentElement!);

expect(mockNavigate).toHaveBeenCalledWith(expect.stringContaining('/filtros?categories=cat-uuid-1'));

expect(mockNavigate).toHaveBeenCalledWith(
expect.stringContaining('/filtros?categories=cat-uuid-1'),
);
});

it('Fluxo 3: Abrir Modais de Ação Rápida (Preços)', async () => {
renderPDP();

const pricesButton = screen.getByText('Preços');
fireEvent.click(pricesButton);

const title = await screen.findByText(/Tabela de Preços/i);
expect(title).toBeDefined();
});

it('Fluxo 4: Verificação de Tags e Nichos (Indicação)', async () => {
renderPDP({ 'Público-Alvo': ['Executivos'] });
renderPDP();

const indicationButton = screen.getByText('Indicação');
fireEvent.click(indicationButton);

const modalTitle = await screen.findByText(/Indicado para/i);
expect(modalTitle).toBeDefined();
});
Expand Down
6 changes: 6 additions & 0 deletions src/tests/ThemeInitializer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ describe('ThemeInitializer', () => {
const mockContext = {
theme: 'light' as const,
actualTheme: 'light' as const,
tooltipStyle: 'standard' as const,
setTheme: vi.fn(),
toggleTheme: vi.fn(),
setTooltipStyle: vi.fn(),
};

render(
Expand All @@ -54,8 +56,10 @@ describe('ThemeInitializer', () => {
value={{
theme: 'light',
actualTheme: 'light',
tooltipStyle: 'standard',
setTheme: vi.fn(),
toggleTheme: vi.fn(),
setTooltipStyle: vi.fn(),
}}
>
<ThemeInitializer />
Expand All @@ -70,8 +74,10 @@ describe('ThemeInitializer', () => {
value={{
theme: 'dark',
actualTheme: 'dark',
tooltipStyle: 'standard',
setTheme: vi.fn(),
toggleTheme: vi.fn(),
setTooltipStyle: vi.fn(),
}}
>
<ThemeInitializer />
Expand Down
Loading