@communecter/cocolight-api-client 1.0.123 → 1.0.125

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/src/api/Poi.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ApiError } from "../error.js";
2
2
  import { BaseEntity } from "./BaseEntity.js";
3
3
  import { PoiItemNormalized } from "./serverDataType/Poi.js";
4
+ import { transformEntityRefs } from "../types/transforms.js";
4
5
 
5
6
  import type { AddPoiData } from "./EndpointApi.types.js";
6
7
 
@@ -39,9 +40,12 @@ export class Poi extends BaseEntity<PoiItemNormalized> {
39
40
  "typeElement"
40
41
  ];
41
42
 
42
- // transforms = {
43
-
44
- // };
43
+ // Le serveur enrichit `parent` avec _id/slug/id/profilThumbImageUrl/etc. qui ne sont
44
+ // pas dans le schéma d'envoi (additionalProperties: false → name, type seuls).
45
+ // On filtre via transformEntityRefs à la construction du draft (pattern identique à Event).
46
+ override transforms: Record<string, (val: any, full?: any) => any> = {
47
+ parent: transformEntityRefs,
48
+ };
45
49
 
46
50
  override _add = async (payload: Record<string, any>): Promise<void> => {
47
51
  if (!this._calledFromSave) {
@@ -98,7 +102,13 @@ export class Poi extends BaseEntity<PoiItemNormalized> {
98
102
 
99
103
  async addPoi(data: Partial<AddPoiData> = {}): Promise<unknown> {
100
104
 
101
- if (!this.isMe && this.parent) {
105
+ // Si le parent direct n'est pas l'utilisateur connecté (ex: création via une org),
106
+ // on injecte le parent dans le payload. Sans ça, le default schéma `{ "@userId": ... }`
107
+ // pose me comme parent — ce qui est faux pour `me.org().poi()`.
108
+ // NB: this.isMe est trompeur ici car userContext propage jusqu'au User connecté
109
+ // (donc isMe=true même quand le parent direct est une org).
110
+ // Si le caller fournit déjà `data.parent`, on respecte sa valeur (pas de merge automatique).
111
+ if (this.parent && this.parent.id && this.parent.id !== this.userId && !(data as any).parent) {
102
112
  (data as any).parent = {};
103
113
  (data as any).parent[`${this.parent.id}`] = {
104
114
  type: this.parent.getEntityType(),
@@ -125,8 +125,13 @@ export class Project extends BaseEntity<ProjectItemNormalized> {
125
125
  */
126
126
  async addProject(data: Partial<AddProjectData> = {}): Promise<unknown> {
127
127
 
128
- // le parent n'est pas me donc on doit ajouter le parent
129
- if (!this.isMe && this.parent) {
128
+ // Si le parent direct n'est pas l'utilisateur connecté (ex: création via une org),
129
+ // on injecte le parent dans le payload. Sans ça, le default schéma `{ "@userId": ... }`
130
+ // pose me comme parent — ce qui est faux pour `me.org().project()`.
131
+ // NB: this.isMe est trompeur ici car userContext propage jusqu'au User connecté
132
+ // (donc isMe=true même quand le parent direct est une org).
133
+ // Si le caller fournit déjà `data.parent`, on respecte sa valeur (pas de merge automatique).
134
+ if (this.parent && this.parent.id && this.parent.id !== this.userId && !data.parent) {
130
135
  data.parent = {};
131
136
  data.parent[`${this.parent.id}`] = {
132
137
  type: this.parent.getEntityType(),
package/src/api/User.ts CHANGED
@@ -112,6 +112,7 @@ export class User extends BaseEntity<UserItemNormalized> {
112
112
  News: typeof import("./News.js").News;
113
113
  Comment: typeof import("./Comment.js").Comment;
114
114
  Answer: typeof import("./Answer.js").Answer;
115
+ Classified?: typeof import("./Classified.js").Classified;
115
116
  }
116
117
  ) {
117
118
  if(!deps.EndpointApi){
@@ -2,6 +2,7 @@ import ApiClient from "../ApiClient.js";
2
2
  import { ApiError, ApiResponseError } from "../error.js";
3
3
  import { Answer } from "./Answer.js";
4
4
  import { Badge } from "./Badge.js";
5
+ import { Classified } from "./Classified.js";
5
6
  import { Comment } from "./Comment.js";
6
7
  import EndpointApi from "./EndpointApi.js";
7
8
  import { Event } from "./Event.js";
@@ -67,7 +68,7 @@ export class UserApi {
67
68
  this.loggedUser = new User(
68
69
  this.client,
69
70
  response.data.user,
70
- { EndpointApi, Organization, Project, Event, Poi, Badge, News, Comment, Answer }
71
+ { EndpointApi, Organization, Project, Event, Poi, Badge, News, Comment, Answer, Classified }
71
72
  );
72
73
  return this.loggedUser;
73
74
  });
@@ -89,7 +90,7 @@ export class UserApi {
89
90
  this.loggedUser = new User(
90
91
  this.client,
91
92
  { id: this.client.userId },
92
- { EndpointApi, Organization, Project, Event, Poi, Badge, News, Comment, Answer }
93
+ { EndpointApi, Organization, Project, Event, Poi, Badge, News, Comment, Answer, Classified }
93
94
  );
94
95
 
95
96
  return this.loggedUser;
@@ -0,0 +1,152 @@
1
+ import type {
2
+ GeoCoordinates,
3
+ GeoPosition,
4
+ IdObject,
5
+ ParentsMap,
6
+ PostalAddress,
7
+ DateValue
8
+ } from "./common.js";
9
+ import type EJSONType from "../../EJSONType.js";
10
+
11
+ type ObjectIDCtor = typeof EJSONType["ObjectID"];
12
+ type ObjectID = InstanceType<ObjectIDCtor>;
13
+
14
+ // ============================================================================
15
+ // SECTIONS
16
+ // ============================================================================
17
+
18
+ export const CLASSIFIED_SECTIONS = ["need", "offer"] as const;
19
+ export type ClassifiedSection = (typeof CLASSIFIED_SECTIONS)[number];
20
+
21
+ // ============================================================================
22
+ // CATÉGORIES
23
+ // ============================================================================
24
+
25
+ export const CLASSIFIED_CATEGORIES = ["service", "competence", "material"] as const;
26
+ export type ClassifiedCategory = (typeof CLASSIFIED_CATEGORIES)[number];
27
+
28
+ // ============================================================================
29
+ // SOUS-CATÉGORIES
30
+ // ============================================================================
31
+
32
+ export interface ClassifiedSubcatEntry {
33
+ key: string;
34
+ label: string;
35
+ icon: string;
36
+ }
37
+
38
+ export interface ClassifiedCategoryDef {
39
+ key: ClassifiedCategory;
40
+ icon: string;
41
+ label: string;
42
+ subcat: Record<string, ClassifiedSubcatEntry>;
43
+ }
44
+
45
+ export const CLASSIFIED_SUBCATEGORIES: Record<ClassifiedCategory, ClassifiedCategoryDef> = {
46
+ service: {
47
+ key: "service",
48
+ icon: "cogs",
49
+ label: "Service",
50
+ subcat: {
51
+ charity: { key: "charity", label: "Charité", icon: "heart" },
52
+ education: { key: "education", label: "Aide éducative", icon: "book" },
53
+ househelp: { key: "househelp", label: "Aide ménagère", icon: "home" },
54
+ washing: { key: "washing", label: "Lavage", icon: "droplets" },
55
+ gardening: { key: "gardening", label: "Jardinage", icon: "flower" },
56
+ farming: { key: "farming", label: "Agriculture", icon: "wheat" },
57
+ generalmaintenance: { key: "generalmaintenance", label: "Maintenance générale", icon: "wrench" },
58
+ childrencare: { key: "childrencare", label: "Garde d'enfants", icon: "baby" },
59
+ ederlycare: { key: "ederlycare", label: "Aide aux personnes âgées", icon: "user" },
60
+ disabledcare: { key: "disabledcare", label: "Aide aux personnes en situation de handicap", icon: "accessibility" },
61
+ hostinghelp: { key: "hostinghelp", label: "Aide à l'accueil", icon: "handshake" },
62
+ animalcare: { key: "animalcare", label: "Soins aux animaux", icon: "paw-print" },
63
+ },
64
+ },
65
+ competence: {
66
+ key: "competence",
67
+ icon: "bookmark",
68
+ label: "Compétence",
69
+ subcat: {
70
+ artistic: { key: "artistic", label: "Artistique", icon: "palette" },
71
+ laws: { key: "laws", label: "Droit", icon: "scale" },
72
+ itdevlopment: { key: "itdevlopment", label: "Développement informatique", icon: "code" },
73
+ handcraft: { key: "handcraft", label: "Artisanat", icon: "scissors" },
74
+ animalcare: { key: "animalcare", label: "Soins aux animaux", icon: "paw-print" },
75
+ agriculture: { key: "agriculture", label: "Agriculture", icon: "wheat" },
76
+ restauration: { key: "restauration", label: "Restauration", icon: "utensils" },
77
+ building: { key: "building", label: "Construction", icon: "hard-hat" },
78
+ },
79
+ },
80
+ material: {
81
+ key: "material",
82
+ icon: "wrench",
83
+ label: "Matériel",
84
+ subcat: {
85
+ electronic: { key: "electronic", label: "Électronique", icon: "cpu" },
86
+ furniture: { key: "furniture", label: "Mobilier", icon: "armchair" },
87
+ primaryressources: { key: "primaryressources", label: "Ressources primaires", icon: "leaf" },
88
+ buildingtools: { key: "buildingtools", label: "Outils de construction", icon: "hammer" },
89
+ gardeningtools: { key: "gardeningtools", label: "Outils de jardinage", icon: "shovel" },
90
+ medicalstuff: { key: "medicalstuff", label: "Matériel médical", icon: "stethoscope" },
91
+ },
92
+ },
93
+ };
94
+
95
+ // Union des clés de sous-catégories
96
+ export type ServiceSubcat = keyof typeof CLASSIFIED_SUBCATEGORIES.service.subcat;
97
+ export type CompetenceSubcat = keyof typeof CLASSIFIED_SUBCATEGORIES.competence.subcat;
98
+ export type MaterialSubcat = keyof typeof CLASSIFIED_SUBCATEGORIES.material.subcat;
99
+ export type ClassifiedSubcat = ServiceSubcat | CompetenceSubcat | MaterialSubcat;
100
+
101
+ // ============================================================================
102
+ // INTERFACES JSON / NORMALISÉES
103
+ // ============================================================================
104
+
105
+ export interface ClassifiedItemJson {
106
+ _id: IdObject;
107
+ collection: "classifieds";
108
+ name: string;
109
+ section: ClassifiedSection;
110
+ category: ClassifiedCategory;
111
+ subtype: ClassifiedSubcat;
112
+ created?: DateValue;
113
+ updated?: DateValue;
114
+ modified?: DateValue;
115
+ parent?: ParentsMap;
116
+ description?: string;
117
+ slug?: string;
118
+ address?: PostalAddress;
119
+ geo?: GeoCoordinates;
120
+ geoPosition?: GeoPosition;
121
+ tags?: string[];
122
+ creator?: string;
123
+ profilImageUrl?: string;
124
+ profilMediumImageUrl?: string;
125
+ profilThumbImageUrl?: string;
126
+ [key: string]: unknown;
127
+ }
128
+
129
+ export interface ClassifiedItemNormalized {
130
+ id: string;
131
+ _id: ObjectID;
132
+ collection: "classifieds";
133
+ name: string;
134
+ section: ClassifiedSection;
135
+ category: ClassifiedCategory;
136
+ subtype: ClassifiedSubcat;
137
+ created?: Date;
138
+ updated?: Date;
139
+ modified?: Date;
140
+ parent?: ParentsMap;
141
+ description?: string;
142
+ slug?: string;
143
+ address?: PostalAddress;
144
+ geo?: GeoCoordinates;
145
+ geoPosition?: GeoPosition;
146
+ tags?: string[];
147
+ creator?: string;
148
+ profilImageUrl?: string;
149
+ profilMediumImageUrl?: string;
150
+ profilThumbImageUrl?: string;
151
+ [key: string]: unknown;
152
+ }