feat: type schedule and auth models

This commit is contained in:
Artem Kokos
2026-04-23 20:57:15 +07:00
parent fa403bfcce
commit 0fdaf0bac4
11 changed files with 531 additions and 243 deletions

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../app/error_message.dart';
import '../app/load_state.dart';
import '../models/schedule_task.dart';
import '../providers/providers.dart';
import '../widgets/load_error_view.dart';
@@ -55,8 +56,8 @@ class _SchedulesScreenState extends ConsumerState<SchedulesScreen> {
}
Widget _buildContent(
LoadState<List<dynamic>> tasksState,
List<dynamic> tasks,
LoadState<List<ScheduleTask>> tasksState,
List<ScheduleTask> tasks,
) {
if ((tasksState.isIdle || tasksState.isLoading) && tasks.isEmpty) {
return const Center(
@@ -125,56 +126,30 @@ class _SchedulesScreenState extends ConsumerState<SchedulesScreen> {
/// Карточка одной задачи расписания
class _TaskCard extends ConsumerWidget {
final dynamic task;
final ScheduleTask task;
const _TaskCard({required this.task});
@override
Widget build(BuildContext context, WidgetRef ref) {
final map = task is Map
? Map<String, dynamic>.from(task)
: <String, dynamic>{};
final jobId = (map['id'] ?? map['job_id'] ?? '').toString();
final targetId = (map['target_id'] ?? map['target'] ?? '').toString();
final state = map['state'];
final runAt = map['run_at'] ?? map['next_run'] ?? map['next_run_time'];
final type = map['type'] ?? (map['cron'] != null ? 'cron' : 'once');
// Формирование описания
final stateStr = state == true
? 'Включить'
: state == false
? 'Выключить'
: '?';
String subtitle = 'Цель: $targetId';
if (runAt != null) subtitle += '\nЗапуск: $runAt';
if (map['cron'] != null) subtitle += '\nCron: ${map['cron']}';
if (map['hour'] != null && map['minute'] != null) {
subtitle += '\nВремя: ${map['hour']}:${map['minute']}';
}
if (map['day_of_week'] != null && map['day_of_week'] != '*') {
subtitle += ' (дни: ${map['day_of_week']})';
}
return Card(
margin: const EdgeInsets.only(bottom: 8),
child: ListTile(
leading: Icon(
type == 'cron' ? Icons.repeat : Icons.timer,
task.isCron ? Icons.repeat : Icons.timer,
color: Colors.deepOrange,
),
title: Text(
'$stateStr - $targetId',
task.title,
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(
subtitle,
task.subtitle,
style: const TextStyle(fontSize: 12, color: Colors.white54),
),
trailing: IconButton(
icon: const Icon(Icons.delete_outline, color: Colors.redAccent),
onPressed: () => _confirmCancel(context, ref, jobId),
onPressed: () => _confirmCancel(context, ref, task.jobId),
),
),
);