Skip to content

Commit 0396792

Browse files
committed
feat(course): add list courses endpoint
1 parent 33f70b9 commit 0396792

File tree

18 files changed

+421
-12
lines changed

18 files changed

+421
-12
lines changed

Cargo.lock

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.nix

Lines changed: 92 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ academy_core_config_contracts.path = "academy_core/config/contracts"
5858
academy_core_config_impl.path = "academy_core/config/impl"
5959
academy_core_contact_contracts.path = "academy_core/contact/contracts"
6060
academy_core_contact_impl.path = "academy_core/contact/impl"
61+
academy_core_course_contracts.path = "academy_core/course/contracts"
62+
academy_core_course_impl.path = "academy_core/course/impl"
6163
academy_core_finance_contracts.path = "academy_core/finance/contracts"
6264
academy_core_finance_impl.path = "academy_core/finance/impl"
6365
academy_core_health_contracts.path = "academy_core/health/contracts"

academy/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ academy_core_coin_contracts.workspace = true
2020
academy_core_coin_impl.workspace = true
2121
academy_core_config_impl.workspace = true
2222
academy_core_contact_impl.workspace = true
23+
academy_core_course_contracts.workspace = true
24+
academy_core_course_impl.workspace = true
2325
academy_core_finance_contracts.workspace = true
2426
academy_core_finance_impl.workspace = true
2527
academy_core_health_impl.workspace = true

academy/src/environment/types.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use academy_cache_valkey::ValkeyCache;
88
use academy_core_coin_impl::{CoinFeatureServiceImpl, coin::CoinServiceImpl};
99
use academy_core_config_impl::ConfigFeatureServiceImpl;
1010
use academy_core_contact_impl::ContactFeatureServiceImpl;
11+
use academy_core_course_impl::CourseFeatureServiceImpl;
1112
use academy_core_finance_impl::{
1213
FinanceFeatureServiceImpl, coin::FinanceCoinServiceImpl, invoice::FinanceInvoiceServiceImpl,
1314
};
@@ -68,6 +69,7 @@ pub type RestServer = academy_api_rest::RestServer<
6869
FinanceFeature,
6970
HeartFeature,
7071
PremiumFeature,
72+
CourseFeature,
7173
Internal,
7274
>;
7375

@@ -231,4 +233,6 @@ pub type PremiumPlan = PremiumPlanServiceImpl;
231233
pub type Premium = PremiumServiceImpl<Time, PremiumPurchase, PremiumRepo>;
232234
pub type PremiumPurchase = PremiumPurchaseServiceImpl<Id, Time, Coin, PremiumPlan, PremiumRepo>;
233235

236+
pub type CourseFeature = CourseFeatureServiceImpl;
237+
234238
pub type Internal = InternalServiceImpl<Database, AuthInternal, UserRepo, Coin, Heart, Premium>;

academy_api/rest/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ academy_auth_contracts.workspace = true
1515
academy_core_coin_contracts.workspace = true
1616
academy_core_config_contracts.workspace = true
1717
academy_core_contact_contracts.workspace = true
18+
academy_core_course_contracts.workspace = true
1819
academy_core_finance_contracts.workspace = true
1920
academy_core_health_contracts.workspace = true
2021
academy_core_heart_contracts.workspace = true

