fix: converter para de maiúsculas para primeira maiúcula.
This commit is contained in:
parent
b1d75213ab
commit
97c2d32e03
@ -6,7 +6,6 @@ using OnlyOneAccessTemplate.Models;
|
||||
|
||||
namespace OnlyOneAccessTemplate.Controllers
|
||||
{
|
||||
|
||||
public abstract class BaseController : Controller
|
||||
{
|
||||
protected readonly ISiteConfigurationService _siteConfig;
|
||||
@ -37,6 +36,7 @@ namespace OnlyOneAccessTemplate.Controllers
|
||||
|
||||
SetupSeoViewBag(config, language, currentUrl);
|
||||
SetupContentViewBag(config, language);
|
||||
SetupConverterViewBag(language); // Nova configuração específica do conversor
|
||||
base.OnActionExecuting(context);
|
||||
}
|
||||
|
||||
@ -118,6 +118,246 @@ namespace OnlyOneAccessTemplate.Controllers
|
||||
ViewBag.ConversionConfig = config.Conversion;
|
||||
}
|
||||
|
||||
// Nova função para configurar textos específicos do conversor
|
||||
protected void SetupConverterViewBag(string language)
|
||||
{
|
||||
var converterType = _configuration.GetValue<string>("Converter:Type") ?? "generic";
|
||||
var converterName = _configuration.GetValue<string>("Converter:Name") ?? "Conversor Online";
|
||||
|
||||
switch (language)
|
||||
{
|
||||
case "en":
|
||||
SetupEnglishConverterContent(converterType, converterName);
|
||||
break;
|
||||
case "es":
|
||||
SetupSpanishConverterContent(converterType, converterName);
|
||||
break;
|
||||
default:
|
||||
SetupPortugueseConverterContent(converterType, converterName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SetupPortugueseConverterContent(string converterType, string converterName)
|
||||
{
|
||||
// Configurações específicas por tipo de conversor
|
||||
switch (converterType)
|
||||
{
|
||||
case "text-case":
|
||||
ViewBag.ConverterTitle = "CONVERSOR DE MAIÚSCULAS E MINÚSCULAS";
|
||||
ViewBag.ConverterDescription = "Converta texto entre maiúsculas, minúsculas, título e primeira maiúscula";
|
||||
ViewBag.Step1Title = "Cole o Texto";
|
||||
ViewBag.Step1Description = "Digite ou cole o texto que deseja converter";
|
||||
ViewBag.Step2Title = "Escolha o Formato";
|
||||
ViewBag.Step2Description = "Selecione o tipo de conversão desejada";
|
||||
ViewBag.Step3Title = "Copie o Resultado";
|
||||
ViewBag.Step3Description = "Copie o texto convertido";
|
||||
ViewBag.InputLabel = "Texto Original";
|
||||
ViewBag.OutputLabel = "Texto Convertido";
|
||||
ViewBag.InputPlaceholder = "Digite ou cole seu texto aqui...";
|
||||
ViewBag.OutputPlaceholder = "O texto convertido aparecerá aqui...";
|
||||
ViewBag.ConvertButtonText = "Converter Texto";
|
||||
ViewBag.ConverterType = "text";
|
||||
ViewBag.OutputType = "text";
|
||||
ViewBag.HasAdvancedOptions = true;
|
||||
break;
|
||||
|
||||
case "csv-json":
|
||||
ViewBag.ConverterTitle = "CONVERSOR CSV PARA JSON";
|
||||
ViewBag.ConverterDescription = "Converta arquivos CSV para formato JSON de forma rápida e fácil";
|
||||
ViewBag.Step1Title = "Upload CSV";
|
||||
ViewBag.Step1Description = "Selecione um arquivo CSV ou cole o conteúdo";
|
||||
ViewBag.Step2Title = "Processar";
|
||||
ViewBag.Step2Description = "Aguarde a conversão automática";
|
||||
ViewBag.Step3Title = "Baixar JSON";
|
||||
ViewBag.Step3Description = "Baixe ou copie o resultado";
|
||||
ViewBag.InputLabel = "Arquivo CSV";
|
||||
ViewBag.OutputLabel = "Resultado JSON";
|
||||
ViewBag.InputPlaceholder = "Cole o conteúdo CSV aqui ou faça upload de um arquivo...";
|
||||
ViewBag.OutputPlaceholder = "O JSON convertido aparecerá aqui...";
|
||||
ViewBag.ConvertButtonText = "Converter para JSON";
|
||||
ViewBag.ConverterType = "text"; // Aceita texto e arquivo
|
||||
ViewBag.OutputType = "text";
|
||||
ViewBag.AcceptedFileTypes = ".csv,.txt";
|
||||
ViewBag.FileHelpText = "Tamanho máximo: 10MB. Formatos: CSV, TXT";
|
||||
break;
|
||||
|
||||
case "image-ocr":
|
||||
ViewBag.ConverterTitle = "CONVERSOR DE IMAGEM PARA TEXTO - OCR ONLINE";
|
||||
ViewBag.ConverterDescription = "Extraia texto de imagens usando tecnologia de Reconhecimento Óptico de Caracteres";
|
||||
ViewBag.Step1Title = "Upload Imagem";
|
||||
ViewBag.Step1Description = "Selecione uma imagem com texto";
|
||||
ViewBag.Step2Title = "Processar OCR";
|
||||
ViewBag.Step2Description = "Aguarde a extração do texto";
|
||||
ViewBag.Step3Title = "Copiar Texto";
|
||||
ViewBag.Step3Description = "Copie ou baixe o texto extraído";
|
||||
ViewBag.InputLabel = "Imagem";
|
||||
ViewBag.OutputLabel = "Texto Extraído";
|
||||
ViewBag.SelectFileText = "SELECIONAR IMAGEM";
|
||||
ViewBag.ConvertButtonText = "Extrair Texto";
|
||||
ViewBag.ConverterType = "file";
|
||||
ViewBag.OutputType = "text";
|
||||
ViewBag.AcceptedFileTypes = ".jpg,.jpeg,.png,.gif,.bmp,.pdf";
|
||||
ViewBag.FileHelpText = "Tamanho máximo: 15MB. Formatos: JPG, PNG, GIF, BMP, PDF";
|
||||
ViewBag.HasAdvancedOptions = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Configuração genérica
|
||||
ViewBag.ConverterTitle = converterName.ToUpper();
|
||||
ViewBag.ConverterDescription = "Converta seus arquivos de forma rápida e segura";
|
||||
ViewBag.Step1Title = "Entrada";
|
||||
ViewBag.Step1Description = "Selecione ou cole seu conteúdo";
|
||||
ViewBag.Step2Title = "Processar";
|
||||
ViewBag.Step2Description = "Aguarde o processamento";
|
||||
ViewBag.Step3Title = "Resultado";
|
||||
ViewBag.Step3Description = "Baixe ou copie o resultado";
|
||||
ViewBag.ConvertButtonText = "Converter";
|
||||
ViewBag.ConverterType = "text";
|
||||
ViewBag.OutputType = "text";
|
||||
break;
|
||||
}
|
||||
|
||||
// Textos comuns do conversor
|
||||
ViewBag.LoadingText = "Processando...";
|
||||
ViewBag.ProcessingText = "Convertendo seu arquivo...";
|
||||
ViewBag.CopyButtonText = "Copiar";
|
||||
ViewBag.ClearButtonText = "Limpar";
|
||||
ViewBag.ShareButtonText = "Compartilhar";
|
||||
ViewBag.CopiedText = "Copiado!";
|
||||
ViewBag.DownloadButtonText = "Baixar";
|
||||
ViewBag.DownloadReadyText = "Seu arquivo está pronto!";
|
||||
ViewBag.SecurityText = "Seus dados estão seguros conosco";
|
||||
ViewBag.DefaultErrorMessage = "Erro ao processar. Tente novamente.";
|
||||
ViewBag.AdvancedOptionsText = "Opções Avançadas";
|
||||
ViewBag.PreviewPlaceholder = "O resultado aparecerá aqui...";
|
||||
|
||||
// Configurações de benefícios
|
||||
ViewBag.BenefitsTitle = "Por Que Usar Nossa Ferramenta?";
|
||||
ViewBag.BenefitsSubtitle = "Descubra os benefícios de nossa solução";
|
||||
ViewBag.FinalCtaTitle = "Pronto para Converter?";
|
||||
ViewBag.FinalCtaSubtitle = "Use nossa ferramenta gratuita agora mesmo";
|
||||
ViewBag.FinalCtaButtonText = "Começar Conversão";
|
||||
|
||||
// Features padrão se não especificadas
|
||||
if (ViewBag.Feature1Title == null)
|
||||
{
|
||||
ViewBag.Feature1Title = "Rápido e Fácil";
|
||||
ViewBag.Feature1Description = "Conversão instantânea sem complicações";
|
||||
ViewBag.Feature2Title = "Seguro";
|
||||
ViewBag.Feature2Description = "Seus dados são processados com segurança";
|
||||
ViewBag.Feature3Title = "Gratuito";
|
||||
ViewBag.Feature3Description = "Use nossa ferramenta sem custos";
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void SetupEnglishConverterContent(string converterType, string converterName)
|
||||
{
|
||||
switch (converterType)
|
||||
{
|
||||
case "text-case":
|
||||
ViewBag.ConverterTitle = "TEXT CASE CONVERTER";
|
||||
ViewBag.ConverterDescription = "Convert text between uppercase, lowercase, title case and sentence case";
|
||||
ViewBag.Step1Title = "Paste Text";
|
||||
ViewBag.Step1Description = "Type or paste the text you want to convert";
|
||||
ViewBag.Step2Title = "Choose Format";
|
||||
ViewBag.Step2Description = "Select the desired conversion type";
|
||||
ViewBag.Step3Title = "Copy Result";
|
||||
ViewBag.Step3Description = "Copy the converted text";
|
||||
ViewBag.InputLabel = "Original Text";
|
||||
ViewBag.OutputLabel = "Converted Text";
|
||||
ViewBag.InputPlaceholder = "Type or paste your text here...";
|
||||
ViewBag.OutputPlaceholder = "Converted text will appear here...";
|
||||
ViewBag.ConvertButtonText = "Convert Text";
|
||||
break;
|
||||
|
||||
case "csv-json":
|
||||
ViewBag.ConverterTitle = "CSV TO JSON CONVERTER";
|
||||
ViewBag.ConverterDescription = "Convert CSV files to JSON format quickly and easily";
|
||||
ViewBag.Step1Title = "Upload CSV";
|
||||
ViewBag.Step1Description = "Select a CSV file or paste content";
|
||||
ViewBag.Step2Title = "Process";
|
||||
ViewBag.Step2Description = "Wait for automatic conversion";
|
||||
ViewBag.Step3Title = "Download JSON";
|
||||
ViewBag.Step3Description = "Download or copy the result";
|
||||
ViewBag.ConvertButtonText = "Convert to JSON";
|
||||
break;
|
||||
|
||||
case "image-ocr":
|
||||
ViewBag.ConverterTitle = "IMAGE TO TEXT CONVERTER - OCR ONLINE";
|
||||
ViewBag.ConverterDescription = "Extract text from images using Optical Character Recognition technology";
|
||||
ViewBag.Step1Title = "Upload Image";
|
||||
ViewBag.Step1Description = "Select an image with text";
|
||||
ViewBag.Step2Title = "Process OCR";
|
||||
ViewBag.Step2Description = "Wait for text extraction";
|
||||
ViewBag.Step3Title = "Copy Text";
|
||||
ViewBag.Step3Description = "Copy or download extracted text";
|
||||
ViewBag.SelectFileText = "SELECT IMAGE";
|
||||
ViewBag.ConvertButtonText = "Extract Text";
|
||||
break;
|
||||
|
||||
default:
|
||||
ViewBag.ConverterTitle = converterName.ToUpper();
|
||||
ViewBag.ConverterDescription = "Convert your files quickly and securely";
|
||||
ViewBag.ConvertButtonText = "Convert";
|
||||
break;
|
||||
}
|
||||
|
||||
// Common English texts
|
||||
ViewBag.LoadingText = "Processing...";
|
||||
ViewBag.ProcessingText = "Converting your file...";
|
||||
ViewBag.CopyButtonText = "Copy";
|
||||
ViewBag.ClearButtonText = "Clear";
|
||||
ViewBag.ShareButtonText = "Share";
|
||||
ViewBag.CopiedText = "Copied!";
|
||||
ViewBag.DownloadButtonText = "Download";
|
||||
ViewBag.SecurityText = "Your data is safe with us";
|
||||
ViewBag.BenefitsTitle = "Why Use Our Tool?";
|
||||
ViewBag.FinalCtaTitle = "Ready to Convert?";
|
||||
}
|
||||
|
||||
protected virtual void SetupSpanishConverterContent(string converterType, string converterName)
|
||||
{
|
||||
switch (converterType)
|
||||
{
|
||||
case "text-case":
|
||||
ViewBag.ConverterTitle = "CONVERTIDOR DE MAYÚSCULAS Y MINÚSCULAS";
|
||||
ViewBag.ConverterDescription = "Convierte texto entre mayúsculas, minúsculas, título y oración";
|
||||
ViewBag.ConvertButtonText = "Convertir Texto";
|
||||
break;
|
||||
|
||||
case "csv-json":
|
||||
ViewBag.ConverterTitle = "CONVERTIDOR CSV A JSON";
|
||||
ViewBag.ConverterDescription = "Convierte archivos CSV a formato JSON de forma rápida y fácil";
|
||||
ViewBag.ConvertButtonText = "Convertir a JSON";
|
||||
break;
|
||||
|
||||
case "image-ocr":
|
||||
ViewBag.ConverterTitle = "CONVERTIDOR DE IMAGEN A TEXTO - OCR EN LÍNEA";
|
||||
ViewBag.ConverterDescription = "Extrae texto de imágenes usando tecnología de Reconocimiento Óptico de Caracteres";
|
||||
ViewBag.SelectFileText = "SELECCIONAR IMAGEN";
|
||||
ViewBag.ConvertButtonText = "Extraer Texto";
|
||||
break;
|
||||
|
||||
default:
|
||||
ViewBag.ConverterTitle = converterName.ToUpper();
|
||||
ViewBag.ConverterDescription = "Convierte tus archivos de forma rápida y segura";
|
||||
ViewBag.ConvertButtonText = "Convertir";
|
||||
break;
|
||||
}
|
||||
|
||||
// Common Spanish texts
|
||||
ViewBag.LoadingText = "Procesando...";
|
||||
ViewBag.ProcessingText = "Convirtiendo tu archivo...";
|
||||
ViewBag.CopyButtonText = "Copiar";
|
||||
ViewBag.ClearButtonText = "Limpiar";
|
||||
ViewBag.CopiedText = "¡Copiado!";
|
||||
ViewBag.SecurityText = "Tus datos están seguros con nosotros";
|
||||
ViewBag.BenefitsTitle = "¿Por Qué Usar Nuestra Herramienta?";
|
||||
ViewBag.FinalCtaTitle = "¿Listo para Convertir?";
|
||||
}
|
||||
|
||||
// Resto dos métodos permanece igual...
|
||||
protected void SetupPortugueseContent()
|
||||
{
|
||||
// Menu
|
||||
@ -127,104 +367,18 @@ namespace OnlyOneAccessTemplate.Controllers
|
||||
ViewBag.MenuPrivacy = "Privacidade";
|
||||
ViewBag.MenuTerms = "Termos";
|
||||
|
||||
// Hero Section
|
||||
ViewBag.DefaultHeroTitle = "Transforme Seu Negócio com Nossa Solução";
|
||||
ViewBag.DefaultHeroSubtitle = "Aumente suas vendas em até 300% com nossa metodologia comprovada e suporte especializado.";
|
||||
ViewBag.DefaultCtaText = "Comece Agora";
|
||||
ViewBag.WatchVideoText = "Assistir Vídeo";
|
||||
|
||||
// Features
|
||||
ViewBag.DefaultFeaturesTitle = "Por Que Escolher Nossa Solução?";
|
||||
ViewBag.DefaultFeaturesSubtitle = "Descubra os benefícios que já transformaram mais de 1000 empresas";
|
||||
ViewBag.Feature1Title = "Resultados Rápidos";
|
||||
ViewBag.Feature1Description = "Veja os primeiros resultados em até 30 dias";
|
||||
ViewBag.Feature2Title = "Suporte 24/7";
|
||||
ViewBag.Feature2Description = "Equipe especializada sempre disponível";
|
||||
ViewBag.Feature3Title = "Metodologia Comprovada";
|
||||
ViewBag.Feature3Description = "Mais de 1000 casos de sucesso documentados";
|
||||
|
||||
// Form
|
||||
ViewBag.FormTitle = "Solicite uma Demonstração Gratuita";
|
||||
ViewBag.FormSubtitle = "Preencha o formulário e nossa equipe entrará em contato";
|
||||
ViewBag.NameLabel = "Nome Completo";
|
||||
ViewBag.NamePlaceholder = "Digite seu nome completo";
|
||||
ViewBag.EmailLabel = "E-mail";
|
||||
ViewBag.EmailPlaceholder = "Digite seu e-mail";
|
||||
ViewBag.PhoneLabel = "Telefone";
|
||||
ViewBag.PhonePlaceholder = "Digite seu telefone";
|
||||
ViewBag.SubmitButtonText = "Solicitar Demonstração";
|
||||
ViewBag.LoadingText = "Enviando...";
|
||||
|
||||
// Quick Form
|
||||
ViewBag.QuickFormTitle = "Acesso Rápido";
|
||||
ViewBag.QuickSubmitText = "Começar Agora";
|
||||
ViewBag.QuickConsentText = "Concordo em receber informações por e-mail";
|
||||
|
||||
// Validation
|
||||
ViewBag.RequiredFieldMessage = "Este campo é obrigatório";
|
||||
ViewBag.EmailValidationMessage = "Digite um e-mail válido";
|
||||
ViewBag.PhoneValidationMessage = "Digite um telefone válido";
|
||||
ViewBag.ConsentValidationMessage = "Você deve concordar para continuar";
|
||||
|
||||
// Consent
|
||||
ViewBag.ConsentText = "Concordo em receber comunicações e com a <a href='/privacy'>Política de Privacidade</a>";
|
||||
|
||||
// Benefits
|
||||
ViewBag.BenefitsTitle = "O que você vai receber:";
|
||||
ViewBag.DefaultBenefit1 = "Consultoria personalizada";
|
||||
ViewBag.DefaultBenefit2 = "Suporte técnico especializado";
|
||||
ViewBag.DefaultBenefit3 = "Garantia de resultados";
|
||||
|
||||
// Testimonials
|
||||
ViewBag.DefaultTestimonialsTitle = "O Que Nossos Clientes Dizem";
|
||||
ViewBag.DefaultTestimonialsSubtitle = "Mais de 1000 empresas já transformaram seus resultados";
|
||||
SetupPortugueseTestimonials();
|
||||
|
||||
// CTA
|
||||
ViewBag.DefaultCtaTitle = "Pronto para Transformar Seu Negócio?";
|
||||
ViewBag.DefaultCtaSubtitle = "Junte-se a mais de 1000 empresas que já alcançaram resultados extraordinários";
|
||||
ViewBag.DefaultCtaButtonText = "Começar Transformação";
|
||||
|
||||
// Footer
|
||||
ViewBag.FooterDescription = "Transformando negócios através de soluções inovadoras";
|
||||
ViewBag.FooterDescription = "Transformando dados através de soluções inovadoras";
|
||||
ViewBag.FooterMenuTitle = "Links";
|
||||
ViewBag.FooterLegalTitle = "Legal";
|
||||
ViewBag.FooterContactTitle = "Contato";
|
||||
ViewBag.FooterCopyright = "Todos os direitos reservados.";
|
||||
ViewBag.FooterMadeWith = "Feito com ❤️ no Brasil";
|
||||
|
||||
// Success
|
||||
ViewBag.SuccessTitle = "Obrigado!";
|
||||
ViewBag.SuccessMessage = "Recebemos sua solicitação. Nossa equipe entrará em contato em breve.";
|
||||
ViewBag.CloseButtonText = "Fechar";
|
||||
|
||||
// Thank You Page
|
||||
ViewBag.NextStepsTitle = "O que acontece agora?";
|
||||
ViewBag.Step1Title = "Análise";
|
||||
ViewBag.Step1Description = "Nossa equipe analisará sua solicitação";
|
||||
ViewBag.Step2Title = "Contato";
|
||||
ViewBag.Step2Description = "Entraremos em contato em até 24h";
|
||||
ViewBag.Step3Title = "Implementação";
|
||||
ViewBag.Step3Description = "Iniciaremos sua transformação";
|
||||
ViewBag.ContactInfoTitle = "Precisa falar conosco?";
|
||||
ViewBag.BackToHomeText = "Voltar ao Início";
|
||||
ViewBag.WhatsAppText = "Falar no WhatsApp";
|
||||
ViewBag.RedirectConfirmText = "Deseja voltar à página inicial?";
|
||||
|
||||
// Security
|
||||
ViewBag.SecurityText = "Seus dados estão seguros conosco";
|
||||
|
||||
// Time
|
||||
ViewBag.DaysText = "Dias";
|
||||
ViewBag.HoursText = "Horas";
|
||||
ViewBag.MinutesText = "Min";
|
||||
ViewBag.SecondsText = "Seg";
|
||||
|
||||
// Contact info
|
||||
ViewBag.ContactEmail = "contato@seusite.com";
|
||||
ViewBag.ContactPhone = "(11) 99999-9999";
|
||||
ViewBag.ContactAddress = "São Paulo, SP";
|
||||
ViewBag.TestimonialsCount = "Mais de 500 avaliações 5 estrelas";
|
||||
}
|
||||
|
||||
protected void SetupEnglishContent()
|
||||
@ -236,104 +390,18 @@ namespace OnlyOneAccessTemplate.Controllers
|
||||
ViewBag.MenuPrivacy = "Privacy";
|
||||
ViewBag.MenuTerms = "Terms";
|
||||
|
||||
// Hero Section
|
||||
ViewBag.DefaultHeroTitle = "Transform Your Business with Our Solution";
|
||||
ViewBag.DefaultHeroSubtitle = "Increase your sales by up to 300% with our proven methodology and expert support.";
|
||||
ViewBag.DefaultCtaText = "Get Started";
|
||||
ViewBag.WatchVideoText = "Watch Video";
|
||||
|
||||
// Features
|
||||
ViewBag.DefaultFeaturesTitle = "Why Choose Our Solution?";
|
||||
ViewBag.DefaultFeaturesSubtitle = "Discover the benefits that have already transformed over 1000 companies";
|
||||
ViewBag.Feature1Title = "Fast Results";
|
||||
ViewBag.Feature1Description = "See first results within 30 days";
|
||||
ViewBag.Feature2Title = "24/7 Support";
|
||||
ViewBag.Feature2Description = "Specialized team always available";
|
||||
ViewBag.Feature3Title = "Proven Method";
|
||||
ViewBag.Feature3Description = "Over 1000 documented success cases";
|
||||
|
||||
// Form
|
||||
ViewBag.FormTitle = "Request a Free Demo";
|
||||
ViewBag.FormSubtitle = "Fill out the form and our team will contact you";
|
||||
ViewBag.NameLabel = "Full Name";
|
||||
ViewBag.NamePlaceholder = "Enter your full name";
|
||||
ViewBag.EmailLabel = "Email";
|
||||
ViewBag.EmailPlaceholder = "Enter your email";
|
||||
ViewBag.PhoneLabel = "Phone";
|
||||
ViewBag.PhonePlaceholder = "Enter your phone";
|
||||
ViewBag.SubmitButtonText = "Request Demo";
|
||||
ViewBag.LoadingText = "Sending...";
|
||||
|
||||
// Quick Form
|
||||
ViewBag.QuickFormTitle = "Quick Access";
|
||||
ViewBag.QuickSubmitText = "Start Now";
|
||||
ViewBag.QuickConsentText = "I agree to receive information by email";
|
||||
|
||||
// Validation
|
||||
ViewBag.RequiredFieldMessage = "This field is required";
|
||||
ViewBag.EmailValidationMessage = "Enter a valid email";
|
||||
ViewBag.PhoneValidationMessage = "Enter a valid phone";
|
||||
ViewBag.ConsentValidationMessage = "You must agree to continue";
|
||||
|
||||
// Consent
|
||||
ViewBag.ConsentText = "I agree to receive communications and with the <a href='/en/privacy'>Privacy Policy</a>";
|
||||
|
||||
// Benefits
|
||||
ViewBag.BenefitsTitle = "What you'll receive:";
|
||||
ViewBag.DefaultBenefit1 = "Personalized consultation";
|
||||
ViewBag.DefaultBenefit2 = "Specialized technical support";
|
||||
ViewBag.DefaultBenefit3 = "Results guarantee";
|
||||
|
||||
// Testimonials
|
||||
ViewBag.DefaultTestimonialsTitle = "What Our Clients Say";
|
||||
ViewBag.DefaultTestimonialsSubtitle = "Over 1000 companies have already transformed their results";
|
||||
SetupEnglishTestimonials();
|
||||
|
||||
// CTA
|
||||
ViewBag.DefaultCtaTitle = "Ready to Transform Your Business?";
|
||||
ViewBag.DefaultCtaSubtitle = "Join over 1000 companies that have already achieved extraordinary results";
|
||||
ViewBag.DefaultCtaButtonText = "Start Transformation";
|
||||
|
||||
// Footer
|
||||
ViewBag.FooterDescription = "Transforming businesses through innovative solutions";
|
||||
ViewBag.FooterDescription = "Transforming data through innovative solutions";
|
||||
ViewBag.FooterMenuTitle = "Links";
|
||||
ViewBag.FooterLegalTitle = "Legal";
|
||||
ViewBag.FooterContactTitle = "Contact";
|
||||
ViewBag.FooterCopyright = "All rights reserved.";
|
||||
ViewBag.FooterMadeWith = "Made with ❤️ in Brazil";
|
||||
|
||||
// Success
|
||||
ViewBag.SuccessTitle = "Thank You!";
|
||||
ViewBag.SuccessMessage = "We received your request. Our team will contact you soon.";
|
||||
ViewBag.CloseButtonText = "Close";
|
||||
|
||||
// Thank You Page
|
||||
ViewBag.NextStepsTitle = "What happens next?";
|
||||
ViewBag.Step1Title = "Analysis";
|
||||
ViewBag.Step1Description = "Our team will analyze your request";
|
||||
ViewBag.Step2Title = "Contact";
|
||||
ViewBag.Step2Description = "We'll contact you within 24h";
|
||||
ViewBag.Step3Title = "Implementation";
|
||||
ViewBag.Step3Description = "We'll start your transformation";
|
||||
ViewBag.ContactInfoTitle = "Need to talk to us?";
|
||||
ViewBag.BackToHomeText = "Back to Home";
|
||||
ViewBag.WhatsAppText = "Chat on WhatsApp";
|
||||
ViewBag.RedirectConfirmText = "Would you like to return to the home page?";
|
||||
|
||||
// Security
|
||||
ViewBag.SecurityText = "Your data is safe with us";
|
||||
|
||||
// Time
|
||||
ViewBag.DaysText = "Days";
|
||||
ViewBag.HoursText = "Hours";
|
||||
ViewBag.MinutesText = "Min";
|
||||
ViewBag.SecondsText = "Sec";
|
||||
|
||||
// Contact info
|
||||
ViewBag.ContactEmail = "contact@yoursite.com";
|
||||
ViewBag.ContactPhone = "+1 (555) 123-4567";
|
||||
ViewBag.ContactAddress = "New York, NY";
|
||||
ViewBag.TestimonialsCount = "Over 500 five-star reviews";
|
||||
}
|
||||
|
||||
protected void SetupSpanishContent()
|
||||
@ -345,149 +413,18 @@ namespace OnlyOneAccessTemplate.Controllers
|
||||
ViewBag.MenuPrivacy = "Privacidad";
|
||||
ViewBag.MenuTerms = "Términos";
|
||||
|
||||
// Hero Section
|
||||
ViewBag.DefaultHeroTitle = "Transforma Tu Negocio con Nuestra Solución";
|
||||
ViewBag.DefaultHeroSubtitle = "Aumenta tus ventas hasta un 300% con nuestra metodología probada y soporte especializado.";
|
||||
ViewBag.DefaultCtaText = "Comenzar Ahora";
|
||||
ViewBag.WatchVideoText = "Ver Video";
|
||||
|
||||
// Features
|
||||
ViewBag.DefaultFeaturesTitle = "¿Por Qué Elegir Nuestra Solución?";
|
||||
ViewBag.DefaultFeaturesSubtitle = "Descubre los beneficios que ya han transformado más de 1000 empresas";
|
||||
ViewBag.Feature1Title = "Resultados Rápidos";
|
||||
ViewBag.Feature1Description = "Ve los primeros resultados en 30 días";
|
||||
ViewBag.Feature2Title = "Soporte 24/7";
|
||||
ViewBag.Feature2Description = "Equipo especializado siempre disponible";
|
||||
ViewBag.Feature3Title = "Metodología Probada";
|
||||
ViewBag.Feature3Description = "Más de 1000 casos de éxito documentados";
|
||||
|
||||
// Form
|
||||
ViewBag.FormTitle = "Solicita una Demo Gratuita";
|
||||
ViewBag.FormSubtitle = "Completa el formulario y nuestro equipo te contactará";
|
||||
ViewBag.NameLabel = "Nombre Completo";
|
||||
ViewBag.NamePlaceholder = "Ingresa tu nombre completo";
|
||||
ViewBag.EmailLabel = "Correo";
|
||||
ViewBag.EmailPlaceholder = "Ingresa tu correo";
|
||||
ViewBag.PhoneLabel = "Teléfono";
|
||||
ViewBag.PhonePlaceholder = "Ingresa tu teléfono";
|
||||
ViewBag.SubmitButtonText = "Solicitar Demo";
|
||||
ViewBag.LoadingText = "Enviando...";
|
||||
|
||||
// Quick Form
|
||||
ViewBag.QuickFormTitle = "Acceso Rápido";
|
||||
ViewBag.QuickSubmitText = "Comenzar Ahora";
|
||||
ViewBag.QuickConsentText = "Acepto recibir información por correo";
|
||||
|
||||
// Validation
|
||||
ViewBag.RequiredFieldMessage = "Este campo es obligatorio";
|
||||
ViewBag.EmailValidationMessage = "Ingresa un correo válido";
|
||||
ViewBag.PhoneValidationMessage = "Ingresa un teléfono válido";
|
||||
ViewBag.ConsentValidationMessage = "Debes aceptar para continuar";
|
||||
|
||||
// Consent
|
||||
ViewBag.ConsentText = "Acepto recibir comunicaciones y la <a href='/es/privacy'>Política de Privacidad</a>";
|
||||
|
||||
// Benefits
|
||||
ViewBag.BenefitsTitle = "Lo que recibirás:";
|
||||
ViewBag.DefaultBenefit1 = "Consultoría personalizada";
|
||||
ViewBag.DefaultBenefit2 = "Soporte técnico especializado";
|
||||
ViewBag.DefaultBenefit3 = "Garantía de resultados";
|
||||
|
||||
// Testimonials
|
||||
ViewBag.DefaultTestimonialsTitle = "Lo Que Dicen Nuestros Clientes";
|
||||
ViewBag.DefaultTestimonialsSubtitle = "Más de 1000 empresas ya han transformado sus resultados";
|
||||
SetupSpanishTestimonials();
|
||||
|
||||
// CTA
|
||||
ViewBag.DefaultCtaTitle = "¿Listo para Transformar Tu Negocio?";
|
||||
ViewBag.DefaultCtaSubtitle = "Únete a más de 1000 empresas que ya han logrado resultados extraordinarios";
|
||||
ViewBag.DefaultCtaButtonText = "Comenzar Transformación";
|
||||
|
||||
// Footer
|
||||
ViewBag.FooterDescription = "Transformando negocios a través de soluciones innovadoras";
|
||||
ViewBag.FooterDescription = "Transformando datos a través de soluciones innovadoras";
|
||||
ViewBag.FooterMenuTitle = "Enlaces";
|
||||
ViewBag.FooterLegalTitle = "Legal";
|
||||
ViewBag.FooterContactTitle = "Contacto";
|
||||
ViewBag.FooterCopyright = "Todos los derechos reservados.";
|
||||
ViewBag.FooterMadeWith = "Hecho con ❤️ en Brasil";
|
||||
|
||||
// Success
|
||||
ViewBag.SuccessTitle = "¡Gracias!";
|
||||
ViewBag.SuccessMessage = "Recibimos tu solicitud. Nuestro equipo te contactará pronto.";
|
||||
ViewBag.CloseButtonText = "Cerrar";
|
||||
|
||||
// Thank You Page
|
||||
ViewBag.NextStepsTitle = "¿Qué pasa ahora?";
|
||||
ViewBag.Step1Title = "Análisis";
|
||||
ViewBag.Step1Description = "Nuestro equipo analizará tu solicitud";
|
||||
ViewBag.Step2Title = "Contacto";
|
||||
ViewBag.Step2Description = "Te contactaremos en 24h";
|
||||
ViewBag.Step3Title = "Implementación";
|
||||
ViewBag.Step3Description = "Comenzaremos tu transformación";
|
||||
ViewBag.ContactInfoTitle = "¿Necesitas hablar con nosotros?";
|
||||
ViewBag.BackToHomeText = "Volver al Inicio";
|
||||
ViewBag.WhatsAppText = "Hablar por WhatsApp";
|
||||
ViewBag.RedirectConfirmText = "¿Te gustaría volver a la página principal?";
|
||||
|
||||
// Security
|
||||
ViewBag.SecurityText = "Tus datos están seguros con nosotros";
|
||||
|
||||
// Time
|
||||
ViewBag.DaysText = "Días";
|
||||
ViewBag.HoursText = "Horas";
|
||||
ViewBag.MinutesText = "Min";
|
||||
ViewBag.SecondsText = "Seg";
|
||||
|
||||
// Contact info
|
||||
ViewBag.ContactEmail = "contacto@tusitioweb.com";
|
||||
ViewBag.ContactPhone = "+34 123 456 789";
|
||||
ViewBag.ContactAddress = "Madrid, España";
|
||||
ViewBag.TestimonialsCount = "Más de 500 reseñas de 5 estrellas";
|
||||
}
|
||||
|
||||
protected void SetupPortugueseTestimonials()
|
||||
{
|
||||
ViewBag.Testimonial1Quote = "Aumentamos nossas vendas em 250% em apenas 3 meses. Incrível!";
|
||||
ViewBag.Testimonial1Name = "Maria Silva";
|
||||
ViewBag.Testimonial1Position = "CEO, TechStart";
|
||||
|
||||
ViewBag.Testimonial2Quote = "O suporte é excepcional. Sempre prontos a ajudar quando precisamos.";
|
||||
ViewBag.Testimonial2Name = "João Santos";
|
||||
ViewBag.Testimonial2Position = "Diretor, InovaCorp";
|
||||
|
||||
ViewBag.Testimonial3Quote = "A metodologia realmente funciona. Resultados visíveis desde o primeiro mês.";
|
||||
ViewBag.Testimonial3Name = "Ana Costa";
|
||||
ViewBag.Testimonial3Position = "Gerente, GrowBiz";
|
||||
}
|
||||
|
||||
protected void SetupEnglishTestimonials()
|
||||
{
|
||||
ViewBag.Testimonial1Quote = "We increased our sales by 250% in just 3 months. Amazing!";
|
||||
ViewBag.Testimonial1Name = "Mary Johnson";
|
||||
ViewBag.Testimonial1Position = "CEO, TechStart";
|
||||
|
||||
ViewBag.Testimonial2Quote = "The support is exceptional. Always ready to help when we need it.";
|
||||
ViewBag.Testimonial2Name = "John Smith";
|
||||
ViewBag.Testimonial2Position = "Director, InovaCorp";
|
||||
|
||||
ViewBag.Testimonial3Quote = "The methodology really works. Visible results from the first month.";
|
||||
ViewBag.Testimonial3Name = "Sarah Davis";
|
||||
ViewBag.Testimonial3Position = "Manager, GrowBiz";
|
||||
}
|
||||
|
||||
protected void SetupSpanishTestimonials()
|
||||
{
|
||||
ViewBag.Testimonial1Quote = "Aumentamos nuestras ventas un 250% en solo 3 meses. ¡Increíble!";
|
||||
ViewBag.Testimonial1Name = "María García";
|
||||
ViewBag.Testimonial1Position = "CEO, TechStart";
|
||||
|
||||
ViewBag.Testimonial2Quote = "El soporte es excepcional. Siempre listos para ayudar cuando lo necesitamos.";
|
||||
ViewBag.Testimonial2Name = "Carlos López";
|
||||
ViewBag.Testimonial2Position = "Director, InovaCorp";
|
||||
|
||||
ViewBag.Testimonial3Quote = "La metodología realmente funciona. Resultados visibles desde el primer mes.";
|
||||
ViewBag.Testimonial3Name = "Ana Rodríguez";
|
||||
ViewBag.Testimonial3Position = "Gerente, GrowBiz";
|
||||
}
|
||||
|
||||
protected void SetupHreflangUrls(string currentUrl, string currentLanguage)
|
||||
@ -523,4 +460,4 @@ namespace OnlyOneAccessTemplate.Controllers
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
OnlyOneAccessTemplate/Controllers/ConverterController.cs
Normal file
129
OnlyOneAccessTemplate/Controllers/ConverterController.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using OnlyOneAccessTemplate.Services.OnlyOneAccessTemplate.Services;
|
||||
using OnlyOneAccessTemplate.Services;
|
||||
using OnlyOneAccessTemplate.Models;
|
||||
|
||||
namespace OnlyOneAccessTemplate.Controllers
|
||||
{
|
||||
public class ConverterController : BaseController
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ILogger _logger;
|
||||
private readonly Dictionary<string, Type> _converterTypes;
|
||||
|
||||
public ConverterController(
|
||||
ISiteConfigurationService siteConfig,
|
||||
ILanguageService languageService,
|
||||
ISeoService seoService,
|
||||
IMemoryCache cache,
|
||||
IConfiguration configuration,
|
||||
IServiceProvider serviceProvider,
|
||||
ILogger logger
|
||||
)
|
||||
: base(siteConfig, languageService, seoService, cache, configuration)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
this._logger = logger;
|
||||
|
||||
// Registrar tipos de conversores disponíveis
|
||||
_converterTypes = new Dictionary<string, Type>
|
||||
{
|
||||
["text-case"] = typeof(TextCaseConverterService),
|
||||
["csv-json"] = typeof(CsvToJsonConverterService),
|
||||
["image-ocr"] = typeof(ImageToTextConverterService)
|
||||
// Adicionar novos conversores aqui
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("api/convert/{converterType}")]
|
||||
public async Task<IActionResult> Convert(string converterType, [FromForm] ConversionRequestDto requestDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_converterTypes.ContainsKey(converterType))
|
||||
{
|
||||
return BadRequest(new { success = false, message = "Conversor não encontrado" });
|
||||
}
|
||||
|
||||
var converterService = (IConverterService)_serviceProvider.GetRequiredService(_converterTypes[converterType]);
|
||||
|
||||
var request = new ConversionRequest(
|
||||
Language: requestDto.Language ?? GetCurrentLanguage(),
|
||||
InputType: requestDto.InputType,
|
||||
TextInput: requestDto.TextInput,
|
||||
FileInput: requestDto.FileInput,
|
||||
UrlInput: requestDto.UrlInput,
|
||||
Options: requestDto.Options
|
||||
);
|
||||
|
||||
// Validar entrada
|
||||
if (!await converterService.ValidateInputAsync(request))
|
||||
{
|
||||
return BadRequest(new { success = false, message = "Entrada inválida" });
|
||||
}
|
||||
|
||||
// Executar conversão
|
||||
var result = await converterService.ConvertAsync(request);
|
||||
|
||||
if (!result.Success)
|
||||
{
|
||||
return BadRequest(new { success = false, message = result.ErrorMessage });
|
||||
}
|
||||
|
||||
// Retornar resultado baseado no tipo de saída
|
||||
if (!string.IsNullOrEmpty(result.OutputText))
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
success = true,
|
||||
outputText = result.OutputText,
|
||||
metadata = result.Metadata
|
||||
});
|
||||
}
|
||||
else if (result.OutputFile != null)
|
||||
{
|
||||
return File(result.OutputFile, result.OutputMimeType ?? "application/octet-stream",
|
||||
result.OutputFileName ?? "converted_file");
|
||||
}
|
||||
else
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
success = true,
|
||||
previewHtml = result.PreviewHtml,
|
||||
metadata = result.Metadata
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Erro na conversão {ConverterType}", converterType);
|
||||
return StatusCode(500, new { success = false, message = "Erro interno do servidor" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("config/{converterType}")]
|
||||
public IActionResult GetConverterConfig(string converterType)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_converterTypes.ContainsKey(converterType))
|
||||
{
|
||||
return NotFound(new { success = false, message = "Conversor não encontrado" });
|
||||
}
|
||||
|
||||
var converterService = (IConverterService)_serviceProvider.GetRequiredService(_converterTypes[converterType]);
|
||||
var language = GetCurrentLanguage();
|
||||
var config = converterService.GetConfiguration(language);
|
||||
|
||||
return Ok(new { success = true, config });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Erro ao buscar configuração do conversor {ConverterType}", converterType);
|
||||
return StatusCode(500, new { success = false, message = "Erro interno do servidor" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
OnlyOneAccessTemplate/Models/ConversionRequestDto.cs
Normal file
12
OnlyOneAccessTemplate/Models/ConversionRequestDto.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace OnlyOneAccessTemplate.Models
|
||||
{
|
||||
public class ConversionRequestDto
|
||||
{
|
||||
public string? Language { get; set; }
|
||||
public string InputType { get; set; } = "text";
|
||||
public string? TextInput { get; set; }
|
||||
public IFormFile? FileInput { get; set; }
|
||||
public string? UrlInput { get; set; }
|
||||
public Dictionary<string, object>? Options { get; set; }
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,6 @@
|
||||
public bool Required { get; init; } = false;
|
||||
public string ValidationRegex { get; init; } = string.Empty;
|
||||
public int Order { get; init; } = 0;
|
||||
|
||||
public Dictionary<string, List<string>> Properties { get; set; }
|
||||
public Dictionary<string, object> Properties { get; init; } = new();
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,10 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Views\Shared\_AdvancedOptions.cshtml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Views\En\" />
|
||||
<Folder Include="Views\Es\" />
|
||||
@ -15,4 +19,16 @@
|
||||
<PackageReference Include="MongoDB.Driver" Version="3.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<UpToDateCheckInput Remove="Views\Shared\_AdvancedOptions.cshtml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_ContentIncludedByDefault Remove="Views\Shared\_AdvancedOptions.cshtml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Views\Shared\_AdvancedOptions.cshtml" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -35,8 +35,17 @@ builder.Services.AddScoped<ILanguageService, LanguageService>();
|
||||
builder.Services.AddScoped<ISeoService, SeoService>();
|
||||
builder.Services.AddScoped<IConversionService, ConversionService>();
|
||||
|
||||
// Converter Services - Registrar todos os conversores disponíveis
|
||||
builder.Services.AddScoped<TextCaseConverterService>();
|
||||
builder.Services.AddScoped<CsvToJsonConverterService>();
|
||||
builder.Services.AddScoped<ImageToTextConverterService>();
|
||||
|
||||
// Adicione aqui novos conversores conforme necessário:
|
||||
// builder.Services.AddScoped<SeuNovoConverterService>();
|
||||
|
||||
// HttpClient for external calls
|
||||
builder.Services.AddHttpClient<ConversionService>();
|
||||
builder.Services.AddHttpClient<ImageToTextConverterService>();
|
||||
|
||||
// Response Compression
|
||||
builder.Services.AddResponseCompression(options =>
|
||||
@ -50,6 +59,11 @@ builder.Services.AddResponseCaching();
|
||||
// Memory Cache
|
||||
builder.Services.AddMemoryCache();
|
||||
|
||||
// Logging
|
||||
builder.Logging.ClearProviders();
|
||||
builder.Logging.AddConsole();
|
||||
builder.Logging.AddDebug();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline
|
||||
@ -72,6 +86,16 @@ app.UseResponseCaching();
|
||||
app.UseRouting();
|
||||
|
||||
// Custom routing for multilingual support
|
||||
app.MapControllerRoute(
|
||||
name: "converter-api",
|
||||
pattern: "converter/api/{action}/{converterType?}",
|
||||
defaults: new { controller = "Converter" });
|
||||
|
||||
app.MapControllerRoute(
|
||||
name: "converter-config",
|
||||
pattern: "converter/config/{converterType}",
|
||||
defaults: new { controller = "Converter", action = "GetConverterConfig" });
|
||||
|
||||
app.MapControllerRoute(
|
||||
name: "default-pt",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
@ -101,4 +125,34 @@ app.MapGet("/robots.txt", async (ISiteConfigurationService siteConfig) =>
|
||||
return Results.Content(robots, "text/plain");
|
||||
});
|
||||
|
||||
// Health check endpoint
|
||||
app.MapGet("/health", () => Results.Ok(new { status = "healthy", timestamp = DateTime.UtcNow }));
|
||||
|
||||
// Initialize default data on startup (only in development)
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
using var scope = app.Services.CreateScope();
|
||||
var siteConfigService = scope.ServiceProvider.GetRequiredService<ISiteConfigurationService>();
|
||||
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
|
||||
|
||||
try
|
||||
{
|
||||
// Verificar se já existem configurações
|
||||
var languages = new[] { "pt", "en", "es" };
|
||||
foreach (var lang in languages)
|
||||
{
|
||||
var configExists = await siteConfigService.ConfigurationExistsAsync(lang);
|
||||
if (!configExists)
|
||||
{
|
||||
logger.LogInformation("Criando configuração padrão para idioma: {Language}", lang);
|
||||
_ = await siteConfigService.GetConfigurationAsync(lang); // Isso criará a configuração padrão
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Erro ao inicializar dados padrão");
|
||||
}
|
||||
}
|
||||
|
||||
app.Run();
|
||||
206
OnlyOneAccessTemplate/Services/ConverterService.cs
Normal file
206
OnlyOneAccessTemplate/Services/ConverterService.cs
Normal file
@ -0,0 +1,206 @@
|
||||
using global::OnlyOneAccessTemplate.Controllers;
|
||||
using global::OnlyOneAccessTemplate.Services.OnlyOneAccessTemplate.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace OnlyOneAccessTemplate.Services
|
||||
{
|
||||
|
||||
namespace OnlyOneAccessTemplate.Services
|
||||
{
|
||||
// Interface principal para conversores
|
||||
public interface IConverterService
|
||||
{
|
||||
string ConverterType { get; }
|
||||
string ConverterName { get; }
|
||||
Task<ConversionResult> ConvertAsync(ConversionRequest request);
|
||||
Task<bool> ValidateInputAsync(ConversionRequest request);
|
||||
ConverterConfiguration GetConfiguration(string language);
|
||||
}
|
||||
|
||||
// Configuração específica do conversor
|
||||
public record ConverterConfiguration
|
||||
{
|
||||
public string ConverterType { get; init; } = "text"; // "text", "file", "url"
|
||||
public string OutputType { get; init; } = "text"; // "text", "download", "preview"
|
||||
public string[] AcceptedFileTypes { get; init; } = Array.Empty<string>();
|
||||
public int MaxFileSize { get; init; } = 10 * 1024 * 1024; // 10MB
|
||||
public bool HasAdvancedOptions { get; init; } = false;
|
||||
public bool AllowShare { get; init; } = false;
|
||||
public Dictionary<string, string> LocalizedTexts { get; init; } = new();
|
||||
}
|
||||
|
||||
// Request de conversão
|
||||
public record ConversionRequest(
|
||||
string Language,
|
||||
string InputType, // "text", "file", "url"
|
||||
string? TextInput = null,
|
||||
IFormFile? FileInput = null,
|
||||
string? UrlInput = null,
|
||||
Dictionary<string, object>? Options = null
|
||||
);
|
||||
|
||||
// Resultado da conversão
|
||||
public record ConversionResult(
|
||||
bool Success,
|
||||
string? OutputText = null,
|
||||
byte[]? OutputFile = null,
|
||||
string? OutputFileName = null,
|
||||
string? OutputMimeType = null,
|
||||
string? PreviewHtml = null,
|
||||
string? ErrorMessage = null,
|
||||
Dictionary<string, object>? Metadata = null
|
||||
);
|
||||
|
||||
// Serviço base para conversores
|
||||
public abstract class BaseConverterService : IConverterService
|
||||
{
|
||||
protected readonly ILogger _logger;
|
||||
protected readonly IConfiguration _configuration;
|
||||
|
||||
public abstract string ConverterType { get; }
|
||||
public abstract string ConverterName { get; }
|
||||
|
||||
protected BaseConverterService(ILogger logger, IConfiguration configuration)
|
||||
{
|
||||
_logger = logger;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public abstract Task<ConversionResult> ConvertAsync(ConversionRequest request);
|
||||
|
||||
public virtual async Task<bool> ValidateInputAsync(ConversionRequest request)
|
||||
{
|
||||
var config = GetConfiguration(request.Language);
|
||||
|
||||
// Validação básica baseada no tipo
|
||||
switch (request.InputType)
|
||||
{
|
||||
case "text":
|
||||
return !string.IsNullOrWhiteSpace(request.TextInput);
|
||||
|
||||
case "file":
|
||||
if (request.FileInput == null || request.FileInput.Length == 0)
|
||||
return false;
|
||||
|
||||
// Verificar tamanho do arquivo
|
||||
if (request.FileInput.Length > config.MaxFileSize)
|
||||
return false;
|
||||
|
||||
// Verificar tipo do arquivo se especificado
|
||||
if (config.AcceptedFileTypes.Length > 0)
|
||||
{
|
||||
var extension = Path.GetExtension(request.FileInput.FileName);
|
||||
return config.AcceptedFileTypes.Contains(extension, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
return true;
|
||||
|
||||
case "url":
|
||||
return Uri.TryCreate(request.UrlInput, UriKind.Absolute, out _);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract ConverterConfiguration GetConfiguration(string language);
|
||||
|
||||
protected virtual Dictionary<string, string> GetLocalizedTexts(string language)
|
||||
{
|
||||
return language switch
|
||||
{
|
||||
"en" => GetEnglishTexts(),
|
||||
"es" => GetSpanishTexts(),
|
||||
_ => GetPortugueseTexts()
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual Dictionary<string, string> GetPortugueseTexts()
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
["ConverterTitle"] = "CONVERSOR ONLINE",
|
||||
["ConverterDescription"] = "Converta seus arquivos de forma rápida e segura",
|
||||
["Step1Title"] = "Upload",
|
||||
["Step1Description"] = "Selecione ou cole seu conteúdo",
|
||||
["Step2Title"] = "Configurar",
|
||||
["Step2Description"] = "Escolha as opções de conversão",
|
||||
["Step3Title"] = "Converter",
|
||||
["Step3Description"] = "Baixe o resultado",
|
||||
["InputLabel"] = "Entrada",
|
||||
["OutputLabel"] = "Resultado",
|
||||
["SelectFileText"] = "Selecionar Arquivo",
|
||||
["ConvertButtonText"] = "Converter",
|
||||
["LoadingText"] = "Processando...",
|
||||
["ProcessingText"] = "Convertendo seu arquivo...",
|
||||
["CopyButtonText"] = "Copiar",
|
||||
["ClearButtonText"] = "Limpar",
|
||||
["ShareButtonText"] = "Compartilhar",
|
||||
["CopiedText"] = "Copiado!",
|
||||
["DownloadButtonText"] = "Baixar",
|
||||
["DownloadReadyText"] = "Seu arquivo está pronto!",
|
||||
["SecurityText"] = "Seus dados estão seguros conosco",
|
||||
["DefaultErrorMessage"] = "Erro ao processar. Tente novamente."
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual Dictionary<string, string> GetEnglishTexts()
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
["ConverterTitle"] = "ONLINE CONVERTER",
|
||||
["ConverterDescription"] = "Convert your files quickly and securely",
|
||||
["Step1Title"] = "Upload",
|
||||
["Step1Description"] = "Select or paste your content",
|
||||
["Step2Title"] = "Configure",
|
||||
["Step2Description"] = "Choose conversion options",
|
||||
["Step3Title"] = "Convert",
|
||||
["Step3Description"] = "Download the result",
|
||||
["InputLabel"] = "Input",
|
||||
["OutputLabel"] = "Output",
|
||||
["SelectFileText"] = "Select File",
|
||||
["ConvertButtonText"] = "Convert",
|
||||
["LoadingText"] = "Processing...",
|
||||
["ProcessingText"] = "Converting your file...",
|
||||
["CopyButtonText"] = "Copy",
|
||||
["ClearButtonText"] = "Clear",
|
||||
["ShareButtonText"] = "Share",
|
||||
["CopiedText"] = "Copied!",
|
||||
["DownloadButtonText"] = "Download",
|
||||
["DownloadReadyText"] = "Your file is ready!",
|
||||
["SecurityText"] = "Your data is safe with us",
|
||||
["DefaultErrorMessage"] = "Processing error. Please try again."
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual Dictionary<string, string> GetSpanishTexts()
|
||||
{
|
||||
return new Dictionary<string, string>
|
||||
{
|
||||
["ConverterTitle"] = "CONVERTIDOR EN LÍNEA",
|
||||
["ConverterDescription"] = "Convierte tus archivos de forma rápida y segura",
|
||||
["Step1Title"] = "Subir",
|
||||
["Step1Description"] = "Selecciona o pega tu contenido",
|
||||
["Step2Title"] = "Configurar",
|
||||
["Step2Description"] = "Elige las opciones de conversión",
|
||||
["Step3Title"] = "Convertir",
|
||||
["Step3Description"] = "Descarga el resultado",
|
||||
["InputLabel"] = "Entrada",
|
||||
["OutputLabel"] = "Resultado",
|
||||
["SelectFileText"] = "Seleccionar Archivo",
|
||||
["ConvertButtonText"] = "Convertir",
|
||||
["LoadingText"] = "Procesando...",
|
||||
["ProcessingText"] = "Convirtiendo tu archivo...",
|
||||
["CopyButtonText"] = "Copiar",
|
||||
["ClearButtonText"] = "Limpiar",
|
||||
["ShareButtonText"] = "Compartir",
|
||||
["CopiedText"] = "¡Copiado!",
|
||||
["DownloadButtonText"] = "Descargar",
|
||||
["DownloadReadyText"] = "¡Tu archivo está listo!",
|
||||
["SecurityText"] = "Tus datos están seguros con nosotros",
|
||||
["DefaultErrorMessage"] = "Error al procesar. Inténtalo de nuevo."
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
114
OnlyOneAccessTemplate/Services/CsvToJsonConverterService.cs
Normal file
114
OnlyOneAccessTemplate/Services/CsvToJsonConverterService.cs
Normal file
@ -0,0 +1,114 @@
|
||||
using OnlyOneAccessTemplate.Services.OnlyOneAccessTemplate.Services;
|
||||
|
||||
namespace OnlyOneAccessTemplate.Services
|
||||
{
|
||||
public class CsvToJsonConverterService : BaseConverterService
|
||||
{
|
||||
public override string ConverterType => "csv-json";
|
||||
public override string ConverterName => "CSV to JSON Converter";
|
||||
|
||||
public CsvToJsonConverterService(ILogger<CsvToJsonConverterService> logger, IConfiguration configuration)
|
||||
: base(logger, configuration) { }
|
||||
|
||||
public override async Task<ConversionResult> ConvertAsync(ConversionRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
string csvContent;
|
||||
|
||||
if (request.InputType == "file" && request.FileInput != null)
|
||||
{
|
||||
using var reader = new StreamReader(request.FileInput.OpenReadStream());
|
||||
csvContent = await reader.ReadToEndAsync();
|
||||
}
|
||||
else if (request.InputType == "text" && !string.IsNullOrEmpty(request.TextInput))
|
||||
{
|
||||
csvContent = request.TextInput;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ConversionResult(false, ErrorMessage: "Nenhum conteúdo CSV fornecido");
|
||||
}
|
||||
|
||||
var lines = csvContent.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||
if (lines.Length < 2)
|
||||
{
|
||||
return new ConversionResult(false, ErrorMessage: "CSV deve ter pelo menos cabeçalho e uma linha de dados");
|
||||
}
|
||||
|
||||
var headers = lines[0].Split(',').Select(h => h.Trim().Trim('"')).ToArray();
|
||||
var jsonObjects = new List<Dictionary<string, string>>();
|
||||
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
var values = lines[i].Split(',').Select(v => v.Trim().Trim('"')).ToArray();
|
||||
var obj = new Dictionary<string, string>();
|
||||
|
||||
for (int j = 0; j < Math.Min(headers.Length, values.Length); j++)
|
||||
{
|
||||
obj[headers[j]] = values[j];
|
||||
}
|
||||
|
||||
jsonObjects.Add(obj);
|
||||
}
|
||||
|
||||
var jsonResult = System.Text.Json.JsonSerializer.Serialize(jsonObjects, new System.Text.Json.JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||
});
|
||||
|
||||
return new ConversionResult(true, OutputText: jsonResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Erro na conversão CSV para JSON");
|
||||
return new ConversionResult(false, ErrorMessage: "Erro ao converter CSV para JSON");
|
||||
}
|
||||
}
|
||||
|
||||
public override ConverterConfiguration GetConfiguration(string language)
|
||||
{
|
||||
var texts = GetLocalizedTexts(language);
|
||||
texts["ConverterTitle"] = language switch
|
||||
{
|
||||
"en" => "CSV TO JSON CONVERTER",
|
||||
"es" => "CONVERTIDOR CSV A JSON",
|
||||
_ => "CONVERSOR CSV PARA JSON"
|
||||
};
|
||||
|
||||
texts["ConverterDescription"] = language switch
|
||||
{
|
||||
"en" => "Convert CSV files to JSON format quickly and easily",
|
||||
"es" => "Convierte archivos CSV a formato JSON de forma rápida y fácil",
|
||||
_ => "Converta arquivos CSV para formato JSON de forma rápida e fácil"
|
||||
};
|
||||
|
||||
texts["InputPlaceholder"] = language switch
|
||||
{
|
||||
"en" => "Paste your CSV content here or upload a file...",
|
||||
"es" => "Pega tu contenido CSV aquí o sube un archivo...",
|
||||
_ => "Cole seu conteúdo CSV aqui ou faça upload de um arquivo..."
|
||||
};
|
||||
|
||||
texts["FileHelpText"] = language switch
|
||||
{
|
||||
"en" => "Max file size: 10MB. Supported formats: .csv, .txt",
|
||||
"es" => "Tamaño máximo: 10MB. Formatos soportados: .csv, .txt",
|
||||
_ => "Tamanho máximo: 10MB. Formatos suportados: .csv, .txt"
|
||||
};
|
||||
|
||||
return new ConverterConfiguration
|
||||
{
|
||||
ConverterType = "text", // Aceita tanto texto quanto arquivo
|
||||
OutputType = "text",
|
||||
AcceptedFileTypes = new[] { ".csv", ".txt" },
|
||||
MaxFileSize = 10 * 1024 * 1024,
|
||||
HasAdvancedOptions = false,
|
||||
AllowShare = true,
|
||||
LocalizedTexts = texts
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
using OnlyOneAccessTemplate.Services.OnlyOneAccessTemplate.Services;
|
||||
|
||||
namespace OnlyOneAccessTemplate.Services
|
||||
{
|
||||
public class ImageToTextConverterService : BaseConverterService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public override string ConverterType => "image-ocr";
|
||||
public override string ConverterName => "Image to Text (OCR)";
|
||||
|
||||
public ImageToTextConverterService(ILogger<ImageToTextConverterService> logger,
|
||||
IConfiguration configuration, HttpClient httpClient)
|
||||
: base(logger, configuration)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public override async Task<ConversionResult> ConvertAsync(ConversionRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (request.FileInput == null)
|
||||
{
|
||||
return new ConversionResult(false, ErrorMessage: "Nenhuma imagem fornecida");
|
||||
}
|
||||
|
||||
// Aqui você integraria com um serviço de OCR real como:
|
||||
// - Azure Computer Vision
|
||||
// - Google Cloud Vision
|
||||
// - AWS Textract
|
||||
// - Tesseract local
|
||||
|
||||
// Por agora, simular processamento
|
||||
await Task.Delay(2000); // Simular processamento
|
||||
|
||||
// Exemplo de resultado simulado
|
||||
var extractedText = $"Texto extraído da imagem: {request.FileInput.FileName}\n\n" +
|
||||
"Este é um exemplo de texto que seria extraído da imagem usando OCR.\n" +
|
||||
"Em uma implementação real, aqui estaria o texto real da imagem.";
|
||||
|
||||
return new ConversionResult(true, OutputText: extractedText);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Erro na conversão de imagem para texto");
|
||||
return new ConversionResult(false, ErrorMessage: "Erro ao processar imagem");
|
||||
}
|
||||
}
|
||||
|
||||
public override ConverterConfiguration GetConfiguration(string language)
|
||||
{
|
||||
var texts = GetLocalizedTexts(language);
|
||||
texts["ConverterTitle"] = language switch
|
||||
{
|
||||
"en" => "IMAGE TO TEXT CONVERTER - OCR ONLINE",
|
||||
"es" => "CONVERTIDOR DE IMAGEN A TEXTO - OCR EN LÍNEA",
|
||||
_ => "CONVERSOR DE IMAGEM PARA TEXTO - OCR ONLINE"
|
||||
};
|
||||
|
||||
texts["ConverterDescription"] = language switch
|
||||
{
|
||||
"en" => "Extract text from images using Optical Character Recognition technology",
|
||||
"es" => "Extrae texto de imágenes usando tecnología de Reconocimiento Óptico de Caracteres",
|
||||
_ => "Extraia texto de imagens usando tecnologia de Reconhecimento Óptico de Caracteres"
|
||||
};
|
||||
|
||||
texts["SelectFileText"] = language switch
|
||||
{
|
||||
"en" => "SELECT IMAGE",
|
||||
"es" => "SELECCIONAR IMAGEN",
|
||||
_ => "SELECIONAR IMAGEM"
|
||||
};
|
||||
|
||||
texts["FileHelpText"] = language switch
|
||||
{
|
||||
"en" => "Max file size: 15MB. Supported formats: JPG, PNG, PDF, TIFF",
|
||||
"es" => "Tamaño máximo: 15MB. Formatos soportados: JPG, PNG, PDF, TIFF",
|
||||
_ => "Tamanho máximo: 15MB. Formatos suportados: JPG, PNG, PDF, TIFF"
|
||||
};
|
||||
|
||||
return new ConverterConfiguration
|
||||
{
|
||||
ConverterType = "file",
|
||||
OutputType = "text",
|
||||
AcceptedFileTypes = new[] { ".jpg", ".jpeg", ".png", ".pdf", ".tiff", ".bmp" },
|
||||
MaxFileSize = 15 * 1024 * 1024,
|
||||
HasAdvancedOptions = true,
|
||||
AllowShare = false, // OCR pode conter informações sensíveis
|
||||
LocalizedTexts = texts
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
84
OnlyOneAccessTemplate/Services/TextCaseConverterService.cs
Normal file
84
OnlyOneAccessTemplate/Services/TextCaseConverterService.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using OnlyOneAccessTemplate.Services.OnlyOneAccessTemplate.Services;
|
||||
|
||||
namespace OnlyOneAccessTemplate.Services
|
||||
{
|
||||
public class TextCaseConverterService : BaseConverterService
|
||||
{
|
||||
public override string ConverterType => "text-case";
|
||||
public override string ConverterName => "Text Case Converter";
|
||||
|
||||
public TextCaseConverterService(ILogger<TextCaseConverterService> logger, IConfiguration configuration)
|
||||
: base(logger, configuration) { }
|
||||
|
||||
public override async Task<ConversionResult> ConvertAsync(ConversionRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(request.TextInput))
|
||||
{
|
||||
return new ConversionResult(false, ErrorMessage: "Texto não fornecido");
|
||||
}
|
||||
|
||||
var caseType = request.Options?.GetValueOrDefault("caseType", "upper")?.ToString() ?? "upper";
|
||||
|
||||
var result = caseType switch
|
||||
{
|
||||
"upper" => request.TextInput.ToUpperInvariant(),
|
||||
"lower" => request.TextInput.ToLowerInvariant(),
|
||||
"title" => System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(request.TextInput.ToLower()),
|
||||
"sentence" => char.ToUpper(request.TextInput[0]) + request.TextInput.Substring(1).ToLower(),
|
||||
_ => request.TextInput
|
||||
};
|
||||
|
||||
return new ConversionResult(true, OutputText: result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Erro na conversão de texto");
|
||||
return new ConversionResult(false, ErrorMessage: "Erro ao converter texto");
|
||||
}
|
||||
}
|
||||
|
||||
public override ConverterConfiguration GetConfiguration(string language)
|
||||
{
|
||||
var texts = GetLocalizedTexts(language);
|
||||
texts["ConverterTitle"] = language switch
|
||||
{
|
||||
"en" => "TEXT CASE CONVERTER",
|
||||
"es" => "CONVERTIDOR DE MAYÚSCULAS Y MINÚSCULAS",
|
||||
_ => "CONVERSOR DE MAIÚSCULAS E MINÚSCULAS"
|
||||
};
|
||||
|
||||
texts["ConverterDescription"] = language switch
|
||||
{
|
||||
"en" => "Convert text between uppercase, lowercase, title case and sentence case",
|
||||
"es" => "Convierte texto entre mayúsculas, minúsculas, título y oración",
|
||||
_ => "Converta texto entre maiúsculas, minúsculas, título e primeira maiúscula"
|
||||
};
|
||||
|
||||
texts["InputPlaceholder"] = language switch
|
||||
{
|
||||
"en" => "Enter your text here...",
|
||||
"es" => "Ingresa tu texto aquí...",
|
||||
_ => "Digite seu texto aqui..."
|
||||
};
|
||||
|
||||
texts["OutputPlaceholder"] = language switch
|
||||
{
|
||||
"en" => "Converted text will appear here...",
|
||||
"es" => "El texto convertido aparecerá aquí...",
|
||||
_ => "O texto convertido aparecerá aqui..."
|
||||
};
|
||||
|
||||
return new ConverterConfiguration
|
||||
{
|
||||
ConverterType = "text",
|
||||
OutputType = "text",
|
||||
HasAdvancedOptions = true,
|
||||
AllowShare = true,
|
||||
LocalizedTexts = texts
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,212 +1,255 @@
|
||||
@model OnlyOneAccessTemplate.Models.PageContent
|
||||
@model PageContent;
|
||||
|
||||
@{
|
||||
ViewData["Title"] = Model?.MetaTitle ?? Model?.Title ?? ViewBag.Title;
|
||||
ViewData["Title"] = ViewBag.Title ?? "Conversor Online";
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
|
||||
@section Head {
|
||||
<!-- Page specific meta tags -->
|
||||
<meta name="description" content="@(Model?.Description ?? ViewBag.Description)">
|
||||
<meta name="keywords" content="@(Model?.Keywords ?? ViewBag.Keywords)">
|
||||
|
||||
<!-- Custom CSS for animations -->
|
||||
<style>
|
||||
.hover-lift {
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.hover-lift:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 25px rgba(0,0,0,0.15) !important;
|
||||
}
|
||||
|
||||
.animate-bounce {
|
||||
animation: bounce 2s infinite;
|
||||
}
|
||||
|
||||
.scroll-smooth {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
.bg-gradient-primary {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
.countdown-number {
|
||||
min-width: 60px;
|
||||
min-height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
}
|
||||
|
||||
<!-- Hero Section -->
|
||||
@{
|
||||
var heroBlock = Model?.Blocks?.FirstOrDefault(b => b.Type == "hero");
|
||||
}
|
||||
@await Html.PartialAsync("Components/_Hero", heroBlock)
|
||||
|
||||
<!-- Features Section -->
|
||||
@{
|
||||
var featuresBlock = Model?.Blocks?.FirstOrDefault(b => b.Type == "features");
|
||||
}
|
||||
@await Html.PartialAsync("Components/_Features", featuresBlock)
|
||||
|
||||
<!-- Benefits/How it Works Section -->
|
||||
@if (Model?.Blocks?.Any(b => b.Type == "benefits") == true)
|
||||
{
|
||||
var benefitsBlock = Model.Blocks.First(b => b.Type == "benefits");
|
||||
<section class="benefits-section py-5">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center mb-5">
|
||||
<div class="col-lg-8 text-center">
|
||||
<h2 class="display-5 fw-bold mb-3" data-aos="fade-up">
|
||||
@benefitsBlock.Title
|
||||
</h2>
|
||||
<p class="lead text-muted" data-aos="fade-up" data-aos-delay="100">
|
||||
@benefitsBlock.Content
|
||||
<!-- Seção Principal do Conversor -->
|
||||
<section class="converter-hero bg-light py-5">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10">
|
||||
<!-- Título e Descrição -->
|
||||
<div class="text-center mb-5">
|
||||
<h1 class="display-4 fw-bold text-primary mb-3">
|
||||
@(ViewBag.ConverterTitle ?? "CONVERSOR ONLINE")
|
||||
</h1>
|
||||
<p class="lead text-muted mb-4">
|
||||
@(ViewBag.ConverterDescription ?? "Converta seus arquivos de forma rápida e segura")
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-md-6" data-aos="fade-right">
|
||||
<div class="benefit-item d-flex mb-4">
|
||||
<div class="benefit-icon me-4">
|
||||
<i class="fas fa-check-circle fa-2x text-success"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="fw-bold mb-2">Resultado Garantido</h5>
|
||||
<p class="text-muted mb-0">Metodologia comprovada com mais de 1000 casos de sucesso documentados.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="benefit-item d-flex mb-4">
|
||||
<div class="benefit-icon me-4">
|
||||
<i class="fas fa-clock fa-2x text-primary"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="fw-bold mb-2">Implementação Rápida</h5>
|
||||
<p class="text-muted mb-0">Veja os primeiros resultados em até 30 dias após a implementação.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="benefit-item d-flex">
|
||||
<div class="benefit-icon me-4">
|
||||
<i class="fas fa-users fa-2x text-warning"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="fw-bold mb-2">Suporte Especializado</h5>
|
||||
<p class="text-muted mb-0">Equipe dedicada para garantir o seu sucesso em cada etapa.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6" data-aos="fade-left">
|
||||
@if (!string.IsNullOrEmpty(benefitsBlock.ImageUrl))
|
||||
{
|
||||
<img src="@benefitsBlock.ImageUrl" alt="@benefitsBlock.Title" class="img-fluid rounded-3 shadow">
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="stats-container bg-light p-4 rounded-3">
|
||||
<div class="row text-center">
|
||||
<div class="col-4">
|
||||
<div class="stat-item">
|
||||
<h3 class="fw-bold text-primary mb-1">1000+</h3>
|
||||
<small class="text-muted">Clientes Atendidos</small>
|
||||
</div>
|
||||
<!-- Card do Conversor -->
|
||||
<div class="card shadow-lg border-0 rounded-3">
|
||||
<div class="card-body p-5">
|
||||
<!-- Steps do Processo -->
|
||||
<div class="row text-center mb-4">
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="step-indicator">
|
||||
<span class="badge bg-primary rounded-circle p-3 fs-5 mb-2">1</span>
|
||||
<h6 class="fw-bold">@(ViewBag.Step1Title ?? "Upload")</h6>
|
||||
<small class="text-muted">@(ViewBag.Step1Description ?? "Selecione seu arquivo")</small>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="stat-item">
|
||||
<h3 class="fw-bold text-success mb-1">95%</h3>
|
||||
<small class="text-muted">Taxa de Sucesso</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="step-indicator">
|
||||
<span class="badge bg-primary rounded-circle p-3 fs-5 mb-2">2</span>
|
||||
<h6 class="fw-bold">@(ViewBag.Step2Title ?? "Processar")</h6>
|
||||
<small class="text-muted">@(ViewBag.Step2Description ?? "Aguarde o processamento")</small>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="stat-item">
|
||||
<h3 class="fw-bold text-warning mb-1">24h</h3>
|
||||
<small class="text-muted">Suporte</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="step-indicator">
|
||||
<span class="badge bg-success rounded-circle p-3 fs-5 mb-2">3</span>
|
||||
<h6 class="fw-bold">@(ViewBag.Step3Title ?? "Download")</h6>
|
||||
<small class="text-muted">@(ViewBag.Step3Description ?? "Baixe o resultado")</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Área do Conversor -->
|
||||
<div id="converter-container">
|
||||
@await Html.PartialAsync("_ConverterWidget")
|
||||
</div>
|
||||
|
||||
<!-- Informações Adicionais -->
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="fas fa-shield-alt text-success me-2"></i>
|
||||
<small class="text-muted">@(ViewBag.SecurityText ?? "Seus dados estão seguros")</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="fas fa-file-alt text-primary me-2"></i>
|
||||
<small class="text-muted">@(ViewBag.FileInfoText ?? "Processamento rápido e seguro")</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Seção de Benefícios -->
|
||||
<section class="benefits-section py-5">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto text-center mb-5">
|
||||
<h2 class="h3 fw-bold mb-3">@(ViewBag.BenefitsTitle ?? "Por Que Usar Nossa Ferramenta?")</h2>
|
||||
<p class="text-muted">@(ViewBag.BenefitsSubtitle ?? "Descubra os benefícios de nossa solução")</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-4">
|
||||
@{
|
||||
bool hasFeatureBlocks = false;
|
||||
if (Model != null && Model.Blocks != null)
|
||||
{
|
||||
var featureBlocks = Model.Blocks.Where(b => b.Type == "features").ToList();
|
||||
if (featureBlocks.Any())
|
||||
{
|
||||
hasFeatureBlocks = true;
|
||||
var firstFeatureBlock = featureBlocks.First();
|
||||
if (firstFeatureBlock.Properties != null && firstFeatureBlock.Properties.ContainsKey("feature_list"))
|
||||
{
|
||||
var featureList = firstFeatureBlock.Properties["feature_list"] as System.Collections.IEnumerable;
|
||||
if (featureList != null)
|
||||
{
|
||||
foreach (var featureObj in featureList)
|
||||
{
|
||||
var featureDict = featureObj as Dictionary<string, object>;
|
||||
if (featureDict != null)
|
||||
{
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="text-center p-3">
|
||||
<div class="feature-icon mb-3">
|
||||
<i class="@(featureDict.GetValueOrDefault("icon", "fas fa-star")) fa-2x text-primary"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold">@(featureDict.GetValueOrDefault("title", "Funcionalidade"))</h6>
|
||||
<small class="text-muted">@(featureDict.GetValueOrDefault("description", "Descrição da funcionalidade"))</small>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@if (!hasFeatureBlocks)
|
||||
{
|
||||
<!-- Features padrão se não houver dados do modelo -->
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="text-center p-3">
|
||||
<div class="feature-icon mb-3">
|
||||
<i class="fas fa-rocket fa-2x text-primary"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold">@(ViewBag.Feature1Title ?? "Rápido e Fácil")</h6>
|
||||
<small class="text-muted">@(ViewBag.Feature1Description ?? "Conversão instantânea")</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="text-center p-3">
|
||||
<div class="feature-icon mb-3">
|
||||
<i class="fas fa-shield-alt fa-2x text-primary"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold">@(ViewBag.Feature2Title ?? "Seguro")</h6>
|
||||
<small class="text-muted">@(ViewBag.Feature2Description ?? "Dados protegidos")</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="text-center p-3">
|
||||
<div class="feature-icon mb-3">
|
||||
<i class="fas fa-users fa-2x text-primary"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold">@(ViewBag.Feature3Title ?? "Confiável")</h6>
|
||||
<small class="text-muted">@(ViewBag.Feature3Description ?? "Resultados precisos")</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="text-center p-3">
|
||||
<div class="feature-icon mb-3">
|
||||
<i class="fas fa-clock fa-2x text-primary"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold">Rápido</h6>
|
||||
<small class="text-muted">Conversão em segundos</small>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Seção de Depoimentos (Opcional) -->
|
||||
@{
|
||||
bool hasTestimonialBlocks = false;
|
||||
if (Model != null && Model.Blocks != null)
|
||||
{
|
||||
var testimonialBlocks = Model.Blocks.Where(b => b.Type == "testimonials").ToList();
|
||||
if (testimonialBlocks.Any())
|
||||
{
|
||||
hasTestimonialBlocks = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@if (hasTestimonialBlocks)
|
||||
{
|
||||
<section class="testimonials-section py-5 bg-light">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto text-center mb-5">
|
||||
<h2 class="h3 fw-bold mb-3">@(ViewBag.DefaultTestimonialsTitle ?? "O Que Nossos Clientes Dizem")</h2>
|
||||
<p class="text-muted">@(ViewBag.TestimonialsCount ?? "Avaliações positivas")</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card border-0 h-100">
|
||||
<div class="card-body text-center">
|
||||
<p class="mb-3">"@(ViewBag.Testimonial1Quote ?? "Excelente ferramenta!")"</p>
|
||||
<h6 class="fw-bold">@(ViewBag.Testimonial1Name ?? "Cliente Satisfeito")</h6>
|
||||
<small class="text-muted">@(ViewBag.Testimonial1Position ?? "Usuário")</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card border-0 h-100">
|
||||
<div class="card-body text-center">
|
||||
<p class="mb-3">"@(ViewBag.Testimonial2Quote ?? "Muito útil e fácil de usar!")"</p>
|
||||
<h6 class="fw-bold">@(ViewBag.Testimonial2Name ?? "Outro Cliente")</h6>
|
||||
<small class="text-muted">@(ViewBag.Testimonial2Position ?? "Usuário")</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card border-0 h-100">
|
||||
<div class="card-body text-center">
|
||||
<p class="mb-3">"@(ViewBag.Testimonial3Quote ?? "Recomendo para todos!")"</p>
|
||||
<h6 class="fw-bold">@(ViewBag.Testimonial3Name ?? "Mais um Cliente")</h6>
|
||||
<small class="text-muted">@(ViewBag.Testimonial3Position ?? "Usuário")</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
<!-- Testimonials Section -->
|
||||
@{
|
||||
var testimonialsBlock = Model?.Blocks?.FirstOrDefault(b => b.Type == "testimonials");
|
||||
}
|
||||
@await Html.PartialAsync("Components/_Testimonials", testimonialsBlock)
|
||||
|
||||
<!-- Conversion Form Section -->
|
||||
@{
|
||||
var conversionConfig = ViewBag.ConversionConfig as OnlyOneAccessTemplate.Models.ConversionConfig;
|
||||
}
|
||||
@await Html.PartialAsync("Components/_ConversionForm", conversionConfig)
|
||||
|
||||
<!-- CTA Section -->
|
||||
@{
|
||||
var ctaBlock = Model?.Blocks?.FirstOrDefault(b => b.Type == "cta");
|
||||
}
|
||||
@await Html.PartialAsync("Components/_CTA", ctaBlock)
|
||||
<!-- Seção CTA Final -->
|
||||
<section class="final-cta py-5">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-8 mx-auto text-center">
|
||||
<h2 class="h3 fw-bold mb-3">@(ViewBag.FinalCtaTitle ?? "Pronto para Converter?")</h2>
|
||||
<p class="text-muted mb-4">@(ViewBag.FinalCtaSubtitle ?? "Use nossa ferramenta gratuita agora mesmo")</p>
|
||||
<a href="#converter-container" class="btn btn-primary btn-lg">
|
||||
@(ViewBag.FinalCtaButtonText ?? "Começar Conversão")
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Scripts específicos do conversor -->
|
||||
@section Scripts {
|
||||
<!-- AOS Animation JS -->
|
||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
|
||||
<script src="~/js/converter.js"></script>
|
||||
@{
|
||||
var converterType = ViewBag.ConverterType ?? "generic";
|
||||
var jsFileName = $"~/js/converters/{converterType.ToString().ToLower()}-converter.js";
|
||||
}
|
||||
<script src="@jsFileName"></script>
|
||||
<script>
|
||||
// Initialize AOS
|
||||
AOS.init({
|
||||
duration: 800,
|
||||
once: true,
|
||||
offset: 100
|
||||
// Inicializar conversor específico
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
if (typeof initializeConverter === 'function') {
|
||||
initializeConverter();
|
||||
}
|
||||
});
|
||||
|
||||
// Smooth scroll for anchor links
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
const target = document.querySelector(this.getAttribute('href'));
|
||||
if (target) {
|
||||
target.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Countdown timer
|
||||
const countdown = document.querySelector('[data-countdown]');
|
||||
if (countdown) {
|
||||
const targetDate = new Date(countdown.dataset.countdown).getTime();
|
||||
|
||||
setInterval(() => {
|
||||
const now = new Date().getTime();
|
||||
const distance = targetDate - now;
|
||||
|
||||
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
|
||||
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
|
||||
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
|
||||
|
||||
countdown.querySelector('[data-days]').textContent = days.toString().padStart(2, '0');
|
||||
countdown.querySelector('[data-hours]').textContent = hours.toString().padStart(2, '0');
|
||||
countdown.querySelector('[data-minutes]').textContent = minutes.toString().padStart(2, '0');
|
||||
countdown.querySelector('[data-seconds]').textContent = seconds.toString().padStart(2, '0');
|
||||
|
||||
if (distance < 0) {
|
||||
countdown.style.display = 'none';
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
</script>
|
||||
}
|
||||
202
OnlyOneAccessTemplate/Views/Shared/_AdvancedOptions.cshtml
Normal file
202
OnlyOneAccessTemplate/Views/Shared/_AdvancedOptions.cshtml
Normal file
@ -0,0 +1,202 @@
|
||||
@* Views/Shared/_AdvancedOptions.cshtml *@
|
||||
|
||||
<div class="advanced-options-container">
|
||||
@{
|
||||
var converterType = ViewBag.ConverterType?.ToString() ?? "text";
|
||||
}
|
||||
|
||||
@if (converterType == "text-case")
|
||||
{
|
||||
<!-- Opções para Conversor de Maiúsculas/Minúsculas -->
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Tipo de Conversão</label>
|
||||
<select name="caseType" class="form-select">
|
||||
<option value="upper">MAIÚSCULAS</option>
|
||||
<option value="lower">minúsculas</option>
|
||||
<option value="title">Primeira Maiúscula Em Cada Palavra</option>
|
||||
<option value="sentence">Primeira maiúscula apenas</option>
|
||||
</select>
|
||||
<div class="form-text">Escolha como você quer converter o texto</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Preservar Formatação</label>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="preserveSpaces" id="preserveSpaces" checked>
|
||||
<label class="form-check-label" for="preserveSpaces">
|
||||
Manter espaços e quebras de linha
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="preserveNumbers" id="preserveNumbers" checked>
|
||||
<label class="form-check-label" for="preserveNumbers">
|
||||
Não alterar números
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (converterType == "csv-json")
|
||||
{
|
||||
<!-- Opções para Conversor CSV para JSON -->
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Separador</label>
|
||||
<select name="delimiter" class="form-select">
|
||||
<option value=",">Vírgula (,)</option>
|
||||
<option value=";">Ponto e vírgula (;)</option>
|
||||
<option value="|">Pipe (|)</option>
|
||||
<option value="tab">Tab</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Codificação</label>
|
||||
<select name="encoding" class="form-select">
|
||||
<option value="utf8">UTF-8</option>
|
||||
<option value="latin1">Latin-1</option>
|
||||
<option value="ascii">ASCII</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="includeHeaders" id="includeHeaders" checked>
|
||||
<label class="form-check-label" for="includeHeaders">
|
||||
Primeira linha contém cabeçalhos
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="skipEmptyLines" id="skipEmptyLines" checked>
|
||||
<label class="form-check-label" for="skipEmptyLines">
|
||||
Ignorar linhas vazias
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (converterType == "image-ocr")
|
||||
{
|
||||
<!-- Opções para OCR -->
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Idioma do OCR</label>
|
||||
<select name="ocrLanguage" class="form-select">
|
||||
<option value="por">Português</option>
|
||||
<option value="eng">English</option>
|
||||
<option value="spa">Español</option>
|
||||
<option value="fra">Français</option>
|
||||
<option value="deu">Deutsch</option>
|
||||
<option value="ita">Italiano</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Qualidade vs Velocidade</label>
|
||||
<select name="ocrMode" class="form-select">
|
||||
<option value="balanced">Balanceado</option>
|
||||
<option value="fast">Rápido</option>
|
||||
<option value="accurate">Preciso</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="autoRotate" id="autoRotate" checked>
|
||||
<label class="form-check-label" for="autoRotate">
|
||||
Detectar e corrigir rotação automaticamente
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="enhanceImage" id="enhanceImage">
|
||||
<label class="form-check-label" for="enhanceImage">
|
||||
Melhorar qualidade da imagem antes do OCR
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (converterType == "json-csv")
|
||||
{
|
||||
<!-- Opções para JSON para CSV -->
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Separador CSV</label>
|
||||
<select name="csvDelimiter" class="form-select">
|
||||
<option value=",">Vírgula (,)</option>
|
||||
<option value=";">Ponto e vírgula (;)</option>
|
||||
<option value="|">Pipe (|)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Tratamento de Objetos Aninhados</label>
|
||||
<select name="nestedHandling" class="form-select">
|
||||
<option value="flatten">Achatar (objeto.propriedade)</option>
|
||||
<option value="json">Manter como JSON</option>
|
||||
<option value="ignore">Ignorar</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="includeHeaders" id="csvHeaders" checked>
|
||||
<label class="form-check-label" for="csvHeaders">
|
||||
Incluir linha de cabeçalho
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<!-- Opções genéricas para outros conversores -->
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Qualidade</label>
|
||||
<select name="quality" class="form-select">
|
||||
<option value="high">Alta</option>
|
||||
<option value="medium" selected>Média</option>
|
||||
<option value="low">Baixa</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Formato de Saída</label>
|
||||
<select name="outputFormat" class="form-select">
|
||||
<option value="auto">Automático</option>
|
||||
<option value="text">Texto</option>
|
||||
<option value="file">Arquivo</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Opções Comuns -->
|
||||
<div class="row mt-3">
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="optimizeOutput" id="optimizeOutput">
|
||||
<label class="form-check-label" for="optimizeOutput">
|
||||
Otimizar resultado para melhor performance
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.advanced-options-container {
|
||||
background-color: #f8f9fa;
|
||||
border: 1px solid #e9ecef;
|
||||
border-radius: 0.375rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.advanced-options-container .form-label {
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.advanced-options-container .form-text {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.advanced-options-container .form-check-label {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
</style>
|
||||
270
OnlyOneAccessTemplate/Views/Shared/_ConverterWidget.cshtml
Normal file
270
OnlyOneAccessTemplate/Views/Shared/_ConverterWidget.cshtml
Normal file
@ -0,0 +1,270 @@
|
||||
@* Views/Shared/_ConverterWidget.cshtml *@
|
||||
|
||||
<!-- Widget Base do Conversor - Personalizável para cada tipo -->
|
||||
<div class="converter-widget">
|
||||
<form id="converterForm" enctype="multipart/form-data">
|
||||
<div class="row">
|
||||
<!-- Input Area -->
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="input-section">
|
||||
<label class="form-label fw-bold">@ViewBag.InputLabel</label>
|
||||
|
||||
<!-- File Upload (se for conversão de arquivo) -->
|
||||
@if (ViewBag.ConverterType == "file")
|
||||
{
|
||||
<div class="upload-area border-2 border-dashed rounded-3 p-4 text-center">
|
||||
<input type="file" id="fileInput" name="file" class="d-none" accept="@ViewBag.AcceptedFileTypes">
|
||||
<div class="upload-placeholder">
|
||||
<i class="fas fa-cloud-upload-alt fa-3x text-muted mb-3"></i>
|
||||
<p class="mb-2">
|
||||
<button type="button" class="btn btn-outline-primary" onclick="document.getElementById('fileInput').click()">
|
||||
@ViewBag.SelectFileText
|
||||
</button>
|
||||
</p>
|
||||
<small class="text-muted">@ViewBag.FileHelpText</small>
|
||||
<div class="file-info mt-2" style="display: none;">
|
||||
<small class="text-success">
|
||||
<i class="fas fa-check-circle me-1"></i>
|
||||
<span id="fileName"></span>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Text Input (se for conversão de texto) -->
|
||||
@if (ViewBag.ConverterType == "text")
|
||||
{
|
||||
<textarea id="inputText" name="inputText" class="form-control" rows="10"
|
||||
placeholder="@ViewBag.InputPlaceholder">@ViewBag.SampleInput</textarea>
|
||||
<div class="form-text">@ViewBag.InputHelpText</div>
|
||||
}
|
||||
|
||||
<!-- URL Input (se for conversão de URL) -->
|
||||
@if (ViewBag.ConverterType == "url")
|
||||
{
|
||||
<input type="url" id="inputUrl" name="inputUrl" class="form-control"
|
||||
placeholder="@ViewBag.InputPlaceholder" value="@ViewBag.SampleInput">
|
||||
<div class="form-text">@ViewBag.InputHelpText</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Configurações Adicionais -->
|
||||
@if (ViewBag.HasAdvancedOptions == true)
|
||||
{
|
||||
<div class="advanced-options mt-3">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" data-bs-toggle="collapse" data-bs-target="#advancedSettings">
|
||||
<i class="fas fa-cog me-1"></i> @(ViewBag.AdvancedOptionsText ?? "Opções Avançadas")
|
||||
</button>
|
||||
<div class="collapse mt-3" id="advancedSettings">
|
||||
@{
|
||||
try
|
||||
{
|
||||
await Html.RenderPartialAsync("_AdvancedOptions");
|
||||
}
|
||||
catch
|
||||
{
|
||||
<!-- Fallback se a partial não existir -->
|
||||
<div class="alert alert-info">
|
||||
<small>Opções avançadas não disponíveis para este conversor.</small>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Output Area -->
|
||||
<div class="col-md-6 mb-4">
|
||||
<div class="output-section">
|
||||
<label class="form-label fw-bold">@ViewBag.OutputLabel</label>
|
||||
|
||||
<!-- Loading State -->
|
||||
<div id="loadingState" class="text-center p-5" style="display: none;">
|
||||
<div class="spinner-border text-primary mb-3" role="status">
|
||||
<span class="visually-hidden">@ViewBag.LoadingText</span>
|
||||
</div>
|
||||
<p class="text-muted">@ViewBag.ProcessingText</p>
|
||||
</div>
|
||||
|
||||
<!-- Output Display -->
|
||||
<div id="outputArea">
|
||||
@if (ViewBag.OutputType == "text")
|
||||
{
|
||||
<textarea id="outputText" class="form-control" rows="10" readonly
|
||||
placeholder="@ViewBag.OutputPlaceholder"></textarea>
|
||||
}
|
||||
else if (ViewBag.OutputType == "download")
|
||||
{
|
||||
<div class="download-area border rounded-3 p-4 text-center" style="display: none;">
|
||||
<i class="fas fa-download fa-2x text-success mb-3"></i>
|
||||
<p class="mb-3">@ViewBag.DownloadReadyText</p>
|
||||
<button type="button" id="downloadBtn" class="btn btn-success">
|
||||
<i class="fas fa-download me-1"></i> @ViewBag.DownloadButtonText
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
else if (ViewBag.OutputType == "preview")
|
||||
{
|
||||
<div id="previewArea" class="preview-container border rounded-3 p-3" style="min-height: 200px;">
|
||||
<div class="text-center text-muted p-4">
|
||||
<i class="fas fa-eye fa-2x mb-2"></i>
|
||||
<p>@ViewBag.PreviewPlaceholder</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Error Display -->
|
||||
<div id="errorArea" class="alert alert-danger mt-3" style="display: none;">
|
||||
<i class="fas fa-exclamation-triangle me-2"></i>
|
||||
<span id="errorMessage"></span>
|
||||
</div>
|
||||
|
||||
<!-- Success Actions -->
|
||||
<div id="successActions" class="mt-3" style="display: none;">
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
<button type="button" id="copyBtn" class="btn btn-sm btn-outline-primary">
|
||||
<i class="fas fa-copy me-1"></i> @ViewBag.CopyButtonText
|
||||
</button>
|
||||
<button type="button" id="clearBtn" class="btn btn-sm btn-outline-secondary">
|
||||
<i class="fas fa-trash me-1"></i> @ViewBag.ClearButtonText
|
||||
</button>
|
||||
@if (ViewBag.AllowShare == true)
|
||||
{
|
||||
<button type="button" id="shareBtn" class="btn btn-sm btn-outline-info">
|
||||
<i class="fas fa-share me-1"></i> @ViewBag.ShareButtonText
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Convert Button -->
|
||||
<div class="text-center mt-4">
|
||||
<button type="submit" id="convertBtn" class="btn btn-primary btn-lg px-5">
|
||||
<i class="fas fa-sync-alt me-2"></i>
|
||||
@ViewBag.ConvertButtonText
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript Base do Conversor -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const form = document.getElementById('converterForm');
|
||||
const convertBtn = document.getElementById('convertBtn');
|
||||
const loadingState = document.getElementById('loadingState');
|
||||
const outputArea = document.getElementById('outputArea');
|
||||
const errorArea = document.getElementById('errorArea');
|
||||
const successActions = document.getElementById('successActions');
|
||||
|
||||
// File input handler
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
if (fileInput) {
|
||||
fileInput.addEventListener('change', function (e) {
|
||||
const file = e.target.files[0];
|
||||
if (file) {
|
||||
document.getElementById('fileName').textContent = file.name;
|
||||
document.querySelector('.file-info').style.display = 'block';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Form submission
|
||||
form.addEventListener('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Reset states
|
||||
hideElement(errorArea);
|
||||
hideElement(successActions);
|
||||
showElement(loadingState);
|
||||
hideElement(outputArea.querySelector('.download-area, #previewArea'));
|
||||
|
||||
// Disable button
|
||||
convertBtn.disabled = true;
|
||||
|
||||
try {
|
||||
const formData = new FormData(form);
|
||||
|
||||
// Call converter-specific function
|
||||
if (typeof performConversion === 'function') {
|
||||
await performConversion(formData);
|
||||
} else {
|
||||
throw new Error('Converter function not implemented');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
showError(error.message || '@ViewBag.DefaultErrorMessage');
|
||||
} finally {
|
||||
hideElement(loadingState);
|
||||
convertBtn.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Utility functions
|
||||
function showElement(element) {
|
||||
if (element) element.style.display = 'block';
|
||||
}
|
||||
|
||||
function hideElement(element) {
|
||||
if (element) element.style.display = 'none';
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
document.getElementById('errorMessage').textContent = message;
|
||||
showElement(errorArea);
|
||||
}
|
||||
|
||||
// Copy button functionality
|
||||
const copyBtn = document.getElementById('copyBtn');
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener('click', function () {
|
||||
const outputText = document.getElementById('outputText');
|
||||
if (outputText) {
|
||||
outputText.select();
|
||||
document.execCommand('copy');
|
||||
|
||||
// Visual feedback
|
||||
const originalText = copyBtn.innerHTML;
|
||||
copyBtn.innerHTML = '<i class="fas fa-check me-1"></i> @ViewBag.CopiedText';
|
||||
setTimeout(() => {
|
||||
copyBtn.innerHTML = originalText;
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Clear button functionality
|
||||
const clearBtn = document.getElementById('clearBtn');
|
||||
if (clearBtn) {
|
||||
clearBtn.addEventListener('click', function () {
|
||||
form.reset();
|
||||
hideElement(successActions);
|
||||
hideElement(errorArea);
|
||||
|
||||
// Clear outputs
|
||||
const outputText = document.getElementById('outputText');
|
||||
if (outputText) outputText.value = '';
|
||||
|
||||
const previewArea = document.getElementById('previewArea');
|
||||
if (previewArea) {
|
||||
previewArea.innerHTML = `
|
||||
<div class="text-center text-muted p-4">
|
||||
<i class="fas fa-eye fa-2x mb-2"></i>
|
||||
<p>@ViewBag.PreviewPlaceholder</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// Hide file info
|
||||
const fileInfo = document.querySelector('.file-info');
|
||||
if (fileInfo) fileInfo.style.display = 'none';
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@ -0,0 +1,56 @@
|
||||
@* Views/Shared/_TestimonialsSection.cshtml *@
|
||||
@model OnlyOneAccessTemplate.Models.ContentBlock
|
||||
|
||||
<div class="row justify-content-center">
|
||||
@{
|
||||
var testimonials = new[]
|
||||
{
|
||||
new { Quote = ViewBag.Testimonial1Quote ?? "Excelente ferramenta, muito fácil de usar!", Name = ViewBag.Testimonial1Name ?? "Maria Silva", Position = ViewBag.Testimonial1Position ?? "Usuária" },
|
||||
new { Quote = ViewBag.Testimonial2Quote ?? "Economizou muito do meu tempo no trabalho.", Name = ViewBag.Testimonial2Name ?? "João Santos", Position = ViewBag.Testimonial2Position ?? "Profissional" },
|
||||
new { Quote = ViewBag.Testimonial3Quote ?? "Recomendo para todos que precisam converter arquivos.", Name = ViewBag.Testimonial3Name ?? "Ana Costa", Position = ViewBag.Testimonial3Position ?? "Cliente" }
|
||||
};
|
||||
}
|
||||
|
||||
@foreach (var testimonial in testimonials)
|
||||
{
|
||||
<div class="col-lg-4 col-md-6 mb-4">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-body text-center p-4">
|
||||
<div class="mb-3">
|
||||
<i class="fas fa-quote-left text-primary fa-2x opacity-50"></i>
|
||||
</div>
|
||||
<p class="card-text mb-4 fst-italic">
|
||||
"@testimonial.Quote"
|
||||
</p>
|
||||
<div class="d-flex align-items-center justify-content-center">
|
||||
<div class="avatar me-3">
|
||||
<div class="bg-primary rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
|
||||
<span class="text-white fw-bold">@testimonial.Name.Substring(0, 1)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-start">
|
||||
<h6 class="mb-0 fw-bold">@testimonial.Name</h6>
|
||||
<small class="text-muted">@testimonial.Position</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Avaliação Geral -->
|
||||
<div class="row mt-4">
|
||||
<div class="col-12 text-center">
|
||||
<div class="d-inline-flex align-items-center bg-success bg-opacity-10 rounded-pill px-4 py-2">
|
||||
<div class="me-2">
|
||||
@for (int i = 1; i <= 5; i++)
|
||||
{
|
||||
<i class="fas fa-star text-warning"></i>
|
||||
}
|
||||
</div>
|
||||
<span class="fw-bold text-success">4.9/5</span>
|
||||
<span class="text-muted ms-2">@(ViewBag.TestimonialsCount ?? "Mais de 500 avaliações positivas")</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,8 +0,0 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
18
OnlyOneAccessTemplate/appsettings.Production.json
Normal file
18
OnlyOneAccessTemplate/appsettings.Production.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"MongoDB": "mongodb+srv://usuario:senha@cluster.mongodb.net/text_case_converter_db?retryWrites=true&w=majority"
|
||||
},
|
||||
|
||||
"SEO": {
|
||||
"DefaultDomain": "https://maiusculasminusculas.com",
|
||||
"GoogleTagManagerId": "GTM-REAL123",
|
||||
"GoogleAnalyticsId": "GA-REAL456"
|
||||
},
|
||||
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,31 +1,43 @@
|
||||
{
|
||||
// Exemplo 1: Conversor de Maiúsculas/Minúsculas
|
||||
"Converter": {
|
||||
"Type": "text-case",
|
||||
"Name": "Conversor de Maiúsculas e Minúsculas"
|
||||
},
|
||||
|
||||
// Exemplo 2: Conversor CSV para JSON
|
||||
// "Converter": {
|
||||
// "Type": "csv-json",
|
||||
// "Name": "Conversor CSV para JSON"
|
||||
// },
|
||||
|
||||
// Exemplo 3: Conversor OCR (Imagem para Texto)
|
||||
// "Converter": {
|
||||
// "Type": "image-ocr",
|
||||
// "Name": "Conversor de Imagem para Texto"
|
||||
// },
|
||||
|
||||
"ConnectionStrings": {
|
||||
"MongoDB": "mongodb://admin:c4rn31r0@k3sw2:27017,k3ss1:27017/?authSource=admin"
|
||||
},
|
||||
|
||||
"MongoDB": {
|
||||
"DatabaseName": "text_case_converter_db"
|
||||
},
|
||||
|
||||
"SEO": {
|
||||
"DefaultDomain": "https://maiusculasminusculas.com",
|
||||
"DefaultSiteName": "Conversor de Maiúsculas e Minúsculas Online",
|
||||
"GoogleTagManagerId": "GTM-XXXXXXX",
|
||||
"GoogleAnalyticsId": "GA-XXXXXXXX"
|
||||
},
|
||||
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"MongoDB": "mongodb://admin:c4rn31r0@k3sw2:27017,k3ss1:27017/?authSource=admin"
|
||||
},
|
||||
"MongoDB": {
|
||||
"DatabaseName": "ConversionSite",
|
||||
"Collections": {
|
||||
"SiteConfigurations": "site_configurations",
|
||||
"ConversionData": "conversion_data",
|
||||
"Analytics": "analytics"
|
||||
}
|
||||
},
|
||||
"SEO": {
|
||||
"DefaultSiteName": "Seu Site de Conversão",
|
||||
"DefaultDomain": "https://seusite.com",
|
||||
"GoogleTagManagerId": "GTM-XXXXXXX",
|
||||
"GoogleAnalyticsId": "GA-XXXXXXXX",
|
||||
"FacebookPixelId": "XXXXXXXXX"
|
||||
},
|
||||
"ResponseCaching": {
|
||||
"Duration": 300,
|
||||
"VaryByHeader": "Accept-Language"
|
||||
}
|
||||
}
|
||||
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
|
||||
@ -0,0 +1,413 @@
|
||||
// wwwroot/js/converters/text-case-converter.js
|
||||
// Implementação específica para conversor de maiúsculas/minúsculas
|
||||
|
||||
let converterConfig = null;
|
||||
|
||||
// Função principal chamada pelo widget base
|
||||
async function performConversion(formData) {
|
||||
const textInput = formData.get('inputText');
|
||||
const caseType = formData.get('caseType') || 'upper';
|
||||
|
||||
if (!textInput || textInput.trim() === '') {
|
||||
throw new Error('Por favor, insira algum texto para converter');
|
||||
}
|
||||
|
||||
// Fazer requisição para o backend
|
||||
const requestData = new FormData();
|
||||
requestData.append('inputType', 'text');
|
||||
requestData.append('textInput', textInput);
|
||||
requestData.append('language', document.documentElement.lang || 'pt');
|
||||
|
||||
// Adicionar opções
|
||||
const options = { caseType: caseType };
|
||||
requestData.append('options', JSON.stringify(options));
|
||||
|
||||
const response = await fetch('/converter/api/convert/text-case', {
|
||||
method: 'POST',
|
||||
body: requestData
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.message || 'Erro na conversão');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// Mostrar resultado
|
||||
showConversionResult(result.outputText);
|
||||
}
|
||||
|
||||
// Função para mostrar o resultado
|
||||
function showConversionResult(outputText) {
|
||||
const outputArea = document.getElementById('outputArea');
|
||||
const outputTextElement = document.getElementById('outputText');
|
||||
const successActions = document.getElementById('successActions');
|
||||
|
||||
if (outputTextElement) {
|
||||
outputTextElement.value = outputText;
|
||||
outputArea.style.display = 'block';
|
||||
successActions.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
// Inicialização específica do conversor
|
||||
function initializeConverter() {
|
||||
loadConverterConfig();
|
||||
setupAdvancedOptions();
|
||||
}
|
||||
|
||||
// Carregar configuração do conversor
|
||||
async function loadConverterConfig() {
|
||||
try {
|
||||
const response = await fetch('/converter/config/text-case');
|
||||
if (response.ok) {
|
||||
converterConfig = await response.json();
|
||||
updateUIWithConfig(converterConfig.config);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erro ao carregar configuração:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Atualizar UI com configuração
|
||||
function updateUIWithConfig(config) {
|
||||
const texts = config.localizedTexts;
|
||||
|
||||
// Atualizar textos localizados
|
||||
Object.keys(texts).forEach(key => {
|
||||
const elements = document.querySelectorAll(`[data-text="${key}"]`);
|
||||
elements.forEach(el => {
|
||||
if (el.tagName === 'INPUT' && (el.type === 'button' || el.type === 'submit')) {
|
||||
el.value = texts[key];
|
||||
} else {
|
||||
el.textContent = texts[key];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Configurar opções avançadas
|
||||
function setupAdvancedOptions() {
|
||||
const advancedContainer = document.getElementById('advancedSettings');
|
||||
if (advancedContainer) {
|
||||
advancedContainer.innerHTML = `
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Tipo de Conversão</label>
|
||||
<select name="caseType" class="form-select">
|
||||
<option value="upper">MAIÚSCULAS</option>
|
||||
<option value="lower">minúsculas</option>
|
||||
<option value="title">Primeira Maiúscula Em Cada Palavra</option>
|
||||
<option value="sentence">Primeira maiúscula apenas</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
// wwwroot/js/converters/csv-json-converter.js
|
||||
// Implementação específica para conversor CSV para JSON
|
||||
|
||||
async function performConversion(formData) {
|
||||
const textInput = formData.get('inputText');
|
||||
const fileInput = formData.get('file');
|
||||
|
||||
if (!textInput && !fileInput) {
|
||||
throw new Error('Por favor, forneça conteúdo CSV ou faça upload de um arquivo');
|
||||
}
|
||||
|
||||
const requestData = new FormData();
|
||||
|
||||
if (fileInput && fileInput.size > 0) {
|
||||
requestData.append('inputType', 'file');
|
||||
requestData.append('fileInput', fileInput);
|
||||
} else {
|
||||
requestData.append('inputType', 'text');
|
||||
requestData.append('textInput', textInput);
|
||||
}
|
||||
|
||||
requestData.append('language', document.documentElement.lang || 'pt');
|
||||
|
||||
const response = await fetch('/converter/api/convert/csv-json', {
|
||||
method: 'POST',
|
||||
body: requestData
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.message || 'Erro na conversão');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// Mostrar resultado formatado
|
||||
showJsonResult(result.outputText);
|
||||
}
|
||||
|
||||
function showJsonResult(jsonText) {
|
||||
const outputTextElement = document.getElementById('outputText');
|
||||
const successActions = document.getElementById('successActions');
|
||||
|
||||
if (outputTextElement) {
|
||||
// Formatar JSON para melhor visualização
|
||||
try {
|
||||
const parsed = JSON.parse(jsonText);
|
||||
outputTextElement.value = JSON.stringify(parsed, null, 2);
|
||||
} catch {
|
||||
outputTextElement.value = jsonText;
|
||||
}
|
||||
|
||||
document.getElementById('outputArea').style.display = 'block';
|
||||
successActions.style.display = 'block';
|
||||
|
||||
// Adicionar botão de download
|
||||
addDownloadButton(jsonText);
|
||||
}
|
||||
}
|
||||
|
||||
function addDownloadButton(content) {
|
||||
const successActions = document.getElementById('successActions');
|
||||
|
||||
// Verificar se já existe botão de download
|
||||
if (document.getElementById('downloadJsonBtn')) return;
|
||||
|
||||
const downloadBtn = document.createElement('button');
|
||||
downloadBtn.id = 'downloadJsonBtn';
|
||||
downloadBtn.type = 'button';
|
||||
downloadBtn.className = 'btn btn-sm btn-outline-success';
|
||||
downloadBtn.innerHTML = '<i class="fas fa-download me-1"></i> Baixar JSON';
|
||||
|
||||
downloadBtn.addEventListener('click', () => {
|
||||
const blob = new Blob([content], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'converted.json';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
});
|
||||
|
||||
successActions.appendChild(downloadBtn);
|
||||
}
|
||||
|
||||
function initializeConverter() {
|
||||
// CSV específico: permitir preview dos dados
|
||||
setupCsvPreview();
|
||||
}
|
||||
|
||||
function setupCsvPreview() {
|
||||
const textInput = document.getElementById('inputText');
|
||||
if (textInput) {
|
||||
textInput.addEventListener('input', debounce(showCsvPreview, 500));
|
||||
}
|
||||
}
|
||||
|
||||
function showCsvPreview() {
|
||||
const textInput = document.getElementById('inputText');
|
||||
const csvContent = textInput.value.trim();
|
||||
|
||||
if (csvContent.length > 0) {
|
||||
try {
|
||||
const lines = csvContent.split('\n').slice(0, 5); // Mostrar só 5 linhas
|
||||
const preview = lines.map(line =>
|
||||
line.split(',').map(cell => `<td>${cell.trim()}</td>`).join('')
|
||||
).map(row => `<tr>${row}</tr>`).join('');
|
||||
|
||||
// Mostrar preview se houver elemento para isso
|
||||
const previewContainer = document.getElementById('csvPreview');
|
||||
if (previewContainer) {
|
||||
previewContainer.innerHTML = `
|
||||
<small class="text-muted">Preview (primeiras 5 linhas):</small>
|
||||
<table class="table table-sm table-bordered mt-1">
|
||||
${preview}
|
||||
</table>
|
||||
`;
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignorar erros de preview
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Utility function
|
||||
function debounce(func, wait) {
|
||||
let timeout;
|
||||
return function executedFunction(...args) {
|
||||
const later = () => {
|
||||
clearTimeout(timeout);
|
||||
func(...args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
}
|
||||
|
||||
// wwwroot/js/converters/image-ocr-converter.js
|
||||
// Implementação específica para conversor de imagem para texto (OCR)
|
||||
|
||||
async function performConversion(formData) {
|
||||
const fileInput = formData.get('file');
|
||||
|
||||
if (!fileInput || fileInput.size === 0) {
|
||||
throw new Error('Por favor, selecione uma imagem');
|
||||
}
|
||||
|
||||
// Validar tipo de arquivo
|
||||
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/bmp', 'application/pdf'];
|
||||
if (!allowedTypes.includes(fileInput.type)) {
|
||||
throw new Error('Formato de arquivo não suportado. Use JPG, PNG, GIF, BMP ou PDF.');
|
||||
}
|
||||
|
||||
// Validar tamanho (15MB)
|
||||
if (fileInput.size > 15 * 1024 * 1024) {
|
||||
throw new Error('Arquivo muito grande. Tamanho máximo: 15MB');
|
||||
}
|
||||
|
||||
const requestData = new FormData();
|
||||
requestData.append('inputType', 'file');
|
||||
requestData.append('fileInput', fileInput);
|
||||
requestData.append('language', document.documentElement.lang || 'pt');
|
||||
|
||||
// Adicionar opções de OCR se houver
|
||||
const ocrLanguage = formData.get('ocrLanguage') || 'por';
|
||||
const options = { ocrLanguage: ocrLanguage };
|
||||
requestData.append('options', JSON.stringify(options));
|
||||
|
||||
const response = await fetch('/converter/api/convert/image-ocr', {
|
||||
method: 'POST',
|
||||
body: requestData
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.message || 'Erro no processamento da imagem');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// Mostrar resultado do OCR
|
||||
showOcrResult(result.outputText, fileInput);
|
||||
}
|
||||
|
||||
function showOcrResult(extractedText, originalFile) {
|
||||
const outputTextElement = document.getElementById('outputText');
|
||||
const successActions = document.getElementById('successActions');
|
||||
|
||||
if (outputTextElement) {
|
||||
outputTextElement.value = extractedText;
|
||||
document.getElementById('outputArea').style.display = 'block';
|
||||
successActions.style.display = 'block';
|
||||
|
||||
// Mostrar preview da imagem
|
||||
showImagePreview(originalFile);
|
||||
|
||||
// Adicionar botão para salvar texto
|
||||
addSaveTextButton(extractedText);
|
||||
}
|
||||
}
|
||||
|
||||
function showImagePreview(file) {
|
||||
const previewContainer = document.getElementById('imagePreview');
|
||||
if (previewContainer && file.type.startsWith('image/')) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
previewContainer.innerHTML = `
|
||||
<div class="mt-3">
|
||||
<small class="text-muted">Imagem processada:</small><br>
|
||||
<img src="${e.target.result}" alt="Preview" class="img-thumbnail mt-1" style="max-height: 200px;">
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
}
|
||||
|
||||
function addSaveTextButton(text) {
|
||||
const successActions = document.getElementById('successActions');
|
||||
|
||||
if (document.getElementById('saveTextBtn')) return;
|
||||
|
||||
const saveBtn = document.createElement('button');
|
||||
saveBtn.id = 'saveTextBtn';
|
||||
saveBtn.type = 'button';
|
||||
saveBtn.className = 'btn btn-sm btn-outline-success';
|
||||
saveBtn.innerHTML = '<i class="fas fa-save me-1"></i> Salvar Texto';
|
||||
|
||||
saveBtn.addEventListener('click', () => {
|
||||
const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'texto-extraido.txt';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
});
|
||||
|
||||
successActions.appendChild(saveBtn);
|
||||
}
|
||||
|
||||
function initializeConverter() {
|
||||
setupAdvancedOcrOptions();
|
||||
setupImagePreview();
|
||||
}
|
||||
|
||||
function setupAdvancedOcrOptions() {
|
||||
const advancedContainer = document.getElementById('advancedSettings');
|
||||
if (advancedContainer) {
|
||||
advancedContainer.innerHTML = `
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Idioma do OCR</label>
|
||||
<select name="ocrLanguage" class="form-select">
|
||||
<option value="por">Português</option>
|
||||
<option value="eng">English</option>
|
||||
<option value="spa">Español</option>
|
||||
<option value="fra">Français</option>
|
||||
<option value="deu">Deutsch</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Qualidade</label>
|
||||
<select name="quality" class="form-select">
|
||||
<option value="balanced">Balanceada</option>
|
||||
<option value="fast">Rápida</option>
|
||||
<option value="accurate">Precisa</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
function setupImagePreview() {
|
||||
const fileInput = document.getElementById('fileInput');
|
||||
if (fileInput) {
|
||||
fileInput.addEventListener('change', function (e) {
|
||||
const file = e.target.files[0];
|
||||
if (file && file.type.startsWith('image/')) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
let previewContainer = document.getElementById('imagePreview');
|
||||
if (!previewContainer) {
|
||||
previewContainer = document.createElement('div');
|
||||
previewContainer.id = 'imagePreview';
|
||||
fileInput.parentNode.appendChild(previewContainer);
|
||||
}
|
||||
|
||||
previewContainer.innerHTML = `
|
||||
<div class="mt-2">
|
||||
<img src="${event.target.result}" alt="Preview" class="img-thumbnail" style="max-height: 150px;">
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user