skill_web/api/
feedback.rs

1//! Feedback API client
2
3use serde::{Deserialize, Serialize};
4use super::{ApiClient, ApiResult};
5
6#[derive(Clone)]
7pub struct FeedbackApi {
8    client: ApiClient,
9}
10
11impl FeedbackApi {
12    pub fn new(client: ApiClient) -> Self {
13        Self { client }
14    }
15
16    /// Submit feedback for a search result
17    pub async fn submit(&self, request: &SubmitFeedbackRequest) -> ApiResult<SubmitFeedbackResponse> {
18        self.client.post("/feedback", request).await
19    }
20
21    /// Get feedback with filters
22    pub async fn get(&self, request: &GetFeedbackRequest) -> ApiResult<GetFeedbackResponse> {
23        let mut query_params = vec![];
24
25        if let Some(query) = &request.query {
26            query_params.push(format!("query={}", urlencoding::encode(query)));
27        }
28        if let Some(result_id) = &request.result_id {
29            query_params.push(format!("result_id={}", urlencoding::encode(result_id)));
30        }
31        if let Some(feedback_type) = &request.feedback_type {
32            query_params.push(format!("feedback_type={}", urlencoding::encode(feedback_type)));
33        }
34        query_params.push(format!("limit={}", request.limit));
35        query_params.push(format!("offset={}", request.offset));
36
37        let query_string = query_params.join("&");
38        let url = format!("/feedback?{}", query_string);
39
40        self.client.get(&url).await
41    }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct SubmitFeedbackRequest {
46    pub query: String,
47    pub result_id: String,
48    pub score: f32,
49    pub rank: usize,
50    pub feedback_type: String, // "positive" or "negative"
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub reason: Option<String>,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub comment: Option<String>,
55    pub client_type: String,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct SubmitFeedbackResponse {
60    pub success: bool,
61    pub feedback_id: String,
62    pub message: String,
63}
64
65#[derive(Debug, Clone, Default)]
66pub struct GetFeedbackRequest {
67    pub query: Option<String>,
68    pub result_id: Option<String>,
69    pub feedback_type: Option<String>,
70    pub limit: usize,
71    pub offset: usize,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct GetFeedbackResponse {
76    pub feedback: Vec<FeedbackEntry>,
77    pub total_count: usize,
78    pub limit: usize,
79    pub offset: usize,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct FeedbackEntry {
84    pub id: String,
85    pub query: String,
86    pub result_id: String,
87    pub score: f32,
88    pub rank: usize,
89    pub feedback_type: String,
90    #[serde(skip_serializing_if = "Option::is_none")]
91    pub reason: Option<String>,
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub comment: Option<String>,
94    pub client_type: String,
95    pub timestamp: String,
96}