* Validate status configuration
(statuses: StatusConfig[])
| 184 | * Validate status configuration |
| 185 | */ |
| 186 | static validateStatuses(statuses: StatusConfig[]): { valid: boolean; errors: string[] } { |
| 187 | const errors: string[] = []; |
| 188 | |
| 189 | // Minimum 2 statuses required |
| 190 | if (statuses.length < 2) { |
| 191 | errors.push("At least 2 statuses are required"); |
| 192 | } |
| 193 | |
| 194 | // At least one completed status required |
| 195 | const hasCompletedStatus = statuses.some((s) => s.isCompleted); |
| 196 | if (!hasCompletedStatus) { |
| 197 | errors.push("At least one status must be marked as completed"); |
| 198 | } |
| 199 | |
| 200 | // Check for unique status values |
| 201 | const values = statuses.map((s) => s.value); |
| 202 | const uniqueValues = new Set(values); |
| 203 | if (values.length !== uniqueValues.size) { |
| 204 | errors.push("Status values must be unique"); |
| 205 | } |
| 206 | |
| 207 | // Check for unique IDs |
| 208 | const ids = statuses.map((s) => s.id); |
| 209 | const uniqueIds = new Set(ids); |
| 210 | if (ids.length !== uniqueIds.size) { |
| 211 | errors.push("Status IDs must be unique"); |
| 212 | } |
| 213 | |
| 214 | // Check for empty values and labels |
| 215 | for (const status of statuses) { |
| 216 | if (!status.value || status.value.trim() === "") { |
| 217 | errors.push("Status values cannot be empty"); |
| 218 | break; |
| 219 | } |
| 220 | if (!status.label || status.label.trim() === "") { |
| 221 | errors.push("Status labels cannot be empty"); |
| 222 | break; |
| 223 | } |
| 224 | if (!isSupportedColorValue(status.color)) { |
| 225 | errors.push("Status colors must be valid CSS colors or Obsidian theme colors"); |
| 226 | break; |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | return { |
| 231 | valid: errors.length === 0, |
| 232 | errors, |
| 233 | }; |
| 234 | } |
| 235 | |
| 236 | /** |
| 237 | * Generate a new unique status ID |
nothing calls this directly
no test coverage detected