Refactor insights handling and error encoding in presentation layer
- Updated insights analyzer tests to use Utc for date handling. - Added timezone support for insights retrieval, allowing insights to be bucketed by the user's local time. - Introduced `encode_domain_error` for better error handling in API responses. - Modified various handlers to utilize the new error encoding function. - Enhanced insights API to reject unknown time zones and return appropriate errors. - Updated frontend components to handle insights data with timezone awareness. - Improved localization for insights sample counts.
This commit is contained in:
@@ -3,13 +3,20 @@
|
||||
//! thresholds. No caching, no snapshots — the same on-the-fly shape as the
|
||||
//! existing live stats.
|
||||
|
||||
use chrono::TimeZone;
|
||||
use domain::{errors::DomainError, models::Insight, value_objects::UserId};
|
||||
|
||||
use crate::insights::deps::GetInsightsDeps;
|
||||
|
||||
pub async fn execute(deps: &GetInsightsDeps, user_id: UserId) -> Result<Vec<Insight>, DomainError> {
|
||||
pub async fn execute<Tz: TimeZone + Sync>(
|
||||
deps: &GetInsightsDeps,
|
||||
user_id: UserId,
|
||||
tz: &Tz,
|
||||
) -> Result<Vec<Insight>, DomainError> {
|
||||
let rows = deps.insights.get_watch_rows(&user_id).await?;
|
||||
Ok(domain::services::insights_analyzer::build_insights(&rows))
|
||||
Ok(domain::services::insights_analyzer::build_insights(
|
||||
&rows, tz,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -31,7 +31,9 @@ async fn returns_analyzer_output_for_the_user() {
|
||||
insights: InMemoryInsightsQuery::with_rows(user, rows),
|
||||
};
|
||||
|
||||
let insights = execute(&deps, UserId::from_uuid(user)).await.unwrap();
|
||||
let insights = execute(&deps, UserId::from_uuid(user), &chrono::Utc)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(insights.iter().any(
|
||||
|i| matches!(i, domain::models::Insight::RatingLift { genre, .. } if genre == "Thriller")
|
||||
));
|
||||
@@ -49,7 +51,9 @@ async fn other_users_rows_are_not_seen() {
|
||||
insights: InMemoryInsightsQuery::with_rows(other, rows),
|
||||
};
|
||||
|
||||
let insights = execute(&deps, UserId::from_uuid(user)).await.unwrap();
|
||||
let insights = execute(&deps, UserId::from_uuid(user), &chrono::Utc)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(insights.is_empty());
|
||||
}
|
||||
|
||||
@@ -60,7 +64,9 @@ async fn empty_diary_returns_empty_list() {
|
||||
insights: InMemoryInsightsQuery::new(),
|
||||
};
|
||||
|
||||
let insights = execute(&deps, UserId::from_uuid(user)).await.unwrap();
|
||||
let insights = execute(&deps, UserId::from_uuid(user), &chrono::Utc)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(insights.is_empty());
|
||||
}
|
||||
|
||||
@@ -83,7 +89,7 @@ async fn port_errors_propagate() {
|
||||
insights: Arc::new(Failing),
|
||||
};
|
||||
|
||||
let err = execute(&deps, UserId::from_uuid(Uuid::new_v4()))
|
||||
let err = execute(&deps, UserId::from_uuid(Uuid::new_v4()), &chrono::Utc)
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert!(matches!(
|
||||
|
||||
Reference in New Issue
Block a user