Skip to content

Commit d8f63a5

Browse files
committed
feat(api): add contact note
1 parent 256d43b commit d8f63a5

File tree

2 files changed

+199
-105
lines changed

2 files changed

+199
-105
lines changed

lib/models/contact.dart

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import '/imports.dart';
22

3-
class ListContactMeta extends ApiListMeta {
4-
const ListContactMeta({
5-
required super.count,
6-
required super.current_page,
3+
class ContactNoteInfo {
4+
final int id;
5+
final String content;
6+
final DateTime created_at;
7+
final DateTime updated_at;
8+
9+
ContactNoteInfo({
10+
required this.id,
11+
required this.content,
12+
required this.created_at,
13+
required this.updated_at,
714
});
815

9-
factory ListContactMeta.fromJson(dynamic json) {
10-
var base = ApiListMeta.fromJson(json);
11-
return ListContactMeta(
12-
count: base.count,
13-
current_page: base.current_page,
16+
factory ContactNoteInfo.fromJson(dynamic json) {
17+
return ContactNoteInfo(
18+
id: json['id'],
19+
content: json['content'],
20+
created_at: toDateTime(json['created_at'])!,
21+
updated_at: toDateTime(json['updated_at'])!,
1422
);
1523
}
1624
}
@@ -70,13 +78,6 @@ class ContactInfo {
7078
});
7179

7280
factory ContactInfo.fromJson(dynamic json) {
73-
var created_at = json['created_at'] != null
74-
? DateTime.fromMillisecondsSinceEpoch(json['created_at'] * 1000)
75-
: null;
76-
var last_activity_at = json['last_activity_at'] != null
77-
? DateTime.fromMillisecondsSinceEpoch(json['last_activity_at'] * 1000)
78-
: null;
79-
8081
return ContactInfo(
8182
id: json['id'],
8283
email: json['email'],
@@ -87,8 +88,23 @@ class ContactInfo {
8788
additional_attributes:
8889
ContactAdditionalAttributes.fromJson(json['additional_attributes']),
8990
custom_attributes: json['custom_attributes'] ?? {},
90-
created_at: created_at,
91-
last_activity_at: last_activity_at,
91+
created_at: toDateTime(json['created_at']),
92+
last_activity_at: toDateTime(json['last_activity_at']),
93+
);
94+
}
95+
}
96+
97+
class ListContactMeta extends ApiListMeta {
98+
const ListContactMeta({
99+
required super.count,
100+
required super.current_page,
101+
});
102+
103+
factory ListContactMeta.fromJson(dynamic json) {
104+
var base = ApiListMeta.fromJson(json);
105+
return ListContactMeta(
106+
count: base.count,
107+
current_page: base.current_page,
92108
);
93109
}
94110
}

lib/services/api.dart

Lines changed: 165 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,9 @@ class ApiService extends GetxService {
127127
'[${error.requestOptions.method}] ${error.requestOptions.uri}');
128128
_logger.w(error, stackTrace: error.stackTrace);
129129

130-
// TODO: custom error not work
131-
// https://github.com/cfug/dio/issues/1950
130+
// TODO: Workaround because handler.reject() doesn't work properly
131+
// See: https://github.com/cfug/dio/issues/1950
132+
// For now, just pass the error through
132133
// return handler.reject(ApiError.fromException(error));
133134

134135
return handler.next(error);
@@ -812,6 +813,168 @@ class ApiService extends GetxService {
812813
}
813814
}
814815

816+
Future<Result<bool>> createContactNote({
817+
int? account_id,
818+
required int contact_id,
819+
required String content,
820+
}) async {
821+
try {
822+
account_id ??= _getAuth.profile.value!.account_id;
823+
824+
final path = '/accounts/$account_id/contacts/$contact_id/notes';
825+
await _http.post(
826+
path,
827+
data: {
828+
'content': content,
829+
},
830+
);
831+
832+
return true.toSuccess();
833+
} on DioException catch (error) {
834+
return ApiError.fromException(error).toFailure();
835+
} on Exception catch (error) {
836+
return error.toFailure();
837+
}
838+
}
839+
840+
Future<Result<List<ContactNoteInfo>>> listContactNotes({
841+
int? account_id,
842+
required int contact_id,
843+
Function(List<ContactNoteInfo> data)? onCacheHit,
844+
}) async {
845+
try {
846+
account_id ??= _getAuth.profile.value!.account_id;
847+
848+
final path = '/accounts/$account_id/contacts/$contact_id/notes';
849+
850+
// if onCacheHit defined
851+
if (onCacheHit != null) {
852+
var cached = await getCache(url: path);
853+
if (cached != null) {
854+
List<dynamic> items = jsonDecode(cached.data);
855+
var transformedData = items.map(ContactNoteInfo.fromJson).toList();
856+
onCacheHit(transformedData);
857+
}
858+
}
859+
860+
final response = await _http.get(path);
861+
862+
// if onCacheHit defined
863+
if (onCacheHit != null) saveCache(url: path, data: response.data);
864+
865+
List<dynamic> items = response.data;
866+
return items.map(ContactNoteInfo.fromJson).toList().toSuccess();
867+
} on DioException catch (error) {
868+
return ApiError.fromException(error).toFailure();
869+
} on Exception catch (error) {
870+
return error.toFailure();
871+
}
872+
}
873+
874+
Future<Result<bool>> deleteContactNote({
875+
int? account_id,
876+
required int contact_id,
877+
required int note_id,
878+
}) async {
879+
try {
880+
account_id ??= _getAuth.profile.value!.account_id;
881+
882+
final path = '/accounts/$account_id/contacts/$contact_id/notes/$note_id';
883+
await _http.delete(path);
884+
885+
return true.toSuccess();
886+
} on DioException catch (error) {
887+
return ApiError.fromException(error).toFailure();
888+
} on Exception catch (error) {
889+
return error.toFailure();
890+
}
891+
}
892+
893+
Future<Result<List<String>>> getContactLabels({
894+
int? account_id,
895+
required int contact_id,
896+
Function(List<String> data)? onCacheHit,
897+
}) async {
898+
try {
899+
account_id ??= _getAuth.profile.value!.account_id;
900+
final path = '/accounts/$account_id/contacts/$contact_id/labels';
901+
902+
// if onCacheHit defined
903+
if (onCacheHit != null) {
904+
final cached = await getCache(url: path);
905+
if (cached != null) {
906+
List<dynamic> items = jsonDecode(cached.data)['payload'];
907+
final transformedData = items.map((e) => e.toString()).toList();
908+
onCacheHit(transformedData);
909+
}
910+
}
911+
912+
final result = await _http.get(path);
913+
List<dynamic> items = result.data['payload'];
914+
915+
// if onCacheHit defined
916+
if (onCacheHit != null) saveCache(url: path, data: result.data);
917+
918+
return items.map((e) => e.toString()).toList().toSuccess();
919+
} on DioException catch (error) {
920+
return ApiError.fromException(error).toFailure();
921+
} on Exception catch (error) {
922+
return error.toFailure();
923+
}
924+
}
925+
926+
Future<Result<bool>> updateContactLabels({
927+
int? account_id,
928+
required int contact_id,
929+
required List<String> labels,
930+
}) async {
931+
try {
932+
account_id ??= _getAuth.profile.value!.account_id;
933+
final path = '/accounts/$account_id/contacts/$contact_id/labels';
934+
935+
await _http.post(path, data: {'labels': labels});
936+
937+
return true.toSuccess();
938+
} on DioException catch (error) {
939+
return ApiError.fromException(error).toFailure();
940+
} on Exception catch (error) {
941+
return error.toFailure();
942+
}
943+
}
944+
945+
Future<Result<List<ConversationInfo>>> getContactConversations({
946+
int? account_id,
947+
required int contact_id,
948+
Function(List<ConversationInfo> data)? onCacheHit,
949+
}) async {
950+
try {
951+
account_id ??= _getAuth.profile.value!.account_id;
952+
final path = '/accounts/$account_id/contacts/$contact_id/conversations';
953+
954+
// if onCacheHit defined
955+
if (onCacheHit != null) {
956+
final cached = await getCache(url: path);
957+
if (cached != null) {
958+
List<dynamic> items = jsonDecode(cached.data)['payload'];
959+
final transformedData = items.map(ConversationInfo.fromJson).toList();
960+
onCacheHit(transformedData);
961+
}
962+
}
963+
964+
final result = await _http.get(path);
965+
List<dynamic> items = result.data['payload'];
966+
967+
// if onCacheHit defined
968+
if (onCacheHit != null) saveCache(url: path, data: result.data);
969+
970+
return items.map(ConversationInfo.fromJson).toList().toSuccess();
971+
} on DioException catch (error) {
972+
return ApiError.fromException(error).toFailure();
973+
} on Exception catch (error) {
974+
return error.toFailure();
975+
}
976+
}
977+
815978
Future<Result<List<CustomAttribute>>> listCustomAttributes({
816979
int? account_id,
817980
AttributeModel? attribute_model,
@@ -1216,91 +1379,6 @@ class ApiService extends GetxService {
12161379
}
12171380
}
12181381

1219-
Future<Result<List<String>>> getContactLabels({
1220-
int? account_id,
1221-
required int contact_id,
1222-
Function(List<String> data)? onCacheHit,
1223-
}) async {
1224-
try {
1225-
account_id ??= _getAuth.profile.value!.account_id;
1226-
final path = '/accounts/$account_id/contacts/$contact_id/labels';
1227-
1228-
// if onCacheHit defined
1229-
if (onCacheHit != null) {
1230-
final cached = await getCache(url: path);
1231-
if (cached != null) {
1232-
List<dynamic> items = jsonDecode(cached.data)['payload'];
1233-
final transformedData = items.map((e) => e.toString()).toList();
1234-
onCacheHit(transformedData);
1235-
}
1236-
}
1237-
1238-
final result = await _http.get(path);
1239-
List<dynamic> items = result.data['payload'];
1240-
1241-
// if onCacheHit defined
1242-
if (onCacheHit != null) saveCache(url: path, data: result.data);
1243-
1244-
return items.map((e) => e.toString()).toList().toSuccess();
1245-
} on DioException catch (error) {
1246-
return ApiError.fromException(error).toFailure();
1247-
} on Exception catch (error) {
1248-
return error.toFailure();
1249-
}
1250-
}
1251-
1252-
Future<Result<bool>> updateContactLabels({
1253-
int? account_id,
1254-
required int contact_id,
1255-
required List<String> labels,
1256-
}) async {
1257-
try {
1258-
account_id ??= _getAuth.profile.value!.account_id;
1259-
final path = '/accounts/$account_id/contacts/$contact_id/labels';
1260-
1261-
await _http.post(path, data: {'labels': labels});
1262-
1263-
return true.toSuccess();
1264-
} on DioException catch (error) {
1265-
return ApiError.fromException(error).toFailure();
1266-
} on Exception catch (error) {
1267-
return error.toFailure();
1268-
}
1269-
}
1270-
1271-
Future<Result<List<ConversationInfo>>> getContactConversations({
1272-
int? account_id,
1273-
required int contact_id,
1274-
Function(List<ConversationInfo> data)? onCacheHit,
1275-
}) async {
1276-
try {
1277-
account_id ??= _getAuth.profile.value!.account_id;
1278-
final path = '/accounts/$account_id/contacts/$contact_id/conversations';
1279-
1280-
// if onCacheHit defined
1281-
if (onCacheHit != null) {
1282-
final cached = await getCache(url: path);
1283-
if (cached != null) {
1284-
List<dynamic> items = jsonDecode(cached.data)['payload'];
1285-
final transformedData = items.map(ConversationInfo.fromJson).toList();
1286-
onCacheHit(transformedData);
1287-
}
1288-
}
1289-
1290-
final result = await _http.get(path);
1291-
List<dynamic> items = result.data['payload'];
1292-
1293-
// if onCacheHit defined
1294-
if (onCacheHit != null) saveCache(url: path, data: result.data);
1295-
1296-
return items.map(ConversationInfo.fromJson).toList().toSuccess();
1297-
} on DioException catch (error) {
1298-
return ApiError.fromException(error).toFailure();
1299-
} on Exception catch (error) {
1300-
return error.toFailure();
1301-
}
1302-
}
1303-
13041382
Future<Result<List<TeamInfo>>> listTeams({
13051383
int? account_id,
13061384
Function(List<TeamInfo> data)? onCacheHit,

0 commit comments

Comments
 (0)