Júlio César de Carvalho 4 meses atrás
pai
commit
529d1fad7a
20 arquivos alterados com 736 adições e 117 exclusões
  1. 130 40
      ConcursoProjetos/Components/Account/Pages/Register.razor
  2. 22 22
      ConcursoProjetos/Components/Pages/PageProjeto.razor
  3. 563 0
      ConcursoProjetos/Components/Pages/PageProjetosFileStream.razor
  4. BIN
      ConcursoProjetos/Files/1/Projeto_1_Projeto Arquitetônico-gInk_v1.1.1-638700227950071594.zip
  5. 0 15
      ConcursoProjetos/Files/1/config.txt
  6. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto Arquitetônico-gInk_v1.2.0-638700325428107583.zip
  7. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto Elétrico-gInk_v1.1.1-638700325476201903.zip
  8. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto Estrutural e Fundação-gInk_v1.1.1-638700337905136736.zip
  9. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto Hidrossanitário-gInk_v1.1.1-638700338305715479.zip
  10. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto Hidrossanitário-gInk_v1.2.0-638700337869966693.zip
  11. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto de Implantação de 8 Blocos-gInk_v1.1.1-638700337814057237.zip
  12. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto de Implantação de 8 Blocos-gInk_v1.1.1-638700338379629107.zip
  13. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto de Implantação de Esgoto Sanitário-gInk_v1.1.1-638700338115312542.zip
  14. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto de Implantação de Água Fria-gInk_v1.2.0-638700337977728643.zip
  15. BIN
      ConcursoProjetos/Files/2/Projeto_2_Projeto de Telecomunicação-gInk_v1.2.0-638700338159258750.zip
  16. 0 15
      ConcursoProjetos/Files/2/config.txt
  17. BIN
      ConcursoProjetos/Files/3/Projeto_3_Projeto Elétrico-gInk_v1.1.1-638700326217756212.zip
  18. BIN
      ConcursoProjetos/Files/3/Projeto_3_Projeto de Implantação de 8 Blocos-gInk_v1.2.0-638700326178150023.zip
  19. 0 15
      ConcursoProjetos/Files/3/config.txt
  20. 21 10
      ConcursoProjetos/wwwroot/js/app.js

+ 130 - 40
ConcursoProjetos/Components/Account/Pages/Register.razor

@@ -19,17 +19,60 @@
 @inject NavigationManager NavigationManager
 @inject IdentityRedirectManager RedirectManager
 @inject ICandidatoService candidatoService
+@inject IJSRuntime JSRuntime
+
+
+
+<HeadContent>
+
+    <script>
+
+        document.addEventListener("DOMContentLoaded", function() {
+
+            console.log("A página foi completamente renderizada.");
+
+
+            alert('Teste');
+
+        });
+
+
+
+        function showHiddenDiv()
+                {
+            var checkbox = document.getElementById('tipo-pessoa');
+            var isChecked = checkbox.checked;
+                    var element = document.getElementById('container-empresa');
+                if (isChecked)
+                    {
+                        element.style.display = 'block';
+                    }
+                        else
+                    {
+                        element.style.display = 'none';
+                    }
+                }
+
+
+
+
+
+    </script>
+
+</HeadContent>
+
 
 <PageTitle>Registro</PageTitle>
 
+
+
 <h1>Registro</h1>
 
 <div class="row">
     <div class="col-md-6">
         <StatusMessage Message="@Message" />
-        <EditForm Model="Input" asp-route-returnUrl="@ReturnUrl" method="post" OnValidSubmit="RegisterUser"  FormName="register">
+        <EditForm Model="Input" asp-route-returnUrl="@ReturnUrl" method="post" OnValidSubmit="RegisterUser" FormName="register">
             <DataAnnotationsValidator />
-            @* <h2>Create a new account.</h2> *@
             <hr />
             <ValidationSummary class="text-danger" role="alert" />
 
@@ -74,12 +117,11 @@
             </div>
 
             <div class="form-check form-switch">
-                <InputCheckbox @bind-Value="Input.TipoPessoa" class="form-check-input" id="tipo-pessoa"/>
+                <InputCheckbox @bind-Value="Input.TipoPessoa" class="form-check-input" id="tipo-pessoa" onclick='showHiddenDiv();' />
                 <label class="form-check-label" for="tipo-empresa">Você irá cadastrar projeto(s) de uma empresa?</label>
             </div>
 
-            @if (Input.TipoPessoa)
-            {
+            <div id="container-empresa" style="@(Input.TipoPessoa ? "display:block;" : "display:none;")">
                 <div class="form-floating mb-3">
                     <InputText @bind-Value="Input.Cnpj" class="form-control" autocomplete="username" aria-required="true" placeholder="Cnpj" />
                     <label for="Cnpj">Cnpj</label>
@@ -103,26 +145,29 @@
                     <label for="telefone">Telefone da Empresa</label>
                     <ValidationMessage For="() => Input.EmpresaTelefone" class="text-danger" />
                 </div>
-            }
+            </div>
 
+            <button type="submit" class="w-100 btn btn-lg btn-primary">Enviar</button>
 
-            <button type="submit" class="w-100 btn btn-lg btn-primary">Register</button>
         </EditForm>
     </div>
