Ir para o conteúdo do rodapé
USANDO O IRONBARCODE

Como criar um leitor de código QR em Blazor

Este artigo explora a integração de um leitor de códigos de resposta rápida (leitor de código QR) em um aplicativo Blazor usando IronQR, uma biblioteca .NET. Um código QR é um código de barras bidimensional que armazena muito mais dados do que um código de barras unidimensional comum.

Blazor, um framework da Microsoft, permite aos desenvolvedores tanto produzir aplicativos de página única (usando o app Blazor WebAssembly) quanto usar C# para construir interfaces web interativas (Blazor Server, que focaremos neste guia).

A integração do IronQR com o Blazor Server para a digitalização de códigos QR é uma combinação estratégica que aproveita as forças de ambas as tecnologias. Ao integrar o IronQR com aplicativos Blazor, você pode lidar de forma eficiente com a geração e digitalização de códigos QR. Esta funcionalidade de um leitor de código QR é cada vez mais requisitada em vários contextos empresariais, como gestão de estoque, sistemas de bilhética e compartilhamento de informações sem contato.

Compreendendo os Conceitos Básicos

O que é um Blazor Server?

Blazor Server é um framework de aplicação web que faz parte da plataforma ASP.NET Core. Ele permite que desenvolvedores construam interfaces de usuário web interativas usando C# em vez de JavaScript. Este modelo do lado do servidor opera lidando com interações do usuário através de uma conexão SignalR, que fornece funcionalidade web em tempo real. Isso ajuda os desenvolvedores a criar apps web eficazes e interativos.

Introdução ao IronQR

IronQR é uma biblioteca .NET que se destaca pela capacidade de ler, interpretar e gerar códigos QR com alta precisão. Ela oferece uma gama de funcionalidades, incluindo a capacidade de lidar com diferentes tipos de conteúdo de código QR. A força do IronQR reside na sua simplicidade e facilidade de integração em aplicações .NET, tornando-o uma escolha ideal para desenvolvedores que desejam incorporar e criar funcionalidades de código QR.

Como Criar um Scanner de Código QR com Blazor

  1. Crie uma Aplicação Blazor Server no Visual Studio Code
  2. Instale a Biblioteca de Classes de Código QR usando o Gerenciador de Pacotes NuGet
  3. Crie a interface do usuário usando HTML e CSS no index.razor
  4. Escreva a lógica de manipulação de arquivos enviados
  5. Escreva a lógica de digitalização do QR usando a biblioteca QR
  6. Exiba o resultado na caixa de texto

Preparando o ambiente

Crie uma Nova Aplicação Blazor Server

Inicie o Visual Studio e escolha "Criar um novo projeto". Na tela de seleção de modelo de projeto, encontre e selecione o modelo "Blazor Server App". Clique em Avançar.

Como Criar um Scanner de Código QR Blazor: Figura 1 - Encontrando o modelo correto para implementar

Tendo escolhido o modelo, insira um Nome para o Projeto e Localização (mantenha tudo o mais nos valores padrão) e clique no botão Avançar.

Como Criar um Scanner de Código QR Blazor: Figura 2 - Configurando os detalhes do projeto

Agora selecione o .NET Framework desejado e pressione o botão de criar. Isso criará uma aplicação Blazor Server.

Como Criar um Scanner de Código QR Blazor: Figura 3 - Selecionando o .NET Framework e criando o projeto

Instalando a Biblioteca IronQR

Clique em Ferramentas na barra de menu. No menu suspenso, selecione o Gerenciador de Pacotes NuGet. No menu de contexto, selecione "Gerenciar Pacotes NuGet para Solução". Isso abrirá a aba do Gerenciador de Pacotes NuGet.

Como Criar um Scanner de Código QR Blazor: Figura 4 - Acessando o gerenciador de pacotes do NuGet

No Gerenciador de Pacotes NuGet, pesquise por "IronQR" na aba "Procurar". Em seguida, localize o pacote "IronQR" na lista. Clique no botão "Instalar".

Como Criar um Scanner de Código QR Blazor: Figura 5 - Instalando o pacote IronQR através da guia Navegar

Agora que você tem tudo instalado, podemos examinar a estrutura do projeto e implementar tudo no seu projeto.

Implementando a Digitalização de Código QR

