diff --git a/.env.dev b/.env.dev index 6f05352e..51b1e4ee 100644 --- a/.env.dev +++ b/.env.dev @@ -4,7 +4,7 @@ export DATABASE_USER=postgres export DATABASE_PASS=postgres export DATABASE_HOST=127.0.0.1 -export DATABASE_NAME=postgres +export DATABASE_NAME=pescarte export DATABASE_PORT=54322 export DATABASE_URL=ecto://$DATABASE_USER:$DATABASE_PASS@$DATABASE_HOST:$DATABASE_PORT/$DATABASE_NAME diff --git a/assets/css/noticias.scss b/assets/css/noticias.scss index b8779238..175d30f6 100644 --- a/assets/css/noticias.scss +++ b/assets/css/noticias.scss @@ -1,11 +1,25 @@ .noticias-grid, - .noticia-wrapper { +.noticia-wrapper { max-width: 100vw !important; div { max-width: 100vw; } } +.landing-grid { + .news-container { + margin-top: -15%; + } +} + +@media (max-width: 768px) { + .landing-grid { + .news-container { + margin-top: -35%; + } + } +} + /* trocando gallery-carousel por land-carousel */ .land-carousel { margin-bottom: 70px; @@ -56,28 +70,28 @@ /* pegando o get-to-know do sobre e ajustando as notícias */ .get-to-know { display: flex; + flex-direction: column; align-items: center; justify-content: center; gap: 56px; - padding: 80px 40px; + padding: 10px 10px 60px 10px; img { object-fit: cover; height: 465px; - width: 50%; - max-width: 668px; + width: 75%; + max-width: 75%; border-radius: 16px; flex-shrink: 1; } .know-content { display: flex; flex-direction: column; - width: 50%; + width: 75%; gap: 25px; } @media (max-width: 768px) { .get-to-know { - flex-direction: column; align-items: center; justify-content: center; gap: 18px; @@ -103,17 +117,18 @@ justify-content: center; gap: 56px; padding: 80px 40px; + width: 75%; + margin: 0 auto; } .noticia-text { - display: flex; - flex-direction: column; - align-items: center; - width: 100%; - gap: 25px; + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + gap: 25px; } - /* Estilo para telas pequenas (móveis) */ @media (max-width: 768px) { .phases { @@ -122,6 +137,7 @@ justify-content: center; gap: 18px; padding: 40px 20px; + margin: 0; } .noticia-text { width: 100vw; @@ -158,7 +174,7 @@ } .noticia .noticia-descricao h2 { - color: #0064C8; + color: #0064c8; font-size: 32px; line-height: 38px; font-weight: 700; @@ -176,7 +192,7 @@ .noticia .noticia-descricao strong em { text-decoration: underline; - color: #0064C8; + color: #0064c8; font-weight: 400; font-style: normal; } @@ -187,11 +203,10 @@ margin-bottom: 40px; } - .noticia .noticia-descricao p a { font-weight: 700; line-height: 24px; - color: #0064C8; + color: #0064c8; } .noticia .noticia-descricao p a::after { @@ -218,3 +233,202 @@ padding: 40px; } } + +/* Estilização página de listagem de notícias */ +.news-container { + grid-area: news; + + h2 { + display: flex; + justify-content: center; + margin-top: 40px; + margin-bottom: 5rem; + } + + .news-cards { + @apply flex flex-wrap justify-center md:mt-10; + + .news-item { + @apply flex flex-col max-w-sm; + margin: 0 2.5rem 2.5rem 2.5rem; + width: 20.125rem; + gap: 6px; + + .text-container { + display: flex; + flex-direction: column; + gap: 6px; + + .news-date { + font-size: 12px; + font-weight: 400; + color: #66a2de; + line-height: 24px; + } + } + + img { + border-radius: 8px; + width: 100%; + height: auto; + object-fit: cover; + max-height: 238px; + } + + h2 { + display: flex; + justify-content: center; + } + + a.link { + display: flex; + align-items: center; + margin: auto 0 1.5rem 1.5rem; + + button { + gap: 1rem; + + p { + font-family: "Work Sans"; + font-size: 1rem; + font-style: normal; + font-weight: 500; + line-height: 1.125rem; + } + + svg { + width: 1.5rem; + height: 1.5rem; + } + } + } + } + } +} + +/* Estilização da notícia destaque na página */ +.main-new { + width: 90%; + display: flex; + justify-content: space-around; + align-items: flex-start; + margin: 0 auto; + + a { + width: 60%; + + img { + border-radius: 16px; + width: 90%; + max-height: 432px; + } + } + + .main-new-text-container { + width: 40%; + padding: 3rem 0; + display: flex; + flex-direction: column; + align-items: flex-start; + text-align: start; + + .news-date { + font-size: 14px; + font-weight: 400; + color: #66a2de; + line-height: 24px; + } + + a{ + width: 100%; + } + + .news-title { + font-size: 32px; + font-weight: 700; + line-height: 46px; + color: #0064c8; + } + + .news-description { + font-size: 14px; + font-weight: 400; + color: #101010; + line-height: 24px; + } + } +} + +@media (max-width: 768px) { + .main-new { + width: 100%; + flex-direction: column; + justify-content: center; + align-items: center; + + a { + width: 90%; + + img { + width: 100%; + min-height: 400px; + max-height: none; + } + } + + .main-new-text-container { + width: 80%; + } + } +} +/*Fim notícia destaque*/ + +/*Estilização searchbar*/ +.search-container { + width: 600px; + display: flex; + flex-direction: column; + margin: -1rem auto 2rem auto; + border-radius: 4px; + gap: 12px; + + input{ + width: inherit; + border: 1.5px solid #E7E7E7; + border-radius: 4px; + padding: 12px; + + ::placeholder{ + color: #E7E7E7; + } + } + .tags-container{ + display: flex; + gap: 12px; + justify-content: space-around; + align-items: center; + + li{ + color: #0064c8; + background-color: #F2F7FC; + padding: 6px 30px; + font-size: 16px; + border-radius: 4px; + cursor: pointer; + } + + .active{ + background-color: #0064c8; + color: #FFF; + } + + } + +} + +@media (max-width: 768px){ + .search-container{ + margin-top: 0px; + width: 328px; + } +} diff --git a/assets/package-lock.json b/assets/package-lock.json index 45fbb69f..c0b1c88d 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -25,21 +25,6 @@ "topbar": "^3.0.0" } }, - "../deps/phoenix": { - "version": "1.7.18", - "license": "MIT" - }, - "../deps/phoenix_html": { - "version": "4.1.0" - }, - "../deps/phoenix_live_view": { - "version": "0.20.17", - "license": "MIT", - "devDependencies": { - "@playwright/test": "^1.43.1", - "monocart-reporter": "^2.3.1" - } - }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -1367,16 +1352,18 @@ } }, "node_modules/phoenix": { - "resolved": "../deps/phoenix", - "link": true + "version": "1.7.18", + "resolved": "file:../deps/phoenix", + "license": "MIT" }, "node_modules/phoenix_html": { - "resolved": "../deps/phoenix_html", - "link": true + "version": "4.2.0", + "resolved": "file:../deps/phoenix_html" }, "node_modules/phoenix_live_view": { - "resolved": "../deps/phoenix_live_view", - "link": true + "version": "0.20.17", + "resolved": "file:../deps/phoenix_live_view", + "license": "MIT" }, "node_modules/picocolors": { "version": "1.0.0", diff --git a/docker-compose.yml b/docker-compose.yml index 50e8ee05..0c8530ed 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: "3.8" + services: pescarte: diff --git a/lib/pescarte/blog/blog.ex b/lib/pescarte/blog/blog.ex index b004bfab..f636c231 100644 --- a/lib/pescarte/blog/blog.ex +++ b/lib/pescarte/blog/blog.ex @@ -3,6 +3,7 @@ defmodule Pescarte.Blog do O contexto Blog é responsável por gerenciar as operações relacionadas a postagens e tags. """ import Ecto.Query + alias Pescarte.Blog.Entity.Tag alias Pescarte.Blog.Post alias Pescarte.Database.Repo @@ -15,7 +16,7 @@ defmodule Pescarte.Blog do optional(:page_size) => pos_integer() } - @spec list_posts_with_filter(filters()) :: {:ok, list(Post.t())} | {:error, term()} + @spec list_posts_with_filter(filters()) :: list(Post.t()) | {:error, term()} def list_posts_with_filter(filters \\ %{}) do Post |> apply_post_search_filter(filters) @@ -57,5 +58,5 @@ defmodule Pescarte.Blog do from p in query, limit: ^page_size, offset: ^offset end - defp apply_pagination(query, _), do: from(p in query, limit: 10, offset: 0) + defp apply_pagination(query, _), do: from(p in query, limit: 7, offset: 0) end diff --git a/lib/pescarte/blog/post.ex b/lib/pescarte/blog/post.ex index 677d4e9d..9a813d19 100644 --- a/lib/pescarte/blog/post.ex +++ b/lib/pescarte/blog/post.ex @@ -47,11 +47,6 @@ defmodule Pescarte.Blog.Post do |> foreign_key_constraint(:usuario_id) end - @spec get_posts :: list(Post.t()) | Ecto.QueryError - def get_posts do - Repo.Replica.all(Post) - end - @spec get_post(String.t()) :: {:ok, Post.t()} | {:error, :not_found} def get_post(id) do Database.fetch(Post, id) diff --git a/lib/pescarte_web/controllers/noticias_controller.ex b/lib/pescarte_web/controllers/noticias_controller.ex index e43323ba..73004be0 100644 --- a/lib/pescarte_web/controllers/noticias_controller.ex +++ b/lib/pescarte_web/controllers/noticias_controller.ex @@ -1,8 +1,17 @@ defmodule PescarteWeb.NoticiasController do use PescarteWeb, :controller + alias Pescarte.Blog def show(conn, _params) do current_path = conn.request_path - render(conn, :show, current_path: current_path, error_message: nil) + + [main_new | news] = Blog.list_posts_with_filter() + + render(conn, :show, + current_path: current_path, + error_message: nil, + news: news, + main_new: main_new + ) end end diff --git a/lib/pescarte_web/live/blog/noticias_live/show.ex b/lib/pescarte_web/live/blog/noticias_live/show.ex new file mode 100644 index 00000000..75c23b88 --- /dev/null +++ b/lib/pescarte_web/live/blog/noticias_live/show.ex @@ -0,0 +1,420 @@ +defmodule PescarteWeb.Blog.NoticiasLive.Show do + use PescarteWeb, :live_view + + alias Pescarte.Blog + + @notice_title_max_length Application.compile_env!(:pescarte, [ + PescarteWeb, + :notice_title_max_length + ]) + + @notice_desc_max_length Application.compile_env!(:pescarte, [ + PescarteWeb, + :notice_desc_max_length + ]) + @impl true + def mount(_params, _session, socket) do + [main_new | news] = Blog.list_posts_with_filter() + + socket = + socket + |> assign(%{error_message: nil, news: news, main_new: main_new}) + + {:ok, socket} + end + + def handle_notice_title_length(text) do + if String.length(text) > @notice_title_max_length do + text + |> truncate_text_until(@notice_title_max_length - 4) + |> put_ellipsis() + else + text + end + end + + def handle_notice_desc_length(text) do + if String.length(text) > @notice_desc_max_length do + text + |> truncate_text_until(@notice_desc_max_length - 4) + |> put_ellipsis() + else + text + end + end + + defp truncate_text_until(text, length) do + text + |> String.slice(0..length) + |> String.trim_trailing() + end + + defp put_ellipsis(text) do + text <> "..." + end + + def date_to_string(date_time) do + DateTime.to_date(date_time) + |> Date.to_string() + |> String.split("-") + |> Enum.reverse() + |> Enum.join("/") + end + + @impl true + def handle_event("more_news", _params, socket) do + current_news_length = socket.assigns.news.length + loaded_news = Blog.list_posts_with_filter(%{page: current_news_length + 1, page_size: 6}) + + IO.inspect("funcionou") + + socket = socket |> assign(news: socket.assigns.news ++ loaded_news) + + {:noreply, socket} + end + + @impl true + def handle_event("dialog", _value, socket) do + {:noreply, socket} + end + + @impl true + def render(assigns) do + ~H""" +
+ <.flash :if={@error_message} id="login-error" kind={:error}> + {@error_message} + + +
+
+ <.text size="h2" color="text-blue-100"> + Notícias + +
+
+ +
+ + +
+ +
+ + + +
+

