api start
This commit is contained in:
+90
-30
@@ -1,52 +1,112 @@
|
|||||||
|
/// Modello delle lezioni per la scuola YogaSoul.
|
||||||
|
///
|
||||||
|
/// Rispecchia il JSON prodotto da `public/api/my_lessons.php`.
|
||||||
|
/// Nota: questa app è single-school, quindi niente concetti multiscuola
|
||||||
|
/// (wallet/entries/recoveries/level) che non esistono nel DB YogaSoul.
|
||||||
|
|
||||||
|
class LessonsResponse {
|
||||||
|
final String month; // "YYYY-MM"
|
||||||
|
final LessonsSummary summary;
|
||||||
|
final List<Lesson> lessons;
|
||||||
|
|
||||||
|
LessonsResponse({
|
||||||
|
required this.month,
|
||||||
|
required this.summary,
|
||||||
|
required this.lessons,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory LessonsResponse.fromJson(Map<String, dynamic> j) {
|
||||||
|
final rawLessons = (j['lessons'] as List?) ?? const [];
|
||||||
|
return LessonsResponse(
|
||||||
|
month: (j['month'] ?? '').toString(),
|
||||||
|
summary: LessonsSummary.fromJson(
|
||||||
|
(j['summary'] as Map?)?.cast<String, dynamic>() ?? const {},
|
||||||
|
),
|
||||||
|
lessons: rawLessons
|
||||||
|
.map((e) => Lesson.fromJson((e as Map).cast<String, dynamic>()))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// I conteggi della fascia riepilogo (le "card pastello" della webapp).
|
||||||
|
class LessonsSummary {
|
||||||
|
final int purchased; // acquistate
|
||||||
|
final int practiced; // praticate
|
||||||
|
final int booked; // prenotate
|
||||||
|
final int pending; // da confermare
|
||||||
|
final int toSchedule; // da programmare
|
||||||
|
final int lost; // perse
|
||||||
|
|
||||||
|
LessonsSummary({
|
||||||
|
required this.purchased,
|
||||||
|
required this.practiced,
|
||||||
|
required this.booked,
|
||||||
|
required this.pending,
|
||||||
|
required this.toSchedule,
|
||||||
|
required this.lost,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory LessonsSummary.fromJson(Map<String, dynamic> j) {
|
||||||
|
int n(dynamic v) => (v as num?)?.toInt() ?? 0;
|
||||||
|
return LessonsSummary(
|
||||||
|
purchased: n(j['purchased']),
|
||||||
|
practiced: n(j['practiced']),
|
||||||
|
booked: n(j['booked']),
|
||||||
|
pending: n(j['pending']),
|
||||||
|
toSchedule: n(j['to_schedule']),
|
||||||
|
lost: n(j['lost']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Lesson {
|
class Lesson {
|
||||||
final int bookingId;
|
final int bookingId;
|
||||||
final String status;
|
final String status;
|
||||||
|
|
||||||
final String date; // YYYY-MM-DD
|
final String datetime; // "YYYY-MM-DD HH:MM:SS"
|
||||||
final String startTime;
|
final String date; // "YYYY-MM-DD"
|
||||||
final String endTime;
|
final String time; // "HH:MM"
|
||||||
final String? roomName;
|
|
||||||
|
|
||||||
final String className;
|
final String className;
|
||||||
final String? level;
|
final String color; // es. "#1ebf73"
|
||||||
|
final String location;
|
||||||
|
|
||||||
final int availableEntries;
|
final String? expireOn; // "YYYY-MM-DD" o null
|
||||||
final int availableRecoveries;
|
final bool lostLesson;
|
||||||
|
|
||||||
final bool canModify;
|
final bool canReschedule;
|
||||||
|
final bool canDelete;
|
||||||
|
|
||||||
Lesson({
|
Lesson({
|
||||||
required this.bookingId,
|
required this.bookingId,
|
||||||
required this.status,
|
required this.status,
|
||||||
|
required this.datetime,
|
||||||
required this.date,
|
required this.date,
|
||||||
required this.startTime,
|
required this.time,
|
||||||
required this.endTime,
|
|
||||||
required this.roomName,
|
|
||||||
required this.className,
|
required this.className,
|
||||||
required this.level,
|
required this.color,
|
||||||
required this.availableEntries,
|
required this.location,
|
||||||
required this.availableRecoveries,
|
required this.expireOn,
|
||||||
required this.canModify,
|
required this.lostLesson,
|
||||||
|
required this.canReschedule,
|
||||||
|
required this.canDelete,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Lesson.fromJson(Map<String, dynamic> j) {
|
factory Lesson.fromJson(Map<String, dynamic> j) {
|
||||||
final session = (j['session'] as Map<String, dynamic>? ?? {});
|
|
||||||
final cls = (j['class'] as Map<String, dynamic>? ?? {});
|
|
||||||
final wallet = (j['wallet'] as Map<String, dynamic>? ?? {});
|
|
||||||
|
|
||||||
return Lesson(
|
return Lesson(
|
||||||
bookingId: (j['booking_id'] as num).toInt(),
|
bookingId: (j['booking_id'] as num?)?.toInt() ?? 0,
|
||||||
status: (j['status'] ?? '').toString(),
|
status: (j['status'] ?? '').toString(),
|
||||||
date: (session['date'] ?? '').toString(),
|
datetime: (j['datetime'] ?? '').toString(),
|
||||||
startTime: (session['start_time'] ?? '').toString(),
|
date: (j['date'] ?? '').toString(),
|
||||||
endTime: (session['end_time'] ?? '').toString(),
|
time: (j['time'] ?? '').toString(),
|
||||||
roomName: session['room_name']?.toString(),
|
className: (j['class_name'] ?? '').toString(),
|
||||||
className: (cls['name'] ?? '').toString(),
|
color: (j['color'] ?? '#1ebf73').toString(),
|
||||||
level: cls['level']?.toString(),
|
location: (j['location'] ?? '').toString(),
|
||||||
availableEntries: (wallet['available_entries'] as num?)?.toInt() ?? 0,
|
expireOn: j['expire_on']?.toString(),
|
||||||
availableRecoveries:
|
lostLesson: j['lost_lesson'] == true,
|
||||||
(wallet['available_recoveries'] as num?)?.toInt() ?? 0,
|
canReschedule: j['can_reschedule'] == true,
|
||||||
canModify: (j['can_modify'] == true),
|
canDelete: j['can_delete'] == true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
|
import '../config/api_config.dart';
|
||||||
|
import '../models/lesson.dart';
|
||||||
|
|
||||||
|
/// Service per le lezioni della scuola YogaSoul.
|
||||||
|
/// Chiama `public/api/my_lessons.php` (phpApiBase), stesso pattern di SettingsApi.
|
||||||
|
class LessonsApi {
|
||||||
|
static Map<String, String> _headers(String token) => {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Carica le lezioni del mese indicato.
|
||||||
|
/// [month] deve essere nel formato "YYYY-MM". Se null, il server usa il mese corrente.
|
||||||
|
static Future<LessonsResponse> fetchMyLessons({
|
||||||
|
required String token,
|
||||||
|
String? month,
|
||||||
|
}) async {
|
||||||
|
final query = (month != null && month.isNotEmpty) ? '?month=$month' : '';
|
||||||
|
final uri = Uri.parse('${ApiConfig.phpApiBase}/my_lessons.php$query');
|
||||||
|
|
||||||
|
final res = await http.get(uri, headers: _headers(token));
|
||||||
|
|
||||||
|
Map<String, dynamic> data;
|
||||||
|
try {
|
||||||
|
data = jsonDecode(res.body) as Map<String, dynamic>;
|
||||||
|
} catch (_) {
|
||||||
|
throw Exception('Risposta non valida dal server (${res.statusCode})');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.statusCode != 200 || data['success'] != true) {
|
||||||
|
throw Exception(data['error'] ?? data['message'] ?? 'Errore lezioni');
|
||||||
|
}
|
||||||
|
|
||||||
|
return LessonsResponse.fromJson(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user