# دليل التكامل — Flutter

## 1. إعداد المشروع

### pubspec.yaml (مقترح)

```yaml
dependencies:
  dio: ^5.4.0
  flutter_secure_storage: ^9.0.0
  json_annotation: ^4.8.1

dev_dependencies:
  json_serializable: ^6.7.1
  build_runner: ^2.4.8
```

### ثابت Base URL

```dart
class ApiConfig {
  static const baseUrl = 'https://pod.sayedkhattab.com';
  static const appPrefix = '/api/app';
  static String get apiBase => '$baseUrl$appPrefix';
  static String resolveUrl(String? path) {
    if (path == null || path.isEmpty) return '';
    if (path.startsWith('http')) return path;
    return '$baseUrl$path';
  }
}
```

---

## 2. عميل HTTP (Dio)

```dart
import 'package:dio/dio.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

class ArkanApiClient {
  ArkanApiClient() {
    _dio = Dio(BaseOptions(
      baseUrl: ApiConfig.apiBase,
      connectTimeout: const Duration(seconds: 20),
      receiveTimeout: const Duration(seconds: 30),
      headers: {'Accept': 'application/json'},
    ));
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) async {
        final token = await _storage.read(key: 'auth_token');
        if (token != null) {
          options.headers['Authorization'] = 'Bearer $token';
        }
        handler.next(options);
      },
      onError: (error, handler) {
        // 401 → logout / navigate to login
        handler.next(error);
      },
    ));
  }

  late final Dio _dio;
  final _storage = const FlutterSecureStorage();

  Future<void> saveToken(String token) =>
      _storage.write(key: 'auth_token', value: token);

  Future<void> clearToken() => _storage.delete(key: 'auth_token');

  Dio get dio => _dio;
}
```

---

## 3. تدفق المصادقة

```dart
Future<User> login(String email, String password) async {
  final res = await client.dio.post('/auth/login', data: {
    'email': email,
    'password': password,
  });
  final token = res.data['token'] as String;
  await client.saveToken(token);
  return User.fromJson(res.data['user']);
}
```

عند **401** على أي طلب: امسح التوكن ووجّه لشاشة الدخول.

---

## 4. تحميل الصور

```dart
Image.network(ApiConfig.resolveUrl(product.imageUrl))
```

Banners و gallery designs تستخدم نفس الدالة.

---

## 5. رفع تصميم (multipart)

```dart
Future<UploadResult> uploadDesign(String filePath) async {
  final form = FormData.fromMap({
    'image': await MultipartFile.fromFile(filePath, filename: 'design.png'),
  });
  final res = await client.dio.post(
    '/uploads/design',
    data: form,
    options: Options(contentType: 'multipart/form-data'),
  );
  return UploadResult.fromJson(res.data);
}

Future<Design> registerDesign(String fileUrl, {String? title}) async {
  final res = await client.dio.post('/designs', data: {
    'title': title,
    'file_url': fileUrl,
    'preview_url': fileUrl,
  });
  return Design.fromJson(res.data);
}
```

**التدفق:** رفع ملف → `POST /designs` → انتظار `status: approved` → استخدام `design_id` في الطلب.

---

## 6. الخريطة ومناطق التوصيل

1. `GET /zones` — ارسم المضلعات على الخريطة (GeoJSON)
2. عند اختيار موقع العميل → `POST /zones/check` أو أرسل `lat`/`lng` في checkout
3. استخدم `map_default_lat/lng/zoom` من `/home` للمركز الافتراضي

---

## 7. السلة (Client-side)

لا يوجد API سلة على الخادم. احفظ السلة محلياً (SharedPreferences / Hive):

```dart
class CartItem {
  final int productId;
  final int? variantId;
  final int quantity;
  final int? designId;
  final int? galleryDesignId;
  final Map<String, dynamic>? printConfig;
}
```

---

## 8. Checkout

```dart
// 1. حساب السعر
final quote = await client.dio.post('/checkout/quote', data: buildPayload());

// 2. عرض للمستخدم: subtotal, discount, shipping, total

// 3. تأكيد
final order = await client.dio.post('/checkout', data: {
  ...buildPayload(),
  'shipping_name': name,
  'shipping_phone': phone,
  'shipping_address': address,
  'notes': notes,
});
```

راجع [CHECKOUT_FLOW.md](./CHECKOUT_FLOW.md) للتفاصيل.

---

## 9. Banners — التنقل

```dart
void onBannerTap(Banner banner) {
  switch (banner.linkType) {
    case 'product':
      navigateToProduct(int.parse(banner.linkValue!));
    case 'category':
      navigateToCategory(int.parse(banner.linkValue!));
    case 'url':
      launchUrl(Uri.parse(banner.linkValue!));
    default:
      break;
  }
}
```

---

## 10. CORS والمنصات

| المنصة | ملاحظة |
|--------|--------|
| **Android / iOS** | لا CORS — يعمل مباشرة |
| **Flutter Web** | قد تحتاج إضافة origin في `CORS_ORIGIN` على الخادم |

---

## 11. معالجة الأخطاء

```dart
String errorMessage(DioException e) {
  final data = e.response?.data;
  if (data is Map && data['message'] != null) {
    return data['message'] as String;
  }
  return 'حدث خطأ. حاول مرة أخرى';
}
```

---

## 12. Checklist قبل الإطلاق

- [ ] تخزين آمن للتوكن
- [ ] التحقق من `orders_accepting` قبل checkout
- [ ] عرض حالة التصميم (`pending` / `approved` / `rejected`)
- [ ] التحقق من `stock` قبل إضافة للسلة
- [ ] إكمال Base URL للصور
- [ ] اختبار COD flow و timeline الطلب
