finish breadcumbs and categories

This commit is contained in:
Aleksandr Trushkin
2024-01-11 19:17:26 +03:00
parent 067c63baa8
commit 8b8a7618a2
4 changed files with 156 additions and 101 deletions

View File

@ -33,8 +33,8 @@ func setupHTTP(cfg config.HTTP, srv xhttp.Server, log *slog.Logger) *http.Server
router.Use(mux.CORSMethodMiddleware(router))
router.Use(middlewareLogger(log))
router.HandleFunc("/updatedesc", coursesAPI.UdpateDescription).Methods(http.MethodPost)
coursesRouter := router.PathPrefix("/courses").Subrouter()
// router.HandleFunc("/updatedesc", coursesAPI.UdpateDescription).Methods(http.MethodPost)
coursesRouter := router.PathPrefix("/courses").Subrouter().StrictSlash(true)
coursesRouter.HandleFunc("/", coursesAPI.List).Methods(http.MethodGet)
coursesListLearningOnlyPath := makePathTemplate(xhttp.LearningTypePathParam)
coursesRouter.HandleFunc(coursesListLearningOnlyPath, coursesAPI.List).Methods(http.MethodGet)

View File

@ -109,28 +109,39 @@ type listCoursesTemplateParams struct {
func mapDomainCourseToTemplate(in ...domain.Course) listCoursesTemplateParams {
coursesBySubcategory := make(map[string][]domain.Course, len(in))
subcategoriesByCategories := make(map[string]map[string]struct{}, len(in))
categoryByID := make(map[string]baseInfo, len(in))
xslices.ForEach(in, func(c domain.Course) {
coursesBySubcategory[c.Thematic] = append(coursesBySubcategory[c.Thematic], c)
if _, ok := subcategoriesByCategories[c.LearningType]; !ok {
subcategoriesByCategories[c.LearningType] = map[string]struct{}{}
coursesBySubcategory[c.ThematicID] = append(coursesBySubcategory[c.ThematicID], c)
if _, ok := subcategoriesByCategories[c.LearningTypeID]; !ok {
subcategoriesByCategories[c.LearningTypeID] = map[string]struct{}{}
}
subcategoriesByCategories[c.LearningTypeID][c.ThematicID] = struct{}{}
if _, ok := categoryByID[c.LearningTypeID]; !ok {
categoryByID[c.LearningTypeID] = baseInfo{
ID: c.LearningTypeID,
Name: c.LearningType,
}
}
if _, ok := categoryByID[c.ThematicID]; !ok {
categoryByID[c.ThematicID] = baseInfo{
ID: c.ThematicID,
Name: c.Thematic,
}
}
subcategoriesByCategories[c.LearningType][c.Thematic] = struct{}{}
})
var out listCoursesTemplateParams
for category, subcategoryMap := range subcategoriesByCategories {
outCategory := categoryInfo{}
outCategory.ID = category
outCategory.Name = category
outCategory.Description = ""
outCategory := categoryInfo{
baseInfo: categoryByID[category],
}
for subcategory := range subcategoryMap {
outSubCategory := subcategoryInfo{
Courses: coursesBySubcategory[subcategory],
baseInfo: categoryByID[subcategory],
Courses: coursesBySubcategory[subcategory],
}
outSubCategory.ID = subcategory
outSubCategory.Name = subcategory
outSubCategory.Description = ""
outCategory.Subcategories = append(outCategory.Subcategories, outSubCategory)
}

View File

@ -13,7 +13,11 @@
<p class="subtitle is-8">{{ .Description }}</p>
</div>
<div class="content">
<p>{{ .FullPrice }} rub.</p>
{{ if .FullPrice }}
<p>{{ .FullPrice }} rub.</p>
{{ else }}
<p>Бесплатно</p>
{{ end }}
</div>
<button class="button" onclick="location.href='{{ .OriginLink }}'">

View File

@ -1,108 +1,148 @@
{{define "courses"}}
<!DOCTYPE html>
<html>
{{ template "html_head" . }}
<body>
{{ template "header" . }}
{{ template "html_head" . }}
<nav class="level">
<div class="level-item has-text-centered">
<div>
<p class="heading">Courses</p>
<p class="title">10k</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Clients</p>
<p class="title">1m</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Categories</p>
<p class="title">1,024</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Likes</p>
<p class="title">Over 9m</p>
</div>
</div>
</nav>
<body>
{{ template "header" . }}
<div class="section">
<div class="container">
<h1>Welcome to the Course Aggregator</h1>
<nav class="breadcrumb" aria-label="breadcrumbs">
<ul>
<li><a href="/courses">Courses</a></li>
{{ if ne .LearningTypeName "" }}
<li><a href="/courses/{{.ActiveLearningType}}">{{ .LearningTypeName }}</a></li>
<nav class="level">
<div class="level-item has-text-centered">
<div>
<p class="heading">Courses</p>
<p class="title">10k</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Clients</p>
<p class="title">1m</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Categories</p>
<p class="title">1,024</p>
</div>
</div>
<div class="level-item has-text-centered">
<div>
<p class="heading">Likes</p>
<p class="title">Over 9m</p>
</div>
</div>
</nav>
<div class="section">
<div class="container block">
<nav class="breadcrumb" aria-label="breadcrumbs">
<ul>
<li><a href="/courses">Курсы</a></li>
{{ if ne .LearningTypeName "" }}
<li><a href="/courses/{{.ActiveLearningType}}">{{ .LearningTypeName }}</a></li>
{{ end }}
{{ if ne .CourseThematicName "" }}
<li><a href="/courses/{{.ActiveLearningType}}/{{.ActiveCourseThematic}}">{{ .CourseThematicName }}</a></li>
{{ end }}
<!-- <li class="is-active"><a href="#" aria-current="page">Breadcrumb</a></li> -->
</ul>
</nav>
<form id="filter-form" class="columns">
<div class="select">
<select id="learning-type-filter" name="learning_type">
<option value="">Все направления</option>
{{ range $t := .AvailableLearningTypes }}
<option value="{{$t.ID}}" {{ if eq $t.ID $.ActiveLearningType }}selected{{ end }}>{{ $t.Name }}</option>
{{ end }}
{{ if ne .CourseThematicName "" }}
<li><a href="/courses/{{.ActiveLearningType}}/{{.ActiveCourseThematic}}">{{ .CourseThematicName }}</a></li>
</select>
</div>
{{ if .LearningTypeName }}
<div class="select">
<select id="course-thematic-filter" name="course_thematic">
<option value="">Все темы</option>
{{ range $t := .AvailableCourseThematics }}
<option value="{{$t.ID}}" {{ if eq $t.ID $.ActiveCourseThematic }}selected{{ end }}>{{ $t.Name }}</option>
{{ end }}
<!-- <li class="is-active"><a href="#" aria-current="page">Breadcrumb</a></li> -->
</ul>
</nav>
<form id="filter-form">
<div class="select columns">
<select id="learning-type-filter" name="learning_type">
<option
value=""
>All Learning Types</option>
{{ range $t := .AvailableLearningTypes }}
<option
value="{{$t.ID}}"
{{ if eq $t.ID $.ActiveLearningType }}selected{{ end }}
>{{ $t.Name }}</option>
{{ end }}
</select>
<select id="course-thematic-filter" name="learning_type">
<option
value=""
>All Course Thematics</option>
{{ range $t := .AvailableCourseThematics }}
<option
value="{{$t.ID}}"
{{ if eq $t.ID $.ActiveCourseThematic }}selected{{ end }}
>{{ $t.Name }}</option>
{{ end }}
</select>
</select>
</div>
{{ end }}
<button id="go-to-filter" class="button">Перейти</button>
</form>
</div>
<div id="category-course-list" class="container">
{{ range $category := .Categories }}
<div class="box">
<div class="title is-3">
<a href="/courses/{{ $category.ID }}">
{{ $category.Name }}
</a>
</div>
</form>
<div id="category-course-list">
{{ range $category := .Categories }}
<div class="title">{{ $category.Name }}</div>
<p>{{ $category.Description }}</p>
<div class="subtitle is-6">
Some description about the learning category {{ $category.Description }}
</div>
{{ range $subcategory := $category.Subcategories }}
<div class="subtitle">{{ $subcategory.Name }}</div>
<p>{{ $subcategory.Description }}</p>
{{ range $subcategory := $category.Subcategories }}
<div class="box">
<div class="title is-4">
<a href="/courses/{{ $category.ID }}/{{ $subcategory.ID }}">
{{ $subcategory.Name }}
</a>
</div>
<div class="subtitle is-6">Some description about course thematics {{ $subcategory.Description }}</div>
<div class="columns is-multiline">
{{ range $course := $subcategory.Courses }}
{{ template "course_info" $course }}
{{ template "course_info" $course }}
{{ end }}
</div>
{{ end }}
</div>
{{ end }}
</div>
<div id="course-info"></div>
</div>
{{ end }}
</div>
<div id="course-info"></div>
</div>
<nav class="pagination is-centered" role="navigation" aria-label="pagination">
<a class="pagination-previous">Previous</a>
<a class="pagination-next" href="/courses/?next={{ .NextPageToken }}&per_page=50">Next page</a>
</nav>
{{ template "footer" . }}
</div>
<nav class="pagination is-centered" role="navigation" aria-label="pagination">
<a class="pagination-previous">Previous</a>
<a class="pagination-next" href="/courses/?next={{ .NextPageToken }}&per_page=50">Next page</a>
</nav>
{{ template "footer" . }}
<script>
const formFilterOnSubmit = event => {
event.preventDefault();
const lt = document.getElementById('learning-type-filter')
const ct = document.getElementById('course-thematic-filter');
let out = '/courses';
if (lt != null && lt.value != '') {
out += '/' + lt.value;
}
if (ct != null && ct.value != '') {
out += '/' + ct.value;
}
document.location.assign(out);
return false;
};
document.addEventListener('DOMContentLoaded', () => {
const ff = document.getElementById('filter-form');
ff.addEventListener('submit', formFilterOnSubmit);
})
</script>
</body>
</body>
</html>
{{end}}