-@*     <div class="col-md-6 col-md-offset-2">
-        <section>
-            <h3>Use another service to register.</h3>
-            <hr />
-            <ExternalLoginPicker />
-        </section>
+
+
+    @*     <div class="col-md-6 col-md-offset-2">
+    <section>
+    <h3>Use another service to register.</h3>
+    <hr />
+    <ExternalLoginPicker />
+    </section>
     </div> *@
+
+
 </div>
 
 
 
 
 @code {
-
     private IEnumerable<IdentityError>? identityErrors;
 
     [SupplyParameterFromForm]
@@ -135,10 +180,22 @@
 
     protected override async Task OnInitializedAsync()
     {
-        Input.TipoPessoa = true;
+        await base.OnInitializedAsync();
+
+        //Input.TipoPessoa = false;
     }
 
 
+    // protected override async Task OnAfterRenderAsync(bool firstRender)
+    // {
+    //     if (firstRender)
+    //     {
+
+    //         await JSRuntime.InvokeVoidAsync("mascaras");
+    //     }
+    // }
+
+
     public async Task RegisterUser(EditContext editContext)
     {
         var user = CreateUser();
@@ -226,61 +283,94 @@
         return (IUserEmailStore<ApplicationUser>)UserStore;
     }
 
-    private sealed class InputModel
+    private sealed class InputModel : IValidatableObject
     {
-        [Required]
+        [Required(ErrorMessage = "O campo Email é obrigatório.")]
         [MaxLength(100)]
-        [EmailAddress]
-        [Display(Name = "Email")]
-        public string Email { get; set; } = "";
+        [EmailAddress(ErrorMessage = "O email informado não é válido.")]
+        [Display(Name = "Email")] public string Email { get; set; } = "";
 
-        [Required]
-        [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
+        [Required(ErrorMessage = "O campo Senha é obrigatório.")]
+        [StringLength(20, ErrorMessage = "A Senha deve ter pelo menos 6 e no máximo 20 caracteres.", MinimumLength = 6)]
         [DataType(DataType.Password)]
-        [Display(Name = "Password")]
+        [Display(Name = "Senha")]
         public string Password { get; set; } = "";
 
         [DataType(DataType.Password)]
-        [Display(Name = "Confirm password")]
-        [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
+        [Display(Name = "Confirme senha")]
+        [Compare("Password", ErrorMessage = "A Senha e a confirmação não são iguais.")]
         public string ConfirmPassword { get; set; } = "";
 
-        [Required]
+        [Required(ErrorMessage = "O Cpf é obrigatório.")]
         [MaxLength(14)]
         [Display(Name = "Cpf")]
         public string Cpf { get; set; } = "";
 
-        [Required]
+        [Required(ErrorMessage = "O Nome é obrigatório.")]
         [StringLength(100, MinimumLength = 5)]
         public string Nome { get; set; } = "";
 
-        [Required]
+        [Required(ErrorMessage = "O Telefone é obrigatório.")]
         [MaxLength(15)]
         [Display(Name = "(Telefone)")]
         public string Telefone { get; set; } = "";
 
-        [Required]
-        public bool TipoPessoa { get; set; } 
 
+        public bool TipoPessoa { get; set; }
 
-        [Required]
         [MaxLength(14)]
         [Display(Name = "Cnpj")]
         public string Cnpj { get; set; } = "";
 
-        [Required]
-        [StringLength(100, MinimumLength = 5)]
+        [MaxLength(100)]
         public string EmpresaRazaoSocial { get; set; } = "";
 
-        [Required]
+        [MaxLength(100)]
+        [Display(Name = "Empresa Empresa")]
+        public string EmpresaEmail { get; set; } = "";
+
         [MaxLength(15)]
         [Display(Name = "(Telefone)")]
-        public string EmpresaTelefone{ get; set; } = "";
+        public string EmpresaTelefone { get; set; } = "";
+
+
+        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
+        {
+            var results = new List<ValidationResult>();
+
+            if (TipoPessoa)
+            {
+                if (string.IsNullOrWhiteSpace(Cnpj))
+                {
+                    results.Add(new ValidationResult("CNPJ é obrigatório.", new[] { nameof(Cnpj) }));
+                }
+                if (string.IsNullOrWhiteSpace(EmpresaRazaoSocial))
+                {
+                    results.Add(new ValidationResult("Razão Social da Empresa é obrigatório.", new[] { nameof(EmpresaRazaoSocial) }));
+                }
+                if (string.IsNullOrWhiteSpace(EmpresaTelefone))
+                {
+                    results.Add(new ValidationResult("Telefone da Empresa é obrigatório.", new[] { nameof(EmpresaTelefone) }));
+                }
+                if (string.IsNullOrWhiteSpace(EmpresaEmail))
+                {
+                    results.Add(new ValidationResult("Email da Empresa é obrigatório.", new[] { nameof(EmpresaEmail) }));
+                }
+                else
+                { 
+                    // Validação de email usando regex 
+                    var emailAttribute = new EmailAddressAttribute(); 
+                    if (!emailAttribute.IsValid(EmpresaEmail)) 
+                    { 
+                        results.Add(new ValidationResult("O email da empresa informado não é válido.", new[] { nameof(EmpresaEmail) })); 
+                    } 
+                }
+            }
+
+            return results;
+        }
 
-        [Required]
-        [MaxLength(100)]
-        [EmailAddress]
-        [Display(Name = "Email")]
-        public string EmpresaEmail { get; set; } = "";
     }
+
+
 }

+ 22 - 22
ConcursoProjetos/Components/Pages/PageProjeto.razor

@@ -52,6 +52,7 @@
                 <RadzenFormField Text="Número de Unidades Habitacionais por Pavimento" Variant="@variant">
                         <RadzenDropDown @bind-Value="@Input.NumeroUnidades" Data="@listaDeUnidades" />
                 </RadzenFormField>
+
                 <RadzenFormField Text="E-mail do Responsável Técnico da Empresa" Variant="@variant">
                         <RadzenTextBox Name="Email" @bind-Value="@Input.ResponsavelTecnicoEmail" />
                         <RadzenRequiredValidator Component="Email" Text="E-mail é obrigatório" Popup=@popup Style="position: relative" />
@@ -59,10 +60,11 @@
                 </RadzenFormField>
 
                 <RadzenFormField Text="Telefone do Responsável Técnico da Empresa" Variant="@variant">
-                        <RadzenTextBox Name="ResponsavelTecnicoTelefone" @bind-Value="@Input.ResponsavelTecnicoTelefone" />
-                        <RadzenRequiredValidator Component="ResponsavelTecnicoTelefone" Text="Telefone do responsável técnico é obrigatório" Popup=@popup Style="position: relative" />
+                    <RadzenMask Mask="(**) *****-****" CharacterPattern="[0-9]" Placeholder="(00) 00000-0000" Name="ResponsavelTecnicoTelefone" @bind-Value="Input.ResponsavelTecnicoTelefone" />
+                    <RadzenRequiredValidator Component="ResponsavelTecnicoTelefone" Text="Telefone do responsável técnico é obrigatório" Popup=@popup Style="position: relative" />
                 </RadzenFormField>
-        </RadzenStack>
+
+             </RadzenStack>
         </RadzenColumn>
 
     </RadzenRow>
@@ -151,7 +153,7 @@
         // calculate the chunks we have to send
         TotalBytes = args.File.Size;
         long percent = 0;
-        long chunkSize = 400000;
+        long chunkSize = 40000; // (1 * 1024 * 1024);  // 1MB
         long numChunks = TotalBytes / chunkSize;
         long remainder = TotalBytes % chunkSize;
 
@@ -237,7 +239,7 @@
         {
             //"Seu projeto foi enviado com sucesso.Caso deseje realizar alguma alteração, o projeto estará listado na área 'meus projetos'"
 
-            await dialogService.Alert("Seu projeto foi enviado com sucesso. <br />Caso deseje realizar alguma alteração, o projeto estará listado na área 'Meus Projetos'.",
+            await dialogService.Alert("Seu projeto foi enviado com sucesso. <p>Caso deseje realizar alguma alteração, o projeto estará listado na área 'Meus Projetos'.</p>",
                                         "Projeto Enviado",
                                         new AlertOptions() { OkButtonText = "Ok" });
 
@@ -258,7 +260,7 @@
 
             if (result != true)
             {
-                await dialogService.Alert("Seu projeto foi enviado com sucesso.</p>Caso deseje realizar alguma alteração, o projeto estará listado na área 'Meus Projetos'",
+                await dialogService.Alert("Seu projeto foi enviado com sucesso.<p>Caso deseje realizar alguma alteração, o projeto estará listado na área 'Meus Projetos'.</p>",
                                             "Projeto Enviado",
                                             new AlertOptions() { OkButtonText = "Ok" });
 
@@ -275,27 +277,27 @@
     private void GerarArquivoTextoParaProjeto(Candidato candidato, Projeto projeto, string path)
     {
         string saudacao = $@"
-        Candidado:
-            Nome......: {candidato.NomeCompleto}
-            E-mail....: {candidato.Email}
-            Telefone..: { candidato.Email}
-        ";
+      Candidado:
+          Nome......: {candidato.NomeCompleto}
+          E-mail....: {candidato.Email}
+          Telefone..: {candidato.Email}
+      ";
 
-        if(candidato.TipoPessoa)  // Representa empresa
+        if (candidato.TipoPessoa)  // Representa empresa
         {
             saudacao += $@"
-            Empresa:
-                Nome....: {candidato.EmpresaRazaoSocial}
-                E-mail..: {candidato.EmpresaEmail}
-                Telefone..: {candidato.EmpresaTelefone}";
+          Empresa:
+              Nome....: {candidato.EmpresaRazaoSocial}
+              E-mail..: {candidato.EmpresaEmail}
+              Telefone..: {candidato.EmpresaTelefone}";
         }
 
         saudacao += $@"
 
-        Projeto '{projeto.Nome}':
-            Responsável.....: {projeto.ResponsavelTecnicoNomeCompleto}
-            E-mail...: {projeto.ResponsavelTecnicoEmail}
-            Telefone.: {projeto.ResponsavelTecnicoTelefone}";
+      Projeto '{projeto.Nome}':
+          Responsável.....: {projeto.ResponsavelTecnicoNomeCompleto}
+          E-mail...: {projeto.ResponsavelTecnicoEmail}
+          Telefone.: {projeto.ResponsavelTecnicoTelefone}";
 
 
         string fullPath = Path.Combine(path, "config.txt");
@@ -303,8 +305,6 @@
         File.WriteAllText(fullPath, saudacao);
     }
 
-
-
     [Parameter] 
     public Guid projetoCodigo { get; set; }
 

+ 563 - 0
ConcursoProjetos/Components/Pages/PageProjetosFileStream.razor

@@ -0,0 +1,563 @@
+@page "/pageprojetoFileStream/{projetoCodigo:guid}"
+
+@attribute [Authorize]
+@rendermode InteractiveServer
+
+@using System.ComponentModel.DataAnnotations
+@using System.Text
+@using System.Text.Encodings.Web
+@using ConcursoProjetos.Service
+@using Microsoft.AspNetCore.Identity
+@using Microsoft.AspNetCore.WebUtilities
+
+@using System;
+@using System.IO;
+
+
+@inject UserManager<ApplicationUser> UserManager
+@inject AuthenticationStateProvider AuthenticationStateProvider
+@inject ICandidatoService candidatoService
+@inject IProjetoService projetoService
+@inject IDocumentoService documentoService
+@inject ITipoDocumentoService tipoDocumentoServico
+@inject DialogService dialogService
+@inject NotificationService notificationService
+@inject NavigationManager Navigation
+
+
+<PageTitle>Cadastro de Projeto</PageTitle>
+
+<div class="container mt-5">
+
+    <h3>Cadastro de Projeto</h3>
+    <br />
+    <RadzenTemplateForm TItem="InputModel" Data=@Input Submit=@OnSubmit InvalidSubmit=@OnInvalidSubmit>
+        <RadzenRow Gap="1rem">
+
+            <RadzenColumn Size="12" SizeSM="6">
+                <RadzenStack>
+                    <RadzenFormField Text="Nome do Projeto" Variant="@variant">
+                        <RadzenTextBox Name="Nome" @bind-Value="@Input.Nome" />
+                        <RadzenRequiredValidator Component="Nome" Text="Nome do projeto é obrigatório" Popup=@popup Style="position: relative" />
+                    </RadzenFormField>
+                    <RadzenFormField Text="Nome do Responsável Técnico da Empresa" Variant="@variant">
+                        <RadzenTextBox Name="ResponsavelNome" @bind-Value="@Input.ResponsavelTecnicoNomeCompleto" />
+                        <RadzenRequiredValidator Component="ResponsavelNome" Text="Nome do responsável técnico é obrigatório" Popup=@popup Style="position: relative" />
+                    </RadzenFormField>
+                    <RadzenFormField Text="CPF do Responsável Técnico da Empresa" Variant="@variant">
+                        <RadzenMask Mask="***.***.***-**" CharacterPattern="[0-9]" Placeholder="000.000.000-00" Name="ResponsavelTecnicoCpf" @bind-Value="Input.ResponsavelTecnicoCpf" />
+                        <RadzenRequiredValidator Component="ResponsavelTecnicoCpf" Text="Cpf do responsável técnico é obrigatório" Popup=@popup Style="position: relative" />
+                    </RadzenFormField>
+                </RadzenStack>
+            </RadzenColumn>
+
+            <RadzenColumn Size="12" SizeSM="6">
+                <RadzenStack>
+                    <RadzenFormField Text="Número de Unidades Habitacionais por Pavimento" Variant="@variant">
+                        <RadzenDropDown @bind-Value="@Input.NumeroUnidades" Data="@listaDeUnidades" />
+                    </RadzenFormField>
+                    <RadzenFormField Text="E-mail do Responsável Técnico da Empresa" Variant="@variant">
+                        <RadzenTextBox Name="Email" @bind-Value="@Input.ResponsavelTecnicoEmail" />
+                        <RadzenRequiredValidator Component="Email" Text="E-mail é obrigatório" Popup=@popup Style="position: relative" />
+                        <RadzenEmailValidator Component="Email" Text="Informe um e-mail válido" Popup=@popup Style="position: relative" />
+                    </RadzenFormField>
+
+                    <RadzenFormField Text="Telefone do Responsável Técnico da Empresa" Variant="@variant">
+                        <RadzenMask Mask="(**) *****-****" CharacterPattern="[0-9]" Placeholder="(00) 00000-0000" Name="ResponsavelTecnicoTelefone" @bind-Value="Input.ResponsavelTecnicoTelefone" />
+                        <RadzenRequiredValidator Component="ResponsavelTecnicoTelefone" Text="Telefone do responsável técnico é obrigatório" Popup=@popup Style="position: relative" />
+                    </RadzenFormField>
+                </RadzenStack>
+            </RadzenColumn>
+
+        </RadzenRow>
+        <RadzenRow AlignItems="AlignItems.Center" class="rz-mt-4">
+            <RadzenColumn Size="12" Offset="0" SizeMD="8" OffsetMD="4">
+                <RadzenButton ButtonType="ButtonType.Submit" Text="@rotuloBotaoGravar"></RadzenButton>
+            </RadzenColumn>
+        </RadzenRow>
+    </RadzenTemplateForm>
+
+
+    <!-- Seção para envio de anexos -->
+    @if (_projeto != null && _candidato != null && _documentosModel != null)
+    {
+        <h4 class="mt-4">Envio de Anexos</h4>
+        <div class="table-responsive">
+            <table class="table table-bordered">
+                <thead>
+                    <tr>
+                        <th>Tipo de Arquivo</th>
+                        <th>Escolher o Arquivo</th>
+                        <th>Status</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    @foreach (var model in _documentosModel)
+                    {
+                        <tr>
+                            <td><strong>@model.TipoDocumento.Nome</strong></td>
+                            <td>
+                                <InputFile disabled="@UploadingLargeFile" OnChange="@((args) => OnLargeFileInputFileChange(args, _candidato, _projeto, model))" />
+                                @if ((listaTipoDocumentoLoading.Count > 0) && listaTipoDocumentoLoading.Where(x => x.TipoDocumento.Id == model.TipoDocumento.Id).First().Uploading)
+                                {
+                                    <progress style="height:50px;width:100%;" value="@UploadedBytes" max="@TotalBytes"></progress>
+                                }
+
+                            </td>
+                            <td>
+                                @if (model.Status)
+                                {
+                                    <i class="bi bi-check-all fs-5 text-success"></i>
+                                }
+                                else
+                                {
+                                    <i class="bi bi-x fs-5 text-danger"></i>
+                                }
+                            </td>
+                        </tr>
+                    }
+                </tbody>
+            </table>
+        </div>
+    }
+
+</div>
+
+
+
+
+
+
+@code {
+    bool popup;
+    Variant variant = Variant.Outlined;
+
+
+    bool Uploading = false;
+    bool UploadingLargeFile = false;
+    string LargeUploadMessage = "";
+    long UploadedBytes;
+    long TotalBytes;
+
+    async Task OnLargeFileInputFileChange(InputFileChangeEventArgs args, Candidato candidato, Projeto projeto, InputModelDocuments modelDocument)
+    {
+        Documento resultado;
+
+        // UploadedBytes = 0;
+
+        // Disable the file input field
+        //UploadingLargeFile = true;
+        var tipoDocumentoLoading = listaTipoDocumentoLoading.Where(x => x.TipoDocumento.Id == modelDocument.TipoDocumento.Id).First();
+        tipoDocumentoLoading.Uploading = true;
+
+        await InvokeAsync(StateHasChanged);
+
+        // calculate the chunks we have to send
+        TotalBytes = args.File.Size;
+        long percent = 0;
+        long chunkSize = 1000000;
+        long numChunks = TotalBytes / chunkSize;
+        long remainder = TotalBytes % chunkSize;
+
+        // get new filename with a bit of entropy
+        string justFileName = Path.GetFileNameWithoutExtension(args.File.Name);
+        string extension = Path.GetExtension(args.File.Name);
+        string newFileNameWithoutPath = $"Projeto_{projeto.Id}_{modelDocument.TipoDocumento.Nome}-{justFileName}-{DateTime.Now.Ticks.ToString()}{extension}";
+        //string projectPath = $"{Environment.CurrentDirectory}\\files\\{projeto.Id}";
+        string projectPath = projetoService.Path(projeto.Id);
+
+        string filename = $"{projectPath}\\{newFileNameWithoutPath}";
+
+        if (!Directory.Exists(projectPath))
+        {
+            Directory.CreateDirectory(projectPath);
+            GerarArquivoTextoParaProjeto(candidato, projeto, projectPath);
+        }
+
+        // Delete the file if it already exists in our \Files folder
+        if (File.Exists(filename))
+        {
+            File.Delete(filename);
+        }
+
+        // Open the input and output file streams
+        // using (var inStream = args.File.OpenReadStream(long.MaxValue))
+        // {
+        //     using (var outStream = File.OpenWrite(filename))
+        //     {
+        //         while (UploadedBytes < TotalBytes)
+        //         {
+        //             var whatsLeft = TotalBytes - UploadedBytes;
+        //             if (whatsLeft < chunkSize)
+        //                 chunkSize = remainder;
+        //             // Read the next chunk
+        //             var bytes = new byte[chunkSize];
+        //             var buffer = new Memory<byte>(bytes);
+        //             var read = await inStream.ReadAsync(buffer);
+        //             // Write it
+        //             await outStream.WriteAsync(bytes, 0, read);
+        //             // Update our progress data and UI
+        //             UploadedBytes += read;
+        //             percent = UploadedBytes * 100 / TotalBytes;
+        //             // Report progress with a string
+        //             LargeUploadMessage = $"Uploading {args.File.Name} {percent}%";
+        //             await InvokeAsync(StateHasChanged);
+        //         }
+        //     }
+        // }
+
+        var file = args.File;
+        var buffer = new byte[1 * 1024 * 1024]; // 80 KB buffer size 1 * 1024 * 1024
+        var totalRead = 0L;
+
+        using (var inStream = file.OpenReadStream(long.MaxValue))
+        using (var outStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))
+        {
+            while (totalRead < file.Size)
+            {
+                var read = await inStream.ReadAsync(buffer, 0, buffer.Length);
+                if (read == 0)
+                    break;
+
+                await outStream.WriteAsync(buffer, 0, read);
+                totalRead += read;
+
+                // Atualize o progresso se necessário
+                percent = (int)((totalRead * 100) / file.Size);
+                LargeUploadMessage = $"Uploading {args.File.Name} {percent}%";
+                Console.WriteLine($"Uploading {file.Name} {percent}%");
+            }
+        }
+
+
+        LargeUploadMessage = "Upload Completo.";
+        //await ListFiles();
+
+        Documento documentoGravado = new()
+            {
+                Descricao = "",
+                ArquivoNomeOriginal = newFileNameWithoutPath,
+                ArquivoTamanhoBytes = TotalBytes,
+                ProjetoId = projeto.Id,
+                TipoDocumentoId = modelDocument.TipoDocumento.Id,
+                UploadCompleto = true
+
+            };
+
+
+        if (documentoGravado.Id > 0)  // Alteração
+        {
+            documentoGravado.AtribuiId(modelDocument.DocumentoId);
+        }
+
+        resultado = documentoService.Gravar(documentoGravado);
+
+        //UploadingLargeFile = false;
+        tipoDocumentoLoading.Uploading = false;
+
+        bool uploadIncompletosAntes = _documentosModel.Any(x => !x.Status);
+
+        AtualizarListaDocumentos();
+
+        bool uploadIncompletosDepois = _documentosModel.Any(x => !x.Status);
+
+        if (uploadIncompletosAntes && !uploadIncompletosDepois)
+        {
+            //"Seu projeto foi enviado com sucesso.Caso deseje realizar alguma alteração, o projeto estará listado na área 'meus projetos'"
+
+            await dialogService.Alert("Seu projeto foi enviado com sucesso. <br />Caso deseje realizar alguma alteração, o projeto estará listado na área 'Meus Projetos'.",
+                                        "Projeto Enviado",
+                                        new AlertOptions() { OkButtonText = "Ok" });
+
+            Navigation.NavigateTo($"/gestaoprojetos");
+
+            return;
+        }
+
+        if (!uploadIncompletosAntes)
+        {
+            // "Deseja alterar mais algum anexo enviado?
+            // sim => permanece na tela
+            // não => exibe mensagem anterior "primeira vez que ele completa."
+
+            bool? result = await dialogService.Confirm("Deseja alterar mais algum anexo enviado?",
+                                        "Anexo Enviado com Sucesso",
+                                        new ConfirmOptions() { OkButtonText = "Yes", CancelButtonText = "No" });
+
+            if (result != true)
+            {
+                await dialogService.Alert("Seu projeto foi enviado com sucesso.</p>Caso deseje realizar alguma alteração, o projeto estará listado na área 'Meus Projetos'",
+                                            "Projeto Enviado",
+                                            new AlertOptions() { OkButtonText = "Ok" });
+
+                Navigation.NavigateTo($"/gestaoprojetos");
+
+                return;
+            }
+
+            return;
+        }
+
+    }
+
+    private void GerarArquivoTextoParaProjeto(Candidato candidato, Projeto projeto, string path)
+    {
+        string saudacao = $@"
+        Candidado:
+            Nome......: {candidato.NomeCompleto}
+            E-mail....: {candidato.Email}
+            Telefone..: {candidato.Email}
+        ";
+
+        if (candidato.TipoPessoa)  // Representa empresa
+        {
+            saudacao += $@"
+            Empresa:
+                Nome....: {candidato.EmpresaRazaoSocial}
+                E-mail..: {candidato.EmpresaEmail}
+                Telefone..: {candidato.EmpresaTelefone}";
+        }
+
+        saudacao += $@"
+
+        Projeto '{projeto.Nome}':
+            Responsável.....: {projeto.ResponsavelTecnicoNomeCompleto}
+            E-mail...: {projeto.ResponsavelTecnicoEmail}
+            Telefone.: {projeto.ResponsavelTecnicoTelefone}";
+
+
+        string fullPath = Path.Combine(path, "config.txt");
+
+        File.WriteAllText(fullPath, saudacao);
+    }
+
+
+
+    [Parameter]
+    public Guid projetoCodigo { get; set; }
+
+    private Candidato? _candidato;
+    private Projeto? _projeto;
+    private IEnumerable<Documento>? _documentos;
+    private IEnumerable<InputModelDocuments>? _documentosModel;
+    private string _mensagem = "Loading...";
+    private long candidatoId;
+    private string rotuloBotaoGravar = "Enviar";
+
+    //private long projetoId = 5;
+    List<ModelTipoDocumento> listaTipoDocumentoLoading = new();
+
+
+
+    [SupplyParameterFromForm]
+    private InputModel Input { get; set; } = new();
+
+    private List<int> listaDeUnidades = Enumerable.Range(2, 31).ToList();
+
+    protected override async Task OnInitializedAsync()
+    {
+        var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
+
+        var user = authState.User;
+
+        if (user.Identity.IsAuthenticated)
+        {
+            var identityUser = await UserManager.GetUserAsync(user);
+
+            if (identityUser != null)
+            {
+                _candidato = candidatoService.ObterPorUserID(identityUser.Id);
+            }
+        }
+
+        if (projetoCodigo != Guid.Empty)
+        {
+            _projeto = projetoService.ObterPorCodigo(projetoCodigo);
+            _documentos = documentoService.Listar(_projeto.Id);
+            AtualizarModel(_projeto);
+            rotuloBotaoGravar = "Alterar Dados do Projeto Cadastrado";
+        }
+
+        AtualizarListaDocumentos();
+
+
+
+        var listaTipo = tipoDocumentoServico.Listar();
+        foreach (var tipo in listaTipo)
+            listaTipoDocumentoLoading.Add(new ModelTipoDocumento { TipoDocumento = tipo, Uploading = false });
+
+    }
+
+    private void AtualizarModel(Projeto projeto)
+    {
+        Input.Id = projeto.Id;
+        Input.Nome = projeto.Nome;
+        Input.NumeroUnidades = projeto.NumeroUnidades;
+        Input.ResponsavelTecnicoCpf = projeto.ResponsavelTecnicoCpf;
+        Input.ResponsavelTecnicoNomeCompleto = projeto.ResponsavelTecnicoNomeCompleto;
+        Input.ResponsavelTecnicoTelefone = projeto.ResponsavelTecnicoTelefone;
+        Input.ResponsavelTecnicoEmail = projeto.ResponsavelTecnicoEmail;
+    }
+
+    private async Task OnSubmit(InputModel model)
+    {
+        Projeto resultado;
+
+        Projeto projeto = new(_candidato.Id)
+            {
+                Codigo = Guid.NewGuid(),
+                Nome = Input.Nome,
+                NumeroUnidades = Input.NumeroUnidades,
+                ResponsavelTecnicoCpf = Input.ResponsavelTecnicoCpf.Replace(".", "").Replace("-", ""),
+                ResponsavelTecnicoNomeCompleto = Input.ResponsavelTecnicoNomeCompleto,
+                ResponsavelTecnicoTelefone = Input.ResponsavelTecnicoTelefone,
+                ResponsavelTecnicoEmail = Input.ResponsavelTecnicoEmail
+            };
+
+        if (_projeto != null)  // Alteração
+        {
+            projeto.AtribuiId(_projeto.Id);
+
+            resultado = projetoService.Alterar(projeto);
+        }
+        else // Inclusão
+        {
+            resultado = projetoService.Adicionar(projeto);
+
+            rotuloBotaoGravar = "Alterar Dados do Projeto Cadastrado";
+        }
+
+        if (resultado != null)
+        {
+            _projeto = resultado;
+            projetoCodigo = resultado.Codigo;
+
+            MontarModelDocuments();
+
+            NotificationMessage message = new NotificationMessage
+                {
+                    Severity = NotificationSeverity.Info,
+                    Summary = "Projeto gravado com sucesso.",
+                    Detail = "",
+                    Duration = 3000
+                };
+
+            notificationService.Notify(message);
+
+        }
+
+        StateHasChanged();
+    }
+
+    private async void OnInvalidSubmit(FormInvalidSubmitEventArgs args)
+    {
+        //Log("InvalidSubmit", JsonSerializer.Serialize(args, new JsonSerializerOptions() { WriteIndented = true }));
+    }
+
+    private void AtualizarListaDocumentos()
+    {
+        if (_projeto == null || _projeto.Id <= 0)
+            return;
+
+        _documentos = documentoService.Listar(_projeto.Id);
+
+        MontarModelDocuments();
+
+        StateHasChanged();
+    }
+
+    private void MontarModelDocuments()
+    {
+        List<InputModelDocuments> resultado = new();
+
+        var listaTipo = tipoDocumentoServico.Listar();
+
+        foreach (TipoDocumento tipo in listaTipo)
+        {
+            long documentoId = 0;
+            bool status = false;
+
+            if (_documentos != null && _documentos.Count() > 0)
+            {
+                var ProjetoPossuiDocumento = _documentos.Where(d => d.TipoDocumentoId == tipo.Id).SingleOrDefault();
+
+                if (ProjetoPossuiDocumento != null)
+                {
+                    documentoId = ProjetoPossuiDocumento.Id;
+                    status = true;
+                }
+            }
+
+            resultado.Add(new InputModelDocuments
+                {
+                    DocumentoId = documentoId,
+                    TipoDocumento = tipo,
+                    Status = status
+                });
+        }
+
+        _documentosModel = resultado;
+    }
+
+
+    private sealed class InputModel
+    {
+        public long Id { get; set; }
+
+
+        [Required]
+        [StringLength(100, MinimumLength = 5)]
+        [Display(Name = "Nome do Projeto")]
+        public string Nome { get; set; } = "";
+
+        [Required]
+        [Range(2, 32, ErrorMessage = "O valor deve estar entre 2 e 32.")]
+        [Display(Name = "Número de Unidades Habitacionais por Pavimento")]
+        public int NumeroUnidades { get; set; } = 2;
+
+        [Required]
+        [MaxLength(100)]
+        [Display(Name = "Nome do Responsável Técnico da Empresa")]
+        public string ResponsavelTecnicoNomeCompleto { get; set; }
+
+        [Required]
+        [MaxLength(100)]
+        [EmailAddress]
+        [Display(Name = "E-mail do Responsável Técnico da Empresa")]
+        public string ResponsavelTecnicoEmail { get; set; }
+
+        [Required]
+        [MaxLength(14)]
+        [Display(Name = "CPF do Responsável Técnico da Empresa")]
+        public string ResponsavelTecnicoCpf { get; set; }
+
+        [Required]
+        [MaxLength(20)]
+        [Display(Name = "Telefone do Responsável Técnico da Empresa")]
+        public string ResponsavelTecnicoTelefone { get; set; }
+
+    }
+
+
+    private sealed class InputModelDocuments
+    {
+        public long DocumentoId { get; set; }
+
+        public TipoDocumento TipoDocumento { get; set; }
+
+        //public DateTime DataInclusao { get; set; }
+
+        public bool Status { get; set; }
+    }
+
+
+    private sealed class ModelTipoDocumento
+    {
+        public TipoDocumento TipoDocumento { get; set; }
+
+        public bool Uploading { get; set; }
+    }
+
+
+
+}

BIN
ConcursoProjetos/Files/1/Projeto_1_Projeto Arquitetônico-gInk_v1.1.1-638700227950071594.zip


+ 0 - 15
ConcursoProjetos/Files/1/config.txt

@@ -1,15 +0,0 @@
-
-        Candidado:
-            Nome......: cesarsoft@gmail.com
-            E-mail....: cesarsoft@gmail.com
-            Telefone..: cesarsoft@gmail.com
-        
-            Empresa:
-                Nome....: cesarsoft@gmail.com
-                E-mail..: cesarsoft@gmail.com
-                Telefone..: 234234324
-
-        Projeto 'Projeto Novo juliocesar':
-            Responsável.....: Joao Batista
-            E-mail...: soasoftware@yahoo.com.br
-            Telefone.: jsjdflkdsa

BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto Arquitetônico-gInk_v1.2.0-638700325428107583.zip


BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto Elétrico-gInk_v1.1.1-638700325476201903.zip


BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto Estrutural e Fundação-gInk_v1.1.1-638700337905136736.zip


BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto Hidrossanitário-gInk_v1.1.1-638700338305715479.zip


BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto Hidrossanitário-gInk_v1.2.0-638700337869966693.zip


BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto de Implantação de 8 Blocos-gInk_v1.1.1-638700337814057237.zip


BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto de Implantação de 8 Blocos-gInk_v1.1.1-638700338379629107.zip


BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto de Implantação de Esgoto Sanitário-gInk_v1.1.1-638700338115312542.zip


BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto de Implantação de Água Fria-gInk_v1.2.0-638700337977728643.zip


BIN
ConcursoProjetos/Files/2/Projeto_2_Projeto de Telecomunicação-gInk_v1.2.0-638700338159258750.zip


+ 0 - 15
ConcursoProjetos/Files/2/config.txt

@@ -1,15 +0,0 @@
-
-        Candidado:
-            Nome......: Julio Cesar de Carvalho
-            E-mail....: cesarsoft@gmail.com
-            Telefone..: cesarsoft@gmail.com
-        
-            Empresa:
-                Nome....: razao
-                E-mail..: mail@com.br
-                Telefone..: 4234324
-
-        Projeto 'Projeto Novo juliocesar':
-            Responsável.....: Joao Batista
-            E-mail...: soasoftware@yahoo.com.br
-            Telefone.: jsjdflkdsa

BIN
ConcursoProjetos/Files/3/Projeto_3_Projeto Elétrico-gInk_v1.1.1-638700326217756212.zip


BIN
ConcursoProjetos/Files/3/Projeto_3_Projeto de Implantação de 8 Blocos-gInk_v1.2.0-638700326178150023.zip


+ 0 - 15
ConcursoProjetos/Files/3/config.txt

@@ -1,15 +0,0 @@
-
-        Candidado:
-            Nome......: Julio Cesar de Carvalho
-            E-mail....: cesarsoft@gmail.com
-            Telefone..: cesarsoft@gmail.com
-        
-            Empresa:
-                Nome....: razao
-                E-mail..: mail@com.br
-                Telefone..: 4234324
-
-        Projeto 'Projeto Nteste':
-            Responsável.....: Joao Batista
-            E-mail...: soasoftware@yahoo.com.br
-            Telefone.: jsjdflkdsa

+ 21 - 10
ConcursoProjetos/wwwroot/js/app.js

@@ -1,19 +1,30 @@
 
-function divShow() {
+window.mascarasRegistro = () => {
 
+    // Máscaras do Titular
+    var CPF = IMask(document.getElementById('CPF'), { mask: '000.000.000-00' });
+
+
+    /*
+    var DataNascimento = IMask(document.getElementById('DataNascimento'), { mask: '00/00/0000' });
+    var NIS = IMask(document.getElementById('NIS'), { mask: '000.00000.00-0' });
+    var Telefone = IMask(document.getElementById('Telefone'), { mask: '(00) 00000-0000' });
+
+    // Máscaras do Cônjuge
+    var ConjugeCPF = IMask(document.getElementById('ConjugeCPF'), { mask: '000.000.000-00' });
+    var ConjugeDataNascimento = IMask(document.getElementById('ConjugeDataNascimento'), { mask: '00/00/0000' });
+    //var ConjugeNIS = IMask(document.getElementById('ConjugeNIS'), { mask: '000.00000.00-0' });
+    var ConjugeTelefone = IMask(document.getElementById('ConjugeTelefone'), { mask: '(00) 00000-0000' });
 
-    debugger;
+    // Máscaras do Dependente
+    var DependenteCPF = IMask(document.getElementById('DependenteCPF'), { mask: '000.000.000-00' });
+    var DependenteDataNascimento = IMask(document.getElementById('DependenteDataNascimento'), { mask: '00/00/0000' });
+    var CEP = IMask(document.getElementById('EnderecoCEP'), { mask: '00000-000' });
+    */
 
 
-    value = true;
+};
 
-    var element = document.getElementById('div-show');
-    if (value) {
-        element.style.display = 'block';
-    } else {
-        element.style.display = 'none';
-    }
-}
 
 
 window.mascaras = () => {