finish breadcumbs and categories
This commit is contained in:
@ -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)
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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 }}'">
|
||||
|
||||
@ -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}}
|
||||
|
||||
Reference in New Issue
Block a user