Skip to content

Commit

Permalink
Setup course library
Browse files Browse the repository at this point in the history
  • Loading branch information
zacksiri committed Nov 19, 2024
1 parent a84c189 commit c48f1d8
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 5 deletions.
2 changes: 1 addition & 1 deletion assets/components/technologies.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function Logo({ src, left, top, hover }) {
}}
alt=""
style={{ left, top }}
className="absolute size-16 flex rounded-full align-middle items-center justify-center bg-white shadow ring-1 ring-black/5"
className="absolute size-16 flex rounded-full align-middle items-center justify-center bg-white shadow ring-1 ring-black/5 p-3"
>
<img src={src} className="h-9" />
</motion.span>
Expand Down
2 changes: 1 addition & 1 deletion lib/opsmaru/content.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ defmodule Opsmaru.Content do

alias __MODULE__.Technology

defdelegate list_technologies(options \\ []),
defdelegate list_technologies(options \\ [end_index: 5]),
to: Technology.Manager,
as: :list

Expand Down
33 changes: 33 additions & 0 deletions lib/opsmaru/content/course.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule Opsmaru.Content.Course do
use Ecto.Schema
import Ecto.Changeset

alias Opsmaru.Content.Image
alias Opsmaru.Content.Technology

embedded_schema do
field :title, :string
field :slug, :string

field :description, :string

embeds_one :cover, Image

embeds_one :main_technology, Technology
end

def changeset(course, params) do
%{"_id" => id, "slug" => %{"current" => slug}} = params

params =
params
|> Map.put("id", id)
|> Map.put("slug", slug)

course
|> cast(params, ~w(id title slug description)a)
|> validate_required(~w(id title slug)a)
|> cast_embed(:cover)
|> cast_embed(:main_technology)
end
end
4 changes: 2 additions & 2 deletions lib/opsmaru/content/technology/manager.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ defmodule Opsmaru.Content.Technology.Manager do
@ttl :timer.hours(1)

@decorate cacheable(cache: Cache, key: {:technologies, options}, opts: [ttl: @ttl])
def list(options \\ []) do
def list(options \\ [end_index: 5]) do
options = Enum.into(options, %{})

