PageProjeto.razor 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. @page "/pageprojeto/{projetoId:long}"
  2. @attribute [Authorize]
  3. @rendermode InteractiveServer
  4. @using System.ComponentModel.DataAnnotations
  5. @using System.Text
  6. @using System.Text.Encodings.Web
  7. @using ConcursoProjetos.Service
  8. @using Microsoft.AspNetCore.Identity
  9. @using Microsoft.AspNetCore.WebUtilities
  10. @inject UserManager<ApplicationUser> UserManager
  11. @inject AuthenticationStateProvider AuthenticationStateProvider
  12. @inject ICandidatoService candidatoService
  13. @inject IProjetoService projetoService
  14. @inject IDocumentoService documentoService
  15. @inject ITipoDocumentoService tipoDocumentoServico
  16. <PageTitle>Cadastro de Projeto</PageTitle>
  17. <div class="container mt-5">
  18. <h2>Cadastro de Projeto</h2>
  19. <EditForm Model="Input" OnValidSubmit="RegisterProjeto" FormName="register">
  20. <!-- Campos principais em duas colunas -->
  21. <div class="row">
  22. <div class="col-md-6">
  23. <div class="mb-3">
  24. <label for="nomeProjeto" class="form-label"><strong>Nome do Projeto</strong></label>
  25. <InputText @bind-Value="Input.Nome" id="nomeProjeto" class="form-control" autocomplete="username" aria-required="true" placeholder="Digite o nome do projeto" />
  26. </div>
  27. <div class="mb-3">
  28. <label for="responsavelTecnico" class="form-label"><strong>Nome do Responsável Técnico da Empresa</strong></label>
  29. <InputText @bind-Value="Input.ResponsavelTecnicoNomeCompleto" id="ResponsavelTecnicoNomeCompleto" class="form-control" autocomplete="username" aria-required="true" placeholder="Digite o nome do responsável técnico" />
  30. </div>
  31. <div class="mb-3">
  32. <label for="cpf" class="form-label"><strong>CPF do Responsável Técnico da Empresa</strong></label>
  33. <InputText @bind-Value="Input.ResponsavelTecnicoCpf" id="ResponsavelTecnicoCpf" class="form-control" autocomplete="username" aria-required="true" placeholder="Digite o CPF" />
  34. </div>
  35. </div>
  36. <div class="col-md-6">
  37. <div class="mb-3">
  38. <label for="numUnidades" class="form-label"><strong>Número de Unidades Habitacionais por Pavimento</strong></label>
  39. <InputSelect @bind-Value="Input.NumeroUnidades" class="form-control">
  40. @foreach (var unidades in listaDeUnidades)
  41. {
  42. <option value="@unidades">@unidades</option>
  43. }
  44. </InputSelect>
  45. </div>
  46. <div class="mb-3">
  47. <label for="email" class="form-label"><strong>E-mail do Responsável Técnico da Empresa</strong></label>
  48. <InputText @bind-Value="Input.ResponsavelTecnicoEmail" id="ResponsavelTecnicoEmail" class="form-control" autocomplete="username" aria-required="true" placeholder="Digite o e-mail" />
  49. </div>
  50. <div class="mb-3">
  51. <label for="telefone" class="form-label"><strong>Telefone do Responsável Técnico da Empresa</strong></label>
  52. <InputText @bind-Value="Input.ResponsavelTecnicoTelefone" id="ResponsavelTecnicoTelefone" class="form-control" autocomplete="username" aria-required="true" placeholder="Digite o telefone" />
  53. </div>
  54. </div>
  55. </div>
  56. <button type="submit" class="btn btn-primary">Enviar</button>
  57. </EditForm>
  58. @* <InputFile disabled="@UploadingLargeFile" OnChange="OnLargeFileInputFileChange" />
  59. <div>@LargeUploadMessage</div>
  60. @if (UploadingLargeFile)
  61. {
  62. <progress style="height:50px;width:100%;" value="@UploadedBytes" max="@TotalBytes"></progress>
  63. }
  64. *@
  65. <!-- Seção para envio de anexos -->
  66. @if (_projeto != null && _candidato != null && _documentosModel != null)
  67. {
  68. <h4 class="mt-4">Envio de Anexos</h4>
  69. <div class="table-responsive">
  70. <table class="table table-bordered">
  71. <thead>
  72. <tr>
  73. <th>Tipo de Arquivo</th>
  74. <th>Escolher o Arquivo</th>
  75. <th>Status</th>
  76. </tr>
  77. </thead>
  78. <tbody>
  79. @foreach (var model in _documentosModel)
  80. {
  81. <tr>
  82. <td><strong>@model.TipoDocumento.Nome</strong></td>
  83. <td>
  84. <InputFile disabled="@UploadingLargeFile" OnChange="@((args) => OnLargeFileInputFileChange(args, _candidato, _projeto, model))" />
  85. @if ((listaTipoDocumentoLoading.Count > 0) && listaTipoDocumentoLoading.Where(x => x.TipoDocumento.Id == model.TipoDocumento.Id).First().Uploading)
  86. {
  87. <progress style="height:50px;width:100%;" value="@UploadedBytes" max="@TotalBytes"></progress>
  88. }
  89. </td>
  90. <td>
  91. @if (model.Status)
  92. {
  93. <i class="bi bi-check-all fs-5 text-success"></i>
  94. }
  95. else
  96. {
  97. <i class="bi bi-x fs-5 text-danger"></i>
  98. }
  99. </td>
  100. </tr>
  101. }
  102. </tbody>
  103. </table>
  104. </div>
  105. }
  106. </div>
  107. @code {
  108. bool Uploading = false;
  109. bool UploadingLargeFile = false;
  110. string LargeUploadMessage = "";
  111. long UploadedBytes;
  112. long TotalBytes;
  113. /// <summary>
  114. /// Occurs when a large file is selected or dropped
  115. /// </summary>
  116. /// <param name="args"></param>
  117. /// <returns></returns>
  118. async Task OnLargeFileInputFileChange(InputFileChangeEventArgs args, Candidato candidato, Projeto projeto, InputModelDocuments modelDocument)
  119. {
  120. Documento resultado;
  121. UploadedBytes = 0;
  122. // Disable the file input field
  123. //UploadingLargeFile = true;
  124. var tipoDocumentoLoading = listaTipoDocumentoLoading.Where(x => x.TipoDocumento.Id == modelDocument.TipoDocumento.Id).First();
  125. tipoDocumentoLoading.Uploading = true;
  126. await InvokeAsync(StateHasChanged);
  127. // calculate the chunks we have to send
  128. TotalBytes = args.File.Size;
  129. long percent = 0;
  130. long chunkSize = 400000;
  131. long numChunks = TotalBytes / chunkSize;
  132. long remainder = TotalBytes % chunkSize;
  133. // get new filename with a bit of entropy
  134. string justFileName = Path.GetFileNameWithoutExtension(args.File.Name);
  135. string extension = Path.GetExtension(args.File.Name);
  136. string newFileNameWithoutPath = $"Projeto_{projeto.Id}_{modelDocument.TipoDocumento.Nome}-{justFileName}-{DateTime.Now.Ticks.ToString()}{extension}";
  137. string projectPath = $"{Environment.CurrentDirectory}\\files\\{projeto.Id}";
  138. string filename = $"{projectPath}\\{newFileNameWithoutPath}";
  139. if (!Directory.Exists(projectPath))
  140. {
  141. Directory.CreateDirectory(projectPath);
  142. }
  143. // Delete the file if it already exists in our \Files folder
  144. if (File.Exists(filename))
  145. {
  146. File.Delete(filename);
  147. }
  148. // Open the input and output file streams
  149. using (var inStream = args.File.OpenReadStream(long.MaxValue))
  150. {
  151. using (var outStream = File.OpenWrite(filename))
  152. {
  153. while (UploadedBytes < TotalBytes)
  154. {
  155. var whatsLeft = TotalBytes - UploadedBytes;
  156. if (whatsLeft < chunkSize)
  157. chunkSize = remainder;
  158. // Read the next chunk
  159. var bytes = new byte[chunkSize];
  160. var buffer = new Memory<byte>(bytes);
  161. var read = await inStream.ReadAsync(buffer);
  162. // Write it
  163. await outStream.WriteAsync(bytes, 0, read);
  164. // Update our progress data and UI
  165. UploadedBytes += read;
  166. percent = UploadedBytes * 100 / TotalBytes;
  167. // Report progress with a string
  168. LargeUploadMessage = $"Uploading {args.File.Name} {percent}%";
  169. await InvokeAsync(StateHasChanged);
  170. }
  171. }
  172. }
  173. LargeUploadMessage = "Upload Complete.";
  174. //await ListFiles();
  175. Documento documentoGravado = new()
  176. {
  177. Descricao = "",
  178. ArquivoNomeOriginal = newFileNameWithoutPath,
  179. ArquivoTamanhoBytes = TotalBytes,
  180. ProjetoId = projeto.Id,
  181. TipoDocumentoId = modelDocument.TipoDocumento.Id,
  182. UploadCompleto = true
  183. };
  184. if (documentoGravado.Id > 0) // Alteração
  185. {
  186. documentoGravado.AtribuiId(modelDocument.DocumentoId);
  187. }
  188. resultado = documentoService.Gravar(documentoGravado);
  189. //UploadingLargeFile = false;
  190. tipoDocumentoLoading.Uploading = false;
  191. AtualizarListaDocumentos();
  192. }
  193. [Parameter] public long projetoId { get; set; }
  194. private Candidato? _candidato;
  195. private Projeto? _projeto;
  196. private IEnumerable<Documento>? _documentos;
  197. private IEnumerable<InputModelDocuments>? _documentosModel;
  198. private string _mensagem = "Loading...";
  199. private long candidatoId;
  200. //private long projetoId = 5;
  201. List<ModelTipoDocumento> listaTipoDocumentoLoading = new();
  202. [SupplyParameterFromForm]
  203. private InputModel Input { get; set; } = new();
  204. private List<int> listaDeUnidades = Enumerable.Range(2, 31).ToList();
  205. protected override async Task OnInitializedAsync()
  206. {
  207. var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
  208. var user = authState.User;
  209. if (user.Identity.IsAuthenticated)
  210. {
  211. var identityUser = await UserManager.GetUserAsync(user);
  212. if (identityUser != null)
  213. {
  214. _candidato = candidatoService.ObterPorUserID(identityUser.Id);
  215. }
  216. }
  217. if (projetoId != null && projetoId > 0)
  218. {
  219. _projeto = projetoService.ObterPorId(projetoId);
  220. _documentos = documentoService.Listar(_projeto.Id);
  221. AtualizarModel(_projeto);
  222. }
  223. AtualizarListaDocumentos();
  224. var listaTipo = tipoDocumentoServico.Listar();
  225. foreach (var tipo in listaTipo)
  226. listaTipoDocumentoLoading.Add(new ModelTipoDocumento { TipoDocumento = tipo, Uploading = false });
  227. }
  228. private void AtualizarModel(Projeto projeto)
  229. {
  230. Input.Id = projeto.Id;
  231. Input.Nome = projeto.Nome;
  232. Input.NumeroUnidades = projeto.NumeroUnidades;
  233. Input.ResponsavelTecnicoCpf = projeto.ResponsavelTecnicoCpf;
  234. Input.ResponsavelTecnicoNomeCompleto = projeto.ResponsavelTecnicoNomeCompleto;
  235. Input.ResponsavelTecnicoTelefone = projeto.ResponsavelTecnicoTelefone;
  236. Input.ResponsavelTecnicoEmail = projeto.ResponsavelTecnicoEmail;
  237. }
  238. public async Task RegisterProjeto(EditContext editContext)
  239. {
  240. Projeto resultado;
  241. Projeto projeto = new(_candidato.Id)
  242. {
  243. Nome = Input.Nome,
  244. NumeroUnidades = Input.NumeroUnidades,
  245. ResponsavelTecnicoCpf = Input.ResponsavelTecnicoCpf,
  246. ResponsavelTecnicoNomeCompleto = Input.ResponsavelTecnicoNomeCompleto,
  247. ResponsavelTecnicoTelefone = Input.ResponsavelTecnicoTelefone,
  248. ResponsavelTecnicoEmail = Input.ResponsavelTecnicoEmail
  249. };
  250. if (_projeto != null) // Alteração
  251. {
  252. projeto.AtribuiId(_projeto.Id);
  253. resultado = projetoService.Alterar(projeto);
  254. }
  255. else // Inclusão
  256. {
  257. resultado = projetoService.Adicionar(projeto);
  258. }
  259. if (resultado != null)
  260. {
  261. _projeto = resultado;
  262. projetoId = resultado.Id;
  263. MontarModelDocuments();
  264. }
  265. StateHasChanged();
  266. }
  267. private void AtualizarListaDocumentos()
  268. {
  269. if (_projeto == null || _projeto.Id <= 0)
  270. return;
  271. _documentos = documentoService.Listar(_projeto.Id);
  272. MontarModelDocuments();
  273. StateHasChanged();
  274. }
  275. private void MontarModelDocuments()
  276. {
  277. List<InputModelDocuments> resultado = new();
  278. var listaTipo = tipoDocumentoServico.Listar();
  279. foreach (TipoDocumento tipo in listaTipo)
  280. {
  281. long documentoId = 0;
  282. bool status = false;
  283. if (_documentos != null && _documentos.Count() > 0)
  284. {
  285. var ProjetoPossuiDocumento = _documentos.Where(d => d.TipoDocumentoId == tipo.Id).SingleOrDefault();
  286. if (ProjetoPossuiDocumento != null)
  287. {
  288. documentoId = ProjetoPossuiDocumento.Id;
  289. status = true;
  290. }
  291. }
  292. resultado.Add(new InputModelDocuments
  293. {
  294. DocumentoId = documentoId,
  295. TipoDocumento = tipo,
  296. Status = status
  297. });
  298. }
  299. _documentosModel = resultado;
  300. }
  301. private sealed class InputModel
  302. {
  303. public long Id { get; set; }
  304. [Required]
  305. [StringLength(100, MinimumLength = 5)]
  306. [Display(Name = "Nome do Projeto")]
  307. public string Nome { get; set; } = "";
  308. [Required]
  309. [Range(2, 32, ErrorMessage = "O valor deve estar entre 2 e 32.")]
  310. [Display(Name = "Número de Unidades Habitacionais por Pavimento")]
  311. public int NumeroUnidades { get; set; } = 2;
  312. [Required]
  313. [MaxLength(100)]
  314. [Display(Name = "Nome do Responsável Técnico da Empresa")]
  315. public string ResponsavelTecnicoNomeCompleto { get; set; }
  316. [Required]
  317. [MaxLength(100)]
  318. [EmailAddress]
  319. [Display(Name = "E-mail do Responsável Técnico da Empresa")]
  320. public string ResponsavelTecnicoEmail { get; set; }
  321. [Required]
  322. [MaxLength(14)]
  323. [Display(Name = "CPF do Responsável Técnico da Empresa")]
  324. public string ResponsavelTecnicoCpf { get; set; }
  325. [Required]
  326. [MaxLength(20)]
  327. [Display(Name = "Telefone do Responsável Técnico da Empresa")]
  328. public string ResponsavelTecnicoTelefone { get; set; }
  329. }
  330. private sealed class InputModelDocuments
  331. {
  332. public long DocumentoId { get; set; }
  333. public TipoDocumento TipoDocumento { get; set; }
  334. //public DateTime DataInclusao { get; set; }
  335. public bool Status { get; set; }
  336. }
  337. private sealed class ModelTipoDocumento
  338. {
  339. public TipoDocumento TipoDocumento { get; set; }
  340. public bool Uploading { get; set; }
  341. }
  342. }