add integration whit directus and test of conferences

This commit is contained in:
Esteban Paz 2025-06-27 17:15:01 -05:00
parent cb7b50fb33
commit 5ffec90278
9 changed files with 82 additions and 134 deletions

View File

View File

@ -2,7 +2,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:lgcc/pages/conferences.dart';
void main() {
Future main() async {
await dotenv.load(fileName: ".env");
runApp(MyApp());
}

View File

@ -1,48 +1,51 @@
// Models of Conferences for MarkDown Text
import 'dart:ffi';
class ConferencesModel {
final int id;
final String title;
final String date;
String activity;
String duration;
final DateTime date;
int activity;
int duration;
String place;
String city;
String state;
String country;
String type;
// List<String> type;
String thumb;
List<String> translations;
// List<String> translations;
ConferencesModel({
required this.id,
required this.title,
required this.date,
this.activity = '',
this.duration = '',
this.activity = 0,
this.duration = 0,
this.place = '',
this.city = '',
this.state = '',
this.country = '',
this.type = '',
// this.type = const [],
this.thumb = '',
this.translations = const [],
// this.translations = const [],
});
Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'date': DateTime.parse(date).toIso8601String(),
'date': date.toIso8601String(),
'activity': activity,
'duration': duration,
'place': place,
'city': city,
'state': state,
'country': country,
'type': type,
// 'type': type,
'thumb': thumb.toString(),
'translations': translations,
// 'translations': translations,
};
}
@ -50,16 +53,17 @@ class ConferencesModel {
return ConferencesModel(
id: json['id'],
title: json['title'],
date: DateTime.parse(json['date'] as String).toIso8601String(),
activity: json['activity'] ?? '',
duration: json['duration'] ?? '',
date: DateTime.parse(json['date'] as String),
activity: json['activity'] ?? 0,
duration: json['duration'] ?? 0,
place: json['place'] ?? '',
city: json['city'] ?? '',
state: json['state'] ?? '',
country: json['country'] ?? '',
type: json['type'] ?? '',
// type: List<String>.from(json['type'] ?? []),
thumb: json['thumb'] ?? '',
translations: List<String>.from(json['translations'] ?? []),
// translations: List<String>.from(json['translations'] ?? []),
);
}
}

View File

@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:lgcc/models/conferences_model.dart';
import 'package:lgcc/providers/conferences_db.dart';
import 'package:lgcc/providers/conferences_api.dart';
import 'package:lgcc/providers/directus_service.dart';
class ConferencesPage extends StatelessWidget {
const ConferencesPage({Key? key}) : super(key: key);
@ -22,31 +21,35 @@ class ConferencesPage extends StatelessWidget {
}
Widget _buildConferenceListView() {
final DirectusService _directusService = DirectusService();
return FutureBuilder(
future: DBProvider.db.getAllConferences(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
future: Future.wait([
_directusService.getConferences(),
]),
builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
print('Error: ${snapshot.error}');
return Center(child: Text('Error: ${snapshot.error}'));
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return const Center(child: Text('No conferences found.'));
} else {
return ListView.separated(
separatorBuilder: (context, index) => Divider(
color: Colors.black12,
),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
List<ConferencesModel> conferences = List<ConferencesModel>.from(snapshot.data![0]);
return ListView.builder(
itemCount: conferences.length,
itemBuilder: (context, index) {
final conference = conferences[index];
return ListTile(
leading: Text(
"${index + 1}",
style: TextStyle(fontSize: 20.0),
title: Text(conference.title, style: const TextStyle(fontSize: 18)),
subtitle: Text(
'${conference.date.toLocal().toString().split(' ')[0]} - ${conference.place}, ${conference.city}, ${conference.state}, ${conference.country}, ${conference.activity}',
style: const TextStyle(fontSize: 16),
),
title: Text(
"titulo: ${snapshot.data[index].title} "),
);
},
);
}
}
);
},
);
}

View File

@ -1,22 +0,0 @@
import 'package:lgcc/models/conferences_model.dart';
import 'package:lgcc/providers/conferences_db.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:dio/dio.dart';
class ConferencesApiProvider {
Future<List<ConferencesModel>> getAllConferences() async {
var url = "https://directus.carpa.com/items/conferences/1";
Response response = await Dio().get(url);
List<ConferencesModel> conferences = (response.data as List).map((conference) {
print('Inserting $conference');
return ConferencesModel.fromJson(conference);
}).toList();
for (var conference in conferences) {
DBProvider.db.createConference(conference);
}
return conferences;
}
}

View File

@ -1,65 +0,0 @@
import 'dart:io';
import 'package:lgcc/models/conferences_model.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
// This is a singleton class that provides access to the database
class DBProvider {
static Database? _database;
static final DBProvider db = DBProvider._();
DBProvider._();
Future<Database?> get database async {
// If database exists, return database
if (_database != null) return _database;
// If database don't exists, create one
_database = await initDB();
return _database;
}
// Create the database and the Employee table
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
final path = join(documentsDirectory.path, 'conferences.db');
return await openDatabase(path, version: 1, onOpen: (db) {},
onCreate: (Database db, int version) async {
await db.execute('CREATE TABLE Conferences('
'id INTEGER PRIMARY KEY,'
'title TEXT,'
'date TEXT,'
'activity TEXT,'
'duration TEXT,'
'place TEXT,'
'city TEXT,'
'state TEXT,'
'country TEXT,'
'thumb TEXT,'
'translations TEXT'
')');
});
}
// Insert conference on database
createConference(ConferencesModel newConference) async {
final db = await database;
final res = await db?.insert('Conferences', newConference.toJson());
return res;
}
Future<List<ConferencesModel>> getAllConferences() async {
final db = await database;
final res = await db?.rawQuery("SELECT * FROM Conferences");
List<ConferencesModel> list =
res!.isNotEmpty ? res.map((c) => ConferencesModel.fromJson(c)).toList() : [];
return list;
}
}

View File

@ -0,0 +1,25 @@
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:lgcc/models/conferences_model.dart';
class DirectusService {
Future<List<dynamic>> getConferences() async {
final String baseUrl = dotenv.env['DIRECTUS_API_URL']!;
final response = await http.get(
Uri.parse('$baseUrl/items/conferences?fields=*&access_token=${dotenv.env['DIRECTUS_API_TOKEN']}'),
);
assert(() {
print('Response status code: ${response.statusCode}');
return true;
}());
if (response.statusCode == 200) {
final data = jsonDecode(response.body)['data'];
return data.map((item) => ConferencesModel.fromJson(item)).toList();
} else {
throw Exception('Failed to load conferences');
}
}
}

View File

@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: async
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
url: "https://pub.dev"
source: hosted
version: "2.12.0"
version: "2.13.0"
boolean_selector:
dependency: transitive
description:
@ -69,10 +69,10 @@ packages:
dependency: transitive
description:
name: fake_async
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev"
source: hosted
version: "1.3.2"
version: "1.3.3"
ffi:
dependency: transitive
description:
@ -143,10 +143,10 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
url: "https://pub.dev"
source: hosted
version: "10.0.8"
version: "10.0.9"
leak_tracker_flutter_testing:
dependency: transitive
description:
@ -396,10 +396,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
url: "https://pub.dev"
source: hosted
version: "14.3.1"
version: "15.0.0"
web:
dependency: transitive
description:

View File

@ -24,3 +24,5 @@ dev_dependencies:
flutter:
uses-material-design: true
assets:
- .env