1use super::{AnimalId, FormId, Method, OwnerId, Request, ReservationId, non_empty_text};
2
3#[derive(Clone, Debug, PartialEq, Eq)]
4pub struct ProviderWhereClause {
6 field: String,
7 value: String,
8}
9
10impl ProviderWhereClause {
11 pub fn new(field: impl Into<String>, value: impl Into<String>) -> Self {
13 Self {
14 field: field.into(),
15 value: value.into(),
16 }
17 }
18
19 fn parameter_pair(&self) -> (String, String) {
20 (format!("params[{}]", self.field), self.value.clone())
21 }
22}
23
24#[derive(Clone, Debug, Default, PartialEq, Eq)]
25pub struct Owners {
27 provider_where_clauses: Vec<ProviderWhereClause>,
28}
29
30impl Owners {
31 pub fn builder() -> OwnersBuilder {
33 OwnersBuilder::default()
34 }
35}
36
37#[derive(Clone, Debug, Default)]
38pub struct OwnersBuilder {
40 provider_where_clauses: Vec<ProviderWhereClause>,
41}
42
43impl OwnersBuilder {
44 pub fn provider_where_clause(mut self, clause: ProviderWhereClause) -> Self {
46 self.provider_where_clauses.push(clause);
47 self
48 }
49
50 pub fn build(self) -> Owners {
52 Owners {
53 provider_where_clauses: self.provider_where_clauses,
54 }
55 }
56}
57
58impl Request for Owners {
59 fn method(&self) -> Method {
60 Method::Get
61 }
62
63 fn path(&self) -> &'static str {
64 "/api/v1/owners"
65 }
66
67 fn parameters(&self) -> Vec<(String, String)> {
68 self.provider_where_clauses
69 .iter()
70 .map(ProviderWhereClause::parameter_pair)
71 .collect()
72 }
73}
74
75#[derive(Clone, Debug, Default, PartialEq, Eq)]
76pub struct Animals {
78 provider_where_clauses: Vec<ProviderWhereClause>,
79}
80
81impl Animals {
82 pub fn builder() -> AnimalsBuilder {
84 AnimalsBuilder::default()
85 }
86}
87
88#[derive(Clone, Debug, Default)]
89pub struct AnimalsBuilder {
91 provider_where_clauses: Vec<ProviderWhereClause>,
92}
93
94impl AnimalsBuilder {
95 pub fn provider_where_clause(mut self, clause: ProviderWhereClause) -> Self {
97 self.provider_where_clauses.push(clause);
98 self
99 }
100
101 pub fn build(self) -> Animals {
103 Animals {
104 provider_where_clauses: self.provider_where_clauses,
105 }
106 }
107}
108
109impl Request for Animals {
110 fn method(&self) -> Method {
111 Method::Get
112 }
113
114 fn path(&self) -> &'static str {
115 "/api/v1/animals"
116 }
117
118 fn parameters(&self) -> Vec<(String, String)> {
119 self.provider_where_clauses
120 .iter()
121 .map(ProviderWhereClause::parameter_pair)
122 .collect()
123 }
124}
125
126#[derive(Clone, Debug, PartialEq, Eq)]
127pub struct SensitiveLookup(String);
129
130impl SensitiveLookup {
131 pub fn new(value: impl Into<String>) -> super::Result<Self> {
133 Ok(Self(non_empty_text(value)?))
134 }
135
136 fn as_str(&self) -> &str {
137 &self.0
138 }
139}
140
141#[derive(Clone, Debug, PartialEq, Eq)]
142pub enum OwnerLookup {
144 OwnerId(OwnerId),
146 AnimalId(AnimalId),
148 ReservationId(ReservationId),
150 Phone(SensitiveLookup),
152 Email(SensitiveLookup),
154}
155
156#[derive(Clone, Debug, PartialEq, Eq)]
157pub struct Owner {
159 lookup: OwnerLookup,
160}
161
162impl Owner {
163 pub fn by_id(id: OwnerId) -> Self {
165 Self {
166 lookup: OwnerLookup::OwnerId(id),
167 }
168 }
169
170 pub fn by_animal(id: AnimalId) -> Self {
172 Self {
173 lookup: OwnerLookup::AnimalId(id),
174 }
175 }
176
177 pub fn by_reservation(id: ReservationId) -> Self {
179 Self {
180 lookup: OwnerLookup::ReservationId(id),
181 }
182 }
183
184 pub fn by_phone(phone: SensitiveLookup) -> Self {
186 Self {
187 lookup: OwnerLookup::Phone(phone),
188 }
189 }
190
191 pub fn by_email(email: SensitiveLookup) -> Self {
193 Self {
194 lookup: OwnerLookup::Email(email),
195 }
196 }
197}
198
199impl Request for Owner {
200 fn method(&self) -> Method {
201 Method::Get
202 }
203
204 fn path(&self) -> &'static str {
205 "/api/v1/owner"
206 }
207
208 fn parameters(&self) -> Vec<(String, String)> {
209 match &self.lookup {
210 OwnerLookup::OwnerId(id) => vec![("id".to_owned(), id.to_string())],
211 OwnerLookup::AnimalId(id) => vec![("animal_id".to_owned(), id.to_string())],
212 OwnerLookup::ReservationId(id) => vec![("reservation_id".to_owned(), id.to_string())],
213 OwnerLookup::Phone(phone) => vec![("phone".to_owned(), phone.as_str().to_owned())],
214 OwnerLookup::Email(email) => vec![("email".to_owned(), email.as_str().to_owned())],
215 }
216 }
217
218 fn sensitive_parameter_names(&self) -> &'static [&'static str] {
219 match self.lookup {
220 OwnerLookup::Phone(_) => &["phone"],
221 OwnerLookup::Email(_) => &["email"],
222 _ => &[],
223 }
224 }
225}
226
227#[derive(Clone, Copy, Debug, PartialEq, Eq)]
228pub enum FormKind {
230 Owner,
232 Animal,
234}
235
236impl FormKind {
237 pub const fn form_id(self) -> FormId {
239 match self {
240 Self::Owner => FormId::new(1),
241 Self::Animal => FormId::new(2),
242 }
243 }
244}
245
246impl core::fmt::Display for FormKind {
247 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
248 let value = match self {
249 Self::Owner => "owner_form",
250 Self::Animal => "animal_form",
251 };
252 formatter.write_str(value)
253 }
254}
255
256#[derive(Clone, Debug, PartialEq, Eq)]
257pub struct Form {
259 kind: FormKind,
260}
261
262impl Form {
263 pub const fn new(kind: FormKind) -> Self {
265 Self { kind }
266 }
267}
268
269impl Request for Form {
270 fn method(&self) -> Method {
271 Method::Get
272 }
273
274 fn path(&self) -> &'static str {
275 "/forms/get_form"
276 }
277
278 fn parameters(&self) -> Vec<(String, String)> {
279 vec![("form".to_owned(), self.kind.to_string())]
280 }
281}
282
283pub mod custom_field {
285 use super::*;
286
287 #[derive(Clone, Debug, PartialEq, Eq)]
288 pub struct Name(String);
290
291 impl Name {
292 pub fn new(value: impl Into<String>) -> super::super::Result<Self> {
294 Ok(Self(non_empty_text(value)?))
295 }
296 }
297
298 #[derive(Clone, Debug, PartialEq, Eq)]
299 pub struct Search {
301 form: FormKind,
302 field_name: Name,
303 search: SensitiveLookup,
304 }
305
306 impl Search {
307 pub fn builder() -> SearchBuilder {
309 SearchBuilder::default()
310 }
311 }
312
313 #[derive(Clone, Debug, Default)]
314 pub struct SearchBuilder {
316 form: Option<FormKind>,
317 field_name: Option<Name>,
318 search: Option<SensitiveLookup>,
319 }
320
321 impl SearchBuilder {
322 pub fn form(mut self, form: FormKind) -> Self {
324 self.form = Some(form);
325 self
326 }
327
328 pub fn field_name(mut self, field_name: Name) -> Self {
330 self.field_name = Some(field_name);
331 self
332 }
333
334 pub fn search(mut self, search: SensitiveLookup) -> Self {
336 self.search = Some(search);
337 self
338 }
339
340 pub fn build(self) -> Search {
342 Search {
343 form: self.form.expect("Search requires form"),
344 field_name: self.field_name.expect("Search requires field_name"),
345 search: self.search.expect("Search requires search"),
346 }
347 }
348 }
349
350 impl Request for Search {
351 fn method(&self) -> Method {
352 Method::Get
353 }
354
355 fn path(&self) -> &'static str {
356 "/api/v1/custom_field_search"
357 }
358
359 fn parameters(&self) -> Vec<(String, String)> {
360 vec![
361 ("form_id".to_owned(), self.form.form_id().to_string()),
362 ("field_name".to_owned(), self.field_name.0.clone()),
363 ("search".to_owned(), self.search.as_str().to_owned()),
364 ]
365 }
366
367 fn sensitive_parameter_names(&self) -> &'static [&'static str] {
368 &["search"]
369 }
370 }
371}
372
373#[derive(Clone, Debug, PartialEq, Eq)]
374pub struct AnimalCareInfo {
376 path: &'static str,
377 animal_id: AnimalId,
378}
379
380impl AnimalCareInfo {
381 pub fn feeding(animal_id: AnimalId) -> Self {
383 Self {
384 path: "/api/v1/get_feeding_info",
385 animal_id,
386 }
387 }
388
389 pub fn medication(animal_id: AnimalId) -> Self {
391 Self {
392 path: "/api/v1/get_medication_info",
393 animal_id,
394 }
395 }
396}
397
398impl Request for AnimalCareInfo {
399 fn method(&self) -> Method {
400 Method::Get
401 }
402
403 fn path(&self) -> &'static str {
404 self.path
405 }
406
407 fn parameters(&self) -> Vec<(String, String)> {
408 vec![("animal_id".to_owned(), self.animal_id.to_string())]
409 }
410}