feat: Add _getMap and _postMap methods for improved API handling and refactor resetPassword to use _postMap
Test Suite / test (24.15.0) (push) Has been cancelled
Test Suite / test (24.15.0) (push) Has been cancelled
This commit is contained in:
@@ -42,7 +42,7 @@ class AdminRepository {
|
|||||||
return _parseList(data, fromJson);
|
return _parseList(data, fromJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// POST-anrop som returnerar ett typad objekt med [fromJson].
|
/// POST-anrop som returnerar ett typat objekt med [fromJson].
|
||||||
Future<T> _post<T>(
|
Future<T> _post<T>(
|
||||||
String path, {
|
String path, {
|
||||||
required Map<String, dynamic>? body,
|
required Map<String, dynamic>? body,
|
||||||
@@ -57,7 +57,7 @@ class AdminRepository {
|
|||||||
return parse(data);
|
return parse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PATCH-anrop som returnerar ett typad objekt med [fromJson].
|
/// PATCH-anrop som returnerar ett typat objekt med [fromJson].
|
||||||
Future<T> _patch<T>(
|
Future<T> _patch<T>(
|
||||||
String path, {
|
String path, {
|
||||||
required Map<String, dynamic> body,
|
required Map<String, dynamic> body,
|
||||||
@@ -98,6 +98,31 @@ class AdminRepository {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> _getMap(
|
||||||
|
String path, {
|
||||||
|
bool requiresAuth = true,
|
||||||
|
}) async {
|
||||||
|
final token = requiresAuth ? await _token() : null;
|
||||||
|
final data = await guardedApiCall(
|
||||||
|
_ref,
|
||||||
|
() => _apiClient.getJson(path, token: token),
|
||||||
|
);
|
||||||
|
return Map<String, dynamic>.from(data as Map);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> _postMap(
|
||||||
|
String path, {
|
||||||
|
Map<String, dynamic>? body,
|
||||||
|
bool requiresAuth = true,
|
||||||
|
}) async {
|
||||||
|
final token = requiresAuth ? await _token() : null;
|
||||||
|
final data = await guardedApiCall(
|
||||||
|
_ref,
|
||||||
|
() => _apiClient.postJson(path, body: body, token: token),
|
||||||
|
);
|
||||||
|
return Map<String, dynamic>.from(data as Map);
|
||||||
|
}
|
||||||
|
|
||||||
/// Tolerant listparsning — accepterar ren lista eller wrapper ({items, data}).
|
/// Tolerant listparsning — accepterar ren lista eller wrapper ({items, data}).
|
||||||
static List<T> _parseList<T>(
|
static List<T> _parseList<T>(
|
||||||
dynamic data,
|
dynamic data,
|
||||||
@@ -164,17 +189,16 @@ class AdminRepository {
|
|||||||
|
|
||||||
/// Returns `{ temporaryPassword, to, subject, body }`.
|
/// Returns `{ temporaryPassword, to, subject, body }`.
|
||||||
Future<Map<String, dynamic>> resetPassword(int userId) =>
|
Future<Map<String, dynamic>> resetPassword(int userId) =>
|
||||||
_post<Map<String, dynamic>>(
|
_postMap(UserApiPaths.resetPassword(userId), body: null);
|
||||||
UserApiPaths.resetPassword(userId),
|
|
||||||
body: null,
|
|
||||||
parse: (d) => d as Map<String, dynamic>,
|
|
||||||
);
|
|
||||||
|
|
||||||
// ── Produkter ──────────────────────────────────────────────────────────────
|
// ── Produkter ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
Future<List<AdminProduct>> listProducts() =>
|
Future<List<AdminProduct>> listProducts() =>
|
||||||
_getList(ProductApiPaths.list, AdminProduct.fromJson, requiresAuth: false);
|
_getList(ProductApiPaths.list, AdminProduct.fromJson, requiresAuth: false);
|
||||||
|
|
||||||
|
@Deprecated('Use listProducts(). Kept for temporary compatibility.')
|
||||||
|
Future<List<AdminProduct>> listGlobalProducts() => listProducts();
|
||||||
|
|
||||||
Future<List<PendingProduct>> listPrivateProducts() =>
|
Future<List<PendingProduct>> listPrivateProducts() =>
|
||||||
_getList(ProductApiPaths.privateList, PendingProduct.fromJson);
|
_getList(ProductApiPaths.privateList, PendingProduct.fromJson);
|
||||||
|
|
||||||
@@ -204,8 +228,6 @@ class AdminRepository {
|
|||||||
_postVoid(ProductApiPaths.restore(productId));
|
_postVoid(ProductApiPaths.restore(productId));
|
||||||
|
|
||||||
// ── Product canonical name updates ────────────────────────────────────────
|
// ── Product canonical name updates ────────────────────────────────────────
|
||||||
// Admin can update any product; users can only update their own private products
|
|
||||||
|
|
||||||
Future<void> updateCanonicalName(int productId, String canonicalName) =>
|
Future<void> updateCanonicalName(int productId, String canonicalName) =>
|
||||||
_patchVoid(
|
_patchVoid(
|
||||||
ProductApiPaths.canonicalName(productId),
|
ProductApiPaths.canonicalName(productId),
|
||||||
@@ -219,8 +241,6 @@ class AdminRepository {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// ── Product merging ────────────────────────────────────────────────────────
|
// ── Product merging ────────────────────────────────────────────────────────
|
||||||
// Admin can merge any products; users can only merge their own private products
|
|
||||||
|
|
||||||
Future<void> mergeProductsPrivate({
|
Future<void> mergeProductsPrivate({
|
||||||
required int sourceProductId,
|
required int sourceProductId,
|
||||||
required int targetProductId,
|
required int targetProductId,
|
||||||
@@ -232,23 +252,28 @@ class AdminRepository {
|
|||||||
|
|
||||||
/// Skapar en ny aktiv produkt (kräver admin). Returnerar `{id, name, categoryId?}`.
|
/// Skapar en ny aktiv produkt (kräver admin). Returnerar `{id, name, categoryId?}`.
|
||||||
Future<Map<String, dynamic>> createProduct(String name, {int? categoryId}) =>
|
Future<Map<String, dynamic>> createProduct(String name, {int? categoryId}) =>
|
||||||
_post<Map<String, dynamic>>(
|
_postMap(
|
||||||
ProductApiPaths.list,
|
ProductApiPaths.list,
|
||||||
body: {
|
body: {
|
||||||
'name': name.trim(),
|
'name': name.trim(),
|
||||||
if (categoryId != null) 'categoryId': categoryId,
|
if (categoryId != null) 'categoryId': categoryId,
|
||||||
},
|
},
|
||||||
parse: (d) => d as Map<String, dynamic>,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
int _parseUpdatedCount(dynamic data) {
|
||||||
|
if (data is! Map) {
|
||||||
|
debugPrint('[AdminRepository] bulkSetCategory unexpected response type: ${data.runtimeType}');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
final map = Map<String, dynamic>.from(data);
|
||||||
|
return (map['updated'] as num?)?.toInt() ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
Future<int> bulkSetCategory(List<int> ids, {required int? categoryId}) =>
|
Future<int> bulkSetCategory(List<int> ids, {required int? categoryId}) =>
|
||||||
_post<int>(
|
_post<int>(
|
||||||
ProductApiPaths.bulkUpdate,
|
ProductApiPaths.bulkUpdate,
|
||||||
body: {'ids': ids, 'categoryId': categoryId},
|
body: {'ids': ids, 'categoryId': categoryId},
|
||||||
parse: (d) {
|
parse: _parseUpdatedCount,
|
||||||
final map = Map<String, dynamic>.from(d as Map);
|
|
||||||
return (map['updated'] as num?)?.toInt() ?? 0;
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<void> mergeProducts({
|
Future<void> mergeProducts({
|
||||||
@@ -263,17 +288,8 @@ class AdminRepository {
|
|||||||
Future<Map<String, dynamic>> previewMerge({
|
Future<Map<String, dynamic>> previewMerge({
|
||||||
required int sourceProductId,
|
required int sourceProductId,
|
||||||
required int targetProductId,
|
required int targetProductId,
|
||||||
}) async {
|
}) =>
|
||||||
final token = await _token();
|
_getMap(ProductApiPaths.mergePreview(sourceProductId, targetProductId));
|
||||||
final data = await guardedApiCall(
|
|
||||||
_ref,
|
|
||||||
() => _apiClient.getJson(
|
|
||||||
ProductApiPaths.mergePreview(sourceProductId, targetProductId),
|
|
||||||
token: token,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return Map<String, dynamic>.from(data as Map);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<AdminAiCategorizeResult>> aiCategorizeBulk({
|
Future<List<AdminAiCategorizeResult>> aiCategorizeBulk({
|
||||||
List<int>? productIds,
|
List<int>? productIds,
|
||||||
@@ -438,15 +454,8 @@ class AdminRepository {
|
|||||||
Future<Map<String, dynamic>> previewAdminInventoryMerge({
|
Future<Map<String, dynamic>> previewAdminInventoryMerge({
|
||||||
required int sourceInventoryId,
|
required int sourceInventoryId,
|
||||||
required int targetInventoryId,
|
required int targetInventoryId,
|
||||||
}) async {
|
}) =>
|
||||||
final token = await _token();
|
_getMap(
|
||||||
final data = await guardedApiCall(
|
|
||||||
_ref,
|
|
||||||
() => _apiClient.getJson(
|
|
||||||
AdminInventoryApiPaths.mergePreview(sourceInventoryId, targetInventoryId),
|
AdminInventoryApiPaths.mergePreview(sourceInventoryId, targetInventoryId),
|
||||||
token: token,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return Map<String, dynamic>.from(data as Map);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user