Construindo a Interface do Usuário

A interface do usuário para o Scanner de Código QR é construída principalmente dentro do arquivo Index.razor. Este arquivo, parte de um projeto Blazor Server, usa uma combinação de HTML e Sintaxe Razor para criar uma página web dinâmica e interativa. A estrutura inclui:

@page "/"
@using System.IO
@using Microsoft.AspNetCore.Components.Forms
@using IronQr
@using IronSoftware.Drawing
@inject IJSRuntime JSRuntime
<PageTitle>QR Code Scanner</PageTitle>
<div>
    <h1>QR Code Scanner</h1> 
    <InputFile OnChange="HandleSelectedFile" accept="image/*" class="file-input" />
    @if (!string.IsNullOrEmpty(qrImageSrcForDisplay))
    {
        <img src="@qrImageSrcForDisplay" alt="QR Code Image" class="qr-image" />
    }
    <button @onclick="ScanQRCode" disabled="@(!fileSelected)" class="button scan-button">Scan QR Code</button>
    @if (!string.IsNullOrEmpty(scannedText))
    {
        <div class="result-section">
            <input type="text" value="@scannedText" readonly class="result-input" />
            <button @onclick="CopyToClipboard" class="button copy-button">Copy</button>
        </div>
    }
</div>

Título e Cabeçalho: As tags <PageTitle> e <h1> definem o título da página e o cabeçalho principal, respectivamente, estabelecendo o contexto para o usuário.

Controle de Upload de Imagem: Um componente <InputFile> é usado para fazer upload de imagens de código QR. Este elemento é adaptado para aceitar apenas arquivos de imagem, melhorando a experiência do usuário ao filtrar tipos de arquivos não relevantes.

Exibição de Imagem: Uma vez que uma imagem é carregada, ela é exibida usando uma tag <img>. Este feedback visual é crucial para assegurar ao usuário que o arquivo correto foi enviado.

Botão de Escanear: Um botão marcado com @onclick="ScanQRCode" aciona o processo de escaneamento. Sua disponibilidade depende de um arquivo ser selecionado, melhorando a intuitividade da interface.

Exibição do Resultado: O texto do código QR escaneado é exibido em um campo de entrada de texto para fácil visualização. Um botão separado permite aos usuários copiar este texto para a área de transferência.

Estilização CSS em site.css

A estética visual e o layout do Scanner de Código QR são definidos no arquivo site.css.

.content {
    padding: 20px;
    margin: 10px auto; /* Centers the content */
    max-width: 500px; /* Sets a max width for the content */
    border-radius: 10px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.2);
    text-align: center;
}

.file-input, .result-input {
    margin: 10px 0;
    padding: 10px;
    border-radius: 5px;
    border: 1px solid #ddd;
    width: 100%;
}

.button {
    background-color: #4CAF50;
    color: white;
    border: none;
    cursor: pointer;
    padding: 10px;
    margin: 10px 0;
    border-radius: 5px;
    transition: background-color 0.3s, box-shadow 0.3s;
    width: auto; /* Adjusts button width */
    display: inline-block; /* Allows the width to adjust to content */
}

.button:hover {
    background-color: #45a049;
    box-shadow: 0 4px 8px rgba(0,0,0,0.2);
} 

.qr-image {
    max-width: 300px;
    max-height: 300px;
    display: block;
    margin: 10px auto;
    border-radius: 10px;
}

.result-section {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
}

.result-input {
    width: 100%;
    box-sizing: border-box;
}

.copy-button {
    margin-top: 10px;
    white-space: nowrap;
}

.content: Esta classe estila a área de conteúdo principal, dando-lhe uma largura definida, alinhamento centralizado e sombra sutil para profundidade.

.file-input, .result-input: Estas classes estilizam os elementos de entrada de arquivo e exibição de resultados, garantindo que sejam visualmente consistentes e preencham totalmente a largura do container.

.button: Os botões são estilizados com um fundo verde distinto, cantos arredondados e um efeito de hover para melhor interação do usuário.

.qr-image: Os estilos aplicados à imagem do código QR incluem restrições de tamanho e margem automática para centralizar, tornando a imagem proeminente, mas não avassaladora.

.result-section: Esta classe garante que os elementos dentro da seção de resultados estejam alinhados centralmente e espaçados adequadamente.

