@la-main-verte/shared-types 1.0.74 → 1.0.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@la-main-verte/shared-types",
3
- "version": "1.0.74",
3
+ "version": "1.0.77",
4
4
  "description": "Shared TypeScript interfaces for frontend of la-main-verte app",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
package/src/apiError.d.ts CHANGED
@@ -1,28 +1,49 @@
1
- export interface ApiErrorI {
2
- /**
3
- * Literally describe what the server error is, ideally in the language of the user
4
- */
5
- error_message?: string
6
- /**
7
- * A string code to identify the error
8
- */
9
- error_type?:
1
+ /**
2
+ * Standard API Response Types
3
+ * ------------------------------------------------------------------------------------------------
4
+ * These types define the standard shapes for all API responses.
5
+ * The frontend uses these to display toast notifications:
6
+ * - Error responses: error_message → toast title, error_suggestion → toast subtitle
7
+ * - Success responses: message toast title, suggestion → toast subtitle
8
+ * ------------------------------------------------------------------------------------------------
9
+ */
10
+
11
+ /**
12
+ * Standard error response returned by apiResponse.helper functions.
13
+ * The frontend shows error_message and error_suggestion in a toast.error().
14
+ */
15
+ export interface ErrorApiResponseI {
16
+ error_code: number | string
17
+ error_type:
10
18
  | 'not_identified'
11
19
  | 'invalid_request'
12
20
  | 'subscription_required'
21
+ | 'not_authorized'
13
22
  | 'internal_server_error'
14
23
  | 'resource_already_exists'
15
24
  | 'not_found'
16
25
  | 'app_update_required'
26
+ | 'sequelize_validation_error'
17
27
  | string
18
- /**
19
- * A numerical code that can be used to identify the error
20
- * Ex: 401, 403, 404, 500 or L12, L13, L14
21
- */
22
- error_code?: string | number
23
- /**
24
- * A string that can be used to suggest a solution to the user
25
- * Ex: "Please check your internet connection and try again."
26
- */
27
- error_suggestion?: string
28
+ /** Describes the error, ideally in the user's language. Displayed as the toast title. */
29
+ error_message: string
30
+ /** Suggests a resolution to the user. Displayed as the toast subtitle. */
31
+ error_suggestion: string
28
32
  }
33
+
34
+ /**
35
+ * Standard success response shape for endpoints that return a confirmation with an optional message.
36
+ * The frontend shows message and suggestion in a toast.success() when present.
37
+ */
38
+ export interface SuccessApiResponseI {
39
+ success: true
40
+ /** Contextual message to display (e.g. "Félicitation !"). Displayed as the toast title. */
41
+ message?: string
42
+ /** Additional detail shown alongside message (e.g. next task info). Displayed as the toast subtitle. */
43
+ suggestion?: string
44
+ /** Optional icon name for the frontend to render alongside the message. */
45
+ iconName?: string
46
+ }
47
+
48
+ /** @deprecated Use ErrorApiResponseI instead */
49
+ export type ApiErrorI = ErrorApiResponseI
@@ -1,143 +1,214 @@
1
- import type { FertilizerI } from './fertilizer'
2
- import type { PlantSelectionI } from './plantSelection'
3
-
4
- /**
5
- * Viewport corners with x/y coordinates
6
- * Used by front-end to describe the visible area of the map
7
- */
8
- export interface ViewportCornersI {
9
- topLeft: { x: number; y: number } | null
10
- topRight: { x: number; y: number } | null
11
- bottomLeft: { x: number; y: number } | null
12
- bottomRight: { x: number; y: number } | null
13
- }
14
-
15
- /**
16
- * Viewport as min/max boundaries
17
- * Used by back-end placement logic for collision detection
18
- */
19
- export interface ViewportBoundariesI {
20
- minX: number
21
- minY: number
22
- maxX: number
23
- maxY: number
24
- }
25
-
26
- /**
27
- * Available garden map categories across the platform
28
- */
29
- export type GardenMapCategory =
30
- | 'community_garden'
31
- | 'greenhouse'
32
- | 'garden'
33
- | 'recipe'
34
- | 'favorites'
35
- | 'indoor_garden'
36
- | 'balcony'
37
- | 'inventory'
38
- | 'others'
39
-
40
- /**
41
- * A gardenMap is a collection of garden zones
42
- */
43
- export interface GardenMapI {
44
- id: number
45
- name: string
46
- icon_name: string
47
- category: GardenMapCategory
48
- default: boolean
49
- memberId: number
50
- width_in_units: number
51
- height_in_units: number
52
- createdAt: string
53
- Selections: SelectionI[]
54
- GardenZones: GardenZoneI[]
55
- imageURL: string
56
- }
57
-
58
- export interface GardenZoneI {
59
- id: number
60
- name: string | null
61
- gardenMapId: number
62
- widthInMeters: number
63
- heightInMeters: number
64
- diameterInMeters: number
65
- shape: 'rectangle' | 'circle'
66
- xPosition: number
67
- yPosition: number
68
- zIndex: number
69
- order: number
70
- /**
71
- * When set, the zone is shown only for that year.
72
- * Null means the zone is timeless (visible for every year).
73
- */
74
- yearOfCulture: number | null
75
- totalSurfaceInSquareMeters: number
76
- totalSurfaceInSquareFeet: number
77
- backgroundColor: string
78
- createdAt: Date
79
- updatedAt: Date
80
- /**
81
- * When set, the garden zone is a subdivision of another garden zone
82
- * Parent zones are meant to be as eternal as possible.
83
- * Subdivisions are meant to be created and destroyed on a yearly basis.
84
- */
85
- parent_garden_zone_id: number
86
- /**
87
- * Virtual field to check if the garden zone is a subdivision
88
- * It is a renamed field from parent_garden_zone_id
89
- */
90
- is_subdivision: boolean
91
- has_subdivisions: boolean
92
- timeless: boolean
93
- /**
94
- * Orientation virtual field ONLY USE FOR RECTANGLES
95
- * --------------------------------
96
- * Disregard if the shape is a circle or square. It will return 'vertical'
97
- */
98
- orientation: 'horizontal' | 'vertical'
99
- /**
100
- * NOT USED BY THE FRONTEND YET - Use GardenZoneCulture instead
101
- */
102
- GardenZoneCultures?: GardenZoneCultureI[]
103
- /**
104
- * The culture on the GardenZone
105
- */
106
- GardenZoneCulture?: GardenZoneCultureI
107
- rotationSuggestion?: string
108
- }
109
-
110
- export interface GardenZoneCultureI {
111
- id: number
112
- gardenZoneId: number
113
- plantSelectionId: number
114
- seedQuantity: number
115
- densityMode: 'dense' | 'sparse' | 'custom'
116
- fertilizerId: number
117
- /**
118
- * The year of the culture - do not use it yet.
119
- * @deprecated Potentially a mistake to have this field here
120
- */
121
- yearOfCulture: number
122
- PlantSelection?: PlantSelectionI
123
- /**
124
- * The number of alleys
125
- * --------------------------------
126
- * Value is computed by the backend and NOT coming from the DB.
127
- */
128
- numberOfAlleys?: number
129
- /**
130
- * The number of seeds per alley
131
- * --------------------------------
132
- * Value is computed by the backend and NOT coming from the DB.
133
- */
134
- numberOfSeedsPerAlley?: number
135
- Fertilizer?: FertilizerI
136
- custom_space_between_seeds_in_cm?: number
137
- custom_space_between_alley_in_cm?: number
138
- }
139
-
140
- export type UpdateGardenZonePayload = Partial<GardenZoneI> &
141
- Partial<GardenZoneCultureI> & {
142
- targetNumberOfPlants?: number
143
- }
1
+ import type { FertilizerI } from './fertilizer'
2
+ import type { PlantSelectionI } from './plantSelection'
3
+
4
+ /**
5
+ * Viewport corners with x/y coordinates
6
+ * Used by front-end to describe the visible area of the map
7
+ */
8
+ export interface ViewportCornersI {
9
+ topLeft: { x: number; y: number } | null
10
+ topRight: { x: number; y: number } | null
11
+ bottomLeft: { x: number; y: number } | null
12
+ bottomRight: { x: number; y: number } | null
13
+ }
14
+
15
+ /**
16
+ * Viewport as min/max boundaries
17
+ * Used by back-end placement logic for collision detection
18
+ */
19
+ export interface ViewportBoundariesI {
20
+ minX: number
21
+ minY: number
22
+ maxX: number
23
+ maxY: number
24
+ }
25
+
26
+ /**
27
+ * Available garden map categories across the platform
28
+ */
29
+ export type GardenMapCategory =
30
+ | 'community_garden'
31
+ | 'greenhouse'
32
+ | 'garden'
33
+ | 'recipe'
34
+ | 'favorites'
35
+ | 'indoor_garden'
36
+ | 'balcony'
37
+ | 'inventory'
38
+ | 'others'
39
+
40
+ /**
41
+ * A gardenMap is a collection of garden zones
42
+ */
43
+ export interface GardenMapI {
44
+ id: number
45
+ name: string
46
+ icon_name: string
47
+ category: GardenMapCategory
48
+ default: boolean
49
+ memberId: number
50
+ width_in_units: number
51
+ height_in_units: number
52
+ createdAt: string
53
+ Selections: SelectionI[]
54
+ GardenZones: GardenZoneI[]
55
+ imageURL: string
56
+ }
57
+
58
+ /**
59
+ * Legacy shape values accepted by the v1 route
60
+ * (`POST /selections/:slug/gardenMap/gardenZone`).
61
+ * This legacy param must remain rectangle/circle only.
62
+ */
63
+ export type GardenZoneLegacyShape = 'rectangle' | 'circle'
64
+
65
+ /**
66
+ * Visual shape identifier stored in `geometry.properties.shape`.
67
+ */
68
+ export type GardenZoneShape = 'rectangle' | 'circle' | 'polygon'
69
+
70
+ export type GardenZoneCategory = 'cultural' | 'decorative'
71
+
72
+ /**
73
+ * Inner GeoJSON Polygon geometry (coordinates ring).
74
+ */
75
+ export interface GeoJSONPolygon {
76
+ type: 'Polygon'
77
+ coordinates: number[][][]
78
+ }
79
+
80
+ /**
81
+ * Properties stored alongside the GeoJSON Feature.
82
+ * `shape` is the canonical shape identifier.
83
+ * Shape-specific fields (center, radius, radiusX, radiusY) describe the parametric definition.
84
+ * `rotation` (degrees, clockwise) and `cornerRadius` (cm) follow GeoJSON/MapBox conventions.
85
+ * `svgPath` holds the editable SVG path string for Bézier polygon rendering.
86
+ */
87
+ export interface GeoJSONFeatureProperties {
88
+ shape: GardenZoneShape
89
+ /** Rotation in degrees, clockwise. GeoJSON convention name. */
90
+ rotation?: number
91
+ /** Corner radius in cm. MapBox convention name. */
92
+ cornerRadius?: number
93
+ /** SVG path string with Bézier curves for polygon rendering. */
94
+ svgPath?: string
95
+ /** Center point [x, y] in cm for circle/ellipse shapes. */
96
+ center?: [number, number]
97
+ /** Radius in cm for circle shapes. */
98
+ radius?: number
99
+ /** Horizontal radius in cm for ellipse shapes. */
100
+ radiusX?: number
101
+ /** Vertical radius in cm for ellipse shapes. */
102
+ radiusY?: number
103
+ }
104
+
105
+ /**
106
+ * GeoJSON Feature wrapping a Polygon geometry with shape properties.
107
+ * This is the canonical storage format for all garden zone geometries.
108
+ *
109
+ * - `properties` holds the parametric definition (shape, rotation, radii, svgPath)
110
+ * - `geometry` holds the computed polygon coordinates for calculations
111
+ *
112
+ * GeoJSON is the truth (for logic), SVG is the projection (for display and editing).
113
+ */
114
+ export interface GeoJSONFeature {
115
+ type: 'Feature'
116
+ properties: GeoJSONFeatureProperties
117
+ geometry: GeoJSONPolygon
118
+ }
119
+
120
+ export interface GardenZoneI {
121
+ id: number
122
+ name: string | null
123
+ gardenMapId: number
124
+ widthInMeters: number
125
+ heightInMeters: number
126
+ diameterInMeters: number
127
+ shape: GardenZoneShape
128
+ /**
129
+ * Virtual field — the actual visual shape derived from geometry.properties.shape,
130
+ * falling back to the DB shape column for legacy zones.
131
+ */
132
+ geometryShape: GardenZoneShape
133
+ geometry?: GeoJSONFeature | null
134
+ category: GardenZoneCategory
135
+ backgroundImage: string | null
136
+ xPosition: number
137
+ yPosition: number
138
+ zIndex: number
139
+ order: number
140
+ /**
141
+ * When set, the zone is shown only for that year.
142
+ * Null means the zone is timeless (visible for every year).
143
+ */
144
+ yearOfCulture: number | null
145
+ totalSurfaceInSquareMeters: number
146
+ totalSurfaceInSquareFeet: number
147
+ backgroundColor: string
148
+ createdAt: Date
149
+ updatedAt: Date
150
+ /**
151
+ * When set, the garden zone is a subdivision of another garden zone
152
+ * Parent zones are meant to be as eternal as possible.
153
+ * Subdivisions are meant to be created and destroyed on a yearly basis.
154
+ */
155
+ parent_garden_zone_id: number
156
+ /**
157
+ * Virtual field to check if the garden zone is a subdivision
158
+ * It is a renamed field from parent_garden_zone_id
159
+ */
160
+ is_subdivision: boolean
161
+ has_subdivisions: boolean
162
+ timeless: boolean
163
+ /**
164
+ * Orientation virtual field ONLY USE FOR RECTANGLES
165
+ * --------------------------------
166
+ * Disregard if the shape is a circle or square. It will return 'vertical'
167
+ */
168
+ orientation: 'horizontal' | 'vertical'
169
+ /**
170
+ * NOT USED BY THE FRONTEND YET - Use GardenZoneCulture instead
171
+ */
172
+ GardenZoneCultures?: GardenZoneCultureI[]
173
+ /**
174
+ * The culture on the GardenZone
175
+ */
176
+ GardenZoneCulture?: GardenZoneCultureI
177
+ rotationSuggestion?: string
178
+ category?: 'cultural' | 'decorative' | null
179
+ }
180
+
181
+ export interface GardenZoneCultureI {
182
+ id: number
183
+ gardenZoneId: number
184
+ plantSelectionId: number
185
+ seedQuantity: number
186
+ densityMode: 'dense' | 'sparse' | 'custom'
187
+ fertilizerId: number
188
+ /**
189
+ * The year of the culture - do not use it yet.
190
+ * @deprecated Potentially a mistake to have this field here
191
+ */
192
+ yearOfCulture: number
193
+ PlantSelection?: PlantSelectionI
194
+ /**
195
+ * The number of alleys
196
+ * --------------------------------
197
+ * Value is computed by the backend and NOT coming from the DB.
198
+ */
199
+ numberOfAlleys?: number
200
+ /**
201
+ * The number of seeds per alley
202
+ * --------------------------------
203
+ * Value is computed by the backend and NOT coming from the DB.
204
+ */
205
+ numberOfSeedsPerAlley?: number
206
+ Fertilizer?: FertilizerI
207
+ custom_space_between_seeds_in_cm?: number
208
+ custom_space_between_alley_in_cm?: number
209
+ }
210
+
211
+ export type UpdateGardenZonePayload = Partial<GardenZoneI> &
212
+ Partial<GardenZoneCultureI> & {
213
+ targetNumberOfPlants?: number
214
+ }
@@ -1,79 +1,87 @@
1
- /**
2
- * Garden Overview Types
3
- * Represents the detailed overview of a garden selection
4
- */
5
- import { PlantI } from './plant'
6
-
7
- export interface GardenOverviewI {
8
- id: number
9
- title: string
10
- iconName: string
11
- yearOfCulture: number
12
- statistics: GardenOverviewStatsI
13
- }
14
-
15
- export interface GardenOverviewStatsI {
16
- totalSeeds: number
17
- totalSurface: string
18
- totalSurfaceWithoutCulture: string
19
- surfaceComparisonMessage: string | null
20
- familyDistribution: FamilyStatsI[]
21
- fertilization: FertilizationStatsI
22
- zones: GardenOverviewZoneStatsI[]
23
- }
24
-
25
- export interface FertilizationStatsI {
26
- totalWeightInKg: number
27
- weightComparisonMessage: string | null
28
- fertilizerDetails: FertilizerStatsI[]
29
- }
30
-
31
- export interface FertilizerStatsI {
32
- fertilizerName: string
33
- fertilizerQuantity: string
34
- imageURL: string
35
- }
36
-
37
- export interface FamilyStatsI {
38
- family: string
39
- hexColor: string
40
- totalSeeds: number
41
- totalSurface: string
42
- percentage: number
43
- plants: GardenOverviewPlantStatsI[]
44
- }
45
-
46
- /**
47
- * Extended PlantI with overview-specific statistics
48
- * Contains the full plant data plus surface, seedQuantity, and position
49
- */
50
- export interface GardenOverviewPlantStatsI extends PlantI {
51
- seedQuantity: number
52
- surface: string
53
- position: number
54
- densityMode: string
55
- fertilizerName: string
56
- fertilizerQuantity: string
57
- }
58
-
59
- export interface GardenOverviewZonePlantStatsI {
60
- id: number
61
- name: string
62
- imageURL: string | null
63
- }
64
-
65
- export interface GardenOverviewZoneFertilizerStatsI {
66
- name: string
67
- quantity: string
68
- }
69
-
70
- export interface GardenOverviewZoneStatsI {
71
- id: number
72
- name: string
73
- totalSeeds: number
74
- surface: string
75
- fertilizerQuantity: string
76
- thumbnailURL: string
77
- plants: GardenOverviewZonePlantStatsI[]
78
- fertilizers: GardenOverviewZoneFertilizerStatsI[]
79
- }
1
+ /**
2
+ * Garden Overview Types
3
+ * Represents the detailed overview of a garden selection
4
+ */
5
+ import { PlantI } from './plant'
6
+
7
+ export interface GardenOverviewI {
8
+ id: number
9
+ title: string
10
+ iconName: string
11
+ yearOfCulture: number
12
+ statistics: GardenOverviewStatsI
13
+ }
14
+
15
+ export interface GardenOverviewStatsI {
16
+ totalSeeds: number
17
+ totalSurface: string
18
+ totalSurfaceWithoutCulture: string
19
+ surfaceComparisonMessage: string | null
20
+ familyDistribution: FamilyStatsI[]
21
+ jardinVivrierComparison: GardenOverviewJardinVivrierFamilyStatsI[]
22
+ fertilization: FertilizationStatsI
23
+ zones: GardenOverviewZoneStatsI[]
24
+ }
25
+
26
+ export interface FertilizationStatsI {
27
+ totalWeightInKg: number
28
+ weightComparisonMessage: string | null
29
+ fertilizerDetails: FertilizerStatsI[]
30
+ }
31
+
32
+ export interface FertilizerStatsI {
33
+ fertilizerName: string
34
+ fertilizerQuantity: string
35
+ imageURL: string
36
+ }
37
+
38
+ export interface FamilyStatsI {
39
+ family: string
40
+ hexColor: string
41
+ totalSeeds: number
42
+ totalSurface: string
43
+ percentage: number
44
+ plants: GardenOverviewPlantStatsI[]
45
+ }
46
+
47
+ export interface GardenOverviewJardinVivrierFamilyStatsI {
48
+ family: string
49
+ parentImageURL: string | null
50
+ cultivatedQuantity: number
51
+ suggestedQuantityForFiveInJardinVivrier: number | null
52
+ }
53
+
54
+ /**
55
+ * Extended PlantI with overview-specific statistics
56
+ * Contains the full plant data plus surface, seedQuantity, and position
57
+ */
58
+ export interface GardenOverviewPlantStatsI extends PlantI {
59
+ seedQuantity: number
60
+ surface: string
61
+ position: number
62
+ densityMode: string
63
+ fertilizerName: string
64
+ fertilizerQuantity: string
65
+ }
66
+
67
+ export interface GardenOverviewZonePlantStatsI {
68
+ id: number
69
+ name: string
70
+ imageURL: string | null
71
+ }
72
+
73
+ export interface GardenOverviewZoneFertilizerStatsI {
74
+ name: string
75
+ quantity: string
76
+ }
77
+
78
+ export interface GardenOverviewZoneStatsI {
79
+ id: number
80
+ name: string
81
+ totalSeeds: number
82
+ surface: string
83
+ fertilizerQuantity: string
84
+ thumbnailURL: string
85
+ plants: GardenOverviewZonePlantStatsI[]
86
+ fertilizers: GardenOverviewZoneFertilizerStatsI[]
87
+ }
package/src/home.api.d.ts CHANGED
@@ -180,6 +180,7 @@ export namespace HOME {
180
180
  }
181
181
 
182
182
  export interface UpcomingTaskAdviceI {
183
+ /** @deprecated Since 1.9.10, this field is always `''`. */
183
184
  content: string
184
185
  taskName: string
185
186
  plantName: string
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ import * as UsersAPI from './users.api'
19
19
  import * as SessionsAPI from './sessions.api'
20
20
  import * as HomeAPI from './home.api'
21
21
  import * as PagesAPI from './pages.api'
22
+ import * as PaymentsAPI from './payments.api'
22
23
 
23
24
  // Allow access to the API namespaces without conflicts
24
25
  export namespace API {
@@ -27,4 +28,5 @@ export namespace API {
27
28
  export import SESSIONS = SessionsAPI
28
29
  export import HOME = HomeAPI
29
30
  export import PAGES = PagesAPI
31
+ export import PAYMENTS = PaymentsAPI
30
32
  }
@@ -0,0 +1,17 @@
1
+ export namespace PAYMENTS {
2
+ export namespace GET {
3
+ export interface Request {
4
+ params: {
5
+ checkoutSessionId: string
6
+ }
7
+ }
8
+
9
+ export interface Response {
10
+ amount: number
11
+ category: 'Analysis' | 'Subscription'
12
+ email: string
13
+ member_id: number | null
14
+ productType: 'analysis' | 'monthlySubscription' | 'yearlySubscription' | 'fiveYearLicense' | null
15
+ }
16
+ }
17
+ }
package/src/plant.d.ts CHANGED
@@ -1,107 +1,120 @@
1
- import type { TaxonFamilyI } from './taxonFamily'
2
- import type { SeedingInfoI } from './pages.api'
3
- /**
4
- * Range filter value for min/max filters
5
- */
6
- export interface RangeFilterValueI {
7
- min: number
8
- max: number
9
- }
10
-
11
- /**
12
- * Plant filter value types
13
- * Represents the possible values for a single filter
14
- */
15
- export type PlantFilterValueI = string | string[] | number | boolean | RangeFilterValueI
16
-
17
- /**
18
- * Plant attributes for filtering
19
- * Used in JSONB field and as query parameters
20
- * Supports multiple value types for different filter types
21
- */
22
- export type PlantAttributesI = Record<string, PlantFilterValueI>
23
-
24
- export interface PlantI {
25
- id: number
26
- name: string
27
- slug: string
28
- description: string
29
- descriptionSource?: string
30
- female: boolean
31
- family?: string | null
32
- taxonFamilyId?: number | null
33
- spaceBetweenSeedMin: number
34
- spaceBetweenSeedMax: number
35
- spaceBetweenAlleyMin: number
36
- spaceBetweenAlleyMax: number
37
- weeksInTransplant: number
38
- weeksDuringWhichYouCanSeedOutdoor: number
39
- weeksToMaturity: number
40
- daysToMaturity: number | null
41
- weeksToWaitAfterFreezingDate: number
42
- weeksToHarvest: number
43
- indoorSeeding: boolean
44
- outdoorSeeding: boolean
45
- azoteNeedsKgPerHa: number
46
- hibernate: boolean
47
- germinationTemperature: number | null
48
- minGerminationTemperature: number | null
49
- germinationNumberOfDays: string | null
50
- germinationSeedDepth: string | null
51
- cultivationInfo: string | null
52
- parentId: number | null
53
- memberId?: number
54
- memberFirstName?: string | null
55
- shared: boolean
56
- hexColor: string | null
57
- sunRequirements: 'partialShade' | 'fullSun' | 'fullShade' | null
58
- isHardy: boolean | null
59
- imageURL: string
60
- totalWeeksToMaturity: number
61
- hasNoInformation: boolean
62
- createdAt: Date
63
- updatedAt: Date
64
- translatedSunRequirements: 'Plein soleil' | 'Mi-ombre' | 'Ombre' | null
65
- parent?: PlantI
66
- children?: PlantI[]
67
- PlantInventories?: PlantInventoryI[]
68
- taggedItems?: TaggedItemI[]
69
- /**
70
- * List of selections that the plant is in.
71
- * --------------------------------------
72
- * Tends to be used for featured selections
73
- */
74
- Selections?: SelectionI[]
75
- tasks?: TaskI[]
76
- Images?: ImageI[]
77
- Member?: Partial<MemberI>
78
- notes?: NoteI[]
79
- rotationGroup?: string
80
- // @deprecate once v1.8.1 is fully adopted
81
- rotationFamily?: string
82
- taxonFamily?: TaxonFamilyI
83
- seedingInfo: SeedingInfoI
84
- /**
85
- * Contextual search text for recommended plants
86
- * Provides additional context when suggesting plants for specific garden zones
87
- */
88
- contextualSearchText?: string
89
- }
90
-
91
- interface PlantInventoryI {
92
- id: number
93
- plantId: number
94
- supplierName: string
95
- plantName: string
96
- supplierURL: string
97
- imageLocation: string
98
- description: string
99
- inStock: boolean
100
- }
101
-
102
- export interface PlantSearchResultI {
103
- plants: PlantModelI[]
104
- selections: SelectionModelI[]
105
- total?: number
106
- familyName?: string
107
- }
1
+ import type { TaxonFamilyI } from './taxonFamily'
2
+ import type { SeedingInfoI } from './pages.api'
3
+ import type { PlantFilterI } from './plantFilters'
4
+ /**
5
+ * Range filter value for min/max filters
6
+ */
7
+ export interface RangeFilterValueI {
8
+ min: number
9
+ max: number
10
+ }
11
+
12
+ /**
13
+ * Plant filter value types
14
+ * Represents the possible values for a single filter
15
+ */
16
+ export type PlantFilterValueI = string | string[] | number | boolean | RangeFilterValueI
17
+
18
+ /**
19
+ * Plant attributes for filtering
20
+ * Used in JSONB field and as query parameters
21
+ * Supports multiple value types for different filter types
22
+ */
23
+ export type PlantAttributesI = Record<string, PlantFilterValueI>
24
+
25
+ export interface PlantI {
26
+ id: number
27
+ name: string
28
+ slug: string
29
+ description: string
30
+ descriptionSource?: string
31
+ female: boolean
32
+ family?: string | null
33
+ taxonFamilyId?: number | null
34
+ spaceBetweenSeedMin: number
35
+ spaceBetweenSeedMax: number
36
+ spaceBetweenAlleyMin: number
37
+ spaceBetweenAlleyMax: number
38
+ weeksInTransplant: number
39
+ weeksDuringWhichYouCanSeedOutdoor: number
40
+ weeksToMaturity: number
41
+ daysToMaturity: number | null
42
+ weeksToWaitAfterFreezingDate: number
43
+ weeksToHarvest: number
44
+ indoorSeeding: boolean
45
+ outdoorSeeding: boolean
46
+ azoteNeedsKgPerHa: number
47
+ hibernate: boolean
48
+ germinationTemperature: number | null
49
+ minGerminationTemperature: number | null
50
+ germinationNumberOfDays: string | null
51
+ germinationSeedDepth: string | null
52
+ cultivationInfo: string | null
53
+ parentId: number | null
54
+ memberId?: number
55
+ memberFirstName?: string | null
56
+ shared: boolean
57
+ hexColor: string | null
58
+ sunRequirements: 'partialShade' | 'fullSun' | 'fullShade' | null
59
+ isHardy: boolean | null
60
+ quantityForFiveInJardinVivrier?: number | null
61
+ imageURL: string
62
+ totalWeeksToMaturity: number
63
+ hasNoInformation: boolean
64
+ createdAt: Date
65
+ updatedAt: Date
66
+ translatedSunRequirements: 'Plein soleil' | 'Mi-ombre' | 'Ombre' | null
67
+ parent?: PlantI
68
+ children?: PlantI[]
69
+ PlantInventories?: PlantInventoryI[]
70
+ taggedItems?: TaggedItemI[]
71
+ /**
72
+ * List of selections that the plant is in.
73
+ * --------------------------------------
74
+ * Tends to be used for featured selections
75
+ */
76
+ Selections?: SelectionI[]
77
+ tasks?: TaskI[]
78
+ Images?: ImageI[]
79
+ Member?: Partial<MemberI>
80
+ notes?: NoteI[]
81
+ rotationGroup?: string
82
+ // @deprecate once v1.8.1 is fully adopted
83
+ rotationFamily?: string
84
+ taxonFamily?: TaxonFamilyI
85
+ seedingInfo: SeedingInfoI
86
+ /**
87
+ * Contextual search text for recommended plants
88
+ * Provides additional context when suggesting plants for specific garden zones
89
+ */
90
+ contextualSearchText?: string
91
+ }
92
+
93
+ interface PlantInventoryI {
94
+ id: number
95
+ plantId: number
96
+ supplierName: string
97
+ plantName: string
98
+ supplierURL: string
99
+ imageLocation: string
100
+ description: string
101
+ inStock: boolean
102
+ }
103
+
104
+ export type AvailableGrowingConditionsI = Record<string, string[]>
105
+
106
+ export interface GrowingConditionsConfigI {
107
+ filters: PlantFilterI[]
108
+ }
109
+
110
+ export interface GrowingConditionsFiltersI {
111
+ sunRequirements?: 'partialShade' | 'fullShade'
112
+ rotationGroup?: 'regenerative' | 'demanding' | 'moderately_demanding' | 'less_demanding'
113
+ }
114
+
115
+ export interface PlantSearchResultI {
116
+ plants: PlantModelI[]
117
+ selections: SelectionModelI[]
118
+ total?: number
119
+ familyName?: string
120
+ }
package/src/task.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { SuccessApiResponseI } from './apiError'
2
+
1
3
  export interface TaskI {
2
4
  id: number
3
5
  name: string
@@ -29,23 +31,14 @@ export interface TaskTagI {
29
31
  iconName?: string
30
32
  }
31
33
 
32
- /** Optional toast notification payload returned after task completion. All fields are optional — the frontend applies its own defaults for any missing field. */
33
- export interface CompleteTaskToastI {
34
- title?: string
35
- subtitle?: string
36
- iconName?: string
37
- }
38
-
39
34
  /**
40
35
  * Response returned when one or more tasks are marked as done.
36
+ * Extends SuccessApiResponseI for standard message/suggestion fields.
41
37
  * Keys are plant slugs, values are the full updated task list for that plant selection.
42
38
  * Single completion returns a record with one entry; bulk returns one entry per plant.
43
39
  */
44
- export interface CompleteTaskResponseI {
45
- success: boolean
40
+ export interface CompleteTaskResponseI extends SuccessApiResponseI {
46
41
  updatedTasksByPlant: Record<string, TaskI[]>
47
- /** Optional toast to display after completion. Missing fields fall back to frontend defaults. */
48
- toast?: CompleteTaskToastI
49
42
  }
50
43
 
51
44
  /**
@@ -1,122 +1,136 @@
1
- import type { DeviceDataI } from './device.d'
2
- import type { MemberI as MemberDataI } from './member.d'
3
- import type { SelectionI } from './selection.d'
4
- import type { PlantI } from './plant.d'
5
-
6
- interface RequestHeaders {
7
- 'x-session-token': string
8
- 'x-native-app-version'?: string
9
- 'x-application-type'?: 'react-native' | 'web'
10
- }
11
-
12
- export namespace USERS {
13
- export namespace GET {
14
- export interface Request {
15
- headers: RequestHeaders
16
- params: {
17
- scopes: ('unreadNotificationsCount' | 'coordinates')[]
18
- }
19
- }
20
- export type Response = MemberDataI & {
21
- unreadAlertsCount?: number
22
- }
23
- }
24
- export namespace DEVICES {
25
- export interface Request {
26
- headers: RequestHeaders
27
- body: {
28
- /** @see DeviceDataI */
29
- userAgent?: DeviceDataI['userAgent']
30
- platform?: DeviceDataI['platform']
31
- version?: DeviceDataI['version']
32
- model?: DeviceDataI['model']
33
- name?: DeviceDataI['name']
34
- appVersion?: DeviceDataI['appVersion']
35
- pushKey?: DeviceDataI['pushKey']
36
- apnsToken?: DeviceDataI['apnsToken']
37
- fcmToken?: DeviceDataI['fcmToken']
38
- webPushEndpoint?: DeviceDataI['webPushEndpoint']
39
- webPushP256dh?: DeviceDataI['webPushP256dh']
40
- webPushAuth?: DeviceDataI['webPushAuth']
41
- webPushSubscription?: DeviceDataI['webPushSubscription']
42
- }
43
- }
44
- export type Response = DeviceDataI
45
- }
46
- export namespace RECOMMENDATIONS {
47
- export type ComponentType = 'PlantCarousel' | 'SelectionCarousel' | 'HeroCardsCarousel' | 'YourSelection'
48
-
49
- interface BaseRecommendation {
50
- id: string
51
- componentType: ComponentType
52
- title?: string
53
- subtitle?: string
54
- cardsVisible?: number
55
- }
56
-
57
- export interface PlantCarouselRecommendation extends BaseRecommendation {
58
- componentType: 'PlantCarousel'
59
- selection: SelectionI & { Plants?: PlantI[] }
60
- displayRanking?: boolean
61
- }
62
-
63
- export interface SelectionCarouselRecommendation extends BaseRecommendation {
64
- componentType: 'SelectionCarousel'
65
- selections: SelectionI[]
66
- displayRanking?: boolean
67
- }
68
-
69
- export interface HeroCardsCarouselRecommendation extends BaseRecommendation {
70
- componentType: 'HeroCardsCarousel'
71
- selections: SelectionI[]
72
- }
73
-
74
- export interface YourSelectionRecommendation extends BaseRecommendation {
75
- componentType: 'YourSelection'
76
- }
77
-
78
- export type RecommendationI =
79
- | PlantCarouselRecommendation
80
- | SelectionCarouselRecommendation
81
- | HeroCardsCarouselRecommendation
82
- | YourSelectionRecommendation
83
-
84
- export interface Request {
85
- headers: RequestHeaders
86
- }
87
-
88
- export type Response = RecommendationI[]
89
- }
90
- export namespace UPDATE {
91
- export interface Request {
92
- headers: RequestHeaders
93
- body: {
94
- city?: string
95
- lastFreezingDate?: string | Date
96
- firstFreezingDate?: string | Date
97
- moveDatesRequested?: boolean
98
- lastFertilizerIdChosen?: number
99
- lastOrganicMatterPercentage?: number
100
- unitSystem?: 'imperial' | 'metric'
101
- gardenZoneTimelessPreference?: boolean
102
- }
103
- }
104
- export type Response = MemberDataI
105
- }
106
- export namespace GIFT_CARDS {
107
- export namespace REDEEM {
108
- export interface Request {
109
- headers: RequestHeaders
110
- body: {
111
- code: string
112
- }
113
- }
114
- export interface Response {
115
- success: boolean
116
- message?: string
117
- error?: string
118
- error_message?: string
119
- }
120
- }
121
- }
122
- }
1
+ import type { DeviceDataI } from './device.d'
2
+ import type { MemberI as MemberDataI } from './member.d'
3
+ import type { SelectionI } from './selection.d'
4
+ import type { PlantI } from './plant.d'
5
+
6
+ interface RequestHeaders {
7
+ 'x-session-token': string
8
+ 'x-native-app-version'?: string
9
+ 'x-application-type'?: 'react-native' | 'web'
10
+ }
11
+
12
+ export namespace USERS {
13
+ export namespace GET {
14
+ export interface Request {
15
+ headers: RequestHeaders
16
+ params: {
17
+ scopes: ('unreadNotificationsCount' | 'coordinates')[]
18
+ }
19
+ }
20
+ export type Response = MemberDataI & {
21
+ unreadAlertsCount?: number
22
+ }
23
+ }
24
+ export namespace DEVICES {
25
+ export interface Request {
26
+ headers: RequestHeaders
27
+ body: {
28
+ /** @see DeviceDataI */
29
+ userAgent?: DeviceDataI['userAgent']
30
+ platform?: DeviceDataI['platform']
31
+ version?: DeviceDataI['version']
32
+ model?: DeviceDataI['model']
33
+ name?: DeviceDataI['name']
34
+ appVersion?: DeviceDataI['appVersion']
35
+ pushKey?: DeviceDataI['pushKey']
36
+ apnsToken?: DeviceDataI['apnsToken']
37
+ fcmToken?: DeviceDataI['fcmToken']
38
+ webPushEndpoint?: DeviceDataI['webPushEndpoint']
39
+ webPushP256dh?: DeviceDataI['webPushP256dh']
40
+ webPushAuth?: DeviceDataI['webPushAuth']
41
+ webPushSubscription?: DeviceDataI['webPushSubscription']
42
+ }
43
+ }
44
+ export type Response = DeviceDataI
45
+ }
46
+ export namespace RECOMMENDATIONS {
47
+ export type ComponentType = 'PlantCarousel' | 'SelectionCarousel' | 'HeroCardsCarousel' | 'YourSelection'
48
+
49
+ interface BaseRecommendation {
50
+ id: string
51
+ componentType: ComponentType
52
+ title?: string
53
+ subtitle?: string
54
+ cardsVisible?: number
55
+ }
56
+
57
+ export interface PlantCarouselRecommendation extends BaseRecommendation {
58
+ componentType: 'PlantCarousel'
59
+ selection: SelectionI & { Plants?: PlantI[] }
60
+ displayRanking?: boolean
61
+ }
62
+
63
+ export interface SelectionCarouselRecommendation extends BaseRecommendation {
64
+ componentType: 'SelectionCarousel'
65
+ selections: SelectionI[]
66
+ displayRanking?: boolean
67
+ }
68
+
69
+ export interface HeroCardsCarouselRecommendation extends BaseRecommendation {
70
+ componentType: 'HeroCardsCarousel'
71
+ selections: SelectionI[]
72
+ }
73
+
74
+ export interface YourSelectionRecommendation extends BaseRecommendation {
75
+ componentType: 'YourSelection'
76
+ }
77
+
78
+ export interface ThemedRecommendationI {
79
+ id: string
80
+ label: string
81
+ icon: string
82
+ title?: string
83
+ subtitle?: string
84
+ selections: SelectionI[]
85
+ cardsVisible?: number
86
+ displayRanking?: boolean
87
+ }
88
+
89
+ export type RecommendationI =
90
+ | PlantCarouselRecommendation
91
+ | SelectionCarouselRecommendation
92
+ | HeroCardsCarouselRecommendation
93
+ | YourSelectionRecommendation
94
+
95
+ export interface Request {
96
+ headers: RequestHeaders
97
+ }
98
+
99
+ export interface Response {
100
+ recommendations: RecommendationI[]
101
+ themedRecommendations: ThemedRecommendationI[]
102
+ }
103
+ }
104
+ export namespace UPDATE {
105
+ export interface Request {
106
+ headers: RequestHeaders
107
+ body: {
108
+ city?: string
109
+ lastFreezingDate?: string | Date
110
+ firstFreezingDate?: string | Date
111
+ moveDatesRequested?: boolean
112
+ lastFertilizerIdChosen?: number
113
+ lastOrganicMatterPercentage?: number
114
+ unitSystem?: 'imperial' | 'metric'
115
+ gardenZoneTimelessPreference?: boolean
116
+ }
117
+ }
118
+ export type Response = MemberDataI
119
+ }
120
+ export namespace GIFT_CARDS {
121
+ export namespace REDEEM {
122
+ export interface Request {
123
+ headers: RequestHeaders
124
+ body: {
125
+ code: string
126
+ }
127
+ }
128
+ export interface Response {
129
+ success: boolean
130
+ message?: string
131
+ error?: string
132
+ error_message?: string
133
+ }
134
+ }
135
+ }
136
+ }