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

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.76",
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
@@ -55,6 +55,68 @@ export interface GardenMapI {
55
55
  imageURL: string
56
56
  }
57
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
+
58
120
  export interface GardenZoneI {
59
121
  id: number
60
122
  name: string | null
@@ -62,7 +124,15 @@ export interface GardenZoneI {
62
124
  widthInMeters: number
63
125
  heightInMeters: number
64
126
  diameterInMeters: number
65
- shape: 'rectangle' | 'circle'
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
66
136
  xPosition: number
67
137
  yPosition: number
68
138
  zIndex: number
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
@@ -1,30 +1,32 @@
1
- export * from './member'
2
- export * from './selection'
3
- export * from './plantSelection'
4
- export * from './plant'
5
- export * from './task'
6
- export * from './calendarView'
7
- export * from './apiError'
8
- export * from './gardenMap'
9
- export * from './gardenOverview'
10
- export * from './alert'
11
- export * from './image'
12
- export * from './note'
13
- export * from './taggedItem'
14
- export * from './fertilizer'
15
- export * from './utmParams'
16
- export * from './plantFilters'
17
- import * as PlantsAPI from './plants.api'
18
- import * as UsersAPI from './users.api'
19
- import * as SessionsAPI from './sessions.api'
20
- import * as HomeAPI from './home.api'
21
- import * as PagesAPI from './pages.api'
22
-
23
- // Allow access to the API namespaces without conflicts
24
- export namespace API {
25
- export import PLANTS = PlantsAPI
26
- export import USERS = UsersAPI
27
- export import SESSIONS = SessionsAPI
28
- export import HOME = HomeAPI
29
- export import PAGES = PagesAPI
30
- }
1
+ export * from './member'
2
+ export * from './selection'
3
+ export * from './plantSelection'
4
+ export * from './plant'
5
+ export * from './task'
6
+ export * from './calendarView'
7
+ export * from './apiError'
8
+ export * from './gardenMap'
9
+ export * from './gardenOverview'
10
+ export * from './alert'
11
+ export * from './image'
12
+ export * from './note'
13
+ export * from './taggedItem'
14
+ export * from './fertilizer'
15
+ export * from './utmParams'
16
+ export * from './plantFilters'
17
+ import * as PlantsAPI from './plants.api'
18
+ import * as UsersAPI from './users.api'
19
+ import * as SessionsAPI from './sessions.api'
20
+ import * as HomeAPI from './home.api'
21
+ import * as PagesAPI from './pages.api'
22
+ import * as PaymentsAPI from './payments.api'
23
+
24
+ // Allow access to the API namespaces without conflicts
25
+ export namespace API {
26
+ export import PLANTS = PlantsAPI
27
+ export import USERS = UsersAPI
28
+ export import SESSIONS = SessionsAPI
29
+ export import HOME = HomeAPI
30
+ export import PAGES = PagesAPI
31
+ export import PAYMENTS = PaymentsAPI
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,107 @@
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
+ /**
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
+ }
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
+ }