Gerenciamento de uploads de arquivos

O método HandleSelectedFile é uma parte crucial do processo de escaneamento de código QR, lidando com o upload de arquivo do usuário e preparando-o para escaneamento. Este método é acionado quando o usuário seleciona um arquivo através do componente <InputFile>. Isto é mostrado no seguinte código:

private async Task HandleSelectedFile(InputFileChangeEventArgs e)
{
    selectedFile = e.File;
    fileSelected = true;
    var imagesDirectory = Path.Combine(Directory.GetCurrentDirectory(), "UploadedImages");
    Directory.CreateDirectory(imagesDirectory); // Ensure the directory exists

    // Use a GUID as the unique file name
    var uniqueFileName = Guid.NewGuid().ToString() + Path.GetExtension(selectedFile.Name);
    var fullPath = Path.Combine(imagesDirectory, uniqueFileName);

    await using (var fileStream = new FileStream(fullPath, FileMode.Create))
    {
        await selectedFile.OpenReadStream().CopyToAsync(fileStream);
    }

    // Store the full path in qrImageSrc for scanning
    qrImageSrc = fullPath;

    // Optionally, create a base64 string for displaying the image (if needed)
    byte[] imageBytes = await File.ReadAllBytesAsync(fullPath);
    var base64String = Convert.ToBase64String(imageBytes);
    qrImageSrcForDisplay = $"data:image/{Path.GetExtension(selectedFile.Name).TrimStart('.')};base64,{base64String}";
}
private async Task HandleSelectedFile(InputFileChangeEventArgs e)
{
    selectedFile = e.File;
    fileSelected = true;
    var imagesDirectory = Path.Combine(Directory.GetCurrentDirectory(), "UploadedImages");
    Directory.CreateDirectory(imagesDirectory); // Ensure the directory exists

    // Use a GUID as the unique file name
    var uniqueFileName = Guid.NewGuid().ToString() + Path.GetExtension(selectedFile.Name);
    var fullPath = Path.Combine(imagesDirectory, uniqueFileName);

    await using (var fileStream = new FileStream(fullPath, FileMode.Create))
    {
        await selectedFile.OpenReadStream().CopyToAsync(fileStream);
    }

    // Store the full path in qrImageSrc for scanning
    qrImageSrc = fullPath;

    // Optionally, create a base64 string for displaying the image (if needed)
    byte[] imageBytes = await File.ReadAllBytesAsync(fullPath);
    var base64String = Convert.ToBase64String(imageBytes);
    qrImageSrcForDisplay = $"data:image/{Path.GetExtension(selectedFile.Name).TrimStart('.')};base64,{base64String}";
}
$vbLabelText   $csharpLabel

Aqui está uma análise detalhada da sua funcionalidade:

Seleção e Validação de Arquivo: Quando um usuário faz upload de um arquivo, o método captura os detalhes do arquivo usando InputFileChangeEventArgs e. A variável selectedFile é então atribuída a este arquivo, e um booleano fileSelected é definido como verdadeiro, indicando que os dados/arquivo de entrada estão prontos para processamento.

Criando o Caminho do Arquivo: O método prepara um diretório para armazenar a imagem carregada. Ele usa Path.Combine para criar um caminho para o diretório 'UploadedImages', garantindo que ele exista com Directory.CreateDirectory. Esta etapa é crucial para organizar arquivos carregados sistematicamente.

Gerando um Nome de Arquivo Único: Para evitar conflitos com arquivos existentes, um nome de arquivo único é gerado usando um GUID (Identificador Único Global) seguido da extensão original do arquivo. Isso garante que cada arquivo carregado seja identificado de forma exclusiva.

Salvando o Arquivo: O arquivo é então salvo no servidor. O método cria um stream de arquivo apontando para o caminho do arquivo gerado recentemente, e o conteúdo do arquivo carregado é copiado para este stream usando await selectedFile.OpenReadStream().CopyToAsync(fileStream). Esta etapa finaliza o processo de upload.

Preparando a Imagem para Exibição: Após o arquivo ser salvo, é necessário exibir a imagem de volta ao usuário para confirmação. O método lê o arquivo em um array de bytes e o converte em uma string base64, adequada para ser embutida diretamente no atributo src de uma tag <img>. Esta conversão permite que a imagem seja exibida sem exigir uma solicitação separada ao servidor para o arquivo da imagem.

