reinhardt_admin/types/models.rs
1//! Model information types
2
3use serde::{Deserialize, Serialize};
4
5/// Model information for dashboard
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct ModelInfo {
8 /// Model name
9 pub name: String,
10 /// List URL
11 pub list_url: String,
12}
13
14/// Field metadata for dynamic form generation
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct FieldInfo {
17 /// Field name (e.g., "username", "email")
18 pub name: String,
19 /// Display label (e.g., "Username", "Email Address")
20 pub label: String,
21 /// Field type
22 pub field_type: FieldType,
23 /// Whether the field is required
24 pub required: bool,
25 /// Whether the field is readonly
26 pub readonly: bool,
27 /// Help text displayed below the field
28 pub help_text: Option<String>,
29 /// Placeholder text for input
30 pub placeholder: Option<String>,
31}
32
33/// Field type for form rendering
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35#[serde(tag = "type", content = "options")]
36pub enum FieldType {
37 /// Text input (single line)
38 Text,
39 /// Textarea (multi-line)
40 TextArea,
41 /// Number input
42 Number,
43 /// Boolean checkbox
44 Boolean,
45 /// Email input
46 Email,
47 /// Date input
48 Date,
49 /// DateTime input
50 DateTime,
51 /// Select dropdown with choices.
52 Select {
53 /// Available choices as `(value, label)` pairs.
54 choices: Vec<(String, String)>,
55 },
56 /// Multiple select.
57 MultiSelect {
58 /// Available choices as `(value, label)` pairs.
59 choices: Vec<(String, String)>,
60 },
61 /// File upload
62 File,
63 /// Hidden field
64 Hidden,
65}
66
67/// Rendering specification for a form field.
68///
69/// This type preserves the structural information needed to emit the
70/// correct HTML element (e.g., `<input>`, `<textarea>`, `<select>`),
71/// along with any choices required for `<select>` options. It is derived
72/// from `FieldType` via `From<&FieldType>`.
73#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
74#[serde(tag = "kind", content = "data")]
75pub enum FormFieldSpec {
76 /// Plain `<input>` element with the given HTML `type` attribute.
77 Input {
78 /// Value for the HTML `type` attribute (e.g., "text", "email",
79 /// "number", "checkbox", "date", "datetime-local").
80 ///
81 /// Owned `String` (not `&'static str`) so the variant can round-trip
82 /// through `serde` deserialization at API boundaries — borrowed
83 /// `'static` strings cannot be reconstructed from incoming JSON.
84 html_type: String,
85 },
86 /// `<textarea>` element for multi-line text.
87 TextArea,
88 /// `<select>` dropdown with the given `(value, label)` choices.
89 Select {
90 /// Available choices as `(value, label)` pairs.
91 choices: Vec<(String, String)>,
92 },
93 /// `<select multiple>` dropdown with the given `(value, label)` choices.
94 MultiSelect {
95 /// Available choices as `(value, label)` pairs.
96 choices: Vec<(String, String)>,
97 },
98 /// `<input type="file">` for file uploads.
99 File,
100 /// `<input type="hidden">` for hidden values.
101 Hidden,
102}
103
104impl From<&FieldType> for FormFieldSpec {
105 fn from(field_type: &FieldType) -> Self {
106 match field_type {
107 FieldType::Text => FormFieldSpec::Input {
108 html_type: "text".to_string(),
109 },
110 FieldType::Number => FormFieldSpec::Input {
111 html_type: "number".to_string(),
112 },
113 FieldType::Boolean => FormFieldSpec::Input {
114 html_type: "checkbox".to_string(),
115 },
116 FieldType::Email => FormFieldSpec::Input {
117 html_type: "email".to_string(),
118 },
119 FieldType::Date => FormFieldSpec::Input {
120 html_type: "date".to_string(),
121 },
122 FieldType::DateTime => FormFieldSpec::Input {
123 html_type: "datetime-local".to_string(),
124 },
125 FieldType::TextArea => FormFieldSpec::TextArea,
126 FieldType::Select { choices } => FormFieldSpec::Select {
127 choices: choices.clone(),
128 },
129 FieldType::MultiSelect { choices } => FormFieldSpec::MultiSelect {
130 choices: choices.clone(),
131 },
132 FieldType::File => FormFieldSpec::File,
133 FieldType::Hidden => FormFieldSpec::Hidden,
134 }
135 }
136}
137
138/// Filter type for UI rendering
139#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
140#[serde(tag = "type", content = "options")]
141pub enum FilterType {
142 /// Boolean filter (Yes/No checkbox)
143 Boolean,
144 /// Choice filter (dropdown with predefined options).
145 Choice {
146 /// Available filter choices.
147 choices: Vec<FilterChoice>,
148 },
149 /// Date range filter (predefined ranges like "Today", "Last 7 days").
150 DateRange {
151 /// Available date range options.
152 ranges: Vec<FilterChoice>,
153 },
154 /// Number range filter (predefined ranges).
155 NumberRange {
156 /// Available number range options.
157 ranges: Vec<FilterChoice>,
158 },
159}
160
161/// Filter choice for Choice/DateRange/NumberRange filters
162#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
163pub struct FilterChoice {
164 /// Value to send to API
165 pub value: String,
166 /// Display label for UI
167 pub label: String,
168}
169
170/// Filter metadata sent from backend to frontend
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct FilterInfo {
173 /// Field name (e.g., "status", "is_active")
174 pub field: String,
175 /// Display title (e.g., "Status", "Active")
176 pub title: String,
177 /// Filter type and options
178 pub filter_type: FilterType,
179 /// Current value (if filter is active)
180 pub current_value: Option<String>,
181}
182
183/// Column metadata for list view display
184#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct ColumnInfo {
186 /// Field name to extract from data
187 pub field: String,
188 /// Display label for column header
189 pub label: String,
190 /// Whether column is sortable
191 pub sortable: bool,
192}