@wasto/sdk 1.0.3
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/dist/index.d.mts +2562 -0
- package/dist/index.d.ts +2562 -0
- package/dist/index.js +2566 -0
- package/dist/index.mjs +2405 -0
- package/package.json +30 -0
- package/src/client.ts +692 -0
- package/src/dashboard-apps.ts +350 -0
- package/src/dto/cms-app-settings.ts +91 -0
- package/src/enums.ts +298 -0
- package/src/free-tier.ts +56 -0
- package/src/index.ts +35 -0
- package/src/opening-hours/constants.ts +48 -0
- package/src/opening-hours/convert.ts +276 -0
- package/src/opening-hours/format.ts +99 -0
- package/src/opening-hours/index.ts +9 -0
- package/src/opening-hours/is-open-now.ts +38 -0
- package/src/opening-hours/resolve.ts +71 -0
- package/src/opening-hours/time.ts +74 -0
- package/src/opening-hours/timezone.ts +34 -0
- package/src/opening-hours/types.ts +53 -0
- package/src/opening-hours/validate.ts +182 -0
- package/src/roi/calculations.ts +732 -0
- package/src/roi/index.ts +1 -0
- package/src/types/asset-bookings.types.ts +19 -0
- package/src/types/asset-interventions.types.ts +24 -0
- package/src/types/assets.types.ts +68 -0
- package/src/types/auth.types.ts +37 -0
- package/src/types/blog-posts.types.ts +19 -0
- package/src/types/calendar-pdf.types.ts +24 -0
- package/src/types/calendo-events.types.ts +64 -0
- package/src/types/challenges.types.ts +30 -0
- package/src/types/chatbot.types.ts +82 -0
- package/src/types/cities.types.ts +27 -0
- package/src/types/city-groups.types.ts +46 -0
- package/src/types/cms.types.ts +87 -0
- package/src/types/field-reports.types.ts +66 -0
- package/src/types/free-tier.types.ts +54 -0
- package/src/types/index.ts +32 -0
- package/src/types/iot.types.ts +31 -0
- package/src/types/maintenance.types.ts +44 -0
- package/src/types/mapso.types.ts +146 -0
- package/src/types/notifications.types.ts +68 -0
- package/src/types/onboarding.types.ts +117 -0
- package/src/types/operational-zones.types.ts +70 -0
- package/src/types/pagination.types.ts +33 -0
- package/src/types/providers.types.ts +29 -0
- package/src/types/quiz-questions.types.ts +59 -0
- package/src/types/recycling-points.types.ts +47 -0
- package/src/types/roi.types.ts +60 -0
- package/src/types/surveys.types.ts +103 -0
- package/src/types/tickets.types.ts +65 -0
- package/src/types/users.types.ts +30 -0
- package/src/types/waste-collection-places-query.types.ts +4 -0
- package/src/types/waste-collection-places.types.ts +33 -0
- package/src/types/waste-types.types.ts +21 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface CreateIotDeviceRequest {
|
|
2
|
+
name: string;
|
|
3
|
+
deviceId: string;
|
|
4
|
+
assetId?: string;
|
|
5
|
+
clientCert: string;
|
|
6
|
+
clientKey: string;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface UpdateIotDeviceRequest {
|
|
11
|
+
name?: string;
|
|
12
|
+
deviceId?: string;
|
|
13
|
+
assetId?: string;
|
|
14
|
+
clientCert?: string;
|
|
15
|
+
clientKey?: string;
|
|
16
|
+
enabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface IotWebhookPayloadRequest {
|
|
20
|
+
deviceId: string;
|
|
21
|
+
eventType: 'position' | 'consumption' | 'alert';
|
|
22
|
+
latitude?: number;
|
|
23
|
+
longitude?: number;
|
|
24
|
+
value?: number;
|
|
25
|
+
unit?: string;
|
|
26
|
+
periodStart?: string;
|
|
27
|
+
periodEnd?: string;
|
|
28
|
+
title?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
metadata?: Record<string, unknown>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface CreateMaintenanceTypeRequest {
|
|
2
|
+
name: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
downtimeHours: number;
|
|
5
|
+
recommendedFrequency?: number;
|
|
6
|
+
estimatedCost?: number;
|
|
7
|
+
instructions?: string;
|
|
8
|
+
isActive?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface UpdateMaintenanceTypeRequest {
|
|
12
|
+
name?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
downtimeHours?: number;
|
|
15
|
+
recommendedFrequency?: number;
|
|
16
|
+
estimatedCost?: number;
|
|
17
|
+
instructions?: string;
|
|
18
|
+
isActive?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface MaintenanceProgramItemRequest {
|
|
22
|
+
maintenanceTypeId: string;
|
|
23
|
+
frequencyDays: number;
|
|
24
|
+
order?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface CreateMaintenanceProgramRequest {
|
|
28
|
+
name: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
items: MaintenanceProgramItemRequest[];
|
|
31
|
+
isActive?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface UpdateMaintenanceProgramRequest {
|
|
35
|
+
name?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
items?: MaintenanceProgramItemRequest[];
|
|
38
|
+
isActive?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface AssignProgramRequest {
|
|
42
|
+
programId: string;
|
|
43
|
+
startDate: string;
|
|
44
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
MapEventStatus,
|
|
3
|
+
MapEventType,
|
|
4
|
+
MapPoiCategory,
|
|
5
|
+
MapPoiStatus,
|
|
6
|
+
MapZoneType,
|
|
7
|
+
} from '../enums';
|
|
8
|
+
|
|
9
|
+
export interface CreateMapEventRequest {
|
|
10
|
+
title: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
type?: MapEventType;
|
|
13
|
+
status?: MapEventStatus;
|
|
14
|
+
startDate?: string;
|
|
15
|
+
endDate?: string;
|
|
16
|
+
centerLatitude?: number;
|
|
17
|
+
centerLongitude?: number;
|
|
18
|
+
defaultZoom?: number;
|
|
19
|
+
perimeterGeoJson?: Record<string, unknown> | null;
|
|
20
|
+
cityId?: string;
|
|
21
|
+
cityGroupId?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface UpdateMapEventRequest {
|
|
25
|
+
title?: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
type?: MapEventType;
|
|
28
|
+
status?: MapEventStatus;
|
|
29
|
+
startDate?: string | null;
|
|
30
|
+
endDate?: string | null;
|
|
31
|
+
centerLatitude?: number | null;
|
|
32
|
+
centerLongitude?: number | null;
|
|
33
|
+
defaultZoom?: number | null;
|
|
34
|
+
perimeterGeoJson?: Record<string, unknown> | null;
|
|
35
|
+
cityId?: string | null;
|
|
36
|
+
cityGroupId?: string | null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface CreateMapPoiRequest {
|
|
40
|
+
name: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
category: MapPoiCategory;
|
|
43
|
+
status?: MapPoiStatus;
|
|
44
|
+
latitude: number;
|
|
45
|
+
longitude: number;
|
|
46
|
+
openingHours?: string;
|
|
47
|
+
tags?: string[];
|
|
48
|
+
sortOrder?: number;
|
|
49
|
+
dateFrom?: string;
|
|
50
|
+
dateTo?: string;
|
|
51
|
+
streetIds?: string[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface UpdateMapPoiRequest {
|
|
55
|
+
name?: string;
|
|
56
|
+
description?: string;
|
|
57
|
+
category?: MapPoiCategory;
|
|
58
|
+
status?: MapPoiStatus;
|
|
59
|
+
latitude?: number;
|
|
60
|
+
longitude?: number;
|
|
61
|
+
openingHours?: string | null;
|
|
62
|
+
tags?: string[];
|
|
63
|
+
sortOrder?: number;
|
|
64
|
+
dateFrom?: string | null;
|
|
65
|
+
dateTo?: string | null;
|
|
66
|
+
streetIds?: string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface CreateMapZoneRequest {
|
|
70
|
+
name: string;
|
|
71
|
+
type: MapZoneType;
|
|
72
|
+
geoJson: Record<string, unknown>;
|
|
73
|
+
color?: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
dateFrom?: string;
|
|
76
|
+
dateTo?: string;
|
|
77
|
+
streetIds?: string[];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface UpdateMapZoneRequest {
|
|
81
|
+
name?: string;
|
|
82
|
+
type?: MapZoneType;
|
|
83
|
+
geoJson?: Record<string, unknown>;
|
|
84
|
+
color?: string;
|
|
85
|
+
description?: string;
|
|
86
|
+
dateFrom?: string | null;
|
|
87
|
+
dateTo?: string | null;
|
|
88
|
+
streetIds?: string[];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface MapZoneSummary {
|
|
92
|
+
id: string;
|
|
93
|
+
mapEventId: string;
|
|
94
|
+
name: string;
|
|
95
|
+
type: MapZoneType;
|
|
96
|
+
geoJson: Record<string, unknown>;
|
|
97
|
+
color?: string | null;
|
|
98
|
+
description?: string | null;
|
|
99
|
+
dateFrom?: string | null;
|
|
100
|
+
dateTo?: string | null;
|
|
101
|
+
streets?: Array<{ street: { id: string; name: string } }>;
|
|
102
|
+
createdAt: string;
|
|
103
|
+
updatedAt: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface MapPoiSummary {
|
|
107
|
+
id: string;
|
|
108
|
+
mapEventId: string;
|
|
109
|
+
name: string;
|
|
110
|
+
description?: string | null;
|
|
111
|
+
category: MapPoiCategory;
|
|
112
|
+
status: MapPoiStatus;
|
|
113
|
+
latitude: number;
|
|
114
|
+
longitude: number;
|
|
115
|
+
openingHours?: string | null;
|
|
116
|
+
tags: string[];
|
|
117
|
+
dateFrom?: string | null;
|
|
118
|
+
dateTo?: string | null;
|
|
119
|
+
streets?: Array<{ street: { id: string; name: string } }>;
|
|
120
|
+
sortOrder: number;
|
|
121
|
+
createdAt: string;
|
|
122
|
+
updatedAt: string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface MapEventSummary {
|
|
126
|
+
id: string;
|
|
127
|
+
title: string;
|
|
128
|
+
description?: string | null;
|
|
129
|
+
type: MapEventType;
|
|
130
|
+
status: MapEventStatus;
|
|
131
|
+
startDate?: string | null;
|
|
132
|
+
endDate?: string | null;
|
|
133
|
+
centerLatitude?: number | null;
|
|
134
|
+
centerLongitude?: number | null;
|
|
135
|
+
defaultZoom?: number | null;
|
|
136
|
+
perimeterGeoJson?: Record<string, unknown> | null;
|
|
137
|
+
cityId?: string | null;
|
|
138
|
+
cityGroupId?: string | null;
|
|
139
|
+
city?: { id: string; name: string } | null;
|
|
140
|
+
cityGroup?: { id: string; name: string } | null;
|
|
141
|
+
pois?: MapPoiSummary[];
|
|
142
|
+
zones?: MapZoneSummary[];
|
|
143
|
+
_count?: { pois: number; zones?: number };
|
|
144
|
+
createdAt: string;
|
|
145
|
+
updatedAt: string;
|
|
146
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { RecipientGroupType } from '../enums';
|
|
2
|
+
|
|
3
|
+
export interface CreateNotificationRequest {
|
|
4
|
+
title: string;
|
|
5
|
+
body: string;
|
|
6
|
+
data?: Record<string, unknown>;
|
|
7
|
+
recipientGroupId: string;
|
|
8
|
+
scheduledAt?: string;
|
|
9
|
+
/** Envoyer une notification push (défaut: true) */
|
|
10
|
+
sendPush?: boolean;
|
|
11
|
+
/** Afficher en modale dans l'app (défaut: false) */
|
|
12
|
+
showAsModal?: boolean;
|
|
13
|
+
/** Média CMS affiché dans la modale */
|
|
14
|
+
imageMediaId?: string | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface UpdateNotificationRequest {
|
|
18
|
+
title?: string;
|
|
19
|
+
body?: string;
|
|
20
|
+
data?: Record<string, unknown>;
|
|
21
|
+
recipientGroupId?: string;
|
|
22
|
+
scheduledAt?: string;
|
|
23
|
+
sendPush?: boolean;
|
|
24
|
+
showAsModal?: boolean;
|
|
25
|
+
imageMediaId?: string | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface CreateRecipientGroupRequest {
|
|
29
|
+
name: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
type: RecipientGroupType;
|
|
32
|
+
/** Requis pour CITY_GROUP (tout le groupement) */
|
|
33
|
+
cityGroupId?: string;
|
|
34
|
+
/** Requis non vide pour CITY */
|
|
35
|
+
cityIds?: string[];
|
|
36
|
+
/** Requis non vide pour ZONE (lieux de collecte) */
|
|
37
|
+
wasteCollectionPlaceIds?: string[];
|
|
38
|
+
/** @deprecated Prefer cityIds */
|
|
39
|
+
cityId?: string;
|
|
40
|
+
/** @deprecated Prefer wasteCollectionPlaceIds */
|
|
41
|
+
wasteCollectionPlaceId?: string;
|
|
42
|
+
/** @deprecated Legacy operational zone targeting */
|
|
43
|
+
operationalZoneId?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface UpdateRecipientGroupRequest {
|
|
47
|
+
name?: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
type?: RecipientGroupType;
|
|
50
|
+
cityGroupId?: string;
|
|
51
|
+
cityIds?: string[];
|
|
52
|
+
wasteCollectionPlaceIds?: string[];
|
|
53
|
+
/** @deprecated Prefer cityIds */
|
|
54
|
+
cityId?: string;
|
|
55
|
+
/** @deprecated Prefer wasteCollectionPlaceIds */
|
|
56
|
+
wasteCollectionPlaceId?: string;
|
|
57
|
+
/** @deprecated Legacy operational zone targeting */
|
|
58
|
+
operationalZoneId?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Annonce modale active pour l'app mobile */
|
|
62
|
+
export interface PublicAnnouncement {
|
|
63
|
+
id: string;
|
|
64
|
+
title: string;
|
|
65
|
+
body: string;
|
|
66
|
+
imageUrl?: string | null;
|
|
67
|
+
sentAt?: string | null;
|
|
68
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { CityGroupType } from '../enums';
|
|
2
|
+
import type { DashboardAppSlug } from '../dashboard-apps';
|
|
3
|
+
import { FREE_SELF_SERVE_DASHBOARD_APP_SLUGS } from '../dashboard-apps';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Contrats API onboarding self-serve (compte gratuit → collectivité → mode restreint → PWA light).
|
|
7
|
+
* Routes : `POST /onboarding/bootstrap-city-group`, `POST /onboarding/request-join`,
|
|
8
|
+
* `GET /onboarding/search-city-groups`, `GET /onboarding/search-sinoe`,
|
|
9
|
+
* `POST /onboarding/bootstrap-pwa-light`, `POST /onboarding/sync-restricted-access`.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** Étapes du parcours post-inscription (console). */
|
|
13
|
+
export type OnboardingStepId =
|
|
14
|
+
| 'account'
|
|
15
|
+
| 'collectivite'
|
|
16
|
+
| 'restricted'
|
|
17
|
+
| 'pwa_light'
|
|
18
|
+
| 'done';
|
|
19
|
+
|
|
20
|
+
export type BootstrapCityGroupRequest = {
|
|
21
|
+
/** Nom du groupement (ex. « CA du Pays de … »). */
|
|
22
|
+
name: string;
|
|
23
|
+
type?: CityGroupType;
|
|
24
|
+
/** Code / SIREN optionnels pour dédoublonnage. */
|
|
25
|
+
code?: string | null;
|
|
26
|
+
siren?: string | null;
|
|
27
|
+
/** Première commune rattachée (minimale). */
|
|
28
|
+
city?: {
|
|
29
|
+
name: string;
|
|
30
|
+
country?: string;
|
|
31
|
+
codeInsee?: string | null;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type BootstrapCityGroupResponse = {
|
|
36
|
+
cityGroupId: string;
|
|
37
|
+
cityId?: string | null;
|
|
38
|
+
/** Apps activées (= preset free / restreint). */
|
|
39
|
+
enabledDashboardAppSlugs: DashboardAppSlug[];
|
|
40
|
+
/** Membership créateur : GESTIONNAIRE + authorizations. */
|
|
41
|
+
membershipId: string;
|
|
42
|
+
/** Prochaine étape console recommandée. */
|
|
43
|
+
nextStep: OnboardingStepId;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type OnboardingCityGroupSearchHit = {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
type: CityGroupType;
|
|
50
|
+
code?: string | null;
|
|
51
|
+
siren?: string | null;
|
|
52
|
+
citiesCount: number;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Hit ADEME / SINOE (Data Fair flux collecte) pour le sélecteur onboarding.
|
|
57
|
+
* `codeActeur` = `c_acteur` SINOE (pas un SIREN légal) — stocké en `CityGroup.code` au create.
|
|
58
|
+
*/
|
|
59
|
+
export type OnboardingSinoeSearchHit = {
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
codeActeur: string;
|
|
63
|
+
departement?: string | null;
|
|
64
|
+
codeDepartement?: string | null;
|
|
65
|
+
region?: string | null;
|
|
66
|
+
population?: number | null;
|
|
67
|
+
year: number;
|
|
68
|
+
typologie?: string | null;
|
|
69
|
+
/** CityGroup Wasto déjà présent (match code/siren = codeActeur). */
|
|
70
|
+
existingCityGroup?: OnboardingCityGroupSearchHit | null;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type RequestJoinCityGroupRequest = {
|
|
74
|
+
cityGroupId: string;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export type RequestJoinCityGroupResponse = {
|
|
78
|
+
membershipId: string;
|
|
79
|
+
cityGroupId: string;
|
|
80
|
+
/** MVP : false — en attente d’acceptation par un gestionnaire. */
|
|
81
|
+
isAccepted: boolean;
|
|
82
|
+
nextStep: OnboardingStepId;
|
|
83
|
+
/** TODO produit : workflow d’approbation / notification gestionnaire. */
|
|
84
|
+
note?: string;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export type PwaLightBootstrapRequest = {
|
|
88
|
+
cityGroupId: string;
|
|
89
|
+
/** Slug public PWA (unique). */
|
|
90
|
+
slug: string;
|
|
91
|
+
name?: string;
|
|
92
|
+
/** Publier immédiatement (`pwaPublished`). Défaut true. */
|
|
93
|
+
publish?: boolean;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type PwaLightBootstrapResponse = {
|
|
97
|
+
cmsAppId: string;
|
|
98
|
+
slug: string;
|
|
99
|
+
/** Écrans light : tri + calendrier (hors carte / défis sur free). */
|
|
100
|
+
screens: ReadonlyArray<'tri' | 'calendrier' | 'carte' | 'defis'>;
|
|
101
|
+
previewPath: string;
|
|
102
|
+
pwaPublished: boolean;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type SyncRestrictedAccessRequest = {
|
|
106
|
+
cityGroupId: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export type SyncRestrictedAccessResponse = {
|
|
110
|
+
cityGroupId: string;
|
|
111
|
+
enabledDashboardAppSlugs: DashboardAppSlug[];
|
|
112
|
+
membershipAuthorizations: string[];
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/** Preset appliqué au bootstrap self-serve. */
|
|
116
|
+
export const ONBOARDING_RESTRICTED_APP_SLUGS: readonly DashboardAppSlug[] =
|
|
117
|
+
FREE_SELF_SERVE_DASHBOARD_APP_SLUGS;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { OperationalZoneStatus, OperationalZoneType } from '../enums';
|
|
2
|
+
|
|
3
|
+
export interface OperationalZoneStreetLink {
|
|
4
|
+
street: {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
latitude?: number | null;
|
|
8
|
+
longitude?: number | null;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface OperationalZone {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
type: OperationalZoneType;
|
|
16
|
+
status: OperationalZoneStatus;
|
|
17
|
+
geoJson: Record<string, unknown>;
|
|
18
|
+
color?: string | null;
|
|
19
|
+
description?: string | null;
|
|
20
|
+
dateFrom?: string | null;
|
|
21
|
+
dateTo?: string | null;
|
|
22
|
+
cityId: string;
|
|
23
|
+
city?: { id: string; name: string };
|
|
24
|
+
wasteCollectionPlaceId?: string | null;
|
|
25
|
+
wasteCollectionPlace?: { id: string; name: string; reference?: string | null } | null;
|
|
26
|
+
wasteTypeId?: string | null;
|
|
27
|
+
wasteType?: { id: string; name: string; color?: string | null } | null;
|
|
28
|
+
syncCalendarException?: boolean;
|
|
29
|
+
collectionExceptionId?: string | null;
|
|
30
|
+
collectionException?: {
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
dateFrom: string;
|
|
34
|
+
dateTo: string;
|
|
35
|
+
} | null;
|
|
36
|
+
streets?: OperationalZoneStreetLink[];
|
|
37
|
+
createdAt?: string;
|
|
38
|
+
updatedAt?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CreateOperationalZoneRequest {
|
|
42
|
+
name: string;
|
|
43
|
+
type: OperationalZoneType;
|
|
44
|
+
status?: OperationalZoneStatus;
|
|
45
|
+
geoJson: Record<string, unknown>;
|
|
46
|
+
color?: string;
|
|
47
|
+
description?: string;
|
|
48
|
+
dateFrom?: string;
|
|
49
|
+
dateTo?: string;
|
|
50
|
+
cityId: string;
|
|
51
|
+
streetIds?: string[];
|
|
52
|
+
wasteCollectionPlaceId?: string;
|
|
53
|
+
wasteTypeId?: string;
|
|
54
|
+
syncCalendarException?: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface UpdateOperationalZoneRequest {
|
|
58
|
+
name?: string;
|
|
59
|
+
type?: OperationalZoneType;
|
|
60
|
+
status?: OperationalZoneStatus;
|
|
61
|
+
geoJson?: Record<string, unknown>;
|
|
62
|
+
color?: string;
|
|
63
|
+
description?: string;
|
|
64
|
+
dateFrom?: string | null;
|
|
65
|
+
dateTo?: string | null;
|
|
66
|
+
streetIds?: string[];
|
|
67
|
+
wasteCollectionPlaceId?: string | null;
|
|
68
|
+
wasteTypeId?: string | null;
|
|
69
|
+
syncCalendarException?: boolean;
|
|
70
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const DEFAULT_PAGE = 1;
|
|
2
|
+
export const DEFAULT_PAGE_SIZE = 20;
|
|
3
|
+
export const MAX_PAGE_SIZE = 100;
|
|
4
|
+
|
|
5
|
+
export interface PaginationQuery {
|
|
6
|
+
page?: number;
|
|
7
|
+
pageSize?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PaginationMeta {
|
|
11
|
+
page: number;
|
|
12
|
+
pageSize: number;
|
|
13
|
+
total: number;
|
|
14
|
+
totalPages: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface PaginatedResponse<T> {
|
|
18
|
+
data: T[];
|
|
19
|
+
meta: PaginationMeta;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function buildPaginationMeta(
|
|
23
|
+
page: number,
|
|
24
|
+
pageSize: number,
|
|
25
|
+
total: number,
|
|
26
|
+
): PaginationMeta {
|
|
27
|
+
return {
|
|
28
|
+
page,
|
|
29
|
+
pageSize,
|
|
30
|
+
total,
|
|
31
|
+
totalPages: Math.ceil(total / pageSize) || 1,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ProviderType } from '../enums';
|
|
2
|
+
|
|
3
|
+
export interface CreateProviderRequest {
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
type?: ProviderType;
|
|
7
|
+
email?: string;
|
|
8
|
+
phone?: string;
|
|
9
|
+
address?: string;
|
|
10
|
+
siret?: string;
|
|
11
|
+
siren?: string;
|
|
12
|
+
website?: string;
|
|
13
|
+
cityGroupIds?: string[];
|
|
14
|
+
cityIds?: string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface UpdateProviderRequest {
|
|
18
|
+
name?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
type?: ProviderType;
|
|
21
|
+
email?: string;
|
|
22
|
+
phone?: string;
|
|
23
|
+
address?: string;
|
|
24
|
+
siret?: string;
|
|
25
|
+
siren?: string;
|
|
26
|
+
website?: string;
|
|
27
|
+
cityGroupIds?: string[];
|
|
28
|
+
cityIds?: string[];
|
|
29
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export type QuizQuestionKind = 'waste_bin' | 'ab_image' | 'mcq';
|
|
2
|
+
|
|
3
|
+
export type QuizAbImageChoice = {
|
|
4
|
+
id: string;
|
|
5
|
+
imageUrl: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type QuizAbImageOptions = {
|
|
10
|
+
choices: [QuizAbImageChoice, QuizAbImageChoice];
|
|
11
|
+
correctChoiceId: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type QuizMcqChoice = {
|
|
15
|
+
id: string;
|
|
16
|
+
text: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type QuizMcqOptions = {
|
|
20
|
+
choices: QuizMcqChoice[];
|
|
21
|
+
correctChoiceId: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type QuizQuestionOptions = QuizAbImageOptions | QuizMcqOptions;
|
|
25
|
+
|
|
26
|
+
/** Détail référentiel lié à une explication (WasteTypeDetail). */
|
|
27
|
+
export type QuizExplanationDetail = {
|
|
28
|
+
id: string;
|
|
29
|
+
material: string;
|
|
30
|
+
description?: string | null;
|
|
31
|
+
instructions?: string | null;
|
|
32
|
+
imageUrl?: string | null;
|
|
33
|
+
wasteType?: { id: string; name: string } | null;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export interface CreateQuizQuestionRequest {
|
|
37
|
+
/** @deprecated Ignored — city is taken from `serie.challenge.cityId`. */
|
|
38
|
+
cityId?: string;
|
|
39
|
+
/** Required for `waste_bin`; optional for `ab_image`. */
|
|
40
|
+
wasteTypeId?: string;
|
|
41
|
+
materialId?: string;
|
|
42
|
+
material: string;
|
|
43
|
+
question: string;
|
|
44
|
+
imageUrl?: string;
|
|
45
|
+
imageBase64?: string;
|
|
46
|
+
/** Required for `waste_bin`; optional for `ab_image`. */
|
|
47
|
+
correctWasteTypeId?: string;
|
|
48
|
+
/** Required: question belongs to a series (city = that series' challenge city). */
|
|
49
|
+
serieId: string;
|
|
50
|
+
order?: number;
|
|
51
|
+
/** Defaults to `waste_bin` (legacy). */
|
|
52
|
+
kind?: QuizQuestionKind;
|
|
53
|
+
/** Typed payload for non-waste_bin kinds. */
|
|
54
|
+
options?: QuizQuestionOptions;
|
|
55
|
+
/** Free-text explanation shown after answering (takes priority over detail). */
|
|
56
|
+
explanationText?: string | null;
|
|
57
|
+
/** Link to a référentiel WasteTypeDetail for explanation. */
|
|
58
|
+
explanationDetailId?: string | null;
|
|
59
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { HoursInputMode, OpeningHours } from '../opening-hours/types';
|
|
2
|
+
|
|
3
|
+
export interface CreateRecyclingPointRequest {
|
|
4
|
+
cityId: string;
|
|
5
|
+
name: string;
|
|
6
|
+
type: string;
|
|
7
|
+
acceptedWasteTypes: string[];
|
|
8
|
+
latitude?: number;
|
|
9
|
+
longitude?: number;
|
|
10
|
+
/** @deprecated Prefer longitude (alias X = longitude). */
|
|
11
|
+
coordinateX?: number;
|
|
12
|
+
/** @deprecated Prefer latitude (alias Y = latitude). */
|
|
13
|
+
coordinateY?: number;
|
|
14
|
+
address?: string;
|
|
15
|
+
hours?: string;
|
|
16
|
+
phone?: string;
|
|
17
|
+
details?: RecyclingPointDetails;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type { HoursInputMode };
|
|
21
|
+
|
|
22
|
+
export type RecyclingPointDetails = {
|
|
23
|
+
address?: string;
|
|
24
|
+
hours?: string;
|
|
25
|
+
phone?: string;
|
|
26
|
+
hoursMode?: HoursInputMode;
|
|
27
|
+
openingHours?: OpeningHours;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export interface RecyclingPoint {
|
|
32
|
+
id: string;
|
|
33
|
+
cityId?: string | null;
|
|
34
|
+
name: string;
|
|
35
|
+
type: string;
|
|
36
|
+
acceptedWasteTypes: string[];
|
|
37
|
+
latitude?: number | null;
|
|
38
|
+
longitude?: number | null;
|
|
39
|
+
/** @deprecated Prefer longitude. */
|
|
40
|
+
coordinateX?: number | null;
|
|
41
|
+
/** @deprecated Prefer latitude. */
|
|
42
|
+
coordinateY?: number | null;
|
|
43
|
+
address?: string | null;
|
|
44
|
+
hours?: string | null;
|
|
45
|
+
phone?: string | null;
|
|
46
|
+
details?: RecyclingPointDetails | null;
|
|
47
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { TerritoryActionStatus, TerritoryActionType } from '../enums'
|
|
2
|
+
|
|
3
|
+
export type { TerritoryActionStatus, TerritoryActionType }
|
|
4
|
+
|
|
5
|
+
export interface UpsertTerritoryEconomicsRequest {
|
|
6
|
+
cityId?: string
|
|
7
|
+
cityGroupId?: string
|
|
8
|
+
fiscalYear?: number
|
|
9
|
+
annualTonnageOmr: number
|
|
10
|
+
errorRatePercent: number
|
|
11
|
+
costPerBadTonne?: number
|
|
12
|
+
tgapEurPerTonne?: number
|
|
13
|
+
householdCount?: number | null
|
|
14
|
+
population?: number | null
|
|
15
|
+
wastoAnnualCostEur?: number
|
|
16
|
+
citeoSupportGainEur?: number
|
|
17
|
+
notes?: string | null
|
|
18
|
+
/** Si true, fige la baseline (avant) sur les valeurs courantes. */
|
|
19
|
+
lockBaseline?: boolean
|
|
20
|
+
annualBilanConfirmed?: boolean
|
|
21
|
+
dataSource?: 'MANUAL' | 'SINOE' | 'IMPORT'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ImportTerritoryYearRequest {
|
|
25
|
+
fiscalYear: number
|
|
26
|
+
annualTonnageOmr: number
|
|
27
|
+
errorRatePercent?: number
|
|
28
|
+
costPerBadTonne?: number
|
|
29
|
+
citeoSupportGainEur?: number
|
|
30
|
+
population?: number | null
|
|
31
|
+
householdCount?: number | null
|
|
32
|
+
notes?: string | null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ImportTerritoryHistoryRequest {
|
|
36
|
+
cityGroupId: string
|
|
37
|
+
years: ImportTerritoryYearRequest[]
|
|
38
|
+
/** Si true, marque dataSource=SINOE. */
|
|
39
|
+
fromSinoe?: boolean
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface CreateTerritoryActionRequest {
|
|
43
|
+
name: string
|
|
44
|
+
description?: string
|
|
45
|
+
type?: TerritoryActionType
|
|
46
|
+
status?: TerritoryActionStatus
|
|
47
|
+
zoneLabel?: string
|
|
48
|
+
startDate?: string
|
|
49
|
+
endDate?: string
|
|
50
|
+
budgetCapexEur?: number
|
|
51
|
+
budgetOpexEur?: number
|
|
52
|
+
expectedErrorReductionPercent?: number
|
|
53
|
+
measuredErrorReductionPercent?: number | null
|
|
54
|
+
challengeId?: string | null
|
|
55
|
+
surveyId?: string | null
|
|
56
|
+
order?: number
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface UpdateTerritoryActionRequest
|
|
60
|
+
extends Partial<CreateTerritoryActionRequest> {}
|