Protocol.UndefinedError at GET /products/1

protocol Ecto.Queryable not implemented for TrainWeb.Catalog.Category of type Atom, the given module does not exist. This protocol is implemented for the following type(s): Atom, BitString, Ecto.Query, Ecto.SubQuery, Tuple

my code in product.ex

defmodule TrainWeb.Catalog.Product do
	use Ecto.Schema
	import Ecto.Changeset
	alias TrainWeb.Catalog.Category

	schema "products" do
		field :title, :string
		field :description, :string
		field :price, :decimal
		field :views, :integer

		many_to_many :categories, Category, join_through: "product_categories", on_replace: :delete

		timestamps(type: :utc_datetime)
	end

	def changeset(product, attrs) do
		product
		|> cast(attrs, [:title, :description, :price, :views])
		|> validate_required([:title, :description, :price, :views])
	end

end

my code in product_html.ex

defmodule TrainWeb.ProductHTML do
	use TrainWeb, :html

	embed_templates "product_html/*"

	attr :changeset, Ecto.Changeset, required: true
	attr :action, :string, required: true

	def product_form(assigns)

	def category_opts(changeset) do
		existing_ids =
			changeset
			|> Ecto.Changeset.get_change(:categories, [])
			|> Enum.map(& &1.data.id)
		for cat <- TrainWeb.Catalog.list_categories(),
			do: [key: cat.title, value: cat.id, selected: cat.id in existing_ids]
	end
end

My code in product_controller.ex

defmodule TrainWeb.ProductController do
	use TrainWeb, :controller

	alias TrainWeb.Catalog
	alias TrainWeb.Catalog.Product

	def index(conn, _params) do
		products = Catalog.list_products()
		render(conn, :index, products: products)
	end

	def new(conn, _params) do
		changeset = Catalog.change_product(%Product{})
		render(conn, :new, changeset: changeset)
	end

	def create(conn, %{"product" => product_params}) do
		case Catalog.create_product(product_params) do
			{:ok, product} ->
				conn
				|> put_flash(:info, "Product created successfully")
				|> redirect(to: ~p"/products/#{product}")
			{:error, %Ecto.Changeset{} = changeset} ->
				render(conn, :new, changeset: changeset)
		end
	end

	def update(conn, %{"id" => id, "product" => product_params}) do
		product = Catalog.get_product!(id)
		case Catalog.update_product(product, product_params) do
			{:ok, product} ->
				conn
				|> put_flash(:info, "Product updated successfully")
				|> redirect(to: ~p"/products/#{product}")
			{:error, %Ecto.Changeset{} = changeset} ->
				render(conn, :edit, product: product, changeset: changeset) 
		end
	end
	
  def show(conn, %{"id" => id}) do
    product = 
    id 
    |> Catalog.get_product!()
    |> Catalog.inc_page_views()
    render(conn, :show, product: product)
  end

	def edit(conn, %{"id" => id}) do
		product = Catalog.get_product!(id)
		changeset = Catalog.change_product(product)
		render(conn, :edit, product: product, changeset: changeset)
	end


	def delete(conn, %{"id" => id}) do
		product = Catalog.get_product!(id)
		{:ok, _product} = Catalog.delete_product(product)

		conn
		|> put_flash(:info, "Product deleted successfully")
		|> redirect(to: ~p"/products")
	end
end

My code in context catalog.ex

defmodule TrainWeb.Catalog do
	import Ecto.Query, warn: false
	alias Train.Repo
	alias TrainWeb.Catalog.Product
  	alias Train.Catalog.Category

  	def list_products do
    	Repo.all(Product)
  	end

	# def get_product!(id), do: Repo.get!(Product, id)
	def get_product!(id) do
		Product |> Repo.get!(id) |> Repo.preload(:categories)
	end

	def create_product(attrs \\ %{}) do
		%Product{}
		# |> Product.changeset(attrs)
		|> change_product(attrs)
		|> Repo.insert()
	end

	def change_product(%Product{} = product, attrs \\ %{}) do
		# Product.changeset(product, attrs)
		categories = list_categories_by_id(attrs["category_ids"])

		product
		|> Repo.preload(:categories)
		|> Product.changeset(attrs)
		|> Ecto.Changeset.put_assoc(:categories, categories)
	end

	def update_product(%Product{} = product, attrs) do
		product
		# |> Product.changeset(attrs)
		|> change_product(attrs)
		|> Repo.update()
	end

	def delete_product(%Product{} = product) do
		Repo.delete(product)
	end

	def inc_page_views(%Product{} = product) do
		{1, [%Product{views: views}]} = from(p in Product, where: p.id == ^product.id, select: [:views])
		|> Repo.update_all(inc: [views: 1])

		put_in(product.views, views)
	end



  def list_categories do
    Repo.all(Category)
  end

  def get_category!(id), do: Repo.get!(Category, id)

  def create_category(attrs \\ %{}) do
    %Category{}
    |> Category.changeset(attrs)
    |> Repo.insert()
  end

  def update_category(%Category{} = category, attrs) do
    category
    |> Category.changeset(attrs)
    |> Repo.update()
  end

  def delete_category(%Category{} = category) do
    Repo.delete(category)
  end

  def change_category(%Category{} = category, attrs \\ %{}) do
    Category.changeset(category, attrs)
  end

  def list_categories_by_id(nil), do: []
  def list_categories_by_id(category_ids) do
  	Repo.all(from c in Category, where: c.id in ^category_ids)
  end
end

My code in category.ex

defmodule Train.Catalog.Category do
  use Ecto.Schema
  import Ecto.Changeset

  schema "categories" do
    field :title, :string

    timestamps(type: :utc_datetime)
  end

  @doc false
  def changeset(category, attrs) do
    category
    |> cast(attrs, [:title])
    |> validate_required([:title])
    |> unique_constraint(:title)
  end
end

Do i miss something? it’s error when i try to view one of list product

Ups i forgot to recompile the all code, but first thing first is change the TrainWeb.Catalog.Category to Train.Catalog.Category