{date_to_string(@main_new.inserted_at)}

+ +

+ {@main_new.titulo} +

+
+

+ {handle_notice_desc_length(@main_new.conteudo)} +

+
+
+ +
+
+
+ <%= for new <- @news do %> +
+ + + +
+

{date_to_string(new.inserted_at)}

+ + <.text size="h4" color="text-blue-100"> + {handle_notice_title_length(new.titulo)} + + + <.text size="base" color="text-black-60"> + {handle_notice_desc_length(new.conteudo)} + +
+
+ <% end %> + +
+
+
+ +
+ <.button style="primary"> + <.text size="base" color="text-wite-100">Ver mais... + +
+ + +
+ """ + end +end diff --git a/lib/pescarte_web/router.ex b/lib/pescarte_web/router.ex index 2725d75f..be300644 100644 --- a/lib/pescarte_web/router.ex +++ b/lib/pescarte_web/router.ex @@ -39,12 +39,12 @@ defmodule PescarteWeb.Router do get "/publicacoes", JournalController, :show get "/censo", CensoController, :show get "/confirmar", TokenController, :confirm - get "/noticias", NoticiasController, :show get "/pgtrs", PGTRSController, :show get "/pgtr", PGTRController, :show get "/naipa", NaipaController, :show get "/sedes", SedesController, :show get "/aplicativos", AplicativosController, :show + live "/noticias", Blog.NoticiasLive.Show delete "/acessar", LoginController, :delete diff --git a/lib/pescarte_web/templates/noticia_html/show.html.heex b/lib/pescarte_web/templates/noticia_html/show.html.heex new file mode 100644 index 00000000..613eb8aa --- /dev/null +++ b/lib/pescarte_web/templates/noticia_html/show.html.heex @@ -0,0 +1,63 @@ +
+
+
+ <.text size="h2" color="text-blue-100"> + Pescarte participa de plenária sudeste para a construção do Plano Nacional da Pesca Artesanal + +
+
+ +
+ +
+ <.text size="lg" color="text-black-80"> + Entre os dias 9 e 11 de outubro de 2024 o Projeto de Educação Ambiental Pescarte (PEA Pescarte) + participou da primeira Plenária Regional para a construção do Plano Nacional da Pesca Artesanal + (PNPA), em Vitória (ES). O evento foi realizado pelo Ministério da Pesca e Aquicultura (MPA) + e reuniu pescadores(as), pesquisadores(as), gestores públicos e grupos de apoio para, de forma + participativa, discutir e definir políticas públicas para o setor nos próximos 10 anos. + + <.text size="lg" color="text-black-80"> + Durante a plenária, os participantes abordaram sete eixos, com transversalidades de gênero, + juventude e étnico racial, que estruturam o PNPA: economia da sociobiodiversidade pesqueira + artesanal, diálogos de saberes artesanais, gestão e ordenamento, direito aos territórios, + cultura e identidade, saúde e assistência e emergências climáticas. + + <.text size="lg" color="text-black-80"> + No evento foram eleitos os 20 delegados que irão representar a Região Sudeste na Plenária + Nacional, marcada para junho de 2025, em Brasília. Angeline Lopes, pescadora da Praia do Siqueira, em Cabo Frio, e educadora socioambiental do Pescarte e Priscila Castro, educadora socioambiental do Pescarte, foram escolhidas como delegada e suplente da pesquisa, respectivamente. + + <.text size="lg" color="text-black-80"> + A articulação para a participação na plenária sudeste foi iniciada no mês de maio, durante o + Seminário Internacional da Pesca Artesanal, realizado pelo Pescarte, quando Natália Tavares, + representante do MPA, anunciou as atividades previstas para o segundo semestre. + + <.text size="lg" color="text-black-80"> + De acordo com Priscila Castro, supervisora do Núcleo de Autonomia e Incidência da Pesca + Artesanal (NAIPA), o Seminário da Pesca e o Encontro Regional, ocorrido em junho, foram + importantes para o diálogo com os integrantes do Pescarte. + + <.text size="lg" color="text-black-80"> + "Fizemos um caderno de propostas, que serviu como base para a nossa participação na plenária + sudeste, onde falamos sobre a realidade da pesca no âmbito do Pescarte. Nosso grupo contou com + 16 pessoas, entre pescadores(as) e pesquisadores, sendo 12 selecionadas pelo MPA e quatro da equipe de apoio do projeto", completou. + + <.text size="lg" color="text-black-80"> + Pescador em Arraial do Cabo e integrante do Pescarte há 10 anos, José Antônio Freitas destaca que + sua participação na plenária foi a oportunidade de relatar sobre a sua vivência e os desafios que + enfrenta para exercer a atividade. + + <.text size="lg" color="text-black-80"> + "Esse momento foi muito esperado. Tivemos a oportunidade de mostrar para o poder público a nossa + realidade, falando sobre as necessidades, conflitos que enfrentamos, como a perda de território + pesqueiro. O Plano Nacional da Pesca Artesanal vai nos auxiliar de forma positiva, porque tivemos uma oportunidade única de mostrar o que conhecemos e ajudar a criar políticas públicas que nos beneficiem", pontuou. + + <.text size="lg" color="text-black-80"> + Com o encerramento da Plenária Sudeste, o PNPA segue para a Região Centro-Oeste, com plenária + marcada para 30, 31 de outubro e 01 novembro em Campo Grande (MS). O Ministério da Pesca e Aquicultura pretende consolidar o compromisso do Estado com a pesca artesanal por meio de políticas públicas que serão acompanhadas e cobradas pelos próprios pescadores e pescadoras artesanais. + +
+
+ + +
diff --git a/lib/pescarte_web/templates/noticias_html.ex b/lib/pescarte_web/templates/noticias_html.ex index 53acafe6..15d94086 100644 --- a/lib/pescarte_web/templates/noticias_html.ex +++ b/lib/pescarte_web/templates/noticias_html.ex @@ -1,6 +1,8 @@ defmodule PescarteWeb.NoticiasHTML do use PescarteWeb, :html + alias Pescarte.Blog + embed_templates("noticias_html/*") @notice_title_max_length Application.compile_env!(:pescarte, [ @@ -43,6 +45,23 @@ defmodule PescarteWeb.NoticiasHTML do text <> "..." end + def date_to_string(date_time) do + DateTime.to_date(date_time) + |> Date.to_string() + |> String.split("-") + |> Enum.reverse() + |> Enum.join("/") + end + + def handle_event("get_news", _, socket) do + current_news_length = socket.assigns.news.length + loaded_news = Blog.list_posts_with_filter(%{page: current_news_length + 1, page_size: 6}) + + socket = socket |> assign(news: socket.assigns.news ++ loaded_news) + + {:noreply, socket} + end + def handle_event("dialog", _value, socket) do {:noreply, socket} end diff --git a/lib/pescarte_web/templates/noticias_html/show.html.heex b/lib/pescarte_web/templates/noticias_html/show.html.heex index 3078876a..a6a34828 100644 --- a/lib/pescarte_web/templates/noticias_html/show.html.heex +++ b/lib/pescarte_web/templates/noticias_html/show.html.heex @@ -2,9 +2,8 @@ <.flash :if={@error_message} id="login-error" kind={:error}> {@error_message} - - + + --> +
+
+ <.text size="h2" color="text-blue-100"> + Notícias + +
+
+ +
+ + +
+ +
+ + + +
+

{date_to_string(@main_new.inserted_at)}

+ +

+ {@main_new.titulo} +

+
+

+ {handle_notice_desc_length(@main_new.conteudo)} +

+
-
- <.text size="h2" color="text-blue-100">Notícias +
- + <%= for new <- @news do %> +
+ + + +
+

{date_to_string(new.inserted_at)}

+ + <.text size="h4" color="text-blue-100"> + {handle_notice_title_length(new.titulo)} + + + <.text size="base" color="text-black-60"> + {handle_notice_desc_length(new.conteudo)} + +
+
+ <% end %> +
+ + <.button style="primary" click="get_news"> + <.text size="base" color="text-wite-100">Ver mais... + diff --git a/mix.lock b/mix.lock index 24f0f286..332599ae 100644 --- a/mix.lock +++ b/mix.lock @@ -2,8 +2,8 @@ "absinthe": {:hex, :absinthe, "1.7.8", "43443d12ad2b4fcce60e257ac71caf3081f3d5c4ddd5eac63a02628bcaf5b556", [:mix], [{:dataloader, "~> 1.0.0 or ~> 2.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:opentelemetry_process_propagator, "~> 0.2.1 or ~> 0.3", [hex: :opentelemetry_process_propagator, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c4085df201892a498384f997649aedb37a4ce8a726c170d5b5617ed3bf45d40b"}, "absinthe_phoenix": {:hex, :absinthe_phoenix, "2.0.3", "74e0862f280424b7bc290f6f69e133268bce0b4e7db0218c7e129c5c2b1d3fd4", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:absinthe_plug, "~> 1.5", [hex: :absinthe_plug, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.5", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.13 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}], "hexpm", "caffaea03c17ea7419fe07e4bc04c2399c47f0d8736900623dbf4749a826fd2c"}, "absinthe_plug": {:hex, :absinthe_plug, "1.5.8", "38d230641ba9dca8f72f1fed2dfc8abd53b3907d1996363da32434ab6ee5d6ab", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bbb04176647b735828861e7b2705465e53e2cf54ccf5a73ddd1ebd855f996e5a"}, - "aws_signature": {:hex, :aws_signature, "0.3.3", "5844bee0d3cc42eefd21d236bbfaa8aa9b16e2f2b7ee79edaecb321db3fb6adf", [:rebar3], [], "hexpm", "87e8f42b8e49002aa8d0350a71d13d69ea91b9afb4ca9b526ae36db1d585c924"}, - "bandit": {:hex, :bandit, "1.6.5", "24096d6232e0d050096acec96a0a382c44de026f9b591b883ed45497e1ef4916", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "b6b91f630699c8b41f3f0184bd4f60b281e19a336ad9dc1a0da90637b6688332"}, + "aws_signature": {:hex, :aws_signature, "0.3.2", "adf33bc4af00b2089b7708bf20e3246f09c639a905a619b3689f0a0a22c3ef8f", [:rebar3], [], "hexpm", "b0daf61feb4250a8ab0adea60db3e336af732ff71dd3fb22e45ae3dcbd071e44"}, + "bandit": {:hex, :bandit, "1.6.2", "a5fa4cfbae9baaf196269a88533e18eef9e7c53bea07b03f6bc2c6d5bf87b1ce", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4563b81ec94f25448ac02a8853453198cf7a63abac6202dbd4bda2c7f1a71eed"}, "bcrypt_elixir": {:hex, :bcrypt_elixir, "3.2.0", "feab711974beba4cb348147170346fe097eea2e840db4e012a145e180ed4ab75", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "563e92a6c77d667b19c5f4ba17ab6d440a085696bdf4c68b9b0f5b30bc5422b8"}, "blankable": {:hex, :blankable, "1.0.0", "89ab564a63c55af117e115144e3b3b57eb53ad43ba0f15553357eb283e0ed425", [:mix], [], "hexpm", "7cf11aac0e44f4eedbee0c15c1d37d94c090cb72a8d9fddf9f7aec30f9278899"}, "brcpfcnpj": {:hex, :brcpfcnpj, "1.0.0", "23319e5f7e4da533f36dc5b7793e7c505fd80e43b0fa720c7a459daffbaa5034", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "8e6f38910896ea4f39b75c37855a702cebd495c2a74d88cdfd5c3c715c871510"},