1use crate::{DummyJsonClient, API_BASE_URL};
2use once_cell::sync::Lazy;
3use serde::{Deserialize, Serialize};
4
5static PRODUCTS_BASE_URL: Lazy<String> = Lazy::new(|| format!("{}/products", API_BASE_URL));
6
7#[derive(Deserialize, Debug)]
8pub struct Product {
9 pub id: u32,
10 #[serde(flatten)]
11 pub other_fields: AddProduct,
12}
13
14#[derive(Serialize, Deserialize, Debug, Default)]
15pub struct AddProduct {
16 pub title: String,
17 pub description: Option<String>,
18 pub price: Option<f32>,
19 #[serde(rename = "discountPercentage")]
20 pub discount_percentage: Option<f32>,
21 pub rating: Option<f32>,
22 pub stock: Option<u32>,
23 pub tags: Option<Vec<String>>,
24 pub sku: Option<String>,
28 pub weight: Option<u16>,
29 pub dimensions: Option<Dimension>,
30 #[serde(rename = "warrantyInformation")]
31 pub warranty_info: Option<String>,
32 #[serde(rename = "shippingInformation")]
33 pub shipping_info: Option<String>,
34 #[serde(rename = "availabilityStatus")]
35 pub availability_status: Option<String>,
36 pub reviews: Option<Vec<Review>>,
37 #[serde(rename = "returnPolicy")]
38 pub return_policy: Option<String>,
39 #[serde(rename = "minimumOrderQuantity")]
40 pub min_order_qty: Option<u16>,
41 pub meta: Option<Meta>,
42 pub images: Option<Vec<String>>,
43 pub thumbnail: Option<String>,
44}
45
46#[derive(Serialize, Deserialize, Debug)]
47pub struct Dimension {
48 pub width: f32,
49 pub height: f32,
50 pub depth: f32,
51}
52
53#[derive(Serialize, Deserialize, Debug)]
54pub struct Review {
55 pub rating: u8,
56 pub comment: String,
57 pub date: String,
58 #[serde(rename = "reviewerName")]
59 pub reviewer_name: String,
60 #[serde(rename = "reviewerEmail")]
61 pub reviewer_email: String,
62}
63
64#[derive(Serialize, Deserialize, Debug)]
65pub struct Meta {
66 #[serde(rename = "createdAt")]
67 pub created_at: String,
68 #[serde(rename = "updatedAt")]
69 pub updated_at: String,
70 pub barcode: String,
71 #[serde(rename = "qrCode")]
72 pub qr_code: String,
73}
74
75#[derive(Deserialize, Debug)]
76pub struct GetAllProductsResponse {
77 pub products: Vec<Product>,
78 pub total: u32,
79 pub skip: u32,
80 pub limit: u32,
81}
82
83#[derive(Deserialize, Debug)]
84pub struct ProductCategory {
85 pub slug: String,
86 pub name: String,
87 pub url: String,
88}
89
90#[derive(Deserialize, Debug)]
91pub struct DeleteProductResponse {
92 #[serde(flatten)]
93 pub other_fields: Product,
94 #[serde(rename = "isDeleted")]
95 pub is_deleted: bool,
96 #[serde(rename = "deletedOn")]
97 pub deleted_on: String,
98}
99
100impl DummyJsonClient {
101 pub async fn get_all_products(&self) -> Result<GetAllProductsResponse, reqwest::Error> {
103 let response = self.client.get(PRODUCTS_BASE_URL.as_str()).send().await?;
104 response.json::<GetAllProductsResponse>().await
105 }
106
107 pub async fn get_product_by_id(&self, id: u32) -> Result<Product, reqwest::Error> {
109 let url = &format!("{}/{}", PRODUCTS_BASE_URL.as_str(), id);
110 let response = self.client.get(url).send().await?;
111 response.json::<Product>().await
112 }
113
114 pub async fn search_products(
116 &self,
117 query: &str,
118 ) -> Result<GetAllProductsResponse, reqwest::Error> {
119 let url = &format!("{}/search?q={}", PRODUCTS_BASE_URL.as_str(), query);
120 let response = self.client.get(url).send().await?;
121 response.json::<GetAllProductsResponse>().await
122 }
123
124 pub async fn limit_and_skip_products(
126 &self,
127 limit: u32,
128 skip: u32,
129 selects: &str,
130 ) -> Result<GetAllProductsResponse, reqwest::Error> {
131 let url = &format!(
132 "{}/?limit={}&skip={}&select={}",
133 PRODUCTS_BASE_URL.as_str(),
134 limit,
135 skip,
136 selects
137 );
138 let response = self.client.get(url).send().await?;
139 response.json::<GetAllProductsResponse>().await
140 }
141
142 pub async fn sort_products_by(
144 &self,
145 field: &str,
146 order: &str,
147 ) -> Result<GetAllProductsResponse, reqwest::Error> {
148 let url = &format!("{}/?sortBy={}&order={}", PRODUCTS_BASE_URL.as_str(), field, order);
149 let response = self.client.get(url).send().await?;
150 response.json::<GetAllProductsResponse>().await
151 }
152
153 pub async fn get_product_categories(&self) -> Result<Vec<ProductCategory>, reqwest::Error> {
155 let url = &format!("{}/categories", PRODUCTS_BASE_URL.as_str());
156 let response = self.client.get(url).send().await?;
157 response.json::<Vec<ProductCategory>>().await
158 }
159
160 pub async fn get_product_categories_list(&self) -> Result<Vec<String>, reqwest::Error> {
162 let url = &format!("{}/category-list", PRODUCTS_BASE_URL.as_str());
163 let response = self.client.get(url).send().await?;
164 response.json::<Vec<String>>().await
165 }
166
167 pub async fn get_products_by_category(
169 &self,
170 category: &str,
171 ) -> Result<GetAllProductsResponse, reqwest::Error> {
172 let url = &format!("{}/category/{}", PRODUCTS_BASE_URL.as_str(), category);
173 let response = self.client.get(url).send().await?;
174 response.json::<GetAllProductsResponse>().await
175 }
176
177 pub async fn add_product(&self, product: &AddProduct) -> Result<Product, reqwest::Error> {
179 let url = &format!("{}/add", PRODUCTS_BASE_URL.as_str());
180 let response = self.client.post(url).json(product).send().await?;
181 response.json::<Product>().await
182 }
183
184 pub async fn update_product(
186 &self,
187 id: u32,
188 product: &AddProduct,
189 ) -> Result<Product, reqwest::Error> {
190 let url = &format!("{}/{}", PRODUCTS_BASE_URL.as_str(), id);
191 let response = self.client.put(url).json(product).send().await?;
192 response.json::<Product>().await
193 }
194
195 pub async fn delete_product(&self, id: u32) -> Result<DeleteProductResponse, reqwest::Error> {
197 let url = &format!("{}/{}", PRODUCTS_BASE_URL.as_str(), id);
198 let response = self.client.delete(url).send().await?;
199 response.json::<DeleteProductResponse>().await
200 }
201}