- Resumo do Orçamento
+ Resumo do Orçamento
{isCalculating && }
@@ -165,7 +165,7 @@ export function QuantityAndResult({
- Código de orçamento - clique para copiar
+ Código de orçamento - clique para copiar
@@ -177,7 +177,7 @@ export function QuantityAndResult({
{error ? (
-
Erro ao calcular preço
+
Erro ao calcular preço
{error}
) : (
@@ -193,7 +193,7 @@ export function QuantityAndResult({
{priceData && (
<>
- {/* Gravação */}
+ {/* Gravação */}
{priceData.technique}
@@ -209,12 +209,12 @@ export function QuantityAndResult({
{formatCurrency(priceData.subtotal_pecas)}
- {/* Faturamento mÃnimo aplicado */}
+ {/* Faturamento mínimo aplicado */}
{priceData.minimum_applied && (
- Faturamento mÃnimo aplicado
+ Faturamento mínimo aplicado
{formatCurrency(priceData.faturamento_minimo_gravacao)}
@@ -222,9 +222,9 @@ export function QuantityAndResult({
)}
- {/* Subtotal gravação */}
+ {/* Subtotal gravação */}
-
Subtotal gravação
+
Subtotal gravação
0 && (
- Prazo estimado: {priceData.production_days} dias úteis
+ Prazo estimado: {priceData.production_days} dias úteis
)}
@@ -271,7 +271,7 @@ export function QuantityAndResult({
Markup: {priceData.markup_percent}% |
- Preço mÃn. unitário: {formatCurrency(priceData.preco_minimo_unitario)}
+ Preço mín. unitário: {formatCurrency(priceData.preco_minimo_unitario)}
)}
@@ -280,14 +280,14 @@ export function QuantityAndResult({
- {/* Info box sobre a lógica v5.1 */}
+ {/* Info box sobre a lógica v5.1 */}
{priceData && (
-
📊 Sistema de Preços v5.1
+
📊 Sistema de Preços v5.1
- O setup é aplicado como faturamento mÃnimo, não é somado ao total.
- Se o subtotal das peças for menor que o mÃnimo, o total será igual ao faturamento
- mÃnimo.
+ O setup é aplicado como faturamento mínimo, não é somado ao total.
+ Se o subtotal das peças for menor que o mínimo, o total será igual ao faturamento
+ mínimo.
)}
diff --git a/src/components/pricing/simulator/TechniqueSelector.tsx b/src/components/pricing/simulator/TechniqueSelector.tsx
index f04aa246d..9980b25c9 100644
--- a/src/components/pricing/simulator/TechniqueSelector.tsx
+++ b/src/components/pricing/simulator/TechniqueSelector.tsx
@@ -114,7 +114,7 @@ export function TechniqueSelector({
return (
-
Erro ao carregar técnicas
+
Erro ao carregar técnicas
);
}
@@ -123,7 +123,7 @@ export function TechniqueSelector({
return (
-
Este produto não possui técnicas de personalização cadastradas
+
Este produto não possui técnicas de personalização cadastradas
);
}
@@ -158,14 +158,14 @@ export function TechniqueSelector({
wizardStep >= 3 ? 'bg-primary/20 font-medium text-primary' : 'bg-muted',
)}
>
- Técnica
+ Técnica
{/* Step 1: Component Selection */}
{!selectedComponent && (
-
Qual parte do produto será personalizada?
+
Qual parte do produto será personalizada?
{components.map((comp, idx) => (
@@ -196,7 +196,7 @@ export function TechniqueSelector({
- Onde será a gravação em "{selectedComponent.name}"?
+ Onde será a gravação em "{selectedComponent.name}"?
@@ -239,7 +239,7 @@ export function TechniqueSelector({
{selectedComponent && selectedLocation && !selectedTechnique && (
-
Qual técnica de gravação?
+
Qual técnica de gravação?
@@ -259,9 +259,9 @@ export function TechniqueSelector({
{tech.areaName || tech.techniqueCode}
- {tech.techniqueCode && `Código: ${tech.techniqueCode}`}
- {tech.maxColors && ` • Até ${tech.maxColors} cores`}
- {tech.areaCm2 && ` • ${tech.areaCm2}cm²`}
+ {tech.techniqueCode && `Código: ${tech.techniqueCode}`}
+ {tech.maxColors && ` • Até ${tech.maxColors} cores`}
+ {tech.areaCm2 && ` • ${tech.areaCm2}cm²`}
@@ -284,7 +284,7 @@ export function TechniqueSelector({
- Técnica selecionada
+ Técnica selecionada
-
Técnica
+
Técnica
{selectedTechnique.techniqueName}
@@ -317,13 +317,13 @@ export function TechniqueSelector({
{selectedTechnique.maxWidth && selectedTechnique.maxHeight && (
- Ãrea máx: {selectedTechnique.maxWidth}x{selectedTechnique.maxHeight}mm
+ Área máx: {selectedTechnique.maxWidth}x{selectedTechnique.maxHeight}mm
)}
{selectedTechnique.maxColors && (
- Até {selectedTechnique.maxColors} cores
+ Até {selectedTechnique.maxColors} cores
)}
diff --git a/src/hooks/voice/processTranscript.ts b/src/hooks/voice/processTranscript.ts
index cdc8d1757..bd353eaa9 100644
--- a/src/hooks/voice/processTranscript.ts
+++ b/src/hooks/voice/processTranscript.ts
@@ -47,7 +47,7 @@ function validateAction(action: VoiceAgentAction): VoiceAgentAction {
if (!action?.action || !action?.response) {
return {
action: 'answer',
- response: action?.response || 'Desculpe, não entendi. Pode repetir?',
+ response: action?.response || 'Desculpe, não entendi. Pode repetir?',
data: {},
};
}
diff --git a/src/lib/kit-builder/mock-data.ts b/src/lib/kit-builder/mock-data.ts
index 2774c9e18..8f63e362d 100644
--- a/src/lib/kit-builder/mock-data.ts
+++ b/src/lib/kit-builder/mock-data.ts
@@ -55,7 +55,7 @@ export const MOCK_BOXES: KitBox[] = [
internalHeight: 18,
internalDepth: 12,
internalVolume: 6048,
- material: 'Papelão Revestido',
+ material: 'Papelão Revestido',
weight: 280,
},
];
@@ -63,7 +63,7 @@ export const MOCK_BOXES: KitBox[] = [
export const MOCK_ITEMS: KitItem[] = [
{
id: 'mock-item-1',
- name: 'Caneca Cerâmica 350ml',
+ name: 'Caneca Cerâmica 350ml',
sku: 'CAN-CER-350',
imageUrl: null,
price: 18.9,
@@ -72,7 +72,7 @@ export const MOCK_ITEMS: KitItem[] = [
depth: 9,
volume: 810,
weight: 320,
- material: 'Cerâmica',
+ material: 'Cerâmica',
category: 'Canecas',
quantity: 1,
isOptional: false,
@@ -90,7 +90,7 @@ export const MOCK_ITEMS: KitItem[] = [
depth: 2,
volume: 630,
weight: 250,
- material: 'Papel / Couro Sintético',
+ material: 'Papel / Couro Sintético',
category: 'Cadernos',
quantity: 1,
isOptional: false,
@@ -117,7 +117,7 @@ export const MOCK_ITEMS: KitItem[] = [
},
{
id: 'mock-item-4',
- name: 'Garrafa Térmica 500ml',
+ name: 'Garrafa Térmica 500ml',
sku: 'GAR-TERM-500',
imageUrl: null,
price: 35.0,
@@ -126,7 +126,7 @@ export const MOCK_ITEMS: KitItem[] = [
depth: 7,
volume: 1225,
weight: 280,
- material: 'Aço Inox',
+ material: 'Aço Inox',
category: 'Garrafas',
quantity: 1,
isOptional: true,
@@ -145,7 +145,7 @@ export const MOCK_ITEMS: KitItem[] = [
volume: 1440,
weight: 80,
material: 'Nylon',
- category: 'Acessórios',
+ category: 'Acessórios',
quantity: 1,
isOptional: true,
isReplaceable: false,
@@ -162,7 +162,7 @@ export const MOCK_ITEMS: KitItem[] = [
depth: 1,
volume: 12,
weight: 15,
- material: 'Plástico / Metal',
+ material: 'Plástico / Metal',
category: 'Tecnologia',
quantity: 1,
isOptional: true,
diff --git a/src/lib/kit-builder/price-calculator.ts b/src/lib/kit-builder/price-calculator.ts
index 88c45e5bf..cd2eae2c5 100644
--- a/src/lib/kit-builder/price-calculator.ts
+++ b/src/lib/kit-builder/price-calculator.ts
@@ -1,16 +1,16 @@
/**
* Kit Builder - Price Calculator
- * Cálculos de preço para kits
+ * Cálculos de preço para kits
*/
import type { KitItem, KitBox, KitPersonalization } from './types';
// ============================================
-// CÃLCULOS DE PREÇO
+// CÁLCULOS DE PREÇO
// ============================================
/**
- * Calcula o preço total da caixa
+ * Calcula o preço total da caixa
*/
export function calculateBoxPrice(box: KitBox | null, quantity: number = 1): number {
if (!box) return 0;
@@ -18,7 +18,7 @@ export function calculateBoxPrice(box: KitBox | null, quantity: number = 1): num
}
/**
- * Calcula o preço total dos itens
+ * Calcula o preço total dos itens
*/
export function calculateItemsPrice(items: KitItem[]): number {
return items.reduce((total, item) => {
@@ -27,7 +27,7 @@ export function calculateItemsPrice(items: KitItem[]): number {
}
/**
- * Calcula o preço estimado de personalização
+ * Calcula o preço estimado de personalização
*/
export function calculatePersonalizationPrice(
personalization: KitPersonalization,
@@ -36,12 +36,12 @@ export function calculatePersonalizationPrice(
): number {
let total = 0;
- // Personalização da caixa
+ // Personalização da caixa
if (personalization.box.enabled && personalization.box.estimatedPrice) {
total += personalization.box.estimatedPrice * quantity;
}
- // Personalização dos itens
+ // Personalização dos itens
items.forEach((item) => {
const itemPersonalization = personalization.items[item.id];
if (itemPersonalization?.enabled && itemPersonalization.estimatedPrice) {
@@ -53,7 +53,7 @@ export function calculatePersonalizationPrice(
}
/**
- * Calcula o preço total do kit
+ * Calcula o preço total do kit
*/
export function calculateTotalKitPrice(
box: KitBox | null,
@@ -88,7 +88,7 @@ export function calculateTotalKitPrice(
}
/**
- * Calcula economia em relação à compra individual
+ * Calcula economia em relação à compra individual
*/
export function calculateSavings(
kitPrice: number,
@@ -115,7 +115,7 @@ import { formatCurrency } from '@/lib/format';
export { formatCurrency };
/**
- * Formata preço por unidade
+ * Formata preço por unidade
*/
export function formatUnitPrice(total: number, quantity: number): string {
if (quantity === 0) return formatCurrency(0);
@@ -135,7 +135,7 @@ export interface PriceBreakdownItem {
}
/**
- * Gera breakdown detalhado do preço
+ * Gera breakdown detalhado do preço
*/
export function generatePriceBreakdown(
box: KitBox | null,
@@ -154,10 +154,10 @@ export function generatePriceBreakdown(
totalPrice: box.price * kitQuantity,
});
- // Personalização da caixa
+ // Personalização da caixa
if (personalization.box.enabled && personalization.box.estimatedPrice) {
breakdown.push({
- label: `↳ Gravação: ${personalization.box.techniqueName || 'Personalização'}`,
+ label: `↳ Gravação: ${personalization.box.techniqueName || 'Personalização'}`,
quantity: kitQuantity,
unitPrice: personalization.box.estimatedPrice,
totalPrice: personalization.box.estimatedPrice * kitQuantity,
@@ -176,11 +176,11 @@ export function generatePriceBreakdown(
totalPrice: item.price * totalQty,
});
- // Personalização do item
+ // Personalização do item
const itemPersonalization = personalization.items[item.id];
if (itemPersonalization?.enabled && itemPersonalization.estimatedPrice) {
breakdown.push({
- label: `↳ Gravação: ${itemPersonalization.techniqueName || 'Personalização'}`,
+ label: `↳ Gravação: ${itemPersonalization.techniqueName || 'Personalização'}`,
quantity: totalQty,
unitPrice: itemPersonalization.estimatedPrice,
totalPrice: itemPersonalization.estimatedPrice * totalQty,
diff --git a/src/lib/kit-builder/volume-calculator.ts b/src/lib/kit-builder/volume-calculator.ts
index 689d216c1..f8173bfa9 100644
--- a/src/lib/kit-builder/volume-calculator.ts
+++ b/src/lib/kit-builder/volume-calculator.ts
@@ -1,6 +1,6 @@
/**
* Kit Builder - Volume Calculator
- * Utilitários para cálculo e validação de volume
+ * Utilitários para cálculo e validação de volume
*/
import type { KitBox, KitItem, CompatibilityResult } from './types';
@@ -9,25 +9,25 @@ import type { KitBox, KitItem, CompatibilityResult } from './types';
// CONSTANTES
// ============================================
-// Fator de folga para empacotamento (itens não ocupam 100% do volume)
-const PACKING_EFFICIENCY = 0.75; // 75% de eficiência
+// Fator de folga para empacotamento (itens não ocupam 100% do volume)
+const PACKING_EFFICIENCY = 0.75; // 75% de eficiência
// Limite de alerta de volume
const VOLUME_WARNING_THRESHOLD = 0.85; // 85%
// ============================================
-// CÃLCULOS BÃSICOS
+// CÁLCULOS BÁSICOS
// ============================================
/**
- * Calcula o volume de um objeto em cm³
+ * Calcula o volume de um objeto em cm³
*/
export function calculateVolume(width: number, height: number, depth: number): number {
return width * height * depth;
}
/**
- * Calcula o volume utilizável de uma caixa (com fator de eficiência)
+ * Calcula o volume utilizável de uma caixa (com fator de eficiência)
*/
export function calculateUsableVolume(box: KitBox): number {
return box.internalVolume * PACKING_EFFICIENCY;
@@ -69,18 +69,18 @@ export function checkItemFits(
const percentAfterAdd = (totalVolumeAfter / usableVolume) * 100;
- // Verifica se o item cabe em alguma das 6 orientações possÃveis
+ // Verifica se o item cabe em alguma das 6 orientações possíveis
const itemDims = [item.width, item.height, item.depth].sort((a, b) => a - b);
const boxDims = [box.internalWidth, box.internalHeight, box.internalDepth].sort((a, b) => a - b);
- // Se as dimensões ordenadas do item excedem as da caixa, não cabe em nenhuma orientação
+ // Se as dimensões ordenadas do item excedem as da caixa, não cabe em nenhuma orientação
const fitsAnyOrientation =
itemDims[0] <= boxDims[0] && itemDims[1] <= boxDims[1] && itemDims[2] <= boxDims[2];
if (!fitsAnyOrientation) {
return {
fits: false,
- reason: `Dimensões do item (${item.width}×${item.height}×${item.depth}cm) não cabem na caixa (${box.internalWidth}×${box.internalHeight}×${box.internalDepth}cm) em nenhuma orientação`,
+ reason: `Dimensões do item (${item.width}×${item.height}×${item.depth}cm) não cabem na caixa (${box.internalWidth}×${box.internalHeight}×${box.internalDepth}cm) em nenhuma orientação`,
};
}
@@ -88,7 +88,7 @@ export function checkItemFits(
if (totalVolumeAfter > usableVolume) {
return {
fits: false,
- reason: `Volume total excederá a capacidade da caixa (${Math.round(percentAfterAdd)}% > 100%)`,
+ reason: `Volume total excederá a capacidade da caixa (${Math.round(percentAfterAdd)}% > 100%)`,
volumeAfterAdd: totalVolumeAfter,
percentAfterAdd,
};
@@ -102,14 +102,14 @@ export function checkItemFits(
}
/**
- * Verifica se a caixa está no limite de alerta
+ * Verifica se a caixa está no limite de alerta
*/
export function isNearCapacity(usagePercent: number): boolean {
return usagePercent >= VOLUME_WARNING_THRESHOLD * 100;
}
/**
- * Verifica se a caixa está cheia
+ * Verifica se a caixa está cheia
*/
export function isAtCapacity(usagePercent: number): boolean {
return usagePercent >= 100;
@@ -120,17 +120,17 @@ export function isAtCapacity(usagePercent: number): boolean {
// ============================================
/**
- * Formata volume para exibição
+ * Formata volume para exibição
*/
export function formatVolume(volumeCm3: number): string {
if (volumeCm3 >= 1000) {
return `${(volumeCm3 / 1000).toFixed(1)}L`;
}
- return `${Math.round(volumeCm3)}cm³`;
+ return `${Math.round(volumeCm3)}cm³`;
}
/**
- * Formata dimensões para exibição
+ * Formata dimensões para exibição
*/
export function formatDimensions(width: number, height: number, depth: number): string {
return `${width} × ${height} × ${depth} cm`;
@@ -152,7 +152,7 @@ export function getVolumeStatusLabel(percent: number): string {
if (percent >= 100) return 'Cheio';
if (percent >= 85) return 'Quase cheio';
if (percent >= 50) return 'Bom uso';
- if (percent > 0) return 'Espaço disponÃvel';
+ if (percent > 0) return 'Espaço disponível';
return 'Vazio';
}
@@ -161,7 +161,7 @@ export function getVolumeStatusLabel(percent: number): string {
// ============================================
/**
- * Tenta extrair dimensões de uma string de dimensões
+ * Tenta extrair dimensões de uma string de dimensões
* Formatos suportados: "10x20x5", "10 x 20 x 5", "10×20×5"
*/
export function parseDimensionsString(
@@ -169,14 +169,14 @@ export function parseDimensionsString(
): { width: number; height: number; depth: number } | null {
if (!dimensionsStr) return null;
- // Remove espaços extras e normaliza separadores
+ // Remove espaços extras e normaliza separadores
const normalized = dimensionsStr
.toLowerCase()
.replace(/\s+/g, '')
.replace(/×/g, 'x')
.replace(/cm/g, '');
- // Tenta match com padrão NxNxN
+ // Tenta match com padrão NxNxN
const match = normalized.match(/(\d+(?:\.\d+)?)[x×](\d+(?:\.\d+)?)[x×](\d+(?:\.\d+)?)/);
if (match) {
@@ -191,7 +191,7 @@ export function parseDimensionsString(
}
/**
- * Extrai dimensões de um produto externo
+ * Extrai dimensões de um produto externo
*/
export function extractProductDimensions(product: {
dimensions?:
@@ -208,7 +208,7 @@ export function extractProductDimensions(product: {
internal_width_cm?: number | null;
internal_height_cm?: number | null;
}): { width: number; height: number; depth: number } | null {
- // Primeiro tenta campos especÃficos de dimensão interna (para caixas)
+ // Primeiro tenta campos específicos de dimensão interna (para caixas)
if (product.internal_width_cm && product.internal_length_cm && product.internal_height_cm) {
return {
width: product.internal_width_cm,
@@ -217,7 +217,7 @@ export function extractProductDimensions(product: {
};
}
- // Depois tenta campos de dimensão externa
+ // Depois tenta campos de dimensão externa
if (product.box_width_cm && product.box_length_cm && product.box_height_cm) {
return {
width: product.box_width_cm,
@@ -258,7 +258,7 @@ export function extractProductDimensions(product: {
}
}
- // Por fim tenta parsear string de dimensões
+ // Por fim tenta parsear string de dimensões
if (typeof product.dimensions === 'string') {
return parseDimensionsString(product.dimensions);
}
@@ -271,7 +271,7 @@ export function extractProductDimensions(product: {
// ============================================
/**
- * Estima dimensões padrão baseado na categoria do produto
+ * Estima dimensões padrão baseado na categoria do produto
*/
export function estimateDefaultDimensions(category?: string): {
width: number;
@@ -306,6 +306,6 @@ export function estimateDefaultDimensions(category?: string): {
return { width: 7, height: 14, depth: 2 };
}
- // Padrão genérico para itens pequenos
+ // Padrão genérico para itens pequenos
return { width: 10, height: 10, depth: 5 };
}
diff --git a/src/lib/personalization/calculators.ts b/src/lib/personalization/calculators.ts
index d67700004..59231c727 100644
--- a/src/lib/personalization/calculators.ts
+++ b/src/lib/personalization/calculators.ts
@@ -1,7 +1,7 @@
/**
- * Domain Calculators: Personalização
+ * Domain Calculators: Personalização
*
- * Funções puras para cálculo de preços, sem side effects.
+ * Funções puras para cálculo de preços, sem side effects.
*/
import type {
@@ -17,7 +17,7 @@ import type {
// ============================================
/**
- * Calcula o preço total de personalização para uma tabela e parâmetros dados
+ * Calcula o preço total de personalização para uma tabela e parâmetros dados
*/
export function calculatePrice(
table: PriceTableInput,
@@ -25,22 +25,22 @@ export function calculatePrice(
): PriceCalculationResult {
const { quantity, colors, widthCm, heightCm } = params;
- // 1. Encontrar a faixa de preço correta
+ // 1. Encontrar a faixa de preço correta
const tier = findPriceTier(table.tiers, quantity);
if (!tier) {
- throw new Error(`Nenhuma faixa de preço encontrada para quantidade ${quantity}`);
+ throw new Error(`Nenhuma faixa de preço encontrada para quantidade ${quantity}`);
}
- // 2. Calcular preço unitário base
+ // 2. Calcular preço unitário base
let unitPrice = tier.unitPrice;
- // 3. Ajustar por número de cores (se aplicável)
+ // 3. Ajustar por número de cores (se aplicável)
if (table.priceByColor && colors && table.maxColors) {
unitPrice = adjustPriceByColors(unitPrice, colors, table.maxColors);
}
- // 4. Ajustar por área (se aplicável)
+ // 4. Ajustar por área (se aplicável)
if (table.priceByArea && widthCm && heightCm) {
unitPrice = adjustPriceByArea(
unitPrice,
@@ -58,7 +58,7 @@ export function calculatePrice(
// 6. Calcular economia vs primeira faixa
const savings = calculateTierSavings(table.tiers, tier, unitPrice, quantity);
- // 7. Montar área máxima
+ // 7. Montar área máxima
const maxArea: PrintArea | null =
table.maxWidthCm && table.maxHeightCm
? {
@@ -87,12 +87,12 @@ export function calculatePrice(
}
/**
- * Encontra a faixa de preço apropriada para uma quantidade
+ * Encontra a faixa de preço apropriada para uma quantidade
*/
export function findPriceTier(tiers: PriceTier[], quantity: number): PriceTier | null {
if (tiers.length === 0) return null;
- // Ordenar por quantidade mÃnima
+ // Ordenar por quantidade mínima
const sortedTiers = [...tiers].sort((a, b) => a.minQuantity - b.minQuantity);
// Encontrar a maior faixa que a quantidade atinge
@@ -110,8 +110,8 @@ export function findPriceTier(tiers: PriceTier[], quantity: number): PriceTier |
}
/**
- * Ajusta preço baseado no número de cores
- * Se o cliente precisa de mais cores que o máximo da tabela, aplica proporcional
+ * Ajusta preço baseado no número de cores
+ * Se o cliente precisa de mais cores que o máximo da tabela, aplica proporcional
*/
export function adjustPriceByColors(
basePrice: number,
@@ -122,14 +122,14 @@ export function adjustPriceByColors(
return basePrice;
}
- // Preço proporcional para cores extras
+ // Preço proporcional para cores extras
const colorFactor = requestedColors / tableMaxColors;
return basePrice * colorFactor;
}
/**
- * Ajusta preço baseado na área
- * Se a área excede o máximo, aplica proporcional
+ * Ajusta preço baseado na área
+ * Se a área excede o máximo, aplica proporcional
*/
export function adjustPriceByArea(
basePrice: number,
@@ -147,7 +147,7 @@ export function adjustPriceByArea(
return basePrice;
}
- // Preço proporcional para área extra
+ // Preço proporcional para área extra
const areaFactor = requestedArea / maxArea;
return basePrice * areaFactor;
}
@@ -181,7 +181,7 @@ function calculateTierSavings(
}
/**
- * Calcula economia entre dois preços unitários (exportada)
+ * Calcula economia entre dois preços unitários (exportada)
*/
export function calculateSavings(
originalUnitPrice: number,
@@ -200,7 +200,7 @@ export function calculateSavings(
// ============================================
/**
- * Retorna a quantidade mÃnima de uma lista de faixas
+ * Retorna a quantidade mínima de uma lista de faixas
*/
export function getMinimumQuantity(tiers: PriceTier[]): number {
if (tiers.length === 0) return 1;
@@ -209,7 +209,7 @@ export function getMinimumQuantity(tiers: PriceTier[]): number {
}
/**
- * Retorna a quantidade máxima explÃcita (ou null se ilimitado)
+ * Retorna a quantidade máxima explícita (ou null se ilimitado)
*/
export function getMaximumQuantity(tiers: PriceTier[]): number | null {
if (tiers.length === 0) return null;
@@ -219,7 +219,7 @@ export function getMaximumQuantity(tiers: PriceTier[]): number | null {
}
/**
- * Sugere a próxima faixa de quantidade para economia
+ * Sugere a próxima faixa de quantidade para economia
*/
export function suggestNextTier(
tiers: PriceTier[],
@@ -250,7 +250,7 @@ export function suggestNextTier(
// ============================================
/**
- * Calcula preço para múltiplas técnicas (gravação em várias posições)
+ * Calcula preço para múltiplas técnicas (gravação em várias posições)
*/
export function calculateMultiTechniquePrice(calculations: PriceCalculationResult[]): {
subtotal: number;
diff --git a/src/lib/personalization/selectors.ts b/src/lib/personalization/selectors.ts
index b0d61101e..2d62601d5 100644
--- a/src/lib/personalization/selectors.ts
+++ b/src/lib/personalization/selectors.ts
@@ -1,7 +1,7 @@
/**
- * Domain Selectors: Personalização
+ * Domain Selectors: Personalização
*
- * Funções puras para seleção e filtragem de dados.
+ * Funções puras para seleção e filtragem de dados.
*/
import type {
@@ -18,8 +18,8 @@ import type {
// ============================================
/**
- * Seleciona a melhor tabela de preço para os critérios dados
- * Prioridade: cores -> dimensões -> primeira disponÃvel
+ * Seleciona a melhor tabela de preço para os critérios dados
+ * Prioridade: cores -> dimensões -> primeira disponível
*/
export function selectBestTable(
tables: PriceTableInput[],
@@ -32,14 +32,14 @@ export function selectBestTable(
if (candidates.length === 0) return null;
- // Filtrar por nome da técnica
+ // Filtrar por nome da técnica
if (criteria.techniqueName) {
const techniqueName = criteria.techniqueName.toLowerCase();
const byName = candidates.filter((t) => t.techniqueName.toLowerCase().includes(techniqueName));
if (byName.length > 0) candidates = byName;
}
- // Filtrar por código da técnica
+ // Filtrar por código da técnica
if (criteria.techniqueCode) {
const techniqueCode = criteria.techniqueCode.toLowerCase();
const byCode = candidates.filter(
@@ -50,7 +50,7 @@ export function selectBestTable(
if (byCode.length > 0) candidates = byCode;
}
- // Ordenar por número de cores (preferir a que atende exatamente)
+ // Ordenar por número de cores (preferir a que atende exatamente)
if (criteria.colors) {
const colors = criteria.colors;
candidates.sort((a, b) => {
@@ -70,7 +70,7 @@ export function selectBestTable(
});
}
- // Filtrar por dimensões
+ // Filtrar por dimensões
if (criteria.widthCm && criteria.heightCm) {
const widthCm = criteria.widthCm;
const heightCm = criteria.heightCm;
@@ -86,7 +86,7 @@ export function selectBestTable(
}
/**
- * Filtra tabelas por técnica
+ * Filtra tabelas por técnica
*/
export function filterTablesByTechnique(
tables: PriceTableInput[],
@@ -102,7 +102,7 @@ export function filterTablesByTechnique(
}
/**
- * Agrupa tabelas por nome de técnica
+ * Agrupa tabelas por nome de técnica
*/
export function groupTablesByTechnique(tables: PriceTableInput[]): Map
{
const grouped = new Map();
@@ -123,7 +123,7 @@ export function groupTablesByTechnique(tables: PriceTableInput[]): Map();
@@ -147,7 +147,7 @@ export function getUniqueTechniques(techniques: TechniqueInput[]): TechniqueInpu
}
/**
- * Retorna categorias únicas das técnicas
+ * Retorna categorias únicas das técnicas
*/
export function getUniqueCategories(techniques: TechniqueInput[]): string[] {
const categories = [...new Set(techniques.map((t) => t.category))];
@@ -159,7 +159,7 @@ export function getUniqueCategories(techniques: TechniqueInput[]): string[] {
// ============================================
/**
- * Extrai opções de cores disponÃveis das tabelas
+ * Extrai opções de cores disponíveis das tabelas
*/
export function extractColorOptions(
tables: PriceTableInput[],
@@ -167,12 +167,12 @@ export function extractColorOptions(
): ColorOption[] {
if (!hasPriceByColor || tables.length === 0) return [];
- // Coletar todos os maxColors únicos
+ // Coletar todos os maxColors únicos
const uniqueColors = [
...new Set(tables.map((t) => t.maxColors).filter((c): c is number => c !== null && c > 0)),
].sort((a, b) => a - b);
- // Se só há um valor, criar opções de 1 até o máximo
+ // Se só há um valor, criar opções de 1 até o máximo
if (uniqueColors.length <= 1) {
const maxColors = uniqueColors[0] || 4;
return Array.from({ length: maxColors }, (_, i) => ({
@@ -181,7 +181,7 @@ export function extractColorOptions(
}));
}
- // Se há variação, usar os valores disponÃveis
+ // Se há variação, usar os valores disponíveis
return uniqueColors.map((c) => ({
value: c,
label: `${c} ${c === 1 ? 'cor' : 'cores'}`,
@@ -189,7 +189,7 @@ export function extractColorOptions(
}
/**
- * Extrai opções de tamanho disponÃveis das tabelas
+ * Extrai opções de tamanho disponíveis das tabelas
*/
export function extractSizeOptions(tables: PriceTableInput[]): SizeOption[] {
if (tables.length === 0) return [];
@@ -215,7 +215,7 @@ export function extractSizeOptions(tables: PriceTableInput[]): SizeOption[] {
}
}
- // Ordenar por área
+ // Ordenar por área
return Array.from(uniqueAreas.values()).sort((a, b) => a.areaCm2 - b.areaCm2);
}
@@ -233,7 +233,7 @@ export function extractQuantityOptions(tiers: PriceTier[]): number[] {
// ============================================
/**
- * Calcula score de compatibilidade entre tabela e critérios
+ * Calcula score de compatibilidade entre tabela e critérios
* Maior score = melhor match
*/
export function calculateTableScore(
@@ -253,7 +253,7 @@ export function calculateTableScore(
if (nameMatch) score += 50;
}
- // Match por código
+ // Match por código
if (criteria.techniqueCode) {
const codeMatch = table.tableCode.toLowerCase().includes(criteria.techniqueCode.toLowerCase());
if (codeMatch) score += 50;
@@ -262,14 +262,14 @@ export function calculateTableScore(
// Match por cores
if (criteria.colors && table.maxColors !== null) {
if (table.maxColors >= criteria.colors) {
- // Quanto mais próximo do necessário, melhor
+ // Quanto mais próximo do necessário, melhor
score += 30 - Math.min(table.maxColors - criteria.colors, 30);
} else {
- score -= 20; // Penaliza se não atende
+ score -= 20; // Penaliza se não atende
}
}
- // Match por dimensões
+ // Match por dimensões
if (criteria.widthCm && criteria.heightCm) {
const fitsWidth = table.maxWidthCm === null || table.maxWidthCm >= criteria.widthCm;
const fitsHeight = table.maxHeightCm === null || table.maxHeightCm >= criteria.heightCm;
diff --git a/src/lib/personalization/transformers.ts b/src/lib/personalization/transformers.ts
index 083d315e8..d4d2b9ae5 100644
--- a/src/lib/personalization/transformers.ts
+++ b/src/lib/personalization/transformers.ts
@@ -1,11 +1,11 @@
/**
- * Domain Transformers: Personalização
+ * Domain Transformers: Personalização
*
- * Funções puras para transformação entre formatos de dados.
- * Converte entre tipos de infraestrutura (API/DB) e tipos de domÃnio.
+ * Funções puras para transformação entre formatos de dados.
+ * Converte entre tipos de infraestrutura (API/DB) e tipos de domínio.
*
- * SSOT: Este módulo é a única fonte de transformadores de dados.
- * Hooks devem importar daqui, não definir transformadores próprios.
+ * SSOT: Este módulo é a única fonte de transformadores de dados.
+ * Hooks devem importar daqui, não definir transformadores próprios.
*/
import type { PriceTableInput, TechniqueInput, PriceTier } from './types';
@@ -111,7 +111,7 @@ export function rawToTabelaPrecoTecnica(raw: CustomizationPriceTableRaw): Tabela
}
/**
- * Batch: Transforma array de técnicas raw
+ * Batch: Transforma array de técnicas raw
*/
export function transformRawToTecnicas(raws: PersonalizationTechniqueRaw[]): TecnicaUnificada[] {
return raws.map(rawToTecnicaUnificada);
@@ -243,7 +243,7 @@ export function rawTableToPriceTableInput(raw: CustomizationPriceTableRaw): Pric
}
/**
- * Extrai faixas de preço do formato raw
+ * Extrai faixas de preço do formato raw
*/
function extractTiersFromRaw(raw: CustomizationPriceTableRaw): PriceTier[] {
const tiers: PriceTier[] = [];
@@ -307,7 +307,7 @@ export function rawTechniqueToTechniqueInput(raw: PersonalizationTechniqueRaw):
// ============================================
/**
- * Formata preço para exibição
+ * Formata preço para exibição
*/
export function formatPrice(value: number, currency = 'BRL'): string {
return new Intl.NumberFormat('pt-BR', {
@@ -317,24 +317,24 @@ export function formatPrice(value: number, currency = 'BRL'): string {
}
/**
- * Formata área para exibição
+ * Formata área para exibição
*/
export function formatArea(widthCm: number, heightCm: number): string {
return `${widthCm} x ${heightCm} cm`;
}
/**
- * Formata SLA para exibição
+ * Formata SLA para exibição
*/
export function formatSla(days: number | null): string {
if (days === null) return 'A consultar';
if (days === 0) return 'Pronta entrega';
- if (days === 1) return '1 dia útil';
- return `${days} dias úteis`;
+ if (days === 1) return '1 dia útil';
+ return `${days} dias úteis`;
}
/**
- * Formata economia para exibição
+ * Formata economia para exibição
*/
export function formatSavings(percentOff: number): string {
if (percentOff <= 0) return '';
@@ -353,7 +353,7 @@ export function transformTables(tabelas: TabelaPrecoTecnica[]): PriceTableInput[
}
/**
- * Transforma array de técnicas
+ * Transforma array de técnicas
*/
export function transformTechniques(tecnicas: TecnicaUnificada[]): TechniqueInput[] {
return tecnicas.map(tecnicaToTechniqueInput);
@@ -367,7 +367,7 @@ export function transformRawTables(raws: CustomizationPriceTableRaw[]): PriceTab
}
/**
- * Transforma array de técnicas raw
+ * Transforma array de técnicas raw
*/
export function transformRawTechniques(raws: PersonalizationTechniqueRaw[]): TechniqueInput[] {
return raws.map(rawTechniqueToTechniqueInput);
diff --git a/src/lib/personalization/validators.ts b/src/lib/personalization/validators.ts
index 6e558ebed..382bed8ec 100644
--- a/src/lib/personalization/validators.ts
+++ b/src/lib/personalization/validators.ts
@@ -1,7 +1,7 @@
/**
- * Domain Validators: Personalização
+ * Domain Validators: Personalização
*
- * Funções puras para validação de parâmetros de personalização.
+ * Funções puras para validação de parâmetros de personalização.
*/
import type {
@@ -18,7 +18,7 @@ import type {
// ============================================
/**
- * Valida se uma tabela de preço pode ser usada com os parâmetros dados
+ * Valida se uma tabela de preço pode ser usada com os parâmetros dados
*/
export function validateTableForParams(
table: PriceTableInput,
@@ -38,7 +38,7 @@ export function validateTableForParams(
});
}
- // Validar quantidade mÃnima
+ // Validar quantidade mínima
const minQuantity =
table.tiers.length > 0 ? Math.min(...table.tiers.map((t) => t.minQuantity)) : 1;
@@ -46,7 +46,7 @@ export function validateTableForParams(
errors.push({
code: 'BELOW_MIN_QUANTITY',
field: 'quantity',
- message: `Quantidade mÃnima é ${minQuantity} unidades`,
+ message: `Quantidade mínima é ${minQuantity} unidades`,
});
}
@@ -56,7 +56,7 @@ export function validateTableForParams(
errors.push({
code: 'INVALID_COLORS',
field: 'colors',
- message: 'Número de cores deve ser maior que zero',
+ message: 'Número de cores deve ser maior que zero',
});
}
@@ -64,12 +64,12 @@ export function validateTableForParams(
warnings.push({
code: 'EXCEEDS_MAX_COLORS',
field: 'colors',
- message: `Número de cores (${colors}) excede máximo da tabela (${table.maxColors}). Preço será ajustado proporcionalmente.`,
+ message: `Número de cores (${colors}) excede máximo da tabela (${table.maxColors}). Preço será ajustado proporcionalmente.`,
});
}
}
- // Validar dimensões
+ // Validar dimensões
if (table.priceByArea) {
if (widthCm !== undefined && widthCm <= 0) {
errors.push({
@@ -91,7 +91,7 @@ export function validateTableForParams(
warnings.push({
code: 'EXCEEDS_MAX_WIDTH',
field: 'widthCm',
- message: `Largura (${widthCm}cm) excede máximo (${table.maxWidthCm}cm)`,
+ message: `Largura (${widthCm}cm) excede máximo (${table.maxWidthCm}cm)`,
});
}
@@ -99,11 +99,11 @@ export function validateTableForParams(
warnings.push({
code: 'EXCEEDS_MAX_HEIGHT',
field: 'heightCm',
- message: `Altura (${heightCm}cm) excede máximo (${table.maxHeightCm}cm)`,
+ message: `Altura (${heightCm}cm) excede máximo (${table.maxHeightCm}cm)`,
});
}
- // Validar área
+ // Validar área
if (widthCm && heightCm) {
const areaCm2 = widthCm * heightCm;
@@ -111,7 +111,7 @@ export function validateTableForParams(
errors.push({
code: 'BELOW_MIN_AREA',
field: 'area',
- message: `Ãrea (${areaCm2}cm²) abaixo do mÃnimo (${table.minAreaCm2}cm²)`,
+ message: `Área (${areaCm2}cm²) abaixo do mínimo (${table.minAreaCm2}cm²)`,
});
}
@@ -119,7 +119,7 @@ export function validateTableForParams(
warnings.push({
code: 'EXCEEDS_MAX_AREA',
field: 'area',
- message: `Ãrea (${areaCm2}cm²) excede máximo (${table.maxAreaCm2}cm²). Preço será ajustado.`,
+ message: `Área (${areaCm2}cm²) excede máximo (${table.maxAreaCm2}cm²). Preço será ajustado.`,
});
}
}
@@ -133,7 +133,7 @@ export function validateTableForParams(
}
/**
- * Valida se uma técnica é compatÃvel com os parâmetros solicitados
+ * Valida se uma técnica é compatível com os parâmetros solicitados
*/
export function validateTechniqueForParams(
technique: TechniqueInput,
@@ -149,7 +149,7 @@ export function validateTechniqueForParams(
errors.push({
code: 'TECHNIQUE_INACTIVE',
field: 'technique',
- message: 'Técnica não está ativa',
+ message: 'Técnica não está ativa',
});
}
@@ -159,14 +159,14 @@ export function validateTechniqueForParams(
errors.push({
code: 'COLORS_REQUIRED',
field: 'colors',
- message: 'Esta técnica requer especificação de cores',
+ message: 'Esta técnica requer especificação de cores',
});
} else {
if (colors < technique.minColors) {
errors.push({
code: 'BELOW_MIN_COLORS',
field: 'colors',
- message: `MÃnimo de ${technique.minColors} cor(es) requerido`,
+ message: `Mínimo de ${technique.minColors} cor(es) requerido`,
});
}
@@ -174,13 +174,13 @@ export function validateTechniqueForParams(
warnings.push({
code: 'EXCEEDS_MAX_COLORS',
field: 'colors',
- message: `Número de cores (${colors}) excede máximo (${technique.maxColors})`,
+ message: `Número de cores (${colors}) excede máximo (${technique.maxColors})`,
});
}
}
}
- // Validar área
+ // Validar área
if (technique.priceByArea && widthCm && heightCm) {
const areaCm2 = widthCm * heightCm;
@@ -188,7 +188,7 @@ export function validateTechniqueForParams(
errors.push({
code: 'BELOW_MIN_AREA',
field: 'area',
- message: `Ãrea mÃnima é ${technique.minAreaCm2}cm²`,
+ message: `Área mínima é ${technique.minAreaCm2}cm²`,
});
}
@@ -196,7 +196,7 @@ export function validateTechniqueForParams(
warnings.push({
code: 'EXCEEDS_MAX_AREA',
field: 'area',
- message: `Ãrea (${areaCm2}cm²) excede máximo (${technique.maxAreaCm2}cm²)`,
+ message: `Área (${areaCm2}cm²) excede máximo (${technique.maxAreaCm2}cm²)`,
});
}
}
@@ -213,7 +213,7 @@ export function validateTechniqueForParams(
// ============================================
/**
- * Valida se quantidade é válida para um conjunto de faixas
+ * Valida se quantidade é válida para um conjunto de faixas
*/
export function validateQuantityRange(
quantity: number,
@@ -235,7 +235,7 @@ export function validateQuantityRange(
errors.push({
code: 'BELOW_MIN_QUANTITY',
field: 'quantity',
- message: `Quantidade mÃnima é ${minQuantity}`,
+ message: `Quantidade mínima é ${minQuantity}`,
});
}
@@ -243,7 +243,7 @@ export function validateQuantityRange(
warnings.push({
code: 'EXCEEDS_MAX_QUANTITY',
field: 'quantity',
- message: `Quantidade (${quantity}) excede máximo usual (${maxQuantity})`,
+ message: `Quantidade (${quantity}) excede máximo usual (${maxQuantity})`,
});
}
@@ -255,14 +255,14 @@ export function validateQuantityRange(
}
/**
- * Valida quantidade simples (para serviços)
+ * Valida quantidade simples (para serviços)
*/
export function validateQuantity(quantity: number): ValidationResult {
return validateQuantityRange(quantity, 1);
}
/**
- * Valida número de cores
+ * Valida número de cores
*/
export function validateColors(colors: number, maxColors?: number): ValidationResult {
const errors: ValidationError[] = [];
@@ -272,7 +272,7 @@ export function validateColors(colors: number, maxColors?: number): ValidationRe
errors.push({
code: 'INVALID_COLORS',
field: 'colors',
- message: 'Número de cores deve ser maior que zero',
+ message: 'Número de cores deve ser maior que zero',
});
}
@@ -280,7 +280,7 @@ export function validateColors(colors: number, maxColors?: number): ValidationRe
warnings.push({
code: 'EXCEEDS_MAX_COLORS',
field: 'colors',
- message: `Número de cores (${colors}) excede máximo (${maxColors})`,
+ message: `Número de cores (${colors}) excede máximo (${maxColors})`,
});
}
@@ -292,7 +292,7 @@ export function validateColors(colors: number, maxColors?: number): ValidationRe
}
/**
- * Valida dimensões de área
+ * Valida dimensões de área
*/
export function validateArea(
widthCm: number,
@@ -323,7 +323,7 @@ export function validateArea(
warnings.push({
code: 'EXCEEDS_MAX_WIDTH',
field: 'widthCm',
- message: `Largura (${widthCm}cm) excede máximo (${maxWidthCm}cm)`,
+ message: `Largura (${widthCm}cm) excede máximo (${maxWidthCm}cm)`,
});
}
@@ -331,7 +331,7 @@ export function validateArea(
warnings.push({
code: 'EXCEEDS_MAX_HEIGHT',
field: 'heightCm',
- message: `Altura (${heightCm}cm) excede máximo (${maxHeightCm}cm)`,
+ message: `Altura (${heightCm}cm) excede máximo (${maxHeightCm}cm)`,
});
}
@@ -347,10 +347,10 @@ export function validateArea(
// ============================================
/**
- * Verifica se precisa de setup (primeira gravação ou novo cliente)
+ * Verifica se precisa de setup (primeira gravação ou novo cliente)
*/
export function requiresSetup(isFirstOrder: boolean, hasExistingMatrix: boolean): boolean {
- // Cobra setup apenas se não tiver matriz existente
+ // Cobra setup apenas se não tiver matriz existente
return isFirstOrder || !hasExistingMatrix;
}
@@ -364,12 +364,12 @@ export function calculateHandlingCost(
): number {
let cost = baseHandling;
- // Múltiplas posições aumenta manuseio
+ // Múltiplas posições aumenta manuseio
if (positions > 1) {
- cost *= 1 + (positions - 1) * 0.25; // +25% por posição adicional
+ cost *= 1 + (positions - 1) * 0.25; // +25% por posição adicional
}
- // Produtos frágeis dobram manuseio
+ // Produtos frágeis dobram manuseio
if (isFragile) {
cost *= 2;
}
diff --git a/src/pages/auth/Auth.tsx b/src/pages/auth/Auth.tsx
index b2204a13c..da8002c98 100644
--- a/src/pages/auth/Auth.tsx
+++ b/src/pages/auth/Auth.tsx
@@ -56,12 +56,12 @@ export default function Auth() {
const { isAllowed: isDevAllowed } = useDevGate();
/**
- * Destino pós-login. Precedência:
+ * Destino pós-login. Precedência:
* 1. `location.state.from` (vindo do ProtectedRoute na mesma aba)
* 2. `?redirect=/path` na URL (deep-link manual)
* 3. `sessionStorage` (sobrevive ao round-trip OAuth)
* 4. fallback `/`
- * Consumido aqui para que login por e-mail/senha também respeite o destino.
+ * Consumido aqui para que login por e-mail/senha também respeite o destino.
*/
const resolveRedirectTargetCb = useCallback((): string => {
const fromState = (
@@ -80,7 +80,7 @@ export default function Auth() {
const [blockedIP, setBlockedIP] = useState(null);
const [currentIP, setCurrentIP] = useState(null);
const [geoLocation, setGeoLocation] = useState(null);
- // Fallback social → email/senha: mensagem amigável quando OAuth falha.
+ // Fallback social → email/senha: mensagem amigável quando OAuth falha.
const [socialError, setSocialError] = useState(null);
// External Database Check State
@@ -94,7 +94,7 @@ export default function Auth() {
crm: { ok: false, loading: true },
});
const emailInputRef = useRef(null);
- // Função `retry` publicada pelo SocialLoginButtons para reexecutar o Google login.
+ // Função `retry` publicada pelo SocialLoginButtons para reexecutar o Google login.
const googleRetryRef = useRef<(() => void) | null>(null);
const handleRetryGoogle = useCallback(() => {
setSocialError(null);
@@ -130,11 +130,11 @@ export default function Auth() {
(message: string, opts?: { autoFallback?: boolean }) => {
const copy = resolveOAuthError(message);
setSocialError(copy);
- // Fallback automático em falhas recuperáveis (timeout/silencioso):
- // o usuário não precisa clicar — o foco vai direto pro e-mail.
+ // Fallback automático em falhas recuperáveis (timeout/silencioso):
+ // o usuário não precisa clicar — o foco vai direto pro e-mail.
if (opts?.autoFallback && !copy.isConfig) {
toast({
- title: 'Login com Google indisponÃvel',
+ title: 'Login com Google indisponível',
description: 'Mudamos para entrada com e-mail e senha automaticamente.',
});
setTimeout(() => focusEmailFallback(), 50);
@@ -147,7 +147,7 @@ export default function Auth() {
// Fetch IP, geolocation and backend status
useEffect(() => {
- // Guarda de cancelamento: evita setState após o unmount do componente.
+ // Guarda de cancelamento: evita setState após o unmount do componente.
// Sem isso, os awaits de loadInfo podem resolver depois do teardown e
// disparar setDbStatus/setCurrentIP fora do ciclo de vida do React
// (em testes, isso vaza como "ReferenceError: window is not defined").
@@ -182,7 +182,7 @@ export default function Auth() {
},
}));
- // 3. External (Gestão de Produtos) via bridge ping op
+ // 3. External (Gestão de Produtos) via bridge ping op
try {
const { data, error } = await supabase.functions.invoke('external-db-bridge', {
body: { operation: 'ping' },
@@ -246,7 +246,7 @@ export default function Auth() {
variant: 'destructive',
title: 'Acesso Bloqueado',
description:
- ipValidation.error || `Seu IP (${ipValidation.currentIP}) não está autorizado.`,
+ ipValidation.error || `Seu IP (${ipValidation.currentIP}) não está autorizado.`,
duration: 10000,
});
return false;
@@ -287,28 +287,28 @@ export default function Auth() {
let diagnosis = 'Verifique as credenciais';
let title = 'Erro ao entrar';
- // HeurÃstica de erro baseada no código e mensagem
+ // Heurística de erro baseada no código e mensagem
if (error.message.includes('Invalid login credentials') || error.status === 400) {
description = 'Email ou senha incorretos. Por favor, tente novamente.';
- diagnosis = 'AUTH_FAILED: Credenciais inválidas (400).';
+ diagnosis = 'AUTH_FAILED: Credenciais inválidas (400).';
} else if (error.message.includes('Email not confirmed')) {
- description = 'E-mail pendente de confirmação. Por favor, valide sua conta.';
- diagnosis = 'AUTH_CONFIRM: Usuário existe mas e-mail não foi confirmado.';
+ description = 'E-mail pendente de confirmação. Por favor, valide sua conta.';
+ diagnosis = 'AUTH_CONFIRM: Usuário existe mas e-mail não foi confirmado.';
} else if (error.message.includes('rate limit') || error.status === 429) {
title = 'Conta Temporariamente Bloqueada';
- description = 'Muitas tentativas falhas. Por segurança, aguarde alguns minutos.';
- diagnosis = 'RATE_LIMIT: Bloqueio temporário ativado (429).';
+ description = 'Muitas tentativas falhas. Por segurança, aguarde alguns minutos.';
+ diagnosis = 'RATE_LIMIT: Bloqueio temporário ativado (429).';
} else if (
error.status === 0 ||
error.message.includes('network') ||
error.message.includes('Fetch')
) {
- title = 'Erro de Conexão';
- description = 'Não foi possÃvel alcançar o servidor. Verifique sua internet.';
- diagnosis = 'NETWORK_ERROR: Falha fÃsica ou DNS (0).';
+ title = 'Erro de Conexão';
+ description = 'Não foi possível alcançar o servidor. Verifique sua internet.';
+ diagnosis = 'NETWORK_ERROR: Falha física ou DNS (0).';
} else if (error.message.includes('Database error') || error.status >= 500) {
title = 'Erro no Servidor';
- description = 'O sistema está instável no momento. Nossa equipe já foi notificada.';
+ description = 'O sistema está instável no momento. Nossa equipe já foi notificada.';
diagnosis = `SERVER_ERROR: Erro interno do Supabase (${error.status || 500}).`;
}
@@ -362,8 +362,8 @@ export default function Auth() {
if (!userId) {
toast({
variant: 'destructive',
- title: 'Erro de sessão',
- description: 'Login realizado mas a sessão não pôde ser iniciada.',
+ title: 'Erro de sessão',
+ description: 'Login realizado mas a sessão não pôde ser iniciada.',
});
return;
}
@@ -382,10 +382,10 @@ export default function Auth() {
const isRLSError = profileError.code === 'PGRST301' || profileError.code === '42501';
toast({
variant: 'destructive',
- title: 'Erro de Sessão',
+ title: 'Erro de Sessão',
description: (
-
Autenticado, mas não conseguimos carregar suas permissões.
+
Autenticado, mas não conseguimos carregar suas permissões.
{isRLSError ? 'RLS_BLOCK' : 'PROFILE_MISSING'}: {profileError.code} -{' '}
{profileError.message}
@@ -399,13 +399,13 @@ export default function Auth() {
toast({
variant: 'destructive',
title: 'Acesso Bloqueado',
- description: 'Sua conta está inativa. Entre em contato com o administrador.',
+ description: 'Sua conta está inativa. Entre em contato com o administrador.',
});
await signOut();
return;
}
- // 2. Verificação de Roles (user_roles)
+ // 2. Verificação de Roles (user_roles)
const { data: rolesData, error: rolesError } = await supabase
.from('user_roles')
.select('role')
@@ -417,14 +417,14 @@ export default function Auth() {
});
}
- // 3. Validação final de IP e Redirecionamento
+ // 3. Validação final de IP e Redirecionamento
await validateAndRedirect(userId, data.email);
} catch {
logger.error('[AUTH_LOGIN_EXCEPTION] Unexpected login exception');
toast({
variant: 'destructive',
title: 'Erro inesperado',
- description: 'Não foi possÃvel conectar ao servidor. Verifique sua internet.',
+ description: 'Não foi possível conectar ao servidor. Verifique sua internet.',
});
} finally {
setIsSubmitting(false);
@@ -436,7 +436,7 @@ export default function Auth() {
@@ -459,8 +459,8 @@ export default function Auth() {
-
Você já está conectado
-
Redirecionando para sua área segura...
+
Você já está conectado
+
Redirecionando para sua área segura...
@@ -471,14 +471,14 @@ export default function Auth() {