Files
PlantGuide/PlantGuide/Data/DataSources/Remote/TrefleAPI/DTOs/TrefleDTOs.swift
Trey t 136dfbae33 Add PlantGuide iOS app with plant identification and care management
- Implement camera capture and plant identification workflow
- Add Core Data persistence for plants, care schedules, and cached API data
- Create collection view with grid/list layouts and filtering
- Build plant detail views with care information display
- Integrate Trefle botanical API for plant care data
- Add local image storage for captured plant photos
- Implement dependency injection container for testability
- Include accessibility support throughout the app

Bug fixes in this commit:
- Fix Trefle API decoding by removing duplicate CodingKeys
- Fix LocalCachedImage to load from correct PlantImages directory
- Set dateAdded when saving plants for proper collection sorting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 12:18:01 -06:00

336 lines
11 KiB
Swift

//
// TrefleDTOs.swift
// PlantGuide
//
// Created on 2026-01-21.
//
import Foundation
// MARK: - TrefleSearchResponseDTO
/// The root response object from the Trefle plant search API.
///
/// This DTO represents the complete response from the `/api/v1/plants/search` endpoint,
/// including search results, pagination links, and metadata.
struct TrefleSearchResponseDTO: Decodable, Sendable {
/// The list of plant summaries matching the search query.
let data: [TreflePlantSummaryDTO]
/// Pagination links for navigating through search results.
let links: TrefleLinksDTO
/// Metadata about the search results, including total count.
let meta: TrefleMetaDTO
}
// MARK: - TrefleSpeciesResponseDTO
/// The root response object for a single species from the Trefle API.
///
/// This DTO represents the complete response from the `/api/v1/species/{id}` endpoint,
/// containing detailed species information and metadata.
struct TrefleSpeciesResponseDTO: Decodable, Sendable {
/// The detailed species information.
let data: TrefleSpeciesDTO
/// Metadata about the response.
let meta: TrefleMetaDTO
}
// MARK: - TreflePlantSummaryDTO
/// Represents basic plant information returned from a Trefle search query.
///
/// This DTO contains summarized plant data suitable for displaying in search results
/// or lists, with links to more detailed species information.
struct TreflePlantSummaryDTO: Decodable, Sendable {
/// The unique identifier for this plant in the Trefle database.
let id: Int
/// The common name for this plant (e.g., "European Oak").
/// May be nil if no common name is available.
let commonName: String?
/// The URL-friendly slug for this plant (e.g., "quercus-robur").
let slug: String
/// The scientific name for this plant (e.g., "Quercus robur").
let scientificName: String
/// The family name for this plant (e.g., "Fagaceae").
/// May be nil if family information is not available.
let family: String?
/// The genus name for this plant (e.g., "Quercus").
/// May be nil if genus information is not available.
let genus: String?
/// The URL to the primary image for this plant.
/// May be nil if no image is available.
let imageUrl: String?
}
// MARK: - TrefleSpeciesDTO
/// Represents detailed species information from the Trefle API.
///
/// This DTO contains comprehensive plant data including taxonomic details,
/// images, growth requirements, and physical specifications.
struct TrefleSpeciesDTO: Decodable, Sendable {
/// The unique identifier for this species in the Trefle database.
let id: Int
/// The common name for this species (e.g., "European Oak").
/// May be nil if no common name is available.
let commonName: String?
/// The URL-friendly slug for this species (e.g., "quercus-robur").
let slug: String
/// The scientific name for this species (e.g., "Quercus robur").
let scientificName: String
/// The year this species was first formally described.
/// May be nil if the year is not known.
let year: Int?
/// The bibliographic reference for the original species description.
/// May be nil if not available.
let bibliography: String?
/// The author who first described this species (e.g., "L." for Linnaeus).
/// May be nil if not available.
let author: String?
/// The common name of the plant family (e.g., "Beech family").
/// May be nil if not available.
let familyCommonName: String?
/// The scientific family name (e.g., "Fagaceae").
/// May be nil if not available.
let family: String?
/// The genus name (e.g., "Quercus").
/// May be nil if not available.
let genus: String?
/// The unique identifier for the genus in the Trefle database.
/// May be nil if not available.
let genusId: Int?
/// The URL to the primary image for this species.
/// May be nil if no image is available.
let imageUrl: String?
/// Categorized images of different plant parts.
/// May be nil if no images are available.
let images: TrefleImagesDTO?
/// Physical specifications and characteristics of this species.
/// May be nil if specifications are not available.
let specifications: TrefleSpecificationsDTO?
/// Growth requirements and seasonal information for this species.
/// May be nil if growth data is not available.
let growth: TrefleGrowthDTO?
}
// MARK: - TrefleGrowthDTO
/// Represents growth requirements and seasonal information for a plant species.
///
/// This DTO contains detailed environmental preferences and growing conditions,
/// including light, humidity, temperature ranges, and seasonal activity.
struct TrefleGrowthDTO: Decodable, Sendable {
/// Light requirement on a scale of 0-10 (0 = full shade, 10 = full sun).
/// May be nil if not available.
let light: Int?
/// Atmospheric humidity requirement on a scale of 0-10.
/// May be nil if not available.
let atmosphericHumidity: Int?
/// Months during which the plant actively grows (e.g., ["mar", "apr", "may"]).
/// May be nil if not available.
let growthMonths: [String]?
/// Months during which the plant blooms (e.g., ["apr", "may"]).
/// May be nil if not available.
let bloomMonths: [String]?
/// Months during which the plant produces fruit (e.g., ["sep", "oct"]).
/// May be nil if not available.
let fruitMonths: [String]?
/// The minimum precipitation requirement for this species.
/// May be nil if not available.
let minimumPrecipitation: TrefleMeasurementDTO?
/// The maximum precipitation tolerance for this species.
/// May be nil if not available.
let maximumPrecipitation: TrefleMeasurementDTO?
/// The minimum temperature tolerance for this species.
/// May be nil if not available.
let minimumTemperature: TrefleMeasurementDTO?
/// The maximum temperature tolerance for this species.
/// May be nil if not available.
let maximumTemperature: TrefleMeasurementDTO?
/// Soil nutrient requirement on a scale of 0-10 (0 = low, 10 = high).
/// May be nil if not available.
let soilNutriments: Int?
/// Soil humidity requirement on a scale of 0-10 (0 = dry, 10 = wet).
/// May be nil if not available.
let soilHumidity: Int?
/// The minimum soil pH tolerance for this species.
/// May be nil if not available.
let phMinimum: Double?
/// The maximum soil pH tolerance for this species.
/// May be nil if not available.
let phMaximum: Double?
}
// MARK: - TrefleSpecificationsDTO
/// Represents physical specifications and characteristics of a plant species.
///
/// This DTO contains information about growth rate, toxicity, and size dimensions.
struct TrefleSpecificationsDTO: Decodable, Sendable {
/// The growth rate classification (e.g., "slow", "moderate", "rapid").
/// May be nil if not available.
let growthRate: String?
/// Toxicity information (e.g., "none", "low", "medium", "high").
/// May be nil if not available.
let toxicity: String?
/// The average height of mature plants.
/// May be nil if not available.
let averageHeight: TrefleMeasurementDTO?
/// The maximum height of mature plants.
/// May be nil if not available.
let maximumHeight: TrefleMeasurementDTO?
}
// MARK: - TrefleMeasurementDTO
/// Represents a measurement value with various unit representations.
///
/// This DTO contains the same measurement expressed in different units,
/// supporting heights (cm), precipitation (mm), and temperatures (Celsius/Fahrenheit).
struct TrefleMeasurementDTO: Decodable, Sendable {
/// The measurement in centimeters (used for heights).
/// May be nil if not applicable.
let cm: Double?
/// The measurement in millimeters (used for precipitation).
/// May be nil if not applicable.
let mm: Double?
/// The measurement in degrees Celsius (used for temperatures).
/// May be nil if not applicable.
let degC: Double?
/// The measurement in degrees Fahrenheit (used for temperatures).
/// May be nil if not applicable.
let degF: Double?
}
// MARK: - TrefleImagesDTO
/// Represents categorized images of different plant parts.
///
/// This DTO organizes plant images by the part of the plant they depict,
/// making it easy to find specific types of reference images.
struct TrefleImagesDTO: Decodable, Sendable {
/// Images of the plant's flowers.
/// May be nil or empty if no flower images are available.
let flower: [TrefleImageDTO]?
/// Images of the plant's leaves.
/// May be nil or empty if no leaf images are available.
let leaf: [TrefleImageDTO]?
/// Images of the plant's bark.
/// May be nil or empty if no bark images are available.
let bark: [TrefleImageDTO]?
/// Images of the plant's fruit.
/// May be nil or empty if no fruit images are available.
let fruit: [TrefleImageDTO]?
/// Images of the plant's overall habit/form.
/// May be nil or empty if no habit images are available.
let habit: [TrefleImageDTO]?
}
// MARK: - TrefleImageDTO
/// Represents a single plant image from the Trefle database.
struct TrefleImageDTO: Decodable, Sendable {
/// The unique identifier for this image in the Trefle database.
let id: Int
/// The URL to access this image.
let imageUrl: String
}
// MARK: - TrefleLinksDTO
/// Represents pagination links for navigating through Trefle API results.
///
/// This DTO contains URLs for traversing paginated search results,
/// following the HATEOAS pattern for RESTful APIs.
struct TrefleLinksDTO: Decodable, Sendable {
/// The URL for the current page of results.
/// Note: Maps from "self" in JSON (reserved keyword in Swift).
let selfLink: String
/// The URL for the first page of results.
let first: String
/// The URL for the last page of results.
/// May be nil if not available.
let last: String?
/// The URL for the next page of results.
/// May be nil if this is the last page.
let next: String?
/// The URL for the previous page of results.
/// May be nil if this is the first page.
let prev: String?
// CodingKeys required because "self" is a reserved keyword
private enum CodingKeys: String, CodingKey {
case selfLink = "self"
case first
case last
case next
case prev
}
}
// MARK: - TrefleMetaDTO
/// Represents metadata about a Trefle API response.
///
/// This DTO contains supplementary information about the response,
/// such as the total number of results or when the data was last updated.
struct TrefleMetaDTO: Decodable, Sendable {
/// The total number of results matching the query.
/// May be nil for single-resource responses.
let total: Int?
/// The timestamp when the data was last modified.
/// May be nil if not available.
let lastModified: String?
}