query = ~S"""
*[_type == "technology"] {
*[_type == "technology"][0..$end_index] {
...,
"logo": {"url": logo.asset -> url, "alt": logo.alt}
}
Expand Down
7 changes: 7 additions & 0 deletions lib/opsmaru/courses.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
defmodule Opsmaru.Courses do
alias __MODULE__.Category

defdelegate list_categories(options \\ []),
to: Category.Manager,
as: :list
end
35 changes: 35 additions & 0 deletions lib/opsmaru/courses/category.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
defmodule Opsmaru.Courses.Category do
use Ecto.Schema
import Ecto.Changeset

alias Opsmaru.Content.Course

embedded_schema do
field :name, :string
field :slug, :string

field :index, :integer

embeds_many :courses, Course
end

def changeset(category, params) do
%{"_id" => id, "slug" => %{"current" => slug}} = params

params =
params
|> Map.put("id", id)
|> Map.put("slug", slug)

category
|> cast(params, ~w(id name slug index)a)
|> validate_required(~w(id name slug index)a)
|> cast_embed(:courses)
end

def parse(params) do
%__MODULE__{}
|> changeset(params)
|> apply_action!(:insert)
end
end
26 changes: 26 additions & 0 deletions lib/opsmaru/courses/category/manager.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule Opsmaru.Courses.Category.Manager do
import Opsmaru.Sanity

alias Opsmaru.Courses.Category

def list(_options \\ []) do
query = ~s"""
*[_type == "courseCategory"] | order(index asc){
...,
"courses": *[ _type == "course" && references(^._id) ] {
...,
main_technology -> {
...,
"logo": { "url": logo.asset -> url, "alt": logo.alt }
}
}
}
"""

query
|> Sanity.query(%{}, perspective: "published")
|> Sanity.request!(sanity_request_opts())
|> Sanity.result!()
|> Enum.map(&Category.parse/1)
end
end
71 changes: 71 additions & 0 deletions lib/opsmaru_web/components/course_components.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
defmodule OpsmaruWeb.CourseComponents do
use OpsmaruWeb, :html

alias Opsmaru.Courses

def header(assigns) do
h2 = Enum.find(assigns.section.contents, &(&1.slug == "learn-header-h2"))
title = Enum.find(assigns.section.contents, &(&1.slug == "learn-header-title"))
description = Enum.find(assigns.section.contents, &(&1.slug == "learn-header-description"))

assigns =
assigns
|> assign(:h2, h2)
|> assign(:title, title)
|> assign(:description, description)

~H"""
<div class="px-6 lg:px-8">
<div class="mx-auto max-w-2xl lg:max-w-7xl">
<h2 class="mt-16 font-mono text-xs/5 font-semibold uppercase tracking-widest text-gray-500 data-[dark]:text-gray-400">
<%= @h2.body %>
</h2>
<h1 class="mt-2 text-pretty text-4xl font-medium tracking-tighter text-gray-950 data-[dark]:text-white sm:text-6xl">
<%= @title.body %>
</h1>
<p class="mt-6 max-w-3xl text-2xl font-medium text-gray-500">
<%= @description.body %>
</p>
</div>
</div>
"""
end

attr :categories, :list, required: true

def categories(assigns) do
infrastructure_setup_category = Enum.find(assigns.categories, &(&1.slug == "infrastructure-setup"))

assigns = assign(assigns, :infrastructure_setup_category, infrastructure_setup_category)

~H"""
<div class="my-32 px-6 lg:px-8">
<.infrastructure_setup category={@infrastructure_setup_category} />
</div>
"""
end

attr :category, Courses.Category, required: true

def infrastructure_setup(assigns) do
~H"""
<div class="mx-auto max-w-2xl lg:max-w-7xl">
<h3 class="mt-24 font-mono text-xs/5 font-semibold uppercase tracking-widest text-gray-500 data-[dark]:text-gray-400">
<%= @category.name %>
</h3>
<hr class="mt-6 border-t border-slate-200" />
<ul role="list" class="mx-auto mt-10 grid grid-cols-1 gap-8 lg:grid-cols-2">
<li :for={course <- @category.courses}>
<img src={course.main_technology.logo.url} alt={course.main_technology.logo.alt} class="h-14" />
<p class="mt-6 max-w-lg text-sm/6 text-slate-500">
<%= course.description %>
</p>
<.link navigate={~p"/how-to/#{course.slug}"} class="mt-8 inline-flex items-center justify-center px-2 py-[calc(theme(spacing.[1.5])-1px)] rounded-lg border border-transparent shadow ring-1 ring-black/10 whitespace-nowrap text-sm font-medium text-gray-950 data-[disabled]:bg-transparent data-[hover]:bg-gray-50 data-[disabled]:opacity-40">
<%= gettext("View course") %>
</.link>
</li>
</ul>
</div>
"""
end
end
1 change: 0 additions & 1 deletion lib/opsmaru_web/live/blog_live/index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ defmodule OpsmaruWeb.BlogLive.Index do
{:ok, socket}
end

attr :mobile_nav_active, :boolean, default: false
attr :header_section, Pages.Section, required: true
attr :featured_posts, :list, required: true
attr :posts_count, :integer, required: true
Expand Down
File renamed without changes.
36 changes: 36 additions & 0 deletions lib/opsmaru_web/live/course_live/index.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
defmodule OpsmaruWeb.CourseLive.Index do
use OpsmaruWeb, :live_view

alias Opsmaru.Content
alias Opsmaru.Courses

alias OpsmaruWeb.CourseComponents

@page_slug "learn"

def mount(_params, _session, socket) do
page = Content.show_page(@page_slug)

header_section = Enum.find(page.sections, & &1.slug == "learn-header")

categories = Courses.list_categories()

socket =
socket
|> assign(:page_title, page.title)
|> assign(:page, page)
|> assign(:header_section, header_section)
|> assign(:categories, categories)

{:ok, socket}
end

def render(assigns) do
~H"""
<div>
<CourseComponents.header section={@header_section} />
<CourseComponents.categories categories={@categories} />
</div>
"""
end
end
2 changes: 2 additions & 0 deletions lib/opsmaru_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ defmodule OpsmaruWeb.Router do
live "/blog", BlogLive.Index
live "/blog/:id", BlogLive

live "/how-to", CourseLive.Index

live "/our-product/pricing", PricingLive

live "/legal/:id", LegalLive
Expand Down

0 comments on commit c48f1d8

Please sign in to comment.