Escaneando o Código QR

O método ScanQRCode é o coração da funcionalidade de escaneamento de código QR na aplicação Blazor Server. Este método pega a imagem carregada e utiliza IronQR para extrair os dados do código QR.

private async Task ScanQRCode()
{
    // Check if there is a valid image to work with
    if (string.IsNullOrEmpty(qrImageSrc)) return;

    try
    {
        var inputBmp = AnyBitmap.FromFile(qrImageSrc);
        QrImageInput imageInput = new QrImageInput(inputBmp);
        QrReader reader = new QrReader();
        IEnumerable<QrResult> results = reader.Read(imageInput);

        // Check if there are any results and if the first result contains text
        var firstResult = results.FirstOrDefault();
        if (firstResult != null && !string.IsNullOrWhiteSpace(firstResult.Value.ToString()))
        {
            scannedText = firstResult.Value.ToString();
        }
        else
        {
            scannedText = "QR value not found!";
        }
    }
    catch (Exception ex)
    {
        scannedText = "Error scanning QR code: " + ex.Message;
    }
}
private async Task ScanQRCode()
{
    // Check if there is a valid image to work with
    if (string.IsNullOrEmpty(qrImageSrc)) return;

    try
    {
        var inputBmp = AnyBitmap.FromFile(qrImageSrc);
        QrImageInput imageInput = new QrImageInput(inputBmp);
        QrReader reader = new QrReader();
        IEnumerable<QrResult> results = reader.Read(imageInput);

        // Check if there are any results and if the first result contains text
        var firstResult = results.FirstOrDefault();
        if (firstResult != null && !string.IsNullOrWhiteSpace(firstResult.Value.ToString()))
        {
            scannedText = firstResult.Value.ToString();
        }
        else
        {
            scannedText = "QR value not found!";
        }
    }
    catch (Exception ex)
    {
        scannedText = "Error scanning QR code: " + ex.Message;
    }
}
$vbLabelText   $csharpLabel

Inicialmente, o método verifica se a variável qrImageSrc, que contém o caminho para a imagem carregada, não está vazia. Esta verificação assegura que há uma imagem válida para trabalhar antes de prosseguir.

Uma vez que é confirmado que uma imagem está pronta para processamento, o método prossegue para a funcionalidade central de leitura de código QR. Isso envolve algumas etapas-chave, começando com o carregamento da imagem de seu local armazenado em um formato adequado para análise de código QR. Esta conversão é possibilitada pelo método AnyBitmap.FromFile(qrImageSrc), que prepara a imagem para o processo de escaneamento.

O próximo passo envolve a criação de um objeto QrReader. Este objeto é integral à biblioteca IronQR, servindo como a principal ferramenta para decodificar códigos QR a partir de imagens. Com a instância QrReader pronta, a aplicação prossegue para escanear a imagem carregada. A função reader.Read(imageInput) é responsável por esta ação, pesquisando meticulosamente a imagem por códigos QR e extraindo seus dados.

Os resultados do escaneamento são armazenados em uma coleção IEnumerable<QrResult>. Esta coleção é então examinada para encontrar o primeiro resultado de código QR. Se um código QR for detectado e contiver texto legível, este texto é capturado e armazenado na variável scannedText. No entanto, em cenários onde um código QR não é encontrado ou não contém texto, a aplicação define uma mensagem padrão para informar o usuário que nenhum valor QR foi detectado.

Uma vez que o código QR é escaneado com sucesso, a string de texto é exibida em um campo de entrada de texto, graças às capacidades de binding de dados bidirecional do Blazor. Isso é conseguido vinculando a variável scannedText a um elemento de entrada de texto. O campo de entrada é configurado para estar desabilitado, tornando-o somente leitura. Esta escolha de design foca a interação do usuário em visualizar o resultado e copiá-lo em vez de editar o conteúdo.

Todo o processo de escaneamento é envolvido por um bloco try-catch, protegendo contra quaisquer erros imprevistos durante a operação de escaneamento. Isso poderia incluir problemas relacionados ao formato do arquivo de imagem ou erros inesperados durante o processo de leitura. Se ocorrer uma exceção, ela é capturada, e uma mensagem de erro é formulada e exibida ao usuário. Essa abordagem ajuda a monitorar problemas enquanto mantém a transparência com o usuário, aumentando a confiabilidade do aplicativo.

