diff --git a/crates/app/src/public/images/default-avatar.svg b/crates/app/src/public/images/default-avatar.svg
index 00fa7ab..2f92a92 100644
--- a/crates/app/src/public/images/default-avatar.svg
+++ b/crates/app/src/public/images/default-avatar.svg
@@ -6,4 +6,11 @@
xmlns="http://www.w3.org/2000/svg"
>
+
+
+
diff --git a/crates/app/src/routes/api/v1/products.rs b/crates/app/src/routes/api/v1/products.rs
index 6a48dd3..05d8e9c 100644
--- a/crates/app/src/routes/api/v1/products.rs
+++ b/crates/app/src/routes/api/v1/products.rs
@@ -1,13 +1,20 @@
use crate::{
get_user_from_token,
image::{save_webp_buffer, JsonMultipart},
- routes::api::v1::{
- communities::posts::MAXIMUM_FILE_SIZE, CreateProduct, UpdateProductDescription,
- UpdateProductName, UpdateProductPrice,
+ routes::{
+ api::v1::{
+ communities::posts::MAXIMUM_FILE_SIZE, CreateProduct, UpdateProductDescription,
+ UpdateProductName, UpdateProductPrice,
+ },
+ pages::PaginatedQuery,
},
State,
};
-use axum::{extract::Path, response::IntoResponse, Extension, Json};
+use axum::{
+ extract::{Path, Query},
+ response::IntoResponse,
+ Extension, Json,
+};
use axum_extra::extract::CookieJar;
use tetratto_core::model::{
oauth,
@@ -31,14 +38,18 @@ pub async fn get_request(
}
}
-pub async fn list_request(jar: CookieJar, Extension(data): Extension) -> impl IntoResponse {
+pub async fn list_request(
+ jar: CookieJar,
+ Extension(data): Extension,
+ Query(props): Query,
+) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadProducts) {
Some(ua) => ua,
None => return Json(Error::NotAllowed.into()),
};
- match data.get_products_by_user(user.id).await {
+ match data.get_products_by_user(user.id, 12, props.page).await {
Ok(x) => Json(ApiReturn {
ok: true,
message: "Success".to_string(),
diff --git a/crates/app/src/routes/pages/marketplace.rs b/crates/app/src/routes/pages/marketplace.rs
index f2b6b11..0de9be7 100644
--- a/crates/app/src/routes/pages/marketplace.rs
+++ b/crates/app/src/routes/pages/marketplace.rs
@@ -1,6 +1,9 @@
use super::render_error;
-use crate::{assets::initial_context, get_lang, get_user_from_token, State};
+use crate::{
+ assets::initial_context, get_lang, get_user_from_token, State, routes::pages::PaginatedQuery,
+};
use axum::{
+ extract::Query,
response::{Html, IntoResponse},
Extension,
};
@@ -11,6 +14,7 @@ use tetratto_core::model::Error;
pub async fn seller_settings_request(
jar: CookieJar,
Extension(data): Extension,
+ Query(props): Query,
) -> impl IntoResponse {
let data = data.read().await;
let user = match get_user_from_token!(jar, data.0) {
@@ -22,14 +26,16 @@ pub async fn seller_settings_request(
}
};
- let products = match data.0.get_products_by_user(user.id).await {
+ let products = match data.0.get_products_by_user(user.id, 12, props.page).await {
Ok(x) => x,
Err(e) => return Err(Html(render_error(e, &jar, &data, &None).await)),
};
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0.0, lang, &Some(user)).await;
+
context.insert("list", &products);
+ context.insert("page", &props.page);
// return
Ok(Html(
diff --git a/crates/core/src/database/common.rs b/crates/core/src/database/common.rs
index e7cd0ef..e61b565 100644
--- a/crates/core/src/database/common.rs
+++ b/crates/core/src/database/common.rs
@@ -75,6 +75,26 @@ impl DataManager {
Ok(res.unwrap())
}
+
+ pub async fn get_table_row_count_where(&self, table: &str, r#where: &str) -> Result {
+ let conn = match self.0.connect().await {
+ Ok(c) => c,
+ Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
+ };
+
+ let res = query_row!(
+ &conn,
+ &format!("SELECT COUNT(*)::int FROM {} {}", table, r#where),
+ params![],
+ |x| Ok(x.get::(0))
+ );
+
+ if let Err(e) = res {
+ return Err(Error::DatabaseError(e.to_string()));
+ }
+
+ Ok(res.unwrap())
+ }
}
#[macro_export]
diff --git a/crates/core/src/database/products.rs b/crates/core/src/database/products.rs
index 5127f78..0eab9aa 100644
--- a/crates/core/src/database/products.rs
+++ b/crates/core/src/database/products.rs
@@ -30,7 +30,38 @@ impl DataManager {
///
/// # Arguments
/// * `id` - the ID of the user to fetch products for
- pub async fn get_products_by_user(&self, id: usize) -> Result> {
+ /// * `batch`
+ /// * `page`
+ pub async fn get_products_by_user(
+ &self,
+ id: usize,
+ batch: usize,
+ page: usize,
+ ) -> Result> {
+ let conn = match self.0.connect().await {
+ Ok(c) => c,
+ Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
+ };
+
+ let res = query_rows!(
+ &conn,
+ "SELECT * FROM products WHERE owner = $1 ORDER BY created DESC LIMIT {} OFFSET {}",
+ &[&(id as i64), &(batch as i64), &((page * batch) as i64)],
+ |x| { Self::get_product_from_row(x) }
+ );
+
+ if res.is_err() {
+ return Err(Error::GeneralNotFound("product".to_string()));
+ }
+
+ Ok(res.unwrap())
+ }
+
+ /// Get all products by user.
+ ///
+ /// # Arguments
+ /// * `id` - the ID of the user to fetch products for
+ pub async fn get_products_by_user_all(&self, id: usize) -> Result> {
let conn = match self.0.connect().await {
Ok(c) => c,
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
@@ -68,9 +99,11 @@ impl DataManager {
let owner = self.get_user_by_id(data.owner).await?;
if !owner.permissions.check(FinePermission::SUPPORTER) {
- let products = self.get_products_by_user(data.owner).await?;
+ let products = self
+ .get_table_row_count_where("products", &format!("owner = {}", owner.id))
+ .await? as usize;
- if products.len() >= Self::MAXIMUM_FREE_PRODUCTS {
+ if products >= Self::MAXIMUM_FREE_PRODUCTS {
return Err(Error::MiscError(
"You already have the maximum number of products you can have".to_string(),
));
diff --git a/crates/core/src/database/stacks.rs b/crates/core/src/database/stacks.rs
index 6a64b53..cea2be9 100644
--- a/crates/core/src/database/stacks.rs
+++ b/crates/core/src/database/stacks.rs
@@ -165,9 +165,11 @@ impl DataManager {
let owner = self.get_user_by_id(data.owner).await?;
if !owner.permissions.check(FinePermission::SUPPORTER) {
- let stacks = self.get_stacks_by_user(data.owner).await?;
+ let stacks = self
+ .get_table_row_count_where("stacks", &format!("owner = {}", owner.id))
+ .await? as usize;
- if stacks.len() >= Self::MAXIMUM_FREE_STACKS {
+ if stacks >= Self::MAXIMUM_FREE_STACKS {
return Err(Error::MiscError(
"You already have the maximum number of stacks you can have".to_string(),
));