academy_api/rest/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{
66
use academy_core_coin_contracts::CoinFeatureService;
77
use academy_core_config_contracts::ConfigFeatureService;
88
use academy_core_contact_contracts::ContactFeatureService;
9+
use academy_core_course_contracts::CourseFeatureService;
910
use academy_core_finance_contracts::FinanceFeatureService;
1011
use academy_core_health_contracts::HealthFeatureService;
1112
use academy_core_heart_contracts::HeartFeatureService;
@@ -57,6 +58,7 @@ pub struct RestServer<
5758
Finance,
5859
Heart,
5960
Premium,
61+
Course,
6062
Internal,
6163
> {
6264
_config: RestServerConfig,
@@ -72,6 +74,7 @@ pub struct RestServer<
7274
finance: Finance,
7375
heart: Heart,
7476
premium: Premium,
77+
course: Course,
7578
internal: Internal,
7679
}
7780

@@ -101,6 +104,7 @@ impl<
101104
Finance,
102105
Heart,
103106
Premium,
107+
Course,
104108
Internal,
105109
>
106110
RestServer<
@@ -116,6 +120,7 @@ impl<
116120
Finance,
117121
Heart,
118122
Premium,
123+
Course,
119124
Internal,
120125
>
121126
where
@@ -131,6 +136,7 @@ where
131136
Finance: FinanceFeatureService,
132137
Heart: HeartFeatureService,
133138
Premium: PremiumFeatureService,
139+
Course: CourseFeatureService,
134140
Internal: InternalService,
135141
{
136142
pub async fn serve(self) -> anyhow::Result<()> {
@@ -162,6 +168,7 @@ where
162168
routes::finance::TAG,
163169
routes::heart::TAG,
164170
routes::premium::TAG,
171+
routes::course::TAG,
165172
routes::internal::TAG,
166173
]
167174
.into_iter()
@@ -239,6 +246,7 @@ where
239246
.merge(routes::finance::router(self.finance.into()))
240247
.merge(routes::heart::router(self.heart.into()))
241248
.merge(routes::premium::router(self.premium.into()))
249+
.merge(routes::course::router(self.course.into()))
242250
.merge(routes::internal::router(self.internal.into()))
243251
}
244252
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use academy_models::{
2+
course::{
3+
CourseAuthor, CourseAuthorName, CourseDescription, CourseId, CourseLectureTitle,
4+
CourseLectureUserSummary, CourseSectionTitle, CourseSectionUserSummary, CourseTitle,
5+
CourseUserSummary,
6+
},
7+
url::Url,
8+
};
9+
use schemars::JsonSchema;
10+
use serde::Serialize;
11+
12+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, JsonSchema)]
13+
pub struct ApiCourseUserSummary {
14+
pub id: CourseId,
15+
pub title: CourseTitle,
16+
pub description: CourseDescription,
17+
pub category: Option<String>,
18+
pub language: Option<&'static str>,
19+
pub image: Option<Url>,
20+
pub authors: Vec<ApiCourseAuthor>,
21+
pub price: u64,
22+
pub learnings_goals: Vec<String>,
23+
pub requirements: Vec<String>,
24+
pub last_update: i64,
25+
pub sections: Vec<ApiCourseSectionUserSummary>,
26+
pub completed: Option<bool>,
27+
}
28+
29+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, JsonSchema)]
30+
pub struct ApiCourseAuthor {
31+
pub name: CourseAuthorName,
32+
pub url: Option<Url>,
33+
}
34+
35+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, JsonSchema)]
36+
pub struct ApiCourseSectionUserSummary {
37+
pub title: CourseSectionTitle,
38+
pub lectures: Vec<ApiCourseLectureUserSummary>,
39+
pub completed: Option<bool>,
40+
}
41+
42+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, JsonSchema)]
43+
pub struct ApiCourseLectureUserSummary {
44+
pub title: CourseLectureTitle,
45+
pub duration: u64,
46+
pub completed: Option<bool>,
47+
}
48+
49+
impl From<CourseUserSummary> for ApiCourseUserSummary {
50+
fn from(value: CourseUserSummary) -> Self {
51+
Self {
52+
id: value.base.id,
53+
title: value.base.title,
54+
description: value.base.description,
55+
category: None,
56+
language: Some("de"),
57+
image: value.base.image_url,
58+
authors: value.base.authors.into_iter().map(Into::into).collect(),
59+
price: value.base.price,
60+
learnings_goals: vec![],
61+
requirements: vec![],
62+
last_update: value.base.last_update.timestamp(),
63+
sections: value.sections.into_iter().map(Into::into).collect(),
64+
completed: value.completed,
65+
}
66+
}
67+
}
68+
69+
impl From<CourseAuthor> for ApiCourseAuthor {
70+
fn from(value: CourseAuthor) -> Self {
71+
Self {
72+
name: value.name,
73+
url: value.url,
74+
}
75+
}
76+
}
77+
78+
impl From<CourseSectionUserSummary> for ApiCourseSectionUserSummary {
79+
fn from(value: CourseSectionUserSummary) -> Self {
80+
Self {
81+
title: value.title,
82+
lectures: value.lectures.into_iter().map(Into::into).collect(),
83+
completed: value.completed,
84+
}
85+
}
86+
}
87+
88+
impl From<CourseLectureUserSummary> for ApiCourseLectureUserSummary {
89+
fn from(value: CourseLectureUserSummary) -> Self {
90+
Self {
91+
title: value.title,
92+
duration: value.duration.as_secs(),
93+
completed: value.completed,
94+
}
95+
}
96+
}

academy_api/rest/src/models/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::const_schema;
88

99
pub mod coin;
1010
pub mod contact;
11+
pub mod course;
1112
pub mod heart;
1213
pub mod oauth2;
1314
pub mod premium;

0 commit comments

Comments
 (0)