2026-01-26 14:20:25 +00:00
|
|
|
|
|
|
|
|
import React, { useState } from 'react';
|
|
|
|
|
import { Settings as SettingsIcon, Truck, Key, Building, Users, Save, Globe, Smartphone, Bell, Shield, FileCheck, ShoppingBag, RefreshCw, AlertCircle, Upload, Palette } from 'lucide-react';
|
|
|
|
|
import clsx from 'clsx';
|
|
|
|
|
import { useCRM } from '../context/CRMContext';
|
|
|
|
|
import { useTheme } from '../context/ThemeContext';
|
|
|
|
|
|
|
|
|
|
const ThemeSelector = () => {
|
|
|
|
|
const { theme, setTheme } = useTheme();
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-white/5 pb-2">Tema do Sistema</h3>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
|
|
|
{[
|
|
|
|
|
{ id: 'light', name: 'Simples (Clean)', color: 'bg-slate-50 border-2 border-slate-200', accent: 'bg-blue-600', text: 'Visual limpo e direto.' },
|
|
|
|
|
{ id: 'ocean', name: 'Complexo (Ocean)', color: 'bg-[#0f172a]', accent: 'bg-cyan-500', text: 'Alta densidade e contraste.' },
|
|
|
|
|
{ id: 'dark', name: 'Completo (Pro)', color: 'bg-[#0a0a0c]', accent: 'bg-indigo-600', text: 'Interface imersiva padrão.' },
|
|
|
|
|
].map(t => (
|
|
|
|
|
<button
|
|
|
|
|
key={t.id}
|
|
|
|
|
onClick={() => setTheme(t.id as any)}
|
|
|
|
|
className={clsx(
|
|
|
|
|
"group relative rounded-2xl overflow-hidden transition-all duration-300 border-2 flex flex-col items-start text-left",
|
|
|
|
|
theme === t.id ? "border-indigo-500 ring-2 ring-indigo-500/20 scale-[1.02]" : "border-white/5 hover:border-white/10"
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
{/* Preview Header */}
|
|
|
|
|
<div className={clsx("h-24 w-full relative", t.color)}>
|
|
|
|
|
<div className="absolute top-3 left-3 flex gap-1.5">
|
|
|
|
|
<div className="w-2 h-2 rounded-full bg-red-400/50"></div>
|
|
|
|
|
<div className="w-2 h-2 rounded-full bg-amber-400/50"></div>
|
|
|
|
|
<div className="w-2 h-2 rounded-full bg-emerald-400/50"></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={clsx("absolute bottom-3 right-3 px-2 py-1 rounded text-[10px] font-bold text-white shadow-lg", t.accent)}>
|
|
|
|
|
Aa
|
|
|
|
|
</div>
|
|
|
|
|
{/* Fake UI Lines */}
|
|
|
|
|
<div className="absolute top-8 left-3 w-3/4 h-2 bg-white/5 rounded-full"></div>
|
|
|
|
|
<div className="absolute top-12 left-3 w-1/2 h-2 bg-white/5 rounded-full"></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Content */}
|
|
|
|
|
<div className="p-5 bg-card w-full">
|
|
|
|
|
<div className="flex justify-between items-center mb-1">
|
|
|
|
|
<span className="text-sm font-bold text-foreground">{t.name}</span>
|
|
|
|
|
{theme === t.id && <div className="w-2 h-2 rounded-full bg-emerald-500 shadow-emerald-500/50 shadow-lg"></div>}
|
|
|
|
|
</div>
|
|
|
|
|
<p className="text-xs text-muted-foreground">{t.text}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const Settings: React.FC = () => {
|
|
|
|
|
const { overheadPercent, exchangeRate, settings, updateSettings } = useCRM();
|
|
|
|
|
const [activeTab, setActiveTab] = useState<'general' | 'fiscal' | 'marketplaces' | 'logistics' | 'email' | 'notifications'>('general');
|
|
|
|
|
|
|
|
|
|
// Local state for form, initialized with context settings
|
|
|
|
|
const [config, setConfig] = useState(settings || {
|
|
|
|
|
companyName: 'Arbitra System',
|
|
|
|
|
cnpj: '',
|
|
|
|
|
ie: '',
|
|
|
|
|
defaultOverhead: 20,
|
|
|
|
|
defaultExchange: 5.65,
|
|
|
|
|
certificateName: '',
|
|
|
|
|
certificatePassword: '',
|
|
|
|
|
geminiKey: 'sk-....................',
|
|
|
|
|
melhorEnvioToken: '',
|
|
|
|
|
blingToken: '',
|
|
|
|
|
tinyToken: '',
|
|
|
|
|
whatsappNumber: '',
|
|
|
|
|
nfeSerie: '1',
|
|
|
|
|
nfeNumber: '159',
|
|
|
|
|
autoSyncSales: true,
|
|
|
|
|
autoSyncStock: true,
|
|
|
|
|
smtpHost: '',
|
|
|
|
|
smtpPort: '587',
|
|
|
|
|
smtpUser: '',
|
|
|
|
|
smtpPass: '',
|
2026-01-27 18:40:32 +00:00
|
|
|
electricityCostKwh: 0.90,
|
2026-01-26 14:20:25 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Sync state when settings load from DB
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
|
if (settings) {
|
|
|
|
|
setConfig(prev => ({ ...prev, ...settings }));
|
|
|
|
|
}
|
|
|
|
|
}, [settings]);
|
|
|
|
|
|
|
|
|
|
const handleSave = async () => {
|
|
|
|
|
try {
|
|
|
|
|
await updateSettings(config);
|
|
|
|
|
alert('Configurações salvas com sucesso!');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
alert('Erro ao salvar configurações.');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const tabs = [
|
|
|
|
|
{ id: 'general', label: 'Geral', icon: Building, description: 'Dados cadastrais' },
|
|
|
|
|
{ id: 'fiscal', label: 'Fiscal & NFe', icon: FileCheck, description: 'Certificado e tributação' },
|
|
|
|
|
{ id: 'appearance', label: 'Aparência', icon: Palette, description: 'Temas e Cores' },
|
|
|
|
|
{ id: 'marketplaces', label: 'Marketplaces', icon: ShoppingBag, description: 'Integrações de vendas' },
|
|
|
|
|
{ id: 'logistics', label: 'Logística', icon: Truck, description: 'Fretes e entregas' },
|
|
|
|
|
{ id: 'email', label: 'Email SMTP', icon: Globe, description: 'Configuração de envio' },
|
|
|
|
|
{ id: 'notifications', label: 'Notificações', icon: Bell, description: 'Alertas e avisos' },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="animate-in fade-in duration-500 container mx-auto max-w-[1600px] pb-20">
|
|
|
|
|
|
|
|
|
|
<div className="flex flex-col md:flex-row justify-between items-end mb-6 border-b border-white/5 pb-6">
|
|
|
|
|
<div>
|
|
|
|
|
<h1 className="text-2xl font-bold tracking-tight text-white mb-1">Configurações do Sistema</h1>
|
|
|
|
|
<p className="text-sm text-slate-400">Gerencie todos os parâmetros fiscais, integrações e regras de negócio.</p>
|
|
|
|
|
</div>
|
|
|
|
|
<button
|
|
|
|
|
onClick={handleSave}
|
|
|
|
|
className="bg-indigo-600 hover:bg-indigo-500 text-white px-6 py-2.5 rounded-lg font-bold text-sm shadow-lg shadow-indigo-900/20 active:scale-95 transition-all flex items-center gap-2"
|
|
|
|
|
>
|
|
|
|
|
<Save size={16} /> Salvar Alterações
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
|
|
|
|
|
|
|
|
|
|
{/* Denser Sidebar */}
|
|
|
|
|
<div className="lg:col-span-2 flex flex-col gap-1">
|
|
|
|
|
{tabs.map(tab => (
|
|
|
|
|
<button
|
|
|
|
|
key={tab.id}
|
|
|
|
|
onClick={() => setActiveTab(tab.id as any)}
|
|
|
|
|
className={clsx(
|
|
|
|
|
"text-left px-4 py-3 rounded-lg transition-all border group flex items-center gap-3",
|
|
|
|
|
activeTab === tab.id
|
|
|
|
|
? "bg-indigo-600/10 border-indigo-500/30 text-white"
|
|
|
|
|
: "bg-transparent border-transparent text-slate-400 hover:bg-white/5 hover:text-slate-200"
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
<tab.icon size={16} className={activeTab === tab.id ? "text-indigo-400" : "text-slate-500"} />
|
|
|
|
|
<div className="leading-tight">
|
|
|
|
|
<p className="font-semibold text-xs uppercase tracking-wide">{tab.label}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Content Area - Denser Forms */}
|
|
|
|
|
<div className="lg:col-span-10">
|
|
|
|
|
<div className="bg-[#0F1115] border border-white/10 rounded-xl p-6 shadow-sm min-h-[600px]">
|
|
|
|
|
|
|
|
|
|
{activeTab === 'general' && (
|
|
|
|
|
<div className="space-y-8 animate-in fade-in duration-300">
|
|
|
|
|
{/* Section */}
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-white/5 pb-2">Identificação da Empresa</h3>
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
|
|
|
<div className="md:col-span-1 space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">CNPJ</label>
|
|
|
|
|
<input
|
|
|
|
|
value={config.cnpj}
|
|
|
|
|
onChange={e => setConfig({ ...config, cnpj: e.target.value })}
|
|
|
|
|
placeholder="00.000.000/0000-00"
|
|
|
|
|
className="w-full bg-black/20 border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-200 focus:border-indigo-500 outline-none transition-all font-mono"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="md:col-span-1 space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Inscrição Estadual</label>
|
|
|
|
|
<input
|
|
|
|
|
value={config.ie}
|
|
|
|
|
onChange={e => setConfig({ ...config, ie: e.target.value })}
|
|
|
|
|
className="w-full bg-black/20 border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-200 focus:border-indigo-500 outline-none transition-all"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="md:col-span-1 space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Nome Fantasia</label>
|
|
|
|
|
<input
|
|
|
|
|
value={config.companyName}
|
|
|
|
|
onChange={e => setConfig({ ...config, companyName: e.target.value })}
|
|
|
|
|
className="w-full bg-black/20 border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-200 focus:border-indigo-500 outline-none transition-all"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Section */}
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-white/5 pb-2">Parâmetros Financeiros</h3>
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Cotação Dólar (Base)</label>
|
|
|
|
|
<div className="relative">
|
|
|
|
|
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-500 text-xs font-bold">R$</span>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
value={config.defaultExchange}
|
|
|
|
|
onChange={e => setConfig({ ...config, defaultExchange: parseFloat(e.target.value) })}
|
|
|
|
|
className="w-full bg-black/20 border border-white/10 rounded-lg pl-8 pr-3 py-2 text-sm text-slate-200 focus:border-emerald-500 outline-none transition-all font-mono"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Overhead Padrão (%)</label>
|
|
|
|
|
<div className="relative">
|
|
|
|
|
<span className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-500 text-xs font-bold">%</span>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
value={config.defaultOverhead}
|
|
|
|
|
onChange={e => setConfig({ ...config, defaultOverhead: parseFloat(e.target.value) })}
|
|
|
|
|
className="w-full bg-black/20 border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-200 focus:border-indigo-500 outline-none transition-all font-mono"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-01-27 18:40:32 +00:00
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Custo Energia (R$/kWh)</label>
|
|
|
|
|
<div className="relative">
|
|
|
|
|
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-500 text-xs font-bold">R$</span>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
step="0.01"
|
|
|
|
|
value={config.electricityCostKwh}
|
|
|
|
|
onChange={e => setConfig({ ...config, electricityCostKwh: parseFloat(e.target.value) })}
|
|
|
|
|
className="w-full bg-black/20 border border-white/10 rounded-lg pl-8 pr-3 py-2 text-sm text-slate-200 focus:border-emerald-500 outline-none transition-all font-mono"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-01-26 14:20:25 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{activeTab === 'appearance' && (
|
|
|
|
|
<div className="space-y-8 animate-in fade-in duration-300">
|
|
|
|
|
<ThemeSelector />
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{activeTab === 'fiscal' && (
|
|
|
|
|
<div className="space-y-8 animate-in fade-in duration-300">
|
|
|
|
|
{/* Certificate */}
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-white/5 pb-2">Certificado Digital (A1)</h3>
|
|
|
|
|
|
|
|
|
|
<div className="bg-white/5 border border-white/5 rounded-lg p-6 flex flex-col items-center justify-center border-dashed group hover:border-indigo-500/50 transition-colors cursor-pointer">
|
|
|
|
|
<Upload className="text-slate-500 mb-2 group-hover:text-indigo-400" size={32} />
|
|
|
|
|
<p className="text-sm font-bold text-slate-300 group-hover:text-white">Clique para selecionar o Certificado .PFX</p>
|
|
|
|
|
<p className="text-xs text-slate-500 mt-1">Sua senha será solicitada após o upload</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="mt-4 grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Senha do Certificado</label>
|
|
|
|
|
<input
|
|
|
|
|
type="password"
|
|
|
|
|
value={config.certificatePassword}
|
|
|
|
|
onChange={e => setConfig({ ...config, certificatePassword: e.target.value })}
|
|
|
|
|
className="w-full bg-black/20 border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-200 focus:border-indigo-500 outline-none transition-all"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Validade</label>
|
|
|
|
|
<div className="w-full bg-black/20 border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-500 cursor-not-allowed flex items-center justify-between">
|
|
|
|
|
<span>--/--/----</span>
|
|
|
|
|
<AlertCircle size={14} className="text-amber-500" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* NFe Config */}
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-white/5 pb-2">Configuração de Emissão (NFe 4.0)</h3>
|
|
|
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Próximo Número NFe</label>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
value={config.nfeNumber}
|
|
|
|
|
onChange={e => setConfig({ ...config, nfeNumber: e.target.value })}
|
|
|
|
|
className="w-full bg-black/20 border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-200 focus:border-indigo-500 outline-none transition-all font-mono"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Série</label>
|
|
|
|
|
<input
|
|
|
|
|
type="number"
|
|
|
|
|
value={config.nfeSerie}
|
|
|
|
|
onChange={e => setConfig({ ...config, nfeSerie: e.target.value })}
|
|
|
|
|
className="w-full bg-black/20 border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-200 focus:border-indigo-500 outline-none transition-all font-mono"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="space-y-1.5">
|
|
|
|
|
<label className="text-[10px] font-bold text-slate-500 uppercase">Ambiente</label>
|
|
|
|
|
<select className="w-full bg-black/20 border border-white/10 rounded-lg px-3 py-2 text-sm text-slate-200 focus:border-indigo-500 outline-none transition-all">
|
|
|
|
|
<option value="homologacao">Homologação (Teste)</option>
|
|
|
|
|
<option value="producao">Produção</option>
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{activeTab === 'marketplaces' && (
|
|
|
|
|
<div className="space-y-8 animate-in fade-in duration-300">
|
|
|
|
|
{/* Major Marketplaces */}
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-white/5 pb-2">Hub de Integração (Mais de 30 canais)</h3>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
|
|
|
{[
|
|
|
|
|
{ name: 'Mercado Livre', color: 'bg-yellow-500', status: 'connected', sales: 1240 },
|
|
|
|
|
{ name: 'Shopee', color: 'bg-orange-600', status: 'error', sales: 0 },
|
|
|
|
|
{ name: 'Amazon Seller', color: 'bg-slate-800', status: 'disconnected', sales: 0 },
|
|
|
|
|
{ name: 'Magalu', color: 'bg-blue-600', status: 'disconnected', sales: 0 },
|
|
|
|
|
{ name: 'Via Varejo', color: 'bg-green-600', status: 'disconnected', sales: 0 },
|
|
|
|
|
{ name: 'B2W (Americanas)', color: 'bg-red-600', status: 'disconnected', sales: 0 },
|
|
|
|
|
{ name: 'Shein', color: 'bg-black', status: 'disconnected', sales: 0 },
|
|
|
|
|
{ name: 'AliExpress', color: 'bg-red-500', status: 'disconnected', sales: 0 },
|
|
|
|
|
].map(mk => (
|
|
|
|
|
<div key={mk.name} className="flex flex-col justify-between p-4 bg-white/5 border border-white/5 rounded-lg hover:bg-white/10 transition-colors h-[140px]">
|
|
|
|
|
<div className="flex items-start justify-between">
|
|
|
|
|
<div className="flex items-center gap-3">
|
|
|
|
|
<div className={clsx("w-10 h-10 rounded-lg flex items-center justify-center text-white font-bold text-xs shadow-lg", mk.color)}>
|
|
|
|
|
{mk.name.substring(0, 2)}
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<p className="text-sm font-bold text-white leading-tight">{mk.name}</p>
|
|
|
|
|
{mk.status === 'connected' && <p className="text-[10px] text-emerald-400">● Online</p>}
|
|
|
|
|
{mk.status === 'error' && <p className="text-[10px] text-rose-400">● Erro</p>}
|
|
|
|
|
{mk.status === 'disconnected' && <p className="text-[10px] text-slate-500">● Offline</p>}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Toggle Switch Mockup */}
|
|
|
|
|
<div className={clsx("w-8 h-4 rounded-full relative transition-colors", mk.status === 'connected' ? "bg-emerald-500/20" : "bg-white/10")}>
|
|
|
|
|
<div className={clsx("absolute top-0.5 w-3 h-3 rounded-full transition-all", mk.status === 'connected' ? "left-4 bg-emerald-500" : "left-0.5 bg-slate-500")}></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="mt-4 pt-3 border-t border-white/5 flex items-center justify-between">
|
|
|
|
|
<div>
|
|
|
|
|
{mk.status === 'connected' ? (
|
|
|
|
|
<>
|
|
|
|
|
<p className="text-[10px] text-slate-500 uppercase font-bold">Vendas Hoje</p>
|
|
|
|
|
<p className="text-sm font-bold text-white">R$ {mk.sales.toLocaleString('pt-BR')}</p>
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
<p className="text-[10px] text-slate-600 italic">Clique para configurar</p>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<button className="px-3 py-1.5 rounded bg-white/5 text-[10px] font-bold text-slate-300 hover:bg-white/20 transition-colors uppercase tracking-wide">
|
|
|
|
|
{mk.status === 'disconnected' ? 'Configurar' : 'Gerenciar'}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Custom Sites / E-commerce Platforms */}
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-white/5 pb-2">Lojas Virtuais & Sites Próprios</h3>
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
|
|
|
{[
|
|
|
|
|
{ name: 'WooCommerce', color: 'bg-purple-600' },
|
|
|
|
|
{ name: 'Shopify', color: 'bg-emerald-500' },
|
|
|
|
|
{ name: 'Nuvemshop', color: 'bg-blue-500' },
|
|
|
|
|
{ name: 'Vtex', color: 'bg-pink-600' },
|
|
|
|
|
{ name: 'API Personalizada', color: 'bg-slate-700', isCustom: true },
|
|
|
|
|
].map(platform => (
|
|
|
|
|
<div key={platform.name} className="flex items-center justify-between p-3 bg-white/5 border border-white/5 rounded-lg hover:border-indigo-500/30 transition-all cursor-pointer group">
|
|
|
|
|
<div className="flex items-center gap-3">
|
|
|
|
|
<div className={clsx("w-8 h-8 rounded-lg flex items-center justify-center text-white font-bold text-[10px]", platform.color)}>
|
|
|
|
|
{platform.isCustom ? <Key size={14} /> : platform.name.substring(0, 1)}
|
|
|
|
|
</div>
|
|
|
|
|
<span className="text-sm font-medium text-slate-300 group-hover:text-white transition-colors">{platform.name}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="w-6 h-6 rounded-full border border-white/10 flex items-center justify-center group-hover:bg-indigo-500 group-hover:border-indigo-500 transition-all">
|
|
|
|
|
<div className="w-1.5 h-1.5 bg-white rounded-full opacity-0 group-hover:opacity-100"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
<p className="text-[10px] text-slate-500 mt-2">* Para API Personalizada, consulte a documentação /docs/api-v1</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Automation Settings */}
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-white/5 pb-2">Regras de Sincronização</h3>
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
<div className="flex items-center justify-between p-3 bg-black/20 rounded-lg border border-white/5">
|
|
|
|
|
<div>
|
|
|
|
|
<p className="text-xs font-bold text-slate-200">Importar Pedidos</p>
|
|
|
|
|
<p className="text-[10px] text-slate-500">Baixar vendas novas a cada 5 min.</p>
|
|
|
|
|
</div>
|
|
|
|
|
<input type="checkbox" checked={config.autoSyncSales} onChange={() => setConfig({ ...config, autoSyncSales: !config.autoSyncSales })} className="accent-emerald-500 w-4 h-4" />
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex items-center justify-between p-3 bg-black/20 rounded-lg border border-white/5">
|
|
|
|
|
<div>
|
|
|
|
|
<p className="text-xs font-bold text-slate-200">Atualizar Estoque</p>
|
|
|
|
|
<p className="text-[10px] text-slate-500">Enviar saldo local para os canais.</p>
|
|
|
|
|
</div>
|
|
|
|
|
<input type="checkbox" checked={config.autoSyncStock} onChange={() => setConfig({ ...config, autoSyncStock: !config.autoSyncStock })} className="accent-emerald-500 w-4 h-4" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{activeTab === 'logistics' && (
|
|
|
|
|
<div className="space-y-8 animate-in fade-in duration-300">
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-sm font-bold text-white uppercase tracking-wider mb-4 border-b border-white/5 pb-2">Hubs de Frete</h3>
|
|
|
|
|
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
|
|
|
<div className="p-4 rounded-lg bg-white/5 border border-white/5 space-y-3">
|
|
|
|
|
<div className="flex justify-between items-center">
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<Truck size={18} className="text-blue-400" />
|
|
|
|
|
<span className="font-bold text-sm text-slate-200">Melhor Envio</span>
|
|
|
|
|
</div>
|
|
|
|
|
<span className="text-[10px] font-bold text-emerald-400 bg-emerald-400/10 px-2 py-0.5 rounded">Ativo</span>
|
|
|
|
|
</div>
|
|
|
|
|
<input
|
|
|
|
|
value={config.melhorEnvioToken}
|
|
|
|
|
onChange={e => setConfig({ ...config, melhorEnvioToken: e.target.value })}
|
|
|
|
|
placeholder="Token de Produção"
|
|
|
|
|
type="password"
|
|
|
|
|
className="w-full bg-black/40 border border-white/10 rounded-lg px-3 py-2 text-slate-400 text-xs focus:border-indigo-500 outline-none transition-all font-mono"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="p-4 rounded-lg bg-white/5 border border-white/5 space-y-3 opacity-50">
|
|
|
|
|
<div className="flex justify-between items-center">
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<Truck size={18} className="text-orange-400" />
|
|
|
|
|
<span className="font-bold text-sm text-slate-200">Frenet</span>
|
|
|
|
|
</div>
|
|
|
|
|
<span className="text-[10px] font-bold text-slate-500 bg-white/5 px-2 py-0.5 rounded">Inativo</span>
|
|
|
|
|
</div>
|
|
|
|
|
<input
|
|
|
|
|
placeholder="Token de Acesso"
|
|
|
|
|
disabled
|
|
|
|
|
className="w-full bg-black/40 border border-white/10 rounded-lg px-3 py-2 text-slate-400 text-xs focus:border-indigo-500 outline-none transition-all font-mono"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default Settings;
|