Copiando o Resultado

Para habilitar o recurso de copiar para a área de transferência, uma função JavaScript chamada copyTextToClipboard é definida no arquivo _Host.cshtml. Este script é uma maneira simples, mas eficaz, de interagir com a área de transferência:

<script>
    function copyTextToClipboard(text) {
        navigator.clipboard.writeText(text).then(function () {
            console.log('Copying to clipboard was successful!');
        }, function (err) {
            console.error('Could not copy text: ', err);
        });
    }
</script>
<script>
    function copyTextToClipboard(text) {
        navigator.clipboard.writeText(text).then(function () {
            console.log('Copying to clipboard was successful!');
        }, function (err) {
            console.error('Could not copy text: ', err);
        });
    }
</script>
HTML

Esta função aceita um parâmetro de texto, que é o texto a ser copiado. Ela utiliza o método navigator.clipboard.writeText, uma abordagem moderna para interagir com a área de transferência. Este método é preferido por sua simplicidade e conformidade com os padrões web. Ele é projetado para registrar uma mensagem de sucesso no console após uma cópia bem-sucedida, auxiliando na depuração e garantindo um funcionamento suave. Em caso de erro, uma mensagem de erro é registrada no console, fornecendo insights sobre quaisquer problemas encontrados durante a operação.

O método CopyToClipboard na parte @code do arquivo index.razor serve como uma ponte entre o aplicativo Blazor e a função JavaScript. Um botão aciona esse método no clique da interface do usuário. Quando ativado, ele invoca a função JavaScript copyTextToClipboard usando as capacidades de InterOp em JavaScript do Blazor. O scannedText é passado como argumento para esta função, efetivamente copiando o texto para a área de transferência do usuário.

private async Task CopyToClipboard()
{
    await JSRuntime.InvokeVoidAsync("copyTextToClipboard", scannedText);
}
private async Task CopyToClipboard()
{
    await JSRuntime.InvokeVoidAsync("copyTextToClipboard", scannedText);
}
$vbLabelText   $csharpLabel

Executando o Aplicativo

Ao rodar o projeto, o usuário verá a seguinte interface limpa e simples. A tela inicial destaca o módulo do Scanner de Código QR de maneira proeminente. Este módulo inclui um botão para carregar o arquivo de imagem do código QR ('Escolher Arquivo') e outro para iniciar o processo de escaneamento ('Escanear Código QR'). Inicialmente, nenhum arquivo é selecionado e a área de escaneamento está em branco, aguardando a entrada do usuário.

Como Criar um Scanner de Código QR Blazor: Figura 6 - Resultado da execução inicial do projeto

O usuário seleciona e carrega uma imagem de código QR usando o botão 'Escolher Arquivo', que agora exibe o nome do arquivo selecionado (por exemplo, 'qrvalue.png'). O código QR carregado é visível na área designada na interface, confirmando ao usuário que a imagem está pronta para ser escaneada.

Como Criar um Scanner de Código QR Blazor: Figura 7 - O resultado de um usuário inputando um código QR

Após o usuário clicar no botão 'Escanear Código QR', o aplicativo processa a imagem. Se o escaneamento for bem-sucedido, o texto codificado dentro do código QR é exibido logo abaixo da imagem. Neste caso, o resultado escaneado ('<https://ironsoftware.com/csharp/qr/>') é um URL indicando para onde o código QR direcionaria um usuário quando escaneado com um leitor de QR. Um botão de cópia aparece ao lado do resultado, permitindo ao usuário copiar facilmente o texto escaneado para a área de transferência para uso posterior.

Como Criar um Scanner de Código QR Blazor: Figura 8 - Isso mostra o texto do código QR e o botão de copiar

Conclusão

Como Criar um Scanner de Código QR Blazor: Figura 9

Em resumo, o processo de integração do IronQR em uma aplicação Blazor Server é suave e eficaz, resultando em uma solução de escaneamento de código QR. Responsivo e fácil de usar, desde o início da configuração deste projeto até sua implementação da funcionalidade de escaneamento, graças a uma mistura do poderoso processamento do IronQR com o renderização dinâmica de UI do Blazor. O processo, desde a configuração do ambiente até a implantação, enfatiza a praticidade e eficácia dessa integração em aplicações do mundo real. Enquanto o IronQR é hábil em códigos QR, para projetos que requerem a funcionalidade de escanear código de barras, IronBarcode é uma opção ideal, oferecendo um nível semelhante de facilidade e integração.

