Skip to main content

max / makenotwork

4.5 KB · 111 lines History Blame Raw
1 //! Discover page query models.
2
3 use chrono::{DateTime, Utc};
4 use serde::Serialize;
5 use sqlx::FromRow;
6
7 use super::super::id_types::{CustomLinkId, ItemId, UserId};
8 use super::super::validated_types::{Slug, Username};
9
10 /// A flattened item row returned by the discover/search query.
11 #[derive(Debug, Clone, FromRow)]
12 #[allow(dead_code)] // Fields populated by sqlx query, read during type conversion
13 pub struct DbDiscoverItemRow {
14 pub id: ItemId,
15 pub title: String,
16 pub description: Option<String>,
17 pub price_cents: i32,
18 pub item_type: super::super::ItemType,
19 pub created_at: DateTime<Utc>,
20 /// Creator's username (joined from users).
21 pub username: Username,
22 /// The creator's settlement currency (joined from users). Carried on the row
23 /// because the discover feed mixes creators, so the page has no single
24 /// currency it could apply to every price it renders.
25 pub settlement_currency: crate::currency::SettlementCurrency,
26 /// Parent project title (joined from projects).
27 pub project_title: String,
28 /// Number of completed purchases.
29 pub sales_count: i64,
30 /// Primary tag name (joined from item_tags/tags), or NULL if no primary tag.
31 pub primary_tag_name: Option<String>,
32 pub pwyw_enabled: bool,
33 /// Minimum price in cents when PWYW is enabled.
34 pub pwyw_min_cents: Option<i32>,
35 /// Which kind of match this row is: `2` = holds at least one typed word,
36 /// `1` = holds none and is here on character overlap alone. `None` when not
37 /// searching.
38 ///
39 /// Ranks ahead of [`Self::match_score`], and the two scores are not
40 /// comparable across the boundary: tier 2 uses `ts_rank`, tier 1 uses
41 /// per-word trigram. That is safe because the tier is decided by a count,
42 /// not by either score. See [`crate::db::discover::MATCH_TIER_LEXICAL`].
43 pub match_tier: Option<i16>,
44 /// How many of the typed words this row holds, and how many were typed.
45 ///
46 /// Drives the per-row "Matched 3 of 5 words" label. `None` when not
47 /// searching, or on the 1-2 character path where there are no words to
48 /// count. Counted separately from [`Self::match_score`] on purpose: the
49 /// score folds in field weighting, so a row holding every typed word but
50 /// only in its description scores 0.5, and a label derived from it would
51 /// undercount.
52 pub matched_terms: Option<i32>,
53 /// Denominator for [`Self::matched_terms`].
54 pub query_terms: Option<i32>,
55 /// Rank within the row's own tier (set when searching, `None` otherwise).
56 pub match_score: Option<f32>,
57 /// AI disclosure tier, drives the badge / row label on Discover.
58 pub ai_tier: super::super::AiTier,
59 }
60
61 /// A flattened project row returned by the discover projects query.
62 #[derive(Debug, Clone, FromRow)]
63 #[allow(dead_code)] // Fields populated by sqlx query, read during type conversion
64 pub struct DbDiscoverProjectRow {
65 pub slug: Slug,
66 pub title: String,
67 pub description: Option<String>,
68 pub project_type: super::super::ProjectType,
69 pub created_at: DateTime<Utc>,
70 /// Creator's username (joined from users).
71 pub username: Username,
72 /// Number of public items in this project.
73 pub item_count: i64,
74 /// Which kind of match this row is. See [`DbDiscoverItemRow::match_tier`].
75 pub match_tier: Option<i16>,
76 /// See [`DbDiscoverItemRow::matched_terms`].
77 pub matched_terms: Option<i32>,
78 /// See [`DbDiscoverItemRow::query_terms`].
79 pub query_terms: Option<i32>,
80 /// Rank within the row's own tier (set when searching, `None` otherwise).
81 pub match_score: Option<f32>,
82 /// Category name (joined from project_categories), or NULL if uncategorized.
83 pub category_name: Option<String>,
84 /// Category slug (joined from project_categories), or NULL if uncategorized.
85 pub category_slug: Option<String>,
86 }
87
88 /// An item_type value paired with the number of matching items.
89 #[derive(Debug, Clone, FromRow)]
90 pub struct DbItemTypeCount {
91 /// The item_type category value.
92 pub category: String,
93 /// Number of matching items of this type.
94 pub count: i64,
95 }
96
97 /// A user-defined external link shown on their profile.
98 #[derive(Debug, Clone, FromRow, Serialize)]
99 pub struct DbCustomLink {
100 pub id: CustomLinkId,
101 pub user_id: UserId,
102 pub url: String,
103 pub title: String,
104 /// Optional description shown below the title.
105 pub description: Option<String>,
106 /// Position in the user's link list.
107 pub sort_order: i32,
108 pub created_at: DateTime<Utc>,
109 pub updated_at: DateTime<Utc>,
110 }
111