Приложение для Osclass на Flutter с использованием REST API

Интересные разработки

Ниже представлен базовый каркас мобильного приложения для работы с Osclass через REST API на Flutter/Dart. Это приложение будет отображать объявления и категории из вашей Osclass системы.

Основные файлы приложения

1. main.dart — Главный файл приложения

import 'package:flutter/material.dart';
import 'package:osclass_app/screens/home_screen.dart';
import 'package:osclass_app/services/api_service.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Osclass App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const HomeScreen(),
      debugShowCheckedModeBanner: false,
    );
  }
}

2. api_service.dart — Сервис для работы с API Osclass

import 'dart:convert';
import 'package:http/http.dart' as http;

class ApiService {
  static const String _baseUrl = 'https://your-osclass-site.com/api';
  static const String _apiKey = 'YOUR_API_KEY';

  Future<List<dynamic>> getLatestItems() async {
    final response = await http.get(
      Uri.parse('$_baseUrl/items/search?limit=20'),
      headers: {'Authorization': 'Bearer $_apiKey'},
    );

    if (response.statusCode == 200) {
      return json.decode(response.body)['items'];
    } else {
      throw Exception('Failed to load items');
    }
  }

  Future<List<dynamic>> getCategories() async {
    final response = await http.get(
      Uri.parse('$_baseUrl/categories'),
      headers: {'Authorization': 'Bearer $_apiKey'},
    );

    if (response.statusCode == 200) {
      return json.decode(response.body)['categories'];
    } else {
      throw Exception('Failed to load categories');
    }
  }

  Future<dynamic> getItemDetails(int itemId) async {
    final response = await http.get(
      Uri.parse('$_baseUrl/items/$itemId'),
      headers: {'Authorization': 'Bearer $_apiKey'},
    );

    if (response.statusCode == 200) {
      return json.decode(response.body);
    } else {
      throw Exception('Failed to load item details');
    }
  }
}

3. models/item_model.dart — Модель данных объявления

class Item {
  final int id;
  final String title;
  final String description;
  final double price;
  final String? imageUrl;
  final String category;
  final String location;
  final DateTime date;

  Item({
    required this.id,
    required this.title,
    required this.description,
    required this.price,
    this.imageUrl,
    required this.category,
    required this.location,
    required this.date,
  });

  factory Item.fromJson(Map<String, dynamic> json) {
    return Item(
      id: json['id'],
      title: json['title'],
      description: json['description'],
      price: double.tryParse(json['price']?.toString() ?? '0') ?? 0,
      imageUrl: json['images']?.isNotEmpty == true ? json['images'][0] : null,
      category: json['category_name'] ?? 'Unknown',
      location: json['city_name'] ?? 'Unknown location',
      date: DateTime.parse(json['dt_pub_date']),
    );
  }
}

4. screens/home_screen.dart — Главный экран приложения

import 'package:flutter/material.dart';
import 'package:osclass_app/models/item_model.dart';
import 'package:osclass_app/services/api_service.dart';
import 'package:osclass_app/widgets/item_card.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final ApiService _apiService = ApiService();
  List<Item> _items = [];
  bool _isLoading = true;

  
  void initState() {
    super.initState();
    _loadItems();
  }

  Future<void> _loadItems() async {
    try {
      final items = await _apiService.getLatestItems();
      setState(() {
        _items = items.map((json) => Item.fromJson(json)).toList();
        _isLoading = false;
      });
    } catch (e) {
      setState(() {
        _isLoading = false;
      });
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Error loading items: ${e.toString()}')),
      );
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Osclass App'),
        actions: [
          IconButton(
            icon: const Icon(Icons.search),
            onPressed: () {
              // Реализация поиска
            },
          ),
        ],
      ),
      body: _isLoading
          ? const Center(child: CircularProgressIndicator())
          : ListView.builder(
              itemCount: _items.length,
              itemBuilder: (context, index) {
                return ItemCard(item: _items[index]);
              },
            ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Переход к экрану добавления объявления
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

5. widgets/item_card.dart — Виджет карточки объявления

import 'package:flutter/material.dart';
import 'package:osclass_app/models/item_model.dart';

class ItemCard extends StatelessWidget {
  final Item item;

  const ItemCard({super.key, required this.item});

  
  Widget build(BuildContext context) {
    return Card(
      margin: const EdgeInsets.all(8.0),
      child: InkWell(
        onTap: () {
          // Переход к деталям объявления
        },
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            if (item.imageUrl != null)
              Image.network(
                item.imageUrl!,
                height: 150,
                width: double.infinity,
                fit: BoxFit.cover,
              ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    item.title,
                    style: const TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    '\$${item.price.toStringAsFixed(2)}',
                    style: const TextStyle(
                      fontSize: 16,
                      color: Colors.green,
                    ),
                  ),
                  const SizedBox(height: 4),
                  Row(
                    children: [
                      const Icon(Icons.location_on, size: 16),
                      const SizedBox(width: 4),
                      Text(item.location),
                    ],
                  ),
                  Row(
                    children: [
                      const Icon(Icons.category, size: 16),
                      const SizedBox(width: 4),
                      Text(item.category),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Настройка проекта

  1. Добавьте необходимые зависимости в pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.5
  intl: ^0.18.1
  cached_network_image: ^3.2.3
  1. Для работы с API Osclass вам нужно:

    • Установить и настроить REST API плагин для Osclass

    • Получить API ключ

    • Обновить _baseUrl и _apiKey в api_service.dart

Дополнительные возможности для реализации

  1. Экран деталей объявления

  2. Поиск по объявлениям

  3. Фильтрация по категориям

  4. Система авторизации

  5. Создание новых объявлений

  6. Избранные объявления

  7. Кэширование данных

Это базовый каркас приложения, который можно расширять в зависимости от ваших требований. Для работы с изображениями рекомендуется использовать пакет cached_network_image, а для навигации между экранами — go_router или стандартный Navigator.

Свободен!

Оцените автора
( Пока оценок нет )
Osclass
Добавить комментарий