IronQR oferece uma versão de teste gratuita para desenvolvedores explorarem seus recursos antes da compra. Para uso prolongado e acesso a todos os seus recursos profissionais em produção, as licenças do IronQR começam a partir de $799.

Perguntas frequentes

Como posso integrar um leitor de código QR em um aplicativo Blazor?

Para integrar um leitor de código QR em um aplicativo Blazor, você pode usar o IronQR, uma biblioteca .NET. Comece configurando um aplicativo Blazor Server no Visual Studio, instale o IronQR por meio do Gerenciador de Pacotes NuGet e crie uma interface de usuário no arquivo index.razor. Implemente a lógica de manipulação de arquivos e de leitura usando o IronQR para ler códigos QR e exibir os resultados.

Quais são os passos para configurar uma aplicação Blazor Server para leitura de código QR?

Para configurar um aplicativo Blazor Server para leitura de código QR, crie um novo aplicativo Blazor Server no Visual Studio, instale o IronQR através do Gerenciador de Pacotes NuGet, projete a interface do usuário com HTML e CSS no arquivo index.razor e escreva a lógica de leitura para processar imagens de código QR usando o IronQR.

Como o IronQR facilita a leitura de códigos QR em uma aplicação Blazor?

O IronQR facilita a leitura de códigos QR em aplicações Blazor, fornecendo métodos fáceis de usar para ler e gerar códigos QR. Ele se integra perfeitamente com aplicações .NET, permitindo que você implemente a lógica de leitura de códigos QR de forma eficiente e exiba os dados lidos em sua interface web.

Que funcionalidades a biblioteca IronQR oferece para o processamento de códigos QR?

A biblioteca IronQR oferece funcionalidades para ler, interpretar e gerar códigos QR. Ela suporta diversos formatos de imagem, facilitando a integração com aplicações que requerem a leitura ou geração de códigos QR. A biblioteca é reconhecida por sua precisão e facilidade de uso em projetos .NET.

Posso usar o IronQR para gerar códigos QR em uma aplicação Blazor?

Sim, o IronQR pode ser usado para gerar códigos QR em uma aplicação Blazor. Você pode integrá-lo à sua aplicação para criar códigos QR a partir de texto ou URLs, que podem então ser exibidos ou impressos conforme necessário.

Como posso solucionar problemas com a leitura de códigos QR no Blazor usando o IronQR?

Para solucionar problemas de leitura de código QR no Blazor usando o IronQR, certifique-se de que a biblioteca IronQR esteja instalada corretamente via NuGet Package Manager, verifique se o formato do arquivo de imagem é compatível e examine a lógica de leitura implementada no aplicativo em busca de erros. A consulta da documentação também pode fornecer informações adicionais.

Quais são as vantagens de usar o Blazor Server para aplicações de código QR?

Utilizar o Blazor Server para aplicações de código QR oferece diversas vantagens, incluindo a capacidade de criar interfaces web interativas usando C#, o processamento de interações do usuário no servidor através de uma conexão SignalR e a integração perfeita com bibliotecas como o IronQR para funcionalidades aprimoradas de código QR.

Como faço para exibir os resultados da leitura de um código QR em um aplicativo Blazor?

Em uma aplicação Blazor, você pode exibir os resultados da leitura de um código QR usando o IronQR para ler os dados do código e, em seguida, exibindo os resultados na interface do usuário. Isso pode ser feito atualizando um elemento de texto ou uma área de exibição na página com as informações lidas.

Curtis Chau
Redator Técnico

Curtis Chau é bacharel em Ciência da Computação (Universidade Carleton) e se especializa em desenvolvimento front-end, com experiência em Node.js, TypeScript, JavaScript e React. Apaixonado por criar interfaces de usuário intuitivas e esteticamente agradáveis, Curtis gosta de trabalhar com frameworks modernos e criar manuais ...

Leia mais

Iron Support Team

We're online 24 hours, 5 days a week.
Chat
Email
Call Me