1use chrono::{DateTime, FixedOffset};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 auth::User,
7 entity_ref::{ExternalId, ExternalIdEntity, Id, Ref, RefTarget, Slug, SlugEntity},
8 helpers::slugify,
9 organizations::Organization,
10 EntityRefPathParam, I18nString, ImageSummary, NestedSize, NestedSizeSummary, Style,
11 StyleSummary,
12};
13use samling_clorinde::{client::GenericClient, queries::color::get_color_id};
14
15#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
17pub struct Color {
18 pub id: Id<Self>,
19 pub style: StyleSummary,
20 pub number: String,
21 pub name: I18nString,
22 pub slug: Slug<Self>,
23 pub images: Vec<ImageSummary>,
24 pub external_id: Option<ExternalId<Self>>,
25 pub created_by: Option<Id<User>>,
26 pub created_at: DateTime<FixedOffset>,
27 pub updated_at: DateTime<FixedOffset>,
28}
29
30impl EntityRefPathParam for Color {
31 fn parameter_name() -> &'static str {
32 "color_ref"
33 }
34}
35
36#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
38pub struct NestedColor {
39 pub id: Id<Color>,
40 pub number: String,
41 pub name: I18nString,
42 pub slug: Slug<Color>,
43 pub external_id: Option<ExternalId<Color>>,
44 pub images: Vec<ImageSummary>,
45 pub sizes: Vec<NestedSize>,
46 pub is_new: Option<bool>,
47}
48
49#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
51pub struct NestedColorSummary {
52 pub id: Id<Color>,
53 pub number: String,
54 pub name: I18nString,
55 pub primary_image: Option<ImageSummary>,
56 pub sizes: Vec<NestedSizeSummary>,
57}
58impl NestedColor {
59 pub(crate) fn into_summary(self) -> NestedColorSummary {
60 NestedColorSummary {
61 id: self.id,
62 number: self.number,
63 name: self.name,
64 primary_image: self.images.into_iter().next(),
65 sizes: self.sizes.into_iter().map(|c| c.into_summary()).collect(),
66 }
67 }
68
69 pub(crate) fn service_item(&self) -> bool {
70 self.sizes
71 .iter()
72 .any(|size| size.service_item == Some(true))
73 }
74
75 pub(crate) fn primary_image(&self) -> Option<&ImageSummary> {
76 self.images.first()
77 }
78}
79
80#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
82pub struct ColorSummary {
83 pub id: Id<Color>,
84 pub style: StyleSummary,
85 pub number: String,
86 pub name: I18nString,
87 pub slug: Slug<Color>,
88 pub external_id: Option<ExternalId<Color>>,
89}
90
91impl RefTarget for Color {
92 async fn lookup_id(
93 client: &impl GenericClient,
94 organization_id: Id<Organization>,
95 entity_ref: &crate::entity_ref::Ref<Self>,
96 ) -> crate::Result<Option<Id<Self>>> {
97 let (id, external_id, slug) = entity_ref.to_owned().take_all_inner();
98 Ok(get_color_id()
99 .bind(
100 client,
101 &organization_id.into(),
102 &id,
103 &external_id.as_deref(),
104 &slug.as_deref(),
105 )
106 .opt()
107 .await?
108 .map(Id::new))
109 }
110}
111
112#[derive(Debug, Deserialize)]
114pub struct CreateColor {
115 pub style: Ref<Style>,
116 pub number: String,
117 pub name: I18nString,
118 pub slug: Option<Slug<Color>>,
119 pub external_id: Option<ExternalId<Color>>,
120}
121
122impl SlugEntity for CreateColor {
123 type RefTarget = Color;
124 fn generate_slug(&self, prefix: &str) -> Option<Slug<Self::RefTarget>> {
125 Some(Slug::new(slugify(&[prefix, &self.number, &self.name.en])))
126 }
127
128 fn slug(&self) -> Option<Slug<Self::RefTarget>> {
129 self.slug.clone()
130 }
131
132 fn set_slug(&mut self, value: Slug<Self::RefTarget>) {
133 self.slug = Some(value);
134 }
135}
136
137impl ExternalIdEntity for CreateColor {
138 type RefTarget = Color;
139
140 fn external_id(&self) -> Option<ExternalId<Self::RefTarget>> {
141 self.external_id.clone()
142 }
143
144 fn set_external_id(&mut self, value: ExternalId<Self::RefTarget>) {
145 self.external_id = Some(value);
146 }
147}
148
149#[derive(Debug, Deserialize)]
151pub struct UpdateColor {
152 pub style: Option<Ref<Style>>,
153 pub number: Option<String>,
154 pub name: Option<I18nString>,
155 pub slug: Option<Slug<Color>>,
156 pub external_id: Option<ExternalId<Color>>,
157}
158
159impl From<CreateColor> for UpdateColor {
160 fn from(color: CreateColor) -> Self {
161 Self {
162 style: Some(color.style),
163 number: Some(color.number),
164 name: Some(color.name),
165 slug: color.slug,
166 external_id: color.external_id,
167 }
168 }
169}
170
171impl SlugEntity for UpdateColor {
172 type RefTarget = Color;
173
174 fn slug(&self) -> Option<Slug<Self::RefTarget>> {
175 self.slug.clone()
176 }
177
178 fn set_slug(&mut self, value: Slug<Self::RefTarget>) {
179 self.slug = Some(value);
180 }
181}
182
183impl ExternalIdEntity for UpdateColor {
184 type RefTarget = Color;
185
186 fn external_id(&self) -> Option<ExternalId<Self::RefTarget>> {
187 self.external_id.clone()
188 }
189
190 fn set_external_id(&mut self, value: ExternalId<Self::RefTarget>) {
191 self.external_id = Some(value);
192 }
193}